home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume3 / xdvi / part02 / dvi_init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-07  |  9.8 KB  |  408 lines

  1. /*
  2.  * DVI previewer for X.
  3.  *
  4.  * Eric Cooper, CMU, September 1985.
  5.  *
  6.  * Code derived from dvi-imagen.c.
  7.  *
  8.  * Modification history:
  9.  * 1/1986    Modified for X.10 by Bob Scheifler, MIT LCS.
  10.  * 7/1988    Modified for X.11 by Mark Eichin, MIT
  11.  * 12/1988    Added 'R' option, toolkit, magnifying glass
  12.  *            --Paul Vojta, UC Berkeley.
  13.  * 2/1989    Added tpic support    --Jeffrey Lee, U of Toronto
  14.  *
  15.  *    Compilation options:
  16.  *    X10    compile for X10
  17.  *    MSBITFIRST    store bitmaps internally in with significant bit first
  18.  *    BMSHORT    store bitmaps in shorts instead of bytes
  19.  *    BMLONG    store bitmaps in longs instead of bytes
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include <ctype.h>
  24. #include "xdvi.h"
  25. #include "dvi.h"
  26. #include <sys/stat.h>
  27.  
  28. #define    dvi_oops(str)    longjmp(dvi_env, (int) str);
  29.  
  30. static    struct stat fstatbuf;        /* mechanism to see if file was */
  31. time_t    dvi_time;            /* modified since last usage */
  32.  
  33. struct font *current_font = NULL;    /* ptr into linked list of fonts */
  34.  
  35. static    Boolean    font_not_found;
  36. static    struct font **old_fonts;    /* used by read_postamble */
  37.  
  38. int    n_fonts_left    = 32767;    /* for LRU management of fonts */
  39.  
  40. /*
  41.  * DVI preamble and postamble information.
  42.  */
  43. int    current_page;
  44. Boolean    spec_warn;
  45. int    total_pages;
  46. double    fraction;
  47. int    maxstack;
  48. static    char    job_id[300];
  49. static    long    numerator, denominator, magnification;
  50.  
  51. /*
  52.  * Table of page offsets in DVI file, indexed by page number - 1.
  53.  * Initialized in prepare_pages().
  54.  */
  55. long    *page_offset;
  56.  
  57. /*
  58.  * Offset in DVI file of last page, set in read_postamble().
  59.  */
  60. static    long    last_page_offset;
  61.  
  62. char    *malloc(), *sprintf();
  63. FILE    *pxl_open();
  64.  
  65. static    Boolean
  66. define_new_font(fontp)
  67.     register struct font *fontp;
  68. {
  69.     read_font_index_proc read_font_index;
  70.  
  71.     if (n_fonts_left == 0)
  72.         close_a_file();
  73.     fontp->file = pxl_open(font_path, fontp->fontname, fontp->size,
  74.         (fontp->size + 2) / 5, &fontp->filename, &read_font_index);
  75.     if (fontp->file == NULL) {
  76.         Fprintf(stderr, "%s at %d dpi [not found]\n", fontp->fontname,
  77.         (fontp->size + 2) / 5);
  78.         font_not_found = True;
  79.         return(False);
  80.     }
  81.     (*read_font_index)(fontp);
  82.     --n_fonts_left;
  83.     return(True);
  84. }
  85.  
  86. /*
  87.  *      define_font reads the rest of the fntdef command and then reads in
  88.  *      the specified pixel file, adding it to the global linked-list holding
  89.  *      all of the fonts used in the job.
  90.  */
  91. static
  92. define_font(cmnd)
  93.     ubyte cmnd;
  94. {
  95.         register struct font *fontp;
  96.     struct font **fontpp = old_fonts;
  97.     struct font *fontp1;
  98.     int len;
  99.     int design;
  100.     int unmodsize;
  101.     float realsize;
  102.     int size;
  103.  
  104.     fontp = (struct font *) malloc((unsigned) sizeof(struct font));
  105.     if (fontp == NULL)
  106.         oops("Can't allocate memory for font");
  107.     fontp->TeXnumber = num(dvi_file, (ubyte) cmnd - FNTDEF1 + 1);
  108.     (void) four(dvi_file);    /* checksum */
  109.     fontp->scale = four(dvi_file);
  110.     design = four(dvi_file);
  111.     len = one(dvi_file) + one(dvi_file);
  112.     fontp->fontname = malloc((unsigned) len + 1);
  113.     Fread(fontp->fontname, sizeof(char), len, dvi_file);
  114.     fontp->fontname[len] = '\0';
  115.     if(debug & DBG_PK)
  116.       Printf("Define font \"%s\" scale=%d design=%d\n",
  117.         fontp->fontname, fontp->scale, design);
  118. /*
  119.  *    In the actual implementation, scaled-size/design-size hasn't been
  120.  *    stored with sufficient precision, hence the messing around to find
  121.  *    its actual value.
  122.  */
  123.     realsize = (magnification/1000.)*((float) fontp->scale / design);
  124.     unmodsize = (realsize * 1000) + 0.5;
  125.     /* a real hack to correct for rounding in some cases */
  126.     switch (unmodsize) {
  127.         case 1095:
  128.         realsize = 1.095445;    /* stephalf */
  129.         break;
  130.         case 1315:
  131.         realsize = 1.314534;    /* stepihalf */
  132.         break;
  133.         case 2074:
  134.         realsize = 2.0736;    /* stepiv */
  135.         break;
  136.         case 2488:
  137.         realsize = 2.48832;    /* stepv */
  138.         break;
  139.         case 2986:
  140.         realsize = 2.985984;    /* stepiv */
  141.         break;
  142.     }
  143.     /*
  144.      * the remaining magnification steps are represented
  145.      * with sufficient accuracy already
  146.      */
  147.     fontp->size = size = (realsize * pixels_per_inch * 5) + 0.5;
  148.     fontp->scale = fontp->scale * fraction;
  149.     /*
  150.      * reuse font if possible
  151.      */
  152.     for (;;) {
  153.         fontp1 = *fontpp;
  154.         if (fontp1 == NULL) {
  155.         if (!define_new_font(fontp)) return;
  156.         break;
  157.         }
  158.         if (strcmp(fontp->fontname, fontp1->fontname) == 0
  159.             && size == fontp1->size) {
  160.         *fontpp = fontp1->next;
  161.         free(fontp->fontname);
  162.         free((char *) fontp);
  163.         fontp = fontp1;
  164.         if (list_fonts)
  165.             fputs("(reusing) ",stdout);
  166.         break;
  167.         }
  168.         fontpp = &fontp1->next;
  169.     }
  170.  
  171.     if (old_fonts == ¤t_font) old_fonts = &fontp->next;
  172.     fontp->next = current_font;
  173.     current_font = fontp;
  174.     if (list_fonts)
  175.         puts(fontp->fontname);
  176. }
  177.  
  178. /*
  179.  *      process_preamble reads the information in the preamble and stores
  180.  *      it into global variables for later use.
  181.  */
  182. static
  183. process_preamble()
  184. {
  185.         ubyte   k;
  186.  
  187.         if (one(dvi_file) != PRE)
  188.         dvi_oops("DVI file doesn't start with preamble");
  189.     if (one(dvi_file) != 2)
  190.         dvi_oops("Wrong version of DVI output for this program");
  191.     numerator     = four(dvi_file);
  192.     denominator   = four(dvi_file);
  193.     magnification = four(dvi_file);
  194.     fraction = (((double) numerator * magnification)
  195.                                      / ((double) denominator * 1000.));
  196.     fraction = fraction * (((long) pixels_per_inch)<<16) / 254000;
  197.     k = one(dvi_file);
  198.     Fread(job_id, sizeof(char), (int) k, dvi_file);
  199.     job_id[k] = '\0';
  200. }
  201.  
  202. /*
  203.  *      find_postamble locates the beginning of the postamble
  204.  *    and leaves the file ready to start reading at that location.
  205.  */
  206. static
  207. find_postamble()
  208. {
  209.     ubyte byte;
  210.     long offset = -4;        /* At least 4 TRAILERS */
  211.  
  212.     do {
  213.         offset -= 1;
  214.         Fseek(dvi_file, offset, 2);
  215.         byte = one(dvi_file);
  216.     } while (byte == TRAILER);
  217.     if (byte != 2)
  218.         dvi_oops("Wrong version of DVI output for this program");
  219.     offset -= 4;
  220.     Fseek(dvi_file, offset, 2);
  221.     Fseek(dvi_file, sfour(dvi_file), 0);
  222. }
  223.  
  224. /*
  225.  *      read_postamble reads the information in the postamble,
  226.  *    storing it into global variables.
  227.  *      It also takes care of reading in all of the pixel files for the fonts
  228.  *      used in the job.
  229.  */
  230. static
  231. read_postamble()
  232. {
  233.         ubyte   cmnd;
  234.  
  235.         if (one(dvi_file) != POST)
  236.         dvi_oops("Postamble doesn't begin with POST");
  237.     last_page_offset = four(dvi_file);
  238.     if (numerator != four(dvi_file)
  239.               ||  denominator != four(dvi_file)
  240.           ||  magnification != four(dvi_file))
  241.         dvi_oops("Postamble doesn't match preamble");
  242.     (void) four(dvi_file);    /* page height */
  243.     (void) four(dvi_file);    /* page width */
  244.     maxstack = two(dvi_file);
  245.     total_pages = two(dvi_file);
  246.     old_fonts = ¤t_font;
  247.     font_not_found = False;
  248.     do {
  249.         switch(cmnd = one(dvi_file)) {
  250.             case FNTDEF1:
  251.             case FNTDEF2:
  252.             case FNTDEF3:
  253.             case FNTDEF4:
  254.             define_font(cmnd);
  255.             break;
  256.         case POSTPOST:
  257.             break;
  258.         default:
  259.             dvi_oops("Non-fntdef command found in postamble");
  260.         }
  261.     } while (cmnd != POSTPOST);
  262.     if (font_not_found)
  263.         dvi_oops("Not all pixel files were found");
  264.     /*
  265.      * free up fonts no longer in use
  266.      */
  267.     {
  268.         struct font *fontp = *old_fonts;
  269.         struct font *fontp1;
  270.         register struct glyph *g;
  271.         *old_fonts = NULL;
  272.         while (fontp != NULL) {
  273.         if (fontp->file != NULL) {
  274.             Fclose(fontp->file);
  275.             ++n_fonts_left;
  276.         }
  277.         free(fontp->fontname);
  278.         free(fontp->filename);
  279.         for (g = &fontp->glyph[0]; g < &fontp->glyph[MAXCHARS]; ++g) {
  280.             if (g->bitmap.bits) free(g->bitmap.bits);
  281.             if (g->bitmap2.bits) free(g->bitmap2.bits);
  282.         }
  283.         fontp1 = fontp->next;
  284.         free((char *) fontp);
  285.         fontp = fontp1;
  286.         }
  287.     }
  288. }
  289.  
  290. static
  291. prepare_pages()
  292. {
  293.     int i;
  294.  
  295.         stack = (struct frame *)
  296.         malloc((unsigned) sizeof(struct frame) * (maxstack+1));
  297.         if (stack == NULL)
  298.         oops("Can't allocate stack space (%d frames)", maxstack);
  299.     page_offset = (long *) malloc((unsigned) total_pages * sizeof(long));
  300.         if (page_offset == NULL)
  301.         oops("Can't allocate page directory (%d pages)",
  302.             total_pages);
  303.     i = total_pages;
  304.     page_offset[--i] = last_page_offset;
  305.     Fseek(dvi_file, last_page_offset, 0);
  306.     /*
  307.      * Follow back pointers through pages in the DVI file,
  308.      * storing the offsets in the page_offset table.
  309.      */
  310.     while (i > 0) {
  311.         Fseek(dvi_file, (long) (1+4+(9*4)), 1);
  312.         Fseek(dvi_file, page_offset[--i] = four(dvi_file), 0);
  313.     }
  314. }
  315.  
  316. init_page()
  317. {
  318.     page_h = PAPER_HEIGHT;
  319.     page_w = PAPER_WIDTH;
  320. }
  321.  
  322. /*
  323.  *    init_dvi_file is the main subroutine for reading the startup information
  324.  *    from the dvi file.
  325.  */
  326. static
  327. init_dvi_file()
  328. {
  329.     (void) fstat(fileno(dvi_file), &fstatbuf);
  330.     dvi_time = fstatbuf.st_mtime;
  331.     process_preamble();
  332.     find_postamble();
  333.     read_postamble();
  334.     prepare_pages();
  335.     init_page();
  336.     if (current_page >= total_pages) current_page = total_pages - 1;
  337.     spec_warn = True;
  338. }
  339.  
  340. /**
  341.  **    open_dvi_file opens the dvi file and calls init_dvi_file() to
  342.  **    initialize it.
  343.  **/
  344.  
  345. open_dvi_file()
  346. {
  347.     char *errmsg;
  348.  
  349.     if ((dvi_file = fopen(dvi_name, OPEN_MODE)) == NULL) {
  350.         int n = strlen(dvi_name);
  351.         char *file = dvi_name;
  352.  
  353.         if (strcmp(dvi_name + n - sizeof(".dvi") + 1, ".dvi") == 0) {
  354.             perror(dvi_name);
  355.             exit(1);
  356.         }
  357.         dvi_name = malloc((unsigned) n + sizeof(".dvi"));
  358.         Sprintf(dvi_name, "%s.dvi", file);
  359.         if ((dvi_file = fopen(dvi_name, OPEN_MODE)) == NULL) {
  360.             perror(dvi_name);
  361.             exit(1);
  362.         }
  363.     }
  364.  
  365.     if (errmsg = (char *) setjmp(dvi_env)) oops(errmsg);
  366.     init_dvi_file();
  367. }
  368.  
  369. /**
  370.  **    Release all shrunken bitmaps for all fonts.
  371.  **/
  372.  
  373. reset_fonts()
  374. {
  375.         register struct font *f;
  376.     register struct glyph *g;
  377.  
  378.     for (f = current_font; f != NULL; f = f->next)
  379.         for (g = &f->glyph[0]; g < &f->glyph[MAXCHARS]; ++g)
  380.         if (g->bitmap2.bits) {
  381.             free(g->bitmap2.bits);
  382.             g->bitmap2.bits = NULL;
  383.         }
  384. }
  385.  
  386. /**
  387.  **    Check for changes in dvi file.
  388.  **/
  389.  
  390. Boolean
  391. check_dvi_file()
  392. {
  393.     if (dvi_file == NULL || fstat(fileno(dvi_file), &fstatbuf) != 0
  394.         || fstatbuf.st_mtime != dvi_time) {
  395.         if (dvi_file) Fclose(dvi_file);
  396.         free((char *) stack);
  397.         free((char *) page_offset);
  398.         dvi_file = fopen(dvi_name, OPEN_MODE);
  399.         if (dvi_file == NULL)
  400.             dvi_oops("Cannot reopen dvi file.");
  401.         if (list_fonts) putchar('\n');
  402.         init_dvi_file();
  403.         redraw_page();
  404.         return False;
  405.     }
  406.     return True;
  407. }
  408.