#import "TeXviewSwitchBoard.h"
#import <appkit/appkit.h>
#import "TeXviewObject.h"
#import "dviAccessors.h"
#import "ComScroll.h"
#import "FREE.h"
#include <string.h>

extern TeXviewObject *myTeXviewObject;
TeXviewSwitchBoard *myTeXviewSwitchBoard;
Boolean context_needs_switching = 0 ;
Boolean new_view = 0;
Boolean cloned = 0 ;
extern Window      *tvWindow;
const char         *legit_types[] = {"dvi", "tex", "latex", "ltx", "texinfo", NULL};
extern NXRect      *initsizewindow();
extern float screendpi ;
extern Boolean pagedrawn ;
extern int debugon ;
extern int initWasOnScreen() ;
extern void dviUnzoom() ;
extern void dviZoom() ;
extern void dviZoomUnzoom() ;
extern void dviGotoPage() ;
extern void dviFirstPage() ;
extern void dviReOpenFile() ;
extern void dviinit();
extern void display();
extern void TPSinit(), TPSdefres() ;
extern void TPSgetfontarray() ;
extern void recalculate() ;
extern void reportnewdpi() ;
extern void print_context() ;
extern int relativepage() ;

extern void newdpi() ;
extern void fontinit() ;
extern Boolean mocked;
extern void clear_context() ;
extern void get_context() ;
void reportname() ;
extern id fpageinit();
void display();
id makenewdoc();
void fdrawrule();
void getpagenum();
void previewtofront();
void openfilename();

extern shalfword hh, vv ;
extern shalfword hhoffset, vvoffset ;
extern shalfword hhmin, hhmax, vvmin, vvmax ;
extern shalfword hhsize, vvsize ;
extern shalfword rhhsize, rvvsize ;
extern shalfword hhmarg, vvmarg ;

id ht_highlight_tag ;
id ht_last_clicked_tag ;
extern ht_highlight ;

@implementation TeXviewSwitchBoard

-init
{
  self = [super init];
  myOpenPanel = nil;
  myTeXviewSwitchBoard = self ;
  docViewList = [[List alloc] initCount:2];
  docViewNum = 0 ;
  TPSinit() ;
  return self;
}

- free
{
  FREE_OBJECT(docViewList) ;
  FREE_OBJECT(myOpenPanel) ;
  return [super free] ;
}

- setConsole:anObject
{
    NXRect             *tr;

    console = anObject;
    [[console window] setExcludedFromWindowsMenu:YES];
    if ((tr = initsizewindow(1))) {
	    [[(ComScroll *) console window] placeWindow:tr];
	    if (initWasOnScreen()) {
	       [[console window] orderFront:self];
	       } else {
	           [[console window] orderOut:self];
	     }
     }
    return self;
}

- getConsole
{
    return console;
}

- setTex:anObject
{
    NXRect             *tr;

    tex = anObject;
    [[tex window] setExcludedFromWindowsMenu:YES];
    if ((tr = initsizewindow(2))) {
	[[(ComScroll *) tex window] placeWindow:tr];
	if (initWasOnScreen()) {
	    [[tex window] orderFront:self];
	} else {
	    [[tex window] orderOut:self];
	}
    }
    return self;
}

- getTeX
{
    return tex;
}

- setCommand:anObject
{
    NXRect             *tr;

    command = anObject;
    [command setExcludedFromWindowsMenu:YES];
    [command removeFromEventMask:(NX_KEYDOWNMASK | NX_KEYUPMASK)];
    if ((tr = initsizewindow(3))) {
	[command moveTo:tr->origin.x:tr->origin.y];
	if (initWasOnScreen()) {
	    [command orderFront:self];
	} else {
	    [command orderOut:self];
	}
    }
    return self;
}

- getCommand
{
    return command;
}

- setMockSwitch:anObject
{
    mockSwitch = anObject;
    [self upMock];
    return self;
}
char                realnameoffile[255];

- reportName:(char *)name
{
   [[currentPageView window] setTitleAsFilename:name];
   return self ;
}

void 
reportname(s)
    char               *s;
{
    static char        *oldname;

    if (s) {
	oldname = s;
	if (*s != '*' || s[1] != ' ')
	    strcpy(realnameoffile, s);
	else
	    realnameoffile[0] = 0;
    } else
	realnameoffile[0] = 0;
    [myTeXviewSwitchBoard reportName:oldname];
}

