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 / Texsun / texsun.c < prev    next >
C/C++ Source or Header  |  1991-02-19  |  53KB  |  2,290 lines

  1. /*
  2.  * Copyright 1989 Dirk Grunwald
  3.  *
  4.  *    Alan Kent, Dept. of Computer Science, RMIT, Melbourne, Aus.
  5.  *    added the th first version of marking and printing marked pages,
  6.  *    as well as the ``goto page'' menu.
  7.  * 
  8.  * Permission to use, copy, modify, distribute, and sell this software
  9.  * and its documentation for any purpose is hereby granted without fee,
  10.  * provided that the above copyright notice appear in all copies and that
  11.  * both that copyright notice and this permission notice appear in
  12.  * supporting documentation, and that the name of Dirk Grunwald or M.I.T.
  13.  * not be used in advertising or publicity pertaining to distribution of
  14.  * the software without specific, written prior permission.  Dirk
  15.  * Grunwald and M.I.T. makes no representations about the suitability of
  16.  * this software for any purpose.  It is provided "as is" without express
  17.  * or implied warranty.
  18.  * 
  19.  * DIRK GRUNWALD AND M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  20.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  21.  * FITNESS, IN NO EVENT SHALL M.I.T.  BE LIABLE FOR ANY SPECIAL, INDIRECT
  22.  * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  23.  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  24.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  25.  * OR PERFORMANCE OF THIS SOFTWARE.
  26.  * 
  27.  * Author:
  28.  *     Dr. Dirk Grunwald
  29.  *     Dept. of Computer Science
  30.  *     Campus Box 430
  31.  *     Univ. of Colorado, Boulder
  32.  *     Boulder, CO 80309
  33.  * 
  34.  *     grunwald@colorado.edu
  35.  *     
  36.  */
  37.  
  38. #include <sys/types.h>
  39. #include <stdio.h>
  40. #include <ctype.h>
  41. #include <sys/file.h>
  42. #include <sys/ioctl.h>
  43. #include <sys/types.h>
  44. #include <sys/timeb.h>
  45. #include <sun/fbio.h>
  46.  
  47. #include <sunwindow/defaults.h>
  48. #include <suntool/sunview.h>
  49. #include <suntool/canvas.h>
  50. #include <suntool/scrollbar.h>
  51. #include <suntool/wmgr.h>
  52.  
  53. #include "libtex/dvistuff.h"
  54. /*
  55.  *    These constants may need to be changed on your implementation
  56.  */
  57. static char *rcsid="$Header: /home/reed/grunwald/Uiuctex/drivers/RCS/texsun.c,v 1.1 89/04/15 18:15:36 grunwald Exp Locker: grunwald $" ;
  58.  
  59. /*
  60.  *    Note that ROUNDUP evaluates Y twice.
  61.  */
  62. #define ROUNDUP(x,y) (((x)+(y)-1) / (y))
  63.  
  64. #define DEBUG printf
  65.  
  66. #define INFORM (Debug > 2)
  67. #define TALK (Debug > 1)
  68. #define VERBOSE (Debug > 0)
  69.  
  70. int Debug = 0;
  71. static int  obscured = 1;
  72.  
  73. /*
  74.  *    Check to see if we're running SunView 4.0 -- only there do they
  75.  *    define the ACTION commands.
  76.  */
  77.  
  78. #ifdef ACTION_NULL_EVENT
  79. #define SUNOS4
  80. #endif
  81.  
  82.  
  83. /*
  84.  *    SunTools related variables
  85.  */
  86.  
  87. static int rootFd;
  88.  
  89. static Window frame = 0;
  90. static char frameLabel[256];
  91. static char *frameLabelName;
  92.  
  93. /*
  94.  *    TeXSun Icon
  95.  */
  96.  
  97. #define MY_ICON_WIDTH    64
  98. #define MY_ICON_WIDTH    64
  99. static short ic_image[256] = {
  100. #include "texsun.icon"
  101. };
  102. mpr_static(texsunIcon_mpr, 64, 64, 1, ic_image);
  103. static    struct icon icon = {64, 64, (struct pixrect *)NULL, 0, 0, 64, 64,
  104.         &texsunIcon_mpr, 0, 0, 0, 0, NULL, (struct pixfont *)NULL,
  105.         ICON_BKGRDCLR};
  106.  
  107. static int clearMode;
  108. static int setMode;
  109. static int copyMode;
  110. static int paintMode;
  111. static int cursorMode;
  112.  
  113. /*
  114.  *    Menu related things
  115.  */
  116.  
  117. Menu menuMain;
  118. Menu menuFrame;
  119. Menu menuGoto;
  120. Menu menuPrint;
  121. Menu menuDocument;
  122.  
  123. char *M_MAIN_FORWARD = "Next Page";
  124. char *M_MAIN_2FORWARD = "Skip 2 Pages";
  125. char *M_MAIN_BACKWARD = "Back a Page";
  126. char *M_MAIN_2BACKWARD = "Back 2 Pages";
  127. char *M_MAIN_QUIT = "Quit";
  128. char *M_MAIN_GOTO = "Goto Page";
  129. char *M_MAIN_DOCUMENT = "Document";
  130. char *M_MAIN_PRINT = "Mark & Print";
  131.  
  132. char *M_DOCUMENT_AGAIN = "Reload File";
  133. char *M_DOCUMENT_INSPECT = "Detail View";
  134. char *M_DOCUMENT_OVERVIEW = "Overview";
  135. char *M_DOCUMENT_EXPOSE = "Expose";
  136. char *M_DOCUMENT_ZOOM = "Zoom";
  137. char *M_DOCUMENT_UNZOOM = "Un-Zoom";
  138.  
  139. char *M_PRINT_MARK = "Mark Page";
  140. char *M_PRINT_LMARK = "Mark Left";
  141. char *M_PRINT_RMARK = "Mark Right";
  142. char *M_PRINT_UNMARK = "Unmark Page";
  143. char *M_PRINT_LUNMARK = "Unmark Left";
  144. char *M_PRINT_RUNMARK = "Unmark Right";
  145. char *M_PRINT_MARKALL = "Mark all";
  146. char *M_PRINT_UNMARKALL = "Unmark all";
  147. char *M_PRINT_PRALL = "Print All";
  148. char *M_PRINT_PRMARKED = "Print Marked";
  149. char *M_PRINT_PRUNMARKED = "Print Unmarked";
  150.  
  151. #define MV_MAIN_FORWARD        1
  152. #define MV_MAIN_BACKWARD    2
  153. #define MV_MAIN_2FORWARD    3
  154. #define MV_MAIN_2BACKWARD    4
  155. #define MV_MAIN_QUIT        11
  156. #define MV_MAIN_GOTO        12
  157. #define MV_MAIN_PRINT        20
  158.  
  159. #define MV_PRINT_PRALL        100
  160. #define MV_PRINT_PRMARKED    101
  161. #define MV_PRINT_PRUNMARKED    102
  162. #define MV_PRINT_MARKALL    103
  163. #define MV_PRINT_UNMARKALL    104
  164. #define MV_PRINT_LMARK        113
  165. #define MV_PRINT_RMARK        114
  166. #define MV_PRINT_LUNMARK    115
  167. #define MV_PRINT_RUNMARK    116
  168.  
  169. #define MV_DOCUMENT_AGAIN        205
  170. #define MV_DOCUMENT_INSPECT        206
  171. #define MV_DOCUMENT_OVERVIEW        207
  172. #define MV_DOCUMENT_EXPOSE        208
  173. #define MV_DOCUMENT_ZOOM        209
  174. #define MV_DOCUMENT_UNZOOM        210
  175.  
  176. /*
  177.  *    Scroll-bar related things.
  178.  */
  179. Scrollbar scrollLeft;
  180. Scrollbar scrollBottom;
  181.  
  182. /*
  183.  *    Variables use to keep track of where we are in the document
  184.  */
  185.  
  186. static int globalArg = 0;
  187. static int globalNumber = 0;
  188. static int globalSign = 1;
  189. static int globalLeaf = 0;
  190. static int globalLeafX;
  191. static int globalLeafY;
  192. static Event globalEvent;
  193. static int globalDisplayState;
  194. static Canvas globalCanvas;
  195.     
  196. #define BOGUSDIR -1
  197. #define FOREWARD 0
  198. #define BACKWARD 1
  199. #define ABSOLUTE 2
  200. static int globalDirection;
  201.  
  202. static int autoReload = 0;
  203. static int autoFit = 1;
  204.  
  205. static int firstPage = 0;
  206.  
  207. static Cursor workingCursor;
  208. static Cursor readyCursor;
  209.  
  210. static char *texsunPrint;
  211. static char *defaultTexsunPrint = "lpr -d";    /* DEFAULT */
  212.  
  213. short workingCursorData[] = {
  214. #include <images/hglass.cursor>
  215. };
  216. mpr_static(workingCursorPixrect, 16, 16, 1, workingCursorData);
  217.  
  218. short readyCursorData[] = {
  219. #include <images/bullseye.cursor>
  220. };
  221. mpr_static(readyCursorPixrect, 16, 16, 1, readyCursorData);
  222.  
  223. /*
  224.  *    TeX-Dvi related variables
  225.  */
  226.  
  227. static int rawDviHeight;
  228. static int rawDviWidth;    /* part of X interface, not dvistuff */
  229. static int maxHeight;
  230. static int maxWidth;
  231. static int maxDepth;
  232.  
  233. static int  screenWidth, screenHeight;
  234.  
  235. #define MAX_LEAVES    2
  236. #define LEAF_LEFT    0
  237. #define LEAF_RIGHT    1
  238.  
  239. #define DEFAULT_LEAVES    2
  240.  
  241. #define SHRINK_NORMAL    0
  242. #define SHRINK_LARGE    1
  243. #define MAX_SHRINKS    2
  244.  
  245. /*
  246.  *    Canvas for looking at the document
  247.  */
  248.  
  249. static Canvas normalCanvas[MAX_LEAVES];
  250. static Canvas largeCanvas;
  251.  
  252. static Pixwin *pasteUpPixwin[MAX_SHRINKS][MAX_LEAVES];
  253. static int largePixwinsAllocated = 0;
  254.  
  255. /*
  256.  *    Routines associated with the canvas
  257.  */
  258.  
  259. void canvasSelected();
  260.  
  261. typedef (*intfuncp)();
  262. int selectLarge();
  263. int selectOne();
  264. int selectTwo();
  265. static intfuncp whichCanvasSelected[MAX_LEAVES] = {selectOne, selectTwo};
  266.  
  267. void largeCanvasRepaint();
  268. void largeCanvasResize();
  269.  
  270. static int Leaves;
  271. static int currentLeaf = 0;
  272. static int pageOnLeaf[MAX_LEAVES] = {-1,-1};
  273. static int havePage[MAX_SHRINKS][MAX_LEAVES] = {0, 0, 0, 0};
  274.  
  275. static int page_w[MAX_SHRINKS], page_h[MAX_SHRINKS];
  276. static int leaf_w[MAX_SHRINKS];
  277.  
  278. /*
  279.  *    Note: these are used by dvi_draw.c, and are not static
  280.  */
  281. int shrinkFactor[MAX_SHRINKS];
  282. int currentShrink;
  283.  
  284. static struct glyph **shrunkenGlyphs[MAX_SHRINKS][MAX_FONTFAMILY];
  285.  
  286. typedef struct mpr_data MprData;
  287. static Pixrect **shrunkenPixrect[MAX_SHRINKS][MAX_FONTFAMILY];
  288.  
  289. static int reverse = 0;
  290.  
  291. static double specialConv;
  292.  
  293. char **globalArgv;
  294. int globalArgc;
  295.  
  296. /*
  297.  *    Subroutine declerations
  298.  */
  299.  
  300. char *malloc(), *calloc(), *index();
  301. static void buildLeaf();
  302.  
  303. #define MAXFUNC(a,b) ((a) < (b)) ? (b) : (a)
  304. #define MINFUNC(a,b) ((a) < (b)) ? (a) : (b)
  305. #define ABSFUNC(a) ( (a) < 0 ? (-(a)) : (a))
  306. #define SWAPINT(a,b) {int xxxtmp = a; a = b; b = xxxtmp;}
  307.  
  308. stop_output()
  309. {
  310.     window_set(frame, FRAME_NO_CONFIRM, TRUE, 0);
  311.     window_destroy (frame);
  312.     dviFini();
  313.     exit (0);
  314. }
  315.  
  316. main(argc, argv)
  317.     int argc;
  318.     char **argv;
  319. {
  320.     int xargc=argc;
  321.     char **xargv=argv;
  322.     int i;
  323.  
  324.     char *display = NULL;
  325.     char option[120];
  326.     int optionEnd;
  327.     char *poption;
  328.  
  329.     char *rootFdName[WIN_NAMESIZE];
  330.     
  331.     int bwidth = 2;
  332.     char *geometry = NULL, def[32];
  333.     
  334.     int bdrpix, mouspix;
  335.     unsigned long xswattrs_mask;
  336.  
  337.     double topMargin;
  338.     double sideMargin;
  339.  
  340.     struct rect frame_rect;
  341.  
  342.     double atof();
  343.     char *getenv();
  344.  
  345.     char *ptr;
  346.     
  347. /*
  348.  *    Choose an explicit name so we always find the options.
  349.  */
  350.  
  351.     ProgName = "texsun";
  352.     argv++;
  353.     argc--;
  354.     DVIFileName = NULL;
  355.  
  356.     strcpy(option, ProgName);
  357.     sprintf(option,"/%s/", ProgName);
  358.     optionEnd = strlen(option);
  359.     option[optionEnd] = 0;
  360.     reverse = (int) defaults_get_boolean(strcat(option,"ReverseVideo"), 0, 0);
  361.  
  362.     option[optionEnd] = 0;
  363.     shrinkFactor[SHRINK_NORMAL] =
  364.     defaults_get_integer(strcat(option,"NormalShrink"), 0, 0);
  365.  
  366.     option[optionEnd] = 0;
  367.     shrinkFactor[SHRINK_LARGE] =
  368.     defaults_get_integer(strcat(option,"LargeShrink"), 0, 0);
  369.  
  370.     option[optionEnd] = 0;
  371.     dviDPI = defaults_get_integer(strcat(option,"Dpi"), DEFAULT_DPI, 0);
  372.  
  373.     option[optionEnd] = 0;
  374.     Leaves = defaults_get_integer(strcat(option,"Leaves"), 0, 0);
  375.  
  376.     option[optionEnd] = 0;
  377.     poption = defaults_get_string(strcat(option,"TopMargin"), 0, 0);
  378.     topMargin = ( (poption == 0) ? 1.0 : atof(poption));
  379.  
  380.     option[optionEnd] = 0;
  381.     poption = defaults_get_string(strcat(option,"SideMargin"), 0, 0);
  382.     sideMargin = ( (poption == 0) ? 1.0 : atof(poption));
  383.  
  384.     option[optionEnd] = 0;
  385.     dviBlackness = defaults_get_integer(strcat(option,"Blackness"),
  386.                     DEFAULT_BLACKNESS, 0);
  387.     optionEnd = strlen(option);
  388.     option[optionEnd] = 0;
  389.     autoReload = (int) defaults_get_boolean(strcat(option,"AutoReload"), 0, 0);
  390.  
  391.     optionEnd = strlen(option);
  392.     option[optionEnd] = 0;
  393.     autoFit = (int) defaults_get_boolean(strcat(option,"AutoFit"), autoFit, 0);
  394.  
  395.     optionEnd = strlen(option);
  396.     option[optionEnd] = 0;
  397.     texsunPrint = (char *) defaults_get_string(strcat(option,"TeXsunPrint"), texsunPrint, 0);
  398.  
  399.     globalArgc = argc;
  400.     globalArgv = argv;
  401.  
  402.     while (argc) {
  403.     if (strcmp(*argv, "-rv") == 0) {
  404.         reverse = !reverse;
  405.     } else if (strcmp(*argv, "-rvOn") == 0 ) {
  406.         reverse = 1;
  407.     } else if (strcmp(*argv, "-rvOff") == 0) {
  408.         reverse = 0;
  409.     } else if (strcmp(*argv,"-l") == 0 && argc > 1) {
  410.         argv++;
  411.         argc--;
  412.         Leaves = atoi(*argv);
  413.         if( Leaves < 1 || Leaves > MAX_LEAVES) {
  414.         fprintf(stderr,"[%s] Bad number of leaves(%d), using %d\n",
  415.             ProgName, Leaves, MAX_LEAVES);
  416.         Leaves = MAX_LEAVES;
  417.         }
  418.     } else if (strcmp(*argv,"-ns") == 0 && argc > 1) {
  419.         argv++;
  420.         argc--;
  421.         shrinkFactor[SHRINK_NORMAL] = atoi(*argv);
  422.     } else if (strcmp(*argv,"-ls") == 0 && argc > 1) {
  423.         argv++;
  424.         argc--;
  425.         shrinkFactor[SHRINK_LARGE] = atoi(*argv);
  426.     } else if (strcmp(*argv,"-dpi") == 0 && argc > 1) {
  427.         argv++;
  428.         argc--;
  429.         dviDPI = atoi(*argv);
  430.     } else if (strcmp(*argv,"-tm") == 0 && argc > 1) {
  431.         argv++;
  432.         argc--;
  433.         topMargin = atof(*argv);
  434.     } else if (strcmp(*argv,"-sm") == 0 && argc > 1) {
  435.         argv++;
  436.         argc--;
  437.         sideMargin = atof(*argv);
  438.     } else if (strcmp(*argv, "-bl") == 0 && argc > 1) {
  439.         argv++;
  440.         argc--;
  441.         dviBlackness = atoi(*argv);
  442.     } else if (strcmp(*argv, "-pg") == 0 && argc > 1) {
  443.         argv++;
  444.         argc--;
  445.         firstPage = atoi(*argv);
  446.     } else if (strcmp(*argv,"-autoReload") == 0) {
  447.         autoReload = ! autoReload;
  448.     } else if (strcmp(*argv,"-autoFit") == 0) {
  449.         autoFit = !autoFit;
  450.     } else if (strcmp(*argv,"-debug") == 0 && argc > 1) {
  451.         argv++;
  452.         argc--;
  453.         Debug = atoi(*argv);
  454.     } else if (**argv != '-') {
  455.         DVIFileName = *argv;
  456.     } else {
  457.     usage:
  458.         fprintf(stderr, "Usage: %s    [-ns <shrink>] [-ls <shrink>] [-dpi <dots>] \n",
  459.             ProgName);
  460.         fprintf(stderr, "        [-l <leaves>] [-rv] [-tm <inches>] [-sm <inches>]  dviFile\n");
  461.         exit(1);
  462.     }
  463.     argv++;
  464.     argc--;
  465.     }
  466.  
  467.     if (DVIFileName == NULL)
  468.     goto usage;
  469.  
  470. /*
  471.  *    Set things which depend on DPI
  472.  */
  473.  
  474.     dviHHMargin = dviDPI * sideMargin;
  475.     dviVVMargin = dviDPI * topMargin;
  476.  
  477.     if (INFORM) {
  478.     fprintf(stderr, "[texsun] call dviInit();\n");
  479.     }
  480.  
  481.     if (dviInit()) {
  482.     dviFini();
  483.     exit(1);
  484.     }
  485.  
  486.     if (TALK) {
  487.     fprintf(stderr,"page is %d wide, %d high\n",
  488.         dviTallestPage, dviWidestPage);
  489.     }
  490.  
  491.     if (((double) dviTallestPage * (double) dviWidestPage) > 4.0e7) {
  492.     fprintf(stderr,"[%s] Warning: Your page size is %d wide and %d tall,\n",
  493.         ProgName, dviTallestPage, dviWidestPage);
  494.     fprintf(stderr,"which may be too big to be displayed\n");
  495.     }
  496.  
  497.     specialConv = (double) dviDPI / 1000.0;
  498.     
  499. /*
  500.  *    If no shrink factor was chosen, pick one which will work out nicely
  501.  *    on their display
  502.  */
  503.     if (INFORM) {
  504.     fprintf(stderr, "[texsun] set screenSpecific\n");
  505.     }
  506.  
  507.     setScreenSpecifics();
  508.     
  509.     rawDviHeight = dviTallestPage + 2 * dviVVMargin;
  510.     rawDviWidth  = dviWidestPage + 2 * dviHHMargin;
  511.     
  512.     if (Leaves == 0) {
  513.     if (dviTotalPages == 1) {
  514.         Leaves = 1;
  515.     } else {
  516.         Leaves = DEFAULT_LEAVES;
  517.     }
  518.     }
  519.  
  520.     if (INFORM) {
  521.     fprintf(stderr, "[texsun] choose screenSpecific\n");
  522.     }
  523.  
  524.     if (shrinkFactor[SHRINK_NORMAL] == 0) {
  525.     int sH;
  526.     int sW;
  527.     int sH2;
  528.     int sW2;
  529.     int shrink2;
  530.     
  531.     sH = (rawDviHeight + maxHeight - 1) / maxHeight;
  532.     sW = (Leaves * rawDviWidth  + maxWidth - 1) / maxWidth;
  533.     
  534.     shrinkFactor[SHRINK_NORMAL] = MAXFUNC(sW, sH);
  535.     shrinkFactor[SHRINK_NORMAL] = MAXFUNC(shrinkFactor[SHRINK_NORMAL], 1);
  536.     
  537. /*
  538.  *    Check to see if we can get another shrink size bigger display
  539.  *    if we cut the margins.
  540.  */
  541.     
  542.     sH2 = (dviTallestPage + (dviHHMargin/32) + maxHeight - 1)
  543.         / maxHeight;
  544.     sW2 = ( Leaves * (dviWidestPage + (dviVVMargin/32))
  545.            + maxHeight - 1) / maxHeight;
  546.     
  547.     shrink2 = MAXFUNC(sH2, sW2);
  548.     shrink2 = MAXFUNC(shrink2, 1);
  549.     
  550.     if (shrink2 < shrinkFactor[SHRINK_NORMAL]) {
  551.         dviVVMargin /= 32;
  552.         dviHHMargin /= 32;
  553.         rawDviHeight = dviTallestPage + 2 * dviVVMargin;
  554.         rawDviWidth  = dviWidestPage + 2 * dviHHMargin;
  555.         shrinkFactor[SHRINK_NORMAL] = shrink2;
  556.     }
  557.     }
  558.     
  559.     page_h[SHRINK_NORMAL]=(rawDviHeight + shrinkFactor[SHRINK_NORMAL] - 1)
  560.     / shrinkFactor[SHRINK_NORMAL];
  561.     leaf_w[SHRINK_NORMAL]=(rawDviWidth + shrinkFactor[SHRINK_NORMAL] - 1)
  562.     / shrinkFactor[SHRINK_NORMAL];
  563.  
  564. /*
  565.  *    Based on the shrink factor, choose a shrink factor for the enlarged
  566.  *    display
  567.  */
  568.  
  569.     if (shrinkFactor[SHRINK_LARGE] == 0) {
  570.     shrinkFactor[SHRINK_LARGE] = shrinkFactor[SHRINK_NORMAL] / 2;
  571.     }
  572.  
  573.     shrinkFactor[SHRINK_LARGE] = MINFUNC(shrinkFactor[SHRINK_LARGE],
  574.                      shrinkFactor[SHRINK_NORMAL]-1);
  575.     shrinkFactor[SHRINK_LARGE] = MAXFUNC(shrinkFactor[SHRINK_LARGE], 1);
  576.  
  577.     page_h[SHRINK_LARGE]=(rawDviHeight + shrinkFactor[SHRINK_LARGE] - 1)
  578.     / shrinkFactor[SHRINK_LARGE];
  579.     leaf_w[SHRINK_LARGE]=(rawDviWidth + shrinkFactor[SHRINK_LARGE] - 1)
  580.     / shrinkFactor[SHRINK_LARGE];
  581.  
  582. /*
  583.  *    Compute the page size given the number of leaves. We may have
  584.  *    to scale back if everything cant fit.
  585.  */
  586.     
  587.     if (leaf_w[SHRINK_NORMAL] * Leaves <= maxWidth) {
  588.     page_w[SHRINK_NORMAL] = leaf_w[SHRINK_NORMAL] * Leaves;
  589.     } else {
  590.     page_w[SHRINK_NORMAL] = leaf_w[SHRINK_NORMAL];
  591.     Leaves = 1;
  592.     }
  593.     
  594.     screenWidth = (page_w[SHRINK_NORMAL] > maxWidth)
  595.     ? maxWidth : page_w[SHRINK_NORMAL];
  596.     screenHeight = (page_h[SHRINK_NORMAL] > maxHeight)
  597.     ? maxHeight : page_h[SHRINK_NORMAL];
  598.  
  599.     if (INFORM) {
  600.     fprintf(stderr,"[texsun] create the frame windows\n");
  601.     }
  602.  
  603. /*
  604.  *    This is an assumption about the window environment.
  605.  */
  606.     
  607.     (void)we_getparentwindow(rootFdName);
  608.     if ((rootFd = open(rootFdName, 0)) < 0) {
  609.     (void)fprintf(stderr, "%s: can't open root window %s\n",
  610.               ProgName, rootFdName);
  611.     dviFini();
  612.     exit(1);
  613.     }
  614.  
  615.     /* Create the short file name by pointing to the last part of */
  616.     /* the filename */
  617.  
  618.     frameLabelName = &DVIFileName[ strlen(DVIFileName) - 1 ];
  619.     while( frameLabelName != DVIFileName && *frameLabelName != '/' ) {
  620.       frameLabelName--;
  621.     }
  622.  
  623.     if (frameLabelName != DVIFileName && *frameLabelName == '/') {
  624.       frameLabelName++;
  625.     }
  626.  
  627. /* create the frame */
  628.     sprintf(frameLabel,"TeXsun : %s, (%4.2f by %4.2f)",
  629.         frameLabelName,
  630.         (float) ((float) rawDviWidth / ( (float) dviDPI)),
  631.         (float) ((float) rawDviHeight / ( (float) dviDPI)) );
  632.  
  633.     
  634.     frame = window_create (0, FRAME,
  635.                FRAME_LABEL, frameLabel,
  636.                FRAME_ICON, &icon,
  637.                FRAME_DONE_PROC, stop_output,
  638.                FRAME_SUBWINDOWS_ADJUSTABLE, FALSE,
  639.                WIN_X, 0,
  640.                WIN_Y, 0,
  641.                WIN_WIDTH, page_w[SHRINK_NORMAL],
  642.                WIN_HEIGHT, page_h[SHRINK_NORMAL],
  643.               0);
  644.     if (frame == 0) {
  645.     fprintf(stderr,"Unable to create window\n");
  646.     dviFini();
  647.     exit(1);
  648.     }
  649.  
  650.     if (reverse) {
  651.     clearMode = PIX_NOT(PIX_COLOR(1) | PIX_CLR);
  652.     setMode = PIX_NOT(PIX_COLOR(0) | PIX_SET);
  653.     copyMode = PIX_SRC;
  654.     paintMode = PIX_NOT(PIX_SRC) & PIX_DST;
  655.     cursorMode = PIX_SRC ^ PIX_DST;
  656.     } else {
  657.     clearMode = PIX_COLOR(1) | PIX_CLR;
  658.     setMode = PIX_COLOR(0) | PIX_SET;
  659.     copyMode = PIX_SRC;
  660.     paintMode = PIX_SRC | PIX_DST;
  661.     cursorMode = PIX_SRC ^ PIX_DST;
  662.     }
  663.  
  664.  
  665.     readyCursor = cursor_create(CURSOR_IMAGE, &readyCursorPixrect,
  666.                 CURSOR_OP, cursorMode, 0);
  667.     workingCursor = cursor_create(CURSOR_IMAGE, &workingCursorPixrect,
  668.                   CURSOR_OP, cursorMode, 0);
  669.  
  670.     initMarks();
  671.  
  672.     menuPrint = menu_create(0);
  673.  
  674.     if (Leaves == 1) {
  675.       menu_set( menuPrint,
  676.            MENU_STRING_ITEM, M_PRINT_MARK, MV_PRINT_LMARK,
  677.            MENU_STRING_ITEM, M_PRINT_UNMARK, MV_PRINT_LUNMARK,
  678.            0);
  679.     } else {
  680.       menu_set( menuPrint,
  681.            MENU_STRING_ITEM, M_PRINT_LMARK, MV_PRINT_LMARK,
  682.            MENU_STRING_ITEM, M_PRINT_RMARK, MV_PRINT_RMARK,
  683.            MENU_STRING_ITEM, M_PRINT_LUNMARK, MV_PRINT_LUNMARK,
  684.            MENU_STRING_ITEM, M_PRINT_RUNMARK, MV_PRINT_RUNMARK,
  685.            0);
  686.     }
  687.     menu_set( menuPrint,
  688.          MENU_STRING_ITEM, M_PRINT_MARKALL, MV_PRINT_MARKALL,
  689.          MENU_STRING_ITEM, M_PRINT_UNMARKALL, MV_PRINT_UNMARKALL,
  690.  
  691.          MENU_STRING_ITEM, M_PRINT_PRALL, MV_PRINT_PRALL,
  692.          MENU_STRING_ITEM, M_PRINT_PRMARKED, MV_PRINT_PRMARKED,
  693.          MENU_STRING_ITEM, M_PRINT_PRUNMARKED, MV_PRINT_PRUNMARKED,
  694.          0);
  695.  
  696.     menuDocument =
  697.       menu_create(
  698.           MENU_STRING_ITEM, M_DOCUMENT_INSPECT, MV_DOCUMENT_INSPECT,
  699.           MENU_ITEM,
  700.           MENU_STRING, M_DOCUMENT_OVERVIEW,
  701.           MENU_VALUE, MV_DOCUMENT_OVERVIEW,
  702.           MENU_INACTIVE, TRUE,
  703.           0,
  704.           MENU_STRING_ITEM, M_DOCUMENT_AGAIN, MV_DOCUMENT_AGAIN,
  705.           0);
  706.           
  707.                 
  708.     menuFrame = (Menu) window_get(frame, WIN_MENU);
  709.     if (Leaves == 1) {
  710.     menuMain =
  711.       menu_create(
  712.               MENU_STRING_ITEM, M_MAIN_FORWARD, MV_MAIN_FORWARD,
  713.               MENU_STRING_ITEM, M_MAIN_BACKWARD, MV_MAIN_BACKWARD,
  714.               MENU_PULLRIGHT_ITEM, M_MAIN_GOTO, menuGoto,
  715.               MENU_PULLRIGHT_ITEM, M_MAIN_DOCUMENT, menuDocument,
  716.               MENU_PULLRIGHT_ITEM, M_MAIN_PRINT, menuPrint,
  717.               MENU_PULLRIGHT_ITEM, "Frame", menuFrame,
  718.               MENU_STRING_ITEM, M_MAIN_QUIT, MV_MAIN_QUIT,
  719.               MENU_INITIAL_SELECTION, MENU_SELECTED,
  720.               MENU_INITIAL_SELECTION_SELECTED, TRUE,
  721. /*            MENU_JUMP_AFTER_SELECTION, TRUE, */
  722. /*            MENU_JUMP_AFTER_NO_SELECTION, TRUE, */
  723.               0);
  724.       } else {
  725.     menuMain =
  726.       menu_create(
  727.               MENU_STRING_ITEM, M_MAIN_FORWARD, MV_MAIN_FORWARD,
  728.               MENU_STRING_ITEM, M_MAIN_2FORWARD, MV_MAIN_2FORWARD,
  729.               MENU_STRING_ITEM, M_MAIN_BACKWARD, MV_MAIN_BACKWARD,
  730.               MENU_STRING_ITEM, M_MAIN_2BACKWARD, MV_MAIN_2BACKWARD,
  731.               MENU_PULLRIGHT_ITEM, M_MAIN_GOTO, menuGoto,
  732.               
  733.               MENU_PULLRIGHT_ITEM, M_MAIN_DOCUMENT, menuDocument,
  734.               
  735.               MENU_PULLRIGHT_ITEM, M_MAIN_PRINT, menuPrint,
  736.               
  737.               MENU_PULLRIGHT_ITEM, "Frame", menuFrame,
  738.               MENU_STRING_ITEM, M_MAIN_QUIT, MV_MAIN_QUIT,
  739.               
  740.               MENU_INITIAL_SELECTION, MENU_SELECTED,
  741.               MENU_INITIAL_SELECTION_SELECTED, TRUE,
  742.               /*
  743.             MENU_JUMP_AFTER_SELECTION, TRUE,
  744.             MENU_JUMP_AFTER_NO_SELECTION, TRUE,
  745.             */
  746.               0);
  747.     }
  748.  
  749.     allocatePixwins();
  750.  
  751.     for (i = 0; i < Leaves; i++) {
  752.     window_fit(normalCanvas[i]);
  753.     }
  754.     window_fit(frame);
  755.  
  756.     globalDisplayState = SHRINK_NORMAL;
  757.     dviCurrentPage = firstPage;
  758.  
  759.     for (i = 0; i < Leaves; i++) {
  760.     pageOnLeaf[i] = firstPage + i;
  761.     }
  762.  
  763.     displayLeaves();
  764.  
  765.     globalArg = 0;
  766.     globalNumber = 0;
  767.  
  768.     window_main_loop (frame);
  769.  
  770.     /* terminate frame */
  771.     stop_output(0);
  772. }
  773.  
  774. /*
  775.  *    Sun Screen-specific things
  776.  */
  777. setScreenSpecifics()
  778. {
  779.     struct fbtype FbType;
  780.     int Fb;    
  781.  
  782.     Fb = open("/dev/fb", O_RDONLY, 0);
  783.     
  784.     if (Fb < 0) {
  785.     perror("open");
  786.     fprintf(stderr,"Unable to open /dev/fb\n");
  787.     dviFini();
  788.     exit(1);
  789.     }
  790.     if (ioctl(Fb, FBIOGTYPE, &FbType) == -1) {
  791.     perror("ioctl");
  792.     fprintf(stderr,"Unable to determine screen size\n");
  793.     dviFini();
  794.     exit(1);
  795.     }
  796.  
  797.     maxWidth = FbType.fb_width;
  798.     maxHeight = FbType.fb_height;
  799.     maxDepth = FbType.fb_depth;
  800.  
  801.     close(Fb);
  802. }
  803. static void
  804. clearLeaf(leaf, shrinkSize)
  805. int leaf;
  806. int shrinkSize;
  807. {
  808.     Pixwin *w;
  809.     int i;
  810.  
  811.     if (leaf< 0 || leaf >= Leaves) {
  812.     fprintf(stderr,"[%s] Reference to bogus leaf in clearLeaf: %d\n",
  813.         ProgName, leaf);
  814.     stop_output();
  815.     exit(1);
  816.     }
  817.  
  818.     if (shrinkSize < 0 || shrinkSize >= MAX_SHRINKS ) {
  819.     fprintf(stderr,"[%s] reference to bogus shrink %d\n",
  820.         ProgName, shrinkSize);
  821.     stop_output();
  822.     exit(1);
  823.     }
  824.  
  825.     w = pasteUpPixwin[shrinkSize][leaf];
  826.  
  827.     i = pw_writebackground(w,
  828.                0, 0,
  829.                leaf_w[shrinkSize], page_h[shrinkSize],
  830.                clearMode);
  831.     if (Debug) {
  832.     printf("Clear the pixmap(%x) = %d\n", w, i);
  833.     }
  834. }
  835.  
  836. allocatePixwins()
  837. {
  838.     int i;
  839.     
  840.     largePixwinsAllocated = 0;
  841.     
  842.     for (i = 0; i < Leaves; i++ ) {
  843.     normalCanvas[i] = window_create(frame, CANVAS,
  844.                     CANVAS_AUTO_SHRINK, FALSE,
  845.                     CANVAS_AUTO_EXPAND, FALSE,
  846.                     CANVAS_WIDTH, leaf_w[SHRINK_NORMAL],
  847.                     CANVAS_HEIGHT, page_h[SHRINK_NORMAL],
  848.                     WIN_WIDTH, leaf_w[SHRINK_NORMAL],
  849.                     WIN_HEIGHT, page_h[SHRINK_NORMAL],
  850.                     CANVAS_RETAINED, TRUE,
  851.                     WIN_EVENT_PROC, whichCanvasSelected[i],
  852.                     WIN_BOTTOM_MARGIN, 0,
  853.                     WIN_LEFT_MARGIN, 0,
  854.                     WIN_TOP_MARGIN, 0,
  855.                     WIN_RIGHT_MARGIN, 0,
  856.  
  857.                     WIN_MENU, menuMain,
  858.  
  859.                     WIN_CONSUME_KBD_EVENT,
  860.                     WIN_TOP_KEYS,
  861.  
  862.                     WIN_CONSUME_KBD_EVENT,
  863.                     WIN_RIGHT_KEYS,
  864.  
  865.                     WIN_CONSUME_KBD_EVENT,
  866.                     WIN_LEFT_KEYS,
  867.  
  868.                     WIN_CONSUME_KBD_EVENT,
  869.                     WIN_ASCII_EVENTS,
  870.                     0);
  871.     
  872.     if (normalCanvas[i] == 0) {
  873.         fprintf(stderr,"Unable to create canvas\n");
  874.         dviFini();
  875.         stop_output();
  876.         exit(1);
  877.     }
  878.  
  879.     pasteUpPixwin[SHRINK_NORMAL][i] =
  880.         (Pixwin*) canvas_pixwin(normalCanvas[i]);
  881.  
  882.     clearLeaf(i, SHRINK_NORMAL);
  883.     
  884. /*
  885.  *    Lay out the windows
  886.  */
  887.     if (i > 0) {
  888.         window_set(normalCanvas[i],
  889.                WIN_RIGHT_OF, normalCanvas[i-1],
  890.                0);
  891.     }
  892.     }
  893. }
  894.  
  895. allocateLargePixwins()
  896. {
  897.     int i;
  898.     Pixwin *p;
  899.     int jj;
  900.     largeCanvas =  window_create(frame,
  901.                  CANVAS,
  902.                  CANVAS_AUTO_SHRINK, FALSE,
  903.                  CANVAS_AUTO_EXPAND, TRUE,
  904.                  CANVAS_WIDTH, leaf_w[SHRINK_LARGE],
  905.                  CANVAS_HEIGHT, page_h[SHRINK_LARGE],
  906.                  WIN_WIDTH, leaf_w[SHRINK_LARGE],
  907.                  WIN_HEIGHT, page_h[SHRINK_LARGE],
  908.                  CANVAS_RETAINED, TRUE,
  909.                  WIN_EVENT_PROC, selectLarge,
  910.                  WIN_VERTICAL_SCROLLBAR, scrollbar_create(0),
  911.                  WIN_HORIZONTAL_SCROLLBAR, scrollbar_create(0),
  912.                  WIN_BOTTOM_MARGIN, 0,
  913.                  WIN_LEFT_MARGIN, 0,
  914.                  WIN_TOP_MARGIN, 0,
  915.                  WIN_RIGHT_MARGIN, 0,
  916.                  WIN_SHOW, FALSE,
  917.  
  918.                  WIN_MENU, menuMain,
  919.                  
  920.                  WIN_CONSUME_KBD_EVENT,
  921.                  WIN_TOP_KEYS,
  922.                  
  923.                  WIN_CONSUME_KBD_EVENT,
  924.                  WIN_RIGHT_KEYS,
  925.                  
  926.                  WIN_CONSUME_KBD_EVENT,
  927.                  WIN_LEFT_KEYS,
  928.                  
  929.                  WIN_CONSUME_KBD_EVENT,
  930.                  WIN_ASCII_EVENTS,
  931.                  0);
  932.     window_fit(largeCanvas);
  933.  
  934.     p = (Pixwin*) canvas_pixwin(largeCanvas);
  935.  
  936.     for (jj = 0; jj < Leaves; jj++) {
  937.     pasteUpPixwin[SHRINK_LARGE][jj] = p;
  938.     }
  939.     clearLeaf(0, SHRINK_LARGE);    /* its both leaves, really */
  940.     largePixwinsAllocated = 1;
  941. }
  942.  
  943. static void
  944. copyLeaf(from, to)
  945. int from;
  946. int to;
  947. {
  948.     Canvas tempCan;
  949.     Pixwin *tempWin;
  950.     int i;
  951.     int tempNum;
  952.  
  953.     if (to < 0 || to >= Leaves) {
  954.     fprintf(stderr,"[%s] bogus to leaf %d in copyLeaf\n",
  955.         ProgName, to);
  956.     stop_output();
  957.     }
  958.     if (from < 0 || from >= Leaves) {
  959.     fprintf(stderr,"[%s] bogus from leaf %d in copyLeaf\n",
  960.         ProgName, from);
  961.     stop_output();
  962.     }
  963.  
  964.     pw_rop(pasteUpPixwin[SHRINK_NORMAL][to],
  965.        0, 0, leaf_w[SHRINK_NORMAL], page_h[SHRINK_NORMAL],
  966.        copyMode,
  967.        (pasteUpPixwin[SHRINK_NORMAL][from]) -> pw_prretained,
  968.        0,0);
  969.  
  970.     SWAPINT(pageOnLeaf[to], pageOnLeaf[from]);
  971.     SWAPINT(havePage[SHRINK_LARGE][to], havePage[SHRINK_LARGE][from]);
  972.     SWAPINT(havePage[SHRINK_NORMAL][to], havePage[SHRINK_NORMAL][from]);
  973.  
  974.     clearLeaf(from, globalDisplayState);
  975. }
  976.  
  977. static void
  978. buildLeaf(leaf, shrinkSize)
  979. int leaf;
  980. int shrinkSize;
  981. {
  982.     int i;
  983.     int page;
  984.  
  985.     if (leaf < 0 || leaf >= Leaves) {
  986.     fprintf(stderr,"[%s] bogus leaf %d in buildLeaf\n",
  987.         ProgName, leaf);
  988.     stop_output();
  989.     }
  990.  
  991.     if (shrinkSize < 0 || shrinkSize >= MAX_SHRINKS ) {
  992.     fprintf(stderr,"[%s] Bogus shrink size %d in buildLeaf\n",
  993.         ProgName, shrinkSize);
  994.     stop_output();
  995.     }
  996.  
  997.     setCursor(workingCursor);
  998.  
  999.     if (shrinkSize == SHRINK_LARGE && !largePixwinsAllocated) {
  1000.     allocateLargePixwins();
  1001.     }
  1002.  
  1003. /*
  1004.  *    Determine if this is a valid page. If it's not, we'll just clear
  1005.  *    the particular leaf.
  1006.  */
  1007.  
  1008.     page = pageOnLeaf[leaf];
  1009.  
  1010.     if (page < 0 || page >= dviTotalPages) {
  1011.     clearLeaf(leaf, shrinkSize);
  1012.     } else {
  1013.     clearLeaf(leaf, shrinkSize);
  1014.     currentLeaf = leaf;
  1015.     currentShrink = shrinkSize;
  1016.     dviPreparePage(page);    /* may change dviCurrentPage */
  1017.     page = dviCurrentPage;
  1018.     }
  1019.  
  1020.     if (shrinkSize == SHRINK_LARGE) {
  1021.     for (i = 0; i < Leaves; i++) {
  1022.         havePage[SHRINK_LARGE][i] = 0;
  1023.     }
  1024.     }
  1025.     pageOnLeaf[leaf] = dviCurrentPage;
  1026.     havePage[shrinkSize][leaf] = 1;
  1027.  
  1028.     setCursor(readyCursor);
  1029. }
  1030.     
  1031. /*
  1032.  *    interfaces to dvistuff
  1033.  */
  1034.  
  1035. /*
  1036.  *    Whenever a new font is registers, we create a shrunken Glyph
  1037.  *    table for it. However, we don't shrink the glyphs -- that's
  1038.  *    done on the fly by the putChar routine.
  1039.  */
  1040.  
  1041. DviFont *
  1042. applicationNewFont(f, key)
  1043. struct font *f;
  1044. int key;
  1045. {
  1046.     int shrink;
  1047.  
  1048.     if (key < 0 || key > MAX_FONTFAMILY) {
  1049.     fprintf(stderr,"[%s] bogus key in Newfont = %d\n",
  1050.         ProgName, key);
  1051.     dviFini();
  1052.     exit(1);
  1053.     }
  1054.     
  1055.     for (shrink = SHRINK_NORMAL; shrink <= SHRINK_LARGE; shrink++) {
  1056.     
  1057.     if (shrunkenGlyphs[shrink][key] == 0) {
  1058.         int lth = sizeof(struct glyph *) * MAX_GLYPH;
  1059.         struct glyph **g;
  1060.         
  1061.         g = (struct glyph **) malloc( lth );
  1062.         bzero(g, lth);
  1063.         shrunkenGlyphs[shrink][key] = g;
  1064.     }
  1065.  
  1066.     if (shrunkenPixrect[shrink][key] == 0) {
  1067.         int lth = sizeof(Pixrect *) * MAX_GLYPH;
  1068.         Pixrect  **g;
  1069.         
  1070.         g = (Pixrect **) malloc( lth );
  1071.         bzero(g, lth);
  1072.         shrunkenPixrect[shrink][key] = g;
  1073.     }
  1074.  
  1075.     }
  1076.     return(f);
  1077. }
  1078.  
  1079. /*
  1080.  *    When we reset a font, we only need to free the storage for the
  1081.  *    shrunken glyphs. We keep the glyph table available because we're
  1082.  *    very likely to fill it in again.
  1083.  */
  1084.  
  1085. void
  1086. applicationResetFont(fi, key)
  1087. struct fontinfo *fi;
  1088. int key;
  1089. {
  1090.     int i;
  1091.     struct glyph **theseGlyphs;
  1092.     Pixrect **thesePixrect;
  1093.     int shrink;
  1094.     
  1095.     
  1096.     for (shrink = SHRINK_NORMAL; shrink <= SHRINK_LARGE; shrink++) {
  1097.     theseGlyphs = shrunkenGlyphs[shrink][key];
  1098.     if (theseGlyphs != 0) {
  1099.         for (i = 0; i < MAX_GLYPH; i++) {
  1100.         struct glyph *g;
  1101.         
  1102.         g = theseGlyphs[i];
  1103.         
  1104.         if (g != 0) {
  1105.             if ( g -> g_raster != 0) {
  1106.             free(g -> g_raster);
  1107.             }
  1108.             free(g);
  1109.             theseGlyphs[i] = 0;
  1110.         }
  1111.         }
  1112.     }
  1113.  
  1114.     thesePixrect = shrunkenPixrect[shrink][key];
  1115.     if (thesePixrect != 0) {
  1116.         for (i = 0; i < MAX_GLYPH; i++) {
  1117.         Pixrect *g;
  1118.         
  1119.         g = thesePixrect[i];
  1120.         
  1121.         if (g != 0) {
  1122.             free(g -> pr_data);
  1123.             free(g);
  1124.             thesePixrect[i] = 0;
  1125.         }
  1126.         }
  1127.     }
  1128.     }
  1129. }
  1130.  
  1131.  
  1132. void
  1133. applicationPutChar(hh, vv, charCode)
  1134. int hh;
  1135. int vv;
  1136. int charCode;
  1137. {
  1138.     register struct glyph *g;
  1139.     int x,y;
  1140.     int key;
  1141.     Pixrect *image;
  1142.     
  1143.     key = dviCurrentFont -> family;
  1144.  
  1145.     g = shrunkenGlyphs[currentShrink][key][charCode];
  1146.  
  1147.     if (g == 0) {
  1148.  
  1149.     MprData *newMpr = (MprData *) malloc(sizeof(MprData));
  1150.     Pixrect *newPixrect = (Pixrect *) malloc(sizeof(Pixrect));
  1151.     extern struct pixrectops mem_ops;
  1152.  
  1153.     g = dviShrinkGlyph(dviCurrentFont -> f -> f_gly[charCode],
  1154.                shrinkFactor[currentShrink],
  1155.                shrinkFactor[currentShrink]);
  1156.     shrunkenGlyphs[currentShrink][key][charCode] = g;
  1157.  
  1158.     newMpr -> md_linebytes = SHRUNK_GLYPH_BYTES_WIDE(g);
  1159.     newMpr -> md_image = (short *) g -> g_raster;
  1160.     newMpr -> md_offset.x = 0;
  1161.     newMpr -> md_offset.y = 0;
  1162.     newMpr -> md_primary = 0;
  1163.     newMpr -> md_flags = 0;
  1164.  
  1165.     newPixrect -> pr_ops = &mem_ops;
  1166.     newPixrect -> pr_size.x = g -> g_width;
  1167.     newPixrect -> pr_size.y = g -> g_height;
  1168.     newPixrect -> pr_depth =1;
  1169.     newPixrect -> pr_data = (caddr_t) newMpr;
  1170.     shrunkenPixrect[currentShrink][key][charCode] = newPixrect;
  1171.     }
  1172.  
  1173.     if (g == 0 || !HASRASTER(g)) return;
  1174.  
  1175.     hh /= shrinkFactor[currentShrink];
  1176.     vv /= shrinkFactor[currentShrink];
  1177.  
  1178.     x = hh - g -> g_xorigin;
  1179.     y = vv - g -> g_yorigin;
  1180.  
  1181.     image = shrunkenPixrect[currentShrink][key][charCode];
  1182.  
  1183.     pw_rop(pasteUpPixwin[currentShrink][currentLeaf],
  1184.        x,y,
  1185.        g->g_width, g->g_height,
  1186.        paintMode,
  1187.        image,
  1188.        0,0);
  1189. }
  1190.  
  1191. void 
  1192. applicationSetRule(hh, vv, h, w)
  1193. int hh, vv;
  1194. int h, w;
  1195. {
  1196. /* (w,h) specifies lower left corner of rule box */
  1197.     int nh, nw;
  1198.  
  1199.     hh /= shrinkFactor[currentShrink];
  1200.     vv /= shrinkFactor[currentShrink];
  1201.  
  1202.     nh = (h + shrinkFactor[currentShrink] - 1) / shrinkFactor[currentShrink];
  1203.     nw = w / shrinkFactor[currentShrink];
  1204.  
  1205.     if (nh == 0 && h != 0) {
  1206.     nh = 1;
  1207.     }
  1208.     if (nw == 0 && w != 0) {
  1209.     nw = 1 ;
  1210.     }
  1211.  
  1212.     put_rectangle(hh, vv - nh, nw, nh);
  1213. }
  1214.  
  1215. /*
  1216.  *    This code attempts to support the same set of specials
  1217.  *    as imagen1
  1218.  */ 
  1219. static char *
  1220. skipWhite(c)
  1221. char *c;
  1222. {
  1223.     while (c != 0 && *c != 0 && isspace(*c)) c++;
  1224.     return(c);
  1225. }
  1226.  
  1227. static char *
  1228. skipNonWhite(c)
  1229. char *c;
  1230. {
  1231.     while (c != 0 && *c != 0 && ! isspace(*c)) c++;
  1232.     return(c);
  1233. }
  1234.  
  1235. /*
  1236.  *    The code to handle the \specials generated by tpic was written by
  1237.  *    Tim Morgan at Univ. of Calif, Irvine
  1238.  */
  1239.  
  1240. #define    COMLEN    128
  1241.  
  1242. void applicationDoSpecial(cp)
  1243. char *cp;
  1244. {
  1245.     char command[COMLEN], *orig_cp;
  1246.     register int len;
  1247.  
  1248.     orig_cp = cp;
  1249.     while (isspace(*cp)) ++cp;
  1250.     len = 0;
  1251.     while (!isspace(*cp) && *cp && len < COMLEN-1) command[len++] = *cp++;
  1252.     command[len] = '\0';
  1253.     if (strcmp(command, "pn") == 0) set_pen_size(cp);
  1254.     else if (strcmp(command, "fp") == 0) flush_path();
  1255.     else if (strcmp(command, "da") == 0) flush_dashed(cp, 0);
  1256.     else if (strcmp(command, "dt") == 0) flush_dashed(cp, 1);
  1257.     else if (strcmp(command, "pa") == 0) add_path(cp);
  1258.     else if (strcmp(command, "ar") == 0) arc(cp);
  1259.     else if (strcmp(command, "sp") == 0) flush_spline();
  1260.     else if (strcmp(command, "sh") == 0) shade_last();
  1261.     else if (strcmp(command, "wh") == 0) whiten_last();
  1262.     else if (strcmp(command, "bk") == 0) blacken_last();
  1263.     else if (strcmp(command, "ps::[begin]") == 0) psfigBegin(cp);
  1264.     else if (strcmp(command, "ps::plotfile") == 0)     /* do nothing */;
  1265.     else if (strcmp(command, "ps::[end]") == 0)     /* do nothing */;
  1266.     else if (strcmp(command, "ps:plotfile") == 0)    /* do nothing */;
  1267.     else if (strcmp(command, "ps:") == 0)        /* do nothing */;
  1268.     else if (strcmp(command, "ps::") == 0)         /* do nothing */;
  1269.     else fprintf(stderr, "[%s] special \"%s\" not implemented\n",
  1270.         ProgName, orig_cp);
  1271. }
  1272.  
  1273. /* Things we need from dvi_draw, unfortunately */
  1274. extern int pen_size, blacken, whiten, shade;
  1275.  
  1276. #define    toint(x)    ((int) ((x) + 0.5))
  1277. #define    xconv(x) toint((specialConv*(x)+dviHH)/shrinkFactor[currentShrink])
  1278. #define    yconv(y) toint((specialConv*(y)+dviVV)/shrinkFactor[currentShrink])
  1279.  
  1280.  
  1281. /*
  1282.  * Draw a line from (fx,fy) to (tx,ty).
  1283.  * Right now, we ignore pen_size.
  1284.  */
  1285. void line_btw(fx, fy, tx, ty)
  1286. int fx, fy, tx, ty;
  1287. {
  1288.     pw_vector(pasteUpPixwin[currentShrink][currentLeaf],
  1289.           xconv(fx), yconv(fy), xconv(tx), yconv(ty),
  1290.           paintMode, -1);
  1291. }
  1292.  
  1293.  
  1294. /*
  1295.  * Draw a dot at (x,y)
  1296.  */
  1297. void dot_at(x, y)
  1298. {
  1299.     line_btw(x,y,x+1,y);
  1300. }
  1301.  
  1302.  
  1303. static void do_op(x0,y0,x1,y1,op,rect)
  1304. int x0,y0,x1,y1,op;
  1305. struct pixrect *rect;
  1306. {
  1307.     pw_rop(pasteUpPixwin[currentShrink][currentLeaf],
  1308.        xconv(x0) + pen_size, yconv(y0) + pen_size,
  1309.        x1 - pen_size, y1 - pen_size,
  1310.        op, rect, 0, 0);
  1311. }
  1312.  
  1313.  
  1314. /*
  1315.  * Apply the requested attributes to the last path (box) drawn.
  1316.  * Attributes are reset.
  1317.  */
  1318.     void do_attribute_path(last_min_x, last_max_x, last_min_y, last_max_y)
  1319.     int last_min_x, last_max_x, last_min_y, last_max_y;
  1320. {
  1321.     static struct pixrect *shade_pr;
  1322.     
  1323.     if (last_min_x < last_max_x && last_min_y < last_max_y) {
  1324.         if (whiten) {
  1325.         do_op(last_min_x, last_min_y,
  1326.           xconv(last_max_x) - xconv(last_min_x),
  1327.           yconv(last_max_y) - yconv(last_min_y),
  1328.           setMode, (struct pixrect *) 0);
  1329.         }
  1330.         else if (blacken) {
  1331.         do_op(last_min_x, last_min_y,
  1332.           xconv(last_max_x) - xconv(last_min_x),
  1333.           yconv(last_max_y) - yconv(last_min_y),
  1334.           PIX_NOT(setMode), (struct pixrect *) 0);
  1335.         }
  1336.         else if (shade) {
  1337.             if (!shade_pr) {
  1338.                 shade_pr = mem_create(3, 3, 1);
  1339.                 if (!shade_pr) Fatal("Out of memory -- cannot create pixrect");
  1340.                 pr_put(shade_pr, 0, 0, 1);
  1341.             }
  1342.         pw_replrop(pasteUpPixwin[currentShrink][currentLeaf],
  1343.                xconv(last_min_x) + pen_size,
  1344.                yconv(last_min_y) + pen_size,
  1345.                xconv(last_max_x) - xconv(last_min_x) - pen_size,
  1346.                yconv(last_max_y) - yconv(last_min_y) - pen_size,
  1347.                copyMode, shade_pr, 0, 0);
  1348.         }
  1349.     }
  1350.     shade = blacken = whiten = FALSE;
  1351. }
  1352.  
  1353. /*
  1354.  * Draw the bounding box for a \psfig special.
  1355.  *
  1356.  * expected format of the command string is
  1357.  *
  1358.  * width height bbllx bblly bburx bbury
  1359.  *
  1360.  * *ll* means lower-left, *ur* means upper-right.
  1361.  *
  1362.  * We just draw the bounding box.
  1363.  */
  1364. psfigBegin(cp)
  1365. char *cp;
  1366. {
  1367.   int bbllx, bblly;
  1368.   int bburx, bbury;
  1369.   int width, height;
  1370.  
  1371.   sscanf(cp, " %d %d %d %d %d %d ",
  1372.      &width, &height,
  1373.      &bbllx, &bblly, &bburx, &bbury);
  1374.  
  1375.   bbllx = ( dviHH) / shrinkFactor[currentShrink];
  1376.   bblly = ( dviVV) / shrinkFactor[currentShrink];
  1377.  
  1378.   width = fromSP(width) / shrinkFactor[currentShrink];
  1379.   height = fromSP(height) / shrinkFactor[currentShrink];
  1380.  
  1381.   put_border( bbllx, bblly, width, height, 1);
  1382. }
  1383.  
  1384. /*
  1385.  *    Prepare everything for re-reading a .dvi file
  1386.  */
  1387. reReadFile()
  1388. {
  1389.     int i;
  1390.     int new_page_w[MAX_SHRINKS], new_page_h[MAX_SHRINKS];
  1391.     int new_leaf_w[MAX_SHRINKS];
  1392.  
  1393.     finiMarks();
  1394.     dviResetAll();
  1395.  
  1396.     if (dviInit()) {
  1397.     fprintf(stderr,"Unable to reload dvi file (%s), exiting\n",
  1398.         DVIFileName);
  1399.     stop_output();
  1400.     }
  1401.  
  1402.     initMarks();
  1403.  
  1404.     dviCurrentPage = pageOnLeaf[0];
  1405.  
  1406.     rawDviHeight = dviTallestPage + 2 * dviVVMargin;
  1407.     rawDviWidth  = dviWidestPage + 2 * dviHHMargin;
  1408.  
  1409.     newFrameLabel();
  1410.     
  1411.     new_page_h[SHRINK_NORMAL]=(rawDviHeight + shrinkFactor[SHRINK_NORMAL] - 1)
  1412.     / shrinkFactor[SHRINK_NORMAL];
  1413.     new_leaf_w[SHRINK_NORMAL]=(rawDviWidth + shrinkFactor[SHRINK_NORMAL] - 1)
  1414.     / shrinkFactor[SHRINK_NORMAL];
  1415.  
  1416.     if (new_leaf_w[SHRINK_NORMAL] * Leaves <= maxWidth) {
  1417.     new_page_w[SHRINK_NORMAL] = new_leaf_w[SHRINK_NORMAL] * Leaves;
  1418.     } else {
  1419.     new_page_w[SHRINK_NORMAL] = new_leaf_w[SHRINK_NORMAL];
  1420.     Leaves = 1;
  1421.     }
  1422.  
  1423.     for (i = 0; i < Leaves; i++ ) {
  1424.     window_set(normalCanvas[i],
  1425.            CANVAS_WIDTH, new_leaf_w[SHRINK_NORMAL],
  1426.            CANVAS_HEIGHT, new_page_h[SHRINK_NORMAL],
  1427.            0);
  1428.  
  1429.     pasteUpPixwin[SHRINK_NORMAL][i] =
  1430.         (Pixwin*) canvas_pixwin(normalCanvas[i]);
  1431.  
  1432.     clearLeaf(i, SHRINK_NORMAL);
  1433.     
  1434.     if (largeCanvas != 0) {
  1435.         window_set(normalCanvas[i],
  1436.                CANVAS_WIDTH, new_leaf_w[SHRINK_NORMAL],
  1437.                CANVAS_HEIGHT, new_page_h[SHRINK_NORMAL],
  1438.                0);
  1439.         pasteUpPixwin[SHRINK_LARGE][i] =
  1440.         (Pixwin *) canvas_pixwin(largeCanvas);
  1441.         clearLeaf(i, SHRINK_LARGE);
  1442.     }
  1443.     }
  1444.  
  1445.     for (i = 0; i < Leaves; i++) {
  1446.     havePage[SHRINK_LARGE][i] = 0;
  1447.     havePage[SHRINK_NORMAL][i] = 0;
  1448.     }
  1449.  
  1450.     displayLeaves();
  1451.  
  1452.     globalArg = 0;
  1453.     globalNumber = 0;
  1454. }
  1455.  
  1456. displayLeaves()
  1457. {
  1458.     int i;
  1459.     if (globalDisplayState == SHRINK_NORMAL) {
  1460.     for (i = 0; i < Leaves; i++) {
  1461.         if (!havePage[SHRINK_NORMAL][i]) {
  1462.         buildLeaf(i, SHRINK_NORMAL);
  1463.         }
  1464.     }
  1465.     displayNormalShrink();
  1466.     }  else {
  1467.     if (!havePage[SHRINK_LARGE][globalLeaf]) {
  1468.         buildLeaf(globalLeaf, SHRINK_LARGE);
  1469.     }
  1470.     displayLargeShrink();
  1471.     }
  1472. }
  1473.  
  1474. displayLargeShrink()
  1475. {
  1476.     int i;
  1477.     int sx;
  1478.     int sy;
  1479.  
  1480. /*
  1481.  *    Build the enlarged page if its not already there -- do this before
  1482.  *    we attempt to display it because were going to spend some time
  1483.  *    generating it.
  1484.  */
  1485.  
  1486.     for (i = 0; i < Leaves; i++) {
  1487.     window_set(normalCanvas[i],
  1488.            WIN_SHOW, FALSE,
  1489.            0);
  1490.     window_set(largeCanvas,
  1491.            WIN_SHOW, FALSE,
  1492.            0);
  1493.     }
  1494.  
  1495.     if (globalLeaf < 0 || globalLeaf >= Leaves) {
  1496.     fprintf(stderr,"globalLeaf is incorrectly set\n");
  1497.     stop_output();
  1498.     }
  1499.  
  1500.     menu_set(menu_find(menuMain,MENU_STRING, M_DOCUMENT_INSPECT,0),
  1501.          MENU_INACTIVE, TRUE, 0);
  1502.     menu_set(menu_find(menuMain, MENU_STRING, M_DOCUMENT_OVERVIEW,0),
  1503.          MENU_INACTIVE, FALSE, 0);
  1504.  
  1505.     if (autoFit) {
  1506.     Rect *rect = (Rect *) window_get(frame, WIN_SCREEN_RECT, 0);
  1507.  
  1508.     int w = leaf_w[SHRINK_LARGE]
  1509.         + (int) scrollbar_get(SCROLLBAR,SCROLL_WIDTH)
  1510.         + (int) window_get(frame, WIN_RIGHT_MARGIN)
  1511.         + (int) window_get(frame, WIN_LEFT_MARGIN);
  1512.  
  1513.     int h = page_h[SHRINK_LARGE]
  1514.         + (int) scrollbar_get(SCROLLBAR,SCROLL_WIDTH)
  1515.         + (int) window_get(frame, WIN_TOP_MARGIN)
  1516.         + (int) window_get(frame, WIN_BOTTOM_MARGIN);
  1517.  
  1518.     window_set(frame,
  1519.            WIN_WIDTH, MINFUNC(rect -> r_width, w),
  1520.            WIN_HEIGHT, MINFUNC(rect -> r_height, h),
  1521.            0);
  1522.     }
  1523.  
  1524.     window_set(largeCanvas,
  1525.            CANVAS_WIDTH, leaf_w[SHRINK_LARGE],
  1526.            CANVAS_HEIGHT, page_h[SHRINK_LARGE],
  1527.            WIN_SHOW, TRUE,
  1528.            WIN_X, 0,
  1529.            WIN_Y, 0,
  1530.            WIN_HEIGHT, WIN_EXTEND_TO_EDGE,
  1531.            WIN_WIDTH, WIN_EXTEND_TO_EDGE,
  1532.            0);
  1533. }
  1534.  
  1535. displayNormalShrink()
  1536. {
  1537.     int i;
  1538.  
  1539.     for (i = 0; i < Leaves; i++) {
  1540.     window_set(largeCanvas,
  1541.            WIN_SHOW, FALSE,
  1542.            0);
  1543.     }
  1544.  
  1545.     window_set(normalCanvas[0],
  1546.            WIN_X,0,
  1547.            WIN_Y,0,
  1548.            WIN_WIDTH, leaf_w[SHRINK_NORMAL],
  1549.            WIN_HEIGHT, page_h[SHRINK_NORMAL],
  1550.            0);
  1551.     for (i = 1; i < Leaves; i++) {
  1552.     window_set(normalCanvas[i],
  1553.            WIN_RIGHT_OF, normalCanvas[i-1],
  1554.            WIN_WIDTH, leaf_w[SHRINK_NORMAL],
  1555.            WIN_HEIGHT, page_h[SHRINK_NORMAL],
  1556.            0);
  1557.     }
  1558.  
  1559.     for (i = 0; i < Leaves; i++) {
  1560.     window_set(normalCanvas[i], WIN_SHOW, TRUE, 0);
  1561.     }
  1562.  
  1563.      if (autoFit) {
  1564.     window_fit(frame);
  1565.     }
  1566.  
  1567.     menu_set(menu_find(menuMain,MENU_STRING, M_DOCUMENT_OVERVIEW,0),
  1568.          MENU_INACTIVE, TRUE, 0);
  1569.     menu_set(menu_find(menuMain, MENU_STRING, M_DOCUMENT_INSPECT,0),
  1570.          MENU_INACTIVE, FALSE, 0);
  1571. }
  1572.  
  1573. /*
  1574.  *    SelectLarge is a little garbagey. The implementation went from having
  1575.  *    two large pixwins to one, and to avoid re-writing a bunch of code,
  1576.  *    we're just mapping two pixwins onto one.
  1577.  *
  1578.  *    However, when turning pages, we don't really know which leaf
  1579.  *    we're looking at. Hence, selectLarge scans ``havePage'' to find
  1580.  *    which leaf we currently have.
  1581.  */
  1582. selectLarge(win, inputEvent, arg)
  1583. Window *win;
  1584. Event *inputEvent;
  1585. caddr_t arg;
  1586. {
  1587.     for (globalLeaf = 0; globalLeaf < Leaves; globalLeaf++) {
  1588.     if (havePage[SHRINK_LARGE][globalLeaf]) break;
  1589.     }
  1590.  
  1591.     canvasSelected(largeCanvas, inputEvent, arg);
  1592. }
  1593.  
  1594. selectOne(win, inputEvent, arg)
  1595. Window *win;
  1596. Event *inputEvent;
  1597. caddr_t arg;
  1598. {
  1599.     globalLeaf = 0;
  1600.     canvasSelected(normalCanvas[0], inputEvent, arg);
  1601. }
  1602.  
  1603. selectTwo(win, inputEvent, arg)
  1604. Window *win;
  1605. Event *inputEvent;
  1606. caddr_t arg;
  1607. {
  1608.     globalLeaf = 1;
  1609.     canvasSelected(normalCanvas[1], inputEvent, arg);
  1610. }
  1611.  
  1612. void
  1613. canvasSelected(thisCanvas, inputEvent, arg)
  1614. Canvas thisCanvas;
  1615. Event *inputEvent;
  1616. caddr_t arg;
  1617. {
  1618.     int ch;
  1619.     Event *ie;
  1620.     Pixwin *pw;
  1621.     int i;
  1622.     int rebuild;
  1623.     
  1624. /*
  1625.  *    Figure out which leaf this event is from
  1626.  */
  1627.     ie = inputEvent;
  1628.  
  1629.     switch(event_id(ie)) {
  1630.     
  1631.     case BUT(1) :
  1632.     case BUT(2) :
  1633.     if (event_is_down(ie)) {
  1634.         int mx;
  1635.         int my;
  1636. /*
  1637.  *    Now, find top left of screen (where we scroll to)
  1638.  */
  1639.         if (globalDisplayState == SHRINK_LARGE) {
  1640.         mx = event_x(ie);
  1641.         my = event_y(ie);
  1642.         } else {
  1643.         mx = (event_x(ie) * leaf_w[SHRINK_LARGE])
  1644.             / leaf_w[SHRINK_NORMAL];
  1645.         my = (event_y(ie) * page_h[SHRINK_LARGE])
  1646.             / page_h[SHRINK_NORMAL];
  1647.         }
  1648.         
  1649.         mx -= (( (int) window_get(frame,WIN_WIDTH)
  1650.            - (int) window_get(frame, WIN_TOP_MARGIN)
  1651.            - (int) window_get(frame, WIN_BOTTOM_MARGIN))/2);
  1652.         mx = MAXFUNC(mx, 0);
  1653.         my -= (( (int) window_get(frame,WIN_HEIGHT)
  1654.            - (int) window_get(frame, WIN_RIGHT_MARGIN)
  1655.            - (int) window_get(frame, WIN_LEFT_MARGIN))/2);
  1656.         my = MAXFUNC(my, 0);
  1657.  
  1658.         globalDisplayState = SHRINK_LARGE;
  1659.         displayLeaves();
  1660.  
  1661.         scrollbar_scroll_to(window_get(largeCanvas,
  1662.                        WIN_VERTICAL_SCROLLBAR),
  1663.                 my);
  1664.         scrollbar_scroll_to(window_get(largeCanvas,
  1665.                        WIN_HORIZONTAL_SCROLLBAR),
  1666.                 mx);
  1667.     }
  1668.     return;
  1669.  
  1670.     case BUT(3):
  1671.     if (event_is_down(ie)) {
  1672.         Event *localEvent;
  1673.         int menuItem;
  1674.  
  1675.         if (globalDisplayState == SHRINK_NORMAL) {
  1676.         localEvent = canvas_window_event(normalCanvas[globalLeaf], ie);
  1677.         menuItem = (int)menu_show(menuMain,
  1678.                       normalCanvas[globalLeaf],
  1679.                       localEvent, 0);
  1680.         } else {
  1681.         localEvent = canvas_window_event(largeCanvas, ie);
  1682.         menuItem = (int)menu_show(menuMain,
  1683.                       largeCanvas,
  1684.                       localEvent, 0);
  1685.         }
  1686.  
  1687.         if (menuItem < 0) {
  1688.         globalDirection = ABSOLUTE;
  1689.         globalArg = 1;
  1690.         globalSign = 1;
  1691.         globalNumber = - menuItem;
  1692.         turnPage();
  1693.         } else {
  1694.         switch (menuItem) {
  1695.         case MV_MAIN_FORWARD :
  1696.             globalDirection = FOREWARD;
  1697.             turnPage();
  1698.             break;
  1699.             case MV_MAIN_2FORWARD :
  1700.             globalDirection = FOREWARD;
  1701.             globalArg = 1;
  1702.             globalSign = 1;
  1703.             globalNumber = 2;
  1704.             turnPage();
  1705.             break;
  1706.         case MV_MAIN_BACKWARD :
  1707.             globalDirection = BACKWARD;
  1708.             turnPage();
  1709.             break;
  1710.         case MV_MAIN_2BACKWARD :
  1711.             globalDirection = BACKWARD;
  1712.             globalArg = 1;
  1713.             globalSign = 1;
  1714.             globalNumber = 2;
  1715.             turnPage();
  1716.             break;
  1717.             case MV_MAIN_QUIT :
  1718.             stop_output(0);
  1719.             break;
  1720.  
  1721. /* Document menu */
  1722.  
  1723.             case MV_DOCUMENT_AGAIN :
  1724.             reReadFile();
  1725.             break;
  1726.             case MV_DOCUMENT_INSPECT :
  1727.             globalDisplayState = SHRINK_LARGE;
  1728.             displayLeaves();
  1729.             break;
  1730.             case MV_DOCUMENT_OVERVIEW :
  1731.             globalDisplayState = SHRINK_NORMAL;
  1732.             displayLeaves();
  1733.             break;
  1734.  
  1735. /*    PRINT sub-menu    */
  1736.  
  1737.         case MV_PRINT_PRMARKED :
  1738.         case MV_PRINT_PRUNMARKED :
  1739.             printPages(menuItem);
  1740.             break;
  1741.         case MV_PRINT_LMARK :
  1742.             markLeaf(LEAF_LEFT);
  1743.             break;
  1744.         case MV_PRINT_RMARK :
  1745.             markLeaf(LEAF_RIGHT);
  1746.             break;
  1747.         case MV_PRINT_LUNMARK :
  1748.             unmarkLeaf(LEAF_LEFT);
  1749.             break;
  1750.         case MV_PRINT_RUNMARK :
  1751.             unmarkLeaf(LEAF_RIGHT);
  1752.             break;
  1753.         case MV_PRINT_PRALL :
  1754.             printPages( menuItem );
  1755.             break;
  1756.         case MV_PRINT_MARKALL :
  1757.         case MV_PRINT_UNMARKALL :
  1758.             markAllPages(menuItem);
  1759.             break;
  1760.         }
  1761.         }
  1762.     }
  1763.     return;
  1764.  
  1765. #ifndef SUNOS4
  1766.     /*    These functions provided by SunView 4.0         */
  1767.  
  1768.     case KEY_LEFT(7):    /* OPEN */
  1769.     if (win_inputposevent(ie)) {
  1770.         break;
  1771.     } else {
  1772.         int frameFd = window_fd(frame);
  1773.  
  1774.         int Iconic = (int) window_get(frame, FRAME_CLOSED,0);
  1775.  
  1776.         if (Iconic) {
  1777.         wmgr_open(frameFd, rootFd);
  1778.         } else {
  1779.         wmgr_close(frameFd, rootFd);
  1780.         }
  1781.     }
  1782.     break;
  1783.     
  1784.     case KEY_LEFT(5) : /* EXPOSE */
  1785.     if (win_inputposevent(ie)) {
  1786.         break;
  1787.     } else {
  1788.         int frameFd = window_fd(frame);
  1789.  
  1790.         if (event_shift_is_down(ie) ||
  1791.         win_getlink(frameFd, WL_COVERING) == WIN_NULLLINK) {
  1792.             wmgr_bottom(frameFd, rootFd);
  1793.         } else {
  1794.             wmgr_top(frameFd, rootFd);
  1795.         }
  1796.     }
  1797.     break;
  1798.  
  1799. #endif /* SUNOS4 */
  1800.  
  1801.     case KEY_LEFT(4) : /* UNDO */
  1802.     if (event_is_down(ie)) {
  1803.         if (globalDisplayState == SHRINK_NORMAL) {
  1804.         globalDisplayState = SHRINK_LARGE;
  1805.         } else {
  1806.         globalDisplayState = SHRINK_NORMAL;
  1807.         }
  1808.         displayLeaves();
  1809.     }
  1810.     return;
  1811.  
  1812.     case KEY_LEFT(3) : /* PROPS */
  1813.     case KEY_LEFT(6) : /* PUT */
  1814.     case KEY_LEFT(8) : /* GET */
  1815.     case KEY_LEFT(9) : /* FIND */
  1816.     break;
  1817.  
  1818.     case 'q':
  1819.     case '\003':    /* control-C */
  1820.     case '\004':    /* control-D */
  1821.     case KEY_LEFT(1):    /* STOP */
  1822. #ifdef SUNOS4
  1823.     case ACTION_CUT:    /* I assume this is delete ? */
  1824. #endif /* SUNOS4 */
  1825.     case KEY_LEFT(10) : /* DELETE */
  1826.     {
  1827.     stop_output(0);
  1828.     }
  1829.     break;
  1830.     
  1831.     case 'n':
  1832.     case 'f':
  1833.     case ' ':
  1834.     case '\n' :
  1835.     case '\r' :
  1836.     /* scroll forward */
  1837.     globalDirection = FOREWARD;
  1838.     turnPage();
  1839.     return;
  1840.     
  1841.     case 'p':
  1842.     case 'b':
  1843.     case '\b':
  1844.     case 0177 : /* DEL */
  1845.     /* scroll backward */
  1846.     globalDirection = BACKWARD;
  1847.     turnPage();
  1848.     return;
  1849.     case 'g':
  1850.     /* go to absolute page */
  1851.     globalDirection = ABSOLUTE; /* may not be, but tough */
  1852.     turnPage();
  1853.     return;
  1854.  
  1855.     case 'R':
  1856. #ifdef SUNOS4
  1857.       case ACTION_AGAIN:
  1858. #endif
  1859.     case KEY_LEFT(2):    /* AGAIN */
  1860.     reReadFile();
  1861.     return;
  1862.     
  1863.     case '0': case '1': case '2': case '3': case '4':
  1864.     case '5': case '6': case '7': case '8': case '9':
  1865.     if (! globalArg) {
  1866.         globalArg = 1;
  1867.         globalSign = 1;
  1868.         globalNumber = 0;
  1869.     }
  1870.     globalNumber = 10*globalNumber + (event_id(ie) - '0');
  1871.     return;
  1872.     
  1873.     case '-':
  1874.     if (! globalArg) {
  1875.         globalArg = 1;
  1876.         globalSign = -1;
  1877.         globalNumber = 0;
  1878.         return;
  1879.     }
  1880.     break;
  1881.  
  1882.     default:
  1883.     globalArg = 0;
  1884.     globalNumber = 1;
  1885.     globalSign = 1;
  1886.     return ;
  1887.     }
  1888.     return;
  1889. }
  1890.  
  1891. /*
  1892.  *    This procedure turns pages based on the values of globalArg
  1893.  *    and globalNumber
  1894.  */
  1895.  
  1896. turnPage()
  1897. {
  1898.     int newLeft;
  1899.     int newRight;
  1900. /*
  1901.  *    canonicalize the request. globalArg is always > 0, were moving in
  1902.  *    some globalDirection.
  1903.  */
  1904.     
  1905.     if (globalArg  == 0 || globalNumber == 0) {
  1906.     globalNumber = 1;
  1907.     }
  1908.     
  1909.     globalNumber = globalNumber * globalSign;
  1910.     
  1911.     if (globalNumber < 0) {
  1912.     if (globalDirection == FOREWARD) {
  1913.         globalDirection = BACKWARD;
  1914.     } else if (globalDirection == BACKWARD){
  1915.         globalDirection = FOREWARD;
  1916.     }
  1917.     globalNumber = -globalNumber;
  1918.     }
  1919.     
  1920. /* 
  1921.  *    Turn pages 
  1922.  */
  1923.     if (currentShrink == SHRINK_LARGE && globalDirection == BACKWARD
  1924.     && globalNumber == 1 && globalLeaf == 1) {
  1925.         globalLeaf = 0;
  1926.         newLeft = pageOnLeaf[LEAF_LEFT];
  1927.     } else  {
  1928.         if (globalDirection == BACKWARD) {
  1929.         newLeft = pageOnLeaf[LEAF_LEFT] - globalNumber;
  1930.         } else if (globalDirection == FOREWARD) {
  1931.         newLeft = pageOnLeaf[LEAF_LEFT] + globalNumber;
  1932.         } else {
  1933.         newLeft = globalNumber - 1;    /* pages globalNumbered at 0 */
  1934.         }
  1935.     }
  1936.  
  1937.     newLeft = MINFUNC(newLeft, dviTotalPages-1);
  1938.     newLeft = MAXFUNC(newLeft, 0);
  1939.  
  1940.     if (Leaves == 1) {
  1941.     if (newLeft != pageOnLeaf[LEAF_LEFT]) {
  1942.         pageOnLeaf[LEAF_LEFT] = newLeft;
  1943.         havePage[SHRINK_NORMAL][LEAF_LEFT] = 0;
  1944.         havePage[SHRINK_LARGE][LEAF_LEFT] = 0;
  1945.         havePage[SHRINK_NORMAL][LEAF_RIGHT] = 0;
  1946.         havePage[SHRINK_LARGE][LEAF_RIGHT] = 0;
  1947.     }
  1948.     } else {
  1949. /*
  1950.  *    If you're in a double-leaf display, and you started looking at
  1951.  *    leaf 1, but you're at the beginnign of the document, you need to
  1952.  *    start looking at leaf 0
  1953.  */
  1954.  
  1955.     if (newLeft == 0 && globalLeaf == 1) {
  1956.         globalLeaf = 0;
  1957.     }
  1958.     
  1959.     newRight = newLeft + 1;
  1960.     if (pageOnLeaf[LEAF_LEFT] != newLeft) {
  1961.         if (newLeft == pageOnLeaf[LEAF_RIGHT]) {
  1962.         copyLeaf(LEAF_RIGHT, LEAF_LEFT); /* right -> left */
  1963.         } else if (newRight == pageOnLeaf[LEAF_LEFT]) {
  1964.         copyLeaf(LEAF_LEFT, LEAF_RIGHT); /* left -> right */
  1965.         }
  1966.         
  1967.         if (pageOnLeaf[LEAF_LEFT] != newLeft) {
  1968.         pageOnLeaf[LEAF_LEFT] = newLeft;
  1969.         havePage[SHRINK_NORMAL][LEAF_LEFT] = 0;
  1970.         havePage[SHRINK_LARGE][LEAF_LEFT] = 0;
  1971.         }
  1972.         
  1973.         if (pageOnLeaf[LEAF_RIGHT] != newRight) {
  1974.         pageOnLeaf[LEAF_RIGHT] = newRight;
  1975.         havePage[SHRINK_NORMAL][LEAF_RIGHT] = 0;
  1976.         havePage[SHRINK_LARGE][LEAF_RIGHT] = 0;
  1977.         }
  1978.     }
  1979.     }
  1980.     displayLeaves();
  1981.     newFrameLabel();
  1982.  
  1983.     globalNumber = 1;
  1984.     globalSign = 1;
  1985.     globalDirection = FOREWARD;
  1986.     globalArg = 0;
  1987. }
  1988.  
  1989. put_border(x, y, w, h, t)
  1990. int x, y, w, h, t;
  1991. {
  1992.     put_rectangle(x, y, w, t);
  1993.     put_rectangle(x, y, t, h);
  1994.     put_rectangle(x, y + h - t, w, t);
  1995.     put_rectangle(x + w - t, y, t, h);
  1996. }
  1997.  
  1998. put_rectangle(x, y, w, h)
  1999. int x, y, w, h;
  2000. {
  2001.     int sm;
  2002.  
  2003.     pw_writebackground(pasteUpPixwin[currentShrink][currentLeaf],
  2004.           x, y, w, h,
  2005.           setMode);
  2006. }
  2007.  
  2008.  
  2009. char *
  2010. intToStr(n)
  2011. int n;
  2012. {
  2013.     char buf[10];
  2014.     char *p;
  2015.  
  2016.     /* make sure 4 bytes, last char for showing marked pages */
  2017.     sprintf(buf, "%3d ", n);
  2018.     p = malloc(strlen(buf)+1);
  2019.     if (p == NULL) {
  2020.     fprintf(stderr,"Out of memory building menu\n");
  2021.     stop_output(0);
  2022.     }
  2023.     strcpy(p, buf);
  2024.     return(p);
  2025. }
  2026.  
  2027.  
  2028. static char **menuText;
  2029. static char *marks;
  2030.  
  2031.  
  2032. buildGotoMenu()
  2033. {
  2034.     int i;
  2035.  
  2036.     menuText = (char **) malloc((dviTotalPages + 1) * sizeof(char *));
  2037.  
  2038.     if (menuText == NULL) {
  2039.     fprintf(stderr,"out of memory\n");
  2040.     stop_output(0);
  2041.     }
  2042.  
  2043.     if (menuGoto != 0) {
  2044.       menu_destroy( menuGoto );
  2045.     }
  2046.  
  2047.     menuGoto = menu_create(0);
  2048.  
  2049. /* reset the menu pointer in the main menu */
  2050.  
  2051.     if (menuMain != 0) {
  2052.       menu_set(menu_find(menuMain, MENU_STRING, M_MAIN_GOTO, 0),
  2053.            MENU_PULLRIGHT, menuGoto, 0);
  2054.     }
  2055.            
  2056.  
  2057.     for (i = 0; i < dviTotalPages; i++) {
  2058.     menuText[i] = intToStr(i+1);
  2059.     menu_set(menuGoto, MENU_STRING_ITEM, menuText[i], -i-1, 0);
  2060.     }
  2061.  
  2062.     if (dviTotalPages > 10) {
  2063.     menu_set(menuGoto, MENU_NCOLS, 5, 0);
  2064.     }
  2065. }
  2066.  
  2067. initMarks()
  2068. {
  2069.     int i;
  2070.  
  2071.     marks = (char *) malloc(dviTotalPages);
  2072.     if (marks == NULL) {
  2073.     fprintf(stderr, "out of memory\n");
  2074.     stop_output(0);
  2075.     }
  2076.  
  2077.     for (i = 0; i < dviTotalPages; i++) {
  2078.     marks[i] = 0;
  2079.     }
  2080.  
  2081.     buildGotoMenu();
  2082.  
  2083. }
  2084.  
  2085. finiMarks()
  2086. {
  2087.   int i;
  2088.  
  2089.   if (marks != 0) {
  2090.     free(marks);
  2091.   }
  2092.  
  2093.   /* clear gotoMenu */
  2094.  
  2095.   for (i = 0; i < dviTotalPages + 1; i++ ) {
  2096.     if (menuText[i] != 0) {
  2097.       free(menuText[i]);
  2098.     }
  2099.   }
  2100.  
  2101. }
  2102.  
  2103. markPage(pagenum)
  2104. int pagenum;
  2105. {
  2106.     if (pagenum >= 0) {
  2107.     marks[pagenum] = 1;
  2108.     /* this makes nasty assumptions about intToStr() */
  2109.     menuText[pagenum][3] = '*';
  2110.     }
  2111. }
  2112.  
  2113. markLeaf(leaf)
  2114. int leaf;
  2115. {
  2116.     markPage(pageOnLeaf[leaf]);
  2117.     newFrameLabel();
  2118. }
  2119.  
  2120.  
  2121. unmarkPage(pagenum)
  2122. int pagenum;
  2123. {
  2124.     if (pagenum >= 0) {
  2125.     marks[pagenum] = 0;
  2126.     /* this makes nasty assumptions about intToStr() */
  2127.     menuText[pagenum][3] = ' ';
  2128.     }
  2129. }
  2130.  
  2131. unmarkLeaf(leaf)
  2132. int leaf;
  2133. {
  2134.     unmarkPage(pageOnLeaf[leaf]);
  2135.     newFrameLabel();
  2136. }
  2137.  
  2138. /* Print some pages. The Menu selection dictates what pages get printed */
  2139.  
  2140. printPages(menuItem)
  2141. int menuItem;
  2142. {
  2143.     char *dvips;
  2144.     int cnt;
  2145.     int i;
  2146.     char buf[20];
  2147.     char printCommand[1024];
  2148.  
  2149.     char *fileToPrint;
  2150.     int deletePrintedFile;
  2151.  
  2152.     if ( menuItem == MV_PRINT_PRALL ) {
  2153.       fileToPrint = DVIFileName;
  2154.       deletePrintedFile = 0;
  2155.     }
  2156.     else {
  2157.  
  2158.       int dviSelectBufferLength = 2048;
  2159.       char dviSelectBuffer[ 2048 ];
  2160.  
  2161.       fileToPrint = tmpnam( 0 );
  2162.       deletePrintedFile = 1;
  2163.  
  2164.       /* Now run dviselect to extract the pages */
  2165.  
  2166.       sprintf(dviSelectBuffer, "dviselect -i %s -o %s ",
  2167.           DVIFileName, fileToPrint);
  2168.  
  2169.       cnt = 0;
  2170.       for (i = 0; i < dviTotalPages; i++) {
  2171.     if (   (marks[i] && menuItem == MV_PRINT_PRMARKED)
  2172.         || (!marks[i] && menuItem == MV_PRINT_PRUNMARKED )) {
  2173.       sprintf(buf, " =%d", i + 1);
  2174.       strcat(dviSelectBuffer, buf);
  2175.       cnt++;
  2176.     }
  2177.       }
  2178.  
  2179.       if (cnt != 0) {
  2180.     window_set(frame, FRAME_LABEL, dviSelectBuffer, 0);
  2181.     setCursor(workingCursor);
  2182.     system(dviSelectBuffer);
  2183.       }
  2184.       else {
  2185.  
  2186.     /* nothing to print? */
  2187.  
  2188.     unlink( fileToPrint );
  2189.     return;
  2190.       }
  2191.     }
  2192.  
  2193.     /* Now print pages */
  2194.  
  2195.  
  2196.     if (texsunPrint == 0) {
  2197.       dvips = getenv("TEXSUNPRINT");
  2198.       if (dvips == NULL) {
  2199.     fprintf(stderr,"Using default ``%s'' to print\n",
  2200.         defaultTexsunPrint);
  2201.     dvips = defaultTexsunPrint;
  2202.       }
  2203.     }
  2204.     else {
  2205.       dvips = texsunPrint;
  2206.     }
  2207.  
  2208.     sprintf(printCommand, "%s %s",
  2209.         dvips, fileToPrint);
  2210.  
  2211.     window_set(frame, FRAME_LABEL, printCommand, 0);
  2212.     setCursor(workingCursor);
  2213.     system(printCommand);
  2214.     newFrameLabel();
  2215.     setCursor(readyCursor);
  2216.     
  2217.     if ( deletePrintedFile ) {
  2218.       unlink( fileToPrint );
  2219.     }
  2220. }
  2221.  
  2222. markAllPages(menuItem)
  2223. int menuItem;
  2224. {
  2225.   int i;
  2226.   int mark = (menuItem == MV_PRINT_MARKALL);
  2227.     
  2228.   for ( i = 0; i < dviTotalPages; i++ ) {
  2229.     if (mark) {
  2230.       markPage(i);
  2231.     } else {
  2232.       unmarkPage(i);
  2233.     }
  2234.   }
  2235.   newFrameLabel();
  2236. }
  2237.  
  2238.  
  2239. newFrameLabel()
  2240. {
  2241.     int pagenum;
  2242.  
  2243.     pagenum = pageOnLeaf[LEAF_LEFT];
  2244.     if (pagenum < 0)
  2245.     return;
  2246.     if (Leaves == 1) {
  2247.     sprintf(frameLabel,"TeXsun  page %d of %d  %s (%4.2f by %4.2f)",
  2248.         pagenum + 1, dviTotalPages,
  2249.         frameLabelName,
  2250.         (float) ((float) rawDviWidth / ( (float) dviDPI)),
  2251.         (float) ((float) rawDviHeight / ( (float) dviDPI)) );
  2252.     if (marks[pagenum])
  2253.         strcat(frameLabel, "   [marked]");
  2254.     } else if (pageOnLeaf[LEAF_LEFT] == pageOnLeaf[LEAF_RIGHT]) {
  2255.     sprintf(frameLabel,"TeXsun  page %d of %d  %s (%4.2f by %4.2f)",
  2256.         pagenum + 1, dviTotalPages,
  2257.         frameLabelName,
  2258.         (float) ((float) rawDviWidth / ( (float) dviDPI)),
  2259.         (float) ((float) rawDviHeight / ( (float) dviDPI)) );
  2260.     if (marks[pagenum])
  2261.         strcat(frameLabel, "   [left marked]");
  2262.     } else {
  2263.     sprintf(frameLabel,"TeXsun  pages %d and %d of %d  %s (%4.2f by %4.2f)",
  2264.         pagenum + 1, pageOnLeaf[LEAF_RIGHT] + 1, dviTotalPages,
  2265.         frameLabelName,
  2266.         (float) ((float) rawDviWidth / ( (float) dviDPI)),
  2267.         (float) ((float) rawDviHeight / ( (float) dviDPI)) );
  2268.     if (marks[pagenum])
  2269.         strcat(frameLabel, "   [left marked]");
  2270.     if (marks[pageOnLeaf[LEAF_RIGHT]])
  2271.         strcat(frameLabel, "   [right marked]");
  2272.     }
  2273.  
  2274.     window_set ( frame, FRAME_LABEL, frameLabel, 0);
  2275. }
  2276.  
  2277.  
  2278. setCursor(cursor)
  2279. Cursor cursor;
  2280. {
  2281.     int i;
  2282.  
  2283.     for (i = 0; i < Leaves; i++) {
  2284.     window_set(normalCanvas[i], WIN_CURSOR, cursor, 0);
  2285.     if (largePixwinsAllocated) {
  2286.         window_set(largeCanvas, WIN_CURSOR, cursor, 0);
  2287.     }
  2288.     }
  2289. }
  2290.