home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / unixtex-6.1b-src.tgz / tar.out / contrib / unixtex / xdvik / dvi_init.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  20KB  |  715 lines

  1. /*
  2.  * Copyright (c) 1994 Paul Vojta.  All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions
  6.  * are met:
  7.  * 1. Redistributions of source code must retain the above copyright
  8.  *    notice, this list of conditions and the following disclaimer.
  9.  * 2. Redistributions in binary form must reproduce the above copyright
  10.  *    notice, this list of conditions and the following disclaimer in the
  11.  *    documentation and/or other materials provided with the distribution.
  12.  *
  13.  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  14.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  15.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  16.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  17.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  18.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  19.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  20.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  21.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  22.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  23.  * SUCH DAMAGE.
  24.  *
  25.  * NOTE:
  26.  *    xdvi is based on prior work as noted in the modification history, below.
  27.  */
  28.  
  29. /*
  30.  * DVI previewer for X.
  31.  *
  32.  * Eric Cooper, CMU, September 1985.
  33.  *
  34.  * Code derived from dvi-imagen.c.
  35.  *
  36.  * Modification history:
  37.  * 1/1986    Modified for X.10    --Bob Scheifler, MIT LCS.
  38.  * 7/1988    Modified for X.11    --Mark Eichin, MIT
  39.  * 12/1988    Added 'R' option, toolkit, magnifying glass
  40.  *                    --Paul Vojta, UC Berkeley.
  41.  * 2/1989    Added tpic support    --Jeffrey Lee, U of Toronto
  42.  * 4/1989    Modified for System V    --Donald Richardson, Clarkson Univ.
  43.  * 3/1990    Added VMS support    --Scott Allendorf, U of Iowa
  44.  * 7/1990    Added reflection mode    --Michael Pak, Hebrew U of Jerusalem
  45.  * 1/1992    Added greyscale code    --Till Brychcy, Techn. Univ. Muenchen
  46.  *                      and Lee Hetherington, MIT
  47.  * 4/1994    Added DPS support, bounding box
  48.  *                    --Ricardo Telichevesky
  49.  *                      and Luis Miguel Silveira, MIT RLE.
  50.  */
  51.  
  52. #include "config.h"
  53. #include <kpathsea/c-fopen.h>
  54. #include <kpathsea/c-stat.h>
  55. #include <kpathsea/magstep.h>
  56. #include <kpathsea/tex-glyph.h>
  57. #include "dvi.h"
  58.  
  59. #define    PK_PRE        247
  60. #define    PK_ID        89
  61. #define    PK_MAGIC    (PK_PRE << 8) + PK_ID
  62. #define    GF_PRE        247
  63. #define    GF_ID        131
  64. #define    GF_MAGIC    (GF_PRE << 8) + GF_ID
  65. #define    VF_PRE        247
  66. #define    VF_ID_BYTE    202
  67. #define    VF_MAGIC    (VF_PRE << 8) + VF_ID_BYTE
  68.  
  69. #define    dvi_oops(str)    (dvi_oops_msg = (str), longjmp(dvi_env, 1))
  70.  
  71. static    struct stat fstatbuf;
  72.  
  73. static    Boolean    font_not_found;
  74.  
  75. /*
  76.  * DVI preamble and postamble information.
  77.  */
  78. static    char    job_id[300];
  79. static    long    numerator, denominator;
  80.  
  81. /*
  82.  * Offset in DVI file of last page, set in read_postamble().
  83.  */
  84. static    long    last_page_offset;
  85.  
  86.  
  87. /*
  88.  *    free_vf_chain frees the vf_chain structure.
  89.  */
  90.  
  91. static    void
  92. free_vf_chain(tnp)
  93.     struct tn *tnp;
  94. {
  95.     while (tnp != NULL) {
  96.         register struct tn *tnp1 = tnp->next;
  97.         free((char *) tnp);
  98.         tnp = tnp1;
  99.     }
  100. }
  101.  
  102.  
  103. /*
  104.  *    Release all shrunken bitmaps for all fonts.
  105.  */
  106.  
  107. void
  108. reset_fonts()
  109. {
  110.     register struct font *f;
  111.     register struct glyph *g;
  112.  
  113.     for (f = font_head; f != NULL; f = f->next)
  114.         if ((f->flags & FONT_LOADED) && !(f->flags & FONT_VIRTUAL))
  115.         for (g = f->glyph; g <= f->glyph + f->maxchar; ++g) {
  116.             if (g->bitmap2.bits) {
  117.             free(g->bitmap2.bits);
  118.             g->bitmap2.bits = NULL;
  119.             }
  120. #ifdef    GREY
  121.             if (g->pixmap2) {
  122.             XDestroyImage(g->image2);
  123.             g->pixmap2 = NULL;
  124.             }
  125. #endif
  126.         }
  127. }
  128.  
  129. /*
  130.  *    realloc_font allocates the font structure to contain (newsize + 1)
  131.  *    characters.
  132.  */
  133.  
  134. void
  135. realloc_font(fontp, newsize)
  136.     struct font    *fontp;
  137.     wide_ubyte    newsize;
  138. {
  139.     struct glyph *glyph;
  140.  
  141.     glyph = fontp->glyph = (struct glyph *) realloc((char *) fontp->glyph,
  142.         ((unsigned int) newsize + 1) * sizeof(struct glyph));
  143.     if (glyph == NULL) oops("! Cannot reallocate space for glyph array.");
  144.     if (newsize > fontp->maxchar)
  145.         bzero((char *) (glyph + fontp->maxchar + 1),
  146.         (int) (newsize - fontp->maxchar) * sizeof(struct glyph));
  147.     maxchar = fontp->maxchar = newsize;
  148. }
  149.  
  150.  
  151. /*
  152.  *    realloc_virtual_font does the same thing for virtual fonts.
  153.  */
  154.  
  155. void
  156. realloc_virtual_font(fontp, newsize)
  157.     struct font    *fontp;
  158.     wide_ubyte    newsize;
  159. {
  160.     struct macro *macro;
  161.  
  162.     macro = fontp->macro = (struct macro *) realloc((char *) fontp->macro,
  163.         ((unsigned int) newsize + 1) * sizeof(struct macro));
  164.     if (macro == NULL) oops("! Cannot reallocate space for macro array.");
  165.     if (newsize > fontp->maxchar)
  166.         bzero((char *) (macro + fontp->maxchar + 1),
  167.         (int) (newsize - fontp->maxchar) * sizeof(struct macro));
  168.     maxchar = fontp->maxchar = newsize;
  169. }
  170.  
  171.  
  172. /*
  173.  *    load_font locates the raster file and reads the index of characters,
  174.  *    plus whatever other preprocessing is done (depending on the format).
  175.  */
  176.  
  177. Boolean
  178. load_font(fontp)
  179.     struct font *fontp;
  180. {
  181.     double    fsize    = fontp->fsize;
  182.     int    dpi    = fsize + 0.5;
  183.     char    *font_found;
  184.     int    size_found;
  185.     int    magic;
  186.     Boolean    hushcs    = hush_chk;
  187.  
  188.     fontp->flags |= FONT_LOADED;
  189.     fontp->file = font_open(fontp->fontname, &font_found,
  190.         fsize, &size_found, fontp->magstepval, &fontp->filename);
  191.     if (fontp->file == NULL) {
  192.         Fprintf(stderr, "xdvi: Can't find font %s.\n", fontp->fontname);
  193.         return True;
  194.     }
  195.     --n_files_left;
  196.     if (font_found != NULL) {
  197.         Fprintf(stderr,
  198.             "xdvi: Can't find font %s; using %s instead at %d dpi.\n",
  199.             fontp->fontname, font_found, dpi);
  200.         free(fontp->fontname);
  201.         fontp->fontname = font_found;
  202.         hushcs = True;
  203.     }
  204.     else if (!kpse_bitmap_tolerance ((double) size_found, fsize))
  205.         Fprintf(stderr,
  206.         "xdvi: Can't find font %s at %d dpi; using %d dpi instead.\n",
  207.         fontp->fontname, dpi, size_found);
  208.     fontp->fsize = size_found;
  209.     fontp->timestamp = ++current_timestamp;
  210.     fontp->maxchar = maxchar = 255;
  211.     fontp->set_char_p = set_char;
  212.     magic = two(fontp->file);
  213. #ifdef    USE_PK
  214.     if (magic == PK_MAGIC) read_PK_index(fontp, WIDENINT hushcs);
  215.     else
  216. #endif
  217. #ifdef    USE_GF
  218.         if (magic == GF_MAGIC) read_GF_index(fontp, WIDENINT hushcs);
  219.     else
  220. #endif
  221.         if (magic == VF_MAGIC) read_VF_index(fontp, WIDENINT hushcs);
  222.     else
  223.         oops("Cannot recognize format for font file %s", fontp->filename);
  224.  
  225.     if (fontp->flags & FONT_VIRTUAL) {
  226.         while (maxchar > 0 && fontp->macro[maxchar].pos == NULL) --maxchar;
  227.         if (maxchar < 255)
  228.         realloc_virtual_font(fontp, WIDENINT maxchar);
  229.     }
  230.     else {
  231.         while (maxchar > 0 && fontp->glyph[maxchar].addr == 0) --maxchar;
  232.         if (maxchar < 255)
  233.         realloc_font(fontp, WIDENINT maxchar);
  234.     }
  235.     return False;
  236. }
  237.  
  238.  
  239. /*
  240.  *    MAGSTEPVALUE - If the given magnification is close to a \magstep
  241.  *    or a \magstephalf, then return twice the number of \magsteps.
  242.  *    Otherwise return NOMAGSTP.
  243.  */
  244.  
  245. #define    NOMAGSTP (-29999)
  246. #define    NOBUILD    29999
  247.  
  248. static    int
  249. magstepvalue(mag)
  250.     float    *mag;
  251. {
  252.   int m_ret;
  253.   unsigned dpi_ret =
  254.     kpse_magstep_fix ((unsigned) *mag, (unsigned) pixels_per_inch, &m_ret);
  255.   *mag = (float) dpi_ret; /* MAG is actually a dpi.  */
  256.   return m_ret ? m_ret : NOMAGSTP;
  257. }
  258.  
  259. /*
  260.  *    reuse_font recursively sets the flags for font structures being reused.
  261.  */
  262.  
  263. static    void
  264. reuse_font(fontp)
  265.     struct font *fontp;
  266. {
  267.     struct font **fp;
  268.     struct tn *tnp;
  269.  
  270.     if (fontp->flags & FONT_IN_USE) return;
  271.  
  272.     fontp->flags |= FONT_IN_USE;
  273.     if (list_fonts)
  274.         Printf("xdvi: (reusing) %s at %d dpi\n", fontp->fontname,
  275.         (int) (fontp->fsize + 0.5));
  276.     if (fontp->flags & FONT_VIRTUAL) {
  277.         for (fp = fontp->vf_table; fp < fontp->vf_table + VFTABLELEN; ++fp)
  278.         if (*fp != NULL) reuse_font(*fp);
  279.         for (tnp = fontp->vf_chain; tnp != NULL; tnp = tnp->next)
  280.         reuse_font(tnp->fontp);
  281.     }
  282. }
  283.  
  284.  
  285. /*
  286.  *      define_font reads the rest of the fntdef command and then reads in
  287.  *      the specified pixel file, adding it to the global linked-list holding
  288.  *      all of the fonts used in the job.
  289.  */
  290. struct font *
  291. define_font(file, cmnd, vfparent, tntable, tn_table_len, tn_headpp)
  292.     FILE        *file;
  293.     wide_ubyte    cmnd;
  294.     struct font    *vfparent;    /* vf parent of this font, or NULL */
  295.     struct font    **tntable;    /* table for low TeXnumbers */
  296.     unsigned int    tn_table_len;    /* length of table for TeXnumbers */
  297.     struct tn    **tn_headpp;    /* addr of head of list of TeXnumbers */
  298. {
  299.     int    TeXnumber;
  300.     struct font *fontp;
  301.     float    fsize;
  302.     double    scale_dimconv;
  303.     long    checksum;
  304.     int    scale;
  305.     int    design;
  306.     int    magstepval;
  307.     int    len;
  308.     char    *fontname;
  309.     int    size;
  310.  
  311.     TeXnumber = num(file, (int) cmnd - FNTDEF1 + 1);
  312.     checksum = four(file);
  313.     scale = four(file);
  314.     design = four(file);
  315.     len = one(file); len += one(file); /* sequence point in the middle */
  316.     fontname = xmalloc((unsigned) len + 1, "font name");
  317.     Fread(fontname, sizeof(char), len, file);
  318.     fontname[len] = '\0';
  319.     if(debug & DBG_PK)
  320.         Printf("xdvi: Define font \"%s\" scale=%d design=%d\n",
  321.         fontname, scale, design);
  322.     if (vfparent == NULL) {
  323.         fsize = 0.001 * scale / design * magnification * pixels_per_inch;
  324.         scale_dimconv = dimconv;
  325.     }
  326.     else {
  327.         /*
  328.          *    The scaled size is given in units of vfparent->scale * 2 ** -20
  329.          *    SPELL units, so we convert it into SPELL units by multiplying by
  330.          *        vfparent->dimconv.
  331.          *    The design size is given in units of 2 ** -20 pt, so we convert
  332.          *    into SPELL units by multiplying by
  333.          *        (pixels_per_inch * 2**16) / (72.27 * 2**20).
  334.          */
  335.         fsize = (72.27 * (1<<4)) * vfparent->dimconv * scale / design;
  336.         scale_dimconv = vfparent->dimconv;
  337.     }
  338.     magstepval = magstepvalue(&fsize);
  339.     size = fsize + 0.5;
  340.     /*
  341.      * reuse font if possible
  342.      */
  343.     for (fontp = font_head;; fontp = fontp->next) {
  344.         if (fontp == NULL) {        /* if font doesn't exist yet */
  345.         if (list_fonts)
  346.             Printf("xdvi: %s at %d dpi\n", fontname, (int) (fsize + 0.5));
  347.         fontp = (struct font *) xmalloc((unsigned) sizeof(struct font),
  348.             "font structure");
  349.         fontp->fontname = fontname;
  350.         fontp->fsize = fsize;
  351.         fontp->checksum = checksum;
  352.         fontp->magstepval = magstepval;
  353.         fontp->flags = FONT_IN_USE;
  354.         fontp->dimconv = scale * scale_dimconv / (1<<20);
  355.         fontp->set_char_p = load_n_set_char;
  356.         /* With virtual fonts, we might be opening another font
  357.            (pncb.vf), instead of what we just allocated for
  358.            (rpncb), thus leaving garbage in the structure for
  359.            when close_a_file comes along looking for something.  */
  360.         fontp->file = NULL; 
  361.         fontp->filename = NULL;
  362.         if (vfparent == NULL) font_not_found |= load_font(fontp);
  363.         fontp->next = font_head;
  364.         font_head = fontp;
  365.         break;
  366.         }
  367.         if (strcmp(fontname, fontp->fontname) == 0
  368.             && size == (int) (fontp->fsize + 0.5)) {
  369.             /* if font already in use */
  370.         reuse_font(fontp);
  371.         free(fontname);
  372.         break;
  373.         }
  374.     }
  375.     if (TeXnumber < tn_table_len)
  376.         tntable[TeXnumber] = fontp;
  377.     else {
  378.         register struct tn *tnp;
  379.         tnp = (struct tn *) xmalloc((unsigned) sizeof(struct tn),
  380.         "TeXnumber structure");
  381.         tnp->next = *tn_headpp;
  382.         *tn_headpp = tnp;
  383.         tnp->TeXnumber = TeXnumber;
  384.         tnp->fontp = fontp;
  385.     }
  386.     return fontp;
  387. }
  388.  
  389.  
  390. /*
  391.  *      process_preamble reads the information in the preamble and stores
  392.  *      it into global variables for later use.
  393.  */
  394. static    void
  395. process_preamble()
  396. {
  397.     ubyte   k;
  398.  
  399.     if (one(dvi_file) != PRE)
  400.         dvi_oops("DVI file doesn't start with preamble");
  401.     if (one(dvi_file) != 2)
  402.         dvi_oops("Wrong version of DVI output for this program");
  403.     numerator     = four(dvi_file);
  404.     denominator   = four(dvi_file);
  405.     magnification = four(dvi_file);
  406.     dimconv = (((double) numerator * magnification)
  407.         / ((double) denominator * 1000.));
  408.     dimconv = dimconv * (((long) pixels_per_inch)<<16) / 254000;
  409.     tpic_conv = pixels_per_inch * magnification / 1000000.0;
  410.     k = one(dvi_file);
  411.     Fread(job_id, sizeof(char), (int) k, dvi_file);
  412.     job_id[k] = '\0';
  413. }
  414.  
  415. /*
  416.  *      find_postamble locates the beginning of the postamble
  417.  *    and leaves the file ready to start reading at that location.
  418.  */
  419. #define    TMPSIZ    516    /* 4 trailer bytes + 512 junk bytes allowed */
  420. static    void
  421. find_postamble()
  422. {
  423.     long    pos;
  424.     ubyte    temp[TMPSIZ];
  425.     ubyte    *p;
  426.     ubyte    *p1;
  427.     ubyte    byte;
  428.  
  429.     Fseek(dvi_file, (long) 0, 2);
  430.     pos = ftell(dvi_file) - TMPSIZ;
  431.     if (pos < 0) pos = 0;
  432.     Fseek(dvi_file, pos, 0);
  433.     p = temp + fread((char *) temp, sizeof(char), TMPSIZ, dvi_file);
  434.     for (;;) {
  435.         p1 = p;
  436.         while (p1 > temp && *(--p1) != TRAILER) ;
  437.         p = p1;
  438.         while (p > temp && *(--p) == TRAILER) ;
  439.         if (p <= p1 - 4) break;    /* found 4 TRAILER bytes */
  440.         if (p <= temp) dvi_oops("DVI file corrupted");
  441.     }
  442.     pos += p - temp;
  443.     byte = *p;
  444.     while (byte == TRAILER) {
  445.         Fseek(dvi_file, --pos, 0);
  446.         byte = one(dvi_file);
  447.     }
  448.     if (byte != 2)
  449.         dvi_oops("Wrong version of DVI output for this program");
  450.     Fseek(dvi_file, pos - 4, 0);
  451.     Fseek(dvi_file, sfour(dvi_file), 0);
  452. }
  453.  
  454.  
  455. /*
  456.  *      read_postamble reads the information in the postamble,
  457.  *    storing it into global variables.
  458.  *      It also takes care of reading in all of the pixel files for the fonts
  459.  *      used in the job.
  460.  */
  461. static    void
  462. read_postamble()
  463. {
  464.     ubyte   cmnd;
  465.     struct font    *fontp;
  466.     struct font    **fontpp;
  467.  
  468.     if (one(dvi_file) != POST)
  469.         dvi_oops("Postamble doesn't begin with POST");
  470.     last_page_offset = four(dvi_file);
  471.     if (numerator != four(dvi_file)
  472.         || denominator != four(dvi_file)
  473.         || magnification != four(dvi_file))
  474.         dvi_oops("Postamble doesn't match preamble");
  475.         /* read largest box height and width */
  476.     unshrunk_page_h = (spell_conv(sfour(dvi_file)) >> 16) + offset_y;
  477.     if (unshrunk_page_h < unshrunk_paper_h)
  478.         unshrunk_page_h = unshrunk_paper_h;
  479.     unshrunk_page_w = (spell_conv(sfour(dvi_file)) >> 16) + offset_x;
  480.     if (unshrunk_page_w < unshrunk_paper_w)
  481.         unshrunk_page_w = unshrunk_paper_w;
  482.     (void) two(dvi_file);    /* max stack size */
  483.     total_pages = two(dvi_file);
  484.     font_not_found = False;
  485.     while ((cmnd = one(dvi_file)) >= FNTDEF1 && cmnd <= FNTDEF4)
  486.         (void) define_font(dvi_file, cmnd, (struct font *) NULL,
  487.         tn_table, TNTABLELEN, &tn_head);
  488.     if (cmnd != POSTPOST)
  489.         dvi_oops("Non-fntdef command found in postamble");
  490.     if (font_not_found)
  491.         dvi_oops("Not all pixel files were found");
  492.     /*
  493.      * free up fonts no longer in use
  494.      */
  495.     fontpp = &font_head;
  496.     while ((fontp = *fontpp) != NULL)
  497.         if (fontp->flags & FONT_IN_USE)
  498.         fontpp = &fontp->next;
  499.         else {
  500.         if (debug & DBG_PK)
  501.             Printf("xdvi: Discarding font \"%s\" at %d dpi\n",
  502.             fontp->fontname, (int) (fontp->fsize + 0.5));
  503.         *fontpp = fontp->next;        /* remove from list */
  504.         free(fontp->fontname);
  505.         if (fontp->flags & FONT_LOADED) {
  506.             if (fontp->file != NULL) {
  507.             Fclose(fontp->file);
  508.             ++n_files_left;
  509.             }
  510.             free(fontp->filename);
  511.             if (fontp->flags & FONT_VIRTUAL) {
  512.             register struct macro *m;
  513.  
  514.             for (m = fontp->macro;
  515.                 m <= fontp->macro + fontp->maxchar; ++m)
  516.                 if (m->free_me) free((char *) m->pos);
  517.             free((char *) fontp->macro);
  518.             free((char *) fontp->vf_table);
  519.             free_vf_chain(fontp->vf_chain);
  520.             }
  521.             else {
  522.             register struct glyph *g;
  523.  
  524.             for (g = fontp->glyph;
  525.                 g <= fontp->glyph + fontp->maxchar; ++g) {
  526.                 if (g->bitmap.bits != NULL) free(g->bitmap.bits);
  527.                 if (g->bitmap2.bits != NULL) free(g->bitmap2.bits);
  528. #ifdef    GREY
  529.                 if (g->pixmap2 != NULL) XDestroyImage(g->image2);
  530. #endif
  531.             }
  532.             free((char *) fontp->glyph);
  533.             }
  534.             free((char *) fontp);
  535.         }
  536.         }
  537. }
  538.  
  539. static    void
  540. prepare_pages()
  541. {
  542.     int i;
  543.  
  544.     page_offset = (long *) xmalloc((unsigned) total_pages * sizeof(long),
  545.         "page directory");
  546.     i = total_pages;
  547.     page_offset[--i] = last_page_offset;
  548.     Fseek(dvi_file, last_page_offset, 0);
  549.     /*
  550.      * Follow back pointers through pages in the DVI file,
  551.      * storing the offsets in the page_offset table.
  552.      */
  553.     while (i > 0) {
  554.         Fseek(dvi_file, (long) (1+4+(9*4)), 1);
  555.         Fseek(dvi_file, page_offset[--i] = four(dvi_file), 0);
  556.     }
  557. }
  558.  
  559. void
  560. init_page()
  561. {
  562.     page_w = ROUNDUP(unshrunk_page_w, mane.shrinkfactor) + 2;
  563.     page_h = ROUNDUP(unshrunk_page_h, mane.shrinkfactor) + 2;
  564. }
  565.  
  566. #ifndef    S_ISDIR
  567. #define    S_ISDIR(m)    (((m) & S_IFMT) == S_IFDIR)
  568. #endif
  569.  
  570. /*
  571.  *    init_dvi_file is the main subroutine for reading the startup
  572.  *    information from the dvi file.  Returns True on success.
  573.  */
  574.  
  575. static    Boolean
  576. init_dvi_file()
  577. {
  578.     (void) fstat(fileno(dvi_file), &fstatbuf);
  579.     if (S_ISDIR(fstatbuf.st_mode))
  580.         return False;
  581.     dvi_time = fstatbuf.st_mtime;
  582.     process_preamble();
  583.     find_postamble();
  584.     read_postamble();
  585.     prepare_pages();
  586.     init_page();
  587.     if (current_page >= total_pages) current_page = total_pages - 1;
  588.     hush_spec_now = hush_spec;
  589.     return True;
  590. }
  591.  
  592. /**
  593.  **    open_dvi_file opens the dvi file and calls init_dvi_file() to
  594.  **    initialize it.
  595.  **/
  596.  
  597. void
  598. open_dvi_file()
  599. {
  600.     int    n;
  601.     char    *file;
  602.  
  603.     if (setjmp(dvi_env)) oops(dvi_oops_msg);
  604.  
  605.     n = strlen(dvi_name);
  606.     file = dvi_name;
  607.  
  608.         /* Try foo.dvi before foo, for the sake of an executable foo
  609.            with documentation foo.tex.  Unless we already have `.dvi'.  */
  610.     if (strcmp(dvi_name + n - sizeof(".dvi") + 1, ".dvi") != 0) {
  611.             dvi_name = xmalloc((unsigned) n + sizeof(".dvi"), "dvi file name");
  612.             Sprintf(dvi_name, "%s.dvi", file);
  613.             dvi_file = fopen(dvi_name, OPEN_MODE);
  614.             if (dvi_file != NULL && init_dvi_file())
  615.                 return;
  616.             free (dvi_name);
  617.             dvi_name = file;
  618.     }
  619.  
  620.         /* Then try `foo', in case the user likes DVI files without `.dvi'.  */
  621.     if ((dvi_file = fopen(dvi_name, OPEN_MODE)) == NULL
  622.         || !init_dvi_file()) {
  623.         perror(dvi_name);
  624.         exit(1);
  625.     }
  626. }
  627.  
  628. #ifdef SELFILE
  629. /* Allow the user to choose a new dvi file, by popping up a dialog box
  630.    which allows the graphical selection of the correct filename,
  631.    maybe we should only allow files ending in .dvi to be selected.  */
  632.  
  633. FILE *
  634. select_filename(open, move_home)
  635.     int open, move_home ;
  636. {
  637.   extern FILE *XsraSelFile();
  638.   FILE *dummy_file ;
  639.   static char *dummy_name ;
  640.  
  641.   dummy_file = XsraSelFile(top_level, "Select a dvi file: ",
  642.                "Ok", "Cancel",
  643.                "Can't open file: ", NULL,
  644.                OPEN_MODE, NULL, &dummy_name) ;
  645.   if (dummy_file != NULL) {
  646.     extern void set_icon_and_title (); /* from xdvi.c */
  647.     extern void home (); /* from events.c */
  648.     
  649.     /* we may not want the file they returned... */
  650.     if (!open)
  651.       fclose (dummy_file) ;
  652.  
  653.     /* The name is what we really want, so use it.  */
  654.     dvi_name = dummy_name ;
  655.     current_page = 0 ;  /* go to start of new dvi file */
  656.     if (move_home)
  657.       home(False);      /* Move to home position on new first page */
  658.     
  659.     /* We do this elsewhere if we don't open the file.  */
  660.     if (open)
  661.       set_icon_and_title (dvi_name);
  662.  
  663.   } else if (open) { /* User cancelled, so open old file */
  664.     dummy_file = fopen(dvi_name, OPEN_MODE);
  665.     --dvi_time;
  666.   }
  667.  
  668.   return dummy_file ;
  669. }
  670. #endif  /* SELFILE */
  671.  
  672. /**
  673.  **    Check for changes in dvi file.
  674.  **/
  675.  
  676. Boolean
  677. check_dvi_file()
  678. {
  679.     struct font *fontp;
  680.  
  681.     if (dvi_file == NULL || fstat(fileno(dvi_file), &fstatbuf) != 0
  682.         || fstatbuf.st_mtime != dvi_time) {
  683.         if (dvi_file) {
  684.             Fclose(dvi_file);
  685.             dvi_file = NULL;
  686.             if (list_fonts) Putchar('\n');
  687.         }
  688.         if (page_offset) {
  689.           /* With SELFILE, we are called once before the file
  690.              selection, and then once recursively (below).  Thus
  691.              we would free a freed pointer.  */
  692.                   free((char *) page_offset);
  693.                   page_offset = NULL;
  694.                   bzero((char *) tn_table, (int) sizeof(tn_table));
  695.                   free_vf_chain(tn_head);
  696.                   tn_head = NULL;
  697.                   for (fontp = font_head; fontp != NULL; fontp = fontp->next)
  698.                       fontp->flags &= ~FONT_IN_USE;
  699.         }
  700. #ifdef SELFILE
  701.         if (dvi_time > fstatbuf.st_mtime) /* choose a new file */
  702.           dvi_file = select_filename(True, True) ;
  703.         else
  704. #endif  /* SELFILE */
  705.         dvi_file = fopen(dvi_name, OPEN_MODE);
  706.         if (dvi_file == NULL
  707.             || !init_dvi_file())
  708.             dvi_oops("Cannot reopen dvi file.");
  709.         reconfig();
  710.         redraw_page();
  711.         return False;
  712.     }
  713.     return True;
  714. }
  715.