home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / s / stex2-18.zip / SeeTeX / Xtex / page.c < prev    next >
C/C++ Source or Header  |  1992-05-04  |  39KB  |  1,639 lines

  1. /*
  2.  * Copyright 1989 Dirk Grunwald
  3.  * 
  4.  * Permission to use, copy, modify, distribute, and sell this software
  5.  * and its documentation for any purpose is hereby granted without fee,
  6.  * provided that the above copyright notice appear in all copies and that
  7.  * both that copyright notice and this permission notice appear in
  8.  * supporting documentation, and that the name of Dirk Grunwald or M.I.T.
  9.  * not be used in advertising or publicity pertaining to distribution of
  10.  * the software without specific, written prior permission.  Dirk
  11.  * Grunwald and M.I.T. makes no representations about the suitability of
  12.  * this software for any purpose.  It is provided "as is" without express
  13.  * or implied warranty.
  14.  * 
  15.  * DIRK GRUNWALD AND M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  16.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17.  * FITNESS, IN NO EVENT SHALL M.I.T.  BE LIABLE FOR ANY SPECIAL, INDIRECT
  18.  * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  19.  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  20.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  21.  * OR PERFORMANCE OF THIS SOFTWARE.
  22.  * 
  23.  * Author:
  24.  *     Dr. Dirk Grunwald
  25.  *     Dept. of Computer Science
  26.  *     Campus Box 430
  27.  *     Univ. of Colorado, Boulder
  28.  *     Boulder, CO 80309
  29.  * 
  30.  *     grunwald@colorado.edu
  31.  *     
  32.  */ 
  33.  
  34. /*
  35.  *
  36.  *    This looks kind of strange because, initially, I had intended to
  37.  *    allow you to `put away' a page without destroying it -- but
  38.  *    I've decided not to do that.
  39.  *
  40.  */
  41.  
  42. #include <stdio.h>
  43. #include <X11/IntrinsicP.h>
  44. #include <X11/Xatom.h>
  45. #include <X11/Object.h>
  46. #include <X11/ObjectP.h>
  47.  
  48. #include <assert.h>
  49.  
  50. #include "dvi-simple.h"
  51.  
  52. #include "xtex.h"
  53.  
  54. #include "DviPage.h"
  55. #include "page.h"
  56. #include "x11fonts.h"
  57. #include "widgets.h"
  58.  
  59. #include "Valuator.h"
  60. #include "EzMenu.h"
  61.  
  62.  
  63. extern Widget TopLevelWidget;
  64.  
  65. #ifdef __STDC__
  66. void TeXPageRealize(TeXPage *, int);
  67. static void showPage(TeXPage *, int);
  68. static void changeMag(TeXPage *, int );
  69. #else
  70. void TeXPageRealize();
  71. static void showPage();
  72. static void changeMag();
  73. #endif
  74.  
  75. int TeXPages;
  76. TeXPage *TheTeXPages[ MAX_TEX_PAGES ];
  77.  
  78. typedef struct {
  79.   char *thePage;
  80.   int refs;
  81. } DviPageRef;
  82.  
  83. DviPageRef *ThePageRefs = 0;
  84.  
  85. #define BUTTONS (xtexResources.useButtons)
  86.  
  87.  
  88. /*
  89.  * free all items in the page stack of a given TeXPage
  90.  */
  91.  
  92. void
  93. TeXPageStackFree(tp)
  94. TeXPage *tp;
  95. {
  96.   while ( tp -> pageStack ) {
  97.     TeXPageStack *p = tp -> pageStack;
  98.     tp -> pageStack = p -> next;
  99.     XtFree( (char *) p );
  100.   }
  101. }
  102.  
  103. void
  104.   TeXPageCloseFile()
  105. {
  106.   int popup;
  107.   
  108.   /* dispose of existing information */
  109.   
  110.   for ( popup = 0; popup < TeXPages; popup++ ) {
  111.     TeXPage *tp = TheTeXPages[popup];
  112.     if ( IS_VALID_PAGE(tp) ) {
  113.       TeXPageDeref( tp );
  114.       TeXFontUnref( tp -> userMag);
  115.       TeXPageStackFree( tp );
  116.       tp -> pageData = 0;
  117.     }
  118.   }
  119.   
  120.   if ( ThePageRefs ) {
  121.     int i;
  122.     for (i = 0; i < DviTotalPages; i++ ) {
  123.       XtFree( ThePageRefs[i].thePage );
  124.       ThePageRefs[ i ].thePage = 0;
  125.     }
  126.   }
  127.   
  128.   XtFree( (char *) ThePageRefs );
  129.   
  130.   ThePageRefs = 0;
  131. }
  132.  
  133. void
  134.   TeXPageSlamPages()
  135. {
  136.   int popup;
  137.   
  138.   /* take down pages, dispose of existing information */
  139.   
  140.   for ( popup = 0; popup < TeXPages; popup++ ) {
  141.     if ( IS_VALID_PAGE(TheTeXPages[popup]) ) {
  142.       XtDestroyWidget( TheTeXPages[ popup ] -> popUpPage ); 
  143.     }
  144.   }
  145. }
  146.  
  147. /*
  148.  *    find the logial page `want'. If we want the next logical page
  149.  *    with that number, set wantNext to True, else False (you can
  150.  *    have multiple logical pages with the same number).
  151.  */
  152. static void findLogicalPage(wantNext, tp, want)
  153.      Bool wantNext;
  154.      TeXPage *tp;
  155.      int want;
  156. {
  157.   int here = tp -> pageNumber;
  158.   int page = here;
  159.   
  160.   if ( here < 0 || here >= DviTotalPages ) {
  161.     here = 0;
  162.   }
  163.   
  164.   if (wantNext) {
  165.     page++;
  166.     if ( page >= DviTotalPages ) {
  167.       page = 0;
  168.     }
  169.   }
  170.   
  171.   for(;;) {
  172.     if ( DviCount[0][page] == want ) {
  173.       tp -> pageNumber = page;
  174.       tp -> logicalPageNumber = want;
  175.       return;
  176.     }
  177.     page++;
  178.     if ( page >= DviTotalPages ) {
  179.       page = 0;
  180.     }
  181.     if ( page == here ) 
  182.       break;
  183.   }
  184.   if ( here < 0 || here >= DviTotalPages ) {
  185.     here = 0;
  186.   }
  187.   tp -> pageNumber = here;
  188.   tp -> logicalPageNumber = DviCount[0][here];
  189. }
  190.  
  191. void
  192.   TeXPageOpenFile()
  193. {
  194.   /* now rebuild it all */
  195.   
  196.   if ( DviFile != 0 ) {
  197.     int i;
  198.     int popup;
  199.     
  200.     ThePageRefs =
  201.       (DviPageRef *)  XtMalloc( (DviTotalPages+1) * sizeof(DviPageRef) );
  202.     
  203.     for (i = 0; i < DviTotalPages; i++ ) {
  204.       ThePageRefs[i].thePage = 0;
  205.       ThePageRefs[i].refs = 0;
  206.     }
  207.     
  208.     /* Scan existing pages, orient new pages based on the count0 field
  209.        of the old page. This field is cached in logicalPageNumber */
  210.     
  211.     for ( popup = 0; popup < TeXPages; popup++ ) {
  212.       
  213.       TeXPage *tp = TheTeXPages[ popup ];
  214.       
  215.       if ( IS_VALID_PAGE(tp) ) {
  216.     int pno;
  217.     findLogicalPage(False, tp, tp -> logicalPageNumber);
  218.     pno = tp -> pageNumber;
  219.     
  220.     if (pno >= 0 && pno < DviTotalPages) {
  221.       Arg argList[20];
  222.       int args = 0;
  223.       
  224.       TeXPageRef(tp, tp -> pageNumber);
  225.       
  226.       XtSetArg(argList[args], XtNredisplay, True); args++;
  227.       XtSetArg(argList[args], XtNpai, &ThePostAmbleInfo); args++;
  228.       XtSetArg(argList[args], XtNpage, tp -> pageData); args++;
  229.       XtSetArg(argList[args], XtNdviFonts, TheFontInfo); args++;
  230.       XtSetArg(argList[args], XtNxFonts,
  231.            TeXFontRef(tp -> userMag)); args++;
  232.       
  233.       XtSetValues( tp -> singleDviPage, argList, args);
  234.       
  235.       showPage( tp, False );
  236.     }
  237.     else {
  238.       XtDestroyWidget( tp -> popUpPage ); 
  239.     }
  240.       }
  241.     }
  242.   }
  243. }
  244.  
  245. /*
  246.  *    Reference and dereference a page structure -- these keep track
  247.  *    of the memory allocated for page buffers & disposes of them
  248.  *    when not in use.
  249.  */
  250.  
  251. void
  252.   TeXPageRef(tp, pageno)
  253. TeXPage *tp;
  254. int pageno;
  255. {
  256.   assert( pageno >= 0 && pageno < DviTotalPages );
  257.   
  258.   ThePageRefs[ pageno ].refs++;
  259.   if ( ThePageRefs[ pageno ].thePage == 0 ) {
  260.     ThePageRefs[ pageno ].thePage = DviFetchPage( pageno );
  261.   }
  262.   
  263.   tp -> pageNumber = pageno;
  264.   tp -> logicalPageNumber = DviCount[0][ pageno ];
  265.   tp -> pageData = ThePageRefs[ pageno ].thePage;
  266. }
  267.  
  268. void
  269.   TeXPageDeref(tp)
  270. TeXPage *tp;
  271. {
  272.   int pageno = tp -> pageNumber;
  273.   
  274.   assert( pageno >= 0 && pageno < DviTotalPages );
  275.   if ( ThePageRefs && ThePageRefs[ pageno ].refs > 0) {
  276.     ThePageRefs[ pageno ].refs--;
  277.     if ( ThePageRefs[ pageno ].refs <= 0 ) {
  278.       XtFree( ThePageRefs[ pageno ].thePage );
  279.       ThePageRefs[ pageno ].thePage = 0;
  280.     }
  281.   }
  282. }
  283.  
  284.  
  285. /*
  286.  *    Locate page containing widget *w*
  287.  */
  288. #ifdef __STDC__
  289. TeXPage *
  290.   TeXPageLocate(Widget w)
  291. #else
  292. TeXPage *
  293.   TeXPageLocate(w) Widget w;
  294. #endif
  295. {
  296.   if ( w ) {
  297.     
  298. #define IS(x) (w == tp -> x)
  299.     int i;
  300.     Widget parent;
  301.     
  302.     for (i = 0; i < TeXPages; i++ ) {
  303.       TeXPage *tp = TheTeXPages[i];
  304.       if ( IS(singleDviPage)
  305.       || IS(popUpPage)
  306.       || IS(dviPageBox)
  307.       || IS( dviPageMenu )
  308.       || IS(viewPort)
  309.       || IS(buttonBox)
  310.       || IS(forewardButton)
  311.       || IS(backwardButton)
  312.       || IS(markButton)
  313.       || IS(dupButton)
  314.       || IS(dupButton)
  315.       || IS(tieButton)
  316.       || IS(largeButton)
  317.       || IS(smallButton)
  318.       || IS(quitButton)
  319.       || IS(pageNumberText)
  320.       || IS(gotoButton)
  321.       || IS(reopenButton) ) {
  322.     return( tp );
  323.       }
  324. #undef IS
  325.     }
  326.     
  327.     /* didn't find it -- attempt to find the parent and try again */
  328.     
  329.     parent = 0;
  330.     if ( XtIsWidget(w) )  {
  331.       parent = XtParent(w);
  332.     }
  333.     else if ( XtIsObject(w) ) {
  334.       Object o = (Object) w;
  335.       parent = o -> object.parent;
  336.     }
  337.     
  338.     if ( parent ) {
  339.       return( TeXPageLocate( parent ) );
  340.     }
  341.   }
  342.   
  343.   return( 0 );
  344. }
  345.  
  346. /*
  347.  *    Locate a free TeXPage structure. See comment at head.
  348.  */
  349. TeXPage *
  350.   TeXPageLocateFree()
  351. {
  352.   int i;
  353.   TeXPage *tp;
  354.   
  355.   for (i = 0; i < TeXPages; i++ ) {
  356.     if ( ! TheTeXPages[ i ] -> active ) {
  357.       return( TheTeXPages[ i ] );
  358.     }
  359.   }
  360.   
  361.   tp = (TeXPage *) XtMalloc(sizeof(TeXPage));
  362.   
  363.   bzero( tp, sizeof(TeXPage) );    /* happily, sets all to default */
  364.   
  365.   /* install the page in the page list */
  366.   
  367.   if ( TeXPages > MAX_TEX_PAGES ) {
  368.     error(0,0,"No more pages available");
  369.     return(0);
  370.   }
  371.   
  372.   TheTeXPages[ TeXPages++ ] = tp;
  373.   
  374.   return( tp );
  375. }
  376.  
  377. /*
  378.  *    The callback when pages die.
  379.  */
  380.  
  381. static void
  382.   dviPageDied(w, clientData,  callData)
  383. Widget w;
  384. caddr_t clientData;    /* unused */
  385. caddr_t callData; /* unused */
  386. {
  387.   TeXPage *tp = (TeXPage*) clientData;
  388.   
  389.   if ( tp != 0 ){
  390.     tp -> active = False;
  391.     tp -> realized = False;
  392.     TeXPageDeref( tp );
  393.     TeXFontUnref( tp -> userMag);
  394.     TeXPageStackFree( tp );
  395.     tp -> popUpPage = 0;
  396.     
  397.     if ( tp -> tiedTo != 0 && tp -> tiedTo -> active ) {
  398.       tp -> tiedTo -> tied = 0;
  399.     }
  400.     
  401.     if ( tp -> tied != 0 && tp -> tied -> active ) {
  402.       tp -> tied -> tiedTo = 0;
  403.     }
  404.     
  405.     tp -> tiedTo = 0;
  406.     tp -> tied = 0;
  407.     
  408.     tp -> inputNumberValid = False;
  409.     
  410.   }
  411. }
  412.  
  413. /* if accelerators haven't been installed yet, so so */
  414.  
  415. static void enableScrollBars(tp)
  416.      TeXPage *tp;
  417. {
  418.   if ( ! tp -> horizBar ) {
  419.     tp -> horizBar = XtNameToWidget(tp -> viewPort, "horizontal");
  420.     if ( tp -> horizBar && ! tp -> horizInit ) {
  421.       XtInstallAccelerators(tp -> singleDviPage, tp -> horizBar);
  422.       tp -> horizInit == TRUE;
  423.     }
  424.   }
  425.   
  426.   if ( ! tp -> vertBar ) {
  427.     tp -> vertBar = XtNameToWidget(tp -> viewPort, "vertical");
  428.     if ( tp -> vertBar && !tp -> vertInit ) {
  429.       XtInstallAccelerators(tp -> singleDviPage, tp -> vertBar);
  430.       tp -> vertInit == TRUE;
  431.     }
  432.   }
  433. }
  434.  
  435. /*
  436.  *    Set all the buttons for this page, possibly also
  437.  *    sending the page information
  438.  */
  439.  
  440. static   Arg sensArgs[] = {
  441.   {XtNsensitive, (XtArgVal) True}
  442. };
  443.  
  444. static   Arg insensArgs[] = {
  445.   {XtNsensitive, (XtArgVal) False}
  446. };
  447.  
  448. static void showPage(tp, displayPage)
  449.      TeXPage *tp;
  450.      Bool displayPage;
  451. {
  452.   Arg argList[20];
  453.   Cardinal args;
  454.   
  455.   Pixel fore;
  456.   Pixel back;
  457.   
  458.   if ( displayPage ) {
  459.     
  460. #if 0
  461.     args = 0;
  462.     XtSetArg(argList[args], XtNresizable, False); args++;
  463.     XtSetValues( tp -> viewPort, argList, args);
  464. #endif
  465.     
  466.     TeXPageRef(tp,  tp -> pageNumber );
  467.     args = 0;
  468.     XtSetArg(argList[args], XtNpage, tp -> pageData); args++;
  469.     XtSetArg(argList[args], XtNredisplay, True); args++;
  470.     XtSetValues(tp -> singleDviPage, argList, args);
  471.     
  472. #if 0
  473.     args = 0;
  474.     XtSetArg(argList[args], XtNresizable, True); args++;
  475.     XtSetValues( tp -> viewPort, argList, args);
  476. #endif
  477.     
  478.   }
  479.   
  480.   if ( xtexResources.updateNames ) {
  481.     char spbuffer[1024];
  482.     
  483.     /* physical pages are zero based internally, one based externally */
  484.     
  485.     sprintf(spbuffer,"%s (%s): Logical Page %d, Physical Page %d",
  486.         ProgName, DVIFileName,
  487.         DviCount[0][tp -> pageNumber],
  488.         tp -> pageNumber + 1);
  489.     
  490.     XChangeProperty(XtDisplay(tp -> popUpPage),
  491.             XtWindow(tp -> popUpPage),
  492.             XA_WM_NAME, XA_STRING, 8, PropModeReplace,
  493.             (unsigned char*) spbuffer, strlen(spbuffer));
  494.     
  495.     sprintf(spbuffer,"%s (%s, page %d)",
  496.         ProgName, DVIFileName, DviCount[0][tp -> pageNumber]);
  497.     
  498.     XChangeProperty(XtDisplay(tp -> popUpPage),
  499.             XtWindow(tp -> popUpPage),
  500.             XA_WM_ICON_NAME, XA_STRING, 8, PropModeReplace,
  501.             (unsigned char*) spbuffer, strlen(spbuffer));
  502.   }
  503.   
  504.   if ( BUTTONS ) {
  505.     if ( tp -> pageNumber == 0 ) {
  506.       XtSetValues( tp -> backwardButton, insensArgs, XtNumber(insensArgs));
  507.     }
  508.     else {
  509.       XtSetValues( tp -> backwardButton, sensArgs, XtNumber(sensArgs));
  510.     }
  511.     
  512.     if ( tp -> pageNumber >= (DviTotalPages-1)) {
  513.       XtSetValues( tp -> forewardButton, insensArgs, XtNumber(insensArgs));
  514.     }
  515.     else {
  516.       XtSetValues( tp -> forewardButton, sensArgs, XtNumber(sensArgs));
  517.     }
  518.     
  519.     /* Take normal values from another button */
  520.     
  521.     args = 0;
  522.     XtSetArg(argList[args], XtNforeground, &fore); args++;
  523.     XtSetArg(argList[args], XtNbackground, &back); args++;
  524.     XtGetValues( tp -> forewardButton, argList, args);
  525.     
  526.     if (TeXMarkState( tp -> pageNumber ) ) {
  527.       Arg argList[20];
  528.       Cardinal args;
  529.       
  530.       args = 0;
  531.       XtSetArg(argList[args], XtNforeground, back); args++;
  532.       XtSetArg(argList[args], XtNbackground, fore); args++;
  533.       
  534.       XtSetValues( tp -> markButton, argList, args );
  535.     }
  536.     else {
  537.       Arg argList[20];
  538.       Cardinal args;
  539.       
  540.       args = 0;
  541.       XtSetArg(argList[args], XtNforeground, fore); args++;
  542.       XtSetArg(argList[args], XtNbackground, back); args++;
  543.       
  544.       XtSetValues( tp -> markButton, argList, args );
  545.     }
  546.   }
  547.   
  548.   enableScrollBars(tp);
  549. }
  550.  
  551. static void changeMag( tp, mag )
  552.      TeXPage *tp;
  553.      int mag;
  554. {
  555.   Arg argList[20];
  556.   Cardinal args;
  557.   
  558.   XFontStruct **x;
  559.   Dimension maxHt;
  560.   Dimension maxWd;
  561.   Dimension dviHt;
  562.   Dimension dviWd;
  563.   Dimension dviBWd;
  564.   Dimension vpWd;
  565.   
  566.   maxWd = xtexResources.pageMaxWd;
  567.   maxHt = xtexResources.pageMaxHt;
  568.   if (maxWd < 1) {
  569.     maxWd = (int) ((WidthOfScreen(XtScreen(TopLevelWidget))) * 0.95);
  570.   }
  571.   if (maxHt < 1) {
  572.     maxHt = (int) ((HeightOfScreen(XtScreen(TopLevelWidget))) * 0.90);
  573.   }
  574.   
  575.   if ( ! xtexResources.autoSize ) {
  576.  
  577.     if ( tp -> userMag != mag ) {
  578.       /*
  579.        * Usually, you use the same fonts over and over. If you unref
  580.        * them first and then ref them, you'll unload them & then load
  581.        * them again. Major waste.
  582.        */
  583.       int oldMag = tp -> userMag;
  584.  
  585.       tp -> userMag = mag;
  586.       x = TeXFontRef(mag);
  587.       TeXFontUnref( oldMag );
  588.  
  589.       args = 0;
  590.       XtSetArg(argList[args], XtNuserMag, tp -> userMag); args++;
  591.       XtSetArg(argList[args], XtNxFonts, x); args++;
  592.       XtSetValues( tp -> singleDviPage, argList, args);
  593.     }
  594.     
  595.   } else {
  596.     
  597.     ViewportWidget vp = (ViewportWidget) (tp -> viewPort);
  598.     
  599.     if ( tp -> userMag != mag ) {
  600.       /*
  601.        * Usually, you use the same fonts over and over. If you unref
  602.        * them first and then ref them, you'll unload them & then load
  603.        * them again. Major waste.
  604.        */
  605.       int oldMag = tp -> userMag;
  606.  
  607.       tp -> userMag = mag;
  608.       x = TeXFontRef(mag);
  609.       TeXFontUnref( oldMag );
  610.       
  611.       XUnmapWindow( XtDisplay(tp -> viewPort), XtWindow(tp -> viewPort));
  612.       
  613.       args = 0;
  614.       XtSetArg(argList[args], XtNuserMag, tp -> userMag); args++;
  615.       XtSetArg(argList[args], XtNxFonts, x); args++;
  616.       XtSetValues( tp -> singleDviPage, argList, args);
  617.     } else {
  618.       XUnmapWindow( XtDisplay(tp -> viewPort), XtWindow(tp -> viewPort));
  619.     }
  620.     
  621.     if ( ! tp -> horizBar ) {
  622.       tp -> horizBar = XtNameToWidget((Widget) vp, "horizontal");
  623.       if ( tp -> horizBar ) {
  624.     XtInstallAccelerators(tp -> singleDviPage, tp -> horizBar);
  625.       }
  626.     }
  627.     
  628.     if ( ! tp -> vertBar ) {
  629.       tp -> vertBar = XtNameToWidget((Widget) vp, "vertical");
  630.       if (tp -> vertBar) {
  631.     XtInstallAccelerators(tp -> singleDviPage, tp -> vertBar);
  632.       }
  633.     }
  634.     
  635.     args = 0;
  636.     XtSetArg(argList[args], XtNwidth, &dviWd); args++;
  637.     XtSetArg(argList[args], XtNborderWidth, &dviBWd); args++;
  638.     XtSetArg(argList[args], XtNheight, &dviHt); args++;
  639.     XtGetValues( tp -> singleDviPage, argList, args);
  640.     
  641.     dviWd += (2 * dviBWd);
  642.     
  643.     if ( dviWd <= maxWd ){
  644.       maxWd = dviWd;
  645.       
  646.       /* will we need scrollbars? */
  647.       
  648.       if ( dviWd <= maxWd ){
  649.     Widget vb = tp -> vertBar;
  650.     maxWd = dviWd;
  651.     if ( vb && dviHt > maxHt ) {
  652.       maxWd = maxWd + vb -> core.width + vb -> core.border_width;
  653.     }
  654.       }
  655.       if ( dviHt <= maxHt ) {
  656.     Widget hb = tp -> horizBar;
  657.     maxHt = dviHt;
  658.     if ( hb && dviWd > maxWd ) {
  659.       maxHt = maxHt + hb -> core.width + hb -> core.border_width;
  660.     }
  661.       }
  662.     }
  663.     
  664.     args = 0;
  665.     XtSetArg(argList[args], XtNwidth, maxWd); args++;
  666.     XtSetArg(argList[args], XtNheight, maxHt); args++;
  667.     XtSetValues( tp -> viewPort, argList, args);
  668.     
  669.     if ( XtIsRealized( tp -> viewPort ) ) {
  670.       XMapWindow( XtDisplay(tp -> viewPort), XtWindow(tp -> viewPort));
  671.     }
  672.   }
  673. }
  674.  
  675. /**************** NUMBER FETCHING ****************/
  676. static int texxPageNumber(tp, def)
  677.      TeXPage *tp;
  678.      int def;
  679. {
  680.   int value;
  681.   if ( tp  && tp -> inputNumberValid ) {
  682.     
  683.     if ( tp -> inputNumberMinus ) {
  684.       value = -( tp -> inputNumber);
  685.     }
  686.     else {
  687.       value = ( tp -> inputNumber );
  688.     }
  689.   }
  690.   else {
  691.     value = def;
  692.   }
  693.   return(value);
  694. }
  695.  
  696. static void texxPageNumberReset(tp)
  697.      TeXPage *tp;
  698. {
  699.   if ( IS_VALID_PAGE(tp) ) {
  700.     tp -> inputNumberValid = False;
  701.     tp -> inputNumberMinus = False;
  702.     tp -> inputNumber = 0;
  703.   }
  704. }
  705.  
  706. /*
  707.  *    Realize the TeXPage structure and pop up the corresponding window
  708.  */
  709. void TeXPageRealize(tp, pageNumber)
  710.      TeXPage *tp;
  711.      int pageNumber;
  712. {
  713.   Arg argList[40];
  714.   int args;
  715.   
  716.   Dimension maxHt;
  717.   Dimension maxWd;
  718.   Dimension dviHt;
  719.   Dimension dviWd;
  720.   extern pushReopenButton();    /* from file */
  721.   Widget scrollBar;
  722.   
  723.   bzero(tp, sizeof(TeXPage));
  724.   
  725.   maxWd = xtexResources.pageMaxWd;
  726.   maxHt = xtexResources.pageMaxHt;
  727.   if (maxWd < 1) {
  728.     maxWd = (int) ((WidthOfScreen(XtScreen(TopLevelWidget))) * 0.95);
  729.   }
  730.   if (maxHt < 1) {
  731.     maxHt = (int) ((HeightOfScreen(XtScreen(TopLevelWidget))) * 0.90);
  732.   }
  733.   
  734.   if ( tp == NULL ) {
  735.     return;
  736.   }
  737.   
  738.   assert(TopLevelWidget != 0);
  739.   
  740.   args = 0;
  741.   tp -> popUpPage = 
  742.     XtCreatePopupShell("xtex-page",
  743.                applicationShellWidgetClass, TopLevelWidget,
  744.                argList,args);
  745.   
  746.   args = 0;
  747.   tp -> dviPageBox =
  748.     XtCreateManagedWidget("form",
  749.               formWidgetClass, tp -> popUpPage,
  750.               argList, args);
  751.   
  752.   if ( BUTTONS ) {
  753.     args = 0;
  754.     XtSetArg(argList[args], XtNleft, XtChainLeft); args++;
  755.     tp -> quitButton =
  756.       XtCreateManagedWidget("quitButton",
  757.                 commandWidgetClass, tp -> dviPageBox,
  758.                 argList, args);
  759.     
  760.     args = 0;
  761.     XtSetArg(argList[args], XtNfromHoriz, tp -> quitButton); args++;
  762.     tp -> forewardButton =
  763.       XtCreateManagedWidget("forwardButton",
  764.                 commandWidgetClass, tp -> dviPageBox,
  765.                 argList, args);
  766.     args = 0;
  767.     XtSetArg(argList[args], XtNfromHoriz, tp -> forewardButton); args++;
  768.     tp -> backwardButton =
  769.       XtCreateManagedWidget("backwardButton",
  770.                 commandWidgetClass, tp -> dviPageBox,
  771.                 argList, args);
  772.     args = 0;
  773.     XtSetArg(argList[args], XtNfromHoriz, tp -> backwardButton); args++;
  774.     tp -> markButton =
  775.       XtCreateManagedWidget("markButton",
  776.                 commandWidgetClass, tp -> dviPageBox,
  777.                 argList, args);
  778.     
  779.     args = 0;
  780.     XtSetArg(argList[args], XtNfromHoriz, tp -> markButton); args++;
  781.     tp -> dupButton =
  782.       XtCreateManagedWidget("dupButton",
  783.                 commandWidgetClass, tp -> dviPageBox,
  784.                 argList, args);
  785.     
  786.     args = 0;
  787.     XtSetArg(argList[args], XtNfromHoriz, tp -> dupButton); args++;
  788.     tp -> tieButton =
  789.       XtCreateManagedWidget("tieButton",
  790.                 commandWidgetClass, tp -> dviPageBox,
  791.                 argList, args);
  792.     
  793.     args = 0;
  794.     XtSetArg(argList[args], XtNfromHoriz, tp -> tieButton); args++;
  795.     tp -> largeButton =
  796.       XtCreateManagedWidget("largeButton",
  797.                 commandWidgetClass, tp -> dviPageBox,
  798.                 argList, args);
  799.     
  800.     args = 0;
  801.     XtSetArg(argList[args], XtNfromHoriz, tp -> largeButton); args++;
  802.     tp -> smallButton =
  803.       XtCreateManagedWidget("smallButton",
  804.                 commandWidgetClass, tp -> dviPageBox,
  805.                 argList, args);
  806.     args = 0;
  807.     XtSetArg(argList[args], XtNfromHoriz, tp -> smallButton); args++;
  808.     tp -> reopenButton = 
  809.       XtCreateManagedWidget("reopenButton",
  810.                 commandWidgetClass, tp -> dviPageBox,
  811.                 argList, args);
  812.     args = 0;
  813.     XtSetArg(argList[args], XtNfromHoriz, tp -> reopenButton); args++;
  814.     XtSetArg(argList[args], XtNeditType, XawtextEdit); args++;
  815.     XtSetArg(argList[args], XtNstring, tp -> pageNumberBuffer); args++;
  816.     XtSetArg(argList[args], XtNlength, MAXPAGENUMBERBUFFER); args++;
  817.     tp -> pageNumberText =
  818.       XtCreateManagedWidget("numberText",
  819.                 asciiTextWidgetClass, tp -> dviPageBox,
  820.                 argList, args);
  821.     
  822.     args = 0;
  823.     XtSetArg(argList[args], XtNfromHoriz, tp -> pageNumberText); args++;
  824.     tp -> gotoButton = 
  825.       XtCreateManagedWidget("gotoButton",
  826.                 commandWidgetClass, tp -> dviPageBox,
  827.                 argList, args);
  828.   }
  829.   
  830.   args = 0;
  831.   if (BUTTONS) {
  832.     XtSetArg(argList[args], XtNfromVert, tp -> pageNumberText); args++;
  833.   }
  834.   tp -> viewPort = 
  835.     XtCreateWidget("viewPort",
  836.            viewportWidgetClass, tp -> dviPageBox,
  837.            argList, args);
  838.   
  839.   bzero(tp -> pageNumberBuffer, MAXPAGENUMBERBUFFER);
  840.   tp -> realized = True;
  841.   TeXPageRef(tp, pageNumber);
  842.   tp -> userMag = xtexResources.userMag;
  843.   tp -> active = True;
  844.   
  845.   args = 0;
  846.   XtSetArg(argList[args], XtNpai, &ThePostAmbleInfo); args++;
  847.   
  848.   XtSetArg(argList[args], XtNdviFonts, TheFontInfo); args++;
  849.   
  850.   {
  851.     IntFloatUnion x;
  852.  
  853.     x.f = xtexResources.dpiHoriz;
  854.     XtSetArg(argList[args], XtNdpiHoriz, x.i); args++;
  855.  
  856.     x.f = xtexResources.dpiVert;
  857.     XtSetArg(argList[args], XtNdpiVert, x.i); args++;
  858.  
  859.     x.f = xtexResources.paperWidth;
  860.     XtSetArg(argList[args], XtNpaperWidth, x.i); args++;
  861.  
  862.     x.f = xtexResources.paperHeight;
  863.     XtSetArg(argList[args], XtNpaperHeight, x.i); args++;
  864.  
  865.     x.f = xtexResources.topOffset;
  866.     XtSetArg(argList[args], XtNtopOffset, x.i); args++;
  867.  
  868.     x.f = xtexResources.leftOffset;
  869.     XtSetArg(argList[args], XtNleftOffset, x.i); args++;
  870.   }
  871.   
  872.   XtSetArg(argList[args], XtNpage, tp -> pageData); args++;
  873.   XtSetArg(argList[args], XtNuserMag, tp -> userMag); args++;
  874.   XtSetArg(argList[args], XtNxFonts, TeXFontRef(tp -> userMag)); args++;
  875.   
  876.   tp -> singleDviPage = 
  877.     XtCreateWidget("dviPage",
  878.            dviPageWidgetClass, tp -> viewPort,
  879.            argList, args);
  880.   
  881.   XtAddCallback( tp -> singleDviPage, XtNdestroyCallback, dviPageDied, tp);
  882.   
  883.   tp -> dviPageMenu = XtCreatePopupShell("menu",
  884.                      ezMenuWidgetClass,
  885.                      tp -> singleDviPage,
  886.                      NULL, 0);
  887.   
  888.   /* get the size of the dvi page. This is an attempt to provide
  889.      a nice default window size */
  890.   
  891.   /* sadly, this appears to be impossible to keep unless we redisplay
  892.      several times each time, so lets just blow it off */
  893.   
  894. #if 0
  895.   args = 0;
  896.   XtSetArg(argList[args], XtNwidth, &dviWd); args++;
  897.   XtSetArg(argList[args], XtNheight, &dviHt); args++;
  898.   XtGetValues( tp -> singleDviPage, argList, args);
  899.   
  900.   scrollBar = XtNameToWidget( tp -> viewPort, "vertical");
  901.   if ( ! scrollBar ) {
  902.     scrollBar = XtNameToWidget( tp -> viewPort, "horizontial");
  903.   }
  904.   
  905.   if ( scrollBar ) {
  906.     Dimension sWd;
  907.     Dimension sHt;
  908.     
  909.     args = 0;
  910.     XtSetArg(argList[args], XtNwidth, &sWd); args++;
  911.     XtSetArg(argList[args], XtNheight, &sHt); args++;
  912.     XtGetValues( scrollBar, argList, args);
  913.     
  914.     dviWd += sWd;
  915.     dviHt += sHt;
  916.   }
  917.   
  918.   if ( dviWd <= maxWd ){
  919.     maxWd = dviWd;
  920.   }
  921.   if ( dviHt <= maxHt ) {
  922.     maxHt = dviHt;
  923.   }
  924.   args = 0;
  925.   XtSetArg(argList[args], XtNwidth, maxWd); args++;
  926.   XtSetArg(argList[args], XtNheight, maxHt); args++;
  927.   XtSetValues( tp -> viewPort, argList, args);
  928. #endif
  929.   
  930.   /* Now manage the viewport & single page */
  931.   XtManageChild( tp -> singleDviPage );
  932.   XtManageChild( tp -> viewPort );
  933.   
  934.   XtRealizeWidget(tp -> popUpPage);
  935.   
  936.   /* some bug somewhere makes the first page not appear unless I reset page */
  937.   args = 0;
  938.   XtSetArg(argList[args], XtNpage, tp -> pageData); args++;
  939.   XtSetValues(tp -> singleDviPage, argList, args);
  940.   
  941.   showPage( tp, False );    /* set remaining buttons */
  942.   
  943.   changeMag( tp, tp -> userMag );
  944.   
  945.   XtPopup( tp -> popUpPage, XtGrabNone);
  946.   
  947.   enableScrollBars(tp);
  948.   
  949. }
  950.  
  951. void TeXPageBuild()
  952. {
  953.   int i;
  954.   
  955.   TeXPage *tp = TeXPageLocateFree();
  956.   
  957.   if ( ! tp -> realized  ) {
  958.     TeXPageRealize(tp, 0);
  959.   }
  960. }
  961.  
  962. /*************** ACTIONS ***************/
  963.  
  964. static int getActionPageNumber(tp, params, num_params)
  965.      TeXPage *tp;
  966.      String *params;
  967.      Cardinal *num_params;
  968. {
  969.   int want;
  970.  
  971.   if ( *num_params == 1 ) {
  972.     if ( tp && strcmp(params[0], "box") == 0) {
  973.       
  974.       if ( ! tp -> pageNumberText ) {
  975.  
  976.     /* do nothing if box doesn't exist... */
  977.  
  978.     want = tp -> logicalPageNumber;
  979.       }
  980.       else {
  981.     Arg argList[2];
  982.     int args = 0;
  983.     char *currentString;
  984.     
  985.     XtSetArg(argList[args], XtNstring, ¤tString); args++;
  986.     XtGetValues(tp -> pageNumberText, argList, args);
  987.     
  988.     want = atoi( currentString );
  989.       }
  990.     }
  991.     else {
  992.       want = atoi( params[0] );
  993.     }
  994.   }
  995.   else {
  996.     int bogus = -99999;
  997.     want = texxPageNumber(tp,bogus);
  998.   }
  999.  
  1000.   return( want );
  1001.  
  1002. }
  1003.  
  1004. static void actionRealize(w, event, params, num_params)
  1005.      Widget w;
  1006.      XEvent *event;
  1007.      String *params;
  1008.      Cardinal *num_params;
  1009. {
  1010.   TeXPage *tp = TeXPageLocate(w);
  1011.   int want = getActionPageNumber( tp, params, num_params ); 
  1012.   TeXPage *newtp = TeXPageLocateFree();
  1013.  
  1014.   if ( ! newtp -> realized  ) {
  1015.     TeXPageRealize(newtp, want);
  1016.   }
  1017.  
  1018. static void actionQuit(w, event, params, num_params)
  1019.      Widget w;
  1020.      XEvent *event;
  1021.      String *params;
  1022.      Cardinal *num_params;
  1023. {
  1024.   TeXPage *tp = TeXPageLocate(w);
  1025.   if ( IS_VALID_PAGE(tp) ) {
  1026.     XtDestroyWidget( tp -> popUpPage);
  1027.   }
  1028.  
  1029. static void actionEcho(w, event, params, num_params)
  1030.      Widget w;
  1031.      XEvent *event;
  1032.      String *params;
  1033.      Cardinal *num_params;
  1034. {
  1035.   int totalLen;
  1036.   int i;
  1037.   char *echoCommand;
  1038.   
  1039.   totalLen = 0;
  1040.   for ( i = 1; i < *num_params; i++ ) {
  1041.     
  1042.     /* some error in the toolkit returns num_params==10 when I only have 2 */
  1043.     
  1044.     if ( params[i] ) {
  1045.       totalLen += strlen( params[i] );
  1046.     }
  1047.     else {
  1048.       break;
  1049.     }
  1050.   }
  1051.   
  1052.   totalLen += (*num_params = 10);
  1053.   
  1054.   echoCommand = (char *) XtMalloc( sizeof(char) * totalLen + 1);
  1055.   bzero(echoCommand, totalLen+1);
  1056.   
  1057.   for ( i = 0; i < *num_params; i++ ) {
  1058.     if ( params[i] ) {
  1059.       strncat(echoCommand, params[i], totalLen);
  1060.       strncat(echoCommand, " ", totalLen);
  1061.     }
  1062.     else {
  1063.       break;
  1064.     }
  1065.   }
  1066.   error(0,0, echoCommand );
  1067.   
  1068.   free( echoCommand );
  1069.  
  1070. static void actionForeward(w, event, params, num_params)
  1071.      Widget w;
  1072.      XEvent *event;
  1073.      String *params;
  1074.      Cardinal *num_params;
  1075. {
  1076.   TeXPage *tp = TeXPageLocate(w);
  1077.   if ( IS_VALID_PAGE(tp) ) {
  1078.     char *p;
  1079.     int increment = texxPageNumber(tp, 1);
  1080.     int nextPageNumber = tp -> pageNumber + increment;
  1081.  
  1082.     /* wants to go to a non-valid page? */
  1083.     
  1084.     if (tp -> pageNumber >= DviTotalPages || nextPageNumber >= DviTotalPages) {
  1085.       nextPageNumber = DviTotalPages-1;
  1086.     }
  1087.     else  if (nextPageNumber < 0) {
  1088.       nextPageNumber = 0;
  1089.     }
  1090.     
  1091.     if (tp -> pageData && nextPageNumber != tp -> pageNumber ) {
  1092.       if ( tp -> pageData )
  1093.     TeXPageDeref( tp );
  1094.  
  1095.       tp -> pageNumber = nextPageNumber;
  1096.       showPage(tp, True);
  1097.       
  1098.       if ( tp -> tied )
  1099.     actionForeward(tp -> tied -> popUpPage, 0, 0, 0);
  1100.     }
  1101.   }
  1102.  
  1103. static void actionBackward(w, event, params, num_params)
  1104.      Widget w;
  1105.      XEvent *event;
  1106.      String *params;
  1107.      Cardinal *num_params;
  1108. {
  1109.   TeXPage *tp = TeXPageLocate(w);
  1110.   if ( IS_VALID_PAGE(tp) ) {
  1111.     char *p;
  1112.     int increment = texxPageNumber(tp, 1);
  1113.     int nextPageNumber = tp -> pageNumber - increment;
  1114.     
  1115.     if ( tp -> tied ) {
  1116.       actionBackward( tp -> tied -> popUpPage, 0, 0, 0);
  1117.     }
  1118.     
  1119.     if ( tp -> pageNumber < 0 || nextPageNumber < 0 ) {
  1120.       nextPageNumber = 0;
  1121.     }
  1122.     else if (nextPageNumber >= DviTotalPages) {
  1123.       nextPageNumber = DviTotalPages - 1 ;
  1124.     }
  1125.     
  1126.     if ( tp -> pageData && nextPageNumber != tp -> pageNumber )  {
  1127.       TeXPageDeref( tp );
  1128.  
  1129.       tp -> pageNumber = nextPageNumber;
  1130.       showPage(tp, True);
  1131.     }
  1132.   }
  1133.  
  1134. static void actionDup(w, event, params, num_params)
  1135.      Widget w;
  1136.      XEvent *event;
  1137.      String *params;
  1138.      Cardinal *num_params;
  1139. {
  1140.   TeXPage *tp = TeXPageLocate(w);
  1141.   if ( IS_VALID_PAGE(tp) ) {
  1142.     TeXPage *newtp = TeXPageLocateFree();
  1143.     TeXPageRealize(newtp, tp -> pageNumber);
  1144.   }
  1145.  
  1146. static void actionTie(w, event, params, num_params)
  1147.      Widget w;
  1148.      XEvent *event;
  1149.      String *params;
  1150.      Cardinal *num_params;
  1151. {
  1152.   TeXPage *tp = TeXPageLocate(w);
  1153.   if ( tp && tp -> tied == 0 ) {
  1154.     TeXPage *newtp = TeXPageLocateFree();
  1155.     tp -> tied = newtp;
  1156.     newtp -> tiedTo = tp;
  1157.     TeXPageRealize(newtp, tp -> pageNumber);
  1158.   }
  1159.  
  1160. /*
  1161.  *    The goto button. This scans, starting at the current page number,
  1162.  *    until a value of ``DviCount[0]'' meets the goto destination.
  1163.  *    This allows us to hit the multiple ``page 1'' refs.
  1164.  *
  1165.  *    recall that we're going to the LOGICAL page specified. Thus, we
  1166.  *    must map the LOGICAL page number to a PHYSICAL page.
  1167.  *
  1168.  */
  1169. #define GOTO_KIND 0
  1170. #define PUSH_KIND 1
  1171.  
  1172. static void commonGoto(kind, w, event, params, num_params)
  1173.      int kind;
  1174.      Widget w;
  1175.      XEvent *event;
  1176.      String *params;
  1177.      Cardinal *num_params;
  1178. {
  1179.   TeXPage *tp = TeXPageLocate(w);
  1180.   if ( IS_VALID_PAGE(tp) ) {
  1181.     int was = tp -> pageNumber;
  1182.     int want = getActionPageNumber( tp, params, num_params );
  1183.  
  1184.     findLogicalPage(True, tp, want);
  1185.  
  1186.     if ( tp -> pageNumber != was ) {
  1187.  
  1188.       if ( kind == PUSH_KIND ) {
  1189.     TeXPageStack *item = (TeXPageStack *) XtMalloc( sizeof(TeXPageStack) );
  1190.     item -> physicalPageNumber = was;
  1191.     item -> next = tp -> pageStack;
  1192.     tp -> pageStack = item;
  1193.       }
  1194.  
  1195.       TeXPageDeref( tp );
  1196.       TeXPageRef(tp, tp -> pageNumber);
  1197.       showPage(tp, True);
  1198.     }
  1199.   }
  1200. }
  1201.  
  1202. static void actionGoto(w, event, params, num_params)
  1203.      Widget w;
  1204.      XEvent *event;
  1205.      String *params;
  1206.      Cardinal *num_params;
  1207. {
  1208.   commonGoto(GOTO_KIND, w, event, params, num_params);
  1209. }
  1210.  
  1211. static void actionPush(w, event, params, num_params)
  1212.      Widget w;
  1213.      XEvent *event;
  1214.      String *params;
  1215.      Cardinal *num_params;
  1216. {
  1217.   commonGoto(PUSH_KIND, w, event, params, num_params);
  1218. }
  1219.  
  1220. static void actionPop(w, event, params, num_params)
  1221.      Widget w;
  1222.      XEvent *event;
  1223.      String *params;
  1224.      Cardinal *num_params;
  1225. {
  1226.   TeXPage *tp = TeXPageLocate(w);
  1227.   if ( IS_VALID_PAGE(tp) ) {
  1228.     TeXPageStack *item;
  1229.     int toPop = getActionPageNumber(tp, params, num_params);
  1230.     int pageNumber = -1;
  1231.  
  1232.     if ( toPop < 1 ) {
  1233.       toPop = 1;
  1234.     }
  1235.     
  1236.     item = tp -> pageStack;
  1237.     while( item ) {
  1238.  
  1239.       tp -> pageStack = item -> next;
  1240.       pageNumber = item -> physicalPageNumber;
  1241.       XtFree( (char *) item );
  1242.       item = tp -> pageStack;
  1243.  
  1244.       toPop--;
  1245.       if ( toPop < 1) break;
  1246.     };
  1247.     
  1248.     if ( pageNumber > -1 ) {
  1249.       if ( pageNumber != tp -> pageNumber ) {
  1250.     TeXPageDeref( tp );
  1251.     TeXPageRef(tp, pageNumber);
  1252.       }
  1253.       showPage(tp, True);
  1254.     }
  1255.   }
  1256. }
  1257.  
  1258. static void actionDivert(w, event, params, num_params)
  1259.      Widget w;
  1260.      XEvent *event;
  1261.      String *params;
  1262.      Cardinal *num_params;
  1263. {
  1264.   if ( xtexResources.divertByPush ) {
  1265.     actionPush(w, event, params, num_params);
  1266.   } else {
  1267.     actionRealize(w, event, params, num_params);
  1268.   }
  1269. }
  1270.  
  1271. static void actionUnDivert(w, event, params, num_params)
  1272.      Widget w;
  1273.      XEvent *event;
  1274.      String *params;
  1275.      Cardinal *num_params;
  1276. {
  1277.   if ( xtexResources.divertByPush ) {
  1278.     actionPop(w, event, params, num_params);
  1279.   }
  1280. }
  1281.  
  1282. void actionRedisplay(w, event, params, num_params)
  1283.      Widget w;
  1284.      XEvent *event;
  1285.      String *params;
  1286.      Cardinal *num_params;
  1287. {
  1288.   TeXPage *tp = TeXPageLocate(w);
  1289.   if ( IS_VALID_PAGE(tp) ) {
  1290.     Arg argList[20];
  1291.     int args = 0;
  1292.  
  1293.     XtSetArg(argList[args], XtNredisplay, True); args++;
  1294.     XtSetValues( tp -> singleDviPage, argList, args);
  1295.   }
  1296. }
  1297.  
  1298. static Widget PopUpWidget;
  1299. static Widget GotoValuatorWidget;
  1300. static TeXPage *GotoTeXPage;
  1301.  
  1302. static void
  1303.   actionGotoPopupConfirm(w, event, params, num_params)
  1304. Widget w;
  1305. XEvent *event;
  1306. String *params;
  1307. Cardinal *num_params;
  1308. {
  1309.   float value;
  1310.   int want;
  1311.   Arg argList[20];
  1312.   int args = 0;
  1313.   
  1314.   TeXPage *tp = GotoTeXPage;
  1315.   
  1316.   args = 0;
  1317.   XtSetArg(argList[args], XtNvalue, &value); args++;
  1318.   XtGetValues(GotoValuatorWidget, argList, args );
  1319.   want = value - 1;
  1320.   if ( want < 0 ) want = 0;
  1321.   if ( want >= DviTotalPages ) want = DviTotalPages - 1;
  1322.   
  1323.   if ( want != tp -> pageNumber ) {
  1324.     TeXPageDeref(tp);
  1325.     TeXPageRef(tp, want);
  1326.     showPage(tp, True);
  1327.   }
  1328.   XtPopdown( PopUpWidget );
  1329. }
  1330.  
  1331. static void
  1332.   actionGotoPopupCancel(w, event, params, num_params)
  1333. Widget w;
  1334. XEvent *event;
  1335. String *params;
  1336. Cardinal *num_params;
  1337. {
  1338.   TeXPage *tp = TeXPageLocate(w);
  1339.   XtPopdown( PopUpWidget );
  1340. }
  1341.  
  1342. static void
  1343.   actionGotoPopup(w, event, params, num_params)
  1344. Widget w;
  1345. XEvent *event;
  1346. String *params;
  1347. Cardinal *num_params;
  1348. {
  1349.   TeXPage *tp = TeXPageLocate(w);
  1350.   float value;
  1351.   Arg argList[20];
  1352.   int args = 0;
  1353.   
  1354.   Window root, child;
  1355.   static Widget labelWidget, formWidget, cancelWidget, confirmWidget,
  1356.   valueWidget;
  1357.   
  1358.   static Boolean inited = False;
  1359.   int root_x, root_y, child_x, child_y;
  1360.   unsigned int buttons;
  1361.   
  1362.   IntFloatUnion max;
  1363.   IntFloatUnion one;
  1364.   IntFloatUnion here;
  1365.   
  1366.   Dimension width;
  1367.   Dimension height;
  1368.   Dimension px,py,pw,ph;
  1369.   
  1370.   /*
  1371.    * Find out where the mouse is, so we can put the confirmation
  1372.    * box right there.
  1373.    */
  1374.   XQueryPointer(XtDisplay(tp -> popUpPage),
  1375.         XtWindow(tp -> popUpPage), &root, &child,
  1376.         &root_x, &root_y, &child_x, &child_y, &buttons);
  1377.   /*
  1378.    * If we need to construct the confirmation box do that,
  1379.    * otherwise just reset the position and callbacks and
  1380.    * put it up again.
  1381.    */
  1382.   if (!inited) {
  1383.     /*
  1384.      * The confirmation box will be a pop-up widget.
  1385.      */
  1386.     PopUpWidget =
  1387.       XtCreatePopupShell("Goto", POPUP_WINDOW_TYPE,
  1388.              TopLevelWidget, NULL, 0);
  1389.     
  1390.     /*
  1391.      * Make a form to put the buttons in.
  1392.      */
  1393.     formWidget = XtCreateWidget("form", formWidgetClass,
  1394.                 PopUpWidget, NULL, 0);
  1395.     
  1396.     /*
  1397.      * Confirmation button.
  1398.      */
  1399.     labelWidget = XtCreateManagedWidget("valueLabel", labelWidgetClass,
  1400.                     formWidget, NULL, 0);
  1401.     
  1402.     /*
  1403.      * Confirmation button.
  1404.      */
  1405.     confirmWidget = XtCreateManagedWidget("confirm", commandWidgetClass,
  1406.                       formWidget, NULL, 0);
  1407.     
  1408.     /*
  1409.      * Valuator.
  1410.      */
  1411.     
  1412.     one.f = 1.0;
  1413.     args = 0;
  1414.     XtSetArg(argList[args], XtNmin, one.i); args++;
  1415.     XtSetArg(argList[args], XtNincrement, one.i); args++;
  1416.     GotoValuatorWidget = XtCreateManagedWidget("valuator", valuatorWidgetClass,
  1417.                            formWidget, argList, args);
  1418.     
  1419.     valueWidget = XtCreateManagedWidget("value", labelWidgetClass,
  1420.                     formWidget, NULL, 0);
  1421.     
  1422.     args = 0;
  1423.     XtSetArg(argList[args], XtNvalueLabel, valueWidget); args++;
  1424.     XtSetValues(GotoValuatorWidget, argList, args);
  1425.     
  1426.     /*
  1427.      * Cancellation button.
  1428.      */
  1429.     cancelWidget = XtCreateManagedWidget("cancel", commandWidgetClass,
  1430.                      formWidget, NULL, 0);
  1431.     
  1432.     /*
  1433.      * Let the shell widget know we're here.
  1434.      */
  1435.     XtManageChild(formWidget);
  1436.     XtRealizeWidget(PopUpWidget);
  1437.     inited = True;
  1438.   }
  1439.   
  1440.   /*
  1441.    * Take some pains to center the popup on the pointer, but be certain
  1442.    * the thing is visible, else they can never exit
  1443.    */
  1444.   args = 0;
  1445.   XtSetArg(argList[args], XtNx, &px); args++;
  1446.   XtSetArg(argList[args], XtNy, &py); args++;
  1447.   XtSetArg(argList[args], XtNwidth, &pw); args++;
  1448.   XtSetArg(argList[args], XtNheight, &ph); args++;
  1449.   XtGetValues(tp -> popUpPage, argList,args);
  1450.   
  1451.   args = 0;
  1452.   XtSetArg(argList[args], XtNwidth, &width); args++;
  1453.   XtSetArg(argList[args], XtNheight, &height); args++;
  1454.   XtGetValues(PopUpWidget,argList,args);
  1455.   
  1456.   root_x -= (width/2);
  1457.   root_y -= (height/2);
  1458.   
  1459.   if ( root_x < 0 ) root_x = 0;
  1460.   if ( root_y < 0 ) root_y = 0;
  1461.   
  1462.   args = 0;
  1463.   XtSetArg(argList[args], XtNx, root_x); args++;
  1464.   XtSetArg(argList[args], XtNy, root_y); args++;
  1465.   XtSetValues(PopUpWidget,argList,args);
  1466.   
  1467.   /* reset the valuator */
  1468.   
  1469.   max.f = DviTotalPages;
  1470.   here.f = tp -> pageNumber + 1;
  1471.   
  1472.   args = 0;
  1473.   XtSetArg(argList[args], XtNmax, max.i); args++;
  1474.   XtSetArg(argList[args], XtNvalue, here.i); args++;
  1475.   XtSetValues(GotoValuatorWidget, argList, args);
  1476.   
  1477.   GotoTeXPage = tp;
  1478.   
  1479.   /* pop it up */
  1480.   XtPopup(PopUpWidget, XtGrabExclusive);
  1481. }
  1482.  
  1483. static void actionMagnify(w, event, params, num_params)
  1484.      Widget w;
  1485.      XEvent *event;
  1486.      String *params;
  1487.      Cardinal *num_params;
  1488. {
  1489.   TeXPage *tp = TeXPageLocate(w);
  1490.   int mag;
  1491.   
  1492.   if ( *num_params > 0 && *params ) {
  1493.     
  1494.     if ( strcmp(params[0], "large") == 0) {
  1495.       mag = xtexResources.largeMag;
  1496.     }
  1497.     else if ( strcmp(params[0], "small") == 0) {
  1498.       mag = xtexResources.smallMag;
  1499.     }
  1500.     else {
  1501.       mag = atoi( params[0] );
  1502.     }
  1503.   }
  1504.   else {
  1505.     mag = texxPageNumber( tp, tp -> userMag );
  1506.   }
  1507.   
  1508.   changeMag( tp, mag );
  1509.  
  1510. static void actionNumber(w, event, params, num_params)
  1511.      Widget w;
  1512.      XEvent *event;
  1513.      String *params;
  1514.      Cardinal *num_params;
  1515. {
  1516.   TeXPage *tp = TeXPageLocate(w);
  1517.   if ( IS_VALID_PAGE(tp) && params && *params) {
  1518.     int digits = strlen(*params);
  1519.     int value = atoi(*params);
  1520.     
  1521.     if ( tp -> inputNumberValid ) {
  1522.       while ( digits > 0 ) {
  1523.     tp -> inputNumber *= 10;
  1524.     digits--;
  1525.       }
  1526.     }
  1527.     else {
  1528.       tp -> inputNumber = 0;
  1529.       tp -> inputNumberValid = True;
  1530.       tp -> inputNumberMinus = False;
  1531.     }
  1532.     tp -> inputNumber +=value;
  1533.   }
  1534.  
  1535. static void actionNumberReset(w, event, params, num_params)
  1536.      Widget w;
  1537.      XEvent *event;
  1538.      String *params;
  1539.      Cardinal *num_params;
  1540. {
  1541.   TeXPage *tp = TeXPageLocate(w);
  1542.   if ( IS_VALID_PAGE(tp) ) {
  1543.     texxPageNumberReset(tp);
  1544.   }
  1545.  
  1546. static void actionNumberMinus(w, event, params, num_params)
  1547.      Widget w;
  1548.      XEvent *event;
  1549.      String *params;
  1550.      Cardinal *num_params;
  1551. {
  1552.   TeXPage *tp = TeXPageLocate(w);
  1553.   if ( IS_VALID_PAGE(tp) ) {
  1554.     if ( ! tp -> inputNumberValid ) {
  1555.       tp -> inputNumberValid = True;
  1556.       tp -> inputNumber = 0;
  1557.       tp -> inputNumberMinus = True;
  1558.     }
  1559.     else {
  1560.       tp -> inputNumberMinus = ~(tp->inputNumberMinus);
  1561.     }
  1562.   }
  1563.  
  1564. static Bool actionBool(oldValue, params, num_params)
  1565.      Bool oldValue;
  1566.      String *params;
  1567.      Cardinal *num_params;
  1568. {
  1569.   static char *trues[] = {"true", "True", "yes", "1", 0};
  1570.   static char *falses[] = {"false", "False", "no", "0", 0};
  1571.  
  1572.   if ( *num_params == 1 ) {
  1573.     int i;
  1574.     for (i = 0; trues[i] != 0; i++ ) {
  1575.       if ( strcmp(trues[i], params[0]) == 0 ) return( True );
  1576.     }
  1577.     for (i = 0; falses[i] != 0; i++ ) {
  1578.       if ( strcmp(trues[i], params[0]) == 0 ) return( False );
  1579.     }
  1580.     return( False );
  1581.   } else {
  1582.     return( !oldValue);
  1583.   }
  1584. }
  1585.  
  1586.  
  1587. static void actionChangeShowPostscript(w, event, params, num_params)
  1588.      Widget w;
  1589.      XEvent *event;
  1590.      String *params;
  1591.      Cardinal *num_params;
  1592. {
  1593.   TeXPage *tp = TeXPageLocate(w);
  1594.   xtexResources.showPostScript = actionBool( xtexResources.showPostScript,
  1595.                         params, num_params );
  1596.  
  1597. static XtActionsRec texxPageActionsTable[] = {
  1598.   {"xtex-echo",  actionEcho },
  1599.   {"xtex-page-realize",  actionRealize },
  1600.   {"xtex-page-quit",  actionQuit },
  1601.   {"xtex-page-forward",  actionForeward },
  1602.   {"xtex-page-foreward",  actionForeward },
  1603.   {"xtex-page-backward",  actionBackward },
  1604.   {"xtex-page-duplicate",  actionDup },
  1605.   {"xtex-page-tie",  actionTie },
  1606.   {"xtex-page-goto",  actionGoto },
  1607.   {"xtex-page-push",  actionPush },
  1608.   {"xtex-page-pop",  actionPop },
  1609.   {"xtex-page-divert",  actionDivert },
  1610.   {"xtex-page-undivert",  actionUnDivert },
  1611.   {"xtex-page-redisplay",  actionRedisplay },
  1612.   {"xtex-page-goto-popup",  actionGotoPopup },
  1613.   {"xtex-page-goto-popup-confirm",  actionGotoPopupConfirm },
  1614.   {"xtex-page-goto-popup-cancel",  actionGotoPopupCancel },
  1615.   {"xtex-page-magnify",  actionMagnify },
  1616.   {"xtex-page-number",  actionNumber },
  1617.   {"xtex-page-number-minus",  actionNumberMinus },
  1618.   {"xtex-page-number-reset",  actionNumberReset },
  1619.   {"xtex-show-postscript",  actionChangeShowPostscript }
  1620. };
  1621.  
  1622. void
  1623.   TeXPageInstallActions()
  1624. {
  1625.   XtAddActions(texxPageActionsTable, XtNumber(texxPageActionsTable));
  1626. }
  1627.