|
|
1.1 root 1: /*
2: * DVI previewer for X.
3: *
4: * Eric Cooper, CMU, September 1985.
5: *
6: * Code derived from dvi-imagen.c.
7: *
8: * Modified for X.10 by Bob Scheifler, MIT LCS, January 1986.
9: *
10: */
11: #ifndef lint
12: static char *dv_c = "$Header: dv.c,v 10.5 86/02/01 15:44:22 tony Rel $";
13: #endif lint
14:
15: #include <sys/types.h>
16: #include <X/Xlib.h>
17: #include <stdio.h>
18: #include <ctype.h>
19: #include "dvi.h"
20: #include "pxl.h"
21:
22: /* These are probably site dependent */
23: #define FONT_DIRECTORY "/usr/lib/tex/fonts"
24: #define FONT_SUFFIX ".%dpxl"
25:
26: #define PAPER_WIDTH ROUNDUP(17*pixels_per_inch,shrink_factor*2)
27: #define PAPER_HEIGHT ROUNDUP(11*pixels_per_inch,shrink_factor)
28: #define X_PAGE_OFFSET ROUNDUP(pixels_per_inch,shrink_factor)
29: #define Y_PAGE_OFFSET ROUNDUP(pixels_per_inch,shrink_factor)
30:
31: #define pixel_round(x) ((long) (conv * (double) (x) + 0.5))
32: #define dvi_round(x) ((long) ((double) (x) / conv + 0.5))
33:
34: #define one(fp) num (fp, 1)
35: #define two(fp) num (fp, 2)
36: #define stwo(fp) snum(fp, 2)
37: #define four(fp) num (fp, 4)
38: #define sfour(fp) snum(fp, 4)
39:
40: typedef unsigned char ubyte;
41:
42: struct frame {
43: long pxl_h, dvi_h, pxl_v, dvi_v, w, x, y, z;
44: };
45:
46: struct frame *stack;
47: int stackp;
48:
49: #define PXL_H stack[stackp].pxl_h
50: #define PXL_V stack[stackp].pxl_v
51: #define DVI_H stack[stackp].dvi_h
52: #define DVI_V stack[stackp].dvi_v
53: #define WW stack[stackp].w
54: #define XX stack[stackp].x
55: #define YY stack[stackp].y
56: #define ZZ stack[stackp].z
57:
58: #define DBG_BITMAP 0x1
59: #define DBG_DVI 0x2
60: #define DBG_ALL (DBG_BITMAP|DBG_DVI)
61:
62: /*
63: * Command line flags.
64: */
65: int debug = 0;
66: int list_fonts = 0;
67:
68: int pixels_per_inch = 300;
69: int shrink_factor = 4;
70:
71: FILE *dvi_file; /* user's file */
72:
73: int font_not_found = 0;
74: struct font *current_font = NULL; /* ptr into circular list of fonts */
75: #define MAX_OPEN_FONTS 12
76: int n_open_fonts = 0; /* for LRU management of fonts */
77:
78: /*
79: * DVI preamble and postamble information.
80: */
81: char job_id[300];
82: int total_pages, maxstack;
83: int current_page;
84: double fraction, conv;
85: long numerator, denominator, magnification;
86:
87: /*
88: * Offset in DVI file of last page, set in read_postamble().
89: */
90: long last_page_offset;
91:
92: /*
93: * Table of page offsets in DVI file, indexed by page number - 1.
94: * Initialized in prepare_pages().
95: */
96: long *page_offset;
97:
98: #define xdvi_width 15
99: #define xdvi_height 15
100: #define xdvi_x_hot 7
101: #define xdvi_y_hot 7
102: static short xdvi_bits[] = {
103: 0x0080, 0x01c0, 0x03e0, 0x06b0,
104: 0x0c98, 0x188c, 0x3086, 0x7fff,
105: 0x3086, 0x188c, 0x0c98, 0x06b0,
106: 0x03e0, 0x01c0, 0x0080};
107:
108: Window win;
109: int forepix, backpix, highpix;
110:
111: long screen_w, screen_h, page_w, page_h;
112: long min_x, max_x, min_y, max_y, base_x, base_y;
113: long smin_x, smax_x, smin_y, smax_y;
114: int redisplay = 0;
115:
116: unsigned long num();
117: long snum();
118:
119: extern char reverse_byte[];
120: char *malloc(), *calloc(), *index();
121:
122: main(argc, argv)
123: int argc;
124: char **argv;
125: {
126: char *prog, *file;
127: char *display = NULL;
128: char *option;
129: OpaqueFrame frame;
130: int reverse = 0;
131: int bwidth = 2;
132: char *fore_color;
133: char *back_color;
134: char *high_color;
135: char *brdr_color;
136: char *mous_color;
137: char *geometry = NULL, def[32];
138: int backmap, bdrmap, mouspix;
139: Color cdef;
140:
141: prog = *argv++;
142: argc--;
143: if ((option = XGetDefault(prog, "ReverseVideo")) &&
144: strcmp(option, "on") == 0)
145: reverse = 1;
146: if (option = XGetDefault(prog, "BorderWidth"))
147: bwidth = atoi(option);
148: fore_color = XGetDefault(prog, "ForeGround");
149: back_color = XGetDefault(prog, "BackGround");
150: high_color = XGetDefault(prog, "Highlight");
151: brdr_color = XGetDefault(prog, "Border");
152: mous_color = XGetDefault(prog, "Mouse");
153: file = NULL;
154: while (argc) {
155: if (strncmp(*argv, "-d", 2) == 0)
156: debug = isdigit(argv[0][2]) ? atoi(&argv[0][2]) : DBG_ALL;
157: else if (strcmp(*argv, "-l") == 0)
158: list_fonts = 1;
159: else if (strcmp(*argv, "-s") == 0 && argc > 1) {
160: argv++;
161: argc--;
162: shrink_factor = atoi(*argv);
163: if (shrink_factor <= 0) goto usage;
164: } else if (strcmp(*argv, "-p") == 0 && argc > 1) {
165: argv++;
166: argc--;
167: pixels_per_inch = atoi(*argv);
168: if (pixels_per_inch <= 0) goto usage;
169: } else if (strcmp(*argv, "-rv") == 0) {
170: reverse = 1;
171: } else if (strcmp(*argv, "-fg") == 0 && argc > 1) {
172: argv++;
173: argc--;
174: fore_color = *argv;
175: } else if (strcmp(*argv, "-bg") == 0 && argc > 1) {
176: argv++;
177: argc--;
178: back_color = *argv;
179: } else if (strcmp(*argv, "-hl") == 0 && argc > 1) {
180: argv++;
181: argc--;
182: high_color = *argv;
183: } else if (strcmp(*argv, "-bd") == 0 && argc > 1) {
184: argv++;
185: argc--;
186: brdr_color = *argv;
187: } else if (strcmp(*argv, "-ms") == 0 && argc > 1) {
188: argv++;
189: argc--;
190: mous_color = *argv;
191: } else if (**argv == '=') {
192: geometry = *argv;
193: } else if (**argv != '-') {
194: if (index(*argv, ':') != NULL)
195: display = *argv;
196: else
197: file = *argv;
198: } else {
199: usage:
200: fprintf(stderr, "Usage: xdvi [-s <shrink>] [-p <pixels>] [-l] [-rv] [-fg <color>] [-bg <color>] [-hl <color>] [-bd <color>] [-ms <color>] [=<geometry>] [host:display] dvi_file\n");
201: exit(1);
202: }
203: argv++;
204: argc--;
205: }
206: if (file == NULL)
207: goto usage;
208: if ((dvi_file = fopen(file, "r")) == NULL) {
209: int n = strlen(file);
210: char *dvi_name;
211:
212: if (strcmp(file + n - sizeof(".dvi") + 1, ".dvi") == 0) {
213: perror(file);
214: exit(1);
215: }
216: dvi_name = malloc((unsigned) n + sizeof(".dvi"));
217: sprintf(dvi_name, "%s.dvi", file);
218: if ((dvi_file = fopen(dvi_name, "r")) == NULL) {
219: perror(dvi_name);
220: exit(1);
221: }
222: }
223: process_preamble();
224: find_postamble();
225: read_postamble();
226: prepare_pages();
227: init_page();
228: if (XOpenDisplay(display) == NULL) {
229: fprintf(stderr, "Can't open display %s!\n", display);
230: exit(1);
231: }
232: if (reverse) {
233: forepix = WhitePixel;
234: highpix = WhitePixel;
235: backpix = BlackPixel;
236: backmap = BlackPixmap;
237: bdrmap = WhitePixmap;
238: mouspix = WhitePixel;
239: } else {
240: forepix = BlackPixel;
241: highpix = BlackPixel;
242: backpix = WhitePixel;
243: backmap = WhitePixmap;
244: bdrmap = BlackPixmap;
245: mouspix = BlackPixel;
246: }
247: if (DisplayCells() > 2) {
248: if (fore_color && XParseColor(fore_color, &cdef) &&
249: XGetHardwareColor(&cdef))
250: forepix = cdef.pixel;
251: if (back_color && XParseColor(back_color, &cdef) &&
252: XGetHardwareColor(&cdef)) {
253: backpix = cdef.pixel;
254: backmap = XMakeTile(backpix);
255: }
256: if (high_color && XParseColor(high_color, &cdef) &&
257: XGetHardwareColor(&cdef))
258: highpix = cdef.pixel;
259: if (brdr_color && XParseColor(brdr_color, &cdef) &&
260: XGetHardwareColor(&cdef))
261: bdrmap = XMakeTile(cdef.pixel);
262: if (mous_color && XParseColor(mous_color, &cdef) &&
263: XGetHardwareColor(&cdef))
264: mouspix = cdef.pixel;
265: }
266: frame.bdrwidth = bwidth;
267: frame.height = page_h;
268: if (frame.height + (bwidth << 1) > DisplayHeight())
269: frame.height = DisplayHeight() - (bwidth << 1);
270: frame.width = page_w;
271: if (frame.width + (bwidth << 1) > DisplayWidth())
272: frame.width = DisplayWidth() - (bwidth << 1);
273: frame.border = bdrmap;
274: frame.background = backmap;
275: frame.x = 0;
276: frame.y = 0;
277: sprintf(def, "=%dx%d+0+0", frame.width, frame.height);
278: win = XCreate("DVI Previewer", prog, geometry, def, &frame, 50, 50);
279: screen_h = frame.height;
280: screen_w = frame.width;
281: XMapWindow(win);
282: XSelectInput(win, KeyPressed|ButtonPressed|ExposeWindow|ExposeRegion);
283: XDefineCursor(win,
284: XCreateCursor(xdvi_width, xdvi_height, xdvi_bits, xdvi_bits,
285: xdvi_x_hot, xdvi_y_hot, mouspix, backpix, GXcopy));
286: do_pages();
287: stop_output(0);
288: }
289:
290: /*
291: ** process_preamble reads the information in the preamble and stores
292: ** it into global variables for later use.
293: */
294: process_preamble()
295: {
296: ubyte k;
297:
298: if (one(dvi_file) != PRE)
299: error("xdvi: DVI file doesn't start with preamble");
300: if (one(dvi_file) != 2)
301: error("xdvi: Wrong version of DVI output for this program");
302: numerator = four(dvi_file);
303: denominator = four(dvi_file);
304: magnification = four(dvi_file);
305: fraction = (((double) numerator * magnification)
306: / ((double) denominator * 1000.));
307: define_conv();
308: k = one(dvi_file);
309: fread(job_id, sizeof(char), k, dvi_file);
310: job_id[k] = '\0';
311: }
312:
313: define_conv ()
314: {
315: conv = ((fraction * pixels_per_inch) / 100000) / (2.54 * shrink_factor);
316: }
317:
318: /*
319: ** find_postamble locates the beginning of the postamble
320: ** and leaves the file ready to start reading at that location.
321: */
322: find_postamble()
323: {
324: ubyte byte;
325: long offset = -4; /* At least 4 TRAILERS */
326:
327: do {
328: offset -= 1;
329: fseek(dvi_file, offset, 2);
330: byte = one(dvi_file);
331: } while (byte == TRAILER);
332: if (byte != 2)
333: error("xdvi: Wrong version of DVI output for this program");
334: offset -= 4;
335: fseek(dvi_file, offset, 2);
336: fseek(dvi_file, sfour(dvi_file), 0);
337: }
338:
339: /*
340: ** read_postamble reads the information in the postamble,
341: ** storing it into global variables.
342: ** It also takes care of reading in all of the PXL files for the fonts
343: ** used in the job.
344: */
345: read_postamble()
346: {
347: ubyte cmnd;
348: int page_width, page_height;
349:
350: if (one(dvi_file) != POST)
351: error("xdvi: Postamble doesn't begin with POST");
352: last_page_offset = four(dvi_file);
353: if (numerator != four(dvi_file)
354: || denominator != four(dvi_file)
355: || magnification != four(dvi_file))
356: error("xdvi: Postamble doesn't match preamble");
357: page_height = pixel_round(four(dvi_file));
358: page_width = pixel_round(four(dvi_file));
359: maxstack = two(dvi_file);
360: total_pages = two(dvi_file);
361: do {
362: switch(cmnd = one(dvi_file)) {
363: case FNTDEF1:
364: case FNTDEF2:
365: case FNTDEF3:
366: case FNTDEF4:
367: define_font(cmnd);
368: break;
369: case POSTPOST:
370: break;
371: default:
372: error("xdvi: Non-fntdef cmnd found in postamble");
373: }
374: } while (cmnd != POSTPOST);
375: if (font_not_found)
376: error("xdvi: Not all PXL files were found");
377: list_fonts = 0;
378: }
379:
380: prepare_pages()
381: {
382: int i;
383:
384: stack = (struct frame *) malloc((unsigned) sizeof(struct frame) * (maxstack+1));
385: if (stack == NULL)
386: error("xdvi: Can't allocate stack space (%d frames)", maxstack);
387: page_offset = (long *) malloc((unsigned) total_pages * sizeof(long));
388: if (page_offset == NULL)
389: error("xdvi: Can't allocate page directory (%d pages)", total_pages);
390: i = total_pages;
391: page_offset[--i] = last_page_offset;
392: fseek(dvi_file, last_page_offset, 0);
393: /*
394: * Follow back pointers through pages in the DVI file,
395: * storing the offsets in the page_offset table.
396: */
397: while (i > 0) {
398: num(dvi_file, 1+4+(9*4));
399: fseek(dvi_file, page_offset[--i] = four(dvi_file), 0);
400: }
401: }
402:
403: /*
404: ** define_font reads the rest of the fntdef command and then reads in
405: ** the specified PXL file, adding it to the global linked-list holding
406: ** all of the fonts used in the job.
407: */
408: define_font(cmnd)
409: ubyte cmnd;
410: {
411: register struct font *fontp;
412: int len;
413: int unmodsize;
414: float realsize;
415: int size;
416: long checksum;
417:
418: fontp = (struct font *) malloc((unsigned) sizeof(struct font));
419: if (fontp == NULL)
420: error("xdvi: Can't allocate memory for font");
421: fontp->TeXnumber = num(dvi_file, cmnd - FNTDEF1 + 1);
422: checksum = four(dvi_file);
423: fontp->scale = four(dvi_file);
424: fontp->design = four(dvi_file);
425: len = one(dvi_file) + one(dvi_file);
426: fontp->fontname = malloc(len + 10); /* leave space for magnification */
427: fread(fontp->fontname, sizeof(char), len, dvi_file);
428: fontp->fontname[len] = '\0';
429: fontp->file = NULL;
430: /*
431: ** In the actual implementation, scaled-size/design-size hasn't been
432: ** stored with sufficient precision, hence the messing around to find
433: ** its actual value.
434: */
435: realsize = (magnification/1000.)*((float) fontp->scale / fontp->design);
436: unmodsize = (realsize * 1000) + 0.5;
437: /* a real hack to correct for rounding in some cases */
438: switch (unmodsize) {
439: case 1095:
440: realsize = 1.095445; /* stephalf */
441: break;
442: case 1315:
443: realsize = 1.314534; /* stepihalf */
444: break;
445: case 2074:
446: realsize = 2.0736; /* stepiv */
447: break;
448: case 2488:
449: realsize = 2.48832; /* stepv */
450: break;
451: case 2986:
452: realsize = 2.985984; /* stepiv */
453: break;
454: }
455: /*
456: * the remaining magnification steps are represented
457: * with sufficient accuracy already
458: */
459: size = (realsize * pixels_per_inch * 5) + 0.5;
460: sprintf(&fontp->fontname[len], FONT_SUFFIX, size);
461: if (!open_pxl_file(fontp))
462: return;
463: read_glyphs(fontp);
464: if (current_font == NULL) {
465: fontp->next = fontp;
466: fontp->prev = fontp;
467: } else {
468: fontp->next = current_font;
469: fontp->prev = current_font->prev;
470: current_font->prev->next = fontp;
471: current_font->prev = fontp;
472: }
473: current_font = fontp;
474: }
475:
476: open_pxl_file(font)
477: struct font *font;
478: {
479: char filename[300];
480: extern int errno;
481:
482: if (font->file == NULL) {
483: sprintf(filename, "%s/%s",
484: FONT_DIRECTORY, font->fontname);
485: if (n_open_fonts == MAX_OPEN_FONTS)
486: close_lru();
487: font->file = fopen(filename, "r");
488: if (font->file == NULL) {
489: font_not_found = 1;
490: printf("%s [not found]\n", font->fontname);
491: return (0);
492: }
493: n_open_fonts += 1;
494: }
495: if (list_fonts)
496: printf("%s\n", font->fontname);
497: return (1);
498: }
499:
500: read_pxl_bitmap(ch, g)
501: ubyte ch;
502: register struct glyph *g;
503: {
504: register struct bitmap *bitmap;
505: register int file_bytes_wide;
506: register char *ptr;
507: register int i, j;
508:
509: bitmap = &g->bitmap;
510:
511: /* in file, bitmap rows are multiples of 32 bits wide */
512: file_bytes_wide = ROUNDUP(bitmap->w, BITS_PER_LONG)*BYTES_PER_LONG;
513: /* width must be multiple of 16 bits for raster_op */
514: bitmap->bytes_wide = ROUNDUP(bitmap->w, BITS_PER_SHORT)*BYTES_PER_SHORT;
515: ptr = bitmap->bits = malloc((unsigned) bitmap->h * bitmap->bytes_wide);
516: if (ptr == NULL)
517: error("xdvi: Can't allocate bitmap for character %d of font %s (%d by %d)",
518: ch, current_font->fontname, bitmap->h, bitmap->w);
519: if (!open_pxl_file(current_font))
520: error("xdvi: Can't find font file %s", current_font->fontname);
521: fseek(current_font->file, g->addr, 0);
522: for (i = 0; i < bitmap->h; i += 1)
523: for (j = 0; j < file_bytes_wide; j += 1)
524: if (j < bitmap->bytes_wide)
525: *ptr++ = reverse_byte[one(current_font->file)];
526: else
527: one(current_font->file);
528: if (shrink_factor != 1)
529: shrink_bitmap(bitmap, shrink_factor, shrink_factor);
530: if (debug & DBG_BITMAP)
531: print_char(ch, g);
532: }
533:
534: /*
535: * Find font #n and move it to the head of the list.
536: */
537: change_font(n)
538: unsigned long n;
539: {
540: register struct font *fontp;
541:
542: fontp = current_font;
543: for (;;) {
544: if (fontp->TeXnumber == n)
545: break;
546: fontp = fontp->next;
547: if (fontp == current_font)
548: error("xdvi: Non-existent font #%d", n);
549: }
550: if (current_font == fontp)
551: return;
552: fontp->prev->next = fontp->next;
553: fontp->next->prev = fontp->prev;
554: fontp->next = current_font;
555: fontp->prev = current_font->prev;
556: current_font->prev->next = fontp;
557: current_font->prev = fontp;
558: current_font = fontp;
559: }
560:
561: /*
562: * Close the PXL file for the least recently used font.
563: */
564: close_lru()
565: {
566: register struct font *f;
567:
568: f = current_font->prev;
569: for (;;) {
570: if (f->file != NULL)
571: break;
572: f = f->prev;
573: if (f == current_font->prev)
574: error("xdvi: Can't find an open PXL file to close");
575: }
576: fclose(f->file);
577: f->file = NULL;
578: n_open_fonts -= 1;
579: }
580:
581: reset_fonts()
582: {
583: register struct font *f;
584: register struct glyph *g;
585:
586: f = current_font;
587: for (;;) {
588: open_pxl_file(f);
589: for (g = &f->glyph[0]; g < &f->glyph[MAXCHARS]; g += 1) {
590: if (g->bitmap.bits) free(g->bitmap.bits);
591: }
592: read_glyphs(f);
593: f = f->next;
594: if (f == current_font) break;
595: }
596: }
597:
598: read_glyphs (fontp)
599: register struct font *fontp;
600: {
601: register struct glyph *g;
602: long checksum, magnify, design_size, font_dir_ptr, pxl_id_word;
603:
604: /* seek to trailer info */
605: fseek(fontp->file, (long) -(5 * BYTES_PER_LONG), 2);
606: checksum = four(fontp->file);
607: magnify = four(fontp->file);
608: design_size = four(fontp->file);
609: font_dir_ptr = sfour(fontp->file) * 4;
610: pxl_id_word = four(fontp->file);
611: #ifdef lint
612: magnify = design_size = pxl_id_word = magnify;
613: #endif
614: /* seek to font directory */
615: fseek(fontp->file, font_dir_ptr, 0);
616: for (g = &fontp->glyph[0]; g < &fontp->glyph[MAXCHARS]; g += 1) {
617: g->bitmap.bits = NULL;
618: g->bitmap.w = two(fontp->file); /* leave this for shrink_bitmap */
619: g->bitmap.h = two(fontp->file); /* leave this for shrink_bitmap */
620: g->x = stwo(fontp->file) / shrink_factor;
621: g->y = stwo(fontp->file) / shrink_factor;
622: g->addr = four(fontp->file) * 4;
623: /*
624: ** The TFM-width word is kind of funny in the units
625: ** it is expressed in. It works this way:
626: **
627: ** If a glyph has width 'w' in a font with design-size
628: ** 'd' (both in same units), the TFM-width word is
629: **
630: ** (w/d) * 2^20
631: **
632: ** Therefore, in order to find the glyph width in
633: ** DVI units (1 / 2^16 points), we take the design-size
634: ** 'd' (in DVI's), the magnification 'm' of the PXL file
635: ** and the TFM-width word 't' to the width (in DVI's)
636: ** as follows:
637: **
638: ** dmt
639: ** w = -----
640: ** 2^20
641: **
642: ** But the magnification of the PXL file is just the
643: ** scaled size 's' over the design size, so the final
644: ** expression for the width is
645: **
646: ** st
647: ** w = ----
648: ** 2^20
649: **
650: */
651: g->dvi_adv =
652: ((double) fontp->scale * four(fontp->file)) / (1 << 20);
653: g->pxl_adv = pixel_round(g->dvi_adv);
654: }
655: }
656:
657: #define nope(str) error("xdvi: %s not implemented", str)
658: #define correct() (PXL_H = pixel_round(DVI_H))
659:
660: do_pages()
661: {
662: ubyte ch;
663:
664: min_x = 0;
665: min_y = 0;
666: max_x = screen_w;
667: max_y = screen_h;
668: base_x = min_x;
669: base_y = min_y;
670: current_page = 0;
671: for (;;) {
672: ch = one(dvi_file);
673: if (debug & DBG_DVI)
674: print_dvi(ch);
675: if (ch <= SETCHAR0 + 127) {
676: set_char(ch);
677: DVI_H += current_font->glyph[ch].dvi_adv;
678: PXL_H += current_font->glyph[ch].pxl_adv;
679: correct();
680: } else if (FNTNUM0 <= ch && ch <= FNTNUM0 + 63) {
681: change_font((unsigned long) (ch - FNTNUM0));
682: } else {
683: long a, b;
684:
685: switch (ch) {
686: case SET1:
687: nope("SET1");
688: break;
689:
690: case SETRULE:
691: a = sfour(dvi_file); b = sfour(dvi_file);
692: if (a > 0 && b > 0) {
693: correct();
694: set_rule(pixel_round(a), pixel_round(b));
695: }
696: DVI_H += b;
697: PXL_H = pixel_round(DVI_H);
698: break;
699:
700: case PUT1:
701: nope("PUT1");
702: break;
703:
704: case PUTRULE:
705: a = sfour(dvi_file); b = sfour(dvi_file);
706: if (a > 0 && b > 0) {
707: correct();
708: set_rule(pixel_round(a), pixel_round(b));
709: }
710: break;
711:
712: case NOP:
713: break;
714:
715: case BOP:
716: num(dvi_file, 11*4);
717: stackp = 0;
718: DVI_H = dvi_round(X_PAGE_OFFSET);
719: PXL_H = X_PAGE_OFFSET;
720: DVI_V = dvi_round(Y_PAGE_OFFSET);
721: PXL_V = Y_PAGE_OFFSET;
722: WW = XX = YY = ZZ = 0;
723: begin_page();
724: break;
725:
726: case EOP:
727: if (stackp > 0)
728: error("Stack not empty at EOP (%d)",
729: stackp);
730: end_page();
731: if (ftell(dvi_file) > last_page_offset)
732: return;
733: break;
734:
735: case PUSH:
736: stackp++;
737: if (stackp > maxstack)
738: error("xdvi: More PUSHes than were promised");
739: stack[stackp] = stack[stackp - 1];
740: break;
741:
742: case POP:
743: stackp--;
744: if (stackp < 0)
745: error("xdvi: More POPs than PUSHes");
746: break;
747:
748: case RIGHT1:
749: case RIGHT2:
750: case RIGHT3:
751: case RIGHT4:
752: DVI_H += snum(dvi_file, ch - RIGHT1 + 1);
753: PXL_H = pixel_round(DVI_H);
754: break;
755:
756: case X0:
757: case X1:
758: case X2:
759: case X3:
760: case X4:
761: if (ch != X0)
762: XX = snum(dvi_file, ch - X0);
763: DVI_H += XX;
764: PXL_H += pixel_round(XX);
765: correct();
766: break;
767:
768: case W0:
769: case W1:
770: case W2:
771: case W3:
772: case W4:
773: if (ch != W0)
774: WW = snum(dvi_file, ch - W0);
775: DVI_H += WW;
776: PXL_H = pixel_round(DVI_H);
777: break;
778:
779: case Y0:
780: case Y1:
781: case Y2:
782: case Y3:
783: case Y4:
784: if (ch != Y0)
785: YY = snum(dvi_file, ch - Y0);
786: DVI_V += YY;
787: PXL_V = pixel_round(DVI_V);
788: break;
789:
790: case Z0:
791: case Z1:
792: case Z2:
793: case Z3:
794: case Z4:
795: if (ch != Z0)
796: ZZ = snum(dvi_file, ch - Z0);
797: DVI_V += ZZ;
798: PXL_V = pixel_round(DVI_V);
799: break;
800:
801: case DOWN1:
802: case DOWN2:
803: case DOWN3:
804: case DOWN4:
805: DVI_V += snum(dvi_file, ch - DOWN1 + 1);
806: PXL_V = pixel_round(DVI_V);
807: break;
808:
809: case FNT1:
810: case FNT2:
811: case FNT3:
812: case FNT4:
813: change_font(num(dvi_file, ch - FNT1 + 1));
814: break;
815:
816: case XXX1:
817: case XXX2:
818: case XXX3:
819: case XXX4:
820: a = num(dvi_file, ch - XXX1 + 1);
821: if(a > 0)
822: special((unsigned long) a);
823: break;
824:
825: case FNTDEF1:
826: case FNTDEF2:
827: case FNTDEF3:
828: case FNTDEF4:
829: fseek(dvi_file, (long) (12 + ch - FNTDEF1 + 1), 1);
830: a = one(dvi_file) + one(dvi_file);
831: fseek(dvi_file, (long) a, 1);
832: break;
833:
834: case PRE:
835: error("xdvi: Shouldn't happen: PRE encountered.");
836: break;
837:
838: case POST:
839: error("xdvi: Shouldn't happen: POST encountered.");
840: break;
841:
842: case POSTPOST:
843: error("xdvi: Shouldn't happen: POSTPOST encountered.");
844: break;
845:
846: default:
847: error("xdvi: Unknown op-code %d, offset %d",
848: ch, ftell(dvi_file));
849: } /* end switch*/
850: } /* end else (ch not a SETCHAR or FNTNUM) */
851: } /* end for */
852: }
853:
854: set_char(ch)
855: ubyte ch;
856: {
857: register struct glyph *g;
858:
859: g = ¤t_font->glyph[ch];
860: if (g->bitmap.bits == NULL)
861: read_pxl_bitmap(ch, g);
862: put_bitmap(&g->bitmap, (PXL_H - g->x), (PXL_V - g->y), forepix);
863: }
864:
865: set_rule(h, w)
866: long h, w;
867: {
868: /* (w,h) specifies lower left corner of rule box */
869: put_rectangle(PXL_H, PXL_V - h, w, h, forepix);
870: }
871:
872: begin_page()
873: {
874: if (debug)
875: return;
876: if (!redisplay)
877: clear_page();
878: put_border(0, 0, page_w, page_h, 1);
879: }
880:
881: end_page()
882: {
883: int ch, arg, sign, number, next_page;
884: XEvent event;
885: char *string;
886: int nbytes;
887:
888: #ifdef lint
889: number = 0;
890: #endif
891: if (debug) {
892: if (++current_page == total_pages)
893: exit(0);
894: return;
895: }
896: if (redisplay) {
897: min_x = smin_x;
898: max_x = smax_x;
899: min_y = smin_y;
900: max_y = smax_y;
901: redisplay = 0;
902: }
903: arg = 0;
904: for (;;) {
905: XNextEvent (&event);
906: switch (event.type) {
907: case ExposeWindow:
908: screen_h = ((XExposeEvent *)(&event))->height;
909: screen_w = ((XExposeEvent *)(&event))->width;
910: max_x = min_x + screen_w;
911: max_y = min_y + screen_h;
912: string = "\f";
913: nbytes = 1;
914: break;
915: case ExposeRegion:
916: smin_x = min_x;
917: smax_x = max_x;
918: smin_y = min_y;
919: smax_y = max_y;
920: min_x = min_x + ((XExposeEvent *)(&event))->x;
921: min_y = min_y + ((XExposeEvent *)(&event))->y;
922: max_x = min_x + ((XExposeEvent *)(&event))->width;
923: max_y = min_y + ((XExposeEvent *)(&event))->height;
924: redisplay = 1;
925: string = "\f";
926: nbytes = 1;
927: break;
928: case ButtonPressed:
929: {
930: short detail = ((XButtonPressedEvent *) (&event))->detail;
931: switch (detail & ValueMask) {
932: case LeftButton:
933: if (detail & ShiftMask)
934: string = "l";
935: else
936: string = "b";
937: nbytes = 1;
938: break;
939: case MiddleButton:
940: if (detail & ShiftMask)
941: string = "u";
942: else
943: string = "d";
944: nbytes = 1;
945: break;
946: case RightButton:
947: if (detail & ShiftMask)
948: string = "r";
949: else
950: string = "f";
951: nbytes = 1;
952: break;
953: }
954: }
955: break;
956: case KeyPressed:
957: string = XLookupMapping (&event, &nbytes);
958: break;
959: }
960: if (nbytes == 0) continue;
961: if (nbytes > 1) goto bad;
962: switch (ch = *string) {
963: case 'q':
964: case '\003': /* control-C */
965: case '\004': /* control-D */
966: stop_output(0);
967: break;
968: case 'n':
969: case 'f':
970: case ' ':
971: /* scroll forward */
972: min_x = 0;
973: min_y = 0;
974: max_x = screen_w;
975: max_y = screen_h;
976: next_page = current_page + 1;
977: break;
978: case 'p':
979: case 'b':
980: case '\b':
981: /* scroll backward */
982: min_x = 0;
983: min_y = 0;
984: max_x = screen_w;
985: max_y = screen_h;
986: next_page = current_page - 1;
987: break;
988: case 'u':
989: if (min_y == 0) goto bad;
990: min_y -= screen_h;
991: if (min_y < 0)
992: min_y = 0;
993: base_y = min_y;
994: max_y = min_y + screen_h;
995: next_page = current_page;
996: break;
997: case 'd':
998: if (min_y >= page_h - screen_h) goto bad;
999: min_y += screen_h;
1000: if (min_y > page_h - screen_h)
1001: min_y = page_h - screen_h;
1002: if (min_y < 0)
1003: min_y = 0;
1004: base_y = min_y;
1005: max_y = min_y + screen_h;
1006: next_page = current_page;
1007: break;
1008: case 'l':
1009: if (min_x == 0) goto bad;
1010: min_x -= screen_w;
1011: if (min_x < 0)
1012: min_x = 0;
1013: base_x = min_x;
1014: max_x = min_x + screen_w;
1015: next_page = current_page;
1016: break;
1017: case 'r':
1018: if (min_x >= page_w - screen_w) goto bad;
1019: min_x += screen_w;
1020: if (min_x > page_w - screen_w)
1021: min_x = page_w - screen_w;
1022: if (min_x < 0)
1023: min_x = 0;
1024: base_x = min_x;
1025: max_x = min_x + screen_w;
1026: next_page = current_page;
1027: break;
1028: case 's':
1029: if (!arg) {
1030: int shrink = shrink_factor;
1031: long fac1, fac2;
1032: shrink_factor = 1;
1033: fac1 = ROUNDUP(PAPER_WIDTH, screen_w);
1034: fac2 = ROUNDUP(PAPER_HEIGHT, screen_h);
1035: if (fac1 < fac2)
1036: number = fac2;
1037: else
1038: number = fac1;
1039: shrink_factor = shrink;
1040: }
1041: if (number <= 0) goto bad;
1042: if (number != shrink_factor) {
1043: shrink_factor = number;
1044: min_x = 0;
1045: min_y = 0;
1046: max_x = screen_w;
1047: max_y = screen_h;
1048: init_page();
1049: define_conv();
1050: reset_fonts();
1051: }
1052: case '\f':
1053: /* redisplay current page */
1054: next_page = current_page;
1055: break;
1056: case '\r':
1057: case '\n':
1058: /* go to relative page */
1059: min_x = 0;
1060: min_y = 0;
1061: max_x = screen_w;
1062: max_y = screen_h;
1063: next_page = current_page + (arg ? number : 1);
1064: break;
1065: case 'g':
1066: /* go to absolute page */
1067: min_x = 0;
1068: min_y = 0;
1069: max_x = screen_w;
1070: max_y = screen_h;
1071: next_page = (arg ? number : total_pages) - 1;
1072: break;
1073: case '0': case '1': case '2': case '3': case '4':
1074: case '5': case '6': case '7': case '8': case '9':
1075: if (! arg) {
1076: arg = 1;
1077: sign = 1;
1078: number = 0;
1079: }
1080: number = 10*number + sign*(ch - '0');
1081: continue;
1082: case '-':
1083: if (! arg) {
1084: arg = 1;
1085: sign = -1;
1086: number = 0;
1087: continue;
1088: } else
1089: goto bad;
1090: default:
1091: goto bad;
1092: }
1093: if (0 <= next_page && next_page < total_pages) {
1094: current_page = next_page;
1095: fseek(dvi_file, page_offset[current_page], 0);
1096: break;
1097: }
1098: bad:
1099: XFeep(0);
1100: arg = 0; /* throw away numeric argument */
1101: continue;
1102: }
1103: }
1104:
1105: special(nbytes)
1106: unsigned long nbytes;
1107: {
1108: char *cmd;
1109: int i;
1110:
1111: cmd = malloc((unsigned) nbytes+1);
1112: if (cmd == NULL)
1113: error("xdvi: Can't allocate memory for special (%d bytes)", nbytes);
1114: for (i = 0; i < nbytes; i += 1)
1115: cmd[i] = getc(dvi_file);
1116: cmd[i] = '\0';
1117: fprintf(stderr, "special ``%s'' not implemented\n", cmd);
1118: free(cmd);
1119: }
1120:
1121: /*
1122: **
1123: ** Read size bytes from the FILE fp, constructing them into a
1124: ** signed/unsigned integer.
1125: **
1126: */
1127: unsigned long
1128: num(fp, size)
1129: register FILE *fp;
1130: register int size;
1131: {
1132: register int i;
1133: register long x;
1134:
1135: x = 0;
1136: for (i = 0; i < size; i += 1)
1137: x = x * 0x100 + (unsigned) getc(fp);
1138: return (x);
1139: }
1140:
1141: long
1142: snum(fp, size)
1143: register FILE *fp;
1144: register int size;
1145: {
1146: register int i;
1147: register long x;
1148:
1149: x = getc(fp) & 0xff;
1150: if (x & 0x80)
1151: x -= 0x100;
1152: for (i = 1; i < size; i += 1)
1153: x = x * 0x100 + (unsigned) getc(fp);
1154: return (x);
1155: }
1156:
1157: stop_output(sig)
1158: {
1159: exit(sig);
1160: }
1161:
1162: /* VARARGS1 */
1163: error(message, a, b, c, d, e, f)
1164: char *message;
1165: {
1166: fprintf(stderr, message, a, b, c, d, e, f);
1167: putc('\n', stderr);
1168: exit(1);
1169: }
1170:
1171: init_page()
1172: {
1173: page_h = PAPER_HEIGHT;
1174: page_w = PAPER_WIDTH;
1175: }
1176:
1177: clear_page()
1178: {
1179: XClear(win);
1180: }
1181:
1182: put_border(x, y, w, h, t)
1183: long x, y, w, h, t;
1184: {
1185: put_rectangle(x, y, w, t, highpix);
1186: put_rectangle(x, y, t, h, highpix);
1187: put_rectangle(x, y + h - t, w, t, highpix);
1188: put_rectangle(x + w - t, y, t, h, highpix);
1189: }
1190:
1191: put_rectangle(x, y, w, h, pix)
1192: long x, y, w, h;
1193: int pix;
1194: {
1195: if (x < max_x && x + w >= min_x && y < max_y && y + h >= min_y)
1196: XPixSet(win, x - base_x, y - base_y, w, h, pix);
1197: }
1198:
1199: put_bitmap(bitmap, x, y, pix)
1200: register struct bitmap *bitmap;
1201: register long x, y;
1202: int pix;
1203: {
1204: if (x < max_x && x + bitmap->w >= min_x &&
1205: y < max_y && y + bitmap->h >= min_y)
1206: XBitmapBitsPut(win, x - base_x, y - base_y,
1207: bitmap->w, bitmap->h, (char *) bitmap->bits,
1208: pix, backpix, NULL, GXcopy, AllPlanes);
1209: }
1210:
1211: sample(bitmap, x, y, w, h)
1212: register struct bitmap *bitmap;
1213: int x, y, w, h;
1214: {
1215: register char *ptr, *endp;
1216: register int b, i, j, m, n;
1217:
1218: ptr = bitmap->bits
1219: + (y * bitmap->bytes_wide)
1220: + (x / BITS_PER_BYTE);
1221: endp = bitmap->bits + (bitmap->h * bitmap->bytes_wide);
1222: b = (1 << (x % BITS_PER_BYTE));
1223: n = 0;
1224: for (i = 0; i < h && ptr < endp; i += 1, ptr += bitmap->bytes_wide)
1225: for (m = b, j = 0; j < w; j += 1, m <<= 1)
1226: if (*ptr & m)
1227: n += 1;
1228: return (n >= (i * w) / 3);
1229: }
1230:
1231: shrink_bitmap(bitmap, x_factor, y_factor)
1232: register struct bitmap *bitmap;
1233: int x_factor, y_factor;
1234: {
1235: char *shrunk_bits;
1236: int shrunk_height, shrunk_width, shrunk_bytes_wide;
1237: register char *ptr;
1238: char *cp;
1239: register int x, y, b, m;
1240:
1241: shrunk_height = ROUNDUP(bitmap->h, y_factor);
1242: shrunk_width = ROUNDUP(bitmap->w, x_factor);
1243: shrunk_bytes_wide = ROUNDUP(shrunk_width, BITS_PER_SHORT)*BYTES_PER_SHORT;
1244: /* width must be multiple of 16 bits for raster_op */
1245: ptr = shrunk_bits = calloc((unsigned) shrunk_height * shrunk_bytes_wide, 1);
1246: if (ptr == NULL)
1247: error("Can't allocate shrunken bitmap (%d by %d)",
1248: shrunk_height, shrunk_width);
1249: for (y = 0; y < bitmap->h; y += y_factor) {
1250: b = 0;
1251: m = (1 << 0);
1252: cp = ptr;
1253: for (x = 0; x < bitmap->w; x += x_factor) {
1254: if (sample(bitmap, x, y, x_factor, y_factor))
1255: *ptr |= m;
1256: else
1257: *ptr &= ~m;
1258: b += 1;
1259: m <<= 1;
1260: if (b % BITS_PER_BYTE == 0) {
1261: b = 0;
1262: m = (1 << 0);
1263: ptr += 1;
1264: }
1265: }
1266: ptr = cp + shrunk_bytes_wide;
1267: }
1268: free(bitmap->bits);
1269: bitmap->bits = shrunk_bits;
1270: bitmap->h = shrunk_height;
1271: bitmap->w = shrunk_width;
1272: bitmap->bytes_wide = shrunk_bytes_wide;
1273: }
1274:
1275: print_char(ch, g)
1276: ubyte ch;
1277: struct glyph *g;
1278: {
1279: printf("char %d", ch);
1280: if (isprint(ch))
1281: printf(" (%c)", ch);
1282: putchar('\n');
1283: printf("x = %d, y = %d, pxl = %d, dvi = %d\n",
1284: g->x, g->y, g->pxl_adv, g->dvi_adv);
1285: print_bitmap(&g->bitmap);
1286: }
1287:
1288: print_bitmap(bitmap)
1289: register struct bitmap *bitmap;
1290: {
1291: register char *ptr;
1292: register int x, y, i;
1293:
1294: ptr = bitmap->bits;
1295: if (ptr == NULL)
1296: return;
1297: printf("w = %d, h = %d, bytes wide = %d\n",
1298: bitmap->w, bitmap->h, bitmap->bytes_wide);
1299: for (y = 0; y < bitmap->h; y += 1) {
1300: for (x = 0; x < bitmap->bytes_wide; x += 1) {
1301: for (i = 0; i < BITS_PER_BYTE; i += 1)
1302: if (*ptr & (1 << i))
1303: putchar('@');
1304: else
1305: putchar(' ');
1306: ptr += 1;
1307: }
1308: putchar('\n');
1309: }
1310: }
1311:
1312: print_dvi(ch)
1313: ubyte ch;
1314: {
1315: printf("%4d %4d ", PXL_H, PXL_V);
1316: if (ch <= SETCHAR0 + 127) {
1317: printf("SETCHAR%-3d", ch - SETCHAR0);
1318: if (isprint(ch))
1319: printf(" (%c)", ch);
1320: } else if (FNTNUM0 <= ch && ch <= FNTNUM0 + 63) {
1321: printf("FNTNUM%d", ch - FNTNUM0);
1322: } else {
1323: switch (ch) {
1324: case SET1:
1325: printf("SET1");
1326: break;
1327: case SETRULE:
1328: printf("SETRULE");
1329: break;
1330: case PUT1:
1331: printf("PUT1");
1332: break;
1333: case PUTRULE:
1334: printf("PUTRULE");
1335: break;
1336: case NOP:
1337: printf("NOP");
1338: break;
1339: case BOP:
1340: printf("BOP");
1341: break;
1342: case EOP:
1343: printf("EOP");
1344: break;
1345: case PUSH:
1346: printf("PUSH");
1347: break;
1348: case POP:
1349: printf("POP");
1350: break;
1351: case RIGHT1:
1352: case RIGHT2:
1353: case RIGHT3:
1354: case RIGHT4:
1355: printf("RIGHT%d", ch - RIGHT1 + 1);
1356: break;
1357: case X0:
1358: case X1:
1359: case X2:
1360: case X3:
1361: case X4:
1362: printf("X%d", ch - X0);
1363: break;
1364: case W0:
1365: case W1:
1366: case W2:
1367: case W3:
1368: case W4:
1369: printf("W%d", ch - W0);
1370: break;
1371: case Y0:
1372: case Y1:
1373: case Y2:
1374: case Y3:
1375: case Y4:
1376: printf("Y%d", ch - Y0);
1377: break;
1378: case Z0:
1379: case Z1:
1380: case Z2:
1381: case Z3:
1382: case Z4:
1383: printf("Z%d", ch - Z0);
1384: break;
1385: case DOWN1:
1386: case DOWN2:
1387: case DOWN3:
1388: case DOWN4:
1389: printf("DOWN%d", ch - DOWN1 + 1);
1390: break;
1391: case FNT1:
1392: case FNT2:
1393: case FNT3:
1394: case FNT4:
1395: printf("FNT%d", ch - FNT1 + 1);
1396: break;
1397: case XXX1:
1398: case XXX2:
1399: case XXX3:
1400: case XXX4:
1401: printf("XXX%d", ch - XXX1 + 1);
1402: break;
1403: case FNTDEF1:
1404: case FNTDEF2:
1405: case FNTDEF3:
1406: case FNTDEF4:
1407: printf("FNTDEF%d", ch - FNTDEF1 + 1);
1408: break;
1409: case PRE:
1410: printf("PRE");
1411: break;
1412: case POST:
1413: printf("POST");
1414: break;
1415: case POSTPOST:
1416: printf("POSTPOST");
1417: break;
1418: default:
1419: error("xdvi: Unknown op-code %d, offset %d",
1420: ch, ftell(dvi_file));
1421: } /* end switch*/
1422: } /* end else (ch not a SETCHAR or FNTNUM) */
1423: putchar('\n');
1424: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.