void 
upmock(void)
{
    [myTeXviewSwitchBoard upMock];
}

- upMock
{
    [mockSwitch setState:mocked];
    return self;
}

- setPositionText:anObject
{
    positionText = anObject;
    return self;
}

- getPositionText
{
   return positionText ;
}

- setPositionRadio:anObject
{
    positionRadio = anObject;
    return self;
}

- setCurrentPageForm:anObject
{
    currentPageForm = anObject;
    return self;
}

-getCurrentPageForm
{
   return currentPageForm ;
}

- setCurrentWindow:anObject 
{
  currentWindow = anObject ;
  return self ;
}

- getCurrentWindow 
{
  return currentWindow ;
}

- setCurrentPageView:anObject 
{
   currentPageView = (PageView *)anObject ;
   return self ;
}

- getCurrentPageView
{
  return currentPageView ;
}

- setCurrentSheetView:anObject ;
{
   currentSheetView = (SheetView *)anObject ;
   return self;
}

- setCurrentZoomed:anObject
{
   currentZoomed = anObject ;
   return self ;
}

- setCurrentHtags:anObject 
{
   currentHtags = anObject ;
   return self ;
}

- getCurrentHtags 
{
  return currentHtags ;
}

- setCurrentHtpages:anObject 
{
  currentHtpages = anObject ;
  return self ;
}

- getCurrentHtpages 
{
   return currentHtpages ;
}

- setCurrent_ht_last_clicked_tag:anObject 
{
  current_ht_last_clicked_tag = anObject ;
  return self ;
}

- getCurrent_ht_last_clicked_tag 
{
  return current_ht_last_clicked_tag ;
}

- setCurrent_ht_highlight_tag:anObject ;
{
  current_ht_highlight_tag = anObject ;
  return self ;
}

- getCurrent_ht_highlight_tag 
{
  return current_ht_highlight_tag ;
}

- zoom:sender ;
{
   [currentZoomed setState:1] ;
   pagedrawn = 0 ;
   dviZoom() ;
   return self ;
}

- unzoom:sender ; 
{
   [currentZoomed setState:0] ;
   pagedrawn = 0;
   dviUnzoom() ;
   return self ;
}

- lastPage:sender
{
  [currentPageView lastPage] ;
  return self;
}
- openPanel
{
    if (!myOpenPanel)
	myOpenPanel = [OpenPanel new];
    return (myOpenPanel);
}

- openFile:sender
{  
   if ([[self openPanel] runModalForTypes:legit_types]) {
     [self openFilename:(char *)[[self openPanel] filename]] ;
    }
   return self;
}

void openfilename(char *filename)
{
  [myTeXviewSwitchBoard openFilename:filename] ;
  return ;
}

-openFilename:(char *)filename
{   
    NXRect             *tr; 

    if (filename == NULL) return self ;
    if (currentPageView) [currentPageView saveDviContext] ;
     [self newDocView:-1] ;
    [currentPageView setAbsoluteFn:filename] ;
    clear_context() ;
	  dviOpenFile(filename);
    if ((tr = initsizewindow(0))) {
	    [currentWindow placeWindow:tr]; }
    tvWindow = currentWindow;
 // new_view = 1 ;
  [currentWindow makeKeyAndOrderFront:0];

  return self;


}

- reOpenFile:sender
{
    dviReOpenFile();
    return self;
}

- newDocView:(int)master /* -1 if master */
{  
  if([NXApp loadNibSection:"docview.nib" owner: self] == nil) {
    return nil;
   }
  [currentWindow setDocViewIndex:docViewNum];
  [currentWindow setMaster:master];
 // [currentWindow setSlave:0]; //now a linked list of slaves
  [docViewList insertObject:currentWindow at:docViewNum] ;
  docViewNum++;
  new_view = 1 ;
  return self ;
}

- (int)getDocViewNum 
{
   return docViewNum ;
}

- clone:sender
{
  [self cloneToPage: -1 ToFront: 1] ;
  return self ;
}

