/* * This file contains the Sun specific bits of TeXtool, a TeX previewer * derived from the texview posted on the network about spring 86, which * in turn was derived from an earlier version and so on right back to * a version for the BBN Bitgraph. * * This stuff deals with all SunView related things and calls things * in the dvistuff file to do the DVI file and font file stuff, which * in turn calls things in here like SetChar and SetRule to drive the * screen. */ /* * Version 2.1 of 30 Oct 87 -- first real outside release * * -> V2.2, 27 Nov 87 -- fixed bug where .dvi file was opened twice, * once from FrameDoneProc() and once by the WIN_REPAINT * case in CanvasEventProc(). This ran us out of fds. * -> V2.3, 29 Mar 88 -- fixed sloppy code in skip_specials() in pkstuff.c * that caused specials to be missed and treated as chars. */ /* include the various global #defines */ #include "defs.h" /* now some definitions for the menu items */ /* * NOTE: The menu items must be in the positions in the menu given by * these values. This is not done automatically! */ #define M_NULL 0 #define M_RESTART 1 #define M_NEWPAGE 2 #define M_NEWFILE 3 #define M_CD 4 #define M_TEX 5 #define M_LATEX 6 #define M_EDIT 7 #define M_SHELL 8 #define SM_TOGGLE_P 0x11 #define SM_TOGGLE_BIGP 0x12 #define SM_TOGGLE_B 0x13 #define SM_TOGGLE_M 0x14 #define DM_TOGGLE_D 0x21 #define DM_TOGGLE_X 0x22 #define DM_SHOW_FD 0x23 #define DM_SHOW_PXL_CACHE 0x24 /* now some Sun include files */ #include #include #include #include #include #include #include #include #include #include #include #include /* general external procedures */ char *getenv(); char *index(); char *rindex(); char *sprintf(); char *strcpy(); char *strcat(); int strlen(); char *getwd(); /* procedures from dvistuff */ extern void CloseDviFile(); extern void DoPage(); extern Boolean DviFileChanged(); extern void FreeFontStorage(); extern void OpenDviFile(); #ifdef DEBUG extern void ShowPxlFd(); extern void ShowPxlCache(); #endif /* procedures from pxlstuff or pkstuff */ extern void LoadAChar(); /* procedures in this file */ void BatchEnd(); void BatchStart(); void CanvasEventProc(); Notify_value CanvasInterposer(); void CheckFiles(); void ErrorEventProc(); char *ExpandTilde(); void Fatal(); void FrameDoneProc(); void InitWindows(); void MenuCd(); void MenuEdit(); Menu MenuGenerate(); void MenuLatex(); void MenuNewFile(); void MenuNewPage(); void MenuRestart(); void MenuShell(); void MenuShortPage(); void MenuTex(); void MenuToggleFlag(); void ProcessPage(); void RestartDviFile(); void SetBop(); void SetChar(); void SetFrameLabel(); void SetPageMenu(); void SetRule(); Menu ShiftMenuGenerate(); void SplitFilename(); void TextInputProc(); void Warning(); #ifdef DEBUG Menu DebugMenuGenerate(); void ShowFd(); #endif /* now include real global variables needed by both files */ #define _DEFINE #include "globals.h" /* now the "globals" only needed here */ static char progname[STRSIZE]; /* program name */ static char ttyinbuf[STRSIZE]; /* for input to ttysubwindow */ static char dirbuf[STRSIZE]; /* current working dir. */ static char framelabelbuf[STRSIZE]; /* for frame label */ static char curarea[STRSIZE]; /* current file area */ static char curext[STRSIZE]; /* current file extension */ static char curname[STRSIZE]; /* current file name */ static char textinputbuffer[STRSIZE]; /* for copying text panel item value */ static char dviname[STRSIZE]; /* current complete DVI filename */ static short textinput_state; /* display related stuff */ static int hh; /* current horizontal position in pixels */ static int vv; /* current vertical position in pixels */ static int current_page; /* pagepointers index for current page */ static int xcanvasoffset = RESOLUTION; /* 1 inch offset to match TeX's */ static int ycanvasoffset = RESOLUTION; /* 1 inch margin on paper */ static Boolean keyscroll; /* bodge to say h,j,k or l typed */ /* SunView defs */ Frame frame; Icon icon; Canvas canvas; Pixwin *pw; Scrollbar vsb, hsb; Cursor canvas_cursor; Menu menu, tenpagemenu, shiftmenu; Menu_item shortpageitem, longpageitem; Frame ttyframe; Tty ttysubwindow; Frame errorframe; Panel errorpanel; Panel_item errorheader, errormessage; Panel_item textinput; #ifdef DEBUG Menu debugmenu; #endif /* now the real code */ main(argc, argv) int argc; char *argv[]; { extern int optind; extern char *optarg; int c; strcpy(progname, argv[0]); /* initialse some globals */ Debug = FALSE; ExtraDebug = FALSE; PreLoad = FALSE; BigPreLoad = FALSE; Batching = TRUE; main_state = SB_INITIAL; Mflag = FALSE; pagepointers = NULL; /* we haven't malloc'd them yet */ InitWindows(&argc, argv); /* setup windows and consume -W args */ current_page = 0; /* start at the beginning */ /* get enviroment variables for different PXL directories */ if ((PXLpath=getenv("PXLPATH")) == NULL) PXLpath = PXLFONTAREA; if ((PKpath=getenv("PKPATH")) == NULL) PKpath = PKFONTAREA; while ((c = getopt(argc, argv, "dxpPbm:")) != EOF) switch(c) { case 'd': /* d selects Debug output */ Debug = TRUE; break; case 'x': /* extra debug info for pxl files */ ExtraDebug = TRUE; break; case 'p': /* p enables font pre-loading */ PreLoad = TRUE; break; case 'P': /* P enables char pixrect pre-loading */ BigPreLoad = TRUE; break; case 'b': /* turn batching off for slowness */ Batching = FALSE; break; case 'm': /* specify mag to override that in DVI file */ Mflag = TRUE; user_mag = atoi(optarg); break; case '?': default: fprintf(stderr, "usage: textool [-pPb] [-m ] [+n] file\n"); exit(1); } if ((optind < argc) && (argv[optind][0] == '+')) /* we have starting page number */ sscanf(&argv[optind][1], "%d", ¤t_page); if (optind >= argc) { main_state = SB_NOFILE; /* cancel SB_INITIAL status */ SplitFilename(""); /* _ as icon labels don't like space */ } else SplitFilename(argv[optind]); SetFrameLabel(); #ifdef DEBUG if (Debug) fprintf(stderr,"going into window_main_loop()\n"); #endif window_main_loop(frame); } /*-->InitWindows*/ void InitWindows(argcptr, argv) /* initialize SunView stuff */ int *argcptr; char **argv; { Pixrect *pr1; char error[IL_ERRORMSG_SIZE]; int i; pr1 = icon_load_mpr("/u/tex/textool/textool.icon", error); if (pr1 == NULL) /* couldn't load icon */ fprintf(stderr, "%s\n", error); /* not Fatal() as windows are not yet active */ icon = icon_create(ICON_IMAGE, pr1, 0); frame = window_create(0,FRAME, WIN_WIDTH, 900, WIN_HEIGHT, 900, WIN_X, 100, WIN_Y, 0, WIN_SHOW, FALSE, FRAME_LABEL, "TeXtool", FRAME_ICON, icon, FRAME_ARGC_PTR_ARGV, argcptr, argv, 0); vsb = scrollbar_create(SCROLL_LINE_HEIGHT, 20, SCROLL_ADVANCED_MODE, TRUE, 0); hsb = scrollbar_create(SCROLL_LINE_HEIGHT, 20, SCROLL_ADVANCED_MODE, TRUE, 0); canvas = window_create(frame,CANVAS, CANVAS_AUTO_SHRINK, FALSE, CANVAS_AUTO_EXPAND, FALSE, CANVAS_WIDTH, (17 * RESOLUTION)/2, /* 8.5in */ CANVAS_HEIGHT, 12 * RESOLUTION, /* 12in */ WIN_VERTICAL_SCROLLBAR, vsb, WIN_HORIZONTAL_SCROLLBAR, hsb, WIN_CONSUME_KBD_EVENT, WIN_ASCII_EVENTS, WIN_EVENT_PROC, CanvasEventProc, 0); pw = canvas_pixwin(canvas); /* interpose before canvas for pageing */ (void)notify_interpose_event_func(canvas, CanvasInterposer, NOTIFY_SAFE); scrollbar_scroll_to(hsb, (long)RESOLUTION/2); scrollbar_scroll_to(vsb, (long)RESOLUTION); /* now make the menu for canvas */ tenpagemenu = menu_create(MENU_ACTION_PROC, MenuShortPage, 0); menu_set(tenpagemenu, MENU_STRING_ITEM, "1", 1, MENU_STRING_ITEM, "2", 2, MENU_STRING_ITEM, "3", 3, MENU_STRING_ITEM, "4", 4, MENU_STRING_ITEM, "5", 5, MENU_STRING_ITEM, "6", 6, MENU_STRING_ITEM, "7", 7, MENU_STRING_ITEM, "8", 8, MENU_STRING_ITEM, "9", 9, MENU_STRING_ITEM, "10", 10, 0); shortpageitem = menu_create_item(MENU_PULLRIGHT_ITEM, "go to page", tenpagemenu, 0); longpageitem = menu_create_item(MENU_ACTION_ITEM, "go to page", MenuNewPage, 0); menu = menu_create(MENU_GEN_PROC, MenuGenerate, MENU_ITEM, MENU_ACTION_ITEM, "restart DVI file", MenuRestart, 0, MENU_ITEM, MENU_ACTION_ITEM, "new file", MenuNewFile, 0, MENU_ITEM, MENU_ACTION_ITEM, "change directory", MenuCd, 0, MENU_ITEM, MENU_ACTION_ITEM, "run tex", MenuTex, 0, MENU_ITEM, MENU_ACTION_ITEM, "run latex", MenuLatex, 0, MENU_ITEM, MENU_ACTION_ITEM, "edit .tex file", MenuEdit, 0, MENU_ITEM, MENU_ACTION_ITEM, "shell", MenuShell, 0,0); menu_set(menu, MENU_INSERT, 1, shortpageitem, 0); /* now a second menu for shift-right button */ shiftmenu = menu_create(MENU_GEN_PROC, ShiftMenuGenerate, MENU_ITEM, MENU_ACTION_PROC, MenuToggleFlag, MENU_VALUE, SM_TOGGLE_P, 0, MENU_ITEM, MENU_ACTION_PROC, MenuToggleFlag, MENU_VALUE, SM_TOGGLE_BIGP, 0, MENU_ITEM, MENU_ACTION_PROC, MenuToggleFlag, MENU_VALUE, SM_TOGGLE_B, 0, MENU_ITEM, MENU_ACTION_PROC, MenuToggleFlag, MENU_VALUE, SM_TOGGLE_M, 0,0); #ifdef DEBUG /* now a debug menu for the meta key */ debugmenu = menu_create(MENU_GEN_PROC, DebugMenuGenerate, MENU_ITEM, MENU_ACTION_PROC, MenuToggleFlag, MENU_VALUE, DM_TOGGLE_D, 0, MENU_ITEM, MENU_ACTION_PROC, MenuToggleFlag, MENU_VALUE, DM_TOGGLE_X, 0, MENU_ITEM, MENU_ACTION_ITEM, "show fd", ShowFd, MENU_VALUE, DM_SHOW_FD, 0, MENU_ITEM, MENU_ACTION_ITEM, "show PXL cache", ShowPxlCache, MENU_VALUE, DM_SHOW_PXL_CACHE, 0,0); #endif DEBUG /* now create a frame and panel for errors */ errorframe = window_create(frame, FRAME, FRAME_NO_CONFIRM, TRUE, WIN_SHOW, FALSE, WIN_COLUMNS, 80, WIN_ROWS, 2, WIN_X, 100, WIN_Y, 100, 0); errorpanel = window_create(errorframe, PANEL, PANEL_BACKGROUND_PROC, ErrorEventProc, PANEL_EVENT_PROC, ErrorEventProc, 0); errorheader = panel_create_item(errorpanel, PANEL_MESSAGE, PANEL_LABEL_STRING, "TeXtool Warning:", 0); errormessage = panel_create_item(errorpanel, PANEL_MESSAGE, PANEL_LABEL_STRING, "dummy message", 0); textinput = panel_create_item(errorpanel, PANEL_TEXT, PANEL_LABEL_STRING, "Magnification:", PANEL_ITEM_Y, ATTR_ROW(1), PANEL_ITEM_X, ATTR_COL(0), PANEL_SHOW_ITEM, FALSE, PANEL_VALUE_DISPLAY_LENGTH, 40, PANEL_NOTIFY_PROC, TextInputProc, 0); window_fit(errorpanel); window_fit(errorframe); /* create shell window for TeX, etc */ ttyframe = window_create(frame, FRAME, FRAME_LABEL, "TeXtool Shell", FRAME_SHOW_LABEL, TRUE, FRAME_NO_CONFIRM, TRUE, FRAME_DONE_PROC, FrameDoneProc, WIN_X, 25, WIN_Y, 25, WIN_SHOW, FALSE, 0); ttysubwindow = window_create(ttyframe, TTY, 0); } /*-->SetFrameLabel*/ void SetFrameLabel() { if (pagepointers == NULL) sprintf(framelabelbuf, "TeXtool: Directory: %s File: %s%s%s", getwd(dirbuf), curarea, curname, curext); else sprintf(framelabelbuf, "TeXtool: Directory: %s File: %s%s%s \"Page\": %d \\count0: %d", getwd(dirbuf), curarea, curname, curext, current_page+1, pagepointers[current_page].count_0); window_set(frame, FRAME_LABEL, framelabelbuf, 0); } /* * Now two procs to deal with canvas input. * CanvasInterposer is called first and filters out * the vertical scroll page requests, turning them into * calls of ProcessPage. * CanvasEventProc handles all other input cases. */ /*-->CanvasInterposer*/ Notify_value CanvasInterposer(object, event, arg, type) Canvas object; Event *event; Notify_arg arg; Notify_event_type type; { Scroll_motion motion; Notify_value retval; #ifdef DEBUG if (Debug) fprintf(stderr,"Interposer called (%d) - ", event_id(event)); if (Debug) fprintf(stderr, "\nobject = %X, *event = %X, arg = %X, type = %X\n", object, event, arg, type); #endif if (event_id(event) == SCROLL_REQUEST) { if ((Scrollbar)arg == vsb) { #ifdef DEBUG if (Debug) fprintf(stderr,"arg is vsb, "); #endif motion = (Scroll_motion)scrollbar_get(vsb, SCROLL_REQUEST_MOTION); if (!keyscroll && ((motion == SCROLL_PAGE_FORWARD) || (motion == SCROLL_PAGE_BACKWARD))) { #ifdef DEBUG if (Debug) fprintf(stderr,"motion is %X (PAGE), ", (int)motion); #endif /* now tell bar to undo scroll */ scrollbar_set(vsb, SCROLL_VIEW_START, scrollbar_get(vsb, SCROLL_LAST_VIEW_START), 0); if (motion == SCROLL_PAGE_BACKWARD) { if (current_page-- > 0) ProcessPage(current_page); else current_page++; } else { if (++current_page < totalpages) ProcessPage(current_page); else current_page--; } #ifdef DEBUG if (Debug) fprintf(stderr,"Interposer return (DONE)\n"); #endif return (NOTIFY_DONE); } } } #ifdef DEBUG if (Debug) fprintf(stderr,"calling next func\n"); #endif retval = (notify_next_event_func(object, event, arg, type)); if (Debug) fprintf(stderr, "Interposer return (%X)\n", retval); return (retval); } /*-->CanvasEventProc*/ void CanvasEventProc(notused, event) Canvas notused; Event *event; { static int intval; #ifdef DEBUG if (Debug) fprintf(stderr,"event proc called (id = %d) - ", event_id(event)); #endif keyscroll = FALSE; switch (event_id(event)) { case '\n': case '\r': if (main_state & (SB_PLUSNUMBER | SB_MINUSNUMBER)) { if ((main_state & SB_MINUSNUMBER) && (current_page -= intval) < 0) current_page = 0; if ((main_state & SB_PLUSNUMBER) && (current_page += intval) >= totalpages) current_page = totalpages-1; main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER); main_state |= SB_INTERPRET; ProcessPage(current_page); break; } /* else fall into next page case */ case ' ': /* normal case - start next page */ case 'n': main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER); main_state |= SB_INTERPRET; if (++current_page < totalpages) ProcessPage(current_page); else current_page--; break; case 'b': case 'P': case 'p': /* redisplay from previous page */ main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER); main_state |= SB_INTERPRET; if (current_page-- > 0) ProcessPage(current_page); else current_page++; break; #ifdef KEYBOARDSCROLL case 'j': main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER); main_state |= SB_INTERPRET; keyscroll = TRUE; scrollbar_scroll_to(vsb, (long)600); break; case 'h': main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER); main_state |= SB_INTERPRET; keyscroll = TRUE; scrollbar_scroll_to(hsb, (long)0); break; case 'l': main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER); main_state |= SB_INTERPRET; keyscroll = TRUE; scrollbar_scroll_to(hsb, (long)300); break; case 'k': main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER); main_state |= SB_INTERPRET; keyscroll = TRUE; scrollbar_scroll_to(vsb, (long)0); break; case 'c': main_state &= (~SB_PLUSNUMBER & ~SB_MINUSNUMBER); main_state |= SB_INTERPRET; keyscroll = TRUE; scrollbar_scroll_to(vsb, (long)RESOLUTION); scrollbar_scroll_to(hsb, (long)(RESOLUTION/2)); break; #endif #ifdef DEBUG case SCROLL_REQUEST: /* scroll request, after Sb gets it */ { int a, b, c, d; if (Debug) { a = (int)scrollbar_get(vsb, SCROLL_VIEW_START); b = (int)scrollbar_get(vsb, SCROLL_LAST_VIEW_START); c = (int)scrollbar_get(hsb, SCROLL_VIEW_START); d = (int)scrollbar_get(hsb, SCROLL_LAST_VIEW_START); fprintf(stderr,"\nVsb scroll from %d to %d\n", b, a); fprintf(stderr,"Hsb scroll from %d to %d\n", d, c); } } break; #endif case '-': /* read in val */ main_state |= SB_MINUSNUMBER; intval = 0; break; case '+': /* read in val */ main_state |= SB_PLUSNUMBER; intval = 0; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (main_state & (SB_PLUSNUMBER | SB_MINUSNUMBER)) intval = intval*10 + (event_id(event) - '0'); break; case '\b': case 127: /* delete key */ if (main_state & (SB_PLUSNUMBER | SB_MINUSNUMBER)) intval /= 10; break; case MS_RIGHT: if (event_is_up(event)) break; #ifdef DEBUG if (event_meta_is_down(event)) { (void)menu_show(debugmenu, canvas, canvas_window_event(canvas, event), 0); break; } #endif if (event_shift_is_down(event)) (void)menu_show(shiftmenu, canvas, canvas_window_event(canvas, event), 0); else (void)menu_show(menu, canvas, canvas_window_event(canvas, event), 0); break; case MS_LEFT: canvas_cursor = window_get(canvas, WIN_CURSOR); if (event_is_up(event)) { cursor_set(canvas_cursor, CURSOR_SHOW_CURSOR, TRUE, CURSOR_SHOW_CROSSHAIRS, FALSE, 0); } else { /* * All these except the pixrect op * are defaults but it does not seem * to work unles they are specified */ cursor_set(canvas_cursor, CURSOR_SHOW_CURSOR, FALSE, CURSOR_CROSSHAIR_COLOR, 1, CURSOR_CROSSHAIR_THICKNESS, 1, CURSOR_CROSSHAIR_GAP, 0, CURSOR_CROSSHAIR_LENGTH, CURSOR_TO_EDGE, CURSOR_CROSSHAIR_OP, PIX_SRC|PIX_DST, CURSOR_SHOW_CROSSHAIRS, TRUE, 0); } window_set(canvas, WIN_CURSOR, canvas_cursor, 0); break; case WIN_REPAINT: if (main_state & SB_INITIAL) { /* first time of display */ main_state &= ~SB_INITIAL; CheckFiles(); /* sets main_state */ OpenDviFile(dviname); if (main_state & (SB_NOFILE | SB_NODVIFILE)) break; SetPageMenu(); main_state &= ~SB_NEWFILE; main_state |= SB_INTERPRET; ProcessPage(current_page); } break; default: #ifdef DEBUG if (Debug) fprintf(stderr,"event proc default case - "); #endif } #ifdef DEBUG if (Debug) fprintf(stderr,"event proc return\n"); #endif } /* * Now the procedures that actually do the work of * drawing on the screen. These get called from * dvistuff to prevent it having to know about * SunView. * SetBop just clears the screen and sets the initial * offset. SetChar and SetRule draw text and lines. */ /*-->SetBop*/ void SetBop() { pw_writebackground(pw, 0, 0, pw->pw_prretained->pr_size.x, pw->pw_prretained->pr_size.y, PIX_CLR); /* * Start with h and v at offset point rather than 0,0. * This means that offset does not need to be added in * on every call to SetChar and SetRule. */ h = xcanvasoffset * hconv; v = ycanvasoffset * vconv; } /*-->SetChar*/ void SetChar(charptr, Set) struct char_entry *charptr; Boolean Set; { hh = PixRound(h, hconv); vv = PixRound(v, vconv); if (!charptr->where.isloaded) LoadAChar(charptr); if (charptr->where.isloaded == TRUE) pw_rop(pw, hh-charptr->xOffset, vv-charptr->yOffset, charptr->width, charptr->height, PIX_SRC | PIX_DST, charptr->where.address.pixrectptr, 0, 0); if (Set) h += charptr->tfmw; } /*-->SetRule*/ void SetRule(a, b, Set) int a, b; Boolean Set; { /* this routine draws \hrule and \vrule */ int ehh, evv; hh = PixRound(h, hconv); vv = PixRound(v-a, vconv); ehh = PixRound(h + b, hconv); evv = PixRound(v, vconv); if (hh == ehh) ehh++; if (vv == evv) vv--; if ((a > 0) && (b > 0)) pw_rop(pw, hh, vv, ehh-hh, evv-vv, PIX_SET, NULL, 0, 0); if (Set) h += b; } /* * These next two are only procedures here to avoid * having dvistuff.c know about Pixwins. * As they are only called once per page the loss of * speed is not a problem. */ /*-->BatchStart*/ void BatchStart() { pw_batch_on(pw); } /*-->BatchEnd*/ void BatchEnd() { pw_batch_off(pw); } /* * Now two procedures that call on things in * dvistuff to get pages displayed. */ /*-->ProcessPage*/ void ProcessPage(page) int page; { if (DviFileChanged()) RestartDviFile(); SetFrameLabel(); DoPage(page); } /*-->RestartDviFile*/ void RestartDviFile() { CloseDviFile(); FreeFontStorage(); main_state &= (~SB_INTERPRET & ~SB_NOFILE); /* main_state |= SB_NEWFILE; /* to allow a try at open */ CheckFiles(); /* sets main_state */ OpenDviFile(dviname); if (main_state & (SB_NOFILE | SB_NODVIFILE)) /* something wrong */ return; SetPageMenu(); main_state &= ~SB_NEWFILE; /* SB_NEWFILE must be set to get to here */ main_state |= SB_INTERPRET; } /* * Now to the menu generating procedures, one for * each menu. There is also a procedure to set * the "go to page" menu item depending on the * number of pages. * MenuGenerate() deals with most of the interlocking * to avoid illegal menu choices. */ /*-->MenuGenerate*/ Menu MenuGenerate(object, operation) Menu object; Menu_generate operation; { if (operation == MENU_CREATE) { menu_set(menu_get(object, MENU_NTH_ITEM, M_RESTART), MENU_INACTIVE, (main_state & (SB_TEXING | SB_NOFILE | SB_NODVIFILE ) ? TRUE : FALSE), 0); menu_set(menu_get(object, MENU_NTH_ITEM, M_NEWPAGE), MENU_INACTIVE, (main_state & (SB_TEXING | SB_NOFILE | SB_NODVIFILE) ? TRUE : FALSE), 0); menu_set(menu_get(object, MENU_NTH_ITEM, M_TEX), MENU_INACTIVE, (main_state & (SB_TEXING | SB_EDITING | SB_SHELL | SB_NOFILE | SB_NOTEXFILE) ? TRUE : FALSE), 0); menu_set(menu_get(object, MENU_NTH_ITEM, M_LATEX), MENU_INACTIVE, (main_state & (SB_TEXING | SB_EDITING | SB_SHELL | SB_NOFILE | SB_NOTEXFILE) ? TRUE : FALSE), 0); menu_set(menu_get(object, MENU_NTH_ITEM, M_EDIT), MENU_INACTIVE, (main_state & (SB_TEXING | SB_EDITING | SB_SHELL | SB_NOFILE) ? TRUE : FALSE), 0); menu_set(menu_get(object, MENU_NTH_ITEM, M_SHELL), MENU_INACTIVE, (main_state & (SB_TEXING | SB_EDITING | SB_SHELL) ? TRUE : FALSE), 0); } return (object); } /*-->ShiftMenuGenerate*/ Menu ShiftMenuGenerate(object, operation) Menu object; Menu_generate operation; { if (operation == MENU_CREATE) { menu_set(menu_get(object, MENU_NTH_ITEM, SM_TOGGLE_P & 0xF), MENU_STRING, (PreLoad ? "reset -p flag" : "set -p flag"), 0); menu_set(menu_get(object, MENU_NTH_ITEM, SM_TOGGLE_B & 0xF), MENU_STRING, (Batching ? "set -b flag" : "reset -b flag"), 0); menu_set(menu_get(object, MENU_NTH_ITEM, SM_TOGGLE_BIGP & 0xF), MENU_STRING, (BigPreLoad ? "reset -P flag" : "set -P flag"), 0); #ifdef USEGLOBALMAG menu_set(menu_get(object, MENU_NTH_ITEM, SM_TOGGLE_M & 0xF), MENU_STRING, (Mflag ? "reset -m flag" : "set -m flag"), 0); #endif } return (object); } #ifdef DEBUG /*-->DebugMenuGenerate*/ Menu DebugMenuGenerate(object, operation) Menu object; Menu_generate operation; { if (operation == MENU_CREATE) { menu_set(menu_get(object, MENU_NTH_ITEM, DM_TOGGLE_D & 0xF), MENU_STRING, (Debug ? "reset -d flag" : "set -d flag"), 0); menu_set(menu_get(object, MENU_NTH_ITEM, DM_TOGGLE_X & 0xF), MENU_STRING, (ExtraDebug ? "reset -x flag" : "set -x flag"), 0); } return (object); } #endif DEBUG /*-->SetPageMenu*/ void SetPageMenu() { short i; if (totalpages > 10) menu_set(menu, MENU_REPLACE, 2, longpageitem, 0); else { menu_set(menu, MENU_REPLACE, 2, shortpageitem, 0); for (i = 0; i < 10; i++) menu_set(menu_get(tenpagemenu, MENU_NTH_ITEM, i+1, 0), MENU_INACTIVE, (i < totalpages ? FALSE : TRUE), 0); } } /* * Now the action procs called after a menu selection * is made. */ /*-->MenuRestart*/ void MenuRestart(object, item) Menu object; Menu_item item; { window_release_event_lock(canvas); /* "I may be some time" */ current_page = 0; RestartDviFile(); DoPage(current_page); } /*-->MenuNewPage*/ void MenuNewPage(object, item) Menu object; Menu_item item; { panel_set(textinput, PANEL_LABEL_STRING, "Page number:", PANEL_VALUE, "", PANEL_SHOW_ITEM, TRUE, 0); panel_set(errorheader, PANEL_SHOW_ITEM, FALSE, 0); panel_set(errormessage, PANEL_LABEL_STRING, "", PANEL_SHOW_ITEM, FALSE, 0); window_fit(errorpanel); window_fit(errorframe); window_set(errorframe, WIN_X, 100, WIN_Y, 100, WIN_SHOW, TRUE, 0); textinput_state = M_NEWPAGE; } /*-->MenuShortPage*/ void MenuShortPage(object, item) Menu object; Menu_item item; { current_page = (int)menu_get(item, MENU_VALUE, 0); current_page--; /* as current_page =0 for page 1 */ if (current_page >= totalpages) current_page = totalpages - 1; ProcessPage(current_page); } /*-->MenuNewFile*/ void MenuNewFile(object, item) Menu object; Menu_item item; { panel_set(textinput, PANEL_LABEL_STRING, "Filename:", PANEL_VALUE, "", PANEL_SHOW_ITEM, TRUE, 0); panel_set(errorheader, PANEL_SHOW_ITEM, FALSE, 0); panel_set(errormessage, PANEL_LABEL_STRING, "", PANEL_SHOW_ITEM, FALSE, 0); window_fit(errorpanel); window_fit(errorframe); window_set(errorframe, WIN_X, 100, WIN_Y, 100, WIN_SHOW, TRUE, 0); textinput_state = M_NEWFILE; } /*-->MenuCd*/ void MenuCd(object, item) Menu object; Menu_item item; { panel_set(textinput, PANEL_LABEL_STRING, "Directory:", PANEL_VALUE, "", PANEL_SHOW_ITEM, TRUE, 0); panel_set(errorheader, PANEL_SHOW_ITEM, FALSE, 0); panel_set(errormessage, PANEL_LABEL_STRING, "", PANEL_SHOW_ITEM, FALSE, 0); window_fit(errorpanel); window_fit(errorframe); window_set(errorframe, WIN_X, 100, WIN_Y, 100, WIN_SHOW, TRUE, 0); textinput_state = M_CD; } /*-->MenuTex*/ void MenuTex(object, item) Menu object; Menu_item item; { strcpy(ttyinbuf, "cd "); strcat(ttyinbuf, getwd(dirbuf)); strcat(ttyinbuf, "\ntex "); strcat(ttyinbuf, curname); strcat(ttyinbuf, ".tex\n"); (void)ttysw_input(ttysubwindow, ttyinbuf, strlen(ttyinbuf)); main_state |= SB_TEXING; window_set(ttyframe, WIN_SHOW, TRUE, 0); } /*-->MenuLatex*/ void MenuLatex(object, item) Menu object; Menu_item item; { strcpy(ttyinbuf, "cd "); strcat(ttyinbuf, getwd(dirbuf)); strcat(ttyinbuf, "\nlatex "); strcat(ttyinbuf, curname); strcat(ttyinbuf, ".tex\n"); (void)ttysw_input(ttysubwindow, ttyinbuf, strlen(ttyinbuf)); main_state |= SB_TEXING; window_set(ttyframe, WIN_SHOW, TRUE, 0); } /*-->MenuEdit*/ void MenuEdit(object, item) Menu object; Menu_item item; { char *tcp; if ((tcp = getenv("EDITOR")) == NULL) tcp = "vi"; strcpy(ttyinbuf, tcp); strcat(ttyinbuf, " "); strcat(ttyinbuf, getwd(dirbuf)); strcat(ttyinbuf, "/"); strcat(ttyinbuf, curname); strcat(ttyinbuf, ".tex\n"); (void)ttysw_input(ttysubwindow, ttyinbuf, strlen(ttyinbuf)); main_state |= SB_EDITING; window_set(ttyframe, WIN_SHOW, TRUE, 0); } /*-->MenuShell*/ void MenuShell(object, item) Menu object; Menu_item item; { main_state |= SB_SHELL; window_set(ttyframe, WIN_SHOW, TRUE, 0); } /*-->MenuToggleFlag*/ void MenuToggleFlag(object, item) Menu object; Menu_item item; { int itemvalue; itemvalue = (int)menu_get(item, MENU_VALUE, 0); switch (itemvalue) { #ifdef DEBUG case DM_TOGGLE_D: Debug ^= 1; break; case DM_TOGGLE_X: ExtraDebug ^= 1; break; #endif case SM_TOGGLE_P: PreLoad ^= 1; break; case SM_TOGGLE_B: Batching ^= 1; break; case SM_TOGGLE_BIGP: BigPreLoad ^= 1; break; #ifdef USEGLOBALMAG case SM_TOGGLE_M: Mflag ^= 1; if (Mflag) { panel_set(textinput, PANEL_LABEL_STRING, "Magnification:", PANEL_VALUE, "", PANEL_SHOW_ITEM, TRUE, 0); panel_set(errorheader, PANEL_SHOW_ITEM, FALSE, 0); panel_set(errormessage, PANEL_LABEL_STRING, "", PANEL_SHOW_ITEM, FALSE, 0); window_fit(errorpanel); window_fit(errorframe); window_set(errorframe, WIN_X, 100, WIN_Y, 100, WIN_SHOW, TRUE, 0); textinput_state = SM_TOGGLE_M; } break; #endif default: break; } } /* * The event proc for the panel which contains the * error message item and the text input item. * If the panel event is an ascii one it passes it * on to the text input item. It removes the panel * on a left mouse button. */ /*-->ErrorEventProc*/ void ErrorEventProc(object, event) Panel object; Event *event; { if (event_id(event) <= ASCII_LAST) panel_accept_key(textinput, event); else if (event_id(event) == MS_LEFT) window_set(errorframe, WIN_SHOW, FALSE, 0); } /* * The notify proc for the panel text input item. * This gets things like page numbers and filenames * from the user. */ /*-->TextInputProc*/ void TextInputProc(item, event) Panel_item item; Event *event; { #ifdef DEBUG if (Debug) fprintf(stderr,"TextInputProc(): panel_get_value returns %s\n", (char *)panel_get_value(textinput)); #endif strcpy(textinputbuffer, (char *)panel_get_value(textinput)); window_set(errorframe, WIN_SHOW, FALSE, 0); if (*textinputbuffer == NULL) return; switch(textinput_state) { case M_NEWPAGE: sscanf(textinputbuffer, "%d", ¤t_page); current_page--; if (current_page >= totalpages) current_page = totalpages - 1; ProcessPage(current_page); break; case M_NEWFILE: window_release_event_lock(errorframe); /* as this may take some time */ SplitFilename(ExpandTilde(textinputbuffer)); /* sets dviname */ CloseDviFile(); /* from dvifp */ FreeFontStorage(); SetBop(); /* clear screen */ current_page = 0; main_state &= (~SB_INTERPRET & ~SB_NOFILE); CheckFiles(); /* see what's there */ OpenDviFile(dviname); /* sets dvifp */ SetFrameLabel(); if (main_state & (SB_NOFILE | SB_NODVIFILE)) /* something wrong */ break; SetPageMenu(); main_state &= ~SB_NEWFILE; main_state |= SB_INTERPRET; DoPage(current_page); break; case M_CD: if (chdir(ExpandTilde(textinputbuffer))) Warning("Couldn't change directory"); SetFrameLabel(); break; case SM_TOGGLE_M: user_mag = atoi(textinputbuffer); break; default: break; } } /* * The done proc for the frame with the tty subwindow. * It removes the frame and adjusts the display if the * DVI file has changed. */ /*-->FrameDoneProc*/ void FrameDoneProc(object) Frame object; { int i; if (Debug) { fprintf(stderr, "FrameDoneProc(), object = %X, frame = %X, ttyframe = %X\n", object, frame, ttyframe); fprintf(stderr,"calling default done proc for object\n"); } frame_default_done_proc(object); main_state &= (~SB_TEXING & ~SB_EDITING & ~SB_SHELL); CheckFiles(); /* see if anything changed */ if (main_state & SB_NEWFILE) { /* we haven't seen it before */ OpenDviFile(dviname); if (main_state & SB_NOFILE)/* can't have NODVIFILE as NEWFILE was set */ return; main_state &= ~SB_NEWFILE; main_state |= SB_INTERPRET; DoPage(current_page); } else if (DviFileChanged()) { RestartDviFile(); DoPage(current_page); } } /* * Now some utility procedures. */ /*-->SplitFilename*/ void SplitFilename(nameptr) char *nameptr; { char *tcp, *tcp1; Icon temp_icon; /* for changing label */ /* process filename */ tcp = rindex(nameptr, '/'); if (tcp == NULL) { curarea[0] = '\0'; tcp = nameptr; } else { strncpy(curarea, nameptr, tcp-nameptr+1); curarea[tcp-nameptr+1] = '\0'; /* as strncpy will not do this */ tcp += 1; } tcp1 = index(tcp, '.'); if (tcp1 == NULL) { strcpy(curname, tcp); curext[0] = '\0'; } else { strncpy(curname, tcp, tcp1-tcp); strcpy(curext, tcp1); } strcpy(dviname, curarea); strcat(dviname, curname); if (curext[0] == '\0') strcat(dviname, ".dvi"); else strcat(dviname, curext); #ifdef DEBUG if (Debug) { fprintf(stderr,"curarea = %s\n", curarea); fprintf(stderr,"curname = %s\nsetting icon label to curname\n", curname); fprintf(stderr,"curext = %s\n", curext); fprintf(stderr,"dviname = %s\n", dviname); } #endif temp_icon = (Icon)window_get(frame, FRAME_ICON, 0); icon_set(temp_icon, ICON_LABEL, curname, 0); window_set(frame, FRAME_ICON, temp_icon, 0); } /* * CheckFiles tries access on the .dvi file, * and if that does not exist, on the .tex file * and sets main_state accordingly. */ /*-->CheckFiles*/ void CheckFiles() { char buf[STRSIZE]; if (access(dviname, F_OK | R_OK) == 0) { /* .dvi file present */ if (main_state & SB_NODVIFILE) /* first time .dvi file found */ main_state |= SB_NEWFILE; main_state &= (~SB_NODVIFILE & ~SB_NOTEXFILE); } else { strcpy(buf, curarea); strcat(buf, curname); strcat(buf, ".tex"); if (access(buf, F_OK | R_OK) == 0) { /* no .dvi file but .tex file ok */ main_state |= SB_NODVIFILE; main_state &= (~SB_NEWFILE & ~SB_NOTEXFILE); } else { /* no .tex file either */ main_state |= SB_NODVIFILE | SB_NOTEXFILE; main_state &= ~SB_NEWFILE; } } } /*-->ExpandTilde*/ char * ExpandTilde(iptr) char *iptr; { char buff[STRSIZE]; char *tptr; struct passwd *passwdptr; #ifdef DEBUG if (Debug) fprintf(stderr,"ExpandTilde(%s) - ", iptr); #endif if (*iptr == '~') { /* something to do */ strcpy(buff, iptr); tptr = index(buff, '/'); if ((strlen(buff) == 1) || ((tptr-buff) == 1)) /* expand to our $HOME */ strcpy(iptr, getenv("HOME")); else { /* ~name/... form */ if (tptr != NULL) *tptr = 0; if ((passwdptr = getpwnam(&buff[1])) != NULL) strcpy(iptr, passwdptr->pw_dir); if (tptr != NULL) *tptr = '/'; } if (tptr != NULL) strcat(iptr, tptr); /* complete rest of path if there is any */ } #ifdef DEBUG if (Debug) fprintf(stderr,"returns %s\n", iptr); #endif return (iptr); } /* * Two error message procedures. * Warning just displays the message, Error displays * and then abandons the DVI file and goes to the * NOFILE state. */ /*-->Warning*/ void Warning(fmt, arg1, arg2, arg3, arg4) /* issue a warning */ char *fmt; /* format */ char *arg1, *arg2, *arg3, *arg4; /* arguments */ { char message[STRSIZE]; sprintf(message, fmt, arg1, arg2, arg3, arg4); panel_set(errorheader, PANEL_LABEL_STRING, "TeXtool Warning:", PANEL_SHOW_ITEM, TRUE, 0); panel_set(errormessage, PANEL_LABEL_STRING, message, PANEL_SHOW_ITEM, TRUE, 0); panel_set(textinput, PANEL_SHOW_ITEM, FALSE, 0); window_fit(errorpanel); window_fit(errorframe); window_set(errorframe, WIN_X, 100, WIN_Y, 100, WIN_SHOW, TRUE, 0); } /*-->Fatal*/ void Fatal(fmt, arg1, arg2, arg3, arg4)/* issue a fatal error message */ char *fmt; /* format */ char *arg1, *arg2, *arg3, *arg4; /* arguments */ { char message[STRSIZE]; sprintf(message, fmt, arg1, arg2, arg3, arg4); panel_set(errorheader, PANEL_LABEL_STRING, "TeXtool Error:", PANEL_SHOW_ITEM, TRUE, 0); panel_set(errormessage, PANEL_LABEL_STRING, message, PANEL_SHOW_ITEM, TRUE, 0); panel_set(textinput, PANEL_SHOW_ITEM, FALSE, 0); window_fit(errorpanel); window_fit(errorframe); window_set(errorframe, WIN_X, 100, WIN_Y, 100, WIN_SHOW, TRUE, 0); CloseDviFile(); FreeFontStorage(); /* to get to known stable state */ main_state |= SB_NOFILE; /* to stop further processing */ main_state &= (~SB_NEWFILE & ~SB_NODVIFILE & ~SB_NOTEXFILE & ~SB_INTERPRET); SplitFilename(""); SetFrameLabel(); } #ifdef DEBUG /* * A procedure to show the fds we are using. * There was a leak of fds somewhere where ptys were * not closed when a frame with a tty subwindow in it * was destroyed and this was used to find it. * The tty subframe is now not destroyed but just * undisplayed to cure the problem. * It also shows the huge number of fds needed by * SunView which cuts down on the number available for * PXL file caching. */ /*-->ShowFd*/ void ShowFd(object, item) Menu object; Menu_item item; { short i; struct stat statbuf; fprintf(stderr,"frame %d, win%d\n", window_get(frame, WIN_FD), window_get(frame, WIN_DEVICE_NUMBER)); fprintf(stderr,"canvas %d, win%d\n", window_get(canvas, WIN_FD), window_get(canvas, WIN_DEVICE_NUMBER)); fprintf(stderr,"ttyframe %d, win%d\n", window_get(ttyframe, WIN_FD), window_get(ttyframe, WIN_DEVICE_NUMBER)); fprintf(stderr,"ttysubwindow %d, win%d\n", window_get(ttysubwindow, WIN_FD), window_get(ttysubwindow, WIN_DEVICE_NUMBER)); fprintf(stderr,"errorframe %d, win%d\n", window_get(errorframe, WIN_FD), window_get(errorframe, WIN_DEVICE_NUMBER)); fprintf(stderr,"errorpanel %d, win%d\n", window_get(errorpanel, WIN_FD), window_get(errorpanel, WIN_DEVICE_NUMBER)); ShowPxlFd(); for (i=0; i<30; i++) /* enumerate fds */ if (fstat(i,&statbuf) == 0) fprintf(stderr,"fd %d open, type = %o, inode = %d\n", i, statbuf.st_mode & S_IFMT, statbuf.st_ino); } #endif