/* Generated by Interface Builder */

#import "PageView.h"
#import "SheetView.h"
#import "appkit/Scroller.h"
#import "TeXviewObject.h"
#import "TVWindow.h"
#import <dpsclient/wraps.h>
#import "dviAccessors.h"
#import <strings.h>
#import <appkit/Application.h>
#import "ComScroll.h"
#import <appkit/TextField.h>
#import <mach/mach.h>

#include <kpathsea/c-fopen.h>
#include <kpathsea/c-pathch.h>
#include <kpathsea/concatn.h>
#include <kpathsea/db.h>
#include <kpathsea/fn.h>
#include <kpathsea/magstep.h>
#include <kpathsea/readable.h>
#include <kpathsea/tex-make.h>
#include <kpathsea/variable.h>


extern real screendpi ;
extern int paranoia ;
extern PageView *myPageView ;
extern Window *tvWindow ;
extern SheetView *myView ;
extern TeXviewObject *myTeXviewObject ;
extern shalfword rvvsize, rhhsize ;
extern Boolean mocked ;
extern NXRect *initsizewindow() ;
extern initWasOnScreen() ;
extern void error() ;

extern void reportname() ;
extern void recalculate() ;
extern void PSflush(), TPSinit() ;
extern void makenewdoc() ;

const char *legit_types[] = { "dvi", "tex", "latex", "ltx", "texinfo", NULL } ;

@implementation PageView

+ newFrame:(const NXRect *)theFrame
{
    NXRect tempRect ;

    self = [super newFrame:theFrame];
    [self setHorizScrollerRequired:YES];
    [self setVertScrollerRequired:YES];
/*  [self setDynamicScrolling:YES];
    [self setBackgroundGray:0.433];
    [self setAutoresizeSubviews:YES];
    [self setBorderType:NX_NOBORDER]; */
    myPageView = self ;
    myOpenPanel = nil ;
    NX_X(&tempRect) = 0 ;
    NX_Y(&tempRect) = 0 ;
    NX_WIDTH(&tempRect) = 1036 ;
    NX_HEIGHT(&tempRect) = 1336 ;
    myView = [SheetView newFrame:&tempRect] ;
    [self setDocView:myView] ;
    reportname(NOFILETITLE) ;
    [[self window] setExcludedFromWindowsMenu:YES] ;
    TPSinit() ;
    recalculate() ;
    return self;
}

- drawSelf:(NXRect *)rects :(int)rectCount
{
   [super drawSelf:rects:rectCount] ;
   return self ;
}

- setPageNum:anObject
{
   pageNum = anObject ;
   return self;
}

- 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 ;
}

- setPageStuff:anObject
{
   pageStuff = anObject ;
   pageStuff = [pageStuff setContentView:nil] ;
   [self addSubview:pageStuff] ;
   [self tile] ;
   return self ;
}

- getPageStuff;
{
   return pageStuff ;
}

- tile
{
   NXRect r1, r2 ;
   Scroller *h ;

   [super tile] ;
   if (pageStuff == 0)
      return self ;
   h = [self horizScroller] ;
   [h getFrame:&r2] ;
   [pageStuff getFrame:&r1] ;
   r2.size.width -= r1.size.width ;
   r1.origin.x = r2.size.width + r2.origin.x ;
   r1.origin.y = r2.origin.y ;
   [h setFrame:&r2] ;
   [pageStuff setFrame:&r1] ;
   return self ;
}

- lastPage:sender
{
    dviLastPage() ;
    return self;
}

- openPanel
{ 
  if (!myOpenPanel) myOpenPanel = [OpenPanel new];
  return (myOpenPanel);
}

- update
{
   if ([self needsDisplay])
      [self display] ;
   return self ;
}

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

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

- nextPage:sender
{
    dviNextPage() ;
    return self;
}

- firstPage:sender
{
    dviFirstPage() ;
    return self;
}

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

- mockUnmock:sender
{
   dviMock(-1) ;
   return self;
}

- mock:sender
{
   dviMock(1) ;
   return self ;
}

- unMock:sender
{
   dviMock(0) ;
   return self ;
}

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

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

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