- cloneToPage:(int)pagenumber ToFront:(int)front 
{ 
  NXRect  *tr ; 
 // int     slave ;
  PageView *pv ;

  pagedrawn = 0 ;
  pv = currentPageView ;
  [pv saveDviContext] ;
  [pv setHt_last_clicked_tag:ht_last_clicked_tag] ;
  [pv setHt_highlight_tag:ht_highlight_tag] ;
  cloned = 1 ;
  [self newDocView:[currentWindow getDocViewIndex]] ;
  [[pv window] installSlave:[currentWindow getDocViewIndex]] ;
  [currentPageView setAbsoluteFn:[pv getAbsoluteFn]] ;
//  currentPageForm = [currentPageView getPageForm] ;
 // currentZoomed = [currentPageView getZoomed];
  clear_context() ;
  dviOpenFile([pv getAbsoluteFn]);
  if (pagenumber != -1) {
       char pn[10] ;
       sprintf(pn, "%d", pagenumber) ;
     // relativepage(1) ;
     // dviGotoPage(pn) ;
       }
  if ((tr = initsizewindow(4))) {
	  [currentWindow placeWindow:tr]; }
  tvWindow = currentWindow;
  if (front) [self currentKeyAndFront] ;
  return self ;
}

- currentKeyAndFront
{
  [currentWindow makeKeyAndOrderFront:0];
  return self ;
}

- slaveToCurrent
{
  int slave;

  if ((slave = [currentWindow getSlave])) {
    [[docViewList objectAt:slave] makeKeyAndOrderFront:0] ;
    } else {
      [self cloneToPage:1 ToFront:0] ;
    }
   return self ;
}

- freezeSlave:sender 
{
   [currentWindow setFrozen:1] ;
   return self ;
}

- unfreezeSlave:sender
{
   [currentWindow setFrozen:0] ;
   return self ;
}

- emancipate:sender
{
  [[docViewList objectAt:[currentWindow getMaster]] 
         removeSlave: [currentWindow getDocViewIndex]] ;
  [currentWindow setMaster:-1] ; /* promote to master */ 
  return self ;
}

- emancipateByNumber:(int) num
{
  TVWindow *w ;

  w = [docViewList objectAt:num] ;
  [[docViewList objectAt:[w getMaster]] removeSlave:[w getDocViewIndex]] ;
  [w setMaster: -1] ;
  return self ;
}

- (int)checkFrozen:(int)win
{
  return [[docViewList objectAt:win] getFrozen] ;
}

- windowWillClose:sender 
{
  // [sender setDelegate:nil] ;
  // [docViewList removeObject:currentPageView] ;
  // [docViewList removeObjectAt:[currentWindow getDocViewIndex]] ;
   [sender emancipateSlaves] ;
   [[docViewList objectAt: [currentWindow getMaster]] 
             removeSlave:[sender getDocViewIndex]];
   if([docViewList count] == 0) { /* This won't happen at the moment */
     currentPageView = nil ;
     currentSheetView = nil ;
     currentHtags = nil ;
     currentHtpages = nil ;
     current_ht_last_clicked_tag = nil ;
     current_ht_highlight_tag = nil ;
     }
   return self ;
}

// The key window gets is context promoted to the global one 
// The window's PageView etc. is made the currently active one

- windowDidBecomeKey:sender
{ 
 int num ;

#ifdef DEBUG
  if (debugon > 1 ) {
 printf("wdbk entered\n");
 //print_context() ;
  }
#endif
 if (!new_view) {
    [currentPageView saveDviContext] ;
    [currentPageView setHt_last_clicked_tag:ht_last_clicked_tag] ;
    [currentPageView setHt_highlight_tag:ht_highlight_tag] ;
     } //make this a save method
  num = [sender getDocViewIndex] ;
  currentWindow = [docViewList objectAt:num];
  TPSgetfontarray(num) ; // Change fontarray in global DPS context
  currentPageView = [currentWindow getPageView] ;
  tvWindow = currentWindow ;
  currentSheetView = [currentPageView docView];
  currentPageForm = [currentPageView getPageForm] ;
  currentZoomed = [currentPageView getZoomed];
  currentHtags = [currentPageView getHtags] ;
  currentHtpages = [currentPageView getHtpages] ;
  ht_highlight_tag = [currentPageView getHt_highlight_tag] ;
#ifdef DEBUG
  if (debugon > 1 ) {
  printf("ht_highlight_tag is %p\n", ht_highlight_tag) ;
  }
#endif
  ht_last_clicked_tag = [currentPageView getHt_last_clicked_tag] ;
    if (!new_view) {
     [currentPageView getDviContext] ;
     TPSdefres((double)screendpi) ;
#ifdef DEBUG
  if (debugon > 1 ) {
    printf("WDBK: getting dvi Context\n") ;
    print_context();
  }
#endif
      }
   new_view = 0 ;
#ifdef DEBUG
  if (debugon > 1 ) {
  printf("wdbk exited\n");
  }
#endif
  reportnewdpi() ;
  return self ;
}

