summaryrefslogtreecommitdiff
path: root/systems/msdos/dviware/xdvi-dos/src/dvi_draw.c
diff options
context:
space:
mode:
Diffstat (limited to 'systems/msdos/dviware/xdvi-dos/src/dvi_draw.c')
-rw-r--r--systems/msdos/dviware/xdvi-dos/src/dvi_draw.c1049
1 files changed, 1049 insertions, 0 deletions
diff --git a/systems/msdos/dviware/xdvi-dos/src/dvi_draw.c b/systems/msdos/dviware/xdvi-dos/src/dvi_draw.c
new file mode 100644
index 0000000000..4c8b0989a7
--- /dev/null
+++ b/systems/msdos/dviware/xdvi-dos/src/dvi_draw.c
@@ -0,0 +1,1049 @@
+/*
+ * DVI previewer for X.
+ *
+ * Eric Cooper, CMU, September 1985.
+ *
+ * Code derived from dvi-imagen.c.
+ *
+ * Modification history:
+ * 1/1986 Modified for X.10 --Bob Scheifler, MIT LCS.
+ * 7/1988 Modified for X.11 --Mark Eichin, MIT
+ * 12/1988 Added 'R' option, toolkit, magnifying glass
+ * --Paul Vojta, UC Berkeley.
+ * 2/1989 Added tpic support --Jeffrey Lee, U of Toronto
+ * 4/1989 Modified for System V --Donald Richardson, Clarkson Univ.
+ * 3/1990 Added VMS support --Scott Allendorf, U of Iowa
+ * 7/1990 Added reflection mode --Michael Pak, Hebrew U of Jerusalem
+ * 1/1992 Added greyscale code --Till Brychcy, Techn. Univ. Muenchen
+ * and Lee Hetherington, MIT
+ *
+ * Compilation options:
+ * SYSV compile for System V
+ * VMS compile for VMS
+ * X10 compile for X10
+ * NOTOOL compile without toolkit (X11 only)
+ * BUTTONS compile with buttons on the side of the window (needs toolkit)
+ * MSBITFIRST store bitmaps internally with most significant bit first
+ * BMSHORT store bitmaps in shorts instead of bytes
+ * BMLONG store bitmaps in longs instead of bytes
+ * ALTFONT default for -altfont option
+ * A4 use European size paper
+ * TEXXET support reflection dvi codes (right-to-left typesetting)
+ * GREY use grey levels to shrink fonts
+ */
+
+#include <ctype.h>
+#include "xdvi.h"
+#include "dvi.h"
+
+#ifndef X_NOT_STDC_ENV
+#include <stdlib.h>
+#endif
+
+#if NeedVarargsPrototypes /* this is for tell_oops */
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef DOPRNT /* define this if vfprintf gives you trouble */
+#define vfprintf(stream, message, args) _doprnt(message, args, stream)
+#endif
+
+static struct frame frame0; /* dummy head of list */
+#ifdef TEXXET
+static struct frame *scan_frame; /* head frame for scanning */
+#endif
+
+#ifndef DVI_BUFFER_LEN
+#define DVI_BUFFER_LEN 512
+#endif
+
+static ubyte dvi_buffer[DVI_BUFFER_LEN];
+static struct frame *current_frame;
+
+#ifndef TEXXET
+#define DIR 1
+#else
+#define DIR currinf.dir
+#endif
+
+/*
+ * Explanation of the following constant:
+ * offset_[xy] << 16: margin (defaults to one inch)
+ * shrink_factor << 16: one pixel page border
+ * shrink_factor << 15: rounding for pixel_conv
+ */
+#define OFFSET_X (offset_x << 16) + (shrink_factor * 3 << 15)
+#define OFFSET_Y (offset_y << 16) + (shrink_factor * 3 << 15)
+
+#ifndef BMLONG
+#ifndef BMSHORT
+unsigned char bit_masks[9] = {
+ 0x0, 0x1, 0x3, 0x7,
+ 0xf, 0x1f, 0x3f, 0x7f,
+ 0xff
+};
+#else /* BMSHORT */
+unsigned short bit_masks[17] = {
+ 0x0, 0x1, 0x3, 0x7,
+ 0xf, 0x1f, 0x3f, 0x7f,
+ 0xff, 0x1ff, 0x3ff, 0x7ff,
+ 0xfff, 0x1fff, 0x3fff, 0x7fff,
+ 0xffff
+};
+#endif /* BMSHORT */
+#else /* BMLONG */
+unsigned long bit_masks[33] = {
+ 0x0, 0x1, 0x3, 0x7,
+ 0xf, 0x1f, 0x3f, 0x7f,
+ 0xff, 0x1ff, 0x3ff, 0x7ff,
+ 0xfff, 0x1fff, 0x3fff, 0x7fff,
+ 0xffff, 0x1ffff, 0x3ffff, 0x7ffff,
+ 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff,
+ 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff,
+ 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
+ 0xffffffff
+};
+#endif /* BMLONG */
+
+#ifdef VMS
+#define off_t int
+#endif
+extern off_t lseek();
+
+#ifndef SEEK_SET /* if <unistd.h> is not provided (or for <X11R5) */
+#define SEEK_SET 0
+#define SEEK_CUR 1
+#define SEEK_END 2
+#endif
+
+static void draw_part();
+
+/*
+ * Byte reading routines for dvi file.
+ */
+
+#define xtell(pos) (lseek(fileno(dvi_file), 0L, SEEK_CUR) - \
+ (currinf.end - (pos)))
+
+static ubyte
+xxone()
+{
+ if (currinf.virtual) {
+ ++currinf.pos;
+ return EOP;
+ }
+ currinf.end = dvi_buffer +
+ read(fileno(dvi_file), (char *) (currinf.pos = dvi_buffer),
+ DVI_BUFFER_LEN);
+ return currinf.end > dvi_buffer ? *(currinf.pos)++ : EOF;
+}
+
+#define xone() (currinf.pos < currinf.end ? *(currinf.pos)++ : xxone())
+
+static unsigned long
+xnum(size)
+ register ubyte size;
+{
+ register long x = 0;
+
+ while (size--) x = (x << 8) | xone();
+ return x;
+}
+
+static long
+xsnum(size)
+ register ubyte size;
+{
+ register long x;
+
+#ifdef __STDC__
+ x = (signed char) xone();
+#else
+ x = xone();
+ if (x & 0x80) x -= 0x100;
+#endif
+ while (--size) x = (x << 8) | xone();
+ return x;
+}
+
+#define xsfour() xsnum(4)
+
+static void
+xskip(offset)
+ long offset;
+{
+ currinf.pos += offset;
+ if (!currinf.virtual && currinf.pos > currinf.end)
+ (void) lseek(fileno(dvi_file), (long) (currinf.pos - currinf.end),
+ SEEK_CUR);
+}
+
+#if NeedVarargsPrototypes
+static NORETURN void
+tell_oops(_Xconst char *message, ...)
+#else
+/* VARARGS */
+static NORETURN void
+tell_oops(va_alist)
+ va_dcl
+#endif
+{
+#if !NeedVarargsPrototypes
+ _Xconst char *message;
+#endif
+ va_list args;
+
+ Fprintf(stderr, "%s: ", prog);
+#if NeedVarargsPrototypes
+ va_start(args, message);
+#else
+ va_start(args);
+ message = va_arg(args, _Xconst char *);
+#endif
+ (void) vfprintf(stderr, message, args);
+ va_end(args);
+ if (currinf.virtual)
+ Fprintf(stderr, " in virtual font %s\n", currinf.virtual->fontname);
+ else
+ Fprintf(stderr, ", offset %ld\n", xtell(currinf.pos - 1));
+ exit(1);
+}
+
+
+/*
+ * Code for debugging options.
+ */
+
+static void
+print_bitmap(bitmap)
+ register struct bitmap *bitmap;
+{
+ register BMUNIT *ptr = (BMUNIT *) bitmap->bits;
+ register int x, y, i;
+
+ if (ptr == NULL) oops("print_bitmap called with null pointer.");
+ Printf("w = %d, h = %d, bytes wide = %d\n",
+ bitmap->w, bitmap->h, bitmap->bytes_wide);
+ for (y = 0; y < bitmap->h; ++y) {
+ for (x = bitmap->bytes_wide; x > 0; x -= BYTES_PER_BMUNIT) {
+#ifndef MSBITFIRST
+ for (i = 0; i < BITS_PER_BMUNIT; ++i)
+#else
+ for (i = BITS_PER_BMUNIT - 1; i >= 0; --i)
+#endif
+ Putchar((*ptr & (1 << i)) ? '@' : ' ');
+ ++ptr;
+ }
+ Putchar('\n');
+ }
+}
+
+static void
+print_char(ch, g)
+ ubyte ch;
+ struct glyph *g;
+{
+ Printf("char %d", ch);
+ if (isprint(ch))
+ Printf(" (%c)", ch);
+ Putchar('\n');
+ Printf("x = %d, y = %d, dvi = %ld\n", g->x, g->y, g->dvi_adv);
+ print_bitmap(&g->bitmap);
+}
+
+static _Xconst char *dvi_table1[] = {
+ "SET1", NULL, NULL, NULL, "SETRULE", "PUT1", NULL, NULL,
+ NULL, "PUTRULE", "NOP", "BOP", "EOP", "PUSH", "POP", "RIGHT1",
+ "RIGHT2", "RIGHT3", "RIGHT4", "W0", "W1", "W2", "W3", "W4",
+ "X0", "X1", "X2", "X3", "X4", "DOWN1", "DOWN2", "DOWN3",
+ "DOWN4", "Y0", "Y1", "Y2", "Y3", "Y4", "Z0", "Z1",
+ "Z2", "Z3", "Z4"};
+
+static _Xconst char *dvi_table2[] = {
+ "FNT1", "FNT2", "FNT3", "FNT4", "XXX1", "XXX2", "XXX3", "XXX4",
+ "FNTDEF1", "FNTDEF2", "FNTDEF3", "FNTDEF4", "PRE", "POST", "POSTPOST",
+ "SREFL", "EREFL", NULL, NULL, NULL, NULL};
+
+static void
+print_dvi(ch)
+ ubyte ch;
+{
+ _Xconst char *s;
+
+ Printf("%4d %4d ", PXL_H, PXL_V);
+ if (ch <= SETCHAR0 + 127) {
+ Printf("SETCHAR%-3d", ch - SETCHAR0);
+ if (isprint(ch))
+ Printf(" (%c)", ch);
+ Putchar('\n');
+ return;
+ }
+ else if (ch < FNTNUM0) s = dvi_table1[ch - 128];
+ else if (ch <= FNTNUM0 + 63) {
+ Printf("FNTNUM%d\n", ch - FNTNUM0);
+ return;
+ }
+ else s = dvi_table2[ch - (FNTNUM0 + 64)];
+ if (s) Puts(s);
+ else
+ tell_oops("unknown op-code %d", ch);
+}
+
+
+/*
+ * Count the number of set bits in a given region of the bitmap
+ */
+
+char sample_count[] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
+
+static int
+sample(bits, bytes_wide, bit_skip, w, h)
+ BMUNIT *bits;
+ int bytes_wide, bit_skip, w, h;
+{
+ BMUNIT *ptr, *endp;
+ register BMUNIT *cp;
+ int bits_left;
+ register int n, bit_shift, wid;
+
+ ptr = bits + bit_skip / BITS_PER_BMUNIT;
+ endp = ADD(bits, h * bytes_wide);
+ bits_left = w;
+#ifndef MSBITFIRST
+ bit_shift = bit_skip % BITS_PER_BMUNIT;
+#else
+ bit_shift = BITS_PER_BMUNIT - bit_skip % BITS_PER_BMUNIT;
+#endif
+ n = 0;
+ while (bits_left) {
+#ifndef MSBITFIRST
+ wid = BITS_PER_BMUNIT - bit_shift;
+#else
+ wid = bit_shift;
+#endif
+ if (wid > bits_left) wid = bits_left;
+ if (wid > 4) wid = 4;
+#ifdef MSBITFIRST
+ bit_shift -= wid;
+#endif
+ for (cp = ptr; cp < endp; cp = ADD(cp, bytes_wide))
+ n += sample_count[(*cp >> bit_shift) & bit_masks[wid]];
+#ifndef MSBITFIRST
+ bit_shift += wid;
+ if (bit_shift == BITS_PER_BMUNIT) {
+ bit_shift = 0;
+ ++ptr;
+ }
+#else
+ if (bit_shift == 0) {
+ bit_shift = BITS_PER_BMUNIT;
+ ++ptr;
+ }
+#endif
+ bits_left -= wid;
+ }
+ return n;
+}
+
+#ifdef GREY
+static void
+shrink_glyph_grey(g)
+ register struct glyph *g;
+{
+ int rows_left, rows, init_cols, cols_left;
+ register int cols;
+ int x, y;
+ long thesample;
+ BMUNIT *old_ptr;
+
+ /* These machinations ensure that the character is shrunk according to
+ its hot point, rather than its upper left-hand corner. */
+ g->x2 = g->x / shrink_factor;
+ init_cols = g->x - g->x2 * shrink_factor;
+ if (init_cols <= 0) init_cols += shrink_factor;
+ else ++g->x2;
+ g->bitmap2.w = g->x2 + ROUNDUP(g->bitmap.w - g->x, shrink_factor);
+ /* include row zero with the positively numbered rows */
+ cols = g->y + 1; /* spare register variable */
+ g->y2 = cols / shrink_factor;
+ rows = cols - g->y2 * shrink_factor;
+ if (rows <= 0) {
+ rows += shrink_factor;
+ --g->y2;
+ }
+ g->bitmap2.h = g->y2 + ROUNDUP(g->bitmap.h - cols, shrink_factor) + 1;
+
+ g->image2 = XCreateImage(DISP, DefaultVisualOfScreen(SCRN),
+ DefaultDepthOfScreen(SCRN),
+ ZPixmap, 0, (char *) NULL,
+ g->bitmap2.w, g->bitmap2.h,
+ BITS_PER_BMUNIT, 0);
+ g->pixmap2 = g->image2->data = xmalloc((unsigned)
+ g->image2->bytes_per_line * g->bitmap2.h,
+ "character pixmap");
+
+ old_ptr = (BMUNIT *) g->bitmap.bits;
+ rows_left = g->bitmap.h;
+ y = 0;
+ while (rows_left) {
+ x = 0;
+ if (rows > rows_left) rows = rows_left;
+ cols_left = g->bitmap.w;
+ cols = init_cols;
+ while (cols_left) {
+ if (cols > cols_left) cols = cols_left;
+
+ thesample = sample(old_ptr, g->bitmap.bytes_wide,
+ g->bitmap.w - cols_left, cols, rows);
+ XPutPixel(g->image2, x, y, pixeltbl[thesample]);
+
+ cols_left -= cols;
+ cols = shrink_factor;
+ x++;
+ }
+ *((char **) &old_ptr) += rows * g->bitmap.bytes_wide;
+ rows_left -= rows;
+ rows = shrink_factor;
+ y++;
+ }
+
+ while (y < g->bitmap2.h) {
+ for (x = 0; x < g->bitmap2.w; x++)
+ XPutPixel(g->image2, x, y, *pixeltbl);
+ y++;
+ }
+
+ g->y2 = g->y / shrink_factor;
+}
+#endif /* GREY */
+
+static void
+shrink_glyph(g)
+ register struct glyph *g;
+{
+ int shrunk_bytes_wide, shrunk_height;
+ int rows_left, rows, init_cols, cols_left;
+ register int cols;
+ BMUNIT *old_ptr, *new_ptr;
+ register BMUNIT m, *cp;
+ int min_sample = shrink_factor * shrink_factor * density / 100;
+
+ /* These machinations ensure that the character is shrunk according to
+ its hot point, rather than its upper left-hand corner. */
+ g->x2 = g->x / shrink_factor;
+ init_cols = g->x - g->x2 * shrink_factor;
+ if (init_cols <= 0) init_cols += shrink_factor;
+ else ++g->x2;
+ g->bitmap2.w = g->x2 + ROUNDUP(g->bitmap.w - g->x, shrink_factor);
+ /* include row zero with the positively numbered rows */
+ cols = g->y + 1; /* spare register variable */
+ g->y2 = cols / shrink_factor;
+ rows = cols - g->y2 * shrink_factor;
+ if (rows <= 0) {
+ rows += shrink_factor;
+ --g->y2;
+ }
+ g->bitmap2.h = shrunk_height = g->y2 +
+ ROUNDUP(g->bitmap.h - cols, shrink_factor) + 1;
+ alloc_bitmap(&g->bitmap2);
+ old_ptr = (BMUNIT *) g->bitmap.bits;
+ new_ptr = (BMUNIT *) g->bitmap2.bits;
+ shrunk_bytes_wide = g->bitmap2.bytes_wide;
+ rows_left = g->bitmap.h;
+ bzero((char *) new_ptr, shrunk_bytes_wide * shrunk_height);
+ while (rows_left) {
+ if (rows > rows_left) rows = rows_left;
+ cols_left = g->bitmap.w;
+#ifndef MSBITFIRST
+ m = (1 << 0);
+#else
+ m = (1 << (BITS_PER_BMUNIT-1));
+#endif
+ cp = new_ptr;
+ cols = init_cols;
+ while (cols_left) {
+ if (cols > cols_left) cols = cols_left;
+ if (sample(old_ptr, g->bitmap.bytes_wide,
+ g->bitmap.w - cols_left, cols, rows) >= min_sample)
+ *cp |= m;
+#ifndef MSBITFIRST
+ if (m == (BMUNIT)(1 << (BITS_PER_BMUNIT-1))) {
+ m = (1 << 0);
+ ++cp;
+ }
+ else m <<= 1;
+#else
+ if (m == (1 << 0)) {
+ m = (1 << (BITS_PER_BMUNIT-1));
+ ++cp;
+ }
+ else m >>= 1;
+#endif
+ cols_left -= cols;
+ cols = shrink_factor;
+ }
+ *((char **) &new_ptr) += shrunk_bytes_wide;
+ *((char **) &old_ptr) += rows * g->bitmap.bytes_wide;
+ rows_left -= rows;
+ rows = shrink_factor;
+ }
+ g->y2 = g->y / shrink_factor;
+ if (debug & DBG_BITMAP)
+ print_bitmap(&g->bitmap2);
+}
+
+/*
+ * Find font #n.
+ */
+
+static void
+change_font(n)
+ unsigned long n;
+{
+ register struct tn *tnp;
+
+ currinf.fontp = NULL;
+ for (tnp = currinf.tn_head; tnp != NULL; tnp = tnp->next)
+ if (tnp->TeXnumber == n) {
+ currinf.fontp = tnp->fontp;
+ if (!(currinf.fontp->flags & FONT_LOADED))
+ load_font(currinf.fontp);
+ break;
+ }
+ if (currinf.fontp == NULL) tell_oops("non-existent font #%d", n);
+ maxchar = currinf.fontp->maxchar;
+ currinf.set_char_p = currinf.fontp->set_char_p;
+}
+
+
+/*
+ * Open a font file.
+ */
+
+static void
+open_font_file(fontp)
+ struct font *fontp;
+{
+ if (fontp->file == NULL) {
+ fontp->file = xfopen(fontp->filename);
+ if (fontp->file == NULL)
+ oops("Font file disappeared: %s", fontp->filename);
+ }
+}
+
+
+/*
+ * Routines to print characters.
+ */
+
+#ifndef TEXXET
+#define ERRVAL 0L
+#else
+#define ERRVAL
+#endif
+
+#ifndef TEXXET
+long
+set_char(ch)
+#else
+void
+set_char(cmd, ch)
+ WIDEARG(ubyte, int) cmd;
+#endif
+ WIDEARG(ubyte, int) ch;
+{
+ register struct glyph *g;
+#ifdef TEXXET
+ long dvi_h_sav;
+#endif
+
+ if (ch > maxchar) realloc_font(currinf.fontp, WIDEARG(,(int)) ch);
+ if ((g = &currinf.fontp->glyph[ch])->bitmap.bits == NULL) {
+ if (g->addr == 0) {
+ if (!hush_chars)
+ Fprintf(stderr, "Character %d not defined in font %s\n", ch,
+ currinf.fontp->fontname);
+ g->addr = -1;
+ return ERRVAL;
+ }
+ if (g->addr == -1)
+ return ERRVAL; /* previously flagged missing char */
+ open_font_file(currinf.fontp);
+ Fseek(currinf.fontp->file, g->addr, 0);
+ (*currinf.fontp->read_char)(currinf.fontp, ch);
+ if (debug & DBG_BITMAP) print_char((ubyte) ch, g);
+ currinf.fontp->timestamp = ++current_timestamp;
+ }
+
+#ifdef TEXXET
+ dvi_h_sav = DVI_H;
+ if (currinf.dir < 0) DVI_H -= g->dvi_adv;
+ if (scan_frame == NULL) {
+#endif
+ if (shrink_factor == 1)
+ put_bitmap(&g->bitmap, PXL_H - g->x, PXL_V - g->y);
+ else {
+#ifdef GREY
+ if (use_grey) {
+ if (g->pixmap2 == NULL) {
+ shrink_glyph_grey(g);
+ }
+ put_image(g->image2, PXL_H - g->x2, PXL_V - g->y2);
+ } else {
+ if (g->bitmap2.bits == NULL) {
+ shrink_glyph(g);
+ }
+ put_bitmap(&g->bitmap2, PXL_H - g->x2, PXL_V - g->y2);
+ }
+#else
+ if (g->bitmap2.bits == NULL) {
+ shrink_glyph(g);
+ }
+ put_bitmap(&g->bitmap2, PXL_H - g->x2, PXL_V - g->y2);
+#endif
+ }
+#ifndef TEXXET
+ return g->dvi_adv;
+#else
+ }
+ if (cmd == PUT1)
+ DVI_H = dvi_h_sav;
+ else
+ if (currinf.dir > 0) DVI_H += g->dvi_adv;
+#endif
+}
+
+
+#ifndef TEXXET
+long
+set_vf_char(ch)
+#else
+void
+set_vf_char(cmd, ch)
+ WIDEARG(ubyte, int) cmd;
+#endif
+ WIDEARG(ubyte, int) ch;
+{
+ register struct macro *m;
+ struct drawinf oldinfo;
+ ubyte oldmaxchar;
+ static ubyte c;
+#ifdef TEXXET
+ long dvi_h_sav;
+#endif
+
+ if (ch > maxchar) realloc_virtual_font(currinf.fontp, ch);
+ if ((m = &currinf.fontp->macro[ch])->pos == NULL) {
+ if (!hush_chars)
+ Fprintf(stderr, "Character %d not defined in font %s\n", ch,
+ currinf.fontp->fontname);
+ m->pos = m->end = &c;
+ return ERRVAL;
+ }
+#ifdef TEXXET
+ dvi_h_sav = DVI_H;
+ if (currinf.dir < 0) DVI_H -= m->dvi_adv;
+ if (scan_frame == NULL) {
+#endif
+ oldinfo = currinf;
+ oldmaxchar = maxchar;
+ WW = XX = YY = ZZ = 0;
+ currinf.tn_head = currinf.fontp->vf_chain;
+ currinf.pos = m->pos;
+ currinf.end = m->end;
+ currinf.virtual = currinf.fontp;
+ draw_part(current_frame, currinf.fontp->dimconv);
+ if (currinf.pos != currinf.end + 1)
+ tell_oops("virtual character macro does not end correctly");
+ currinf = oldinfo;
+ maxchar = oldmaxchar;
+#ifndef TEXXET
+ return m->dvi_adv;
+#else
+ }
+ if (cmd == PUT1)
+ DVI_H = dvi_h_sav;
+ else
+ if (currinf.dir > 0) DVI_H += m->dvi_adv;
+#endif
+}
+
+
+#ifndef TEXXET
+static long
+set_no_char(ch)
+#else
+static void
+set_no_char(cmd, ch)
+ ubyte cmd;
+#endif
+ ubyte ch;
+{
+ if (currinf.virtual) {
+ currinf.fontp = currinf.virtual->first_font;
+ if (currinf.fontp != NULL) {
+ if (!(currinf.fontp->flags & FONT_LOADED))
+ load_font(currinf.fontp);
+ maxchar = currinf.fontp->maxchar;
+ currinf.set_char_p = currinf.fontp->set_char_p;
+#ifndef TEXXET
+ return (*currinf.set_char_p)(ch);
+#else
+ (*currinf.set_char_p)(cmd, ch);
+ return;
+#endif
+ }
+ }
+ tell_oops("attempt to set character of unknown font");
+ /* NOTREACHED */
+}
+
+
+/*
+ * Set rule. Arguments are coordinates of lower left corner.
+ */
+
+static void
+set_rule(h, w)
+ int h, w;
+{
+#ifndef TEXXET
+ put_rectangle(PXL_H, PXL_V - h + 1, w, h, False);
+#else
+ put_rectangle(PXL_H - (currinf.dir < 0 ? w - 1 : 0), PXL_V - h + 1,
+ w, h, False);
+#endif
+}
+
+static void
+put_border(w, h)
+ int w, h;
+{
+ put_rectangle(0, 0, w, 1, True); /* top */
+ put_rectangle(w, 0, 1, h, True); /* right */
+ put_rectangle(1, h, w, 1, True); /* bottom */
+ put_rectangle(0, 1, 1, h, True); /* left */
+}
+
+static void
+special(nbytes)
+ long nbytes;
+{
+ static char *cmd = NULL;
+ static long cmdlen = -1;
+ char *p;
+
+ if (cmdlen < nbytes) {
+ if (cmd) free(cmd);
+ cmd = xmalloc((unsigned) nbytes + 1, "special");
+ cmdlen = nbytes;
+ }
+ p = cmd;
+ for (;;) {
+ int i = currinf.end - currinf.pos;
+
+ if (i > nbytes) i = nbytes;
+ bcopy((_Xconst char *) currinf.pos, p, i);
+ currinf.pos += i;
+ p += i;
+ nbytes -= i;
+ if (nbytes == 0) break;
+ (void) xxone();
+ --(currinf.pos);
+ }
+ *p = '\0';
+ applicationDoSpecial(cmd);
+}
+
+#define xspell_conv(n) spell_conv0(n, current_dimconv)
+
+static void
+draw_part(minframe, current_dimconv)
+ struct frame *minframe;
+ double current_dimconv;
+{
+ ubyte ch;
+#ifdef TEXXET
+ struct drawinf oldinfo;
+ ubyte oldmaxchar;
+ off_t file_pos;
+ int refl_count;
+#endif
+
+ currinf.fontp = NULL;
+ currinf.set_char_p = set_no_char;
+#ifdef TEXXET
+ currinf.dir = 1;
+ scan_frame = NULL; /* indicates we're not scanning */
+#endif
+ for (;;) {
+ ch = xone();
+ if (debug & DBG_DVI)
+ print_dvi(ch);
+ if (ch <= SETCHAR0 + 127)
+#ifndef TEXXET
+ DVI_H += (*currinf.set_char_p)(ch);
+#else
+ (*currinf.set_char_p)(ch, ch);
+#endif
+ else if (FNTNUM0 <= ch && ch <= FNTNUM0 + 63)
+ change_font((unsigned long) (ch - FNTNUM0));
+ else {
+ long a, b;
+
+ switch (ch) {
+ case SET1:
+ case PUT1:
+#ifndef TEXXET
+ a = (*currinf.set_char_p)(xone());
+ if (ch != PUT1) DVI_H += a;
+#else
+ (*currinf.set_char_p)(ch, xone());
+#endif
+ break;
+
+ case SETRULE:
+ /* Be careful, dvicopy outputs rules with
+ height = 0x80000000. We don't want any
+ SIGFPE here. */
+ a = xsfour();
+ b = xspell_conv(xsfour());
+#ifndef TEXXET
+ if (a > 0 && b > 0)
+#else
+ if (a > 0 && b > 0 && scan_frame == NULL)
+#endif
+ set_rule(pixel_round(xspell_conv(a)),
+ pixel_round(b));
+ DVI_H += DIR * b;
+ break;
+
+ case PUTRULE:
+ a = xspell_conv(xsfour());
+ b = xspell_conv(xsfour());
+#ifndef TEXXET
+ if (a > 0 && b > 0)
+#else
+ if (a > 0 && b > 0 && scan_frame == NULL)
+#endif
+ set_rule(pixel_round(a), pixel_round(b));
+ break;
+
+ case NOP:
+ break;
+
+ case BOP:
+ xskip((long) 11 * 4);
+ DVI_H = OFFSET_X;
+ DVI_V = OFFSET_Y;
+ PXL_V = pixel_conv(DVI_V);
+ WW = XX = YY = ZZ = 0;
+ break;
+
+ case EOP:
+ if (current_frame != minframe)
+ tell_oops("stack not empty at EOP");
+ return;
+
+ case PUSH:
+ if (current_frame->next == NULL) {
+ struct frame *newp = (struct frame *)
+ xmalloc(sizeof(struct frame), "stack frame");
+ current_frame->next = newp;
+ newp->prev = current_frame;
+ newp->next = NULL;
+ }
+ current_frame = current_frame->next;
+ current_frame->data = currinf.data;
+ break;
+
+ case POP:
+ if (current_frame == minframe)
+ tell_oops("more POPs than PUSHes");
+ currinf.data = current_frame->data;
+ current_frame = current_frame->prev;
+ break;
+
+#ifdef TEXXET
+ case SREFL:
+ if (scan_frame == NULL) {
+ /* we're not scanning: save some info. */
+ oldinfo = currinf;
+ oldmaxchar = maxchar;
+ if (!currinf.virtual)
+ file_pos = xtell(currinf.pos);
+ scan_frame = current_frame; /* now we're scanning */
+ refl_count = 0;
+ break;
+ }
+ /* we are scanning */
+ if (current_frame == scan_frame) ++refl_count;
+ break;
+
+ case EREFL:
+ if (scan_frame != NULL) { /* if we're scanning */
+ if (current_frame == scan_frame && --refl_count < 0)
+ {
+ /* we've hit the end of our scan */
+ scan_frame = NULL;
+ /* first: push */
+ if (current_frame->next == NULL) {
+ struct frame *newp = (struct frame *)
+ xmalloc(sizeof(struct frame),
+ "stack frame");
+ current_frame->next = newp;
+ newp->prev = current_frame;
+ newp->next = NULL;
+ }
+ current_frame = current_frame->next;
+ current_frame->data = currinf.data;
+ /* next: restore old file position, XX, etc. */
+ if (!currinf.virtual) {
+ off_t bgn_pos = xtell(dvi_buffer);
+
+ if (file_pos >= bgn_pos) {
+ oldinfo.pos = dvi_buffer
+ + (file_pos - bgn_pos);
+ oldinfo.end = currinf.end;
+ }
+ else {
+ (void) lseek(fileno(dvi_file), file_pos,
+ SEEK_SET);
+ oldinfo.pos = oldinfo.end;
+ }
+ }
+ currinf = oldinfo;
+ maxchar = oldmaxchar;
+ /* and then: recover position info. */
+ DVI_H = current_frame->data.dvi_h;
+ DVI_V = current_frame->data.dvi_v;
+ PXL_V = current_frame->data.pxl_v;
+ /* and finally, reverse direction */
+ currinf.dir = -currinf.dir;
+ }
+ break;
+ }
+ /* we're not scanning, */
+ /* so just reverse direction and then pop */
+ currinf.dir = -currinf.dir;
+ currinf.data = current_frame->data;
+ current_frame = current_frame->prev;
+ break;
+#endif /* TEXXET */
+
+ case RIGHT1:
+ case RIGHT2:
+ case RIGHT3:
+ case RIGHT4:
+ DVI_H += DIR * xspell_conv(xsnum(ch - RIGHT1 + 1));
+ break;
+
+ case W1:
+ case W2:
+ case W3:
+ case W4:
+ WW = xspell_conv(xsnum(ch - W0));
+ case W0:
+ DVI_H += DIR * WW;
+ break;
+
+ case X1:
+ case X2:
+ case X3:
+ case X4:
+ XX = xspell_conv(xsnum(ch - X0));
+ case X0:
+ DVI_H += DIR * XX;
+ break;
+
+ case DOWN1:
+ case DOWN2:
+ case DOWN3:
+ case DOWN4:
+ DVI_V += xspell_conv(xsnum(ch - DOWN1 + 1));
+ PXL_V = pixel_conv(DVI_V);
+ break;
+
+ case Y1:
+ case Y2:
+ case Y3:
+ case Y4:
+ YY = xspell_conv(xsnum(ch - Y0));
+ case Y0:
+ DVI_V += YY;
+ PXL_V = pixel_conv(DVI_V);
+ break;
+
+ case Z1:
+ case Z2:
+ case Z3:
+ case Z4:
+ ZZ = xspell_conv(xsnum(ch - Z0));
+ case Z0:
+ DVI_V += ZZ;
+ PXL_V = pixel_conv(DVI_V);
+ break;
+
+ case FNT1:
+ case FNT2:
+ case FNT3:
+ case FNT4:
+ change_font(xnum(ch - FNT1 + 1));
+ break;
+
+ case XXX1:
+ case XXX2:
+ case XXX3:
+ case XXX4:
+ a = xnum(ch - XXX1 + 1);
+ if (a > 0)
+ special(a);
+ break;
+
+ case FNTDEF1:
+ case FNTDEF2:
+ case FNTDEF3:
+ case FNTDEF4:
+ xskip((long) (12 + ch - FNTDEF1 + 1));
+ xskip((long) xone() + (long) xone());
+ break;
+
+#ifndef TEXXET
+ case SREFL:
+ case EREFL:
+#endif
+ case PRE:
+ case POST:
+ case POSTPOST:
+ tell_oops("shouldn't happen: %s encountered",
+ dvi_table2[ch - (FNTNUM0 + 64)]);
+ break;
+
+ default:
+ tell_oops("unknown op-code %d", ch);
+ } /* end switch*/
+ } /* end else (ch not a SETCHAR or FNTNUM) */
+ } /* end for */
+}
+
+#undef xspell_conv
+
+void
+draw_page()
+{
+ /* Check for changes in dvi file. */
+ if (!check_dvi_file()) return;
+
+ put_border(ROUNDUP(unshrunk_paper_w, shrink_factor) + 1,
+ ROUNDUP(unshrunk_paper_h, shrink_factor) + 1);
+
+ (void) lseek(fileno(dvi_file), page_offset[current_page], SEEK_SET);
+
+ bzero((char *) &currinf.data, sizeof(currinf.data));
+ currinf.tn_head = tn_head;
+ currinf.pos = currinf.end = dvi_buffer;
+ currinf.virtual = NULL;
+ draw_part(current_frame = &frame0, dimconv);
+}