- unzoom:sender
{
    [myTeXviewObject unzoom] ;
    dviUnzoom() ;
    return self;
}

- prevPage:sender
{
    dviPrevPage() ;
    return self;
}

- zoom:sender
{
    [myTeXviewObject zoom] ;
    dviZoom() ;
    return self;
}

- closeFile:sender
{
    dviCloseFile() ;
    return self;
}

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

void getpagenum(s)
char *s ;
{
   [myPageView getpagenum:s] ;
}

- getpagenum:(char *)s
{
   strcpy(s, [pageNum stringValue]) ;
   return self ;
}


- fireRandom:sender
{
    [myTeXviewObject firePage] ;
    return self ;
}

void pagereport(pagenum, seq)
integer pagenum, seq ;
{
   char str[30] ;

   if (seq == 0)
      sprintf(str, "%ld", pagenum) ;
   else
      sprintf(str, "%ld.%ld", pagenum, seq) ;
   [myTeXviewObject setPageNum:str] ;
   PSflush() ;
}

char realnameoffile[255] ;

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 ;
   [[myPageView window] setTitleAsFilename:oldname] ;
}

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

#define MILLION 1000000

static int lastxsize = MILLION, lastysize = MILLION ;

- noScrollUpdates
{
   [myPageView setDisplayOnScroll:NO] ;
   [myPageView setCopyOnScroll:NO] ;
   return self ;
}

- scrollUpdates
{
   [myPageView setDisplayOnScroll:YES] ;
   [myPageView setCopyOnScroll:YES] ;
   return self ;
}

- cachePosition:(int)x:(int)y
{
   NXSize s ;

   [self getContentSize:&s] ;
   if (s.width + 16 > lastxsize)
      xcache = 0.5 ;
   else
      xcache = [[self horizScroller] floatValue] ;
   if (s.height + 16 > lastysize)
      ycache = 0.5 ;
   else
      ycache = [[self vertScroller] floatValue] ;
   if (lastxsize == MILLION) { /* cheat these values in */
      xcache = 0.5 ;
      ycache = 0.0 ;
   }
   return self ;
}

static float scroller_to_pos(float x1, float x2, float s) {
   if (x2 < x1)
      return s * (x1 - x2) ;
   else
      return 0 ;
}

- unCachePosition:(int)x:(int)y
{
   NXSize size ;
   NXPoint t ;

   [self getContentSize:&size] ;
   t.x = scroller_to_pos((float)x, size.width, xcache) ;
   t.y = scroller_to_pos((float)y, size.height, 1.0-ycache) ;
   [myView scrollPoint:&t] ;
   lastxsize = x ;
   lastysize = y ;
   return self ;
}

/* moves down about a screenful. */

- (int)moveDown:(int)shiftstate;
{
   NXSize s ;
   NXPoint t ;
   float ypos = [[self vertScroller] floatValue] ;
   float xpos = [[self horizScroller] floatValue] ;
   float f ;

   shiftstate = 1 << (2 * shiftstate) ;
   [self getContentSize:&s] ;
   if (ypos > 0.95 || s.height + 16 >= rvvsize)
      return 0 ;
   if (2 * s.height < rvvsize)
      f = s.height / (rvvsize - s.height) - 0.02 ;
   else
      f = 1.0 ;
   if (f < 0.02)
      f = 0.02 ;
   f /= shiftstate ;
   ypos += f ;
   if (ypos > 1.0)
      ypos = 1.0 ;
   t.y = scroller_to_pos((float)rvvsize, s.height, 1.0 - ypos) ;
   t.x = scroller_to_pos((float)rhhsize, s.width, xpos) ;
   [myView scrollPoint:&t] ;
   return 1 ;
}

/* moves up about a screenful. */