// Context is only saved if it is not resigning because it was cloned or 
// a new document is created. This is taken care of in the methods that
// create a new document. 

- windowDidResignKey:sender
{
  PageView *pv ;

#ifdef DEBUG
  if (debugon > 1 ) { 
  printf("wdrk entered\n");
  }
#endif
  if (!cloned && !new_view) {
#ifdef DEBUG
  if (debugon > 1 ) {
    printf("saving because I wasn't cloned\n") ;
    print_context() ;
  }
#endif
    pv = [[docViewList objectAt:[sender getDocViewIndex]] getPageView] ;
    [pv saveDviContext] ;
    [pv setHt_last_clicked_tag:ht_last_clicked_tag] ;
    [pv setHt_highlight_tag:ht_highlight_tag] ;
    }
     cloned = 0;
#ifdef DEBUG
  if (debugon > 1 ) {
   printf("wdrk exited\n");
  }
#endif
   return self ;
}
    
- nextPage:sender
{
  [currentPageView nextPage] ;
  return self;
}

- firstPage:sender
{
  [currentPageView firstPage] ;
  return self;
}

- zoomUnzoom:sender
{
  dviZoomUnzoom();
  return self;
}

- prevPage:sender
{
  [currentPageView prevPage] ;
  return self;
}

- fireRandom:sender
{
  [currentPageView fireRandom] ;
  return self;
}

- closeFile:sender
{
  [currentPageView closeFile] ;
  return self;
}

- gotoPage:sender
{
    dviGotoPage((char *)[sender stringValueAt:0]);
    return self;
}

- changeDPI:(id)sender
{
    [myTeXviewObject popIt:sender];
    return self;
}

- TeXtexit:sender
{
  [currentPageView TeXtexit] ;
  return self;
}

- TeXlatexit:sender
{
  [currentPageView TeXlatexit] ;
  return self;
}

- TeXslitexit:sender
{
  [currentPageView TeXslitexit] ;
  return self;
}

- TeXbibtexit:sender
{
  [currentPageView TeXbibtexit] ;
  return self;
}

- TeXamstexit:sender
{
  [currentPageView TeXamstexit] ;
  return self;
}

- TeXlatex209it:sender
{
  [currentPageView TeXlatex209it] ;
  return self;
}

- TeXeplainit:sender
{
  [currentPageView TeXeplainit] ;
  return self;
}

- TeXcustomexit:sender
{
  [currentPageView TeXcustomexit] ;
  return self;
}

- TeXdefaultexit:sender
{
  [currentPageView TeXdefaultexit] ;
  return self;
}

- TeXmakeit:sender
{
  [currentPageView TeXmakeit] ;
  return self;
}

- openManual:sender
{
  [currentPageView openManual] ;
  return self;
}

- clearBuffer:sender
{
    ComScroll          *c = 0;

    if (console && [[(ComScroll *) console window] isKeyWindow])
	c = console;
    else if (tex && [[(ComScroll *) tex window] isKeyWindow])
	c = tex;
    if (c)
	[c clear];
    return self;
}

- mockUnmock:sender
{
  [currentPageView mockUnmock] ;
  return self;
}

- mock:sender
{
  [currentPageView mock] ;
  return self;
}

- unMock:sender
{
  [currentPageView unMock] ;
  return self;
}

extern char         LastFormat[], CustomFormat[];

- setDefaultformat:sender
{
    defaultformat = sender;
    [self upDefaultformat:self];
    return self;
}

- setCustomformat:sender
{
    customformat = sender;
    [self upCustomformat:self];
    return self;
}

