home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / s / stex2-18.zip / SeeTeX / Xtex / dvi-simple.c < prev    next >
C/C++ Source or Header  |  1992-06-21  |  14KB  |  591 lines

  1. /*
  2.  * Copyright 1989 Dirk Grunwald
  3.  * 
  4.  * Permission to use, copy, modify, distribute, and sell this software
  5.  * and its documentation for any purpose is hereby granted without fee,
  6.  * provided that the above copyright notice appear in all copies and that
  7.  * both that copyright notice and this permission notice appear in
  8.  * supporting documentation, and that the name of Dirk Grunwald or M.I.T.
  9.  * not be used in advertising or publicity pertaining to distribution of
  10.  * the software without specific, written prior permission.  Dirk
  11.  * Grunwald and M.I.T. makes no representations about the suitability of
  12.  * this software for any purpose.  It is provided "as is" without express
  13.  * or implied warranty.
  14.  * 
  15.  * DIRK GRUNWALD AND M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
  16.  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17.  * FITNESS, IN NO EVENT SHALL M.I.T.  BE LIABLE FOR ANY SPECIAL, INDIRECT
  18.  * OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  19.  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  20.  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  21.  * OR PERFORMANCE OF THIS SOFTWARE.
  22.  * 
  23.  * Author:
  24.  *     Dr. Dirk Grunwald
  25.  *     Dept. of Computer Science
  26.  *     Campus Box 430
  27.  *     Univ. of Colorado, Boulder
  28.  *     Boulder, CO 80309
  29.  * 
  30.  *     grunwald@colorado.edu
  31.  *     
  32.  */ 
  33.  
  34. #include <stdio.h>
  35. #include "dvi-simple.h"
  36. #include "libtex/conv.h"
  37. #include <assert.h>
  38. #ifdef hpux
  39. #include <sys/types.h>
  40. #endif
  41. #include <sys/file.h>
  42. #include "xtex.h"
  43.  
  44. #ifndef TRUE
  45. #define TRUE 1
  46. #endif
  47.  
  48. #ifndef FALSE
  49. #define FALSE 0
  50. #endif
  51.  
  52. #ifdef __STDC__
  53.   extern void bzero(char *, int);
  54.   extern char* malloc(int);
  55.   extern void free(char *);
  56.   extern char *getenv(char *);
  57.   extern char
  58.     *strcpy( char *__s1, const char *__s2 ),
  59.     *strncpy( char *__s1, const char *__s2, size_t __n ),
  60.     *strcat( char *__s1, const char *__s2 );    
  61.   extern FILE *    fopen( const char *__filename, const char *__type );
  62. #else
  63.   extern void bzero();
  64.   extern char* malloc();
  65.   extern void free();
  66.   extern char *getenv();
  67.   extern FILE *fopen();
  68. #endif
  69.  
  70. struct PostAmbleInfo ThePostAmbleInfo;
  71.  
  72. int RegisteredFonts = 0;
  73.  
  74. #define MAX_GLYPHS 256
  75. DviFontInfo TheFontInfo[ MAX_POSTAMBLE_FONTS ];
  76.  
  77. long dviPageOffsets;
  78.  
  79. static long Magnification;
  80. /*static long    Numerator;        /* numerator from DVI file */
  81. /*static long    Denominator;        /* denominator from DVI file */
  82. long    Numerator;        /* numerator from DVI file */
  83. long    Denominator;        /* denominator from DVI file */
  84. double  dvi_per_inch;
  85.  
  86. char *ScaleUnitsString[] =
  87. { "pt", "pc", "in", "bp", "cm", "mm", "dd", "cc", "sp", 0};
  88.  
  89. double ScaleUnitsDen[]
  90.   = {1,  12, 7227, 7227, 7227, 7227, 1238, 14586,   1};
  91.  
  92. double ScaleUnitsNum[]
  93.   = {1,   1,  100, 7200,  254, 2540, 1157, 1157,  65536};
  94.  
  95. double ScaleUnitsInSp[10];
  96.  
  97.  
  98. long    *DviCount[DVI_COUNT];
  99. long    *DviPageOffsets = 0;
  100.  
  101. int    DviHHMargin = -1;    /* horizontal margin (in DEVs) */
  102. int    DviVVMargin = -1;    /* vertical margin (in DEVs) */
  103. int    DviTallestPage = -1;
  104. int    DviWidestPage = -1 ;
  105. int    DviCurrentPage = -1;
  106. int    DviTotalPages = -1;
  107. int    DviDpi = -1;
  108. int    DviMaxDrift = -1;
  109. int    DviUserMag = -1;    /* user-specified magnification */
  110. int    DviBlackness = -1;
  111. FILE    *DviFile;
  112. long    DviFileSize;
  113.  
  114. char    *DVIFileName;
  115.  
  116. static Conv PrivateConv;
  117.  
  118. extern int errno;
  119.  
  120. static int anError;
  121.  
  122. static void savePostAmblePointer(p)
  123. struct PostAmbleInfo *p;
  124. {
  125.   int i;
  126.   int page;
  127.   int pageSize;
  128.   int stackSize;
  129.   long prevPagePointer;
  130.   long wuzAt;
  131.  
  132.   double dScale;
  133.  
  134.   ThePostAmbleInfo = *p;
  135.  
  136.   Numerator = p->pai_Numerator;
  137.   Denominator = p->pai_Denominator;
  138.   Magnification = p->pai_DVIMag;
  139.   
  140.  
  141.   /* define table to convert internal DVI units to physical measures.
  142.      We have a conversion to points. We know there are 7227 pts per
  143.      2.54 M. dScale converts to 10^-7 meters.
  144.      */
  145.  
  146.   dScale =((double) Denominator)/((double) Numerator);
  147.  
  148.   for ( i = 0; ScaleUnitsString[i]; i++ ) {
  149.     double top = ScaleUnitsDen[i] * 25400000;
  150.     double bot = ScaleUnitsNum[i] * 7227;
  151.     ScaleUnitsInSp[i] = (top * dScale) / bot;
  152.   }
  153.   dvi_per_inch = dScale * 254000.0;
  154.  
  155.   /*
  156.    *    Set the conversion factor.  This must be done before using
  157.    *    any fonts or the fromSP routine.
  158.    */
  159.   
  160.   CSetConversion(&PrivateConv,
  161.          DviDpi, DviUserMag, Numerator, Denominator, Magnification);
  162.   
  163.   DviTotalPages = p -> pai_NumberOfPages;
  164.   DviWidestPage = cfromSP(&PrivateConv, p -> pai_WidestPageWidth);
  165.   DviTallestPage = cfromSP(&PrivateConv, p -> pai_TallestPageHeight);
  166.  
  167.   /*
  168.    *    Set of the table of pointers to pages and room for the
  169.    *    count variables.
  170.    */
  171.   
  172.   pageSize = DviTotalPages * sizeof(long);
  173.   if (DviPageOffsets != 0) {
  174.     free( (char *) DviPageOffsets);
  175.     DviPageOffsets = 0;
  176.   }
  177.   DviPageOffsets = (long *) malloc(pageSize);
  178.   
  179.   if (DviPageOffsets == NULL) {
  180.     error(1,0,"Can not allocate page directory (%d pages)", DviTotalPages);
  181.     exit(1);
  182.   }
  183.   
  184.   for (i = 0; i < DVI_COUNT; i++) {
  185.     if (DviCount[i] != 0) {
  186.       free( (char *) DviCount[i]);
  187.       DviCount[i] = 0;
  188.     }
  189.     DviCount[i] = (long *) malloc(pageSize);
  190.     if (DviCount[i] == NULL) {
  191.       error(1,0,"Can not allocate count directory (%d pages)", DviTotalPages);
  192.       exit(1);
  193.     }
  194.   }
  195.   
  196.   /*
  197.    * Follow back pointers through pages in the DVI file,
  198.    * storing the offsets in the DviPageOffsets table.
  199.    */
  200.   
  201.   prevPagePointer = p->pai_PrevPagePointer;
  202.   wuzAt = (long) ftell(DviFile);
  203.  
  204.   fseek(DviFile, 0L, 2);
  205.   DviFileSize = ftell(DviFile);
  206.   
  207.   for (page = DviTotalPages - 1; page >= 0 ; page--) {
  208.     
  209.     /*
  210.      *    Skip to previous page, but skip over BOP marker.
  211.      */
  212.     DviPageOffsets[page] = prevPagePointer;
  213.  
  214.     if( fseek(DviFile, prevPagePointer+1, 0) < 0) {
  215.       error(1, errno, "Improper seek looking up pages\n");
  216.       anError |= 1;
  217.       return;
  218.     }
  219.     
  220.     /*
  221.      *    Read the other counters at the beginning of the page
  222.      */
  223.     
  224.     for (i = 0; i < DVI_COUNT; i++) {
  225.       long value;
  226.       fGetLong(DviFile, value);
  227.       DviCount[i][page] = value;
  228.     }
  229.     fGetLong(DviFile, prevPagePointer);
  230.   }
  231.   fseek(DviFile, wuzAt, 0);
  232. }
  233.  
  234. static char *EnvFontPath;
  235.  
  236. static FILE *openTfmFile(name)
  237. char *name;
  238. {
  239.   char *usePath;
  240.   char path[1024];
  241.   FILE *foo;
  242.  
  243.   if ( EnvFontPath == 0 ) {
  244.     int len;
  245.     EnvFontPath = getenv("TEXFONTS");
  246.     if (EnvFontPath != 0) {
  247.     len = strlen(EnvFontPath);
  248.     if (EnvFontPath[0] == ':') {    /* prepend system path */
  249.         char *tmp = malloc(len + strlen(xtexResources.tfmPath) + 1);
  250.         strcpy(tmp,xtexResources.tfmPath);
  251.         strcat(tmp,EnvFontPath);
  252.         EnvFontPath = tmp;
  253.     } else if (EnvFontPath[len-1] == ':') {    /* append system path */
  254.         char *tmp = malloc(len + strlen(xtexResources.tfmPath) + 1);
  255.         strcpy(tmp,EnvFontPath);
  256.         strcat(tmp,xtexResources.tfmPath);
  257.         EnvFontPath = tmp;
  258.     }
  259.     }
  260.   }
  261.  
  262.   usePath = (EnvFontPath == 0) ? xtexResources.tfmPath : EnvFontPath;
  263.  
  264.   for (;;) {
  265.     char *p = path;
  266.  
  267.     if ( usePath == 0 || *usePath == 0 ) {
  268.       return( 0 );
  269.     }
  270.  
  271.     *p = 0;
  272.  
  273.     while ( *usePath && *usePath != ':' ) {
  274.       *(p++) = *(usePath++);
  275.     }
  276.  
  277.     /* append name */
  278.  
  279.     *(p++) = '/';
  280.     strcpy(p, name);
  281.     strcat(p, ".tfm");
  282.  
  283.     if ( (foo = fopen( path, "r")) != 0 ) {
  284.       return( foo );
  285.     }
  286.  
  287.     if ( *usePath == ':' ) {
  288.       usePath++;
  289.     }
  290.   }
  291. }
  292.  
  293. static void
  294. registerFont(f)
  295. struct PostAmbleFont *f;
  296. {
  297.   int thisFont;
  298.   FILE *tfmFile;
  299.   char *fontName[1024];
  300.  
  301.   assert( RegisteredFonts < MAX_POSTAMBLE_FONTS );
  302.  
  303.   thisFont = RegisteredFonts++;
  304. /* Attempt to locate the TFM files */
  305.  
  306.   tfmFile = openTfmFile( f -> paf_name );
  307.   if ( tfmFile == 0 ) {
  308.     error(0,0,"Can't find TFM file for %s", f -> paf_name);
  309.     anError = 1;
  310.   }
  311.   else {
  312.     struct tfmdata t;
  313.     i32 pspace;
  314.     int len;
  315.  
  316.     TheFontInfo[ thisFont ].paf = *f;
  317.  
  318.     /* make a copy of the name */
  319.  
  320.     len = strlen( f -> paf_name );
  321.     TheFontInfo[ thisFont ].paf.paf_name
  322.       = malloc( sizeof(char) * (len + 1 ));
  323.     strncpy( TheFontInfo[ thisFont ].paf.paf_name, f -> paf_name, len+1);
  324.  
  325.     pspace = f -> paf_DVIMag / 6;    /* a three-unit "thin space" */
  326.  
  327.     TheFontInfo[ thisFont ].pspace = pspace;
  328.     TheFontInfo[ thisFont ].nspace = -4 * pspace;
  329.     TheFontInfo[ thisFont ].vspace = 5 * pspace;
  330.  
  331.     bzero((char *) &t, sizeof(t));
  332.  
  333.     if ( readtfmfile( tfmFile, &t, TRUE ) != 0 ) {
  334.       error(0,0,"Bogus TFM file: %s", f -> paf_name);
  335.     }
  336.     else {
  337.       int i;
  338.       int nc = t.t_hdr.th_ec - t.t_hdr.th_bc + 1;
  339.       int nw;
  340.       int *p;
  341.       int s;    /* see dvitype */
  342.       int d;
  343.  
  344.       if ( TheFontInfo[ thisFont ].widths == 0 ) {
  345.      TheFontInfo[ thisFont ].widths =
  346.        (int *) malloc( sizeof(int) *  MAX_GLYPHS );
  347.       }
  348.  
  349.       /* convert widths */
  350.       assert( t.t_width[0] == 0 );
  351.       nw = t.t_hdr.th_nw;
  352.       s = TheFontInfo[ thisFont ].paf.paf_DVIMag;
  353.       d = TheFontInfo[ thisFont ].paf.paf_DVIDesignSize;
  354.  
  355.       for (i = 0; i < nw; i++) {
  356.  
  357.     int width = t.t_width[i];
  358.  
  359.     if (width != 0) {
  360.       width = ScaleOneWidth(width, s);
  361.     }
  362.     t.t_width[i] = width;
  363.     
  364.       }
  365.  
  366.       p = TheFontInfo[ thisFont ].widths;
  367.       bzero( (char *) p , sizeof(int) * MAX_GLYPHS );
  368.  
  369.       p += t.t_hdr.th_bc;
  370.  
  371.       for (i = 0; i < nc; i++) {
  372.     int wi = t.t_ci[i].ci_width;
  373.     *(p++) = t.t_width[wi];
  374.       }
  375.     }
  376.  
  377.     if (t.t_ci != NULL) free( (char *)t.t_ci );
  378.     if (t.t_width != NULL) free( (char *)t.t_width );
  379.     if (t.t_height != NULL) free( (char *)t.t_height );
  380.     if (t.t_depth != NULL) free( (char *)t.t_depth );
  381. /*    if (t.t_ct != NULL) free( (char *)t.t_ct ); */
  382.  
  383.     fclose(tfmFile);
  384.   }
  385. }
  386.  
  387. /*
  388.  *    Returns TRUE if everything is fine
  389.  */
  390.  
  391. int
  392. DviInit( dviFileName, copy )
  393. char *dviFileName;
  394. int copy;
  395. {
  396.     extern char *ProgName;
  397.     FILE *dviFile;
  398.     char *mktemp();
  399.  
  400.     anError = 0;
  401.  
  402.     DviFini();    /* clean up the old files */
  403.     
  404.     DviFile = 0;
  405.  
  406.     if (dviFileName == 0) {
  407.     dviFile = stdin;
  408.     dviFileName = "<stdin>";
  409.     copy = 1;
  410.     }
  411.     else if ((dviFile = fopen(dviFileName, "r")) == NULL) {
  412.  
  413.     int n = strlen(dviFileName);
  414.     char *dviName;
  415.     
  416.     if (strcmp(dviFileName + n - sizeof(".dvi") + 1, ".dvi") == 0) {
  417.       DviFini();
  418.       error(0, errno, "[fopen] can't open %s", dviFileName);
  419.       return(1);
  420.     }
  421.  
  422.     dviName = (char *) malloc((unsigned) n + sizeof(".dvi") + 1);
  423.     sprintf(dviName, "%s.dvi", dviFileName);
  424.  
  425.     if ((dviFile = fopen(dviName, "r")) == NULL) {
  426.       DviFini();
  427.       error(0, errno, "[fopen] can't open %s", dviName);
  428.       return(1);
  429.     }
  430.     dviFileName = dviName;
  431.     }
  432.  
  433.     DVIFileName = dviFileName;
  434.  
  435.     if ( copy ) {
  436.       
  437.       /*
  438.        *    Copy the file to a temporary location if requested.
  439.        *    This lets the person peruse the file while theyre re-texing it.
  440.        */
  441.       FILE *tmpFile;
  442.       char dviTmpFileNameBuffer[256];
  443.       char *dviTmpFileName;
  444.       
  445.       sprintf(dviTmpFileNameBuffer,"/tmp/Dvistuff.XXXXXX");
  446.       
  447.       dviTmpFileName = mktemp(dviTmpFileNameBuffer);
  448.       
  449.       if (!(tmpFile = fopen(dviTmpFileName,"w+"))) {
  450.     error(0, errno, "[fopen] Unable to create temporary file");
  451.     dviTmpFileName = 0;
  452.       }
  453.       else {
  454.     char buffer[BUFSIZ];
  455.     int b;
  456.     
  457.     rewind(dviFile);
  458.     do {
  459.       b = fread(buffer, 1, BUFSIZ, dviFile);
  460.       fwrite(buffer, 1, b, tmpFile);
  461.     } while (! feof(dviFile));
  462.     
  463.     fclose(dviFile);
  464.     dviFile = tmpFile;
  465.     rewind(dviFile);
  466.     
  467.     /*
  468.      *    Unlink the temporary file. This keeps tmp files from cluttering
  469.      *    up /tmp and it does it in a very application-independent way.
  470.      *    You can't reopen the tmp file, but we don't really allow that
  471.      *    anyway (the tmp file is hidden from the user).
  472.      */
  473.     
  474.     if (dviTmpFileName != 0 &&
  475.         strncmp(dviTmpFileName,"/tmp/",5) == 0) {
  476.       unlink(dviTmpFileName);
  477.     }
  478.       }
  479.     }
  480.  
  481.     assert( dviFile != 0 );
  482.  
  483.     DviFile = dviFile;
  484.  
  485.     if (DviUserMag == -1) {
  486.     DviUserMag = 1000;
  487.     }
  488.  
  489.     if (DviMaxDrift == -1) {
  490.     DviMaxDrift = DEFAULT_MAX_DRIFT;
  491.     }
  492.  
  493.     if (DviDpi == -1) {
  494.     DviDpi = DEFAULT_DPI;
  495.     }
  496.  
  497.     if (DviBlackness == -1) {
  498.     DviBlackness = DEFAULT_BLACKNESS;
  499.     }
  500.  
  501.     /* Margins -- needs work! */
  502.  
  503.     if (DviHHMargin == -1) {
  504.     DviHHMargin = DEFAULT_HHMARGIN;
  505.     }
  506.  
  507.     if (DviVVMargin == -1) {
  508.     DviVVMargin = DEFAULT_VVMARGIN;
  509.     }
  510.  
  511.     anError |= ScanPostAmble( DviFile, savePostAmblePointer, registerFont);
  512.  
  513.     if (anError) {
  514.       DviFini();
  515.     }
  516.  
  517.     return( anError );
  518. }
  519.  
  520. void
  521. DviFini()
  522. {
  523.   int font;
  524.   int c;
  525.  
  526.   if (DviFile != 0) {
  527.     fclose(DviFile);
  528.   }
  529.  
  530.   DviFile = 0;
  531.  
  532.   for (font = 0; font < RegisteredFonts; font++) {
  533.     if ( TheFontInfo[ font ].paf.paf_name ) {
  534.       free ( (char *) TheFontInfo[ font ].paf.paf_name );
  535.       TheFontInfo[ font] .paf.paf_name = 0;
  536.     }
  537.     if ( TheFontInfo[ font ].widths ) {
  538.       free ( (char *) TheFontInfo[ font ].widths );
  539.       TheFontInfo[ font].widths = 0;
  540.     }
  541.   }
  542.   RegisteredFonts = 0;
  543.  
  544.   for (c = 0; c < DVI_COUNT; c++) {
  545.     if ( DviCount[ c ] ) {
  546.       free( (char *) DviCount[ c ] );
  547.       DviCount[ c ] = 0;
  548.     }
  549.   }
  550. }
  551.     
  552.  
  553. char *
  554. DviFetchPage(pageNumber)
  555. int pageNumber;
  556. {
  557.   if ( pageNumber < 0 || pageNumber > DviTotalPages ) {
  558.     return(0);
  559.   }
  560.   else {
  561.     long start = DviPageOffsets[ pageNumber ];
  562.     long end = ( pageNumber == (DviTotalPages-1))
  563.       ? DviFileSize : DviPageOffsets[ pageNumber + 1];
  564.     long toRead = end - start;
  565.  
  566.     char *buffer = malloc( toRead );
  567.  
  568.     if (buffer == 0 ) {
  569.       return( 0 );
  570.     }
  571.     else {
  572.  
  573.       long loc;
  574.       long bytes;
  575.  
  576.       loc = fseek(DviFile, (long) start, 0);
  577.       if (loc < 0) {
  578.     error(0,0,"Improper seek: %d", errno);
  579.       }
  580.  
  581.       bytes = fread( buffer, 1, toRead, DviFile );
  582.  
  583.       if (bytes != toRead) {
  584.     error(0,0,"Tried to read %d, only got %d", toRead, bytes);
  585.       }
  586.       return(buffer);
  587.     }
  588.   }
  589. }
  590.  
  591.