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