/* * This program is Copyright (C) 1987 by the Board of Trustees of the * University of Illinois, and by the author Dirk Grunwald. */ /* * * This looks kind of strange because, initially, I had intended to * allow you to `put away' a page without destroying it -- but * I've decided not to do that. * */ #include #include #include #include #include #include #include "dvi-simple.h" #include "texx2.h" #include "DviPage.h" #include "texx2-page.h" #include "texx2-font.h" #include /* needed to get scrollbar sizes? */ extern Widget TopLevelWidget; #ifdef _STCD_ void TeXPageRealize(TeXPage *, int); static void showPage(TeXPage *, int); #else void TeXPageRealize(); static void showPage(); #endif int TeXPages; TeXPage *TheTeXPages[ MAX_TEX_PAGES ]; typedef struct { char *thePage; int refs; } DviPageRef; DviPageRef *ThePageRefs = 0; void TeXPageCloseFile() { int popup; /* dispose of existing information */ for ( popup = 0; popup < TeXPages; popup++ ) { TeXPage *tp = TheTeXPages[popup]; if ( tp && tp -> popUpPage) { TeXPageDeref( tp -> pageNumber ); TeXFontUnref( tp -> userMag); tp -> pageData = 0; } } if ( ThePageRefs ) { int i; for (i = 0; i < DviTotalPages; i++ ) { XtFree( ThePageRefs[i].thePage ); ThePageRefs[ i ].thePage = 0; } } XtFree( ThePageRefs ); ThePageRefs = 0; } void TeXPageSlamPages() { int popup; /* take down pages, dispose of existing information */ for ( popup = 0; popup < TeXPages; popup++ ) { if ( TheTeXPages[popup] && TheTeXPages[ popup ] -> popUpPage) { XtDestroyWidget( TheTeXPages[ popup ] -> popUpPage ); } } } void TeXPageOpenFile() { /* now rebuild it all */ if ( DviFile != 0 ) { int i; int popup; ThePageRefs = (DviPageRef *) XtMalloc( (DviTotalPages+1) * sizeof(DviPageRef) ); for (i = 0; i < DviTotalPages; i++ ) { ThePageRefs[i].thePage = 0; ThePageRefs[i].refs = 0; } for ( popup = 0; popup < TeXPages; popup++ ) { TeXPage *tp = TheTeXPages[ popup ]; if ( tp && tp -> popUpPage) { int pno = tp -> pageNumber; if (pno >= 0 && pno < DviTotalPages) { Arg argList[20]; int args = 0; tp -> pageData = TeXPageRef( tp -> pageNumber ); XtSetArg(argList[args], XtNpai, &ThePostAmbleInfo); args++; XtSetArg(argList[args], XtNpage, tp -> pageData); args++; XtSetArg(argList[args], XtNdviFonts, TheFontInfo); args++; XtSetArg(argList[args], XtNxFonts, TeXFontRef(tp -> userMag)); args++; XtSetValues( tp -> singleDviPage, argList, args); showPage( tp, False ); } else { XtDestroyWidget( tp -> popUpPage ); } } } } } /* * Reference and dereference a page structure -- these keep track * of the memory allocated for page buffers & disposes of them * when not in use. */ char * TeXPageRef(pageno) int pageno; { assert( pageno >= 0 || pageno < DviTotalPages ); ThePageRefs[ pageno ].refs++; if ( ThePageRefs[ pageno ].thePage == 0 ) { ThePageRefs[ pageno ].thePage = DviFetchPage( pageno ); } return(ThePageRefs[ pageno ].thePage ); } void TeXPageDeref(pageno) int pageno; { assert( pageno >= 0 || pageno < DviTotalPages ); if ( ThePageRefs && ThePageRefs[ pageno ].refs > 0) { ThePageRefs[ pageno ].refs--; if ( ThePageRefs[ pageno ].refs <= 0 ) { XtFree( ThePageRefs[ pageno ].thePage ); ThePageRefs[ pageno ].thePage = 0; } } } /* * Locate a free TeXPage structure. See comment at head. */ TeXPage * TeXPageLocate() { int i; TeXPage *tp; for (i = 0; i < TeXPages; i++ ) { if ( ! TheTeXPages[ i ] -> active ) { return( TheTeXPages[ i ] ); } } tp = (TeXPage *) XtMalloc(sizeof(TeXPage)); bzero( tp, sizeof(TeXPage) ); tp -> realized = False; tp -> tied = 0; tp -> tiedTo = 0; /* install the page in the page list */ if ( TeXPages > MAX_TEX_PAGES ) { error(0,0,"No more pages available"); return(0); } TheTeXPages[ TeXPages++ ] = tp; return( tp ); } /* * The callback when pages die. */ static void dviPageDied(w, clientData, callData) Widget w; caddr_t clientData; /* unused */ caddr_t callData; /* unused */ { TeXPage *tp = (TeXPage*) clientData; if ( tp != 0 ){ tp -> active = False; tp -> realized = False; TeXPageDeref( tp -> pageNumber ); TeXFontUnref( tp -> userMag); tp -> popUpPage = 0; if ( tp -> tiedTo != 0 && tp -> tiedTo -> active ) { tp -> tiedTo -> tied = 0; } if ( tp -> tied != 0 && tp -> tied -> active ) { tp -> tied -> tiedTo = 0; } tp -> tiedTo = 0; tp -> tied = 0; } } static void pushQuitButton(w, clientData, callData) Widget w; caddr_t clientData; /* unused */ caddr_t callData; /* unused */ { TeXPage *tp = (TeXPage*) clientData; XtDestroyWidget( tp -> popUpPage ); } /* * Set all the buttons for this page, possibly also * sending the page information */ static Arg sensArgs[] = { {XtNsensitive, (XtArgVal) True} }; static Arg insensArgs[] = { {XtNsensitive, (XtArgVal) False} }; static void showPage(tp, displayPage) TeXPage *tp; Bool displayPage; { Arg argList[20]; Cardinal args; Pixel fore; Pixel back; if ( displayPage ) { tp -> pageData = TeXPageRef( tp -> pageNumber ); args = 0; XtSetArg(argList[args], XtNpage, tp -> pageData); args++; XtSetValues(tp -> singleDviPage, argList, args); } if ( tp -> pageNumber == 0 ) { XtSetValues( tp -> backwardButton, insensArgs, XtNumber(insensArgs)); } else { XtSetValues( tp -> backwardButton, sensArgs, XtNumber(sensArgs)); } if ( tp -> pageNumber >= (DviTotalPages-1)) { XtSetValues( tp -> forewardButton, insensArgs, XtNumber(insensArgs)); } else { XtSetValues( tp -> forewardButton, sensArgs, XtNumber(sensArgs)); } /* Take normal values from another button */ args = 0; XtSetArg(argList[args], XtNforeground, &fore); args++; XtSetArg(argList[args], XtNbackground, &back); args++; XtGetValues( tp -> forewardButton, argList, args); if (TeXMarkState( tp -> pageNumber ) ) { Arg argList[20]; Cardinal args; args = 0; XtSetArg(argList[args], XtNforeground, back); args++; XtSetArg(argList[args], XtNbackground, fore); args++; XtSetValues( tp -> markButton, argList, args ); } else { Arg argList[20]; Cardinal args; args = 0; XtSetArg(argList[args], XtNforeground, fore); args++; XtSetArg(argList[args], XtNbackground, back); args++; XtSetValues( tp -> markButton, argList, args ); } } static void pushForewardButton(w, clientData, callData) Widget w; caddr_t clientData; /* unused */ caddr_t callData; /* unused */ { TeXPage *tp = (TeXPage*) clientData; /* */ char *p; if (tp -> pageNumber >= DviTotalPages) { return; } else { if ( tp -> pageData != 0 ) { TeXPageDeref( tp -> pageNumber ); } tp -> pageNumber++; } showPage(tp, True); if ( tp -> tied ) { pushForewardButton( tp -> tied, tp -> tied, 0 ); } } static void pushBackwardButton(w, clientData, callData) Widget w; caddr_t clientData; /* unused */ caddr_t callData; /* unused */ { TeXPage *tp = (TeXPage*) clientData; char *p; if ( tp -> tied ) { pushBackwardButton( tp -> tied, tp -> tied, 0 ); } if ( tp -> pageNumber <= 0 ) { return; } else { if ( tp -> pageData != 0 ) { TeXPageDeref( tp -> pageNumber ); } tp -> pageNumber--; } showPage(tp, True); } static void pushMarkButton(w, clientData, callData) Widget w; caddr_t clientData; /* unused */ caddr_t callData; /* unused */ { TeXPage *tp = (TeXPage*) clientData; TeXMarkToggle( tp -> pageNumber ); showPage(tp, False); } static void pushDupButton(w, clientData, callData) Widget w; caddr_t clientData; /* unused */ caddr_t callData; /* unused */ { TeXPage *tp = (TeXPage *) clientData; TeXPage *newtp = TeXPageLocate(); TeXPageRealize(newtp, tp -> pageNumber); } static void pushTieButton(w, clientData, callData) Widget w; caddr_t clientData; /* unused */ caddr_t callData; /* unused */ { TeXPage *tp = (TeXPage *) clientData; if ( tp -> tied == 0 ) { TeXPage *newtp = TeXPageLocate(); tp -> tied = newtp; newtp -> tiedTo = tp; TeXPageRealize(newtp, tp -> pageNumber); } } /* * The goto button. This scans, starting at the current page number, * until a value of ``DviCount[0]'' meets the goto destination. * This allows us to hit the multiple ``page 1'' refs. */ static void pushGotoButton(w, clientData, callData) Widget w; caddr_t clientData; /* unused */ caddr_t callData; /* unused */ { TeXPage *tp = (TeXPage*) clientData; char *pageNumber = tp -> pageNumberBuffer; if ( pageNumber != 0 && strlen( pageNumber ) > 0 ) { int want = atoi( pageNumber ); int here = tp -> pageNumber; int page = here; for(;;) { page++; if ( page >= DviTotalPages ) { page = 0; } if ( page == here ) return; if ( DviCount[0][page] == want ) { TeXPageDeref( tp -> pageNumber ); tp -> pageNumber = page; TeXPageRef( tp -> pageNumber ); showPage(tp, True); return; } } } } void changeMag( tp, mag ) TeXPage *tp; int mag; { Arg argList[20]; Cardinal args; if ( mag > 0 && mag != tp -> userMag ) { XFontStruct **x; Dimension maxHt = (int) ((HeightOfScreen(XtScreen(TopLevelWidget))) * 0.90); Dimension maxWd = (int) ((WidthOfScreen(XtScreen(TopLevelWidget))) * 0.95); Dimension dviHt; Dimension dviWd; TeXFontUnref( tp -> userMag); tp -> userMag = mag; x = TeXFontRef(tp -> userMag); args = 0; XtSetArg(argList[args], XtNuserMag, tp -> userMag); args++; XtSetArg(argList[args], XtNxFonts, x); args++; XtSetValues( tp -> singleDviPage, argList, args); /* get the size of the dvi page */ if ( TeXxResources.autoSize ) { args = 0; XtSetArg(argList[args], XtNwidth, &dviWd); args++; XtSetArg(argList[args], XtNheight, &dviHt); args++; XtGetValues( tp -> singleDviPage, argList, args); if ( dviWd <= maxWd ){ maxWd = dviWd; /* will we need scrollbars? */ if ( dviHt > maxHt ) { ViewportWidget vp = (ViewportWidget) (tp -> viewPort); maxWd = maxWd + vp -> viewport.vert_bar -> core.width + vp -> viewport.vert_bar -> core.border_width; } } if ( dviHt <= maxHt ) { maxHt = dviHt; if ( dviWd > maxWd ) { ViewportWidget vp = (ViewportWidget) (tp -> viewPort); maxHt = maxHt + vp -> viewport.horiz_bar -> core.width + vp -> viewport.horiz_bar -> core.border_width; } } args = 0; XtSetArg(argList[args], XtNwidth, maxWd); args++; XtSetArg(argList[args], XtNheight, maxHt); args++; XtSetValues( tp -> viewPort, argList, args); } } } static void pushMagButton(w, clientData, callData) Widget w; caddr_t clientData; caddr_t callData; { TeXPage *tp = (TeXPage *) clientData; int mag; mag = atoi( tp -> pageNumberBuffer ); changeMag( tp, mag ); } static void pushLargeButton(w, clientData, callData) Widget w; caddr_t clientData; /* unused */ caddr_t callData; /* unused */ { TeXPage *tp = (TeXPage *) clientData; changeMag( tp, TeXxResources.largeMag ); } static void pushSmallButton(w, clientData, callData) Widget w; caddr_t clientData; /* unused */ caddr_t callData; /* unused */ { TeXPage *tp = (TeXPage *) clientData; changeMag( tp, TeXxResources.smallMag ); } /* * Realize the TeXPage structure and pop up the corresponding window */ void TeXPageRealize(tp, pageNumber) TeXPage *tp; int pageNumber; { Arg argList[20]; int args; Dimension maxHt = (int) ((HeightOfScreen(XtScreen(TopLevelWidget))) * 0.90); Dimension maxWd = (int) ((WidthOfScreen(XtScreen(TopLevelWidget))) * 0.95); Dimension dviHt; Dimension dviWd; extern pushReopenButton(); /* from texx2-file */ Dimension gap = 30; if ( tp == NULL ) { return; } assert(TopLevelWidget != 0); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNallowShellResize, True); args++; tp -> popUpPage = XtCreatePopupShell("TeXx2-Page-Display", topLevelShellWidgetClass, TopLevelWidget, argList,args); args = 0; XtSetArg(argList[args], XtNresize, True); args++; tp -> dviPageBox = XtCreateManagedWidget("dviPageBox", formWidgetClass, tp -> popUpPage, argList, args); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNleft, XtChainLeft); args++; XtSetArg(argList[args], XtNtop, XtChainTop); args++; tp -> quitButton = XtCreateManagedWidget("Quit", commandWidgetClass, tp -> dviPageBox, argList, args); XtAddCallback(tp -> quitButton, XtNcallback, pushQuitButton, tp); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNtop, XtChainTop); args++; XtSetArg(argList[args], XtNfromHoriz, tp -> quitButton); args++; XtSetArg(argList[args], XtNhorizDistance, gap); args++; tp -> forewardButton = XtCreateManagedWidget("Forward", commandWidgetClass, tp -> dviPageBox, argList, args); XtAddCallback(tp -> forewardButton, XtNcallback, pushForewardButton, tp); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNtop, XtChainTop); args++; XtSetArg(argList[args], XtNfromHoriz, tp -> forewardButton); args++; tp -> backwardButton = XtCreateManagedWidget("Backward", commandWidgetClass, tp -> dviPageBox, argList, args); XtAddCallback(tp -> backwardButton, XtNcallback, pushBackwardButton, tp); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNtop, XtChainTop); args++; XtSetArg(argList[args], XtNfromHoriz, tp -> backwardButton); args++; tp -> markButton = XtCreateManagedWidget("Mark", commandWidgetClass, tp -> dviPageBox, argList, args); XtAddCallback(tp -> markButton, XtNcallback, pushMarkButton, tp); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNtop, XtChainTop); args++; XtSetArg(argList[args], XtNfromHoriz, tp -> markButton); args++; tp -> dupButton = XtCreateManagedWidget("Dup", commandWidgetClass, tp -> dviPageBox, argList, args); XtAddCallback(tp -> dupButton, XtNcallback, pushDupButton, tp); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNtop, XtChainTop); args++; XtSetArg(argList[args], XtNfromHoriz, tp -> dupButton); args++; tp -> tieButton = XtCreateManagedWidget("Tied", commandWidgetClass, tp -> dviPageBox, argList, args); XtAddCallback(tp -> tieButton, XtNcallback, pushTieButton, tp); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNtop, XtChainTop); args++; XtSetArg(argList[args], XtNfromHoriz, tp -> tieButton); args++; tp -> largeButton = XtCreateManagedWidget("Large", commandWidgetClass, tp -> dviPageBox, argList, args); XtAddCallback(tp -> largeButton, XtNcallback, pushLargeButton, tp); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNtop, XtChainTop); args++; XtSetArg(argList[args], XtNfromHoriz, tp -> largeButton); args++; tp -> smallButton = XtCreateManagedWidget("Small", commandWidgetClass, tp -> dviPageBox, argList, args); XtAddCallback(tp -> smallButton, XtNcallback, pushSmallButton, tp); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNtop, XtChainTop); args++; XtSetArg(argList[args], XtNfromHoriz, tp -> smallButton); args++; tp -> reopenButton = XtCreateManagedWidget("Reopen", commandWidgetClass, tp -> dviPageBox, argList, args); XtAddCallback(tp -> reopenButton, XtNcallback, pushReopenButton, tp); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNtop, XtChainTop); args++; XtSetArg(argList[args], XtNfromHoriz, tp -> reopenButton); args++; XtSetArg(argList[args], XtNhorizDistance, gap); args++; XtSetArg(argList[args], XtNeditType, XttextEdit); args++; XtSetArg(argList[args], XtNstring, tp -> pageNumberBuffer); args++; XtSetArg(argList[args], XtNlength, MAXPAGENUMBERBUFFER); args++; XtSetArg(argList[args], XtNtextOptions, resizeWidth); args++; XtSetArg(argList[args], XtNresizable,True); args++; tp -> pageNumberText = XtCreateManagedWidget("", asciiStringWidgetClass, tp -> dviPageBox, argList, args); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNtop, XtChainTop); args++; XtSetArg(argList[args], XtNfromHoriz, tp -> pageNumberText); args++; tp -> gotoButton = XtCreateManagedWidget("Goto", commandWidgetClass, tp -> dviPageBox, argList, args); XtAddCallback(tp -> gotoButton, XtNcallback, pushGotoButton, tp); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNtop, XtChainTop); args++; XtSetArg(argList[args], XtNfromHoriz, tp -> gotoButton); args++; tp -> magButton = XtCreateManagedWidget("Mag", commandWidgetClass, tp -> dviPageBox, argList, args); XtAddCallback(tp -> magButton, XtNcallback, pushMagButton, tp); args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNleft, XtChainLeft); args++; XtSetArg(argList[args], XtNfromVert, tp -> pageNumberText); args++; XtSetArg(argList[args], XtNresizable, True); args++; XtSetArg(argList[args], XtNallowHoriz, True); args++; XtSetArg(argList[args], XtNallowVert, True); args++; tp -> viewPort = XtCreateWidget("ViewPort", viewportWidgetClass, tp -> dviPageBox, argList, args); bzero(tp -> pageNumberBuffer, MAXPAGENUMBERBUFFER); tp -> realized = True; tp -> pageNumber = pageNumber; tp -> pageData = TeXPageRef( tp -> pageNumber ); tp -> userMag = TeXxResources.userMag; tp -> active = True; args = 0; XtSetArg(argList[args], XtNresize, True); args++; XtSetArg(argList[args], XtNpai, &ThePostAmbleInfo); args++; XtSetArg(argList[args], XtNdviFonts, TheFontInfo); args++; XtSetArg(argList[args], XtNdpi, TeXxResources.dpi ); args++; XtSetArg(argList[args], XtNpaperWidth, TeXxResources.paperWidthString ); args++; XtSetArg(argList[args], XtNpaperHeight, TeXxResources.paperHeightString ); args++; XtSetArg(argList[args], XtNpage, tp -> pageData); args++; XtSetArg(argList[args], XtNuserMag, tp -> userMag); args++; XtSetArg(argList[args], XtNxFonts, TeXFontRef(tp -> userMag)); args++; tp -> singleDviPage = XtCreateWidget("DviPage", dviPageWidgetClass, tp -> viewPort, argList, args); XtAddCallback( tp -> singleDviPage, XtNdestroyCallback, dviPageDied, tp); /* get the size of the dvi page. This is an attempt to provide a nice default window size */ args = 0; XtSetArg(argList[args], XtNwidth, &dviWd); args++; XtSetArg(argList[args], XtNheight, &dviHt); args++; XtGetValues( tp -> singleDviPage, argList, args); if ( dviWd < maxWd ){ maxWd = dviWd; } if ( dviHt < maxHt ) { maxHt = dviHt; } args = 0; XtSetArg(argList[args], XtNwidth, maxWd); args++; XtSetArg(argList[args], XtNheight, maxHt); args++; XtSetValues( tp -> viewPort, argList, args); /* Now manage the viewport & single page */ XtManageChild( tp -> singleDviPage ); XtManageChild( tp -> viewPort ); XtRealizeWidget(tp -> popUpPage); /* did we need scrollbars? */ if ( dviWd <= maxWd ){ maxWd = dviWd; if ( dviHt > maxHt ) { ViewportWidget vp = (ViewportWidget) (tp -> viewPort); maxWd = maxWd + vp -> viewport.vert_bar -> core.width + vp -> viewport.vert_bar -> core.border_width; } } if ( dviHt <= maxHt ) { maxHt = dviHt; if ( dviWd > maxWd ) { ViewportWidget vp = (ViewportWidget) (tp -> viewPort); maxHt = maxHt + vp -> viewport.horiz_bar -> core.width + vp -> viewport.horiz_bar -> core.border_width; } } args = 0; XtSetArg(argList[args], XtNwidth, maxWd); args++; XtSetArg(argList[args], XtNheight, maxHt); args++; XtSetValues( tp -> viewPort, argList, args); /* some bug somewhere makes the first page not appear unless I reset page */ args = 0; XtSetArg(argList[args], XtNpage, tp -> pageData); args++; XtSetValues(tp -> singleDviPage, argList, args); showPage( tp, False ); /* set remaining buttons */ XtPopup( tp -> popUpPage, XtGrabNone); } void TeXPageBuild() { int i; TeXPage *tp = TeXPageLocate(); if ( ! tp -> realized ) { TeXPageRealize(tp, 0); } }