/*========================================================================*\ 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. \*========================================================================*/ #include "xdvi-config.h" #include #include #include #include "dvi.h" 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 extern off_t lseek(); #ifndef SEEK_SET /* if is not provided (or for = 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); } } 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); 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); } } #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 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 0 /* Do we really need? */ 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); #endif 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 /* 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 /* 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 /* 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[] = { #if defined(Omega) || defined(KANJI) "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, #ifdef PTEX "DIRECTION" #else NULL #endif }; 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; } extern double bbox_matrix[2][2]; extern Boolean bbox_scaled, bbox_rotated; static void bbox_scale_bitmap(g) register struct glyph *g; { BMUNIT *new_ptr; int xmax, ymax, xmin, ymin, x, y; double d; if (g->bitmap3.bits) { if (g->matrix[0][0] == (float) bbox_matrix[0][0] && g->matrix[0][1] == (float) bbox_matrix[0][1] && g->matrix[1][0] == (float) bbox_matrix[1][0] && g->matrix[1][1] == (float) bbox_matrix[1][1]) return; else free(g->bitmap.bits); } else { g->bitmap3 = g->bitmap; g->x3 = g->x; g->y3 = g->y; } xmax = ymax = xmin = ymin = 0; x = g->bitmap3.w * bbox_matrix[0][0]; y = g->bitmap3.w * bbox_matrix[1][0]; if (xmax < x) xmax = x; else if (xmin > x) xmin = x; if (ymax < y) ymax = y; else if (ymin > y) ymin = y; x = g->bitmap3.w * bbox_matrix[0][0] + g->bitmap3.h * bbox_matrix[0][1]; y = g->bitmap3.w * bbox_matrix[1][0] + g->bitmap3.h * bbox_matrix[1][1]; if (xmax < x) xmax = x; else if (xmin > x) xmin = x; if (ymax < y) ymax = y; else if (ymin > y) ymin = y; x = g->bitmap3.h * bbox_matrix[0][1]; y = g->bitmap3.h * bbox_matrix[1][1]; if (xmax < x) xmax = x; else if (xmin > x) xmin = x; if (ymax < y) ymax = y; else if (ymin > y) ymin = y; xmin--; ymin--; xmax++; ymax++; d = bbox_matrix[0][0] * bbox_matrix[1][1] - bbox_matrix[0][1] * bbox_matrix[1][0]; g->x = g->x3 * bbox_matrix[0][0] + g->y3 * bbox_matrix[0][1] - xmin; g->y = g->x3 * bbox_matrix[1][0] + g->y3 * bbox_matrix[1][1] - ymin; g->matrix[0][0] = (float) bbox_matrix[0][0]; g->matrix[0][1] = (float) bbox_matrix[0][1]; g->matrix[1][0] = (float) bbox_matrix[1][0]; g->matrix[1][1] = (float) bbox_matrix[1][1]; if (g->bitmap2.bits != NULL) { free(g->bitmap2.bits); g->bitmap2.bits = NULL; } #ifdef GREY if (g->pixmap2 != NULL) { free(g->pixmap2); g->pixmap2 = NULL; } #endif g->bitmap.w = xmax - xmin + 1; g->bitmap.h = ymax - ymin + 1; alloc_bitmap(&g->bitmap); bzero((char *) g->bitmap.bits, g->bitmap.bytes_wide * g->bitmap.h); new_ptr = (BMUNIT *) g->bitmap.bits; for (y = ymin; y <= ymax; y++) { register BMUNIT m, *cp; cp = new_ptr; #ifndef WORDS_BIGENDIAN m = (1 << 0); #else m = ((BMUNIT) 1 << (BMBITS-1)); #endif for (x = xmin; x <= xmax; x++) { int bx, by; bx = (x * bbox_matrix[1][1] - y * bbox_matrix[0][1]) / d; by = (y * bbox_matrix[0][0] - x * bbox_matrix[1][0]) / d; if (bx >= 0 && bx < g->bitmap3.w && by >= 0 && by < g->bitmap3.h && *((BMUNIT *)g->bitmap3.bits + by * (g->bitmap3.bytes_wide / BMBYTES) + bx / BMBITS) #ifndef WORDS_BIGENDIAN & (1 << (bx % BMBITS))) #else & (1 << (BMBITS - 1 - bx % BMBITS))) #endif *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 } *((char **) &new_ptr) += g->bitmap.bytes_wide; } } 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; /* 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 PTEX void rotate_bitmap(bm) struct bitmap *bm; { struct bitmap new_bm; BMUNIT *old_ptr, *new_ptr, *cp; int x, y; BMUNIT m1, m2; new_bm.h = bm->w; new_bm.w = bm->h; alloc_bitmap(&new_bm); old_ptr = (BMUNIT *)bm->bits; *((char **) &old_ptr) += bm->bytes_wide * bm->h; new_ptr = (BMUNIT *)new_bm.bits; bzero((char *) new_ptr, new_bm.bytes_wide * new_bm.h); #ifndef WORDS_BIGENDIAN m1 = (1 << 0); #else m1 = (1 << (BMBITS-1)); #endif for (y = 0; y < bm->h; y++) { *((char **) &old_ptr) -= bm->bytes_wide; #ifndef WORDS_BIGENDIAN m2 = (1 << 0); #else m2 = (1 << (BMBITS-1)); #endif cp = old_ptr; for (x = 0; x < bm->w; x++) { if (*cp & m2) *(BMUNIT *)((char *)new_ptr + x*new_bm.bytes_wide) |= m1; #ifndef WORDS_BIGENDIAN if (m2 == (BMUNIT)(1 << (BMBITS-1))) { m2 = (1 << 0); ++cp; } else m2 <<= 1; #else if (m2 == (1 << 0)) { m2 = (1 << (BMBITS-1)); ++cp; } else m2 >>= 1; #endif } #ifndef WORDS_BIGENDIAN if (m1 == (BMUNIT)(1 << (BMBITS-1))) { m1 = (1 << 0); ++new_ptr; } else m1 <<= 1; #else if (m1 == (1 << 0)) { m1 = (1 << (BMBITS-1)); ++new_ptr; } else m1 >>= 1; #endif } free(bm->bits); *bm = new_bm; } void reverse_rotate_bitmap(bm) struct bitmap *bm; { struct bitmap new_bm; BMUNIT *old_ptr, *new_ptr, *cp; int x, y; BMUNIT m1, m2; new_bm.h = bm->w; new_bm.w = bm->h; alloc_bitmap(&new_bm); old_ptr = (BMUNIT *)bm->bits; /* *((char **) &old_ptr) += bm->bytes_wide * bm->h; */ new_ptr = (BMUNIT *)new_bm.bits; bzero((char *) new_ptr, new_bm.bytes_wide * new_bm.h); #ifndef WORDS_BIGENDIAN m1 = (1 << 0); #else m1 = (1 << (BMBITS-1)); #endif for (y = 0; y < bm->h; y++) { cp = old_ptr; *((char **) &old_ptr) += bm->bytes_wide; #ifndef WORDS_BIGENDIAN m2 = (1 << 0); #else m2 = (1 << (BMBITS-1)); #endif for (x = bm->w; x--;) { if (*cp & m2) *(BMUNIT *)((char *)new_ptr + x * new_bm.bytes_wide) |= m1; #ifndef WORDS_BIGENDIAN if (m2 == (BMUNIT)(1 << (BMBITS-1))) { m2 = (1 << 0); ++cp; } else m2 <<= 1; #else if (m2 == (1 << 0)) { m2 = (1 << (BMBITS-1)); ++cp; } else m2 >>= 1; #endif } #ifndef WORDS_BIGENDIAN if (m1 == (BMUNIT)(1 << (BMBITS-1))) { m1 = (1 << 0); ++new_ptr; } else m1 <<= 1; #else if (m1 == (1 << 0)) { m1 = (1 << (BMBITS-1)); ++new_ptr; } else m1 >>= 1; #endif } free(bm->bits); *bm = new_bm; } #endif /* PTEX */ #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; /* 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; g->image2 = XCreateImage(DISP, our_visual, our_depth, ZPixmap, 0, (char *) NULL, g->bitmap2.w, g->bitmap2.h, BMBITS, 0); 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; } static void shrink_glyph_NeXT(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, BMBITS, 0); g->pixmap2 = g->image2->data = xmalloc((unsigned) g->image2->bytes_per_line * g->bitmap2.h); #ifndef WORDS_BIGENDIAN g->image2->bitmap_bit_order = LSBFirst; #else g->image2->bitmap_bit_order = MSBFirst; #endif { short endian = MSBFirst << 8 | LSBFirst; g->image2->byte_order = *((char *) &endian); } g->image2->bitmap_pad = 32; 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); NeXTPutPixel(g->image2, x, y, (thesample * 100) / (shrink_factor * shrink_factor)); 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++) NeXTPutPixel(g->image2, x, y, 0); y++; } g->y2 = g->y / shrink_factor; } static int NeXTd[3] = {15, 30, 50}; void set_NeXTd(s) char *s; { int i; if (*s == ':') ++s; for (i = 0; i < 3; i++) { NeXTd[i] = atof(s); if ((s = index(s, ':')) == NULL) return; ++s; } } NeXTPutPixel(image, x, y, percent) XImage *image; int x, y, percent; { int pix; pix = percent < NeXTd[0] ? 0 : percent < NeXTd[1] ? 1 : percent < NeXTd[2] ? 2 : 3; image->data[y * image->bytes_per_line + x / 4] |= pix << (2 * (3 - x % 4)); } #endif /* GREY */ /* * Find font #n. */ #ifdef ASCIIDNP static unsigned int cur_TeXnumber; extern void define_kanjifont(); extern void adj_kanjiwidth(); #endif /* ASCIIDNP */ 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; } } #ifdef ASCIIDNP if (currinf.fontp == NULL) { if (n >> 24) { define_kanjifont(n); change_font(n); return; } tell_oops("non-existent font #%d", n); } #else /* ASCIIDNP */ if (currinf.fontp == NULL) tell_oops("non-existent font #%d", n); #endif /* ASCIIDNP */ if (currinf.fontp->set_char_p == NULL) tell_oops("No procedure to set font #%d", n,currinf.fontp->fontname); maxchar = currinf.fontp->maxchar; #ifdef ASCIIDNP cur_TeXnumber = n; #endif /* ASCIIDNP */ 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 || defined(COLOR) /* * 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, #if defined(Omega) || defined(KANJI) 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 `!'. */ #if defined(DVISEL) && defined(COLOR) void #else static void #endif /* DVISEL */ prescan() { ubyte ch; ubyte n; long a; int nextreportpage; char scanmsg[40]; #if PS #ifdef COLOR if (!resource._postscript && !use_color) { #else if (!resource._postscript) { #endif scanned_page = total_pages; return; } #endif nextreportpage = scanned_page; ++scanned_page; #ifdef COLOR if (use_color) { back_color_data = page_color[scanned_page].background; color_stack_top = page_color[scanned_page].stack_top; bcopy(page_color[scanned_page].color_stack, color_stack, color_stack_top); fore_color_data = page_color[scanned_page].color_stack[color_stack_top]; } #endif #ifdef PAGENUM (void) lseek(fileno(dvi_file), page_index[scanned_page].offset, SEEK_SET); #else (void) lseek(fileno(dvi_file), page_offset[scanned_page], SEEK_SET); #endif /* PAGENUM */ 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; #ifndef PTEX case M4: /* unrecognizable */ tell_oops("unknown op-code %d", ch); break; #endif case M5: /* doesn't belong */ tell_oops("shouldn't happen: %s encountered", dvi_table2[ch - (FNTNUM0 + 64)]); break; } } #ifdef COLOR if (use_color) { page_color[scanned_page + 1].background = back_color_data; page_color[scanned_page + 1].stack_top = color_stack_top; page_color[scanned_page + 1].color_stack = (XColor *) xmalloc(sizeof(XColor) * (color_stack_top + 1)); bcopy(color_stack, page_color[scanned_page + 1].color_stack, sizeof(XColor) * color_stack_top); page_color[scanned_page + 1].color_stack[color_stack_top] = fore_color_data; } #endif if (scanned_page >= current_page) break; ++scanned_page; } scanned_page_bak = scanned_page; XClearWindow(DISP, mane.win); psp.endheader(); } #endif /* PS || COLOR */ /* * 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, dvi_v_sav, pxl_v_sav; #if PS long ps_h_sav, ps_v_sav; #endif #endif if (ch > maxchar) realloc_font(currinf.fontp, WIDENINT ch); if ((g = &currinf.fontp->glyph[ch])->bitmap.bits == NULL) { #ifdef NTTZEIT if (!(currinf.fontp->flags & FONT_DNP)) { #endif /* NTTZEIT */ 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); #ifdef NTTZEIT } #endif /* NTTZEIT */ (*currinf.fontp->read_char)(currinf.fontp, ch); #ifdef ASCIIDNP if (cur_TeXnumber >> 24) adj_kanjiwidth(currinf.fontp, cur_TeXnumber >> 24, ch); #endif /* ASCIIDNP */ if (debug & DBG_BITMAP) print_char((ubyte) ch, g); currinf.fontp->timestamp = ++current_timestamp; } #ifdef PTEX if (g->tdir != TATE) { int tmp; if (TATE != currinf.fontp->dir) { rotate_bitmap(&g->bitmap); tmp = g->x; g->x = g->bitmap.w - g->y; g->y = tmp; } else { reverse_rotate_bitmap(&g->bitmap); tmp = g->x; g->x = g->y; g->y = g->bitmap.h - tmp; } g->tdir = TATE; if (g->bitmap2.bits != NULL) { free(g->bitmap2.bits); g->bitmap2.bits = NULL; } #ifdef GREY if (g->pixmap2 != NULL) { free(g->pixmap2); g->pixmap2 = NULL; } #endif } #endif /* PTEX */ #ifdef TEXXET dvi_h_sav = DVI_H; dvi_v_sav = DVI_V; pxl_v_sav = PXL_V; #if PS ps_h_sav = PS_H; ps_v_sav = PS_V; #endif #ifdef PTEX if (! TATE && currinf.dir < 0) { #else if (currinf.dir < 0) { #endif DVI_H -= g->dvi_adv * bbox_matrix[0][0]; DVI_V -= g->dvi_adv * bbox_matrix[1][0]; PXL_V = pixel_conv(DVI_V); #if PS PS_H -= g->dvi_adv; #endif } if (scan_frame == NULL) { #endif if (bbox_scaled) bbox_scale_bitmap(g); else if (g->bitmap3.bits) { free(g->bitmap.bits); g->bitmap = g->bitmap3; g->bitmap3.bits = NULL; g->x = g->x3; g->y = g->y3; if (g->bitmap2.bits != NULL) { free(g->bitmap2.bits); g->bitmap2.bits = NULL; } #ifdef GREY if (g->pixmap2 != NULL) { free(g->pixmap2); g->pixmap2 = 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) { if (DefaultDepthOfScreen(SCRN) == 2) shrink_glyph_NeXT(g); else 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 } #if defined(Omega) || defined(KANJI) if ((cmd == PUT1) || (cmd == PUT2)) { #else if (cmd == PUT1) { #endif DVI_H = dvi_h_sav; DVI_V = dvi_v_sav; PXL_V = pxl_v_sav; #if PS PS_H = ps_h_sav; PS_V = ps_v_sav; #endif } else #ifdef PTEX if (TATE) { DVI_H -= g->dvi_adv * bbox_matrix[1][0]; DVI_V += g->dvi_adv * bbox_matrix[0][0]; PXL_V = pixel_conv(DVI_V); #if PS PS_V += g->dvi_adv; #endif } else #endif /* PTEX */ if (currinf.dir > 0) { DVI_H += g->dvi_adv * bbox_matrix[0][0]; DVI_V += g->dvi_adv * bbox_matrix[1][0]; PXL_V = pixel_conv(DVI_V); #if PS PS_H += g->dvi_adv; #endif } #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 } #if defined(KANJI) && !defined(ASCIIDNP) #ifndef TEXXET long set_char2 P1C(wide_ubyte, ch) #else void set_char2 P2C(wide_ubyte, cmd, wide_ubyte, ch) #endif { register struct glyph *g; #ifdef TEXXET long dvi_h_sav, dvi_v_sav, pxl_v_sav; #if PS long ps_h_sav, ps_v_sav; #endif #endif #ifdef PTEX int i; extern struct TateCorrection TateCorrectionTable[]; #endif g = currinf.fontp->kglyph[jisindex(ch)]; #ifndef PTEX if (g == NULL || g->bitmap.bits == NULL) { (*currinf.fontp->read_char)(currinf.fontp, ch); g = currinf.fontp->kglyph[jisindex(ch)]; } #else if (g == NULL || g->bitmap.bits == NULL) { (*currinf.fontp->read_char)(currinf.fontp, ch); g = currinf.fontp->kglyph[jisindex(ch)]; if (g->bitmap2.bits != NULL) { free(g->bitmap2.bits); g->bitmap2.bits = NULL; } g->tdir = currinf.fontp->dir; } if (g->tdir != TATE) { int tmp; if (g->tdir) { reverse_rotate_bitmap(&g->bitmap); tmp = g->x; g->x = g->y; g->y = g->bitmap.h - tmp; } else { rotate_bitmap(&g->bitmap); tmp = g->x; g->x = g->bitmap.w - g->y; g->y = tmp; } if (g->bitmap2.bits != NULL) { free(g->bitmap2.bits); g->bitmap2.bits = NULL; } #ifdef GREY if (g->pixmap2 != NULL) { free(g->pixmap2); g->pixmap2 = NULL; } #endif g->tdir = TATE; } #endif #ifdef TEXXET dvi_h_sav = DVI_H; dvi_v_sav = DVI_V; pxl_v_sav = PXL_V; #if PS ps_h_sav = PS_H; ps_v_sav = PS_V; #endif #ifdef PTEX if (! TATE && currinf.dir < 0) { #else if (currinf.dir < 0) { #endif DVI_H -= g->dvi_adv * bbox_matrix[0][0]; DVI_V -= g->dvi_adv * bbox_matrix[1][0]; PXL_V = pixel_conv(DVI_V); #if PS PS_H -= g->dvi_adv; #endif } if (scan_frame == NULL) { #endif if (bbox_scaled) bbox_scale_bitmap(g); else if (g->bitmap3.bits) { free(g->bitmap.bits); g->bitmap = g->bitmap3; g->bitmap3.bits = NULL; g->x = g->x3; g->y = g->y3; if (g->bitmap2.bits != NULL) { free(g->bitmap2.bits); g->bitmap2.bits = NULL; } #ifdef GREY if (g->pixmap2 != NULL) { free(g->pixmap2); g->pixmap2 = 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) if (DefaultDepthOfScreen(SCRN) == 2) shrink_glyph_NeXT(g); else 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 } if ((cmd == PUT1) || (cmd == PUT2)) { DVI_H = dvi_h_sav; DVI_V = dvi_v_sav; PXL_V = pxl_v_sav; #if PS PS_H = ps_h_sav; PS_V = ps_v_sav; #endif } else #ifdef PTEX if (TATE) { DVI_H -= g->dvi_adv * bbox_matrix[1][0]; DVI_V += g->dvi_adv * bbox_matrix[0][0]; PXL_V = pixel_conv(DVI_V); #if PS PS_V += g->dvi_adv; #endif } else #endif /* PTEX */ if (currinf.dir > 0) { DVI_H += g->dvi_adv * bbox_matrix[0][0]; DVI_V += g->dvi_adv * bbox_matrix[1][0]; PXL_V = pixel_conv(DVI_V); #if PS PS_H += g->dvi_adv; #endif } #endif } #endif /* KANJI && !ASCIIDNP */ #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; #if defined(Omega) || defined(KANJI) wide_ubyte oldmaxchar; #else ubyte oldmaxchar; #endif static ubyte c; #ifdef TEXXET long dvi_h_sav, dvi_v_sav, pxl_v_sav; #if PS long ps_h_sav, ps_v_sav; #endif #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; dvi_v_sav = DVI_V; pxl_v_sav = PXL_V; #if PS ps_h_sav = PS_H; ps_v_sav = PS_V; #endif #ifdef PTEX if (! TATE && currinf.dir < 0) { #else if (currinf.dir < 0) { #endif DVI_H -= m->dvi_adv * bbox_matrix[0][0]; DVI_V -= m->dvi_adv * bbox_matrix[1][0]; PXL_V = pixel_conv(DVI_V); #if PS PS_H -= m->dvi_adv; #endif } 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 } #if defined(Omega) || defined(KANJI) if ((cmd == PUT1) || (cmd == PUT2)) { #else if (cmd == PUT1) { #endif DVI_H = dvi_h_sav; DVI_V = dvi_v_sav; PXL_V = pxl_v_sav; #if PS PS_H = ps_h_sav; PS_V = ps_v_sav; #endif } else #ifdef PTEX if (TATE) { DVI_H -= m->dvi_adv * bbox_matrix[1][0]; DVI_V += m->dvi_adv * bbox_matrix[0][0]; PXL_V = pixel_conv(DVI_V); #if PS PS_V += m->dvi_adv; #endif } else #endif /* PTEX */ if (currinf.dir > 0) { DVI_H += m->dvi_adv * bbox_matrix[0][0]; DVI_V += m->dvi_adv * bbox_matrix[1][0]; PXL_V = pixel_conv(DVI_V); #if PS PS_H += m->dvi_adv; #endif } #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; { #ifdef PTEX if (TATE) put_rule(PXL_H, PXL_V, (unsigned int) h, (unsigned int) w); else #endif /* PTEX */ #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 } static void set_rotated_rule(h, w) long h, w; { int i; XPoint points[4]; points[0].x = PXL_H - currwin.base_x; points[0].y = PXL_V - currwin.base_y; #ifdef PTEX if (TATE) { points[1].x = -pixel_round(w * bbox_matrix[1][0]); points[1].y = pixel_round(w * bbox_matrix[0][0]); points[2].x = pixel_round(h * bbox_matrix[1][1]); points[2].y = -pixel_round(h * bbox_matrix[0][1]); } else #endif /* PTEX */ { points[1].x = DIR * pixel_round(w * bbox_matrix[0][0]); points[1].y = DIR * pixel_round(w * bbox_matrix[1][0]); points[2].x = -pixel_round(h * bbox_matrix[0][1]); points[2].y = -pixel_round(h * bbox_matrix[1][1]); } points[3].x = -points[1].x; points[3].y = -points[1].y; if (--event_counter == 0) read_events(False); #ifdef HTEX XFillPolygon(DISP, currwin.win, highlight? highGC: ruleGC, #else XFillPolygon(DISP, currwin.win, ruleGC, #endif points, 4, Convex, CoordModePrevious); } #ifdef ASCIIDNP /*** compute_fc : borrowed from jvi2ps1.3j ***/ static void compute_fc(kuten, f, c) register unsigned int kuten; unsigned int *f, *c; { register int n; register unsigned int ku, ten; *f = *c = 1; ku = kuten / 256; ten = kuten % 256; if (ku < 0x21 || (0x29 <= ku && ku <= 0x2f) || 0x74 < ku) { Fprintf(stderr, "invalid ku in jis (%x, %x)", ku, ten); return; } if (ten < 0x21 || 0x7e < ten) { Fprintf(stderr, "invalid ten in jis (%x, %x)", ku, ten); return; } ku -= 0x20; ten -= 0x20; if (ku == 1) { *f = 1; *c = ten; } else if (ku == 2) { *f = 1; *c = ten + 100; } else if (ku == 3) { *f = 2; *c = ten + 32; } else if (ku <= 8) { *f = ku - 1; *c = ten; } else if (ku <= 47) { /* Daiichi Suijun */ n = (ku - 0x10) * 0x5e + ten - 1; *f = (n / 256) + 8; *c = n % 256; } else { /* Daini Suijun */ n = (ku - 0x30) * 0x5e + ten - 1; *f = (n / 256) + 20; *c = n % 256; } } #endif /* ASCIIDNP */ #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 PTEX /* currinf.data.tdir = 0; */ #endif #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 <= (ubyte) (SETCHAR0 + 127)) #ifndef TEXXET { long a; a = (*currinf.set_char_p)(ch); #ifdef PTEX if (TATE) { DVI_H -= a * bbox_matrix[1][0]; DVI_V += a * bbox_matrix[0][0]; #if PS PS_V += a; #endif } else #endif /* PTEX */ { DVI_H += a * bbox_matrix[0][0]; DVI_V += a * bbox_matrix[1][0]; #if PS PS_H += a; #endif } PXL_V = pixel_conv(DVI_V); } #else (*currinf.set_char_p)(ch, ch); #endif else if (FNTNUM0 <= ch && ch <= (ubyte) (FNTNUM0 + 63)) change_font((unsigned long) (ch - FNTNUM0)); else { long a, b; #ifdef ASCIIDNP unsigned int f, c; #endif /* ASCIIDNP */ switch (ch) { case SET1: case PUT1: #ifndef TEXXET a = (*currinf.set_char_p)(xone()); if (ch != PUT1) { #ifdef PTEX if (TATE) { DVI_H -= a * bbox_matrix[1][0]; DVI_V += a * bbox_matrix[0][0]; #if PS PS_V += a; #endif } else #endif /* PTEX */ { DVI_H += a * bbox_matrix[0][0]; DVI_V += a * bbox_matrix[1][0]; #if PS PS_H += a; #endif } PXL_V = pixel_conv(DVI_V); } #else (*currinf.set_char_p)(ch, xone()); #endif break; #if defined(Omega) || defined(KANJI) case SET2: case PUT2: #ifndef TEXXET #ifdef ASCIIDNP compute_fc(xnum(2), &f, &c); if (cur_TeXnumber >> 24 != f) change_font((cur_TeXnumber & 0xffffff) | (f << 24)); a = (*currinf.set_char_p)(c); #else /* ASCIIDNP */ a = (*currinf.set_char_p)(xnum(2)); #endif /* ASCIIDNP */ if (ch != PUT2) { #ifdef PTEX if (TATE) { DVI_H -= a * bbox_matrix[1][0]; DVI_V += a * bbox_matrix[0][0]; #if PS PS_V += a; #endif } else #endif /* PTEX */ { DVI_H += a * bbox_matrix[0][0]; DVI_V += a * bbox_matrix[1][0]; #if PS PS_H += a; #endif } PXL_V = pixel_conv(DVI_V); } #else #ifdef ASCIIDNP compute_fc(xnum(2), &f, &c); if (cur_TeXnumber >> 24 != f) change_font((cur_TeXnumber & 0xffffff) | (f << 24)); (*currinf.set_char_p)(ch, c); #else /* ASCIIDNP */ (*currinf.set_char_p)(ch, xnum(2)); #endif /* ASCIIDNP */ #endif break; #endif /* Omega || KANJI */ 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 if (bbox_rotated) set_rotated_rule((long)xspell_conv(a), b); else set_rule(pixel_round(xspell_conv(a) * bbox_matrix[1][1]), pixel_round(b * bbox_matrix[0][0])); #ifdef PTEX if (TATE) { DVI_H -= b * bbox_matrix[1][0]; DVI_V += b * bbox_matrix[0][0]; #if PS PS_V += b; #endif } else #endif /* PTEX */ { DVI_H += DIR * b * bbox_matrix[0][0]; DVI_V += DIR * b * bbox_matrix[1][0]; #if PS PS_H += DIR * b; #endif } PXL_V = pixel_conv(DVI_V); 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 if (bbox_rotated) set_rotated_rule(a, b); else set_rule(pixel_round(a * bbox_matrix[1][1]), pixel_round(b * bbox_matrix[0][0])); break; case NOP: break; case BOP: xskip((long) 11 * 4); DVI_H = OFFSET_X; DVI_V = OFFSET_Y; PXL_V = pixel_conv(DVI_V); #if PS PS_H = DVI_H; PS_V = DVI_V; #endif WW = XX = YY = ZZ = 0; bbox_matrix[0][0] = bbox_matrix[1][1] = 1.0; bbox_matrix[0][1] = bbox_matrix[1][0] = 0.0; bbox_scaled = bbox_rotated = False; 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; #if PS PS_H = DVI_H; PS_V = DVI_V; #endif /* 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: a = xspell_conv(xsnum(ch - RIGHT1 + 1)); #ifdef PTEX if (TATE) { DVI_H -= a * bbox_matrix[1][0]; DVI_V += a * bbox_matrix[0][0]; #if PS PS_V += a; #endif } else #endif /* PTEX */ { DVI_H += DIR * a * bbox_matrix[0][0]; DVI_V += DIR * a * bbox_matrix[1][0]; #if PS PS_H += DIR * a; #endif } PXL_V = pixel_conv(DVI_V); break; case W1: case W2: case W3: case W4: WW = xspell_conv(xsnum(ch - W0)); case W0: #ifdef PTEX if (TATE) { DVI_H -= WW * bbox_matrix[1][0]; DVI_V += WW * bbox_matrix[0][0]; #if PS PS_V += WW; #endif } else #endif /* PTEX */ { DVI_H += DIR * WW * bbox_matrix[0][0]; DVI_V += DIR * WW * bbox_matrix[1][0]; #if PS PS_H += DIR * WW; #endif } PXL_V = pixel_conv(DVI_V); break; case X1: case X2: case X3: case X4: XX = xspell_conv(xsnum(ch - X0)); case X0: #ifdef PTEX if (TATE) { DVI_H -= XX * bbox_matrix[1][0]; DVI_V += XX * bbox_matrix[0][0]; #if PS PS_V += XX; #endif } else #endif /* PTEX */ { DVI_H += DIR * XX * bbox_matrix[0][0]; DVI_V += DIR * XX * bbox_matrix[1][0]; #if PS PS_H += DIR * XX; #endif } PXL_V = pixel_conv(DVI_V); break; case DOWN1: case DOWN2: case DOWN3: case DOWN4: a = xspell_conv(xsnum(ch - DOWN1 + 1)); #ifdef PTEX if (TATE) { DVI_H -= a * bbox_matrix[1][1]; DVI_V += a * bbox_matrix[0][1]; #if PS PS_H -= a; #endif } else #endif /* PTEX */ { DVI_H += a * bbox_matrix[0][1]; DVI_V += a * bbox_matrix[1][1]; #if PS PS_V += a; #endif } PXL_V = pixel_conv(DVI_V); break; case Y1: case Y2: case Y3: case Y4: YY = xspell_conv(xsnum(ch - Y0)); case Y0: #ifdef PTEX if (TATE) { DVI_H -= YY * bbox_matrix[1][1]; DVI_V += YY * bbox_matrix[0][1]; #if PS PS_H -= YY; #endif } else #endif /* PTEX */ { DVI_H += YY * bbox_matrix[0][1]; DVI_V += YY * bbox_matrix[1][1]; #if PS PS_V += YY; #endif } PXL_V = pixel_conv(DVI_V); break; case Z1: case Z2: case Z3: case Z4: ZZ = xspell_conv(xsnum(ch - Z0)); case Z0: #ifdef PTEX if (TATE) { DVI_H -= ZZ * bbox_matrix[1][1]; DVI_V += ZZ * bbox_matrix[0][1]; #if PS PS_H -= ZZ; #endif } else #endif /* PTEX */ { DVI_H += ZZ * bbox_matrix[0][1]; DVI_V += ZZ * bbox_matrix[1][1]; #if PS PS_V += ZZ; #endif } 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) applicationDoSpecial(read_special(a)); 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; #ifdef PTEX case TDIR: TATE = xone(); break; #endif /* PTEX */ 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(void,) { #ifdef COLOR static Pixel saved_back_pixel; #endif /* Check for changes in dvi file. */ if (!check_dvi_file()) return; #if PS || defined(COLOR) if (scanned_page < current_page) prescan(); #endif put_border(-currwin.base_x, -currwin.base_y, ROUNDUP(unshrunk_paper_w, shrink_factor) + 2, ROUNDUP(unshrunk_paper_h, shrink_factor) + 2, highGC); #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 */ #ifdef PAGENUM (void) lseek(fileno(dvi_file), page_index[current_page].offset, SEEK_SET); #else (void) lseek(fileno(dvi_file), page_offset[current_page], SEEK_SET); #endif /* PAGENUM */ 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; #ifdef COLOR if (use_color) { back_color_data = page_color[current_page + 1].background; color_stack_top = page_color[current_page].stack_top; bcopy(page_color[current_page].color_stack, color_stack, sizeof(XColor) * color_stack_top); fore_color_data = page_color[current_page].color_stack[color_stack_top]; init_colors(); if (saved_back_pixel != back_color_data.pixel) { XSetWindowBackground(DISP, mane.win, back_color_data.pixel); XClearWindow(DISP, mane.win); saved_back_pixel = back_color_data.pixel; } } #endif 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 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: */ #ifdef PAGENUM (void) lseek(fileno(dvi_file), page_index[i].offset, SEEK_SET); #else (void) lseek(fileno(dvi_file), page_offset[i], SEEK_SET); #endif /* PAGENUM */ 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; #if defined(Omega) || defined(KANJI) 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 */