- (int)moveUp:(int)shiftstate;
{
   NXSize s ;
   NXPoint t ;
   float ypos = [[self vertScroller] floatValue] ;
   float xpos = [[self horizScroller] floatValue] ;
   float f ;

   shiftstate = 1 << (2 * shiftstate) ;
   [self getContentSize:&s] ;
   if (ypos < 0.05 || s.height + 16 >= rvvsize)
      return 0 ;
   if (2 * s.height < rvvsize)
      f = s.height / (rvvsize - s.height) - 0.02 ;
   else
      f = 1.0 ;
   if (f < 0.02)
      f = 0.02 ;
   f /= shiftstate ;
   ypos -= f ;
   if (ypos < 0.0)
      ypos = 0.0 ;
   t.y = scroller_to_pos((float)rvvsize, s.height, 1.0 - ypos) ;
   t.x = scroller_to_pos((float)rhhsize, s.width, xpos) ;
   [myView scrollPoint:&t] ;
   return 1 ;
}

- (int)moveRight:(int)shiftstate
{
   NXSize s ;
   NXPoint t ;
   float ypos = [[self vertScroller] floatValue] ;
   float xpos = [[self horizScroller] floatValue] ;
   float f ;

   shiftstate = 1 << (2 * shiftstate) ;
   [self getContentSize:&s] ;
   if (s.width + 16 >= rhhsize)
      return 0 ;
   if (2 * s.width < rhhsize)
      f = s.width / (rhhsize - s.width) - 0.02 ;
   else
      f = 1.0 ;
   if (f < 0.02)
      f = 0.02 ;
   f /= shiftstate ;
   xpos += f ;
   if (xpos > 1.0)
      xpos = 1.0 ;
   t.y = scroller_to_pos((float)rvvsize, s.height, 1.0 - ypos) ;
   t.x = scroller_to_pos((float)rhhsize, s.width, xpos) ;
   [myView scrollPoint:&t] ;
   return 1 ;
}

- (int)moveLeft:(int)shiftstate
{
   NXSize s ;
   NXPoint t ;
   float ypos = [[self vertScroller] floatValue] ;
   float xpos = [[self horizScroller] floatValue] ;
   float f ;

   shiftstate = 1 << (2 * shiftstate) ;
   [self getContentSize:&s] ;
   if (s.width + 16 >= rhhsize)
      return 0 ;
   if (2 * s.width < rhhsize)
      f = s.width / (rhhsize - s.width) - 0.02 ;
   else
      f = 1.0 ;
   if (f < 0.02)
      f = 0.02 ;
   f /= shiftstate ;
   xpos -= f ;
   if (xpos < 0.0)
      xpos = 0.0 ;
   t.y = scroller_to_pos((float)rvvsize, s.height, 1.0 - ypos) ;
   t.x = scroller_to_pos((float)rhhsize, s.width, xpos) ;
   [myView scrollPoint:&t] ;
   return 1 ;
}

- Bot:(int)quiet;
{
   NXSize s ;
   NXPoint t ;
   float xpos = [[self horizScroller] floatValue] ;

   if (quiet)
      [self noScrollUpdates] ;
   [self getContentSize:&s] ;
   t.y = scroller_to_pos((float)rvvsize, s.height, 0.0) ;
   t.x = scroller_to_pos((float)rhhsize, s.width, xpos) ;
   [myView scrollPoint:&t] ;
   if (quiet)
      [self scrollUpdates] ;
   return self ;
}

- Top:(int)quiet;
{
   NXSize s ;
   NXPoint t ;
   float xpos = [[self horizScroller] floatValue] ;

   if (quiet)
      [self noScrollUpdates] ;
   [self getContentSize:&s] ;
   t.y = scroller_to_pos((float)rvvsize, s.height, 1.0) ;
   t.x = scroller_to_pos((float)rhhsize, s.width, xpos) ;
   [myView scrollPoint:&t] ;
   if (quiet)
      [self scrollUpdates] ;
   return self ;
}

void bringupwindow(void) {
   NXRect *tr ;

   if (tr = initsizewindow(0))
      [[myPageView window] placeWindow:tr] ;
   tvWindow = [myPageView window] ;
   [[myPageView window] makeKeyAndOrderFront:0] ;
}

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

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

