home *** CD-ROM | disk | FTP | other *** search
- /*
- * DVI previewer for X.
- *
- * Eric Cooper, CMU, September 1985.
- *
- * Code derived from dvi-imagen.c.
- *
- * Modification history:
- * 1/1986 Modified for X.10 by Bob Scheifler, MIT LCS.
- * 7/1988 Modified for X.11 by Mark Eichin, MIT
- * 12/1988 Added 'R' option, toolkit, magnifying glass
- * --Paul Vojta, UC Berkeley.
- * 2/1989 Added tpic support --Jeffrey Lee, U of Toronto
- *
- * Compilation options:
- * X10 compile for X10
- * MSBITFIRST store bitmaps internally in with significant bit first
- * BMSHORT store bitmaps in shorts instead of bytes
- * BMLONG store bitmaps in longs instead of bytes
- */
-
- #include <stdio.h>
- #include <ctype.h>
- #include "xdvi.h"
- #include "dvi.h"
- #include <sys/stat.h>
-
- #define dvi_oops(str) longjmp(dvi_env, (int) str);
-
- static struct stat fstatbuf; /* mechanism to see if file was */
- time_t dvi_time; /* modified since last usage */
-
- struct font *current_font = NULL; /* ptr into linked list of fonts */
-
- static Boolean font_not_found;
- static struct font **old_fonts; /* used by read_postamble */
-
- int n_fonts_left = 32767; /* for LRU management of fonts */
-
- /*
- * DVI preamble and postamble information.
- */
- int current_page;
- Boolean spec_warn;
- int total_pages;
- double fraction;
- int maxstack;
- static char job_id[300];
- static long numerator, denominator, magnification;
-
- /*
- * Table of page offsets in DVI file, indexed by page number - 1.
- * Initialized in prepare_pages().
- */
- long *page_offset;
-
- /*
- * Offset in DVI file of last page, set in read_postamble().
- */
- static long last_page_offset;
-
- char *malloc(), *sprintf();
- FILE *pxl_open();
-
- static Boolean
- define_new_font(fontp)
- register struct font *fontp;
- {
- read_font_index_proc read_font_index;
-
- if (n_fonts_left == 0)
- close_a_file();
- fontp->file = pxl_open(font_path, fontp->fontname, fontp->size,
- (fontp->size + 2) / 5, &fontp->filename, &read_font_index);
- if (fontp->file == NULL) {
- Fprintf(stderr, "%s at %d dpi [not found]\n", fontp->fontname,
- (fontp->size + 2) / 5);
- font_not_found = True;
- return(False);
- }
- (*read_font_index)(fontp);
- --n_fonts_left;
- return(True);
- }
-
- /*
- * define_font reads the rest of the fntdef command and then reads in
- * the specified pixel file, adding it to the global linked-list holding
- * all of the fonts used in the job.
- */
- static
- define_font(cmnd)
- ubyte cmnd;
- {
- register struct font *fontp;
- struct font **fontpp = old_fonts;
- struct font *fontp1;
- int len;
- int design;
- int unmodsize;
- float realsize;
- int size;
-
- fontp = (struct font *) malloc((unsigned) sizeof(struct font));
- if (fontp == NULL)
- oops("Can't allocate memory for font");
- fontp->TeXnumber = num(dvi_file, (ubyte) cmnd - FNTDEF1 + 1);
- (void) four(dvi_file); /* checksum */
- fontp->scale = four(dvi_file);
- design = four(dvi_file);
- len = one(dvi_file) + one(dvi_file);
- fontp->fontname = malloc((unsigned) len + 1);
- Fread(fontp->fontname, sizeof(char), len, dvi_file);
- fontp->fontname[len] = '\0';
- if(debug & DBG_PK)
- Printf("Define font \"%s\" scale=%d design=%d\n",
- fontp->fontname, fontp->scale, design);
- /*
- * In the actual implementation, scaled-size/design-size hasn't been
- * stored with sufficient precision, hence the messing around to find
- * its actual value.
- */
- realsize = (magnification/1000.)*((float) fontp->scale / design);
- unmodsize = (realsize * 1000) + 0.5;
- /* a real hack to correct for rounding in some cases */
- switch (unmodsize) {
- case 1095:
- realsize = 1.095445; /* stephalf */
- break;
- case 1315:
- realsize = 1.314534; /* stepihalf */
- break;
- case 2074:
- realsize = 2.0736; /* stepiv */
- break;
- case 2488:
- realsize = 2.48832; /* stepv */
- break;
- case 2986:
- realsize = 2.985984; /* stepiv */
- break;
- }
- /*
- * the remaining magnification steps are represented
- * with sufficient accuracy already
- */
- fontp->size = size = (realsize * pixels_per_inch * 5) + 0.5;
- fontp->scale = fontp->scale * fraction;
- /*
- * reuse font if possible
- */
- for (;;) {
- fontp1 = *fontpp;
- if (fontp1 == NULL) {
- if (!define_new_font(fontp)) return;
- break;
- }
- if (strcmp(fontp->fontname, fontp1->fontname) == 0
- && size == fontp1->size) {
- *fontpp = fontp1->next;
- free(fontp->fontname);
- free((char *) fontp);
- fontp = fontp1;
- if (list_fonts)
- fputs("(reusing) ",stdout);
- break;
- }
- fontpp = &fontp1->next;
- }
-
- if (old_fonts == ¤t_font) old_fonts = &fontp->next;
- fontp->next = current_font;
- current_font = fontp;
- if (list_fonts)
- puts(fontp->fontname);
- }
-
- /*
- * process_preamble reads the information in the preamble and stores
- * it into global variables for later use.
- */
- static
- process_preamble()
- {
- ubyte k;
-
- if (one(dvi_file) != PRE)
- dvi_oops("DVI file doesn't start with preamble");
- if (one(dvi_file) != 2)
- dvi_oops("Wrong version of DVI output for this program");
- numerator = four(dvi_file);
- denominator = four(dvi_file);
- magnification = four(dvi_file);
- fraction = (((double) numerator * magnification)
- / ((double) denominator * 1000.));
- fraction = fraction * (((long) pixels_per_inch)<<16) / 254000;
- k = one(dvi_file);
- Fread(job_id, sizeof(char), (int) k, dvi_file);
- job_id[k] = '\0';
- }
-
- /*
- * find_postamble locates the beginning of the postamble
- * and leaves the file ready to start reading at that location.
- */
- static
- find_postamble()
- {
- ubyte byte;
- long offset = -4; /* At least 4 TRAILERS */
-
- do {
- offset -= 1;
- Fseek(dvi_file, offset, 2);
- byte = one(dvi_file);
- } while (byte == TRAILER);
- if (byte != 2)
- dvi_oops("Wrong version of DVI output for this program");
- offset -= 4;
- Fseek(dvi_file, offset, 2);
- Fseek(dvi_file, sfour(dvi_file), 0);
- }
-
- /*
- * read_postamble reads the information in the postamble,
- * storing it into global variables.
- * It also takes care of reading in all of the pixel files for the fonts
- * used in the job.
- */
- static
- read_postamble()
- {
- ubyte cmnd;
-
- if (one(dvi_file) != POST)
- dvi_oops("Postamble doesn't begin with POST");
- last_page_offset = four(dvi_file);
- if (numerator != four(dvi_file)
- || denominator != four(dvi_file)
- || magnification != four(dvi_file))
- dvi_oops("Postamble doesn't match preamble");
- (void) four(dvi_file); /* page height */
- (void) four(dvi_file); /* page width */
- maxstack = two(dvi_file);
- total_pages = two(dvi_file);
- old_fonts = ¤t_font;
- font_not_found = False;
- do {
- switch(cmnd = one(dvi_file)) {
- case FNTDEF1:
- case FNTDEF2:
- case FNTDEF3:
- case FNTDEF4:
- define_font(cmnd);
- break;
- case POSTPOST:
- break;
- default:
- dvi_oops("Non-fntdef command found in postamble");
- }
- } while (cmnd != POSTPOST);
- if (font_not_found)
- dvi_oops("Not all pixel files were found");
- /*
- * free up fonts no longer in use
- */
- {
- struct font *fontp = *old_fonts;
- struct font *fontp1;
- register struct glyph *g;
- *old_fonts = NULL;
- while (fontp != NULL) {
- if (fontp->file != NULL) {
- Fclose(fontp->file);
- ++n_fonts_left;
- }
- free(fontp->fontname);
- free(fontp->filename);
- for (g = &fontp->glyph[0]; g < &fontp->glyph[MAXCHARS]; ++g) {
- if (g->bitmap.bits) free(g->bitmap.bits);
- if (g->bitmap2.bits) free(g->bitmap2.bits);
- }
- fontp1 = fontp->next;
- free((char *) fontp);
- fontp = fontp1;
- }
- }
- }
-
- static
- prepare_pages()
- {
- int i;
-
- stack = (struct frame *)
- malloc((unsigned) sizeof(struct frame) * (maxstack+1));
- if (stack == NULL)
- oops("Can't allocate stack space (%d frames)", maxstack);
- page_offset = (long *) malloc((unsigned) total_pages * sizeof(long));
- if (page_offset == NULL)
- oops("Can't allocate page directory (%d pages)",
- total_pages);
- i = total_pages;
- page_offset[--i] = last_page_offset;
- Fseek(dvi_file, last_page_offset, 0);
- /*
- * Follow back pointers through pages in the DVI file,
- * storing the offsets in the page_offset table.
- */
- while (i > 0) {
- Fseek(dvi_file, (long) (1+4+(9*4)), 1);
- Fseek(dvi_file, page_offset[--i] = four(dvi_file), 0);
- }
- }
-
- init_page()
- {
- page_h = PAPER_HEIGHT;
- page_w = PAPER_WIDTH;
- }
-
- /*
- * init_dvi_file is the main subroutine for reading the startup information
- * from the dvi file.
- */
- static
- init_dvi_file()
- {
- (void) fstat(fileno(dvi_file), &fstatbuf);
- dvi_time = fstatbuf.st_mtime;
- process_preamble();
- find_postamble();
- read_postamble();
- prepare_pages();
- init_page();
- if (current_page >= total_pages) current_page = total_pages - 1;
- spec_warn = True;
- }
-
- /**
- ** open_dvi_file opens the dvi file and calls init_dvi_file() to
- ** initialize it.
- **/
-
- open_dvi_file()
- {
- char *errmsg;
-
- if ((dvi_file = fopen(dvi_name, OPEN_MODE)) == NULL) {
- int n = strlen(dvi_name);
- char *file = dvi_name;
-
- if (strcmp(dvi_name + n - sizeof(".dvi") + 1, ".dvi") == 0) {
- perror(dvi_name);
- exit(1);
- }
- dvi_name = malloc((unsigned) n + sizeof(".dvi"));
- Sprintf(dvi_name, "%s.dvi", file);
- if ((dvi_file = fopen(dvi_name, OPEN_MODE)) == NULL) {
- perror(dvi_name);
- exit(1);
- }
- }
-
- if (errmsg = (char *) setjmp(dvi_env)) oops(errmsg);
- init_dvi_file();
- }
-
- /**
- ** Release all shrunken bitmaps for all fonts.
- **/
-
- reset_fonts()
- {
- register struct font *f;
- register struct glyph *g;
-
- for (f = current_font; f != NULL; f = f->next)
- for (g = &f->glyph[0]; g < &f->glyph[MAXCHARS]; ++g)
- if (g->bitmap2.bits) {
- free(g->bitmap2.bits);
- g->bitmap2.bits = NULL;
- }
- }
-
- /**
- ** Check for changes in dvi file.
- **/
-
- Boolean
- check_dvi_file()
- {
- if (dvi_file == NULL || fstat(fileno(dvi_file), &fstatbuf) != 0
- || fstatbuf.st_mtime != dvi_time) {
- if (dvi_file) Fclose(dvi_file);
- free((char *) stack);
- free((char *) page_offset);
- dvi_file = fopen(dvi_name, OPEN_MODE);
- if (dvi_file == NULL)
- dvi_oops("Cannot reopen dvi file.");
- if (list_fonts) putchar('\n');
- init_dvi_file();
- redraw_page();
- return False;
- }
- return True;
- }
-