- newDefaultformat:sender
{
    char               *p = (char *)[sender stringValueAt:0];

    while (*p <= ' ' && *p)
	p++;
    strcpy(LastFormat, p);
    p = LastFormat;
    while (*p > ' ')
	p++;
    *p = 0;
    return self;
}

- newCustomformat:sender
{
    char               *p = (char *)[sender stringValueAt:0];

    while (*p <= ' ' && *p)
	p++;
    strcpy(CustomFormat, p);
    p = CustomFormat;
    while (*p > ' ')
	p++;
    *p = 0;
    return self;
}

- upDefaultformat:sender
{
    [(TextField *) defaultformat setStringValue:LastFormat];
    return self;
}

- upCustomformat:sender
{
    [(TextField *) customformat setStringValue:CustomFormat];
    return self;
}
void 
upformats(void)
{
    [myTeXviewSwitchBoard upDefaultformat:0];
    [myTeXviewSwitchBoard upCustomformat:0];
}

- appDidBecomeActive:(id)sender
{
// [currentPageView appDidBecomeActive] ;
  return self;
}

- changeUnits:sender
{
  [currentPageView changeUnits] ;
  return self;
}

- moveBackInHistory:sender
{
  [currentPageView moveBackInHistory] ;
  return self;
}

- moveForwardInHistory:sender 
{
  [currentPageView moveForwardInHistory] ;
  return self;
}

- saveCurrentContext
{
  return [currentPageView saveDviContext] ;
}

- restoreCurrentContext
{ 
  return [currentPageView getDviContext] ;
}

- (int)moveDown:(int)shiftstate
{
   return [currentPageView moveDown:shiftstate] ;
}

- (int)moveUp:(int)shiftstate
{
  return [currentPageView moveUp:shiftstate] ;
}

- (int)moveRight:(int)shiftstate
{
  return [currentPageView moveRight:shiftstate] ;
}

- (int)moveLeft:(int)shiftstate
{
  return [currentPageView moveLeft:shiftstate] ;
}

- Bot:(int)quiet
{
   return [currentPageView Bot:quiet] ;
}

- Top:(int)quiet
{
   return [currentPageView Top:quiet] ;
}

-  makeNewDocSheet:(int)hsize:(int)vsize
{
   return [currentSheetView makeNewDoc:hsize:vsize] ;
}

- displaySheet
{
   [currentSheetView display] ;
   return self ;
}

- drawSheetRule:(halfword)xx:(halfword)yy
{
   [currentSheetView drawRule:xx:yy] ;
   return self ;
}

/* From SheetView.m */
id makenewdoc(hsize, vsize)
int hsize, vsize ;
{
   return [myTeXviewSwitchBoard makeNewDocSheet:hsize:vsize] ;
}

static int dontbother = 1 ;

void display()
{
   dontbother = 1 ;
   (void)fpageinit() ;
   dontbother = 0 ;
   [myTeXviewSwitchBoard displaySheet] ;
}
void fdrawrule(xx, yy)
halfword xx, yy ;
{
   register shalfword hmin, hmax, vmin, vmax ;

   if (xx>0 && yy>0) {
      hmin = hh+hhoffset ;
      hmax = hmin + xx - 1 ;
      vmax = vv+vvoffset ;
      vmin = vmax - yy + 1 ;
      [myTeXviewSwitchBoard drawSheetRule:xx:yy] ;
   }
}

- getPageNum:(char *)s
{
    [currentPageView getpagenum:s];
    return self ;
}

- previewToFront
{
  [currentWindow makeKeyAndOrderFront:0];
  return self ;
}

void 
getpagenum(s)
    char               *s;
{
    [myTeXviewSwitchBoard getPageNum:s];
}
void 
previewtofront()
{
    [myTeXviewSwitchBoard previewToFront] ;
}

- noScrollUpdates
{
   [currentPageView noScrollUpdates] ;
    return self;
}

- scrollUpdates
{
    [currentPageView scrollUpdates] ;
    return self;
}

- cachePosition:(int)x :(int)y
{
    [currentPageView cachePosition:x:y] ;
    return self;
}

- unCachePosition:(int)x :(int)y
{
    [currentPageView unCachePosition:x:y] ;
    return self;
}

@end
