home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / unixtex-6.1b-src.tgz / tar.out / contrib / unixtex / xdvik / dvi_draw.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  28KB  |  1,217 lines

  1. /*
  2.  * Copyright (c) 1994 Paul Vojta.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  * 1. Redistributions of source code must retain the above copyright
  8.  *    notice, this list of conditions and the following disclaimer.
  9.  * 2. Redistributions in binary form must reproduce the above copyright
  10.  *    notice, this list of conditions and the following disclaimer in the
  11.  *    documentation and/or other materials provided with the distribution.
  12.  *
  13.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  14.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  17.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23.  * SUCH DAMAGE.
  24.  *
  25.  * NOTE:
  26.  *    xdvi is based on prior work as noted in the modification history, below.
  27.  */
  28.  
  29. /*
  30.  * DVI previewer for X.
  31.  *
  32.  * Eric Cooper, CMU, September 1985.
  33.  *
  34.  * Code derived from dvi-imagen.c.
  35.  *
  36.  * Modification history:
  37.  * 1/1986    Modified for X.10    --Bob Scheifler, MIT LCS.
  38.  * 7/1988    Modified for X.11    --Mark Eichin, MIT
  39.  * 12/1988    Added 'R' option, toolkit, magnifying glass
  40.  *                    --Paul Vojta, UC Berkeley.
  41.  * 2/1989    Added tpic support    --Jeffrey Lee, U of Toronto
  42.  * 4/1989    Modified for System V    --Donald Richardson, Clarkson Univ.
  43.  * 3/1990    Added VMS support    --Scott Allendorf, U of Iowa
  44.  * 7/1990    Added reflection mode    --Michael Pak, Hebrew U of Jerusalem
  45.  * 1/1992    Added greyscale code    --Till Brychcy, Techn. Univ. Muenchen
  46.  *                      and Lee Hetherington, MIT
  47.  * 4/1994    Added DPS support, bounding box
  48.  *                    --Ricardo Telichevesky
  49.  *                      and Luis Miguel Silveira, MIT RLE.
  50.  */
  51.  
  52. #include "config.h"
  53. #include <kpathsea/c-ctype.h>
  54. #include <kpathsea/c-fopen.h>
  55. #include <kpathsea/c-vararg.h>
  56. #include "dvi.h"
  57.  
  58. static    struct frame    frame0;        /* dummy head of list */
  59. #ifdef    TEXXET
  60. static    struct frame    *scan_frame;    /* head frame for scanning */
  61. #endif
  62.  
  63. #ifndef    DVI_BUFFER_LEN
  64. #define    DVI_BUFFER_LEN    512
  65. #endif
  66.  
  67. static    ubyte    dvi_buffer[DVI_BUFFER_LEN];
  68. static    struct frame    *current_frame;
  69.  
  70. #ifndef    TEXXET
  71. #define    DIR    1
  72. #else
  73. #define    DIR    currinf.dir
  74. #endif
  75.  
  76. /*
  77.  *    Explanation of the following constant:
  78.  *    offset_[xy]   << 16:    margin (defaults to one inch)
  79.  *    shrink_factor << 16:    one pixel page border
  80.  *    shrink_factor << 15:    rounding for pixel_conv
  81.  */
  82. #define OFFSET_X    (offset_x << 16) + (shrink_factor * 3 << 15)
  83. #define OFFSET_Y    (offset_y << 16) + (shrink_factor * 3 << 15)
  84.  
  85. #ifndef    BMLONG
  86. #ifndef    BMSHORT
  87. BMUNIT    bit_masks[9] = {
  88.     0x0,    0x1,    0x3,    0x7,
  89.     0xf,    0x1f,    0x3f,    0x7f,
  90.     0xff
  91. };
  92. #else    /* BMSHORT */
  93. BMUNIT    bit_masks[17] = {
  94.     0x0,    0x1,    0x3,    0x7,
  95.     0xf,    0x1f,    0x3f,    0x7f,
  96.     0xff,    0x1ff,    0x3ff,    0x7ff,
  97.     0xfff,    0x1fff,    0x3fff,    0x7fff,
  98.     0xffff
  99. };
  100. #endif    /* BMSHORT */
  101. #else    /* BMLONG */
  102. BMUNIT    bit_masks[33] = {
  103.     0x0,        0x1,        0x3,        0x7,
  104.     0xf,        0x1f,        0x3f,        0x7f,
  105.     0xff,        0x1ff,        0x3ff,        0x7ff,
  106.     0xfff,        0x1fff,        0x3fff,        0x7fff,
  107.     0xffff,        0x1ffff,    0x3ffff,    0x7ffff,
  108.     0xfffff,    0x1fffff,    0x3fffff,    0x7fffff,
  109.     0xffffff,    0x1ffffff,    0x3ffffff,    0x7ffffff,
  110.     0xfffffff,    0x1fffffff,    0x3fffffff,    0x7fffffff,
  111.     0xffffffff
  112. };
  113. #endif    /* BMLONG */
  114.  
  115. #ifdef    VMS
  116. #define    off_t    int
  117. #endif
  118. extern    off_t    lseek();
  119.  
  120. #ifndef    SEEK_SET    /* if <unistd.h> is not provided (or for <X11R5) */
  121. #define    SEEK_SET    0
  122. #define    SEEK_CUR    1
  123. #define    SEEK_END    2
  124. #endif
  125.  
  126. static    void    draw_part();
  127.  
  128. /*
  129.  *    X routines.
  130.  */
  131.  
  132. /*
  133.  *    Draw the border of a rectangle on the screen.
  134.  */
  135.  
  136. /*
  137.  *    Put a rectangle on the screen.
  138.  */
  139.  
  140. static    void
  141. put_rule(x, y, w, h)
  142.     int        x, y;
  143.     unsigned int    w, h;
  144. {
  145.     if (x < max_x && x + w >= min_x && y < max_y && y + h >= min_y) {
  146.         if (--event_counter == 0) read_events(False);
  147.         XFillRectangle(DISP, currwin.win, ruleGC,
  148.         x - currwin.base_x, y - currwin.base_y, w ? w : 1, h ? h : 1);
  149.     }
  150. }
  151.  
  152. static    void
  153. put_bitmap(bitmap, x, y)
  154.     register struct bitmap *bitmap;
  155.     register int x, y;
  156. {
  157.  
  158.     if (debug & DBG_BITMAP)
  159.         Printf("X(%d,%d)\n", x - currwin.base_x, y - currwin.base_y);
  160.     if (x < max_x && x + (int) bitmap->w >= min_x &&
  161.         y < max_y && y + (int) bitmap->h >= min_y) {
  162.         if (--event_counter == 0) read_events(False);
  163.         image->width = bitmap->w;
  164.         image->height = bitmap->h;
  165.         image->data = bitmap->bits;
  166.         image->bytes_per_line = bitmap->bytes_wide;
  167.         XPutImage(DISP, currwin.win, foreGC, image,
  168.             0, 0,
  169.             x - currwin.base_x, y - currwin.base_y,
  170.             bitmap->w, bitmap->h);
  171.         if (foreGC2)
  172.             XPutImage(DISP, currwin.win, foreGC2, image,
  173.             0, 0,
  174.             x - currwin.base_x, y - currwin.base_y,
  175.             bitmap->w, bitmap->h);
  176.     }
  177. }
  178.  
  179. #ifdef    GREY
  180. static    void
  181. put_image(img, x, y)
  182.     register XImage *img;
  183.     register int x, y;
  184. {
  185.     if (x < max_x && x + img->width >= min_x &&
  186.         y < max_y && y + img->height >= min_y) {
  187.  
  188.         if (--event_counter == 0) read_events (False);
  189.  
  190.         XPutImage(DISP, currwin.win, foreGC, img,
  191.             0, 0,
  192.             x - currwin.base_x, y - currwin.base_y,
  193.             (unsigned int) img->width, (unsigned int) img->height);
  194.     }
  195. }
  196. #endif    /* GREY */
  197.  
  198. void
  199. put_border(x, y, width, height, ourGC)
  200.     int        x, y;
  201.     unsigned int    width, height;
  202.     GC        ourGC;
  203. {
  204.  
  205.     --width;
  206.     --height;
  207.     /* top */
  208.     XFillRectangle(DISP, currwin.win, ourGC, x, y, width, 1);
  209.     /* right */
  210.     XFillRectangle(DISP, currwin.win, ourGC, x + (int) width, y, 1, height);
  211.     /* bottom */
  212.     XFillRectangle(DISP, currwin.win, ourGC, x + 1, y + (int) height,
  213.         width, 1);
  214.     /* left */
  215.     XFillRectangle(DISP, currwin.win, ourGC, x, y + 1, 1, height);
  216. }
  217.  
  218.  
  219. /*
  220.  *    Byte reading routines for dvi file.
  221.  */
  222.  
  223. #define    xtell(pos)    ((long) (lseek(fileno(dvi_file), 0L, SEEK_CUR) - \
  224.                 (currinf.end - (pos))))
  225.  
  226. static    ubyte
  227. xxone()
  228. {
  229.     if (currinf.virtual) {
  230.         ++currinf.pos;
  231.         return EOP;
  232.     }
  233.     currinf.end = dvi_buffer +
  234.         read(fileno(dvi_file), (char *) (currinf.pos = dvi_buffer),
  235.         DVI_BUFFER_LEN);
  236.     return currinf.end > dvi_buffer ? *(currinf.pos)++ : EOF;
  237. }
  238.  
  239. #define    xone()  (currinf.pos < currinf.end ? *(currinf.pos)++ : xxone())
  240.  
  241. static    unsigned long
  242. xnum(size)
  243.     register ubyte size;
  244. {
  245.     register long x = 0;
  246.  
  247.     while (size--) x = (x << 8) | xone();
  248.     return x;
  249. }
  250.  
  251. static    long
  252. xsnum(size)
  253.     register ubyte size;
  254. {
  255.     register long x;
  256.  
  257. #ifdef    __STDC__
  258.     x = (signed char) xone();
  259. #else
  260.     x = xone();
  261.     if (x & 0x80) x -= 0x100;
  262. #endif
  263.     while (--size) x = (x << 8) | xone();
  264.     return x;
  265. }
  266.  
  267. #define    xsfour()    xsnum(4)
  268.  
  269. static    void
  270. xskip(offset)
  271.     long    offset;
  272. {
  273.     currinf.pos += offset;
  274.     if (!currinf.virtual && currinf.pos > currinf.end)
  275.         (void) lseek(fileno(dvi_file), (long) (currinf.pos - currinf.end),
  276.         SEEK_CUR);
  277. }
  278.  
  279. #if    NeedVarargsPrototypes
  280. static    NORETURN void
  281. tell_oops(_Xconst char *message, ...)
  282. #else
  283. /* VARARGS */
  284. static    NORETURN void
  285. tell_oops(va_alist)
  286.     va_dcl
  287. #endif
  288. {
  289. #if    !NeedVarargsPrototypes
  290.     _Xconst char *message;
  291. #endif
  292.     va_list    args;
  293.  
  294.     Fprintf(stderr, "%s: ", prog);
  295. #if    NeedVarargsPrototypes
  296.     va_start(args, message);
  297. #else
  298.     va_start(args);
  299.     message = va_arg(args, _Xconst char *);
  300. #endif
  301.     (void) vfprintf(stderr, message, args);
  302.     va_end(args);
  303.     if (currinf.virtual)
  304.         Fprintf(stderr, " in virtual font %s\n", currinf.virtual->fontname);
  305.     else
  306.         Fprintf(stderr, ", offset %ld\n", xtell(currinf.pos - 1));
  307.     exit(1);
  308. }
  309.  
  310.  
  311. /*
  312.  *    Code for debugging options.
  313.  */
  314.  
  315. static    void
  316. print_bitmap(bitmap)
  317.     register struct bitmap *bitmap;
  318. {
  319.     register BMUNIT *ptr = (BMUNIT *) bitmap->bits;
  320.     register int x, y, i;
  321.  
  322.     if (ptr == NULL) oops("print_bitmap called with null pointer.");
  323.     Printf("w = %d, h = %d, bytes wide = %d\n",
  324.         bitmap->w, bitmap->h, bitmap->bytes_wide);
  325.     for (y = 0; y < (int) bitmap->h; ++y) {
  326.         for (x = bitmap->bytes_wide; x > 0; x -= BYTES_PER_BMUNIT) {
  327. #ifndef    MSBITFIRST
  328.         for (i = 0; i < BITS_PER_BMUNIT; ++i)
  329. #else
  330.         for (i = BITS_PER_BMUNIT - 1; i >= 0; --i)
  331. #endif
  332.             Putchar((*ptr & (1 << i)) ? '@' : ' ');
  333.         ++ptr;
  334.         }
  335.         Putchar('\n');
  336.     }
  337. }
  338.  
  339. static    void
  340. print_char(ch, g)
  341.     ubyte ch;
  342.     struct glyph *g;
  343. {
  344.     Printf("char %d", ch);
  345.     if (ISPRINT(ch))
  346.         Printf(" (%c)", ch);
  347.     Putchar('\n');
  348.     Printf("x = %d, y = %d, dvi = %ld\n", g->x, g->y, g->dvi_adv);
  349.     print_bitmap(&g->bitmap);
  350. }
  351.  
  352. static    _Xconst    char    *dvi_table1[] = {
  353.     "SET1", NULL, NULL, NULL, "SETRULE", "PUT1", NULL, NULL,
  354.     NULL, "PUTRULE", "NOP", "BOP", "EOP", "PUSH", "POP", "RIGHT1",
  355.     "RIGHT2", "RIGHT3", "RIGHT4", "W0", "W1", "W2", "W3", "W4",
  356.     "X0", "X1", "X2", "X3", "X4", "DOWN1", "DOWN2", "DOWN3",
  357.     "DOWN4", "Y0", "Y1", "Y2", "Y3", "Y4", "Z0", "Z1",
  358.     "Z2", "Z3", "Z4"};
  359.  
  360. static    _Xconst    char    *dvi_table2[] = {
  361.     "FNT1", "FNT2", "FNT3", "FNT4", "XXX1", "XXX2", "XXX3", "XXX4",
  362.     "FNTDEF1", "FNTDEF2", "FNTDEF3", "FNTDEF4", "PRE", "POST", "POSTPOST",
  363.     "SREFL", "EREFL", NULL, NULL, NULL, NULL};
  364.  
  365. static    void
  366. print_dvi(ch)
  367.     ubyte ch;
  368. {
  369.     _Xconst    char    *s;
  370.  
  371.     Printf("%4d %4d ", PXL_H, PXL_V);
  372.     if (ch <= (ubyte) (SETCHAR0 + 127)) {
  373.         Printf("SETCHAR%-3d", ch - SETCHAR0);
  374.         if (ISPRINT(ch))
  375.         Printf(" (%c)", ch);
  376.         Putchar('\n');
  377.         return;
  378.     }
  379.     else if (ch < FNTNUM0) s = dvi_table1[ch - 128];
  380.     else if (ch <= (ubyte) (FNTNUM0 + 63)) {
  381.         Printf("FNTNUM%d\n", ch - FNTNUM0);
  382.         return;
  383.     }
  384.     else s = dvi_table2[ch - (FNTNUM0 + 64)];
  385.     if (s) Puts(s);
  386.     else
  387.         tell_oops("unknown op-code %d", ch);
  388. }
  389.  
  390.  
  391. /*
  392.  *    Count the number of set bits in a given region of the bitmap
  393.  */
  394.  
  395. char    sample_count[]    = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
  396.  
  397. static    int
  398. sample(bits, bytes_wide, bit_skip, w, h)
  399.     BMUNIT    *bits;
  400.     int    bytes_wide, bit_skip, w, h;
  401. {
  402.     BMUNIT    *ptr, *endp;
  403.     register BMUNIT *cp;
  404.     int    bits_left;
  405.     register int n, bit_shift, wid;
  406.  
  407.     ptr = bits + bit_skip / BITS_PER_BMUNIT;
  408.     endp = ADD(bits, h * bytes_wide);
  409.     bits_left = w;
  410. #ifndef    MSBITFIRST
  411.     bit_shift = bit_skip % BITS_PER_BMUNIT;
  412. #else
  413.     bit_shift = BITS_PER_BMUNIT - bit_skip % BITS_PER_BMUNIT;
  414. #endif
  415.     n = 0;
  416.     while (bits_left) {
  417. #ifndef    MSBITFIRST
  418.         wid = BITS_PER_BMUNIT - bit_shift;
  419. #else
  420.         wid = bit_shift;
  421. #endif
  422.         if (wid > bits_left) wid = bits_left;
  423.         if (wid > 4) wid = 4;
  424. #ifdef    MSBITFIRST
  425.         bit_shift -= wid;
  426. #endif
  427.         for (cp = ptr; cp < endp; cp = ADD(cp, bytes_wide))
  428.         n += sample_count[(*cp >> bit_shift) & bit_masks[wid]];
  429. #ifndef    MSBITFIRST
  430.         bit_shift += wid;
  431.         if (bit_shift == BITS_PER_BMUNIT) {
  432.         bit_shift = 0;
  433.         ++ptr;
  434.         }
  435. #else
  436.         if (bit_shift == 0) {
  437.         bit_shift = BITS_PER_BMUNIT;
  438.         ++ptr;
  439.         }
  440. #endif
  441.         bits_left -= wid;
  442.     }
  443.     return n;
  444. }
  445.  
  446. static    void
  447. shrink_glyph(g)
  448.     register struct glyph *g;
  449. {
  450.     int        shrunk_bytes_wide, shrunk_height;
  451.     int        rows_left, rows, init_cols;
  452.     int        cols_left;
  453.     register int    cols;
  454.     BMUNIT        *old_ptr, *new_ptr;
  455.     register BMUNIT    m, *cp;
  456.     int    min_sample = shrink_factor * shrink_factor * density / 100;
  457.  
  458.     /* These machinations ensure that the character is shrunk according to
  459.        its hot point, rather than its upper left-hand corner. */
  460.     g->x2 = g->x / shrink_factor;
  461.     init_cols = g->x - g->x2 * shrink_factor;
  462.     if (init_cols <= 0) init_cols += shrink_factor;
  463.     else ++g->x2;
  464.     g->bitmap2.w = g->x2 + ROUNDUP((int) g->bitmap.w - g->x, shrink_factor);
  465.     /* include row zero with the positively numbered rows */
  466.     cols = g->y + 1; /* spare register variable */
  467.     g->y2 = cols / shrink_factor;
  468.     rows = cols - g->y2 * shrink_factor;
  469.     if (rows <= 0) {
  470.         rows += shrink_factor;
  471.         --g->y2;
  472.     }
  473.     g->bitmap2.h = shrunk_height = g->y2 +
  474.         ROUNDUP((int) g->bitmap.h - cols, shrink_factor) + 1;
  475.     alloc_bitmap(&g->bitmap2);
  476.     old_ptr = (BMUNIT *) g->bitmap.bits;
  477.     new_ptr = (BMUNIT *) g->bitmap2.bits;
  478.     shrunk_bytes_wide = g->bitmap2.bytes_wide;
  479.     rows_left = g->bitmap.h;
  480.     bzero((char *) new_ptr, shrunk_bytes_wide * shrunk_height);
  481.     while (rows_left) {
  482.         if (rows > rows_left) rows = rows_left;
  483.         cols_left = g->bitmap.w;
  484. #ifndef    MSBITFIRST
  485.         m = (1 << 0);
  486. #else
  487.         m = ((BMUNIT) 1 << (BITS_PER_BMUNIT-1));
  488. #endif
  489.         cp = new_ptr;
  490.         cols = init_cols;
  491.         while (cols_left) {
  492.         if (cols > cols_left) cols = cols_left;
  493.         if (sample(old_ptr, g->bitmap.bytes_wide,
  494.             (int) g->bitmap.w - cols_left, cols, rows)
  495.             >= min_sample)
  496.             *cp |= m;
  497. #ifndef    MSBITFIRST
  498.         if (m == ((BMUNIT)1 << (BITS_PER_BMUNIT-1))) {
  499.             m = (1 << 0);
  500.             ++cp;
  501.         }
  502.         else m <<= 1;
  503. #else
  504.         if (m == (1 << 0)) {
  505.             m = ((BMUNIT) 1 << (BITS_PER_BMUNIT-1));
  506.             ++cp;
  507.         }
  508.         else m >>= 1;
  509. #endif
  510.         cols_left -= cols;
  511.         cols = shrink_factor;
  512.         }
  513.         *((char **) &new_ptr) += shrunk_bytes_wide;
  514.         *((char **) &old_ptr) += rows * g->bitmap.bytes_wide;
  515.         rows_left -= rows;
  516.         rows = shrink_factor;
  517.     }
  518.     g->y2 = g->y / shrink_factor;
  519.     if (debug & DBG_BITMAP)
  520.         print_bitmap(&g->bitmap2);
  521. }
  522.  
  523. #ifdef    GREY
  524. static    void
  525. shrink_glyph_grey(g)
  526.     register struct glyph *g;
  527. {
  528.     int        rows_left, rows, init_cols;
  529.     int        cols_left;
  530.     register int    cols;
  531.     int        x, y;
  532.     long        thesample;
  533.     BMUNIT        *old_ptr;
  534.     unsigned int    size;
  535.  
  536.     /* These machinations ensure that the character is shrunk according to
  537.        its hot point, rather than its upper left-hand corner. */
  538.     g->x2 = g->x / shrink_factor;
  539.     init_cols = g->x - g->x2 * shrink_factor;
  540.     if (init_cols <= 0) init_cols += shrink_factor;
  541.     else ++g->x2;
  542.     g->bitmap2.w = g->x2 + ROUNDUP((int) g->bitmap.w - g->x, shrink_factor);
  543.     /* include row zero with the positively numbered rows */
  544.     cols = g->y + 1; /* spare register variable */
  545.     g->y2 = cols / shrink_factor;
  546.     rows = cols - g->y2 * shrink_factor;
  547.     if (rows <= 0) {
  548.         rows += shrink_factor;
  549.         --g->y2;
  550.     }
  551.     g->bitmap2.h = g->y2 + ROUNDUP((int) g->bitmap.h - cols, shrink_factor)
  552.         + 1;
  553.  
  554.     g->image2 = XCreateImage(DISP, DefaultVisualOfScreen(SCRN),
  555.                  (unsigned int) DefaultDepthOfScreen(SCRN),
  556.                  ZPixmap, 0, (char *) NULL,
  557.                  g->bitmap2.w, g->bitmap2.h,
  558.                  BITS_PER_BMUNIT, 0);
  559.     size = g->image2->bytes_per_line * g->bitmap2.h;
  560.     g->pixmap2 = g->image2->data = xmalloc(size != 0 ? size : 1,
  561.             "character pixmap");
  562.  
  563.     old_ptr = (BMUNIT *) g->bitmap.bits;
  564.     rows_left = g->bitmap.h;
  565.     y = 0;
  566.     while (rows_left) {
  567.         x = 0;
  568.         if (rows > rows_left) rows = rows_left;
  569.         cols_left = g->bitmap.w;
  570.         cols = init_cols;
  571.         while (cols_left) {
  572.         if (cols > cols_left) cols = cols_left;
  573.  
  574.         thesample = sample(old_ptr, g->bitmap.bytes_wide,
  575.             (int) g->bitmap.w - cols_left, cols, rows);
  576.         XPutPixel(g->image2, x, y, pixeltbl[thesample]);
  577.  
  578.         cols_left -= cols;
  579.         cols = shrink_factor;
  580.         x++;
  581.         }
  582.         *((char **) &old_ptr) += rows * g->bitmap.bytes_wide;
  583.         rows_left -= rows;
  584.         rows = shrink_factor;
  585.         y++;
  586.     }
  587.  
  588.     while (y < (int) g->bitmap2.h) {
  589.         for (x = 0; x < (int) g->bitmap2.w; x++)
  590.         XPutPixel(g->image2, x, y, *pixeltbl);
  591.         y++;
  592.     }
  593.  
  594.     g->y2 = g->y / shrink_factor;
  595. }
  596. #endif    /* GREY */
  597.  
  598. /*
  599.  *    Find font #n.
  600.  */
  601.  
  602. static    void
  603. change_font(n)
  604.     unsigned long n;
  605. {
  606.     register struct tn *tnp;
  607.  
  608.     if (n < currinf.tn_table_len) currinf.fontp = currinf.tn_table[n];
  609.     else {
  610.         currinf.fontp = NULL;
  611.         for (tnp = currinf.tn_head; tnp != NULL; tnp = tnp->next)
  612.         if (tnp->TeXnumber == n) {
  613.             currinf.fontp = tnp->fontp;
  614.             break;
  615.         }
  616.     }
  617.     if (currinf.fontp == NULL) tell_oops("non-existent font #%d", n);
  618.     maxchar = currinf.fontp->maxchar;
  619.     currinf.set_char_p = currinf.fontp->set_char_p;
  620. }
  621.  
  622.  
  623. /*
  624.  *    Open a font file.
  625.  */
  626.  
  627. static    void
  628. open_font_file(fontp)
  629.     struct font *fontp;
  630. {
  631.     if (fontp->file == NULL) {
  632.         fontp->file = xfopen(fontp->filename, OPEN_MODE);
  633.         if (fontp->file == NULL)
  634.         oops("Font file disappeared:  %s", fontp->filename);
  635.     }
  636. }
  637.  
  638.  
  639. /*
  640.  *    Routines to print characters.
  641.  */
  642.  
  643. #ifndef    TEXXET
  644. #define    ERRVAL    0L
  645. #else
  646. #define    ERRVAL
  647. #endif
  648.  
  649. #ifndef    TEXXET
  650. long
  651. set_char(ch)
  652. #else
  653. void
  654. set_char(cmd, ch)
  655.     wide_ubyte    cmd;
  656. #endif
  657.     wide_ubyte    ch;
  658. {
  659.     register struct glyph *g;
  660. #ifdef    TEXXET
  661.     long    dvi_h_sav;
  662. #endif
  663.  
  664.     if (ch > maxchar) realloc_font(currinf.fontp, WIDENINT ch);
  665.     if ((g = &currinf.fontp->glyph[ch])->bitmap.bits == NULL) {
  666.         if (g->addr == 0) {
  667.         if (!hush_chars)
  668.             Fprintf(stderr, "Character %d not defined in font %s\n", ch,
  669.             currinf.fontp->fontname);
  670.         g->addr = -1;
  671.         return ERRVAL;
  672.         }
  673.         if (g->addr == -1)
  674.         return ERRVAL;    /* previously flagged missing char */
  675.         open_font_file(currinf.fontp);
  676.         Fseek(currinf.fontp->file, g->addr, 0);
  677.         (*currinf.fontp->read_char)(currinf.fontp, ch);
  678.         if (debug & DBG_BITMAP) print_char((ubyte) ch, g);
  679.         currinf.fontp->timestamp = ++current_timestamp;
  680.     }
  681.  
  682. #ifdef    TEXXET
  683.     dvi_h_sav = DVI_H;
  684.     if (currinf.dir < 0) DVI_H -= g->dvi_adv;
  685.     if (scan_frame == NULL) {
  686. #endif
  687.         if (shrink_factor == 1)
  688.         put_bitmap(&g->bitmap, PXL_H - g->x, PXL_V - g->y);
  689.         else {
  690. #ifdef    GREY
  691.         if (use_grey) {
  692.             if (g->pixmap2 == NULL) {
  693.             shrink_glyph_grey(g);
  694.             }
  695.             put_image(g->image2, PXL_H - g->x2, PXL_V - g->y2);
  696.         } else {
  697.             if (g->bitmap2.bits == NULL) {
  698.             shrink_glyph(g);
  699.             }
  700.             put_bitmap(&g->bitmap2, PXL_H - g->x2, PXL_V - g->y2);
  701.         }
  702. #else
  703.         if (g->bitmap2.bits == NULL) {
  704.             shrink_glyph(g);
  705.         }
  706.         put_bitmap(&g->bitmap2, PXL_H - g->x2, PXL_V - g->y2);
  707. #endif
  708.         }
  709. #ifndef    TEXXET
  710.     return g->dvi_adv;
  711. #else
  712.     }
  713.     if (cmd == PUT1)
  714.         DVI_H = dvi_h_sav;
  715.     else
  716.         if (currinf.dir > 0) DVI_H += g->dvi_adv;
  717. #endif
  718. }
  719.  
  720.  
  721. /* ARGSUSED */
  722. #if    NeedFunctionPrototypes
  723. #ifndef    TEXXET
  724. static    long
  725. set_empty_char(wide_ubyte ch)
  726. #else
  727. static    void
  728. set_empty_char(wide_ubyte cmd, wide_ubyte ch)
  729. #endif    /* TEXXET */
  730. #else    /* !NeedFunctionPrototypes */
  731. #ifndef    TEXXET
  732. static    long
  733. set_empty_char(ch)
  734. #else
  735. static    void
  736. set_empty_char(cmd, ch)
  737.     wide_ubyte    cmd;
  738. #endif    /* TEXXET */
  739.     wide_ubyte    ch;
  740. #endif    /* NeedFunctionPrototypes */
  741. {
  742. #ifndef    TEXXET
  743.     return 0;
  744. #else
  745.     return;
  746. #endif
  747. }
  748.  
  749.  
  750. #ifndef    TEXXET
  751. long
  752. load_n_set_char(ch)
  753. #else
  754. void
  755. load_n_set_char(cmd, ch)
  756.     wide_ubyte    cmd;
  757. #endif
  758.     wide_ubyte    ch;
  759. {
  760.     if (load_font(currinf.fontp)) {    /* if not found */
  761.         Fputs("Character(s) will be left blank.\n", stderr);
  762.         currinf.set_char_p = currinf.fontp->set_char_p = set_empty_char;
  763. #ifndef    TEXXET
  764.         return 0;
  765. #else
  766.         return;
  767. #endif
  768.     }
  769.     maxchar = currinf.fontp->maxchar;
  770.     currinf.set_char_p = currinf.fontp->set_char_p;
  771. #ifndef    TEXXET
  772.     return (*currinf.set_char_p)(ch);
  773. #else
  774.     (*currinf.set_char_p)(cmd, ch);
  775.     return;
  776. #endif
  777. }
  778.  
  779.  
  780. #ifndef    TEXXET
  781. long
  782. set_vf_char(ch)
  783. #else
  784. void
  785. set_vf_char(cmd, ch)
  786.     wide_ubyte    cmd;
  787. #endif
  788.     wide_ubyte    ch;
  789. {
  790.     register struct macro *m;
  791.     struct drawinf    oldinfo;
  792.     ubyte    oldmaxchar;
  793.     static    ubyte    c;
  794. #ifdef    TEXXET
  795.     long    dvi_h_sav;
  796. #endif
  797.  
  798.     if (ch > maxchar) realloc_virtual_font(currinf.fontp, ch);
  799.     if ((m = &currinf.fontp->macro[ch])->pos == NULL) {
  800.         if (!hush_chars)
  801.         Fprintf(stderr, "Character %d not defined in font %s\n", ch,
  802.             currinf.fontp->fontname);
  803.         m->pos = m->end = &c;
  804.         return ERRVAL;
  805.     }
  806. #ifdef    TEXXET
  807.     dvi_h_sav = DVI_H;
  808.     if (currinf.dir < 0) DVI_H -= m->dvi_adv;
  809.     if (scan_frame == NULL) {
  810. #endif
  811.         oldinfo = currinf;
  812.         oldmaxchar = maxchar;
  813.         WW = XX = YY = ZZ = 0;
  814.         currinf.tn_table_len = VFTABLELEN;
  815.         currinf.tn_table = currinf.fontp->vf_table;
  816.         currinf.tn_head = currinf.fontp->vf_chain;
  817.         currinf.pos = m->pos;
  818.         currinf.end = m->end;
  819.         currinf.virtual = currinf.fontp;
  820.         draw_part(current_frame, currinf.fontp->dimconv);
  821.         if (currinf.pos != currinf.end + 1)
  822.         tell_oops("virtual character macro does not end correctly");
  823.         currinf = oldinfo;
  824.         maxchar = oldmaxchar;
  825. #ifndef    TEXXET
  826.     return m->dvi_adv;
  827. #else
  828.     }
  829.     if (cmd == PUT1)
  830.         DVI_H = dvi_h_sav;
  831.     else
  832.         if (currinf.dir > 0) DVI_H += m->dvi_adv;
  833. #endif
  834. }
  835.  
  836.  
  837. #if    NeedFunctionPrototypes
  838. #ifndef    TEXXET
  839. static    long
  840. set_no_char(wide_ubyte ch)
  841. #else
  842. static    void
  843. set_no_char(wide_ubyte cmd, wide_ubyte ch)
  844. #endif    /* TEXXET */
  845. #else    /* !NeedFunctionPrototypes */
  846. #ifndef    TEXXET
  847. static    long
  848. set_no_char(ch)
  849. #else
  850. static    void
  851. set_no_char(cmd, ch)
  852.     ubyte            cmd;
  853. #endif    /* TEXXET */
  854.     wide_ubyte    ch;
  855. #endif    /* NeedFunctionPrototypes */
  856. {
  857.     if (currinf.virtual) {
  858.         currinf.fontp = currinf.virtual->first_font;
  859.         if (currinf.fontp != NULL) {
  860.         maxchar = currinf.fontp->maxchar;
  861.         currinf.set_char_p = currinf.fontp->set_char_p;
  862. #ifndef    TEXXET
  863.         return (*currinf.set_char_p)(ch);
  864. #else
  865.         (*currinf.set_char_p)(cmd, ch);
  866.         return;
  867. #endif
  868.         }
  869.     }
  870.     tell_oops("attempt to set character of unknown font");
  871.     /* NOTREACHED */
  872. }
  873.  
  874.  
  875. /*
  876.  *    Set rule.  Arguments are coordinates of lower left corner.
  877.  */
  878.  
  879. static    void
  880. set_rule(h, w)
  881.     int h, w;
  882. {
  883. #ifndef    TEXXET
  884.     put_rule(PXL_H, PXL_V - h + 1, (unsigned int) w, (unsigned int) h);
  885. #else
  886.     put_rule(PXL_H - (currinf.dir < 0 ? w - 1 : 0), PXL_V - h + 1,
  887.         (unsigned int) w, (unsigned int) h);
  888. #endif
  889. }
  890.  
  891. static    void
  892. special(nbytes)
  893.     long    nbytes;
  894. {
  895.     static    char    *cmd    = NULL;
  896.     static    long    cmdlen    = -1;
  897.     char    *p;
  898.  
  899.     if (cmdlen < nbytes) {
  900.         if (cmd) free(cmd);
  901.         cmd = xmalloc((unsigned) nbytes + 1, "special");
  902.         cmdlen = nbytes;
  903.     }
  904.     p = cmd;
  905.     for (;;) {
  906.         int i = currinf.end - currinf.pos;
  907.  
  908.         if (i > nbytes) i = nbytes;
  909.         bcopy((char *) currinf.pos, p, i);
  910.         currinf.pos += i;
  911.         p += i;
  912.         nbytes -= i;
  913.         if (nbytes == 0) break;
  914.         (void) xxone();
  915.         --(currinf.pos);
  916.     }
  917.     *p = '\0';
  918.     applicationDoSpecial(cmd);
  919. }
  920.  
  921. #define    xspell_conv(n)    spell_conv0(n, current_dimconv)
  922.  
  923. static    void
  924. draw_part(minframe, current_dimconv)
  925.     struct frame    *minframe;
  926.     double        current_dimconv;
  927. {
  928.     ubyte ch;
  929. #ifdef    TEXXET
  930.     struct drawinf    oldinfo;
  931.     ubyte    oldmaxchar;
  932.     off_t    file_pos;
  933.     int    refl_count;
  934. #endif
  935.  
  936.     currinf.fontp = NULL;
  937.     currinf.set_char_p = set_no_char;
  938. #ifdef    TEXXET
  939.     currinf.dir = 1;
  940.     scan_frame = NULL;    /* indicates we're not scanning */
  941. #endif
  942.     for (;;) {
  943.         ch = xone();
  944.         if (debug & DBG_DVI)
  945.         print_dvi(ch);
  946.         if (ch <= (ubyte) (SETCHAR0 + 127))
  947. #ifndef    TEXXET
  948.         DVI_H += (*currinf.set_char_p)(ch);
  949. #else
  950.         (*currinf.set_char_p)(ch, ch);
  951. #endif
  952.         else if (FNTNUM0 <= ch && ch <= (ubyte) (FNTNUM0 + 63))
  953.         change_font((unsigned long) (ch - FNTNUM0));
  954.         else {
  955.         long a, b;
  956.  
  957.         switch (ch) {
  958.             case SET1:
  959.             case PUT1:
  960. #ifndef    TEXXET
  961.             a = (*currinf.set_char_p)(xone());
  962.             if (ch != PUT1) DVI_H += a;
  963. #else
  964.             (*currinf.set_char_p)(ch, xone());
  965. #endif
  966.             break;
  967.  
  968.             case SETRULE:
  969.             /* Be careful, dvicopy outputs rules with
  970.                height = 0x80000000.  We don't want any
  971.                SIGFPE here. */
  972.             a = xsfour();
  973.             b = xspell_conv(xsfour());
  974. #ifndef    TEXXET
  975.             if (a > 0 && b > 0)
  976. #else
  977.             if (a > 0 && b > 0 && scan_frame == NULL)
  978. #endif
  979.                 set_rule(pixel_round(xspell_conv(a)),
  980.                 pixel_round(b));
  981.             DVI_H += DIR * b;
  982.             break;
  983.  
  984.             case PUTRULE:
  985.             a = xspell_conv(xsfour());
  986.             b = xspell_conv(xsfour());
  987. #ifndef    TEXXET
  988.             if (a > 0 && b > 0)
  989. #else
  990.             if (a > 0 && b > 0 && scan_frame == NULL)
  991. #endif
  992.                 set_rule(pixel_round(a), pixel_round(b));
  993.             break;
  994.  
  995.             case NOP:
  996.             break;
  997.  
  998.             case BOP:
  999.             xskip((long) 11 * 4);
  1000.             DVI_H = OFFSET_X;
  1001.             DVI_V = OFFSET_Y;
  1002.             PXL_V = pixel_conv(DVI_V);
  1003.             WW = XX = YY = ZZ = 0;
  1004.             break;
  1005.  
  1006.             case EOP:
  1007.             if (current_frame != minframe)
  1008.                 tell_oops("stack not empty at EOP");
  1009. #if    PS
  1010.             psp.endpage();
  1011. #endif
  1012.             return;
  1013.  
  1014.             case PUSH:
  1015.             if (current_frame->next == NULL) {
  1016.                 struct frame *newp = (struct frame *)
  1017.                 xmalloc(sizeof(struct frame), "stack frame");
  1018.                 current_frame->next = newp;
  1019.                 newp->prev = current_frame;
  1020.                 newp->next = NULL;
  1021.             }
  1022.             current_frame = current_frame->next;
  1023.             current_frame->data = currinf.data;
  1024.             break;
  1025.  
  1026.             case POP:
  1027.             if (current_frame == minframe)
  1028.                 tell_oops("more POPs than PUSHes");
  1029.             currinf.data = current_frame->data;
  1030.             current_frame = current_frame->prev;
  1031.             break;
  1032.  
  1033. #ifdef    TEXXET
  1034.             case SREFL:
  1035.             if (scan_frame == NULL) {
  1036.                 /* we're not scanning:  save some info. */
  1037.                 oldinfo = currinf;
  1038.                 oldmaxchar = maxchar;
  1039.                 if (!currinf.virtual)
  1040.                 file_pos = xtell(currinf.pos);
  1041.                 scan_frame = current_frame; /* now we're scanning */
  1042.                 refl_count = 0;
  1043.                 break;
  1044.             }
  1045.             /* we are scanning */
  1046.             if (current_frame == scan_frame) ++refl_count;
  1047.             break;
  1048.  
  1049.             case EREFL:
  1050.             if (scan_frame != NULL) {    /* if we're scanning */
  1051.                 if (current_frame == scan_frame && --refl_count < 0)
  1052.                 {
  1053.                 /* we've hit the end of our scan */
  1054.                 scan_frame = NULL;
  1055.                 /* first:  push */
  1056.                 if (current_frame->next == NULL) {
  1057.                     struct frame *newp = (struct frame *)
  1058.                     xmalloc(sizeof(struct frame),
  1059.                         "stack frame");
  1060.                     current_frame->next = newp;
  1061.                     newp->prev = current_frame;
  1062.                     newp->next = NULL;
  1063.                 }
  1064.                 current_frame = current_frame->next;
  1065.                 current_frame->data = currinf.data;
  1066.                 /* next:  restore old file position, XX, etc. */
  1067.                 if (!currinf.virtual) {
  1068.                     off_t bgn_pos = xtell(dvi_buffer);
  1069.  
  1070.                     if (file_pos >= bgn_pos) {
  1071.                     oldinfo.pos = dvi_buffer
  1072.                         + (file_pos - bgn_pos);
  1073.                     oldinfo.end = currinf.end;
  1074.                     }
  1075.                     else {
  1076.                     (void) lseek(fileno(dvi_file), file_pos,
  1077.                         SEEK_SET);
  1078.                     oldinfo.pos = oldinfo.end;
  1079.                     }
  1080.                 }
  1081.                 currinf = oldinfo;
  1082.                 maxchar = oldmaxchar;
  1083.                 /* and then:  recover position info. */
  1084.                 DVI_H = current_frame->data.dvi_h;
  1085.                 DVI_V = current_frame->data.dvi_v;
  1086.                 PXL_V = current_frame->data.pxl_v;
  1087.                 /* and finally, reverse direction */
  1088.                 currinf.dir = -currinf.dir;
  1089.                 }
  1090.                 break;
  1091.             }
  1092.             /* we're not scanning, */
  1093.             /* so just reverse direction and then pop */
  1094.             currinf.dir = -currinf.dir;
  1095.             currinf.data = current_frame->data;
  1096.             current_frame = current_frame->prev;
  1097.             break;
  1098. #endif    /* TEXXET */
  1099.  
  1100.             case RIGHT1:
  1101.             case RIGHT2:
  1102.             case RIGHT3:
  1103.             case RIGHT4:
  1104.             DVI_H += DIR * xspell_conv(xsnum(ch - RIGHT1 + 1));
  1105.             break;
  1106.  
  1107.             case W1:
  1108.             case W2:
  1109.             case W3:
  1110.             case W4:
  1111.             WW = xspell_conv(xsnum(ch - W0));
  1112.             case W0:
  1113.             DVI_H += DIR * WW;
  1114.             break;
  1115.  
  1116.             case X1:
  1117.             case X2:
  1118.             case X3:
  1119.             case X4:
  1120.             XX = xspell_conv(xsnum(ch - X0));
  1121.             case X0:
  1122.             DVI_H += DIR * XX;
  1123.             break;
  1124.  
  1125.             case DOWN1:
  1126.             case DOWN2:
  1127.             case DOWN3:
  1128.             case DOWN4:
  1129.             DVI_V += xspell_conv(xsnum(ch - DOWN1 + 1));
  1130.             PXL_V = pixel_conv(DVI_V);
  1131.             break;
  1132.  
  1133.             case Y1:
  1134.             case Y2:
  1135.             case Y3:
  1136.             case Y4:
  1137.             YY = xspell_conv(xsnum(ch - Y0));
  1138.             case Y0:
  1139.             DVI_V += YY;
  1140.             PXL_V = pixel_conv(DVI_V);
  1141.             break;
  1142.  
  1143.             case Z1:
  1144.             case Z2:
  1145.             case Z3:
  1146.             case Z4:
  1147.             ZZ = xspell_conv(xsnum(ch - Z0));
  1148.             case Z0:
  1149.             DVI_V += ZZ;
  1150.             PXL_V = pixel_conv(DVI_V);
  1151.             break;
  1152.  
  1153.             case FNT1:
  1154.             case FNT2:
  1155.             case FNT3:
  1156.             case FNT4:
  1157.             change_font(xnum(ch - FNT1 + 1));
  1158.             break;
  1159.  
  1160.             case XXX1:
  1161.             case XXX2:
  1162.             case XXX3:
  1163.             case XXX4:
  1164.             a = xnum(ch - XXX1 + 1);
  1165.             if (a > 0)
  1166.                 special(a);
  1167.             break;
  1168.  
  1169.             case FNTDEF1:
  1170.             case FNTDEF2:
  1171.             case FNTDEF3:
  1172.             case FNTDEF4:
  1173.             xskip((long) (12 + ch - FNTDEF1 + 1));
  1174.             xskip((long) xone() + (long) xone());
  1175.             break;
  1176.  
  1177. #ifndef    TEXXET
  1178.             case SREFL:
  1179.             case EREFL:
  1180. #endif
  1181.             case PRE:
  1182.             case POST:
  1183.             case POSTPOST:
  1184.             tell_oops("shouldn't happen: %s encountered",
  1185.                 dvi_table2[ch - (FNTNUM0 + 64)]);
  1186.             break;
  1187.  
  1188.             default:
  1189.             tell_oops("unknown op-code %d", ch);
  1190.         } /* end switch*/
  1191.         } /* end else (ch not a SETCHAR or FNTNUM) */
  1192.     } /* end for */
  1193. }
  1194.  
  1195. #undef    xspell_conv
  1196.  
  1197. void
  1198. draw_page()
  1199. {
  1200.     /* Check for changes in dvi file. */
  1201.     if (!check_dvi_file()) return;
  1202.  
  1203.     put_border(-currwin.base_x, -currwin.base_y,
  1204.         ROUNDUP(unshrunk_paper_w, shrink_factor) + 2,
  1205.         ROUNDUP(unshrunk_paper_h, shrink_factor) + 2, highGC);
  1206.  
  1207.     (void) lseek(fileno(dvi_file), page_offset[current_page], SEEK_SET);
  1208.  
  1209.     bzero((char *) &currinf.data, sizeof(currinf.data));
  1210.     currinf.tn_table_len = TNTABLELEN;
  1211.     currinf.tn_table = tn_table;
  1212.     currinf.tn_head = tn_head;
  1213.     currinf.pos = currinf.end = dvi_buffer;
  1214.     currinf.virtual = NULL;
  1215.     draw_part(current_frame = &frame0, dimconv);
  1216. }
  1217.