static float units[] = { 1.0, 2.54, 72.27, 72.0, 84.725 } ;
static int curunits = 0 ;
static NXPoint posevent = {0.0, 0.0}, prevposevent = {0.0, 0.0} ;
static char *unitnames[] = { "inches", "centimeters", "points",
    "PostScript units", "pico-light-seconds", 0 } ;
- changeUnits:sender
{
   curunits = (curunits + 1) ;
   if (unitnames[curunits] == 0)
      curunits = 0 ;
   [self updatePosition] ;
   return self ;
}

- updatePosition
{
   NXPoint pagepos ;
   NXPoint deltapos ;
   char tempbuf[300] ;

   if (positionText && screendpi > 1.0) {
      pagepos = posevent ;
      deltapos = prevposevent ;
      pagepos.x *= units[curunits] / screendpi ;
      pagepos.y *= units[curunits] / screendpi ;
      deltapos.x *= units[curunits] / screendpi ;
      deltapos.y *= units[curunits] / screendpi ;
      sprintf(tempbuf,
              "Click at (%.3g,%.3g) is (%.3g,%.3g) from previous click in %s.",
       pagepos.x, pagepos.y, pagepos.x - deltapos.x, pagepos.y - deltapos.y,
       unitnames[curunits]) ;
      [(TextField *)positionText setStringValue:tempbuf] ;
   }
   return self ;
}

- reportPosition:(NXEvent *)event
{
   if (myView && positionText && screendpi > 1.0) {
      prevposevent = posevent ;
      posevent = (event->location) ;
      posevent.x -= 8.0 ;
      posevent.y -= 8.0 ;
      [myView convertPoint:&posevent fromView:nil] ;
      [self updatePosition] ;
   }
   return self ;
}

- mouseDown: (NXEvent *) ptr
{
    NXPoint     newLoc, oldLoc;
    NXEvent     *nextEvent;
    int         oldMask;
    NXRect      myRect;
    int numdrags = 0 ;

    oldMask =
        [window addToEventMask:(NX_LMOUSEUPMASK | NX_LMOUSEDRAGGEDMASK)];
    [self lockFocus];

    oldLoc = ptr->location;
    [self convertPoint:&oldLoc fromView:nil];

    nextEvent =
        [NXApp getNextEvent:(NX_LMOUSEUPMASK | NX_LMOUSEDRAGGEDMASK)];
    while (nextEvent->type == NX_LMOUSEDRAGGED){
        numdrags++ ;
        newLoc = nextEvent->location;
        [self convertPoint:&newLoc fromView:nil];
        [myView getVisibleRect:&myRect];
        myRect.origin.x -= newLoc.x - oldLoc.x;
        myRect.origin.y += newLoc.y - oldLoc.y;
        [myView scrollRectToVisible: &myRect];
        oldLoc = newLoc;
        nextEvent =
            [NXApp getNextEvent:(NX_LMOUSEUPMASK | NX_LMOUSEDRAGGEDMASK)];
    }
    [self unlockFocus];
    [window setEventMask:oldMask];
    if (numdrags == 0)
       [self reportPosition:nextEvent] ;
    return self;
}

void writeconsole(const char *s) {
   static char wcbuf[1024] ;
   strcpy(wcbuf, s) ;
   strcat(wcbuf, "\n") ;
   [((ComScroll *)[myPageView getConsole]) addText:wcbuf] ;
}




void
misstex P2C(kpse_file_format_type, format,  const_string, cmd)
{
  static FILE *missfont = NULL;

  /* If we weren't trying to make a font, do nothing.  Maybe should
     allow people to specify what they want recorded?  */
  if (format > kpse_any_glyph_format && format != kpse_tfm_format
      && format != kpse_vf_format)
    return;

  /* If this is the first time, have to open the log file.  */
  if (!missfont)
    {
      const_string missfont_name = "missfont.log";
      missfont = fopen (missfont_name, FOPEN_A_MODE);
      if (!missfont && getenv ("TEXMFOUTPUT"))
        {
          missfont_name = concat3 (getenv ("TEXMFOUTPUT"), DIR_SEP_STRING,
                                   missfont_name);
          missfont = fopen (missfont_name, FOPEN_A_MODE);
        }

      /* Should we really be unconditionally shouting this message?  */
      if (missfont) {
	    char tmp[160];
        sprintf (tmp, "kpathsea: Appending font creation commands to %s.\n",
                 missfont_name);
	    [((ComScroll *)[myPageView getConsole]) addText:tmp];
	  }
    }
  
  /* Write the command if we have a log file.  */
  if (missfont)
    {
      fputs (cmd, missfont);
      putc ('\n', missfont);
    }
}

