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 / DviPage.c < prev    next >
C/C++ Source or Header  |  1992-06-25  |  39KB  |  1,617 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. #include <X11/Xos.h>  
  35. #include <X11/IntrinsicP.h>
  36. #include <X11/StringDefs.h>
  37.  
  38. #include <X11/Xmu/Converters.h>
  39. #include <X11/ObjectP.h>
  40.  
  41. #include <stdio.h>
  42. #include "dvi-simple.h"
  43. #include "libtex/conv.h"
  44. #include "mio.h"
  45. #include <assert.h>
  46.  
  47. #include "xtex.h"
  48.  
  49. #include "DviPageP.h"
  50.  
  51. #ifdef HAVE_GHOSTSCRIPT
  52. #include "DviPageGS-1.h"
  53. #endif
  54.  
  55. #ifdef HAVE_NEWS
  56. #include "DviPageNEWS.h"
  57. #endif
  58.  
  59. #ifdef HAVE_DPS
  60. #include "DviPageDPS.h"
  61. #endif
  62.  
  63. static XtResource resources[] = {
  64.   
  65. #define offset(field) XtOffset(DviPageWidget, field)
  66.   
  67.   /* {name, class, type, size, offset, default_type, default_addr}, */
  68.   
  69.   {XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
  70.      offset(dviPage.background), XtRString, "XtDefaultBackground"},
  71.   
  72.   {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  73.      offset(dviPage.foreground), XtRString, "XtDefaultForeground"},
  74.  
  75.   {XtNboxColor, XtCBoxColor, XtRPixel, sizeof(Pixel),
  76.      offset(dviPage.boxColor), XtRString, "red"},
  77.   
  78.   {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  79.      offset(dviPage.font), XtRString, "XtDefaultFont"},
  80.   
  81.   {XtNpage,  XtCPage, XtRPointer, sizeof(char *),
  82.      offset(dviPage.page), XtRPointer, 0},
  83.   
  84.   {XtNpai,  XtCPai, XtRPointer, sizeof(struct PostAmbleInfo *),
  85.      offset(dviPage.pai), XtRPointer, 0 },
  86.   
  87.   {XtNdviFonts,  XtCDviFonts, XtRPointer, sizeof(DviFontInfo *),
  88.      offset(dviPage.dviFonts), XtRPointer, 0 },
  89.   
  90.   {XtNxFonts,  XtCXFonts, XtRPointer, sizeof(XFontStruct **),
  91.      offset(dviPage.xFonts), XtRPointer, 0 },
  92.   
  93.   {XtNuserMag,  XtCUserMag, XtRInt, sizeof(int),
  94.      offset(dviPage.userMag), XtRString, "500"},
  95.   
  96.   {XtNdpiHoriz, XtCDpiHoriz, XtRFloat, sizeof(float),
  97.      offset(dviPage.dpiHoriz), XtRString, "85"},
  98.   
  99.   {XtNdpiVert,  XtCDpiVert, XtRFloat, sizeof(float),
  100.      offset(dviPage.dpiVert), XtRString, "-1"},
  101.   
  102.   {XtNreverseVideo,  XtCReverseVideo, XtRBool, sizeof(Bool),
  103.      offset(dviPage.reverseVideo), XtRString, "False"},
  104.  
  105.   {XtNredisplay,  XtCRedisplay, XtRBool, sizeof(Bool),
  106.      offset(dviPage.redisplay), XtRString, "False"},
  107.   
  108.   {XtNbackingStore, XtCBackingStore, XtRBackingStore, sizeof (int),
  109.      offset (dviPage.useBackingStore), XtRString, "default"},
  110.   
  111.   {XtNpaperWidth, XtCPaperWidth, XtRFloat, sizeof (float),
  112.      offset (dviPage.paperWidth), XtRString, "8.5"},
  113.   
  114.   {XtNpaperHeight, XtCPaperHeight, XtRFloat, sizeof (float),
  115.      offset (dviPage.paperHeight), XtRString, "11"},
  116.   
  117.   {XtNtopOffset, XtCTopOffset, XtRFloat, sizeof (float),
  118.      offset (dviPage.topOffset), XtRString, "1"},
  119.   
  120.   {XtNleftOffset, XtCLeftOffset, XtRFloat, sizeof (float),
  121.      offset (dviPage.leftOffset), XtRString, "1"},
  122.   
  123.   {XtNscaleUnits, XtCScaleUnits, XtRString, sizeof (char *),
  124.      offset (dviPage.scaleUnitsString), XtRString, "in"},
  125.   
  126. #if defined(HAVE_DPS) || defined(HAVE_NEWS)  || defined(HAVE_GHOSTSCRIPT)
  127.   {XtNtrueDpi, XtCTrueDpi, XtRFloat, sizeof (float),
  128.      offset (dviPage.trueDpi), XtRString, "0.0"},
  129. #endif
  130.  
  131. #if defined(HAVE_DPS) || defined(HAVE_NEWS) 
  132.   {XtNdpsPreamble, XtCDPSpreamble, XtRString, sizeof (char *),
  133.      offset (dviPage.dpsPreamble), XtRString, ""},
  134. #endif
  135.  
  136. #ifdef HAVE_GHOSTSCRIPT
  137.   {XtNgsPreamble, XtCGSpreamble, XtRString, sizeof (char *),
  138.      offset (dviPage.gsPreamble), XtRString, ""},
  139.  
  140.   {XtNghostOutput, XtCCallback, XtRCallback, sizeof (XtPointer),
  141.      offset (dviPage.ghostOutput), XtRCallback, (XtPointer) NULL},
  142.   {XtNinterpreter, XtCInterpreter, XtRString, sizeof(String),
  143.      offset(dviPage.interpreter), XtRString, "gs"},
  144.   {XtNintSrchPath, XtCIntSrchPath, XtRString, sizeof(String),
  145.      offset(dviPage.ghostSearchPath), XtRString, "."}
  146. #endif
  147.  
  148. #undef offset
  149. };
  150.  
  151. #ifdef __STDC__
  152. static void ClassInitialize();
  153. #ifdef HAVE_GHOSTSCRIPT
  154. static void ClassPartInitialize( WidgetClass);
  155. #endif
  156. static void Initialize(), Destroy(), Redisplay();
  157. static void Realize();
  158. static Boolean SetValues( );
  159. static void SetPageSize( DviPageWidget, Dimension *width, Dimension *heigth);
  160. static XtGeometryResult QueryGeometry();
  161.  
  162. extern double atof(char *);
  163. #else
  164. static void ClassInitialize();
  165. #ifdef HAVE_GHOSTSCRIPT
  166. static void ClassPartInitialize();
  167. #endif
  168. static void Initialize(), Destroy(), Redisplay();
  169. static void Realize();
  170. static Boolean SetValues();
  171. static XtGeometryResult QueryGeometry();
  172. static XtGeometryResult QueryGeometry();
  173.  
  174. extern double atof();
  175. #endif
  176.  
  177. static void
  178.   actionLineAnchor(),
  179.   actionLineCastOff(),
  180.   actionLineDraw(),
  181.   actionLineUnDraw(),
  182.   actionLineUnits();
  183.  
  184. void /* in DviPage2.c */
  185.   actionPushButton();
  186.  
  187. static XtActionsRec dviPageActionTable[] = {
  188.   {"dvi-line-anchor",  actionLineAnchor},
  189.   {"dvi-line-castoff",  actionLineCastOff},
  190.   {"dvi-line-draw",  actionLineDraw},
  191.   {"dvi-line-undraw",  actionLineUnDraw},
  192.   {"dvi-line-units",  actionLineUnits},
  193.   {"dvi-push-button", actionPushButton}
  194. };
  195.  
  196. DviPageClassRec dviPageClassRec = {
  197.   { /* core fields */
  198.     /* superclass        */
  199.     (WidgetClass) &widgetClassRec,
  200.     /* class_name        */    "DviPage",
  201.     /* widget_size        */    sizeof(DviPageRec),
  202.     /* class_initialize        */    ClassInitialize,
  203. #ifdef HAVE_GHOSTSCRIPT
  204.     /* class_part_initialize    */    ClassPartInitialize,
  205. #else
  206.     /* class_part_initialize    */    NULL,
  207. #endif
  208.     /* class_inited        */    FALSE,
  209.     /* initialize        */    Initialize,
  210.     /* initialize_hook        */    NULL,
  211.     /* realize            */    Realize,
  212.     /* actions            */    dviPageActionTable,
  213.     /* num_actions        */    XtNumber(dviPageActionTable),
  214.     /* resources        */    resources,
  215.     /* num_resources        */    XtNumber(resources),
  216.     /* xrm_class        */    NULLQUARK,
  217.     /* compress_motion        */    TRUE,
  218.     /* compress_exposure    */    TRUE,
  219.     /* compress_enterleave    */    TRUE,
  220.     /* visible_interest        */    FALSE,
  221.     /* destroy            */    Destroy,
  222.     /* resize            */    NULL,
  223.     /* expose            */    Redisplay,
  224.     /* set_values        */    SetValues,
  225.     /* set_values_hook        */    NULL,
  226.     /* set_values_almost    */    XtInheritSetValuesAlmost,
  227.     /* get_values_hook        */    NULL,
  228.     /* accept_focus        */    NULL,
  229.     /* version            */    XtVersion,
  230.     /* callback_private        */    NULL,
  231.     /* tm_table            */    XtInheritTranslations,
  232.     /* query_geometry        */    QueryGeometry,
  233.     /* display_accelerator    */    XtInheritDisplayAccelerator,
  234.     /* extension        */    NULL
  235.     },
  236.       { /* dviPage fields */
  237. #ifdef HAVE_GHOSTSCRIPT
  238.     /* For ghostscript interface */
  239.     /* ghostview         */    NULL,
  240.     /* next            */    NULL,
  241.     /* page            */    NULL,
  242.     /* done            */    NULL
  243. #else
  244.     /* empty            */    0
  245. #endif
  246.     }
  247. };
  248.  
  249. WidgetClass dviPageWidgetClass = (WidgetClass)&dviPageClassRec;
  250.  
  251. /****************************************************************
  252.  *
  253.  * Class Procedures
  254.  *
  255.  ****************************************************************/
  256.      
  257. static void
  258.   ClassInitialize()
  259. {
  260.   XtAddConverter( XtRString, XtRBackingStore, XmuCvtStringToBackingStore,
  261.          NULL, 0 );
  262. }
  263.  
  264. #ifdef HAVE_GHOSTSCRIPT
  265. static void
  266.   ClassPartInitialize(class)
  267. WidgetClass class;
  268. {
  269.   DviPageWidgetClass wc = (DviPageWidgetClass) class;
  270.  
  271.   wc->dviPage_class.ghostview = XmuMakeAtom( "GHOSTVIEW" );
  272.   wc->dviPage_class.next = XmuMakeAtom( "NEXT" );
  273.   wc->dviPage_class.page = XmuMakeAtom( "PAGE" );
  274.   wc->dviPage_class.done = XmuMakeAtom( "DONE" );
  275. }
  276. #endif
  277.  
  278. /****************************************************************
  279.  *
  280.  * Private Procedures
  281.  *
  282.  ****************************************************************/
  283.  
  284. static ScaleUnits
  285. stringToScaleUnits(str)
  286. char *str;
  287. {
  288. #define IS(a,b) if (strcmp(str,a)==0) return b
  289.   IS("in", sIn);
  290.   IS("pt", sPt);
  291.   IS("cm", sCm);
  292.   IS("mm", sMm);
  293.   IS("sp", sSp);
  294.   IS("pc", sPc);
  295.   IS("bp", sBp);
  296.   IS("dd", sDd);
  297.   IS("cc", sCc);
  298.   return( sSp );
  299. }
  300.  
  301.  
  302. static void releaseButtons(dw)
  303. DviPageWidget dw;
  304. {
  305.   while ( dw -> dviPage.buttons ) {
  306.     DviButton *n = dw -> dviPage.buttons -> next;
  307.     if ( dw -> dviPage.buttons -> longerAction ) {
  308.       XtFree(dw -> dviPage.buttons -> longerAction);
  309.     }
  310.     XtFree((char *) dw -> dviPage.buttons);
  311.     dw -> dviPage.buttons = n;
  312.   }
  313. }
  314.  
  315. static void
  316.   SetPageSize(w, wd, ht)
  317. DviPageWidget w;
  318. Dimension *wd;
  319. Dimension *ht;
  320. {
  321.   DviPagePart *pi = & (w -> dviPage);
  322.   struct PostAmbleInfo *pai = pi -> pai;
  323.   
  324.   long ppi;    /* pixels per inch */
  325.   
  326.   extern long Numerator, Denominator;
  327.   double dNumerator = Numerator;
  328.   double dDenominator = Denominator;
  329.   double dMag;
  330.   extern double    DMagFactor();
  331.   
  332.   /* compute horizontial and vertical scaling factors - this code is
  333.      largely taken from ../lib/conv.c, but we need to duplicate it
  334.      because we've got two dpi values to deal with */
  335.   
  336.   if ( pi -> dpiVert < 0 ) {
  337.     pi -> dpiVert = pi -> dpiHoriz;
  338.   }
  339.   
  340.   dMag = DMagFactor( 1000) * DMagFactor(pi -> userMag);
  341.   
  342.   w -> dviPage.fastFromSpValueHoriz =
  343.     (254000.0 / dNumerator) * (dDenominator / pi -> dpiHoriz)
  344.       * (1.0 / dMag);
  345.   
  346.   w -> dviPage.fastFromSpValueVert =
  347.     (254000.0 / dNumerator) * (dDenominator / pi -> dpiVert)
  348.       * (1.0 / dMag);
  349.   
  350.   /* compute the screen pixels per inch at this magnification */
  351.   
  352.   w -> dviPage.pixelsPerInchHoriz = ( (double) pi -> dpiHoriz * dMag );
  353.   
  354.   w -> dviPage.pixelsPerInchVert = ( (double) pi -> dpiVert * dMag );
  355.   
  356.   w -> dviPage.pixelsWide
  357.     = w -> dviPage.pixelsPerInchHoriz * w -> dviPage.paperWidth;
  358.   
  359.   w -> dviPage.pixelsHigh
  360.     = w -> dviPage.pixelsPerInchVert * w -> dviPage.paperHeight;
  361.   
  362.   (*wd) = w -> dviPage.pixelsWide;
  363.   (*ht) = w -> dviPage.pixelsHigh;
  364. }
  365.  
  366. static void Initialize (request, new)
  367.      Widget request, new;
  368. {
  369.   DviPageWidget want = (DviPageWidget) request;
  370.   DviPageWidget w = (DviPageWidget) new;
  371.   
  372.   Dimension wd, ht;
  373.   
  374.  
  375.   /* copy over  everything */
  376.  
  377.   w -> dviPage = want -> dviPage;
  378.  
  379.   w -> dviPage.clearGC  = 0;
  380.   w -> dviPage.paintGC  = 0;
  381.   w -> dviPage.invertGC  = 0;
  382.  
  383.   w -> dviPage.redisplay = False;
  384.  
  385.   w -> dviPage.anchored = False;
  386.  
  387.   w -> dviPage.units = stringToScaleUnits( w -> dviPage.scaleUnitsString);
  388.   w -> dviPage.scalePopup = 0;
  389.   w -> dviPage.scaleLabel = 0;
  390.  
  391.   w -> dviPage.spPerDot = INCH_TO_SP(1.0);
  392.   w -> dviPage.spPerDot /= w -> dviPage.dpiHoriz;
  393.   w -> dviPage.spPerDot *= 1000;
  394.   w -> dviPage.spPerDot /= w -> dviPage.userMag;
  395.  
  396.   w -> dviPage.dviStack  = 0;
  397.   w -> dviPage.dviStackSize  = 0;
  398.   w -> dviPage.pathLen  = 0;
  399.   w -> dviPage.penSize = 1;
  400.   w -> dviPage.whiten = False;
  401.   w -> dviPage.shade = False;
  402.   w -> dviPage.blacken = False;
  403.  
  404. /* Figure out what we want to use to display poscript figures */
  405. /* this routines sets at most one of the following to True */
  406. /* xtexResources.useGhostScript, xtexResources.useDPS, xtexResources.useNEWS */
  407.  
  408. checkExtensions();
  409.  
  410. #ifdef HAVE_DPS
  411.   w -> dviPage.ctx = 0;
  412.   initDPS();
  413. #endif /* HAVE_DPS */
  414.  
  415. #ifdef HAVE_NEWS
  416.   w -> dviPage.newsfile = 0;
  417.   initNEWS();
  418. #endif
  419.  
  420. #ifdef HAVE_GHOSTSCRIPT
  421.   gsintInitialize (w);
  422. #endif
  423.  
  424.   w -> dviPage.buttons = 0;
  425.  
  426.   SetPageSize(w, &wd, &ht);
  427.   
  428. #define MaX(x,y) ((x) > (y) ) ? (x) : (y)
  429.   
  430.   w -> core.width = MaX(wd, want->core.width);
  431.   w -> core.height = MaX(ht, want->core.height);
  432.   
  433. #undef MaX
  434.   
  435. }
  436.  
  437. static void SetGC(w)
  438. DviPageWidget w;
  439. {
  440.   
  441.   XGCValues    values;
  442.   unsigned long fore = w->dviPage.foreground;
  443.   unsigned long aft = w->dviPage.background;
  444.   
  445.   if ( w -> dviPage.reverseVideo ) {
  446.     unsigned long tmp = aft;
  447.     aft = fore;
  448.     fore = tmp;
  449.   }
  450.   values.function    = GXcopy;
  451.   values.foreground    = aft;
  452.   values.background    = fore;
  453.  
  454.   XChangeGC( XtDisplay(w), w -> dviPage.clearGC,
  455.         (unsigned) GCFunction | GCForeground | GCBackground,
  456.         &values);
  457.  
  458.   /* Prepare to paint */
  459.     
  460.   values.function    = GXcopy;
  461.   values.foreground    = fore;
  462.   values.background    = aft;
  463.   values.plane_mask    = AllPlanes;
  464.   values.font        = w->dviPage.font->fid;
  465.   values.line_width    = 1;
  466.     
  467.   XChangeGC( XtDisplay(w), w -> dviPage.paintGC,
  468.         (unsigned) GCFunction | GCPlaneMask
  469.         | GCForeground | GCBackground | GCFont | GCLineWidth,
  470.         &values);
  471.  
  472.   values.function    = GXxor;
  473.   values.foreground    = (fore ^ aft);
  474.   values.background    = (fore ^ aft);
  475.   values.font        = w -> dviPage.font -> fid;
  476.   values.line_width    = 0;
  477.   
  478.   w -> dviPage.invertGC =
  479.     XtGetGC( (Widget) w, 
  480.         (unsigned) GCFunction | GCForeground | GCBackground
  481.         | GCFont | GCLineWidth,
  482.         &values);
  483. }
  484.  
  485. static void Realize (gw, valueMask, attrs)
  486.      Widget gw;
  487.      XtValueMask *valueMask;
  488.      XSetWindowAttributes *attrs;
  489. {
  490.   
  491.   XWindowAttributes wAttributes;
  492.   
  493.   DviPageWidget    w = (DviPageWidget) gw;
  494.  
  495.   switch (w->dviPage.useBackingStore) {
  496.   case Always:
  497.   case WhenMapped:
  498.   case NotUseful:
  499.     *valueMask |=CWBackingStore;
  500.     attrs->backing_store = w->dviPage.useBackingStore;
  501.     break;
  502.     break;
  503.   }
  504.   
  505.   XtCreateWindow( (Widget) w, InputOutput, (Visual *)CopyFromParent,
  506.          *valueMask, attrs);
  507.  
  508.   XGetWindowAttributes( XtDisplay(w), XtWindow(w), &wAttributes );
  509.   
  510.   
  511.   w -> dviPage.haveBackingStore
  512.     = ( wAttributes.backing_store == Always)
  513.       || (wAttributes.backing_store == WhenMapped);
  514.   
  515.   w->dviPage.paintGC
  516.     = XCreateGC( XtDisplay(w), XtWindow(w), 0, NULL);
  517.  
  518.   w->dviPage.clearGC
  519.     = XCreateGC( XtDisplay(w), XtWindow(w), 0, NULL);
  520.  
  521.   w->dviPage.invertGC
  522.       = XCreateGC( XtDisplay(w), XtWindow(w), 0, NULL);
  523.  
  524.   SetGC( w );
  525.  
  526. #ifdef HAVE_GHOSTSCRIPT
  527.   if( xtexResources.useGhostScript ){
  528.      w->dviPage.ghostPixDepth = wAttributes.depth;
  529.      gsintRealize (w); 
  530.   } 
  531. #endif
  532. }
  533.  
  534. static void Destroy (gw)
  535.      Widget gw;
  536. {
  537.   DviPageWidget w = (DviPageWidget) gw;
  538.   XtFree( (char *) w -> dviPage.dviStack );
  539.   w -> dviPage.dviStack = 0;
  540.   
  541.   if ( w -> dviPage.paintGC ) {
  542.     XFreeGC( XtDisplay(w), w -> dviPage.paintGC );
  543.     w -> dviPage.paintGC = 0;
  544.   }
  545.  
  546.   if ( w -> dviPage.clearGC ) {
  547.     XFreeGC( XtDisplay(w), w -> dviPage.clearGC );
  548.     w -> dviPage.clearGC = 0;
  549.   }
  550.  
  551.   if ( w -> dviPage.invertGC ) {
  552.     XtReleaseGC( (Widget) w, w -> dviPage.invertGC );
  553.     w -> dviPage.invertGC = 0;
  554.   }
  555.  
  556.   if ( w -> dviPage.scalePopup) {
  557.     XtDestroyWidget( w -> dviPage.scalePopup );
  558.   }
  559.  
  560. #ifdef HAVE_DPS
  561.   if ( xtexResources.useDPS && w -> dviPage.ctx ) {
  562.     DPSFlushContext( w -> dviPage.ctx );
  563.     DPSWaitContext( w -> dviPage.ctx );
  564.     DPSDestroySpace( DPSSpaceFromContext( w -> dviPage.ctx ));
  565.   }
  566. #endif
  567.  
  568. #ifdef HAVE_NEWS
  569.   if ( xtexResources.useNEWS && w -> dviPage.newsfile ) {
  570.     ps_close_PostScript();
  571.   }
  572. #endif
  573.  
  574. #ifdef HAVE_GHOSTSCRIPT
  575.   if( xtexResources.useGhostScript ) gsintDestroy (w);
  576. #endif
  577.  
  578.   releaseButtons(w);
  579.  
  580. }
  581.  
  582. static Boolean SetValues(current, request, new)
  583.      DviPageWidget current, request, new;
  584. {
  585.   
  586.   DviPagePart *pi = & (request -> dviPage);
  587.   struct PostAmbleInfo *p = pi -> pai;
  588.   Boolean replot = False;
  589.   
  590. #define NOT_SAME_PTR(XX) (request -> dviPage.XX && request->dviPage.XX != current -> dviPage.XX)
  591.   
  592. #define UPDATE_VALUE(XX) {\
  593.     new -> dviPage.XX = request -> dviPage.XX;\
  594.  }
  595.   
  596.   if ( NOT_SAME_PTR(page) ) {
  597.     UPDATE_VALUE(page);
  598.     replot = True;
  599.   }
  600.   
  601.   if ( NOT_SAME_PTR(xFonts) ) {
  602.     UPDATE_VALUE(xFonts);
  603.     replot = True;
  604.   }
  605.   
  606.   if ( NOT_SAME_PTR(pai) ) {
  607.     UPDATE_VALUE(pai);
  608.     replot = True;
  609.   }
  610.   
  611.   if ( new -> dviPage.pai ) {
  612.     
  613.     int stackSize = new -> dviPage.pai -> pai_DVIStackSize;
  614.     
  615.     if (stackSize > new -> dviPage.dviStackSize ) {
  616.       
  617.       stackSize += 2;
  618.       
  619.       XtFree( (char *) new -> dviPage.dviStack );
  620.       
  621.       new -> dviPage.dviStack  = 0;
  622.       new -> dviPage.dviStackSize = stackSize;
  623.       
  624.       if (stackSize > 0 ) {
  625.     new -> dviPage.dviStack  = 
  626.       (LocalDviStack *) (XtMalloc( (stackSize+1) * sizeof(LocalDviStack) ));
  627.       }
  628.     }
  629.   }
  630.   
  631.   if ( NOT_SAME_PTR(dpiHoriz) ) {
  632.     UPDATE_VALUE(dpiHoriz);
  633.     replot = True;
  634.   }
  635.   
  636.   if ( NOT_SAME_PTR(dpiVert) ) {
  637.     UPDATE_VALUE(dpiVert);
  638.     replot = True;
  639.   }
  640.   
  641.   if ( NOT_SAME_PTR(dviFonts) ) {
  642.     UPDATE_VALUE(dviFonts);
  643.     replot = True;
  644.   }
  645.   
  646.   if ( NOT_SAME_PTR(paperWidth) ) {
  647.     UPDATE_VALUE(paperWidth);
  648.     replot = True;
  649.   }
  650.   
  651.   if ( NOT_SAME_PTR(paperHeight) ) {
  652.     UPDATE_VALUE(paperHeight);
  653.     replot = True;
  654.   }
  655.   
  656.   if ( NOT_SAME_PTR(topOffset) ) {
  657.     UPDATE_VALUE(topOffset);
  658.     replot = True;
  659.   }
  660.   
  661.   if ( NOT_SAME_PTR(leftOffset) ) {
  662.     UPDATE_VALUE(leftOffset);
  663.     replot = True;
  664.   }
  665.  
  666.   if ( NOT_SAME_PTR(scaleUnitsString) ) {
  667.     UPDATE_VALUE(scaleUnitsString);
  668.     replot = True;
  669.   }
  670.  
  671.   if ( NOT_SAME_PTR(userMag) ) {
  672.     UPDATE_VALUE(userMag);
  673.     replot = True;
  674.   }
  675.   
  676.   new -> dviPage.units = stringToScaleUnits( new -> dviPage.scaleUnitsString);
  677.  
  678.   new -> dviPage.spPerDot = INCH_TO_SP(1.0);
  679.   new -> dviPage.spPerDot /=  new -> dviPage.dpiHoriz;
  680.   new -> dviPage.spPerDot *= 1000;
  681.   new -> dviPage.spPerDot /= new -> dviPage.userMag;
  682.  
  683.   SetGC( new );
  684.  
  685.   SetPageSize(new, &(new -> core.width), &(new -> core.height));
  686.  
  687.   /*  WHY ? new -> dviPage.anchored = True;*/
  688.   new -> dviPage.anchored = False;
  689.   new -> dviPage.redisplay = False;
  690.  
  691.   /* let application explicitly manage redisplay */
  692.  
  693.   replot = False;
  694.   if ( request -> dviPage.redisplay ) {
  695.     replot = True;
  696.   }
  697.  
  698.   return( replot );
  699. }
  700.  
  701. static XtGeometryResult QueryGeometry(w, intended, preferred)
  702.      Widget w;
  703.      XtWidgetGeometry *intended, *preferred;
  704. {
  705.   register DviPageWidget lw = (DviPageWidget) w;
  706.   Dimension wd, ht;
  707.   
  708.   /* I begin to think that this procedure doesn't do much of worth */
  709.  
  710.   return XtGeometryYes;
  711. /***********************************************************************
  712. #if 0
  713.  
  714.   SetPageSize((DviPageWidget) w, &wd, &ht);
  715.   
  716.   preferred -> request_mode = CWWidth | CWHeight;
  717.   preferred -> width = wd ;
  718.   preferred -> height =  ht ;
  719.  
  720. #define NEAR(X,Y) (abs(X-Y) < 5)
  721.  
  722.   if (  ((intended->request_mode & (CWWidth | CWHeight))
  723.       == (CWWidth | CWHeight)))
  724.     {
  725.       if (intended->width == w->core.width &&
  726.       intended->height == w->core.height) {
  727.     return XtGeometryYes;
  728.       }
  729.       else if (NEAR(intended->width, preferred->width) &&
  730.       NEAR(intended->height, preferred->height)) {
  731.     return XtGeometryAlmost;
  732.       }
  733.       else {
  734.     return XtGeometryNo;
  735.       }
  736.   }
  737.   else {
  738.     return XtGeometryYes;
  739.   }
  740. #endif
  741. ***********************************************************************/
  742. }
  743.  
  744. /*
  745.  *    Some very DVI related things
  746.  */
  747.  
  748. #define    ABS(X)    ( (X) < 0 ? -(X) : (X) )
  749.  
  750. static int selectFont(w, ptr, index, font)
  751.      DviPageWidget w;
  752.      DviFontInfo **ptr;
  753.      int *index;
  754.      int font;
  755. {
  756.   if ( *ptr != 0 && (*ptr) -> paf.paf_DVIFontIndex == font ) {
  757.     return 0;
  758.   }
  759.   else {
  760.     int offset;
  761.     DviFontInfo *fonts = w -> dviPage.dviFonts;
  762.     
  763.     *ptr = 0;
  764.     for ( offset = 0; offset < RegisteredFonts; offset++ ) {
  765.       if ( fonts[offset].paf.paf_DVIFontIndex == font ) {
  766.     *ptr = &(fonts[offset]);
  767.     *index = offset;
  768.     break;
  769.       }
  770.     }
  771.     
  772.     if ( *ptr == 0 ) {
  773.       error(0,0,"Can't find font %d", font);
  774.       return 1;
  775.     }
  776.     else {
  777.       return(0);
  778.     }
  779.   }
  780. }
  781.  
  782. typedef struct {
  783.   int spDrift;
  784.   long spPerDot;
  785.   DviPagePart *page; 
  786.   DviFontInfo *dviCurrentFont;
  787.   int dviCurrentFontIndex;
  788.   XFontStruct *currentFontStruct;
  789.   
  790.   /* following are used to reduce the number of XDrawStrings we do */
  791.   
  792. #define MAX_DVI_STRING 64
  793.   char dviString[ MAX_DVI_STRING ];
  794.   int dviStringLength;
  795.   
  796. #ifdef STATS
  797.   int longestString;
  798. #endif
  799.   
  800.   int startHH, startVV;
  801.   int endHH, endVV;
  802.   
  803.   LocalDviStack *dviStackP;    /* current stack item */
  804.   
  805. } DviDisplayInfo;
  806.  
  807. static void DviDisplayFlush(widget, info)
  808.      DviPageWidget widget;
  809.      DviDisplayInfo *info;
  810. {
  811. #ifdef DEBUG_FLUSH
  812.   if (Debug) {
  813.     fprintf(stderr,"Flush string of %d bytes at %d,%d\n",
  814.         info -> dviStringLength ,  info -> startHH ,  info -> startVV );
  815.   }
  816. #endif
  817.  
  818.   if (  info -> dviStringLength  > 0 ) {
  819.     
  820.     i32 atHH = fastFromSpHoriz(widget,  info -> startHH );
  821.     i32 atVV = fastFromSpVert(widget,  info -> startVV );
  822.     Bool doit = True;
  823.     
  824. #ifdef STATS
  825.     if (info -> dviStringLength > info -> longestString) {
  826.       info -> longestString = info -> dviStringLength;
  827.     }
  828. #endif
  829.     
  830.     if ( widget -> dviPage.haveBackingStore ) {
  831.       i32 width = fastFromSpHoriz(widget,  info -> endHH );
  832.       i32 height = fastFromSpVert(widget,  info -> endVV );
  833.       
  834.       doit =
  835.     XRectInRegion( widget -> dviPage.updateRegion, atHH, atVV,
  836.               width, height) != RectangleOut;
  837.     }
  838.     
  839.     if (doit) {
  840. #if 0
  841.       XDrawImageString( XtDisplay( widget ), XtWindow( widget ),
  842.                info -> page  -> paintGC, atHH, atVV,
  843.                info -> dviString ,  info -> dviStringLength  );
  844. #endif
  845.       XDrawString( XtDisplay( widget ), XtWindow( widget ),
  846.           info -> page  -> paintGC, atHH, atVV,
  847.           info -> dviString ,  info -> dviStringLength  );
  848.     }
  849.   }
  850.   
  851.   info -> dviStringLength = 0;
  852.   info -> startHH = info -> dviStackP -> h;
  853.   info -> startVV = info -> dviStackP -> v ;
  854.   info -> endHH = info -> startHH ;
  855. }
  856.  
  857. static void DviDisplay(widget)
  858.      DviPageWidget widget;
  859. {
  860.   int c;
  861.   i32 p;
  862.   int advance;
  863.   int wuz;
  864.   DviDisplayInfo info;
  865.   double spDriftTmp;
  866.   long tmp;
  867.   
  868.   struct PostAmbleInfo *pai;
  869.   char *thisPage;
  870.   LocalDviStack *dviStack;
  871.   
  872.   /* initialize info structure */
  873.   
  874.   info.page = &( widget -> dviPage); 
  875.   info.dviCurrentFont = 0;
  876.   info.dviCurrentFontIndex = 0;
  877.   info.currentFontStruct = widget -> dviPage.font;
  878.   info.dviStringLength = 0;
  879.   info.startHH = info.startVV = -1;
  880.   info.endHH = info.endVV = -1;
  881. #ifdef STATS
  882.   info.longestString = 0;
  883. #endif
  884.   
  885.   /* compute  spPerDot  -- the number of Sp per actual *dot* on the display */
  886.   
  887.   info.spPerDot = INCH_TO_SP(1.0);
  888.   info.spPerDot /= info.page -> pixelsPerInchHoriz;
  889.   
  890. #ifdef STATS
  891.   fprintf(stderr,"spPerDot        = %f\n", info.spPerDot);
  892. #endif
  893.   
  894.   /* initialize things dependent on info structure */
  895.   
  896.   pai = info.page  -> pai;
  897.   thisPage = info.page->page ;
  898.   dviStack = info.page  -> dviStack;
  899.   
  900.   if ( pai == 0 || thisPage == 0 || dviStack == 0) return;
  901.   
  902.   assert( dviStack != 0 );
  903.   info.dviStackP = dviStack;
  904.   
  905.   /* insure that first byte is a BOP mark */
  906.   
  907.   c = (*thisPage) & 0xff;
  908.   if ( DVI_DT(c) != DT_BOP ) {
  909.     error(0,0,"No BOP found");
  910.     goto cleanup;
  911.   }
  912.   
  913.   for(;;) {
  914.     
  915.     c = mGetByte(&thisPage);
  916.     
  917.     if (DVI_IsChar(c)) {
  918.       
  919.       int offset;
  920.       int thisCharWidthInSp;
  921.       int thisCharTfmWidthInSp;
  922.       int thisWidth;
  923.       int driftInSp;
  924.       
  925.       advance = 1;
  926.       
  927.     doDviChar:
  928.       
  929.       
  930.       /*
  931.        *    The following code makes use of the FontStruct information;
  932.        *    each time we cache a glyph, we update the stack to point to
  933.        *    the location where we should be. endHH, on the other hand,
  934.        *    is the *actual* location, based on the width of the displayed
  935.        *    glyph.
  936.        */
  937.       
  938.       offset = c - ( info.currentFontStruct  -> min_char_or_byte2);
  939.       if (  info.currentFontStruct  -> per_char ) {
  940.     XCharStruct *cs = &( info.currentFontStruct  -> per_char[offset]);
  941.     thisWidth = cs -> width;
  942.       }
  943.       else {
  944.     thisWidth = info.currentFontStruct  -> max_bounds.width;
  945.       }
  946.       thisCharWidthInSp = (thisWidth *  info.spPerDot );
  947.       
  948.       if ( info.dviCurrentFont  &&  info.dviCurrentFont  -> widths) { 
  949.     thisCharTfmWidthInSp =  ( info.dviCurrentFont  -> widths[ c ]);
  950.       }
  951.       
  952.       /*
  953.        * driftInSp is the number of scaled-points we'll be drifting
  954.        * from the true location if we lay down the current glyph.
  955.        *
  956.        * we used to check if the current string when over the drift
  957.        * limit, but that gives choppier output.
  958.        *
  959.        */
  960.       
  961.       driftInSp = ABS((info.endHH + thisCharWidthInSp)
  962.               - ( info.dviStackP  -> h + thisCharTfmWidthInSp));
  963.       
  964. #ifdef DEBUG_FLUSH
  965.       if (Debug) {
  966.     fprintf(stderr,"Flush decision:\n");
  967.     fprintf(stderr,"%-20s=%d\n", "advance", advance);
  968.     fprintf(stderr,"%-20s=%d\n", "thisWidth", thisWidth);
  969.     fprintf(stderr,"%-20s=%d\n", "spPerDot", info.spPerDot);
  970.     fprintf(stderr,"%-20s=%d\n", "thisCharWidthInSp", thisCharWidthInSp);
  971.     fprintf(stderr,"%-20s=%d\n", "driftInSp", driftInSp);
  972.     fprintf(stderr,"%-20s=%d\n", " info.endHH ",
  973.         info.endHH );
  974.     fprintf(stderr,"%-20s=%d\n", " info.endVV ",
  975.         info.endVV );
  976.     fprintf(stderr,"%-20s=%d\n", " info.dviStackP ->v",
  977.         info.dviStackP  -> v);
  978.     fprintf(stderr,"%-20s=%d\n", " info.dviStackP ->h",
  979.         info.dviStackP  -> h);
  980.       }
  981. #endif
  982.  
  983. /*
  984.  * should we flush the existing string before adding the current
  985.  * character?
  986.  */
  987.  
  988.       if ( !advance
  989.        ||  driftInSp > info.spPerDot
  990.        ||  info.endVV  != ( info.dviStackP  -> v)
  991.        ||  info.dviStringLength  >= MAX_DVI_STRING )
  992.     {
  993.       DviDisplayFlush(widget, &info);
  994.     }
  995.       
  996.       if (info.dviStringLength == 0 ) {
  997.     info.startHH = info.dviStackP -> h;
  998.     info.startVV = info.dviStackP -> v ;
  999.     info.endHH = info.startHH ;
  1000.       }
  1001.       info.dviString [  info.dviStringLength ++ ] = c; 
  1002.       
  1003.       if ( advance ) {
  1004.     if ( info.dviCurrentFont  &&  info.dviCurrentFont  -> widths) { 
  1005.       info.dviStackP  -> h += thisCharTfmWidthInSp;
  1006.     }
  1007.     info.endHH  += thisCharWidthInSp;
  1008.       }
  1009.       else {
  1010.     info.endHH = info.dviStackP  -> h;
  1011.       }
  1012.       
  1013.       info.endVV = info.dviStackP  -> v;
  1014.       
  1015.     } else {
  1016.       
  1017.       switch (DVI_OpLen(c)) {
  1018.     
  1019.       case DPL_NONE:
  1020.     break;
  1021.     
  1022.       case DPL_SGN1:
  1023.     p = mGetByte(&thisPage);
  1024.     p = Sign8(p);
  1025.     break;
  1026.     
  1027.       case DPL_SGN2:
  1028.     mGetWord(&thisPage, &p);
  1029.     p = Sign16(p);
  1030.     break;
  1031.     
  1032.       case DPL_SGN3:
  1033.     mGet3Byte(&thisPage, &p);
  1034.     p = Sign24(p);
  1035.     break;
  1036.     
  1037.       case DPL_SGN4:
  1038.     mGetLong(&thisPage, &p);
  1039.     break;
  1040.     
  1041.       case DPL_UNS1:
  1042.     p = UnSign8(mGetByte(&thisPage));
  1043.     break;
  1044.     
  1045.       case DPL_UNS2:
  1046.     mGetWord(&thisPage, &p);
  1047.     p = UnSign16(p);
  1048.     break;
  1049.     
  1050.       case DPL_UNS3:
  1051.     mGet3Byte(&thisPage, &p);
  1052.     p = UnSign24(p);
  1053.     break;
  1054.     
  1055.       default:
  1056.     panic("DVI_OpLen(%d) = %d", c, DVI_OpLen(c));
  1057.     goto cleanup;
  1058.     /* NOTREACHED */
  1059.       }
  1060.       
  1061.       switch (DVI_DT(c)) {
  1062.     
  1063.       case DT_SET:
  1064.     c = p;
  1065.     advance = 1;
  1066. #ifdef DEBUG_FLUSH
  1067.     if (Debug) {
  1068.       fprintf(stderr,"SET character %d (advance)\n", c);
  1069.     }
  1070. #endif
  1071.     goto doDviChar;
  1072.     break;
  1073.     
  1074.       case DT_PUT:
  1075.     c = p;
  1076.     advance = 0;
  1077. #ifdef DEBUG_FLUSH
  1078.     if (Debug) {
  1079.       fprintf(stderr,"PUT character %d (no advance)\n", c);
  1080.     }
  1081. #endif
  1082.     goto doDviChar;
  1083.     break;
  1084.     
  1085.       case DT_SETRULE:
  1086.       case DT_PUTRULE:
  1087.     DviDisplayFlush(widget, &info);
  1088.     {
  1089.       i32 cHH, cVV;
  1090.       double dhh, dvv;
  1091.       i32 rhh, rvv;
  1092.       
  1093.       cHH = fastFromSpHoriz(widget,  info.dviStackP  -> h);
  1094.       cVV = fastFromSpVert(widget,  info.dviStackP  -> v);
  1095.       
  1096.       mGetLong(&thisPage, &rvv);
  1097.       mGetLong(&thisPage, &rhh);
  1098.       
  1099.       if (DVI_DT(c) == DT_SETRULE) {
  1100.         info.dviStackP  -> h += rhh;
  1101.       }
  1102.       
  1103.       dhh = rhh;
  1104.       dvv = rvv;
  1105.       
  1106.       rhh = CEIL( fastFromSpHoriz(widget, dhh) );
  1107.       rvv = CEIL( fastFromSpVert(widget, dvv) );
  1108.       
  1109.       XFillRectangle(XtDisplay(widget), XtWindow(widget),
  1110.              info.page  -> paintGC, cHH, cVV - rvv, rhh, rvv);
  1111.       
  1112.     }
  1113.     break;
  1114.     
  1115.       case DT_NOP:
  1116.     break;
  1117.     
  1118.       case DT_BOP:
  1119.     /*
  1120.      *    Each beginning of  info.page  has 11 4-byte words telling us things
  1121.      *    about the  info.page. We ignore them.
  1122.      */
  1123.     thisPage += (11 * 4);
  1124.     
  1125.     info.dviStackP = dviStack;
  1126.     info.dviStackP  -> h = INCH_TO_SP( (double)  info.page  -> leftOffset);
  1127.     info.dviStackP  -> v = INCH_TO_SP( (double)  info.page  -> topOffset);
  1128.     info.startHH = info.dviStackP  -> h;
  1129.     info.startVV = info.dviStackP  -> v ;
  1130.     info.endHH = info.startHH ;
  1131.     info.endVV = info.startVV ;
  1132.     info.dviStackP  -> w = 0;
  1133.     info.dviStackP  -> x = 0;
  1134.     info.dviStackP  -> y = 0;
  1135.     info.dviStackP  -> z = 0;
  1136.     
  1137.     break;
  1138.     
  1139.       case DT_EOP:
  1140.     goto cleanup;
  1141.     /* NOTREACHED */
  1142.     
  1143.       case DT_PUSH:
  1144.     DviDisplayFlush(widget, &info);
  1145.     {
  1146.       /* copy the old stack to the new one */
  1147.       
  1148.       LocalDviStack *old = info.dviStackP ;
  1149.       info.dviStackP ++;
  1150.       * info.dviStackP = *old;
  1151.     }
  1152.     break;
  1153.     
  1154.       case DT_POP:
  1155.     /* just use the old stack */
  1156.     DviDisplayFlush(widget, &info);
  1157.     info.dviStackP --;
  1158.     break;
  1159.     
  1160.       case DT_W0:    /* there should be a way to make these pretty */
  1161.     p = info.dviStackP  -> w;
  1162.     goto move_right;
  1163.     
  1164.       case DT_W:
  1165.     info.dviStackP  -> w = p;
  1166.     goto move_right;
  1167.     
  1168.       case DT_X0:
  1169.     p = info.dviStackP  -> x;
  1170.     goto move_right;
  1171.     
  1172.       case DT_X:
  1173.     info.dviStackP  -> x = p;
  1174.     goto move_right;
  1175.     
  1176.       case DT_RIGHT:
  1177.       move_right:
  1178.     DviDisplayFlush(widget, &info);
  1179. #ifdef DEBUG_FLUSH
  1180.     if (Debug) {
  1181.       fprintf(stderr,"RIGHT %d\n", p);
  1182.     }
  1183. #endif
  1184.     info.dviStackP  -> h += p;
  1185.     break;
  1186.     
  1187.       case DT_Y0:
  1188.     p = info.dviStackP  -> y;
  1189.     goto move_down;
  1190.     
  1191.       case DT_Y:
  1192.     info.dviStackP  -> y = p;
  1193.     goto move_down;
  1194.     
  1195.       case DT_Z0:
  1196.     p = info.dviStackP  -> z;
  1197.     goto move_down;
  1198.     
  1199.       case DT_Z:
  1200.     info.dviStackP  -> z = p;
  1201.     goto move_down;
  1202.     
  1203.       case DT_DOWN:
  1204.       move_down:
  1205.     DviDisplayFlush(widget, &info);
  1206. #ifdef DEBUG_FLUSH
  1207.     if (Debug) {
  1208.       fprintf(stderr,"DOWN %d\n", p);
  1209.     }
  1210. #endif
  1211.     info.dviStackP  -> v += p;
  1212.     break;
  1213.     
  1214.       case DT_FNTNUM:
  1215.       case DT_FNT:
  1216.     {
  1217.       int font;
  1218.       
  1219.       /* flush existing text */
  1220.       
  1221.       DviDisplayFlush(widget, &info);
  1222.       
  1223.       /* switch to new font */
  1224.       
  1225.       font = ( DVI_DT(c) == DT_FNTNUM )
  1226.         ? font = (c - DVI_FNTNUM0) : p;
  1227.       
  1228.       if ( selectFont(widget,
  1229.               & info.dviCurrentFont , & info.dviCurrentFontIndex , font) ) {
  1230.         goto cleanup;
  1231.       }
  1232.       else {
  1233.         /* load the font */
  1234.         int useFont =
  1235.           (widget -> dviPage.xFonts
  1236.            && widget -> dviPage.xFonts[  info.dviCurrentFontIndex  ]);
  1237.         
  1238.         Font font ;
  1239.         
  1240.         info.currentFontStruct = 
  1241.           (useFont)
  1242.         ? (widget->dviPage.xFonts[  info.dviCurrentFontIndex  ])
  1243.           : widget -> dviPage.font ;
  1244.         
  1245.         font = info.currentFontStruct  -> fid;
  1246.         
  1247.         XSetFont( XtDisplay(widget), widget -> dviPage.paintGC, font );
  1248.       }
  1249.     }
  1250.     break;
  1251.     
  1252.       case DT_XXX:
  1253.     {
  1254.       char specialBuffer [2048];
  1255.       register char *cp;
  1256.       int sweetp = 0;
  1257.       
  1258.       DviDisplayFlush(widget, &info);
  1259.       if (p > 2047) {
  1260.         sweetp = p - 2047;
  1261.         p = 2047;
  1262.       }
  1263.       
  1264.       for (cp = specialBuffer ; p > 0; p--) {
  1265.         *cp = mGetByte(&thisPage);
  1266.         cp++;
  1267.       }
  1268.       *(cp) = 0;
  1269.       
  1270.       while(sweetp > 0) {
  1271.         mGetByte(&thisPage);
  1272.       }
  1273.       
  1274.       widget -> dviPage.dviStackPointer = info.dviStackP ;
  1275.       doSpecial(widget, specialBuffer);
  1276.     }
  1277.     break;
  1278.     
  1279.       case DT_FNTDEF:
  1280.     {
  1281.       int i;
  1282.       long j;
  1283.       mGetLong(&thisPage, &j);
  1284.       mGetLong(&thisPage, &j);
  1285.       mGetLong(&thisPage, &j);
  1286.       i = UnSign8(mGetByte(&thisPage));
  1287.       i += UnSign8(mGetByte(&thisPage));
  1288.       while (--i >= 0) {
  1289.         (void) mGetByte(&thisPage);
  1290.       }
  1291.     }
  1292.     break;
  1293.     
  1294.       case DT_PRE:
  1295.     GripeUnexpectedOp("PRE");
  1296.     goto cleanup;
  1297.     /* NOTREACHED */
  1298.     
  1299.       case DT_POST:
  1300.     GripeUnexpectedOp("POST");
  1301.     goto cleanup;
  1302.     /* NOTREACHED */
  1303.     
  1304.       case DT_POSTPOST:
  1305.     GripeUnexpectedOp("POSTPOST");
  1306.     goto cleanup;
  1307.     /* NOTREACHED */
  1308.     
  1309.       case DT_UNDEF:
  1310.     GripeUndefinedOp(c);
  1311.     goto cleanup;
  1312.     /* NOTREACHED */
  1313.     
  1314.       default:
  1315.     panic("DVI_DT(%d) = %d", c, DVI_DT(c));
  1316.     goto cleanup;
  1317.     /* NOTREACHED */
  1318.       }
  1319.     }
  1320.   }
  1321.   
  1322.  cleanup:
  1323.   /* clean up laststring if there was one */
  1324.   DviDisplayFlush(widget, &info);
  1325.   
  1326. #ifdef STATS
  1327.   fprintf(stderr,"Longest string was %d\n", info.longestString);
  1328. #endif
  1329.   
  1330.   return;
  1331. }
  1332.  
  1333.  
  1334. /* ARGSUSED */
  1335. static void Redisplay (gw, event, region)
  1336.      Widget gw;
  1337.      XEvent *event;        /* unused */
  1338.      Region region;        /* unused */
  1339. {
  1340.   DviPageWidget w = (DviPageWidget) gw;
  1341.  
  1342.   if (XtIsRealized((Widget) w)) {
  1343.  
  1344.     XWindowAttributes w_attr;
  1345.     Window  pg_win;
  1346.     long oldEmask;
  1347.     long newEmask;
  1348.  
  1349.     /* turn off input all key and mouse events and put up the busy cursor */
  1350.     if ((pg_win = XtWindow(w)) != NULL) {
  1351.        XGetWindowAttributes(XtDisplay(w),XtWindow(w),&w_attr);
  1352.        newEmask = oldEmask= w_attr.your_event_mask;
  1353.        newEmask &= ~(KeyPressMask|KeyReleaseMask);
  1354.        newEmask &= ~(ButtonPressMask|ButtonReleaseMask);
  1355.        XSelectInput(XtDisplay(w),pg_win,0);
  1356.        busyCursor();
  1357.     }
  1358.  
  1359.     XSetRegion( XtDisplay(w), w -> dviPage.clearGC, region );
  1360.     
  1361.     XFillRectangle(XtDisplay(w), XtWindow(w),
  1362.            w -> dviPage.clearGC,
  1363.            0, 0,
  1364.            w -> core.width, w -> core.height);
  1365.     
  1366.     XSetRegion( XtDisplay(w), w -> dviPage.paintGC, region );
  1367.     
  1368.     if (w -> dviPage.pai && w -> dviPage.page  && w -> dviPage.dviFonts ) {
  1369.       w -> dviPage.updateRegion = region;
  1370.       releaseButtons(w);
  1371.       DviDisplay(w);
  1372.     }
  1373.  
  1374.     /* start listening for events again and turn off the busy cursor */
  1375.     if (pg_win != NULL) {
  1376.       unbusyCursor();
  1377.       XSelectInput(XtDisplay(w),pg_win,oldEmask);
  1378.     }
  1379.  
  1380.   }
  1381. }
  1382.  
  1383. /************************************************************************
  1384.  *        Action Procedures                    *
  1385.  ***********************************************************************/
  1386.  
  1387. static void actionLineAnchor(w, event, params, num_params)
  1388.      DviPageWidget w;
  1389.      XEvent *event;
  1390.      String *params;
  1391.      Cardinal *num_params;
  1392. {
  1393.   XGCValues    values;
  1394.   unsigned long fore = w -> dviPage.foreground;
  1395.   unsigned long aft = w -> dviPage.background;
  1396.   
  1397.   if ( ! w -> dviPage.scalePopup ) {
  1398.     w -> dviPage.scalePopup =
  1399.       XtCreatePopupShell("scale",
  1400.              POPUP_WINDOW_TYPE, (Widget) w,
  1401.              NULL, 0);
  1402.  
  1403.     w -> dviPage.scaleLabel = (LabelWidget)
  1404.       XtCreateManagedWidget("label",
  1405.                 labelWidgetClass, w -> dviPage.scalePopup,
  1406.                 NULL, 0);
  1407.   }
  1408.   XtPopup(w -> dviPage.scalePopup, XtGrabNone);
  1409.  
  1410.   if ( !event ) return ;
  1411.  
  1412.   if ( event -> type == ButtonPress || event -> type == ButtonRelease ) {
  1413.     XButtonEvent *xb = (XButtonEvent *) event;
  1414.     w -> dviPage.anchorFromX = xb -> x;
  1415.     w -> dviPage.anchorFromY = xb -> y;
  1416.     w -> dviPage.anchored = True;
  1417.   }
  1418.   
  1419.  
  1420. static void actionLineCastOff(w, event, params, num_params)
  1421.      DviPageWidget w;
  1422.      XEvent *event;
  1423.      String *params;
  1424.      Cardinal *num_params;
  1425. {
  1426.   if ( w -> dviPage.scalePopup ) XtPopdown( w -> dviPage.scalePopup );
  1427.   /* un-anchor line ? */
  1428.   w -> dviPage.anchored = False;
  1429. }
  1430.  
  1431. static void actionLineCommon(draw, w, event, params, num_params)
  1432.      int draw;
  1433.      DviPageWidget w;
  1434.      XEvent *event;
  1435.      String *params;
  1436.      Cardinal *num_params;
  1437. {
  1438.   int fx = w -> dviPage.anchorFromX;
  1439.   int fy = w -> dviPage.anchorFromY;
  1440.   int tx;
  1441.   int ty;
  1442.   int st;
  1443.   double xValue, yValue;
  1444.   char *units;
  1445.  
  1446.   char buff[128];
  1447.  
  1448.   Arg argList[20];
  1449.   int args = 0;
  1450.   
  1451.   if ( !event || ! w -> dviPage.anchored ) return ;
  1452.   
  1453.   switch( event -> type ) {
  1454.   case ButtonPress:
  1455.   case ButtonRelease:
  1456.     {
  1457.       XButtonEvent *xb = (XButtonEvent *) event;
  1458.       tx = xb -> x; ty = xb -> y;
  1459.     }
  1460.     break;
  1461.     
  1462.   case MotionNotify:
  1463.     {
  1464.       XMotionEvent *xb = (XMotionEvent *) event;
  1465.       tx = xb -> x; ty = xb -> y;
  1466.     }
  1467.     break;
  1468.     
  1469.     default:
  1470.     return;
  1471.   }
  1472.   
  1473.   
  1474.   if ( draw ) {
  1475.     w -> dviPage.anchorToX = tx;
  1476.     w -> dviPage.anchorToY = ty;
  1477.   }
  1478.   
  1479.   tx = w -> dviPage.anchorToX;
  1480.   ty = w -> dviPage.anchorToY;
  1481.   
  1482.   XDrawLine(XtDisplay(w), XtWindow(w),
  1483.         w -> dviPage.invertGC, fx, fy, tx, ty);
  1484.   XDrawLine(XtDisplay(w), XtWindow(w),
  1485.         w -> dviPage.invertGC, tx, 0, tx, w -> core.height);
  1486.   XDrawLine(XtDisplay(w), XtWindow(w),
  1487.         w -> dviPage.invertGC, 0, ty, w -> core.width, ty);
  1488.  
  1489.   st = (int) w -> dviPage.units;
  1490.   units = ScaleUnitsString[ st ];
  1491.  
  1492.   xValue = ABS(tx-fx);
  1493.   xValue *= w -> dviPage.spPerDot;
  1494.   xValue /= ScaleUnitsInSp[ st ];
  1495.  
  1496.   yValue = ABS(ty-fy);
  1497.   yValue *= w -> dviPage.spPerDot;
  1498.   yValue /= ScaleUnitsInSp[ st ];
  1499.  
  1500.  
  1501.   sprintf(buff, "%4.2f %s, %4.2f %s",
  1502.       xValue, units, yValue, units);
  1503.  
  1504.   args = 0;
  1505.   XtSetArg(argList[args], XtNlabel, buff); args++;
  1506.   XtSetValues( (Widget) w -> dviPage.scaleLabel, argList, args);
  1507.  
  1508. static void actionLineDraw(w, event, params, num_params)
  1509.      DviPageWidget w;
  1510.      XEvent *event;
  1511.      String *params;
  1512.      Cardinal *num_params;
  1513. {
  1514.   actionLineCommon(1, w, event, params, num_params);
  1515.  
  1516. static void actionLineUnDraw(w, event, params, num_params)
  1517.      DviPageWidget w;
  1518.      XEvent *event;
  1519.      String *params;
  1520.      Cardinal *num_params;
  1521. {
  1522.   actionLineCommon(0, w, event, params, num_params);
  1523.  
  1524. static void actionLineUnits(w, event, params, num_params)
  1525.      Widget w;
  1526.      XEvent *event;
  1527.      String *params;
  1528.      Cardinal *num_params;
  1529. {
  1530.   if ( *num_params == 1 ) {
  1531.  
  1532.     DviPageWidget ww;
  1533.  
  1534.     while ( XtClass(w) != dviPageWidgetClass ) {
  1535.       if ( XtIsWidget(w) ) {
  1536.     w = XtParent(w);
  1537.       } else if ( XtIsObject(w) ) {
  1538.     w = ( (Object) w ) -> object.parent; 
  1539.       }
  1540.       if ( ! w ) return;
  1541.     }
  1542.  
  1543.     ww = (DviPageWidget) w;
  1544.  
  1545.     ww -> dviPage.units = stringToScaleUnits( *params );
  1546.   }
  1547.   else {
  1548.     error(0,0,"Bogus number of parameters specified to dvi-line-units: %d",
  1549.       *num_params);
  1550.   }
  1551.  
  1552. /* 
  1553.  *
  1554.  * This routine chhoses which type of postscript rendering to chhose
  1555.  * It will set at most one of these variables to True.
  1556.  * xtexResources.useGhostScript, xtexResources.useDPS, xtexResources.useNEWS
  1557.  *
  1558.  * We choose to use DPS then NEWS then GhostScript if they are available
  1559.  * unless the user has specified GhostScript on the command line or in
  1560.  * a resource.
  1561.  */
  1562.  
  1563. checkExtensions(){
  1564.  
  1565. static int called=0;
  1566.  
  1567.   if( called ) return ;
  1568.  
  1569.   called =1;
  1570.  
  1571.   if( xtexResources.useGhostScript ){
  1572.     /* either it is all we have or the use specified it */
  1573.     xtexResources.useDPS = xtexResources.useNEWS = False;
  1574.     return;
  1575.   }
  1576.  
  1577. #if defined(HAVE_DPS) 
  1578.     if( checkDPS() ){
  1579.     xtexResources.useDPS = True;
  1580.     xtexResources.useNEWS = xtexResources.useGhostScript = False;
  1581.     return;
  1582.     }else{
  1583.     xtexResources.useDPS = False;
  1584.     }
  1585. #endif
  1586.  
  1587. #if defined(HAVE_NEWS)
  1588.     if( checkNEWS() ){
  1589.     xtexResources.useNEWS = True;
  1590.     xtexResources.useDPS = xtexResources.useGhostScript = False;
  1591.     return;
  1592.     }else{
  1593.     xtexResources.useNEWS = False;
  1594.     }
  1595. #endif
  1596.  
  1597. #if defined(HAVE_GHOSTSCRIPT)
  1598.   if( xtexResources.showPostScript ){
  1599.      xtexResources.useGhostScript=True;  
  1600.      xtexResources.useDPS= xtexResources.useNEWS=False;  
  1601.      return;
  1602.   }
  1603. #endif
  1604.  
  1605. /* if we fall through to here it means that we can't (or won't) 
  1606.  * use anything to render postscript
  1607.  */
  1608.  
  1609.   xtexResources.showPostScript = False;
  1610.  
  1611. }
  1612.