diff options
Diffstat (limited to 'Build/source/texk/windvi/dvi-draw.c')
-rw-r--r-- | Build/source/texk/windvi/dvi-draw.c | 1951 |
1 files changed, 1951 insertions, 0 deletions
diff --git a/Build/source/texk/windvi/dvi-draw.c b/Build/source/texk/windvi/dvi-draw.c new file mode 100644 index 00000000000..ffb9afe3980 --- /dev/null +++ b/Build/source/texk/windvi/dvi-draw.c @@ -0,0 +1,1951 @@ +/*========================================================================*\ + +Copyright (c) 1990-1999 Paul Vojta + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +PAUL VOJTA BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +NOTE: + xdvi is based on prior work, as noted in the modification history + in xdvi.c. + +\*========================================================================*/ +#define HAVE_BOOLEAN +#include "xdvi-config.h" +#include <kpathsea/c-ctype.h> +#include <kpathsea/c-fopen.h> +#include <kpathsea/c-vararg.h> +#include "dvi.h" + +#ifdef TRANSFORM +extern BOOL bTransfInUse; +#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) + +#if (BMBYTES == 1) +BMUNIT bit_masks[9] = { + 0x0, 0x1, 0x3, 0x7, + 0xf, 0x1f, 0x3f, 0x7f, + 0xff +}; +#else +#if (BMBYTES == 2) +BMUNIT bit_masks[17] = { + 0x0, 0x1, 0x3, 0x7, + 0xf, 0x1f, 0x3f, 0x7f, + 0xff, 0x1ff, 0x3ff, 0x7ff, + 0xfff, 0x1fff, 0x3fff, 0x7fff, + 0xffff +}; +#else /* BMBYTES == 4 */ +BMUNIT 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 +#endif + +#ifdef VMS +#define off_t int +#endif +#ifndef WIN32 +extern off_t lseek(); +#endif /* ! WIN32 */ + +#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(); + +#if NeedFunctionPrototypes +#ifndef TEXXET +static long set_no_char(wide_ubyte ch); +#else +static void set_no_char(wide_ubyte cmd, wide_ubyte ch); +#endif /* TEXXET */ +#else /* !NeedFunctionPrototypes */ +#ifndef TEXXET +static long set_no_char(); +#else +static void set_no_char(); +#endif /* TEXXET */ +#endif /* NeedFunctionPrototypes */ + +#ifdef TRANSFORM +extern HRGN hClipRgn; +#endif + +/* + * X routines. + */ + +/* + * Put a rectangle on the screen. + */ + +/* HTEX needs this to be non-static -janl */ +void +put_rule(x, y, w, h) + int x, y; + unsigned int w, h; +{ +#ifdef WIN32 + RECT rTemp; +#ifdef HTEX + HDC hdc = highlight? highGC : ruleGC; +#else + HDC hdc = ruleGC; +#endif + +#ifdef TRANSFORM + POINT lppt[4]; + HRGN hNewClipRgn = NULL; + XFORM xfrm, xfrm_temp; + extern BOOL bTransfInUse; + + if (!allowDrawingChars) + return; + + rTemp.left = x - currwin.base_x; + rTemp.top = y - currwin.base_y; + rTemp.right = rTemp.left + w; + rTemp.bottom = rTemp.top + h; + + if (resource.use_xform && bTransfInUse) { + RECT rTemp; + BOOL bClipped1, bClipped2; + extern XFORM current_transf; + if (SetWorldTransform(hdc, ¤t_transf) == 0) + Win32Error("XPutImage/SetWorldTransform/current"); + + lppt[0].x = x - currwin.base_x; + lppt[0].y = y - currwin.base_y; + lppt[1].x = lppt[0].x + w; + lppt[1].y = lppt[0].y; + lppt[2].x = lppt[0].x + w; + lppt[2].y = lppt[0].y + h; + lppt[3].x = lppt[0].x; + lppt[3].y = lppt[0].y + h; + LPtoDP(hdc, lppt, 4); + if ((hNewClipRgn = CreatePolygonRgn(lppt, 4, ALTERNATE)) == NULL) { + Win32Error("XPutImage/CreatePolygonRgn"); + } + if (SelectClipRgn(hdc, hNewClipRgn) == ERROR) { + Win32Error("XPutImage/SelectClipRgn"); + } + bClipped2 = RectVisible(hdc, &rTemp); + if (!bClipped2) + goto nothing; + } + else +#endif + { + if (!RectVisible(hdc, &rTemp)) + goto nothing; + } + FillRect(hdc, &rTemp, foreBrush); + nothing: +#if TRANSFORM + if (resource.use_xform && bTransfInUse) { + SelectClipRgn(hdc, NULL); + if (hNewClipRgn) DeleteObject(hNewClipRgn); + ModifyWorldTransform(hdc, &xfrm_temp, MWT_IDENTITY); + } +#endif +#else + if (x < max_x && x + (int) w >= min_x + && y < max_y && y + (int) h >= min_y) { + if (--event_counter == 0) read_events(False); +#ifdef HTEX + XFillRectangle(DISP, currwin.win, highlight? highGC: ruleGC, +#else + XFillRectangle(DISP, currwin.win, ruleGC, +#endif + x - currwin.base_x, y - currwin.base_y, w ? w : 1, h ? h : 1); + } +#endif +} + +static void +put_bitmap(bitmap, x, y) + struct bitmap *bitmap; + int x, y; +{ + +#ifdef HTEX + if (HTeXAnestlevel > 0) { + htex_recordbits(x, y, bitmap->w, bitmap->h); + } +#endif + + if (debug & DBG_BITMAP) + Printf("X(%d,%d)\n", x - currwin.base_x, y - currwin.base_y); +#ifdef WIN32 + image->width = bitmap->w; + image->height = bitmap->h; + image->data = bitmap->bits; + image->bytes_per_line = bitmap->bytes_wide; + image->endian_permuted = &(bitmap->endian_permuted); + image->depth = 1; +#ifdef HTEX + XPutImage(DISP, currwin.win, HTeXreflevel > 0? highGC: foreGC, image, + 0, 0, + x - currwin.base_x, y - currwin.base_y, + bitmap->w, bitmap->h); +#else + XPutImage(DISP, currwin.win, foreGC, image, + 0, 0, + x - currwin.base_x, y - currwin.base_y, + bitmap->w, bitmap->h); +#endif + +#else + if (x < max_x && x + (int) bitmap->w >= min_x && + y < max_y && y + (int) bitmap->h >= min_y) { + if (--event_counter == 0) read_events(False); + image->width = bitmap->w; + image->height = bitmap->h; + image->data = bitmap->bits; + image->bytes_per_line = bitmap->bytes_wide; +#ifdef HTEX + XPutImage(DISP, currwin.win, HTeXreflevel > 0? highGC: foreGC, image, +#else + XPutImage(DISP, currwin.win, foreGC, image, +#endif + 0, 0, + x - currwin.base_x, y - currwin.base_y, + bitmap->w, bitmap->h); + if (foreGC2) + XPutImage(DISP, currwin.win, foreGC2, image, + 0, 0, + x - currwin.base_x, y - currwin.base_y, + bitmap->w, bitmap->h); + } +#endif +} + +#ifdef GREY +static void +put_image(g, x, y) + struct glyph *g; + int x, y; +{ + XImage *img = g->image2; + +#ifdef HTEX + if (HTeXAnestlevel > 0) { + htex_recordbits(x, y, img->width, img->height); + } +#endif +#ifdef WIN32 + XPutImage(DISP, currwin.win, foreGC, img, + 0, 0, + x - currwin.base_x, y - currwin.base_y, + (unsigned int) img->width, (unsigned int) img->height); + +#else /* ! WIN32 */ + if (x < max_x && x + img->width >= min_x && + y < max_y && y + img->height >= min_y) { + + if (--event_counter == 0) read_events(False); + +#ifdef HTEX + XPutImage(DISP, currwin.win, foreGC, img, +#else + XPutImage(DISP, currwin.win, foreGC, img, +#endif + 0, 0, + x - currwin.base_x, y - currwin.base_y, + (unsigned int) img->width, (unsigned int) img->height); + if (foreGC2) + XPutImage(DISP, currwin.win, foreGC2, img, + 0, 0, + x - currwin.base_x, y - currwin.base_y, + (unsigned int) img->width, (unsigned int) img->height); + if (pixeltbl_t != NULL) { + img->data = g->pixmap2_t; + XPutImage(DISP, currwin.win, foreGC2, img, + 0, 0, + x - currwin.base_x, y - currwin.base_y, + (unsigned int) img->width, (unsigned int) img->height); + img->data = g->pixmap2; + } + } +#endif +} +#endif /* GREY */ + +/* + * Draw the border of a rectangle on the screen. + */ + +static void +put_border(x, y, width, height, ourGC) + int x, y; + unsigned int width, height; + GC ourGC; +{ + + --width; + --height; + /* top */ + XFillRectangle(DISP, currwin.win, ourGC, x, y, width, 1); + /* right */ + XFillRectangle(DISP, currwin.win, ourGC, x + (int) width, y, 1, height); + /* bottom */ + XFillRectangle(DISP, currwin.win, ourGC, x + 1, y + (int) height, + width, 1); + /* left */ + XFillRectangle(DISP, currwin.win, ourGC, x, y + 1, 1, height); +} + +#ifdef GRID +#ifdef WIN32 +void +put_grid(struct WindowRec *win, unsigned int unit, GC gc1, GC gc2, GC gc3) +{ + int i; /* looping variable */ + float sep; /* grid separation */ + int tmp; /* temporary variable */ + HDC hdc; + unsigned int offset; + + if (!allowDrawingChars) + return; + + switch (grid_mode) { + case 0: + return; + break; + case 1: + sep = ((float) unit); + hdc = gc1; + break; + case 2: + sep = ((float) unit) / 2.0; + hdc = gc2; + break; + case 3: + sep = ((float) unit) / 4.0; + hdc = gc3; + break; + default: + fprintf(stderr, "Warning: invalid grid_mode %d\n", grid_mode); + return; + } +#if 1 + fprintf(stderr, "Put_grid in base (%d, %d) rect (%d, %d) x (%d, %d)\n", + win->base_x, win->base_y, + win->min_x, win->min_y, + win->max_x, win->max_y); +#endif + + /* Horizontal Grid */ + for (i = 0, offset = (unsigned int)(sep - (win->base_y+win->min_y) % (int) sep) -1; + win->min_y + i*sep + offset <= win->max_y; + i++) + XFillRectangle(DISP, win->win, (hdc), win->min_x, win->min_y + i*sep + offset, + win->max_x - win->min_x, 1); + + /* Vertical Grid */ + for (i = 0, offset = (unsigned int)(sep - (win->base_x+win->min_x) % (int) sep) - 1; + win->min_x + i*sep + offset <= win->max_x; + i++) + XFillRectangle(DISP, win->win, (hdc), win->min_x + i*sep + offset, + win->min_y, 1, win->max_y - win->min_y); + +} +#else /* ! WIN32 */ +/* drawing grid */ +void +put_grid(x, y, width, height, unit, gc1, gc2, gc3) + int x, y; + unsigned int width, height, unit; + GC gc1, gc2, gc3; +{ + int i; /* looping variable */ + float sep; /* grid separation */ + int tmp; /* temporary variable */ + + --width; + --height; + +/* drawing vertial grid */ +#define DRAWGRID_VER(gc) for (i=1; \ + (tmp=x+(int) (((float) i)*sep)) < x+width; \ + i++) \ + XFillRectangle(DISP, currwin.win, (gc), \ + tmp, y, 1, height) +/* drawing horizontal grid */ +#define DRAWGRID_HOR(gc) for (i=1; \ + (tmp=y+(int) (((float) i)*sep)) < y+height; \ + i++) \ + XFillRectangle(DISP, currwin.win, (gc), \ + x, tmp, width, 1) + + if ( grid_mode > 2 ) /* third level grid */ + { + sep = (float) unit / 4.0; + DRAWGRID_VER ( gc3 ); /* vertical grid */ + DRAWGRID_HOR ( gc3 ); /* horizontal grid */ + } + + if ( grid_mode > 1 ) /* second */ + { + sep = (float) unit / 2.0; + DRAWGRID_VER ( gc2 ); /* vertical grid */ + DRAWGRID_HOR ( gc2 ); /* horizontal grid */ + } + + if ( grid_mode > 0 ) /* first level */ + { + sep = (float) unit ; + DRAWGRID_VER ( gc1 ); /* vertical grid */ + DRAWGRID_HOR ( gc1 ); /* horizontal grid */ + } +} +#endif /* WIN32 */ + +#endif /* GRID */ + +/* + * Byte reading routines for dvi file. + */ + +#define xtell(pos) ((long) (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) + ubyte size; +{ + long x = 0; + + while (size--) x = (x << 8) | xone(); + return x; +} + +static long +xsnum(size) + ubyte size; +{ + long x; + +#if __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); +} + +#ifdef HAVE_PROTOTYPES +static NORETURN void +tell_oops(_Xconst char *message, ...) +#else +/* VARARGS */ +static NORETURN void +tell_oops(va_alist) + va_dcl +#endif +{ +#ifndef HAVE_PROTOTYPES + _Xconst char *message; +#endif + va_list args; + + Fprintf(stderr, "%s: ", prog); +#ifdef HAVE_PROTOTYPES + 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)); +#if PS + ps_destroy(); +#endif + Exit(1); +} + + +/* + * Code for debugging options. + */ + +static void +print_bitmap(bitmap) + struct bitmap *bitmap; +{ + BMUNIT *ptr = (BMUNIT *) bitmap->bits; + 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 < (int) bitmap->h; ++y) { + for (x = bitmap->bytes_wide; x > 0; x -= BMBYTES) { +#ifndef WORDS_BIGENDIAN + for (i = 0; i < BMBITS; ++i) +#else + for (i = BMBITS - 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[] = { +#ifdef Omega + "SET1", "SET2", NULL, NULL, "SETRULE", "PUT1", "PUT2", NULL, +#else + "SET1", NULL, NULL, NULL, "SETRULE", "PUT1", NULL, NULL, +#endif + 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 <= (ubyte) (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 <= (ubyte) (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; + BMUNIT *cp; + int bits_left; + int n, bit_shift, wid; + + ptr = bits + bit_skip / BMBITS; + endp = ADD(bits, h * bytes_wide); + bits_left = w; +#ifndef WORDS_BIGENDIAN + bit_shift = bit_skip % BMBITS; +#else + bit_shift = BMBITS - bit_skip % BMBITS; +#endif + n = 0; + while (bits_left) { +#ifndef WORDS_BIGENDIAN + wid = BMBITS - bit_shift; +#else + wid = bit_shift; +#endif + if (wid > bits_left) wid = bits_left; + if (wid > 4) wid = 4; +#ifdef WORDS_BIGENDIAN + bit_shift -= wid; +#endif + for (cp = ptr; cp < endp; cp = ADD(cp, bytes_wide)) + n += sample_count[(*cp >> bit_shift) & bit_masks[wid]]; +#ifndef WORDS_BIGENDIAN + bit_shift += wid; + if (bit_shift == BMBITS) { + bit_shift = 0; + ++ptr; + } +#else + if (bit_shift == 0) { + bit_shift = BMBITS; + ++ptr; + } +#endif + bits_left -= wid; + } + return n; +} + +static void +shrink_glyph(g) + struct glyph *g; +{ + int shrunk_bytes_wide, shrunk_height; + int rows_left, rows, init_cols; + int cols_left; + int cols; + BMUNIT *old_ptr, *new_ptr; + BMUNIT m, *cp; + int min_sample = shrink_factor * shrink_factor * density / 100; + int rtmp; +#ifdef WIN32 + extern PF_BSWAP bswap; + + /* Ensure that the original data are not permuted */ + if (g->bitmap.endian_permuted == 1) { + bswap((BMUNIT*)g->bitmap.bits, + (g->bitmap.bytes_wide * g->bitmap.h)/BMBYTES); + g->bitmap.endian_permuted = 0; + } +#endif + /* 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((int) g->bitmap.w - g->x, shrink_factor); + /* include row zero with the positively numbered rows */ + rtmp = g->y + 1; + g->y2 = rtmp / shrink_factor; + rows = rtmp - g->y2 * shrink_factor; + if (rows <= 0) { + rows += shrink_factor; + --g->y2; + } + g->bitmap2.h = shrunk_height = g->y2 + + ROUNDUP((int) g->bitmap.h - rtmp, 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 WORDS_BIGENDIAN + m = (1 << 0); +#else + m = ((BMUNIT) 1 << (BMBITS-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, + (int) g->bitmap.w - cols_left, cols, rows) + >= min_sample) + *cp |= m; +#ifndef WORDS_BIGENDIAN + if (m == ((BMUNIT)1 << (BMBITS-1))) { + m = (1 << 0); + ++cp; + } + else m <<= 1; +#else + if (m == (1 << 0)) { + m = ((BMUNIT) 1 << (BMBITS-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); +#ifdef WIN32 + g->bitmap2.endian_permuted = 0; +#endif +} + +#ifdef GREY +static void +shrink_glyph_grey(g) + struct glyph *g; +{ + int rows_left, rows, init_cols; + int cols_left; + int cols; + int x, y; + long thesample; + BMUNIT *old_ptr; + unsigned int size; + int rtmp; +#ifdef WIN32 + extern PF_BSWAP bswap; + + /* Ensure that the original data are not permuted */ + if (g->bitmap.endian_permuted == 1) { + bswap((BMUNIT*)g->bitmap.bits, + (g->bitmap.bytes_wide * g->bitmap.h)/BMBYTES); + g->bitmap.endian_permuted = 0; + } +#endif + /* 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((int) g->bitmap.w - g->x, shrink_factor); + /* include row zero with the positively numbered rows */ + rtmp = g->y + 1; + g->y2 = rtmp / shrink_factor; + rows = rtmp - g->y2 * shrink_factor; + if (rows <= 0) { + rows += shrink_factor; + --g->y2; + } + g->bitmap2.h = g->y2 + ROUNDUP((int) g->bitmap.h - rtmp, shrink_factor) + + 1; + +#ifdef WIN32 + g->image2 = XCreateImage(DISP, maneDrawDC, + 4, + ZPixmap, 0, (char *) NULL, + g->bitmap2.w, g->bitmap2.h, + BMBITS, 0); + g->image2->endian_permuted = NULL; +#else + g->image2 = XCreateImage(DISP, our_visual, our_depth, ZPixmap, + 0, (char *) NULL, g->bitmap2.w, g->bitmap2.h, BMBITS, 0); +#endif + size = g->image2->bytes_per_line * g->bitmap2.h; + g->pixmap2 = g->image2->data = xmalloc(size != 0 ? size : 1); + if (pixeltbl_t != NULL) + g->pixmap2_t = xmalloc(size != 0 ? size : 1); + + 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, + (int) g->bitmap.w - cols_left, cols, rows); + XPutPixel(g->image2, x, y, pixeltbl[thesample]); + if (pixeltbl_t != NULL) { + g->image2->data = g->pixmap2_t; + XPutPixel(g->image2, x, y, pixeltbl_t[thesample]); + g->image2->data = g->pixmap2; + } + + cols_left -= cols; + cols = shrink_factor; + x++; + } + *((char **) &old_ptr) += rows * g->bitmap.bytes_wide; + rows_left -= rows; + rows = shrink_factor; + y++; + } + + while (y < (int) g->bitmap2.h) { + for (x = 0; x < (int) g->bitmap2.w; x++) { + XPutPixel(g->image2, x, y, *pixeltbl); + if (pixeltbl_t != NULL) { + g->image2->data = g->pixmap2_t; + XPutPixel(g->image2, x, y, *pixeltbl_t); + g->image2->data = g->pixmap2; + } + } + y++; + } + + g->y2 = g->y / shrink_factor; +#ifdef WIN32 + g->bitmap2.endian_permuted = 0; +#endif +} +#endif /* GREY */ + +/* + * Find font #n. + */ + +static void +change_font(n) + unsigned long n; +{ + struct tn *tnp; + + if (n < currinf.tn_table_len) currinf.fontp = currinf.tn_table[n]; + else { + currinf.fontp = NULL; + for (tnp = currinf.tn_head; tnp != NULL; tnp = tnp->next) + if (tnp->TeXnumber == n) { + currinf.fontp = tnp->fontp; + break; + } + } + if (currinf.fontp == NULL) tell_oops("non-existent font #%d", n); + if (currinf.fontp->set_char_p == NULL) + tell_oops("No procedure to set font #%d", + n,currinf.fontp->fontname); + 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_local(fontp->filename, OPEN_MODE); + if (fontp->file == NULL) + oops("Font file disappeared: %s", fontp->filename); + } +} + +/* + * Read special string. + */ + +static char * +read_special(nbytes) + long nbytes; +{ + static char *spcl = NULL; + static long spcl_len = -1; + char *p; + + if (spcl_len < nbytes) { + if (spcl != NULL) free(spcl); + spcl = xmalloc((unsigned) nbytes + 1); + spcl_len = nbytes; + } + p = spcl; + for (;;) { + int i = currinf.end - currinf.pos; + + if (i > nbytes) i = nbytes; + bcopy((char *) currinf.pos, p, i); + currinf.pos += i; + p += i; + nbytes -= i; + if (nbytes == 0) break; + (void) xxone(); + --(currinf.pos); + } + *p = '\0'; + return spcl; +} + +#if PS + +/* + * Size of page interval for "Scanning pages xx-xx" message. + */ + +#ifndef REPORT_INCR +#define REPORT_INCR 50 +#endif + +/* + * Table used for scanning. If >= 0, then skip that many bytes. + * M1 means end of page, M2 means special, M3 means FNTDEF, + * M4 means unrecognizable, and M5 means doesn't belong here. + */ + +#define M1 255 +#define M2 254 +#define M3 253 +#define M4 252 +#define M5 251 +#define MM 251 + +static ubyte scantable[256] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* chars 0 - 127 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +#ifdef Omega + 1,2, /* SET1,SET2 (128,129) */ + /* -,-,SETRULE,PUT1,PUT2,-,-,PUTRULE,NOP,BOP (130-139) */ + M4,M4,8,1,2,M4,M4,8,0,44, +#else + + 1,M4, /* SET1,- (128,129) */ + /* -,-,SETRULE,PUT1,-,-,-,PUTRULE,NOP,BOP (130-139) */ + M4,M4,8,1,M4,M4,M4,8,0,44, +#endif + M1,0,0,1,2,3,4,0,1,2, /* EOP,PUSH,POP,RIGHT1-4,W0M2 (140-149) */ + 3,4,0,1,2,3,4,1,2,3, /* W3-4,X0-4,DOWN1-3 (150-159) */ + 4,0,1,2,3,4,0,1,2,3, /* DOWN4,Y0-4,Z0-3 (160-169) */ + 4, /* Z4 (170) */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* change font 171 - 234 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 1,2,3,4,M2, /* FNT1-4,XXX1 (235-239) */ + /* XXX2-4,FNTDEF1-4,PRE,POST,POSTPOST (240-249) */ + M2,M2,M2,M3,M3,M3,M3,M5,M5,M5, + 0,0,M4,M4,M4,M4}; /* SREFL,EREFL,-,-,-,- (250-255) */ + +/* + * Prescanning routine for dvi file. This looks for specials like + * `header=' and `!'. + */ + +void +prescan() +{ + ubyte ch; + ubyte n; + long a; + int nextreportpage; + char scanmsg[40]; +#ifdef WIN32 + extern void scan_init_fore_color(void); + extern void scan_get_last_fore_color(void); +#endif + +#ifndef WIN32 + if (!resource._postscript) { + scanned_page = total_pages; + return; + } +#else + /* debug = DBG_PS; */ + scan_init_fore_color(); +#endif + nextreportpage = scanned_page; + ++scanned_page; + (void) lseek(fileno(dvi_file), page_offset[scanned_page], SEEK_SET); + currinf.pos = currinf.end = dvi_buffer; + for (;;) { + if (debug & DBG_PS) + Printf("Scanning page %d\n", scanned_page); + if (scanned_page > nextreportpage) { + nextreportpage += REPORT_INCR; + if (nextreportpage > current_page) + nextreportpage = current_page; + Sprintf(scanmsg, "Scanning pages %d-%d", + scanned_page + pageno_correct, + nextreportpage + pageno_correct); + showmessage(scanmsg); + XFlush(DISP); + } + for (;;) { + ch = xone(); + n = scantable[ch]; + if (n < MM) + while (n-- != 0) + (void) xone(); + else if (n == M1) break; /* end of page */ + else switch (n) { + case M2: /* special */ + a = xnum(ch - XXX1 + 1); + if (a > 0) + scan_special(read_special(a)); + break; + case M3: /* FNTDEF */ + xskip((long) (12 + ch - FNTDEF1 + 1)); + ch = xone(); + xskip((long) ch + (long) xone()); + break; + case M4: /* unrecognizable */ + tell_oops("unknown op-code %d", ch); + break; + case M5: /* doesn't belong */ + tell_oops("prescan, shouldn't happen: %s encountered", + dvi_table2[ch - (FNTNUM0 + 64)]); + break; + } + } +#ifdef WIN32 + scan_get_last_fore_color(); +#if DEBUG_SPECIALS + fprintf(stderr, "Mid : scanned_page = %d, current_page = %d\n", + scanned_page, current_page); +#endif +#endif + if (scanned_page >= current_page) break; + ++scanned_page; + } +#if DEBUG_SPECIALS + fprintf(stderr, "End of prescan, scanned_page = %d\n", scanned_page); +#endif + scanned_page_bak = scanned_page; +#ifndef WIN32 + /* I don't think this is the right place for this. */ + XClearWindow(DISP, mane.win); +#endif + psp.endheader(); +} + +#endif /* PS */ + +/* + * Routines to print characters. + */ + +#ifndef TEXXET +#define ERRVAL 0L +#else +#define ERRVAL +#endif + +#ifndef TEXXET +long +set_char P1C(wide_ubyte, ch) +#else +void +set_char P2C(wide_ubyte, cmd, wide_ubyte, ch) +#endif +{ + struct glyph *g; +#ifdef TEXXET + long dvi_h_sav; +#endif + + if (ch > maxchar) realloc_font(currinf.fontp, WIDENINT 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, 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 + } +#ifdef Omega + if ((cmd == PUT1) || (cmd == PUT2)) +#else + if (cmd == PUT1) +#endif + DVI_H = dvi_h_sav; + else + if (currinf.dir > 0) DVI_H += g->dvi_adv; +#endif +} + + +#ifndef TEXXET +static long set_empty_char P1C(wide_ubyte, ch) +{ return 0; } +#else +static void set_empty_char P2C(wide_ubyte, cmd, wide_ubyte, ch) +{ return; } +#endif + +#ifndef TEXXET +long load_n_set_char P1C(wide_ubyte, ch) +#else +void load_n_set_char P2C(wide_ubyte, cmd, wide_ubyte, ch) +#endif +{ + if (load_font(currinf.fontp)) { /* if not found */ + Fputs("Character(s) will be left blank.\n", stderr); + currinf.set_char_p = currinf.fontp->set_char_p = set_empty_char; + currinf.fontp->glyph = NULL; /* init for read_postamble */ +#ifndef TEXXET + return 0; +#else + return; +#endif + } + 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 +} + + +#ifndef TEXXET +long +set_vf_char P1C(wide_ubyte, ch) +#else +void +set_vf_char P2C(wide_ubyte, cmd, wide_ubyte, ch) +#endif +{ + struct macro *m; + struct drawinf oldinfo; +#ifdef Omega + wide_ubyte oldmaxchar; +#else + ubyte oldmaxchar; +#endif + 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_table_len = VFTABLELEN; + currinf.tn_table = currinf.fontp->vf_table; + 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 + } +#ifdef Omega + if ((cmd == PUT1) || (cmd == PUT2)) +#else + if (cmd == PUT1) +#endif + DVI_H = dvi_h_sav; + else + if (currinf.dir > 0) DVI_H += m->dvi_adv; +#endif +} + + +#ifndef TEXXET +static long +set_no_char P1C(wide_ubyte, ch) +#else +static void +set_no_char P2C(wide_ubyte, cmd, wide_ubyte, ch) +#endif +{ + if (currinf.virtual) { + currinf.fontp = currinf.virtual->first_font; + if (currinf.fontp != NULL) { + 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_rule(PXL_H, PXL_V - h + 1, (unsigned int) w, (unsigned int) h); +#else + put_rule(PXL_H - (currinf.dir < 0 ? w - 1 : 0), PXL_V - h + 1, + (unsigned int) w, (unsigned int) h); +#endif +} + +#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 + float curr_pt_size; // added SU + static char *spc_bak = NULL; + + currinf.fontp = NULL; + currinf.set_char_p = set_no_char; +#ifdef TEXXET + currinf.dir = 1; + scan_frame = NULL; /* indicates we're not scanning */ +#endif + // delay_src = False; + for (;;) { + ch = xone(); + if (debug & DBG_DVI) + print_dvi(ch); + if (ch <= (ubyte) (SETCHAR0 + 127)) { +#ifndef TEXXET + DVI_H += (*currinf.set_char_p)(ch); +#else + (*currinf.set_char_p)(ch, ch); +#endif + /* check if there are delayed src specials */ + if (delay_src) { + // fprintf(stderr, "now calling src spec \n"); + applicationDoSpecial(spc_bak, 1); + // delay_src = false; + } + else { + // fprintf(stderr, "NOT calling src spec \n"); + } + } + else if (FNTNUM0 <= ch && ch <= (ubyte) (FNTNUM0 + 63)) { + change_font((unsigned long) (ch - FNTNUM0)); + // fprintf(stderr, "changing font\n"); + } + 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; + +#ifdef Omega + case SET2: + case PUT2: +#ifndef TEXXET + a = (*currinf.set_char_p)(xnum(2)); + if (ch != PUT2) DVI_H += a; +#else + (*currinf.set_char_p)(ch, xnum(2)); +#endif + break; +#endif /* Omega */ + + 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 = xmalloc(sizeof(struct 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 = + xmalloc(sizeof(struct 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) { + spc_bak = read_special(a); + applicationDoSpecial(spc_bak, 0); + } + break; + + case FNTDEF1: + case FNTDEF2: + case FNTDEF3: + case FNTDEF4: + xskip((long) (12 + ch - FNTDEF1 + 1)); + a = (long) xone(); + xskip(a + (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 + +#ifdef HTEX +static void +check_for_anchor() /* see if anchor requested, if so go to it */ +{ + if (anchor_name != NULL) { + htex_reinit(); /* Set up hypertext stuff */ + htex_do_loc(anchor_name); + free(anchor_name); + anchor_name = NULL; + } +} +#endif /* HTEX */ + +void draw_page P1C() +{ + extern HDC magDC, magMemDC; + + /* Check for changes in dvi file. */ + if (!check_dvi_file()) return; + +#ifdef WIN32 + if (! allowDrawingChars && !isPrinting) + bColorPage = FALSE; +#endif +#if PS + if (scanned_page < current_page) prescan(); +#ifdef WIN32 + { + if (!bMagDisp && !allowDrawingChars && !isPrinting) { + psToDisplay = False; + } + } +#endif +#endif + + if (!allowDrawingChars && !isPrinting) { + RECT r; + COLORREF new_back_Pixel = get_back_color(current_page); +#if 0 + extern void dump_colors(char *); + dump_colors("draw_page()"); +#endif + if ( back_Pixel != new_back_Pixel ) { + back_Pixel = new_back_Pixel; + if (backBrush) + DeleteObject(backBrush); +#if 0 /* DEBUG_COLOR */ + fprintf(stderr, "Creating back brush %-8x\n", back_Pixel); +#endif + backBrush = CreateSolidBrush(back_Pixel); + } +#if 0 + fprintf(stderr, "draw_page filling bg with color %-8x\n", back_Pixel); +#endif + r.left = min_x - currwin.base_x; + r.top = min_y - currwin.base_y; + r.right = min(page_w - currwin.base_x, max_x); + r.bottom = min(page_h - currwin.base_y, max_y); + FillRect(foreGC, &r, backBrush); + } + +#ifdef WIN32 + if (!isPrinting) { + /* FIXME : we should ensure that base_x and base_y + do correspond to Scroll variables everywhere ! */ + extern int xCurrentScroll, yCurrentScroll; + if (1) { + put_border(-currwin.base_x, -currwin.base_y, + ROUNDUP(unshrunk_paper_w, shrink_factor) + 2, + ROUNDUP(unshrunk_paper_h, shrink_factor) + 2, highGC); + } + else { + put_border(-xCurrentScroll, -yCurrentScroll, + ROUNDUP(unshrunk_paper_w, shrink_factor) + 2, + ROUNDUP(unshrunk_paper_h, shrink_factor) + 2, highGC); + } + } +#else + put_border(-currwin.base_x, -currwin.base_y, + ROUNDUP(unshrunk_paper_w, shrink_factor) + 2, + ROUNDUP(unshrunk_paper_h, shrink_factor) + 2, highGC); +#endif +#if 0 +#ifdef GRID + if ( grid_mode > 0 ) /* grid is wanted */ + put_grid(-currwin.base_x, -currwin.base_y, + ROUNDUP(unshrunk_paper_w, shrink_factor) + 2, + ROUNDUP(unshrunk_paper_h, shrink_factor) + 2, + ROUNDUP(unshrunk_paper_unit, shrink_factor), + grid1GC, grid2GC, grid3GC); +#endif /* GRID */ +#endif + (void) lseek(fileno(dvi_file), page_offset[current_page], SEEK_SET); + + bzero((char *) &currinf.data, sizeof(currinf.data)); + currinf.tn_table_len = TNTABLELEN; + currinf.tn_table = tn_table; + currinf.tn_head = tn_head; + currinf.pos = currinf.end = dvi_buffer; + currinf.virtual = NULL; +#ifdef HTEX + htex_initpage(); /* Start up the hypertext stuff for this page */ +#endif + psfig_begun = False; + draw_part(current_frame = &frame0, dimconv); +#ifdef HTEX + htex_donepage(current_page, 1); /* Finish up the hypertext stuff for this page */ + check_for_anchor(); /* see if a new anchor was requested */ +#endif +#if PS + psp.endpage(); +#endif +#ifdef WIN32 +#ifdef GRID + if ( grid_mode > 0 ) { /* grid is wanted */ + extern unsigned int xCurrentScroll, yCurrentScroll; + put_grid(&currwin, + ROUNDUP(unshrunk_paper_unit, shrink_factor), +#if 0 + grid1GC, grid2GC, grid3GC +#else + highGC, highGC, highGC +#endif + ); + } +#endif /* GRID */ +#endif +} + +#ifdef HTEX +extern int *htex_parsedpages; /* List of pages parsed */ + +/* Parse dvi pages not yet scanned by xdvi, searching for html anchors */ +void htex_parsepages() +{ + int i; + + for (i=0; i < total_pages; i++) { + if (htex_parsedpages[i] != 0) continue; + htex_parse_page(i); + } + /* Return to original position in dvi file? */ +} + +void htex_parse_page(i) +int i; +{ + /* Skip to beginning of page i */ +/* Stuff from draw_page in dvi_draw.c: */ + (void) lseek(fileno(dvi_file), page_offset[i], SEEK_SET); + bzero((char *) &currinf.data, sizeof(currinf.data)); + currinf.tn_head = tn_head; + currinf.pos = currinf.end = dvi_buffer; + currinf.virtual = NULL; + htex_initpage(); + htex_scanpage(i); + htex_donepage(i, 0); +} + + +/* HTeX parse page without drawing it function: */ +/* Basically the same as is done by draw_part, except we don't + do anything other than record html anchors */ +/* Assumes page has been set up properly as above */ +void htex_scanpage(pageno) +int pageno; +{ + ubyte ch; + long a; + + /* Read in page, searching for XXX1 to XXX4 (\special) + sections and ignoring everything else */ + for (;;) { + ch = xone(); + if (ch <= SETCHAR0 + 127) { /* It's a character - do nothing */ + } else if (FNTNUM0 <= ch && ch <= FNTNUM0 + 63) { + /* It's a previously numbered font - again do nothing */ + } else { + switch(ch) { + case PUSH: /* No args */ + case POP: /* No args */ + case NOP: /* Nothing! */ + break; + case SET1: + case PUT1: + xskip((long) 1); /* Set or put 1 char - skip it */ + break; +#ifdef Omega + case SET2: + case PUT2: + xskip((long) 2); /* Set or put 16-bit char - skip it */ + break; +#endif + case SETRULE: + case PUTRULE: + xskip((long) 8); /* two integers a and b */ + break; + case BOP: /* Beginning of page stuff */ + xskip((long) 11*4); + break; + case EOP: /* End of the page! */ + return; + case SREFL: + case EREFL: + break; + case RIGHT1: + case RIGHT2: + case RIGHT3: + case RIGHT4: + xskip(ch - RIGHT1 + 1); + break; + case W1: + case W2: + case W3: + case W4: + xskip(ch - W0); + case W0: + break; + case X1: + case X2: + case X3: + case X4: + xskip(ch - X0); + case X0: + break; + case DOWN1: + case DOWN2: + case DOWN3: + case DOWN4: + xskip(ch - DOWN1 + 1); + break; + case Y1: + case Y2: + case Y3: + case Y4: + xskip(ch - Y0); + case Y0: + break; + case Z1: + case Z2: + case Z3: + case Z4: + xskip(ch - Z0); + case Z0: + break; + case FNT1: + case FNT2: + case FNT3: + case FNT4: + xskip(ch - FNT1 + 1); + break; + case XXX1: + case XXX2: + case XXX3: + case XXX4: /* Only thing we pay attention to! */ + a = xnum(ch - XXX1 + 1); + if (a > 0) + htex_dospecial(a, pageno); + break; + case FNTDEF1: + case FNTDEF2: + case FNTDEF3: + case FNTDEF4: + xskip((long) (12 + ch - FNTDEF1 + 1)); + xskip((long) xone() + (long) xone()); + break; + case PRE: + case POST: + case POSTPOST: + default: + break; + } + } + } +} + +/* Do the same same stuff as special() in dvi_draw.c */ +/* But only check HTeX specials */ +void htex_dospecial(nbytes, pageno) +long nbytes; +int pageno; +{ + static char *cmd = NULL; + static long cmdlen = -1; + char *p; + + if (cmdlen < nbytes) { + if (cmd) free(cmd); + cmd = xmalloc((unsigned) nbytes+1); + 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'; + p = cmd; + while (isspace(*p)) ++p; + checkHyperTeX(p, pageno); +} +#endif /* HTEX */ |