string
maketex P2C(kpse_file_format_type, format,  const_string, cmd)
{
  string ret;
  string fn;                  /* The final filename.  */
  fn_type output=fn_init();   /* Collect the script output.  */
  unsigned len;
  
  [((ComScroll *)[myPageView getConsole]) logCommand:cmd inBack:0] ;
  ret=[((ComScroll *)[myPageView getConsole]) getLastLine] ;
  
  output=fn_copy0(ret,strlen(ret));

  len = FN_LENGTH (output);
  fn = FN_STRING (output);

  /* If no output from script, return NULL.  Otherwise check
     what it output.  */
  ret = len == 1 ? NULL : kpse_readable_file (fn);

  /* Free the name if we're not returning it.  */
  if (fn != ret)
    free (fn);
  return ret;
  
  if (ret == NULL)
    misstex (format, cmd);
  else
    db_insert (ret);
    
  return ret;
}



void mysystem(const char *s) {
   if (paranoia)
      system(s) ;
   else
      [((ComScroll *)[myPageView getConsole]) logCommand:s inBack:0] ;
}

void consoletofront() {
   [[((ComScroll *)[myPageView getConsole]) window] makeKeyAndOrderFront:0] ;
}

void textofront() {
   [[((ComScroll *)[myPageView getTeX]) window] makeKeyAndOrderFront:0] ;
}

void commandup() {
   [[myPageView getCommand] orderFront:0] ;
}

void previewtofront() {
   [[myPageView window] makeKeyAndOrderFront:0] ;
}

void myasyncsystem(const char *s) {
   textofront() ;
   [((ComScroll *)[myPageView getTeX]) logCommand:s inBack:1] ;
}

extern void reTeXit() ;

- TeXtexit:sender {
   reTeXit("tex -v \"%s\"") ;
   return self ;
}
- TeXlatexit:sender {
   reTeXit("latex -v \"%s\"") ;
   return self ;
}
- TeXslitexit:sender {
   reTeXit("slitex -v \"%s\"") ;
   return self ;
}
- TeXbibtexit:sender {
   reTeXit("bibtex \"%s\"") ;
   return self ;
}
- TeXamstexit:sender {
   reTeXit("amstex -v \"%s\"") ;
   return self ;
}
- TeXlatex209it:sender {
   reTeXit("latex209 -v \"%s\"") ;
   return self ;
}
- TeXeplainit:sender {
   reTeXit("eplain -v \"%s\"") ;
   return self ;
}
- openManual:sender {
   dviOpenFile("/usr/tex/ntman.dvi") ;
   return self ;
}
- TeXcustomexit:sender {
   reTeXit("%C -v \"%s\"") ;
   return self ;
}
- TeXdefaultexit:sender {
   reTeXit("%L -v \"%s\"") ;
   return self ;
}
- TeXmakeit:sender {
   reTeXit("make \"%s.dvi\"") ;
   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 ;
}

- appDidBecomeActive:(id)sender;
{
/* [tvWindow makeKeyAndOrderFront:self] ; */
   return self ;
}

- servercalled
{
   return self ;
}

/*
 *   What we do here is we try to find data of type NXFilenamePboardType,
 *   and then open it up.
 */
- serverOpen:(id)pb userData:(const char *)userData error:(char **)msg {
   char *data ;
   int len ;
   char *const *s ;
   char *const *types = [pb types] ;

   [self servercalled] ;
   for (s=types; *s; s++)
      if (*s == NXFilenamePboardType)
         break ;
   dviSaveFormat(userData) ;
   if (*s && [pb readType:NXFilenamePboardType data:&data length:&len]) {
      dviOpenFile(data) ;
      vm_deallocate(task_self(), (vm_address_t)data, len) ;
   }
   return self ;
}

