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 / Tex3b1 / tex3b1.c < prev   
C/C++ Source or Header  |  1990-07-10  |  25KB  |  1,143 lines

  1. /*
  2.  *    This program is Copyright (C) 1987 by the Board of Trustees of the
  3.  *    University of Illinois, and by the author Dirk Grunwald.
  4.  *
  5.  *    This program may be freely copied, as long as this copyright
  6.  *    message remaines affixed. It may not be sold, altough it may
  7.  *    be distributed with other software which is sold. If the
  8.  *    software is distributed, the source code must be made available.
  9.  *
  10.  *    No warrenty, expressed or implied, is given with this software.
  11.  *    It is presented in the hope that it will prove useful.
  12.  *
  13.  *    Adapted for the 3b1 by Andy Fyfe  (andy@csvax.caltech.edu)
  14.  *    Fixes from John Campbell  (...!arizona!naucse!thunde!jdc)
  15.  */
  16.  
  17. static char *version="1.2";
  18.  
  19. #include <sys/types.h>
  20. #include <stdio.h>
  21. #include <ctype.h>
  22. #include <fcntl.h>
  23. #include <signal.h>
  24. #include <string.h>
  25. #include <sys/window.h>
  26. #include <sys/file.h>
  27. #include <sys/ioctl.h>
  28. #include <sys/termio.h>
  29. #include "dvistuff.h"
  30.  
  31. #ifndef __STDC__
  32. #define const
  33. #endif
  34.  
  35. #ifndef __GNUC__
  36. #define inline
  37. #define volatile
  38. #endif
  39.  
  40. #ifndef PAGE_HEIGHT
  41. #define PAGE_HEIGHT    11        /* in inches */
  42. #endif
  43.  
  44. #ifndef PAGE_WIDTH
  45. #define PAGE_WIDTH    8.5        /* in inches */
  46. #endif
  47.  
  48. #ifndef FONT_DPI
  49. #define FONT_DPI    300
  50. #endif
  51.  
  52. #ifndef BLACKNESS
  53. #define BLACKNESS    3
  54. #endif
  55.  
  56. #ifndef SHRINK_1
  57. #define SHRINK_1    3
  58. #endif
  59.  
  60. #ifndef SHRINK_2
  61. #define SHRINK_2    4
  62. #endif
  63.  
  64. #ifndef SHRINK_3
  65. #define SHRINK_3    2
  66. #endif
  67.  
  68. #define SHRINKS 3        /* Be careful if you change this! */
  69.  
  70. /*
  71.  *    These constants may need to be changed on your implementation
  72.  */
  73.  
  74. int Debug;
  75.  
  76. /*
  77.  *    3b1 related variables
  78.  */
  79.  
  80. static int WindowFD;
  81. static unsigned short *Image[SHRINKS];
  82. static int X_origin[SHRINKS], Y_origin[SHRINKS];
  83.  
  84. static int globalNumber;
  85. static int globalShrink;
  86. static int defaultShrink;
  87. static int firstPage;
  88.  
  89. extern char *DVIFileName;
  90.  
  91. /*
  92.  *    TeX-Dvi related variables
  93.  */
  94.  
  95. static int maxHeight[SHRINKS];
  96. static int maxWidth[SHRINKS];
  97. static int bytesWide[SHRINKS];
  98.  
  99. static int imageWidth[SHRINKS], imageHeight[SHRINKS];
  100. static int screenWidth[SHRINKS], screenHeight[SHRINKS];
  101.  
  102. static int shrink[SHRINKS] = { SHRINK_1, SHRINK_2, SHRINK_3 };
  103.  
  104. static int page_w[SHRINKS], page_h[SHRINKS], page_num[SHRINKS];
  105.  
  106. static struct glyph **shrunkenGlyphs[SHRINKS][MAX_FONTFAMILY];
  107.  
  108. typedef struct mpr_data MprData;
  109.  
  110. #ifdef __STDC__
  111. extern void *malloc();
  112. #else
  113. extern char *malloc();
  114. #endif
  115. extern volatile void exit();
  116.  
  117. #define MAXFUNC(a,b) (((a) < (b)) ? (b) : (a))
  118. #define MINFUNC(a,b) (((a) < (b)) ? (a) : (b))
  119.  
  120. static int inHelp;
  121.  
  122. static struct uwdata d;
  123. static void displayLeaves(), buildLeaf();
  124. volatile void usage();
  125.  
  126. static const char clear_str[] = "\033[=1C\033[2J\033[H";
  127. #define clearWindow() write(WindowFD, clear_str, sizeof(clear_str)-1)
  128.  
  129. volatile void
  130. stop_output(status)
  131. int status;
  132. {
  133.     close(WindowFD);
  134.     dviFini();
  135.     exit(status);
  136. }
  137.  
  138. static
  139. sig_window()
  140. {
  141.     struct uwdata tmp;
  142.     int i;
  143.  
  144.     if (ioctl(WindowFD, WIOCGETD, &tmp) < 0) {
  145.     fprintf(stderr, "%s: window ioctl failed: ", ProgName);
  146.     perror("");
  147.     stop_output(1);
  148.     }
  149.     if (tmp.uw_width != d.uw_width || tmp.uw_height != d.uw_height) {
  150.     d.uw_width = tmp.uw_width;
  151.     d.uw_height = tmp.uw_height;
  152.     for (i=0; i<SHRINKS; ++i) {
  153.         screenWidth[i] = MINFUNC(imageWidth[i], d.uw_width);
  154.         screenHeight[i] = MINFUNC(imageHeight[i], d.uw_height);
  155.     }
  156.     if (!inHelp) {
  157.         adjust_origin();
  158.         displayLeaves();
  159.     }
  160.     }
  161.  
  162.     signal(SIGWIND, sig_window);
  163. }
  164.  
  165. volatile void
  166. main(argc, argv)
  167.     int argc;
  168.     char **argv;
  169. {
  170.     struct utdata t;
  171.     int fd, i, c, smallWindow = 0;
  172.     extern int optind;
  173.     extern char *optarg;
  174.  
  175.     ProgName = argv[0];
  176.     firstPage = 1;
  177.     defaultShrink = 0;
  178.     Debug = 0;
  179.     dviDPI = FONT_DPI;
  180.     dviBlackness = BLACKNESS;
  181.  
  182.     while ((c = getopt(argc, argv, "b:d:f:m:s:D:SV")) != EOF) {
  183.     switch(c) {
  184.     case 'b':
  185.         dviBlackness = atoi(optarg);
  186.         break;
  187.     case 'd':
  188.         dviDPI = atoi(optarg);
  189.         break;
  190.     case 'f':
  191.         firstPage = atoi(optarg);
  192.         break;
  193.     case 'm':
  194.         defaultShrink = atoi(optarg) - 1;
  195.         if (defaultShrink < 0)
  196.         defaultShrink = 0;
  197.         else if (defaultShrink >= SHRINKS)
  198.         defaultShrink = SHRINKS - 1;
  199.         break;
  200.     case 's':
  201.         setShrinks(optarg);
  202.         break;
  203.     case 'D':
  204.         Debug = atoi(optarg);
  205.         break;
  206.     case 'S':
  207.         ++smallWindow;
  208.         break;
  209.     case 'V':
  210.         fprintf(stderr,"%s: version %s\n", ProgName, version);
  211.         usage();
  212.         break;
  213.     case '?':
  214.         usage();
  215.         break;
  216.     }
  217.     }
  218.  
  219.     for (i = 0; i < SHRINKS; ++i) {
  220.     maxWidth[i]  = ((int)(PAGE_WIDTH *dviDPI) + (shrink[i]-1)) / shrink[i];
  221.     maxHeight[i] = ((int)(PAGE_HEIGHT*dviDPI) + (shrink[i]-1)) / shrink[i];
  222.     bytesWide[i] = ((maxWidth[i] + 15) >> 4) << 1;
  223.     maxWidth[i]  = bytesWide[i] * 8;
  224.     }
  225.  
  226.     globalShrink = defaultShrink;
  227.  
  228.     if (optind != argc - 1)
  229.     usage();
  230.     else
  231.     DVIFileName = argv[optind];
  232.  
  233.     if (dviInit()) {
  234.     dviFini();
  235.     exit(1);
  236.     }
  237.  
  238.     if (Debug > 0) {
  239.     fprintf(stderr,"page is %d wide, %d high\n",
  240.         dviWidestPage, dviTallestPage);
  241.     }
  242.  
  243.     if (((double) dviTallestPage * (double) dviWidestPage) > 4.0e7) {
  244.     fprintf(stderr,"[%s] Warning: Your page size is %d wide and %d tall,\n",
  245.         ProgName, dviTallestPage, dviWidestPage);
  246.     fprintf(stderr,"which may be too big to be displayed\n");
  247.     }
  248.  
  249.     for (i = 0; i < SHRINKS; ++i) {
  250.     page_h[i] = (dviTallestPage + 2 * dviDPI + shrink[i] - 1) / shrink[i];
  251.     page_w[i] = (dviWidestPage + 2 * dviDPI + shrink[i] - 1) / shrink[i];
  252.     page_num[i] = -1;
  253.     imageWidth[i] = MINFUNC(page_w[i], maxWidth[i]);
  254.     imageHeight[i] = MINFUNC(page_h[i], maxHeight[i]);
  255.     if (Debug > 0)
  256.         fprintf(stderr,"page [mag %d] is (%d, %d), image is (%d,%d)\n",
  257.         i+1, page_w[i], page_h[i], imageWidth[i], imageHeight[i]);
  258.     }
  259.  
  260.     /*
  261.      * Make sure we're running in a window
  262.      */
  263.     fd = open("/dev/tty", O_RDWR, 0);
  264.     if (fd < 0) {
  265.     fprintf(stderr, "%s: can't open /dev/tty: ", ProgName);
  266.     perror("");
  267.     dviFini();
  268.     exit(1);
  269.     }
  270.     if (ioctl(fd, WIOCGETD, &d) < 0) {
  271.     fprintf(stderr, "%s must be run from a console window\n", ProgName);
  272.     dviFini();
  273.     exit(1);
  274.     }
  275.     close(fd);
  276.  
  277.     /*
  278.      * Create a new window.
  279.      */
  280.     WindowFD = open("/dev/window", O_RDWR, 0);
  281.     if (WindowFD < 0) {
  282.     fprintf(stderr, "%s: can't open /dev/window: ", ProgName);
  283.     perror("");
  284.     dviFini();
  285.     exit(1);
  286.     }
  287.  
  288.     /*
  289.      * Set the window to use the full screen or just a part of it
  290.      */
  291.     if (smallWindow) {
  292.     d.uw_x = 0;
  293.     d.uw_y = WLINE(2);
  294.     d.uw_width = 600;
  295.     d.uw_height = WTXTVS * 18;
  296.     d.uw_uflags =
  297.         BORDHSCROLL | BORDVSCROLL | BORDHELP | BORDCANCEL | BORDRESIZE;
  298.     }
  299.     else {
  300.     d.uw_x = 0;
  301.     d.uw_y = WLINE(1);
  302.     d.uw_width = WINWIDTH;
  303.     d.uw_height = WINHEIGHT - d.uw_y;
  304.     d.uw_uflags = NBORDER;
  305.     }
  306.     for (i = 0; i < SHRINKS; ++i) {
  307.     screenWidth[i] = MINFUNC(imageWidth[i], d.uw_width);
  308.     screenHeight[i] = MINFUNC(imageHeight[i], d.uw_height);
  309.     }
  310.     if (ioctl(WindowFD, WIOCSETD, &d) < 0) {
  311.     fprintf(stderr, "%s: window ioctl failed: ", ProgName);
  312.     perror("");
  313.     stop_output(1);
  314.     }
  315.     inHelp = 1;        /* lie a bit -- no image yet for sig_window */
  316.     signal(SIGWIND, sig_window);
  317.     kbd_nowait();
  318.     clearWindow();
  319.  
  320.     /*
  321.      * Give the window a name
  322.      */
  323.     t.ut_num = WTXTUSER;
  324.     strncpy(t.ut_text, "TeX 3b1 Previewer", WTXTLEN);
  325.     t.ut_text[WTXTLEN-1] = '\0';
  326.     ioctl(WindowFD, WIOCSETTEXT, &t);
  327.     
  328.     globalNumber = 0;
  329.  
  330.     dviCurrentPage = firstPage - 1;
  331.  
  332.     buildLeaf();
  333.     inHelp = 0;
  334.     displayLeaves();
  335.  
  336.     while (1)
  337.     check_input();
  338. }
  339.  
  340. volatile void
  341. usage()
  342. {
  343.     fprintf(stderr, "%s: usage: %s [options] dvi-file\n",
  344.     ProgName, ProgName);
  345.     fprintf(stderr, "options:\n");
  346.     fprintf(stderr, "    -b <blackness>\n");
  347.     fprintf(stderr, "    -d <dvi Dots Per Inch>\n");
  348.     fprintf(stderr, "    -f <first (phyical) page>\n");
  349.     fprintf(stderr, "    -m <default magnification>\n");
  350.     fprintf(stderr, "    -s <shrink factors (eg 342)>\n");
  351.     fprintf(stderr, "    -D <debug value>\n");
  352.     fprintf(stderr, "    -S      [use small screen]\n");
  353.     fprintf(stderr, "    -V      [print version]\n");
  354.     exit(1);
  355. }
  356.  
  357. setShrinks(values)
  358. char *values;
  359. {
  360.     int s1, s2, s3;
  361.  
  362.     s1 = values[0] - '0';
  363.     s2 = values[1] - '0';
  364.     s3 = values[2] - '0';
  365.  
  366.     if (s1 < 0 || s1 > 9 || s2 < 0 || s2 > 9 || s3 < 0 || s3 > 9) {
  367.     fprintf(stderr,
  368.         "%s: Illegal shrink values %s: must be 3 single digits\n",
  369.         ProgName, values);
  370.     exit(1);
  371.     }
  372.  
  373.     shrink[0] = s1;
  374.     shrink[1] = s2;
  375.     shrink[2] = s3;
  376. }
  377.  
  378. static void
  379. clearPixmap(shk)
  380. int shk;
  381. {
  382.     int size = maxHeight[shk] * bytesWide[shk];
  383.  
  384.     if (Image[shk] == 0) {
  385.     Image[shk] = (unsigned short *)malloc(size);
  386.     if (Image[shk] == 0) {
  387.         fprintf(stderr, "%s: can't malloc %d bytes %s image array: ",
  388.         ProgName, size, shk == 0 ? "small" : "large");
  389.         perror("");
  390.         stop_output(1);
  391.     }
  392.     }
  393.     memset(Image[shk], 0, size);
  394. }
  395.  
  396. /*
  397.  *    display the normal sized leaf
  398.  */
  399. static void
  400. displayLeaves()
  401. {
  402.     struct urdata r;
  403.     struct utdata t;
  404.     int i, l;
  405.     static int last_width = 0, last_height;
  406.  
  407.     r.ur_srcbase = (unsigned short *)Image[globalShrink];
  408.     r.ur_srcwidth = bytesWide[globalShrink];
  409.     r.ur_dstbase = 0;
  410.     r.ur_dstwidth = 0;
  411.     r.ur_srcx = X_origin[globalShrink];
  412.     r.ur_srcy = Y_origin[globalShrink];
  413.     r.ur_dstx = 0;
  414.     r.ur_dsty = 0;
  415.     r.ur_width = screenWidth[globalShrink];
  416.     r.ur_height = screenHeight[globalShrink];
  417.     r.ur_srcop = SRCSRC;
  418.     r.ur_dstop = DSTSRC;
  419.     r.ur_pattern = 0;
  420.  
  421.     if ((r.ur_width < last_width && r.ur_width < d.uw_width) ||
  422.     (r.ur_height < last_height && r.ur_height < d.uw_height))
  423.     clearWindow();
  424.  
  425.     if (ioctl(WindowFD, WIOCRASTOP, &r) < 0) {
  426.     fprintf(stderr, "[%s]: displayLeaves: ioctl(RASTOP): ", ProgName);
  427.     perror("");
  428.     dump_rast(&r);
  429.     }
  430.  
  431.     t.ut_num = WTXTSLK1;
  432.     sprintf(t.ut_text,
  433.     "Page %3d of %3d (%4d,%4d)     Current 1/%d     ",
  434.     dviCurrentPage+1, dviTotalPages,
  435.     X_origin[globalShrink], Y_origin[globalShrink],
  436.     shrink[globalShrink]);
  437.  
  438.     l = strlen(t.ut_text);
  439.     for (i=0; i<SHRINKS; ++i) {
  440.     if (page_num[i] == dviCurrentPage) {
  441.           t.ut_text[l++] = '[';
  442.           t.ut_text[l++] = '1';
  443.           t.ut_text[l++] = '/';
  444.           t.ut_text[l++] = shrink[i] + '0';
  445.           t.ut_text[l++] = ']';
  446.     }
  447.     else {
  448.           t.ut_text[l++] = ' ';
  449.           t.ut_text[l++] = ' ';
  450.           t.ut_text[l++] = ' ';
  451.           t.ut_text[l++] = ' ';
  452.           t.ut_text[l++] = ' ';
  453.     }
  454.         t.ut_text[l++] = ' ';
  455.     }
  456.     t.ut_text[l] = '\0';
  457.  
  458.     ioctl(WindowFD, WIOCSETTEXT, &t);
  459.  
  460.     last_width = r.ur_width;
  461.     last_height = r.ur_height;
  462. }
  463.  
  464. static void
  465. buildLeaf()
  466. {
  467.     clearPixmap(globalShrink);
  468.  
  469.     if (dviCurrentPage < 0)
  470.     dviCurrentPage = 0;
  471.     if (dviCurrentPage >= dviTotalPages)
  472.     dviCurrentPage = dviTotalPages - 1;
  473.  
  474.     dviPreparePage(dviCurrentPage);
  475.  
  476.     page_num[globalShrink] = dviCurrentPage;
  477. }
  478.     
  479. /*
  480.  *    interfaces to dvistuff
  481.  */
  482.  
  483. /*
  484.  *    Whenever a new font is registers, we create a shrunken Glyph
  485.  *    table for it. However, we don't shrink the glyphs -- that's
  486.  *    done on the fly by the putChar routine.
  487.  */
  488.  
  489. DviFont *
  490. applicationNewFont(f, key)
  491. struct font *f;
  492. int key;
  493. {
  494.     int shk;
  495.  
  496.     if (key < 0 || key > MAX_FONTFAMILY) {
  497.     fprintf(stderr,"[%s] bogus key in Newfont = %d\n",
  498.         ProgName, key);
  499.     stop_output(1);
  500.     }
  501.     
  502.     for (shk = 0; shk < SHRINKS; ++shk) {
  503.     if (shrunkenGlyphs[shk][key] == 0) {
  504.         int lth = sizeof(struct glyph *) * MAX_GLYPH;
  505.         struct glyph **g;
  506.         
  507.         g = (struct glyph **) malloc( lth );
  508.         bzero(g, lth);
  509.         shrunkenGlyphs[shk][key] = g;
  510.     }
  511.     }
  512.  
  513.     return(f);
  514. }
  515.  
  516. /*
  517.  *    When we reset a font, we only need to free the storage for the
  518.  *    shrunken glyphs. We keep the glyph table available because we're
  519.  *    very likely to fill it in again.
  520.  */
  521.  
  522. void
  523. applicationResetFont(fi, key)
  524. struct fontinfo *fi;
  525. int key;
  526. {
  527.     int i, shk;
  528.     struct glyph **theseGlyphs;
  529.     
  530.     for (shk=0; shk<SHRINKS; ++shk) {
  531.     theseGlyphs = shrunkenGlyphs[shk][key];
  532.     if (theseGlyphs != 0) {
  533.         for (i = 0; i < MAX_GLYPH; i++) {
  534.         struct glyph *g;
  535.         
  536.         g = theseGlyphs[i];
  537.         
  538.         if (g != 0) {
  539.             if ( g -> g_raster != 0) {
  540.             free(g -> g_raster);
  541.             }
  542.             free(g);
  543.             theseGlyphs[i] = 0;
  544.         }
  545.         }
  546.     }
  547.     }
  548. }
  549.  
  550. static inline void
  551. reverse_raster(g)
  552. struct glyph *g;
  553. {
  554.     unsigned short rev(), *p;
  555.     int i; 
  556.  
  557.     p = (unsigned short *)g->g_raster;
  558.     for (i = 0; i < (g->g_height + 1) * ((g->g_width + 15) >> 4); ++i) {
  559.     *p = rev(*p);
  560.     p++;
  561.     }
  562. }
  563.  
  564. void
  565. applicationPutChar(hh, vv, charCode)
  566. int hh;
  567. int vv;
  568. int charCode;
  569. {
  570.     register struct glyph *g;
  571.     int x,y;
  572.     int key;
  573. #if 0
  574.     struct urdata r;
  575. #endif
  576.     
  577.     key = dviCurrentFont -> family;
  578.  
  579.     g = shrunkenGlyphs[globalShrink][key][charCode];
  580.  
  581.     if (g == 0) {
  582.     g = dviShrinkGlyph(dviCurrentFont -> f -> f_gly[charCode],
  583.         shrink[globalShrink], shrink[globalShrink]);
  584.     shrunkenGlyphs[globalShrink][key][charCode] = g;
  585.     reverse_raster(g);
  586.     }
  587.  
  588.     if (g == 0 || !HASRASTER(g)) return;
  589.  
  590.     hh /= shrink[globalShrink];
  591.     vv /= shrink[globalShrink];
  592.  
  593.     x = hh - g -> g_xorigin;
  594.     y = vv - g -> g_yorigin;
  595.  
  596.     bitblt(Image[globalShrink], x, y, bytesWide[globalShrink],
  597.     g->g_raster, g->g_width, g->g_height);
  598. #if 0
  599.     r.ur_srcbase = (unsigned short *)g->g_raster;
  600.     r.ur_srcwidth = ((g->g_width + 15) >> 4) * 2;
  601.     r.ur_dstbase = (unsigned short *)Image[globalShrink] + ((x>1024)?64:0);
  602.     r.ur_dstwidth = bytesWide[globalShrink];
  603.     r.ur_srcx = 0;
  604.     r.ur_srcy = 0;
  605.     r.ur_dstx = (x > 1024) ? x-1024 : x;
  606.     r.ur_dsty = y;
  607.     r.ur_width = g->g_width;
  608.     r.ur_height = g->g_height;
  609.     r.ur_srcop = SRCSRC;
  610.     r.ur_dstop = DSTOR;
  611.     r.ur_pattern = 0;
  612.  
  613.     if (ioctl(WindowFD, WIOCRASTOP, &r) < 0) {
  614.     fprintf(stderr, "[%s]: applicationPutChar: ioctl(RASTOP): ", ProgName);
  615.     perror("");
  616.     dump_rast(&r);
  617.     }
  618. #endif
  619. }
  620.  
  621. void 
  622. applicationSetRule(hh, vv, h, w)
  623. int hh, vv;
  624. int h, w;
  625. {
  626.     int nh, nw;
  627.  
  628.     hh /= shrink[globalShrink];
  629.     vv /= shrink[globalShrink];
  630.  
  631.     nh = h / shrink[globalShrink];
  632.     nw = w / shrink[globalShrink];
  633.  
  634.     if (nh == 0 && h != 0)
  635.     nh = 1;
  636.     if (nw == 0 && w != 0)
  637.     nw = 1;
  638.  
  639.     put_rectangle(hh, vv - nh, nw, nh);
  640. }
  641.  
  642. #define    COMLEN    128
  643.  
  644. void
  645. applicationDoSpecial(cp)
  646. char *cp;
  647. {
  648.     char command[COMLEN], *orig_cp;
  649.     register int len;
  650.  
  651.     orig_cp = cp;
  652.     while (isspace(*cp)) ++cp;
  653.     len = 0;
  654.     while (!isspace(*cp) && *cp && len < COMLEN-1) command[len++] = *cp++;
  655.     command[len] = '\0';
  656.     if (strcmp(command, "ps::[begin]") == 0) psfigBegin(cp);
  657.     else if (strcmp(command, "ps::plotfile") == 0)     /* do nothing */;
  658.     else if (strcmp(command, "ps::[end]") == 0)     /* do nothing */;
  659.     else if (strcmp(command, "ps:plotfile") == 0)    /* do nothing */;
  660.     else if (strcmp(command, "ps:") == 0)        /* do nothing */;
  661.     else if (strcmp(command, "ps::") == 0)         /* do nothing */;
  662.     else fprintf(stderr, "[%s] special \"%s\" not implemented\n",
  663.         ProgName, orig_cp);
  664. }
  665.  
  666. /*
  667.  * Draw the bounding box for a \psfig special.
  668.  *
  669.  * expected format of the command string is
  670.  *
  671.  * width height bbllx bblly bburx bbury
  672.  *
  673.  * *ll* means lower-left, *ur* means upper-right.
  674.  *
  675.  * We just draw the bounding box.
  676.  */
  677. psfigBegin(cp)
  678. char *cp;
  679. {
  680.   int bbllx, bblly;
  681.   int bburx, bbury;
  682.   int width, height;
  683.  
  684.   sscanf(cp, " %d %d %d %d %d %d ",
  685.      &width, &height,
  686.      &bbllx, &bblly, &bburx, &bbury);
  687.  
  688.   bbllx = ( dviHH) / shrink[globalShrink];
  689.   bblly = ( dviVV) / shrink[globalShrink];
  690.  
  691.   width = fromSP(width) / shrink[globalShrink];
  692.   height = fromSP(height) / shrink[globalShrink];
  693.  
  694.   put_border( bbllx, bblly, width, height, 1);
  695. }
  696.  
  697. put_border(x, y, w, h, t)
  698. int x, y, w, h, t;
  699. {
  700.     put_rectangle(x, y, w, t);
  701.     put_rectangle(x, y, t, h);
  702.     put_rectangle(x, y + h - t, w, t);
  703.     put_rectangle(x + w - t, y, t, h);
  704. }
  705.  
  706. /*
  707.  *    Prepare everything for re-reading a .dvi file
  708.  */
  709. reReadFile()
  710. {
  711.     int i;
  712.  
  713.     dviResetAll();
  714.  
  715.     if (dviInit()) {
  716.     fprintf(stderr,"Unable to reload dvi file (%s), exiting\n",
  717.         DVIFileName);
  718.     stop_output(1);
  719.     }
  720.  
  721.     for (i = 0; i < SHRINKS; ++i) {
  722.     page_h[i] = (dviTallestPage + 2 * dviDPI + shrink[i] - 1) / shrink[i];
  723.     page_w[i] = (dviWidestPage + 2 * dviDPI + shrink[i] - 1) / shrink[i];
  724.     page_num[i] = -1;
  725.     imageWidth[i] = MINFUNC(page_w[i], maxWidth[i]);
  726.     imageHeight[i] = MINFUNC(page_h[i], maxHeight[i]);
  727.     if (Debug > 0)
  728.         fprintf(stderr,"page [mag %d] is (%d, %d), image is (%d,%d)\n",
  729.         i+1, page_w[i], page_h[i], imageWidth[i], imageHeight[i]);
  730.     }
  731.  
  732.     buildLeaf();
  733.  
  734.     globalNumber = 0;
  735. }
  736.  
  737. kbd_nowait()
  738. {
  739.     struct termio t;
  740.     struct umdata m;
  741.  
  742.     ioctl(WindowFD, TCGETA, &t);
  743.     t.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL);
  744.     t.c_cc[VMIN] = 1;
  745.     ioctl(WindowFD, TCSETA, &t);
  746.  
  747.     m.um_flags = MSDOWN;
  748.     m.um_icon = 0;
  749.     if (ioctl(WindowFD, WIOCSETMOUSE, &m) < 0) {
  750.     fprintf(stderr, "%s: ioctl WIOSETMOUSE: ", ProgName);
  751.     perror("");
  752.     }
  753. }
  754.  
  755. check_input()
  756. {
  757.     int ch;
  758.     int direction;
  759.     
  760. #define BOGUSDIR -1
  761. #define FOREWARD 0
  762. #define BACKWARD 1
  763. #define ABSOLUTE 2
  764.     
  765.     direction = BOGUSDIR;
  766.  
  767.     ch = getKeyboard();
  768.  
  769.     switch(ch) {
  770.     case 'h':
  771.     X_origin[globalShrink] -= dviDPI/4/shrink[globalShrink];
  772.     break;
  773.  
  774.     case 'k':
  775.     Y_origin[globalShrink] -= dviDPI/2/shrink[globalShrink];
  776.     break;
  777.  
  778.     case 'l':
  779.     X_origin[globalShrink] += dviDPI/4/shrink[globalShrink];
  780.     break;
  781.  
  782.     case 'j':
  783.     Y_origin[globalShrink] += dviDPI/2/shrink[globalShrink];
  784.     break;
  785.  
  786.     case 'H':
  787.     X_origin[globalShrink] = 0;
  788.     break;
  789.  
  790.     case 'K':
  791.     Y_origin[globalShrink] = 0;
  792.     break;
  793.  
  794.     case 'L':
  795.     X_origin[globalShrink] =
  796.         imageWidth[globalShrink] - screenWidth[globalShrink];
  797.     break;
  798.  
  799.     case 'J':
  800.     Y_origin[globalShrink] =
  801.         imageHeight[globalShrink] - screenHeight[globalShrink];
  802.     break;
  803.  
  804.     case 'q':
  805.     case 'x':
  806.     case '\003':    /* control-C */
  807.     case '\004':    /* control-D */
  808.     stop_output(0);
  809.     
  810.     case 'n':
  811.     case 'f':
  812.     case ' ':
  813.     case '\n':
  814.     case '\r':
  815.     /* scroll forward */
  816.     direction = FOREWARD;
  817.     break;
  818.     
  819.     case 'p':
  820.     case 'b':
  821.     case '\b':
  822.     case '\177' : /* DEL */
  823.     /* scroll backward */
  824.     direction = BACKWARD;
  825.     break;
  826.     
  827.     case 'g':
  828.     case 'G':
  829.     /* go to absolute page */
  830.     direction = ABSOLUTE; /* may not be, but tough */
  831.     break;
  832.     
  833.     case '\f':
  834.     case 'r' :
  835.     X_origin[globalShrink] = Y_origin[globalShrink] = 0;
  836.     break;
  837.  
  838. #if SHRINKS >= 2
  839.     case 'm':
  840.     change_mag(screenWidth[globalShrink]/2, screenHeight[globalShrink]/2,
  841.         globalShrink == 1 ? 4 : 2);
  842.     break;
  843. #endif
  844.  
  845. #if SHRINKS >= 3
  846.     case 'M':
  847.     change_mag(screenWidth[globalShrink]/2, screenHeight[globalShrink]/2,
  848.         globalShrink == 2 ? 4 : 1);
  849.     break;
  850. #endif
  851.  
  852.     case 'R':
  853.     reReadFile();
  854.     break;
  855.     
  856.     case '0': case '1': case '2': case '3': case '4':
  857.     case '5': case '6': case '7': case '8': case '9':
  858.     globalNumber = 10*globalNumber + (ch - '0');
  859.     return;
  860.     
  861.     case '?':
  862.     help_screen();
  863.     break;
  864.  
  865.     case '\000':
  866.     break;
  867.  
  868.     default:
  869.     globalNumber = 0;
  870.     return;
  871.     }
  872.     
  873.     adjust_origin();
  874.  
  875.     if (direction != BOGUSDIR) {
  876.     if (globalNumber == 0)
  877.         globalNumber = 1;
  878.  
  879. /* 
  880.  *    Turn pages 
  881.  */
  882.     if (direction == BACKWARD)
  883.         dviCurrentPage -= globalNumber;
  884.     else if (direction == FOREWARD)
  885.         dviCurrentPage += globalNumber;
  886.     else
  887.         dviCurrentPage = globalNumber - 1;    /* pages globalNumbered at 0 */
  888.     
  889.     globalShrink = defaultShrink;
  890.     X_origin[0] = Y_origin[0] = 0;
  891.     X_origin[1] = Y_origin[1] = 0;
  892.     X_origin[2] = Y_origin[2] = 0;
  893.  
  894.     dviCurrentPage = MINFUNC(dviCurrentPage, dviTotalPages-1);
  895.     dviCurrentPage = MAXFUNC(dviCurrentPage, 0);
  896.     }
  897.  
  898.     if (dviCurrentPage != page_num[globalShrink])
  899.     buildLeaf();
  900.     
  901.     displayLeaves();
  902.     globalNumber = 0;
  903.  
  904.     return;
  905. }
  906.  
  907. #ifdef NOSHARED_LIB
  908. const unsigned short patwhite[16] =
  909.     { 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
  910.       0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff };
  911. #else
  912. extern unsigned short patwhite[16];
  913. #endif
  914.  
  915. put_rectangle(x, y, w, h)
  916. int x, y, w, h;
  917. {
  918.     struct urdata r;
  919.  
  920.     r.ur_srcbase = 0;
  921.     r.ur_srcwidth = 0;
  922.     r.ur_dstbase = (unsigned short *)Image[globalShrink] + ((x>1024)?64:0);
  923.     r.ur_dstwidth = bytesWide[globalShrink];
  924.     r.ur_srcx = 0;
  925.     r.ur_srcy = 0;
  926.     r.ur_dstx = (x > 1024) ? x-1024 : x;
  927.     r.ur_dsty = y;
  928.     r.ur_width = w;
  929.     r.ur_height = h;
  930.     r.ur_srcop = SRCPAT;
  931.     r.ur_dstop = DSTOR;
  932.     r.ur_pattern = (unsigned short *)patwhite;
  933.  
  934.     if (ioctl(WindowFD, WIOCRASTOP, &r) < 0) {
  935.     fprintf(stderr, "[%s]: put_rectangle: ioctl(RASTOP): ", ProgName);
  936.     perror("");
  937.     dump_rast(&r);
  938.     }
  939. }
  940.  
  941. dump_rast(p)
  942. struct urdata *p;
  943. {
  944.     fprintf(stderr,
  945.     "\tsrc %x[%d] @ (%d,%d); dst %x[%d] @ (%d,%d)\n",
  946.     p->ur_srcbase, p->ur_srcwidth, p->ur_srcx, p->ur_srcy,
  947.     p->ur_dstbase, p->ur_dstwidth, p->ur_dstx, p->ur_dsty);
  948.     fprintf(stderr,
  949.     "\tsrcop = %d, dstop = %d, size (%d,%d), pattern = %x\n",
  950.     p->ur_srcop, p->ur_dstop, p->ur_width, p->ur_height, p->ur_pattern);
  951. }
  952.  
  953. get_char()
  954. {
  955.     char ch;
  956.     int count;
  957.  
  958.     count = read(WindowFD, &ch, 1);
  959.     if (count == 0)
  960.     return 'q';
  961.     else if (count < 0)
  962.     return -1;
  963.     else
  964.     return ch;
  965. }
  966.  
  967. getKeyboard()
  968. {
  969.     char ch;
  970.  
  971.     ch = get_char();
  972.     if (ch != '\033')
  973.     return ch;
  974.  
  975.     /*
  976.      * if the char is escape, try and interpret escape sequences and return
  977.      * an equivalent single character.  mouse clicks on border icons return
  978.      * a key sequence.  resize icon handled by sigwind.
  979.      */
  980.  
  981.     switch (get_char()) {
  982.     case '[':
  983.     switch(get_char()) {
  984.     case '?':    /* mouse button (among other things?) */
  985.         return get_mouse();
  986.     case 'A':    /* up arrow */
  987.     case 'T':    /* shift up arrow */
  988.         return 'k';
  989.     case 'B':    /* down arrow */
  990.     case 'S':    /* shift down arrow */
  991.         return 'j';
  992.     case 'C':    /* right arrow */
  993.         return 'l';
  994.     case 'D':    /* left arrow */
  995.         return 'h';
  996.     case 'H':    /* home */
  997.         return 'r';
  998.     case 'U':    /* page down */
  999.         return 'J';
  1000.     case 'V':    /* page up */
  1001.         return 'K';
  1002.     }
  1003.     break;
  1004.     case 'O':
  1005.     switch(get_char()) {
  1006.     case 'm':    /* help */
  1007.     case 'M':    /* shift help */
  1008.         return '?';
  1009.     case 'k':    /* exit */
  1010.     case 'K':    /* shift exit */
  1011.     case 'w':    /* cancl */
  1012.     case 'W':    /* shift cancl */
  1013.         return 'q';
  1014.     case 'v':    /* open */
  1015.         return 'R';
  1016.     }
  1017.     break;
  1018.     case 'N':
  1019.     switch(get_char()) {
  1020.     case 'g':    /* prev */
  1021.         return 'b';
  1022.     case 'h':    /* next */
  1023.         return 'f';
  1024.     case 'L':    /* shift right arrow */
  1025.         return 'l';
  1026.     case 'K':    /* shift left arrow */
  1027.         return 'h';
  1028.     }
  1029.     break;
  1030.     case '9':        /* beg */
  1031.     globalNumber = 1;
  1032.     return 'g';
  1033.     case '0':        /* end */
  1034.     globalNumber = dviTotalPages;
  1035.     return 'g';
  1036.     }
  1037.     return -1;
  1038. }
  1039.  
  1040. get_mouse()
  1041. {
  1042.     int param[4], n;
  1043.     int ch;
  1044.  
  1045.     for (n=0; n<4; ++n) {
  1046.     param[n] = 0;
  1047.     ch = get_char();
  1048.     while (ch >= '0' && ch <= '9') {
  1049.         param[n] = 10 * param[n] + ch - '0';
  1050.         ch = get_char();
  1051.     }
  1052.     if (n < 3 && ch != ';')
  1053.         return -1;
  1054.     if (n == 3 && ch != 'M')
  1055.         return -1;
  1056.     }
  1057.  
  1058.     change_mag(param[0], param[1], param[2]);
  1059.  
  1060.     return '\000';
  1061. }
  1062.  
  1063. change_mag(x, y, z)
  1064. int x, y, z;
  1065. {
  1066.     int prev = globalShrink;
  1067.     int next = 0;
  1068.     int k, u, v;
  1069.  
  1070.     for (k = 0; k<MAXFUNC(3,SHRINKS); ++k)
  1071.     if (z & (1<<(2-k)))
  1072.         next = k;
  1073.  
  1074.     u = (X_origin[prev] + x) * shrink[prev];
  1075.     v = (Y_origin[prev] + y) * shrink[prev];
  1076.  
  1077.     X_origin[next] = u / shrink[next] - screenWidth[next]/2;
  1078.     Y_origin[next] = v / shrink[next] - screenHeight[next]/2;
  1079.  
  1080.     globalShrink = next;
  1081. }
  1082.  
  1083. adjust_origin()
  1084. {
  1085.     if (X_origin[globalShrink] >=
  1086.       imageWidth[globalShrink] - screenWidth[globalShrink])
  1087.     X_origin[globalShrink] =
  1088.         imageWidth[globalShrink] - screenWidth[globalShrink];
  1089.     if (X_origin[globalShrink] < 0)
  1090.     X_origin[globalShrink] = 0;
  1091.     if (Y_origin[globalShrink] >=
  1092.       imageHeight[globalShrink] - screenHeight[globalShrink])
  1093.     Y_origin[globalShrink] =
  1094.         imageHeight[globalShrink] - screenHeight[globalShrink];
  1095.     if (Y_origin[globalShrink] < 0)
  1096.     Y_origin[globalShrink] = 0;
  1097. }
  1098.  
  1099. help_screen()
  1100. {
  1101.     int i;
  1102.     char buffer[80];
  1103.     static char *help_message_1[] = {
  1104.     "    h, j, k, l, H, J, K, L, <ff>, r,\n",
  1105.     "       <arrows>, <page>, <home>:        move around the page\n",
  1106.     "    <spc>, f, n, <nl>, <cr>, <next>:    next page       (*)\n",
  1107.     "    b, p, <bs>, <del>, <prev>:          previous page   (*)\n",
  1108.     "    g, G, <beg>, <end>:                 goto page       (*)\n",
  1109.     "    m, M:                               change the magnification\n",
  1110.     "    R, <open>:                          re-open dvi file\n",
  1111.     "    ?, <help>:                          this help screen\n",
  1112.     "    q, x, ^C, ^D, <cancl>, <exit>:      exit\n",
  1113.     "\n",
  1114.     "The (*) commands can be prefixed by a number.  The program can\n",
  1115.     NULL };
  1116.  
  1117.     static char *help_message_2[] = {
  1118.     "be used to change magnifications (using one of the 3 buttons)\n",
  1119.     "and move a point to the centre of the screen.\n",
  1120.     "\n",
  1121.     "    Press any key to continue\n",
  1122.     NULL };
  1123.  
  1124.     inHelp = 1;
  1125.     clearWindow();
  1126.  
  1127.     for (i = 0; i < sizeof (help_message_1)/sizeof (char *); ++i)
  1128.        write (WindowFD, help_message_1[i], strlen(help_message_1[i]));
  1129.  
  1130.     sprintf(buffer, 
  1131.     "display the dvi file at %d, %d and %d dpi.  The mouse can also\n",
  1132.     dviDPI/shrink[0], dviDPI/shrink[1], dviDPI/shrink[2]);
  1133.     write (WindowFD, buffer, strlen(buffer));
  1134.  
  1135.     for (i = 0; i < sizeof (help_message_2)/sizeof (char *); ++i)
  1136.        write (WindowFD, help_message_2[i], strlen(help_message_2[i]));
  1137.  
  1138.     getKeyboard();
  1139.  
  1140.     clearWindow();
  1141.     inHelp = 0;
  1142. }
  1143.