/*
 *   The rest actually ignore the filename, since the user may be editing
 *   an auxilliary file.
 */
- serverReopen:(id)pb userData:(const char *)userData error:(char **)msg {
   [self servercalled] ;
   [self reOpenFile:self] ;
   return self ;
}

- serverCommand:(id)pb userData:(const char *)userData error:(char **)msg {
   [self servercalled] ;
   reTeXit(userData) ;
   return self ;
}

- serverMakeEquation:(id)pb userData:(const char *)userData
            error:(char **)msg {
   char *data, *p ;
   int len ;
   char *const *s ;
   char *const *types = [pb types] ;
   FILE *f ;
   char tempname[40] ;
   char cmd[120] ;
   extern char *mktemp() ;
   extern void unlink() ;
   extern int system() ;

   [self servercalled] ;
   for (s=types; *s; s++)
      if (*s == NXAsciiPboardType)
         break ;
   if (*s && [pb readType:NXAsciiPboardType data:&data length:&len]) {
      strcpy(tempname, "TeXEQN.XXXXXX") ;
      p = mktemp(tempname) ;
      p = p + strlen(p) ;
      strcpy(p, ".tex") ;
      f = fopen(tempname, "w") ;
      if (f == 0) {
         *msg = "Couldn't open temporary file" ;
         return self ;
      }
      fwrite(data, 1, len, f) ;
      fputs("\n \\nopagenumbers \\bye\n", f) ;
      fclose(f) ;
      *p = 0 ;
      sprintf(cmd, ((userData && *userData) ? userData :
         "tex %s.tex ; dvips %s.dvi -E -n 1 -o %s.eps -P epsf"),
          tempname, tempname, tempname) ;
      system(cmd) ; /* we want to use mysystem */
      strcpy(p, ".eps") ;
      f = fopen(tempname, "r") ;
      if (f) {
         int nlen ;
         char *mbuf ;
         const char *nt[1] ;

         nt[0] = NXPostScriptPboardType ;
         fseek(f, 0L, 2) ;
         nlen = ftell(f) ;
         fseek(f, 0L, 0) ;
         mbuf = malloc(nlen) ;
         if (mbuf == 0)
            error("! no memory?") ;
         fread(mbuf, 1, nlen, f) ;
         [pb declareTypes:nt num:1 owner:NULL] ;
         [pb writeType:NXPostScriptPboardType data:mbuf length:nlen] ;
         free(mbuf) ;
         fclose(f) ;
      } else
         *msg = "Output file didn't get created, somehow" ;
      vm_deallocate(task_self(), (vm_address_t)data, len) ;
      strcpy(p, ".dvi") ; unlink(tempname) ;
      strcpy(p, ".log") ; unlink(tempname) ;
      strcpy(p, ".tex") ; unlink(tempname) ;
      strcpy(p, ".eps") ; unlink(tempname) ;
   }
   return self ;
}

extern char Tbasename[] ;

- validRequestorForSendType:(NXAtom)sendType andReturnType:(NXAtom)returnType {
   printf("Someone's asking for %s but getting %s\n",
      (sendType ? sendType : ""), (returnType ? returnType : "")) ;
   if (sendType == NXFilenamePboardType && returnType == 0 && Tbasename[0])
      return self ;
   else
      return nil ;
}

- (BOOL)writeSelectionToPasteboard:(Pasteboard *)pboard types:(NXAtom *)types
/*
 * If one of the requested types is one of the ones we handle,
 * then we put our selection in the Pasteboard.
 */
{
    while (types && *types) {
	if (*types == NXFilenamePboardType)
           break ;
	types++;
    }
    if (types && *types && Tbasename[0]) {
        char tempname[1000] ;
        strcpy(tempname, Tbasename) ;
        strcat(tempname, ".tex") ;
        [pboard writeType:*types data:tempname length:(strlen(tempname))] ;
	return YES;
    } else {
	return NO;
    }
}

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) {
   [myPageView upDefaultformat:0] ;
   [myPageView upCustomformat:0] ;
}
@end
