home *** CD-ROM | disk | FTP | other *** search
/ OpenStep 3.3J / os33j.iso / NextLibrary / TeX / tex / src / dvips / output.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-28  |  28.6 KB  |  1,131 lines

  1. /*
  2.  *   These routines do most of the communicating with the printer.
  3.  *
  4.  *   LINELENGTH tells the maximum line length to send out.
  5.  */
  6. #define LINELENGTH (78)
  7. #include "dvips.h" /* The copyright notice in that file is included too! */
  8. #include <ctype.h>
  9. /*
  10.  *   The external routines called here:
  11.  */
  12. extern void error() ;
  13. extern void send_headers() ;
  14. extern int add_header() ;
  15. extern FILE *search() ;
  16. extern char *getenv() ;
  17. extern void fonttableout() ;
  18. extern void makepsname() ;
  19. extern void handlepapersize() ;
  20. extern void findbb() ;
  21. /*
  22.  *   These are the external variables used by these routines.
  23.  */
  24. extern integer hh, vv ;
  25. extern fontdesctype *curfnt ;
  26. extern FILE *bitfile ;
  27. extern char *oname ;
  28. extern Boolean secure ;
  29. extern Boolean reverse ;
  30. extern Boolean removecomments ;
  31. extern Boolean sendcontrolD, disablecomments, multiplesects ;
  32. extern Boolean usesPSfonts, headers_off ;
  33. extern Boolean safetyenclose ;
  34. extern Boolean cropmarks ;
  35. extern Boolean tryepsf ;
  36. extern int numcopies ;
  37. extern int collatedcopies ;
  38. extern integer pagecopies ;
  39. extern int totalpages ;
  40. extern integer pagenum ;
  41. extern Boolean manualfeed ;
  42. extern int landscape ;
  43. extern int quiet ;
  44. extern int prettycolumn ;
  45. extern int actualdpi, vactualdpi ;
  46. extern char *iname, *nextstring ;
  47. extern char *paperfmt ;
  48. extern char *headerpath ;
  49. extern char errbuf[] ;
  50. extern shalfword linepos ;
  51. extern char *figpath ;
  52. extern struct header_list *ps_fonts_used ;
  53. extern char banner[] ;
  54. extern int gargc ;
  55. extern char **gargv ;
  56. extern struct papsiz *papsizes ;
  57. extern integer hpapersize, vpapersize ;
  58. char preamblecomment[256] ; /* usually "TeX output ..." */
  59. /*
  60.  *   We need a few statics to take care of things.
  61.  */
  62. static integer rhh, rvv ;
  63. static int instring ;
  64. static Boolean lastspecial = 1 ;
  65. static shalfword d ;
  66. static Boolean popened = 0 ;
  67. int lastfont ; /* exported to dospecial to fix rotate.tex problem */
  68. static void chrcmd();                   /* just a forward declaration */
  69. static char strbuffer[LINELENGTH + 20], *strbp = strbuffer ;
  70. static struct papsiz *finpapsiz ;
  71. static struct papsiz defpapsiz = {
  72.    0, 40258437L, 52099154L, "letter", ""
  73. } ;
  74. #ifdef CREATIONDATE
  75. #ifndef VMS          /* The VAXC compiler doesn't like/need this !! */
  76. #include <sys/types.h>
  77. #include <sys/time.h> /* time(), at least on BSD Unix */
  78. #endif
  79. #include <time.h> /* asctime() and localtime(), at least on BSD Unix */
  80. static time_t jobtime;
  81. #endif
  82. /*
  83.  *   This routine copies a file down the pipe.  Search path uses the
  84.  *   header path.
  85.  *
  86.  *   We add code to handle the case of MS-DOS font files.
  87.  *
  88.  *   Format:  80 {01,02} four byte length in littleendian order data
  89.  *   repeated possibly multiple times.
  90.  */
  91. static char *hxdata = "0123456789ABCDEF" ;
  92. static int infigure ;
  93. extern char *infont ;
  94. void
  95. copyfile(s)
  96.         char *s ;
  97. {
  98.    FILE *f = NULL ;
  99.    int c, prevc = '\n' ;
  100.    long len ;
  101. #ifdef VMCMS
  102.    register char *lastdirsep ;
  103.    register char *trunc_s ;
  104.    trunc_s = s ;
  105. #endif
  106. #ifdef MSXA
  107.    register char *lastdirsep ;
  108.    register char *trunc_s ;
  109.    trunc_s = s ;
  110. #endif
  111.  
  112.    switch (infigure) {
  113.    case 1:
  114.       f = search(figpath, s, READ) ;
  115. #ifdef VMCMS
  116.       lastdirsep = strrchr(s, '/') ;
  117.       if ( NULL != lastdirsep ) trunc_s = lastdirsep + 1 ;
  118.       (void)sprintf(errbuf,
  119.    "Couldn't find figure file %s with CMS name %s; continuing", s, trunc_s) ;
  120. #else
  121. #ifdef MVSXA
  122.       lastdirsep = strrchr(s, '/') ;
  123.       if ( NULL != lastdirsep ) trunc_s = lastdirsep + 1 ;
  124.       (void)sprintf(errbuf,
  125.     "Couldn't find figure file %s with MVS name %s; continuing", s, trunc_s) ;
  126. #else
  127.       (void)sprintf(errbuf, "Couldn't find figure file %s; continuing", s) ;
  128. #endif
  129. #endif
  130.       break ;
  131.    default:
  132.       f = search(headerpath, s, READ) ;
  133.       (void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
  134.       break ;
  135. #ifndef VMCMS
  136. #ifndef VMS
  137. #ifndef MSDOS
  138. #ifndef __THINK__
  139.    case 2:
  140. #ifdef SECURE
  141.       (void)sprintf(errbuf, "<%s>: Tick filename execution disabled", s) ;
  142. #else
  143.       if (secure == 0)
  144.          f = popen(s, "r") ;
  145.       (void)sprintf(errbuf, "Failure to execute %s; continuing", s) ;
  146. #endif
  147.       break;
  148. #endif
  149. #endif
  150. #endif
  151. #endif
  152.    }
  153.    if (f==NULL)
  154.       error(errbuf) ;
  155.    else {
  156.       if (! quiet) {
  157.          if (strlen(s) + prettycolumn > STDOUTSIZE) {
  158.             fprintf(stderr, "\n") ;
  159.             prettycolumn = 0 ;
  160.          }
  161. #ifdef VMCMS
  162.          (void)fprintf(stderr, "<%s>", trunc_s) ;
  163. #else
  164.          (void)fprintf(stderr, "<%s>", s) ;
  165. #endif
  166.          (void)fflush(stderr) ;
  167.          prettycolumn += 2 + strlen(s) ;
  168.       }
  169.       if (linepos != 0)
  170.          (void)putc('\n', bitfile) ;
  171.       if (! disablecomments)
  172.          if (infigure)
  173.             (void)fprintf(bitfile, "%%%%BeginDocument: %s\n", s) ;
  174.          else if (infont)
  175.             (void)fprintf(bitfile, "%%%%BeginFont: %s\n", infont) ;
  176.          else
  177.             (void)fprintf(bitfile, "%%%%BeginProcSet: %s\n", s) ;
  178.       c = getc(f) ;
  179.       if (c == 0x80) {
  180. #ifdef MSDOS
  181.          (void)fclose(f) ;  /* close MSDOS font file */
  182.          f = search(headerpath, s, READBIN) ;  /* reopen in BINARY mode */
  183.          (void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
  184.          if (f==NULL)
  185.            error(errbuf) ;
  186.          c = getc(f);
  187. #endif
  188.          while (1) {
  189.             c = getc(f) ;
  190.             switch(c) {
  191. case 1:
  192. case 2:
  193.                len = getc(f) ;
  194.                len += getc(f) * 256L ;
  195.                len += getc(f) * 65536L ;
  196.                len += getc(f) * 256L * 65536 ;
  197.                if (c == 1) {
  198.                   while (len > 0) {
  199.                      c = getc(f) ;
  200.                      if (c == EOF) {
  201.                         error("premature EOF in MS-DOS font file") ;
  202.                         len = 0 ;
  203.                      } else {
  204.                         if (c == 13)
  205.                            (void)putc('\n', bitfile) ;
  206.                         else
  207.                            (void)putc(c, bitfile) ;
  208.                         len-- ;
  209.                      }
  210.                   }
  211.                } else {
  212.                   putc('\n', bitfile) ;
  213.                   prevc = 0 ;
  214.                   while (len > 0) {
  215.                      c = getc(f) ;
  216.                      if (c == EOF) {
  217.                         error("premature EOF in MS-DOS font file") ;
  218.                         len = 0 ;
  219.                      } else {
  220.                         (void)putc(hxdata[c >> 4], bitfile) ;
  221.                         (void)putc(hxdata[c & 15], bitfile) ;
  222.                         len-- ;
  223.                         prevc += 2 ;
  224.                         if (prevc >= 76) {
  225.                            putc('\n', bitfile) ;
  226.                            prevc = 0 ;
  227.                         }
  228.                      }
  229.                   }
  230.                }
  231.                break ;
  232. case 3:
  233.                goto msdosdone ;
  234. default:
  235.                error("saw type other than 1, 2, or 3 in MS-DOS font file") ;
  236.                break ;
  237.             }
  238.             c = getc(f) ;
  239.             if (c == EOF)
  240.                break ;
  241.             if (c != 0x80) {
  242.                error("saw non-MSDOS header in MSDOS font file") ;
  243.                break ;
  244.             }
  245.          }
  246. msdosdone:
  247.          prevc = 0 ;
  248.       } else {
  249.          if (c != EOF) {
  250.             while (1) {
  251.                if (removecomments && c == '%' && prevc == '\n') {/* skip comments */
  252.                   while ((c=getc(f))!=EOF) {
  253.                      if (c == '\n' || c == '\r') {
  254.                         c = '\n' ;
  255.                         break ;
  256.                      }
  257.                   }
  258. #ifdef VMCMS
  259.                } else if (c != 0x37 ) {
  260. #else
  261. #ifdef MVSXA
  262.                } else if (c != 0x37 ) {
  263. #else
  264.                } else if (c != 4) {
  265. #endif
  266. #endif
  267.                   (void)putc(c, bitfile) ;
  268.                }
  269.                prevc = c ;
  270.                c = getc(f) ;
  271.                if (c == EOF)
  272.                   break ;
  273.                else if (c == '\r')
  274.                   c = '\n' ;
  275.             }
  276.          }
  277.       }
  278.       if (prevc != '\n')
  279.          (void)putc('\n', bitfile) ;
  280.       linepos = 0 ;
  281. #ifndef VMCMS
  282. #ifndef VMS
  283. #ifndef MSDOS
  284. #ifndef __THINK__
  285.       if (infigure == 2)
  286.          (void)pclose(f) ;
  287.       else
  288. #endif
  289. #endif
  290. #endif
  291. #endif
  292.          (void)fclose(f) ;
  293.       if (!disablecomments)
  294.          if (infigure)
  295.             (void)fprintf(bitfile, "%%%%EndDocument\n") ;
  296.          else if (infont)
  297.             (void)fprintf(bitfile, "%%%%EndFont\n") ;
  298.          else
  299.             (void)fprintf(bitfile, "%%%%EndProcSet\n") ;
  300.    }
  301. }
  302.  
  303. /*
  304.  *   For included PostScript graphics, we use the above routine, but
  305.  *   with no fatal error message.
  306.  */
  307. void figcopyfile(s, systemtype)
  308. char *s ;
  309. int systemtype ;
  310. {
  311.    infigure = systemtype ? 2 : 1 ;
  312.    copyfile(s) ;
  313.    infigure = 0 ;
  314. }
  315. /*
  316.  *   This next routine writes out a `special' character.  In this case,
  317.  *   we simply put it out, since any special character terminates the
  318.  *   preceding token.
  319.  */
  320. void
  321. specialout(c)
  322.         char c ;
  323. {
  324.    if (linepos >= LINELENGTH) {
  325.       (void)putc('\n', bitfile) ;
  326.       linepos = 0 ;
  327.    }
  328.    (void)putc(c, bitfile) ;
  329.    linepos++ ;
  330.    lastspecial = 1 ;
  331. }
  332.  
  333. void
  334. stringend()
  335. {
  336.    if (linepos + instring >= LINELENGTH - 2) {
  337.       (void)putc('\n', bitfile) ;
  338.       linepos = 0 ;
  339.    }
  340.    (void)putc('(', bitfile) ;
  341.    *strbp = 0 ;
  342.    (void)fputs(strbuffer, bitfile) ;
  343.    (void)putc(')', bitfile) ;
  344.    linepos += instring + 2 ;
  345.    lastspecial = 1 ;
  346.    instring = 0 ;
  347.    strbp = strbuffer ;
  348. }
  349.  
  350. void
  351. scout(c)   /* string character out */
  352.         char c ;
  353. {
  354. /*
  355.  *   Is there room in the buffer?  LINELENGTH-6 is used because we
  356.  *   need room for (, ), and a possible four-byte string \000, for
  357.  *   instance.  If it is too long, we send out the string.
  358.  */
  359.    if (instring > LINELENGTH-6) {
  360.       stringend() ;
  361.       chrcmd('p') ;
  362.    }
  363. /*  changed next line to hex representation for VMCMS port
  364.    if (c<' ' || c > 126 || c=='%' ) {
  365. */
  366.    if ( c<0x20 || c>= 0x7F || c==0x25 ) {
  367.       *strbp++ = '\\' ;
  368.       *strbp++ = '0' + ((c >> 6) & 3) ;
  369.       *strbp++ = '0' + ((c >> 3) & 7) ;
  370.       *strbp++ = '0' + (c & 7) ;
  371.       instring += 4 ;
  372.    } else {
  373. #ifdef VMCMS
  374.      c = ascii2ebcdic[c];
  375. #else
  376. #ifdef MVSXA
  377.      c = ascii2ebcdic[c];
  378. #endif
  379. #endif
  380.      if (c == '(' || c == ')' || c == '\\') {
  381.        *strbp++ = '\\' ;
  382.        *strbp++ = c ;
  383.        instring += 2 ;
  384.      } else {
  385.        *strbp++ = c ;
  386.        instring++ ;
  387.      }
  388.    }
  389. }
  390.  
  391. void
  392. cmdout(s)
  393.         char *s ;
  394. {
  395.    int l ;
  396.  
  397.    /* hack added by dorab */
  398.    if (instring) {
  399.         stringend();
  400.         chrcmd('p');
  401.    }
  402.    l = strlen(s) ;
  403.    if ((! lastspecial && linepos >= LINELENGTH - 20) ||
  404.            linepos + l >= LINELENGTH) {
  405.       (void)putc('\n', bitfile) ;
  406.       linepos = 0 ;
  407.       lastspecial = 1 ;
  408.    } else if (! lastspecial) {
  409.       (void)putc(' ', bitfile) ;
  410.       linepos++ ;
  411.    }
  412.    (void)fputs(s, bitfile) ;
  413.    linepos += l ;
  414.    lastspecial = 0 ;
  415. }
  416.  
  417.  
  418. static void
  419. chrcmd(c)
  420.         char c ;
  421. {
  422.    if ((! lastspecial && linepos >= LINELENGTH - 20) ||
  423.        linepos + 2 > LINELENGTH) {
  424.       (void)putc('\n', bitfile) ;
  425.       linepos = 0 ;
  426.       lastspecial = 1 ;
  427.    } else if (! lastspecial) {
  428.       (void)putc(' ', bitfile) ;
  429.       linepos++ ;
  430.    }
  431.    (void)putc(c, bitfile) ;
  432.    linepos++ ;
  433.    lastspecial = 0 ;
  434. }
  435.  
  436. void
  437. floatout(n)
  438.         float n ;
  439. {
  440.    char buf[20] ;
  441.  
  442.    (void)sprintf(buf, "%.2f", n) ;
  443.    cmdout(buf) ;
  444. }
  445.  
  446. void
  447. numout(n)
  448.         integer n ;
  449. {
  450.    char buf[10] ;
  451.  
  452. #ifdef SHORTINT
  453.    (void)sprintf(buf, "%ld", n) ;
  454. #else
  455.    (void)sprintf(buf, "%d", n) ;
  456. #endif
  457.    cmdout(buf) ;
  458. }
  459.  
  460. void
  461. mhexout(p, len)
  462. register unsigned char *p ;
  463. register long len ;
  464. {
  465.    register char *hexchar = hxdata ;
  466.    register int n, k ;
  467.  
  468.    while (len > 0) {
  469.       if (linepos > LINELENGTH - 2) {
  470.          (void)putc('\n', bitfile) ;
  471.          linepos = 0 ;
  472.       }
  473.       k = (LINELENGTH - linepos) >> 1 ;
  474.       if (k > len)
  475.          k = len ;
  476.       len -= k ;
  477.       linepos += (k << 1) ;
  478.       while (k--) {
  479.          n = *p++ ;
  480.          (void)putc(hexchar[n >> 4], bitfile) ;
  481.          (void)putc(hexchar[n & 15], bitfile) ;
  482.       }
  483.    }
  484. }
  485.  
  486. void
  487. fontout(n)
  488.         int n ;
  489. {
  490.    char buf[6] ;
  491.  
  492.    if (instring) {
  493.       stringend() ;
  494.       chrcmd('p') ;
  495.    }
  496.    makepsname(buf, n) ;
  497.    cmdout(buf) ;
  498. }
  499.  
  500. void
  501. hvpos()
  502. {
  503.    if (rvv != vv) {
  504.       if (instring) {
  505.          stringend() ;
  506.          numout(hh) ;
  507.          numout(vv) ;
  508.          chrcmd('y') ;
  509.       } else if (rhh != hh) {
  510.          numout(hh) ;
  511.          numout(vv) ;
  512.          chrcmd('a') ;
  513.       } else { /* hard to get this case, but it's there when you need it! */
  514.          numout(vv - rvv) ;
  515.          chrcmd('x') ;
  516.       }
  517.       rvv = vv ;
  518.    } else if (rhh != hh) {
  519.       if (instring) {
  520.          stringend() ;
  521.          if (hh - rhh < 5 && rhh - hh < 5) {
  522. #ifdef VMCMS /*  should replace 'p' in non-VMCMS line as well */
  523.             chrcmd(ascii2ebcdic[(char)(112 + hh - rhh)]) ;
  524. #else
  525. #ifdef MVSXA /*  should replace 'p' in non-MVSXA line as well */
  526.             chrcmd(ascii2ebcdic[(char)(112 + hh - rhh)]) ;
  527. #else
  528.             chrcmd((char)('p' + hh - rhh)) ;
  529. #endif
  530. #endif
  531.          } else if (hh - rhh < d + 5 && rhh - hh < 5 - d) {
  532. #ifdef VMCMS /* should replace 'g' in non-VMCMS line as well  */
  533.             chrcmd(ascii2ebcdic[(char)(103 + hh - rhh - d)]) ;
  534. #else
  535. #ifdef MVSXA /* should replace 'g' in non-MVSXA line as well  */
  536.             chrcmd(ascii2ebcdic[(char)(103 + hh - rhh - d)]) ;
  537. #else
  538.             chrcmd((char)('g' + hh - rhh - d)) ;
  539. #endif
  540. #endif
  541.             d = hh - rhh ;
  542.          } else {
  543.             numout(hh - rhh) ;
  544.             chrcmd('b') ;
  545.             d = hh - rhh ;
  546.          }
  547.       } else {
  548.          numout(hh - rhh) ;
  549.          chrcmd('w') ;
  550.       }
  551.    }
  552.    rhh = hh ;
  553. }
  554.  
  555. /*
  556.  *   initprinter opens the bitfile and writes the initialization sequence
  557.  *   to it.
  558.  */
  559. void newline()
  560. {
  561.    if (linepos != 0) {
  562.       (void)fprintf(bitfile, "\n") ;
  563.       linepos = 0 ;
  564.    }
  565.    lastspecial = 1 ;
  566. }
  567.  
  568. void
  569. nlcmdout(s)
  570.         char *s ;
  571. {
  572.    newline() ;
  573.    cmdout(s) ;
  574.    newline() ;
  575. }
  576. /*
  577.  *   Is the dimension close enough for a match?  We use a quarter inch
  578.  *   as a match; this is 65536*72.27/4 or 1,184,072 scaled points.
  579.  */
  580. static int indelta(i)
  581. integer i ;
  582. {
  583.    if (i < 0)
  584.       i = -i ;
  585.    return (i <= 1184072) ;
  586. }
  587. /*
  588.  *   A case-irrelevant string compare.
  589.  */
  590. int mlower(c)
  591. int c ;
  592. {
  593.    if ('A' <= c && c <= 'Z')
  594.       return c - 'A' + 'a' ;
  595.    else
  596.       return c ;
  597. }
  598. int ncstrcmp(a, b)
  599. char *a, *b ;
  600. {
  601.    while (*a && (*a == *b ||
  602.                        mlower(*a) == mlower(*b)))
  603.       a++, b++ ;
  604.    if (*a == 0 && *b == 0)
  605.       return 0 ;
  606.    else
  607.       return 1 ;
  608. }
  609. /*
  610.  *   Find the paper size.
  611.  */
  612. void findpapersize() {
  613.    if (finpapsiz == 0) {
  614.       struct papsiz *ps ;
  615.  
  616.       if (tryepsf && !landscape) {
  617.          finpapsiz = &defpapsiz ;
  618.          hpapersize = defpapsiz.xsize ;
  619.          vpapersize = defpapsiz.ysize ;
  620.          return ;
  621.       }
  622.       if (cropmarks) {
  623. /*
  624.  *   If user wanted crop marks, we increase the size of the page by
  625.  *   a half inch all around.
  626.  */
  627.          if (hpapersize == 0 || vpapersize == 0) {
  628.             error(
  629.  "warning: -k crop marks wanted, but no paper size specified; using default") ;
  630.             if (landscape) {
  631.                hpapersize = defpapsiz.ysize ;
  632.                vpapersize = defpapsiz.xsize ;
  633.             } else {
  634.                hpapersize = defpapsiz.xsize ;
  635.                vpapersize = defpapsiz.ysize ;
  636.             }
  637.          }
  638.          hpapersize += 2368143L ;
  639.          vpapersize += 2368143L ;
  640.          add_header(CROPHEADER) ;
  641.       }
  642.       if (paperfmt && *paperfmt) {
  643.          for (ps = papsizes; ps; ps = ps->next)
  644.             if (ncstrcmp(paperfmt, ps->name)==0)
  645.                finpapsiz = ps ;
  646.          if (finpapsiz == 0)
  647.             error("no match for papersize") ;
  648.       }
  649.       if (finpapsiz == 0 && hpapersize > 0 && vpapersize > 0) {
  650.          for (ps=papsizes; ps; ps = ps->next) {
  651.             if (indelta(ps->xsize-hpapersize) &&
  652.                 indelta(ps->ysize-vpapersize)) {
  653.                landscape = 0 ;
  654.                break ;
  655.             }
  656.          }
  657.          if (ps == 0) {
  658.             for (ps=papsizes; ps; ps = ps->next) {
  659.                if (indelta(ps->ysize-hpapersize) &&
  660.                    indelta(ps->xsize-vpapersize)) {
  661.                   landscape = 1 ;
  662.                   break ;
  663.                }
  664.             }
  665.             if (ps == 0) {
  666.                for (ps=papsizes; ps; ps = ps->next) {
  667.                   if (ps->ysize == 0 && ps->xsize == 0)
  668.                      break ;
  669.                }
  670.                if (ps == 0) {
  671.                   landscape = (hpapersize > vpapersize) ;
  672.                   error(
  673.                     "no match for special paper size found; using default") ;
  674.                }
  675.             }
  676.          }
  677.          finpapsiz = ps ;
  678.       }
  679.       if (finpapsiz == 0) {
  680.          if (papsizes)
  681.             finpapsiz = papsizes ;
  682.          else
  683.             finpapsiz = &defpapsiz ;
  684. /*
  685.  *   But change xsize/ysize to match so bounding box works.
  686.  */
  687.          if (hpapersize && vpapersize) {
  688.             if (landscape) {
  689.                finpapsiz->ysize = hpapersize ;
  690.                finpapsiz->xsize = vpapersize ;
  691.             } else {
  692.                finpapsiz->xsize = hpapersize ;
  693.                finpapsiz->ysize = vpapersize ;
  694.             }
  695.          }
  696.       }
  697. /*
  698.  *   Here, there was no papersize special.  We set the paper size from
  699.  *   the selected paper format.  If the selected paper format has no
  700.  *   sizes, we use the defaults.
  701.  */
  702.       if (hpapersize == 0 || vpapersize == 0) {
  703.          if (finpapsiz->xsize == 0 || finpapsiz->ysize == 0) {
  704.             finpapsiz->xsize = defpapsiz.xsize ;
  705.             finpapsiz->ysize = defpapsiz.ysize ;
  706.          }
  707.          if (landscape) {
  708.             vpapersize = finpapsiz->xsize ;
  709.             hpapersize = finpapsiz->ysize ;
  710.          } else {
  711.             hpapersize = finpapsiz->xsize ;
  712.             vpapersize = finpapsiz->ysize ;
  713.          }
  714. /*
  715.  *   Here, there was a papersize special, but the selected paper
  716.  *   format has 0 0 for sizes.  We set the sizes here so that the
  717.  *   bounding box works.
  718.  */
  719.       } else if (finpapsiz->xsize == 0 || finpapsiz->ysize == 0) {
  720.          finpapsiz->xsize = hpapersize ;
  721.          finpapsiz->ysize = vpapersize ;
  722. /*
  723.  *   Here, the user specified a size with -t, and there was a
  724.  *   papersize special, and its sizes were greater than zero.
  725.  *   We make sure the sizes are okay.  Note that the user must have
  726.  *   specified landscape if this is desired.
  727.  */
  728.       } else if (paperfmt && *paperfmt) {
  729.          if (landscape) {
  730.             if (!indelta(vpapersize - finpapsiz->xsize) ||
  731.                 !indelta(hpapersize - finpapsiz->ysize)) {
  732.                if (vpapersize > finpapsiz->xsize ||
  733.                    hpapersize > finpapsiz->ysize)
  734.                   error("warning: -t selected paper may be too small") ;
  735.                else
  736.                   error("note: -t selected paper may be too large") ;
  737.             }
  738.          } else {
  739.             if (!indelta(hpapersize - finpapsiz->xsize) ||
  740.                 !indelta(vpapersize - finpapsiz->ysize)) {
  741.                if (hpapersize > finpapsiz->xsize ||
  742.                    vpapersize > finpapsiz->ysize)
  743.                   error("warning: -t selected paper may be too small") ;
  744.                else
  745.                   error("note: -t selected paper may be too large") ;
  746.             }
  747.          }
  748.       }
  749.    }
  750. }
  751. /*
  752.  *   Convert scaled points to PostScript points.  This is the same
  753.  *   as return (i * 72 / (65536 * 72.27)), which is the same as
  754.  *   dividing by 65781.76, but we want to round up.
  755.  */
  756. static int topoints(i)
  757. integer i ;
  758. {
  759.    i += 65780L ;
  760.    return (i / 6578176L)*100 + (i % 6578176) * 100 / 6578176 ;
  761. }
  762. /*
  763.  *   Send out the special paper stuff.  If `hed' is non-zero, only
  764.  *   send out lines starting with `!' else send all other lines out.
  765.  */
  766. void paperspec(s, hed)
  767. char *s ;
  768. int hed ;
  769. {
  770.    int sendit ;
  771.  
  772.    while (*s) {
  773.       s++ ;
  774.       if (*s == '\0')
  775.          return ;
  776.       if (*s == '!') {
  777.          s++ ;
  778.          while (*s == ' ') s++ ;
  779.          sendit = hed ;
  780.       } else
  781.          sendit = ! hed ;
  782.       if (sendit) {
  783.          while (*s && *s != '\n')
  784.             (void)putc(*s++, bitfile) ;
  785.          putc('\n', bitfile) ;
  786.       } else {
  787.          while (*s && *s != '\n')
  788.             s++ ;
  789.       }
  790.    }
  791. }
  792. char *epsftest() {
  793.    if (tryepsf && totalpages == 1 && paperfmt == 0 && *iname) {
  794.       findbb() ;
  795.       return nextstring ;
  796.    }
  797.    return 0 ;
  798. }
  799. static char *isepsf = 0 ;
  800. static int endprologsent ;
  801.  
  802. #if defined(hppa)
  803. #pragma CC_OPT_OFF
  804. #warning "Workaround for 45692.  See also #45670."
  805. #endif
  806.  
  807. void
  808. initprinter(n)
  809. int n ; /* number of pages if greater than 0 */
  810. {
  811.    void tell_needed_fonts() ;
  812.  
  813.    n *= pagecopies * collatedcopies ;
  814.    if (*oname != 0) {
  815. /*
  816.  *   We check to see if the first character is a exclamation
  817.  *   point, and popen if so.
  818.  */
  819.       if (*oname == '!' || *oname == '|') {
  820. #ifdef MSDOS
  821.             error("! can't open output pipe") ;
  822. #else
  823. #ifdef VMS
  824.             error("! can't open output pipe") ;
  825. #else
  826. #ifdef VMCMS
  827.             error("! can't open output pipe") ;
  828. #else
  829. #ifdef MVSXA
  830.             error("! can't open output pipe") ;
  831. #else
  832. #ifdef __THINK__
  833.             error("! can't open output pipe") ;
  834. #else
  835.          if (secure || (bitfile=popen(oname+1, "w"))==NULL)
  836.             error("! couldn't open output pipe") ;
  837.          else
  838.             popened = 1 ;
  839. #endif
  840. #endif
  841. #endif
  842. #endif
  843. #endif
  844.       } else {
  845.          if ((bitfile=fopen(oname,"w"))==NULL)
  846.             error("! couldn't open PostScript file") ;
  847.       }
  848.    } else {
  849.       bitfile = stdout ;
  850.    }
  851.    findpapersize() ;
  852.    if (disablecomments)
  853.       (void)fprintf(bitfile,
  854.              "%%!PS (but not EPSF; comments have been disabled)\n") ;
  855.    else {
  856.       if (multiplesects)
  857.          (void)fprintf(bitfile,
  858.              "%%!PS (but not EPSF because of memory limits)\n") ;
  859.       else {
  860.          isepsf = epsftest() ;
  861.          if (isepsf)
  862.             (void)fprintf(bitfile, "%%!PS-Adobe-2.0 EPSF-2.0\n") ;
  863.          else
  864.             (void)fprintf(bitfile, "%%!PS-Adobe-2.0\n") ;
  865.       }
  866.       if (tryepsf && isepsf == 0)
  867.          error("We tried, but couldn't make it EPSF.") ;
  868.       (void)fprintf(bitfile, "%%%%Creator: %s", banner + 8) ;
  869.       if (*iname)
  870.          (void)fprintf(bitfile, "%%%%Title: %s\n", iname) ;
  871. #ifdef CREATIONDATE
  872.       jobtime=time(0);
  873.       (void)fprintf(bitfile, "%%%%CreationDate: %s",
  874.                                  asctime(localtime(&jobtime))) ;
  875. #endif
  876.       if (! isepsf) {
  877. /*
  878.  *   Normally, we wouldn't want to add that second field
  879.  *   indicating that the page order is reversed, as per page
  880.  *   644 of the Red book.  But we have to, for many existing
  881.  *   spoolers.
  882.  */
  883.         (void)fprintf(bitfile, "%%%%Pages: %d%s\n", (n ? n : totalpages),
  884.                                                     (reverse?" -1":"")) ;
  885.         (void)fprintf(bitfile, "%%%%PageOrder: %sscend\n", reverse?"De":"A");
  886.       }
  887.       if (landscape) {
  888.          fprintf(bitfile, "%%%%Orientation: Landscape\n") ;
  889.          fprintf(bitfile, "%%%%BoundingBox: 0 0 %d %d\n",
  890.               topoints(finpapsiz->xsize), topoints(finpapsiz->ysize)) ;
  891.       } else if (isepsf)
  892.          fprintf(bitfile, "%%%%BoundingBox: %s\n", isepsf) ;
  893.       else
  894.          fprintf(bitfile, "%%%%BoundingBox: 0 0 %d %d\n",
  895.               topoints(finpapsiz->xsize), topoints(finpapsiz->ysize)) ;
  896.       tell_needed_fonts() ;
  897.       paperspec(finpapsiz->specdat, 1) ;
  898.       (void)fprintf(bitfile, "%%%%EndComments\n") ;
  899.    }
  900.    {
  901.       int i ;
  902.       char *p ;
  903.  
  904.       (void)fprintf(bitfile, "%%DVIPSCommandLine:") ;
  905.       for (i=0; i<gargc; i++) {
  906.          (void)fputc(' ', bitfile) ;
  907.          p = gargv[i] ;
  908.          while (*p > ' ')
  909.             p++ ;
  910.          (void)fprintf(bitfile, (*p ? "\"%s\"" : "%s"), gargv[i]) ;
  911.       }
  912.       (void)fputc('\n', bitfile) ;
  913.    }
  914. #ifdef VMCMS  /* convert preamblecomment to ebcdic so we can read it */
  915.    {
  916.       int i ;
  917.       for ( i=0 ; preamblecomment[i] ; i++ )
  918.           preamblecomment[i] = ascii2ebcdic[preamblecomment[i]] ;
  919.    }
  920. #else
  921. #ifdef MVSXA   /* IBM: MVS/XA */
  922.    {
  923.       int i ;
  924.       for ( i=0 ; preamblecomment[i] ; i++ )
  925.           preamblecomment[i] = ascii2ebcdic[preamblecomment[i]] ;
  926.    }
  927. #endif  /* VMCMS */
  928. #endif
  929.    (void)fprintf(bitfile, "%%DVIPSSource: %s\n", preamblecomment) ;
  930.    linepos = 0 ;
  931.    endprologsent = 0 ;
  932.    if (safetyenclose)
  933.       (void)fprintf(bitfile, "/SafetyEnclosure save def\n") ;
  934.    if (! headers_off)
  935.       send_headers() ;
  936. }
  937.  
  938. #if defined(hppa)
  939. #pragma CC_OPT_RESTORE
  940. #endif
  941.  
  942. void setup() {
  943.    fonttableout() ;
  944.    newline() ;
  945.    if (endprologsent == 0 && !disablecomments) {
  946.       (void)fprintf(bitfile, "%%%%EndProlog\n") ;
  947.       (void)fprintf(bitfile, "%%%%BeginSetup\n") ;
  948.       if (vactualdpi == actualdpi)
  949.          (void)fprintf(bitfile, "%%%%Feature: *Resolution %ddpi\n",
  950.                                            actualdpi) ;
  951.       else
  952.          (void)fprintf(bitfile, "%%%%Feature: *Resolution %dx%ddpi\n",
  953.                                            actualdpi, vactualdpi) ;
  954.       if (multiplesects && *(finpapsiz->specdat)) {
  955.          (void)fprintf(bitfile, "TeXDict begin\n") ;
  956.          paperspec(finpapsiz->specdat, 0) ;
  957.          (void)fprintf(bitfile, "end\n") ;
  958.       }
  959.       if (manualfeed)
  960.          (void)fprintf(bitfile, "%%%%Feature: *ManualFeed True\n") ;
  961.       if (multiplesects)
  962.          (void)fprintf(bitfile, "%%%%EndSetup\n") ;
  963.    }
  964.    if (multiplesects && ! disablecomments)
  965.       (void)fprintf(bitfile, "%%DVIPSBeginSection\n") ;
  966.    cmdout("TeXDict") ;
  967.    cmdout("begin") ;
  968.    if (endprologsent || disablecomments || multiplesects == 0) {
  969.       (void)fprintf(bitfile, "\n") ;
  970.       paperspec(finpapsiz->specdat, 0) ;
  971.    }
  972.    if (manualfeed) cmdout("@manualfeed") ;
  973.    if (landscape) cmdout("@landscape") ;
  974.    if (numcopies != 1) {
  975.       numout((integer)numcopies) ;
  976.       cmdout("@copies") ;
  977.    }
  978.    if (endprologsent == 0 && !disablecomments) {
  979.       newline() ;
  980.       endprologsent = 1 ;
  981.       if (! multiplesects)
  982.          (void)fprintf(bitfile, "%%%%EndSetup\n") ;
  983.    }
  984. }
  985. /*
  986.  *   cleanprinter is the antithesis of the above routine.
  987.  */
  988. void
  989. cleanprinter()
  990. {
  991.    (void)fprintf(bitfile, "\n") ;
  992.    (void)fprintf(bitfile, "userdict /end-hook known{end-hook}if\n") ;
  993.    if (safetyenclose)
  994.       (void)fprintf(bitfile, "SafetyEnclosure restore\n") ;
  995.    if (!disablecomments)
  996.       (void)fprintf(bitfile, "%%%%EOF\n") ;
  997.    if (sendcontrolD)
  998.       (void)putc(4, bitfile) ;
  999.    if (ferror(bitfile))
  1000.       error("Problems with file writing; probably disk full.") ;
  1001. #ifndef MSDOS
  1002. #ifndef VMS
  1003. #ifndef VMCMS
  1004. #ifndef __THINK__
  1005.    if (popened)
  1006.       (void)pclose(bitfile) ;
  1007. #endif
  1008. #endif
  1009. #endif
  1010. #endif
  1011.    if (popened == 0)
  1012.       (void)fclose(bitfile) ;
  1013.    bitfile = NULL ;
  1014. }
  1015.  
  1016. /* this tells dvips that it has no clue where it is. */
  1017. static int thispage = 0 ;
  1018. static integer rulex, ruley ;
  1019. void psflush() {
  1020.    rulex = ruley = rhh = rvv = -314159265 ;
  1021.    lastfont = -1 ;
  1022. }
  1023. /*
  1024.  *   pageinit initializes the output variables.
  1025.  */
  1026. void
  1027. pageinit()
  1028. {
  1029.    psflush() ;
  1030.    newline() ;
  1031.    thispage++ ;
  1032.    if (!disablecomments)
  1033.       if (multiplesects)
  1034. #ifdef SHORTINT
  1035.          (void)fprintf(bitfile, "%%DVIPSSectionPage: %ld\n", pagenum) ;
  1036.       else if (! isepsf)
  1037.          (void)fprintf(bitfile, "%%%%Page: %ld %d\n", pagenum, thispage) ;
  1038. #else
  1039.          (void)fprintf(bitfile, "%%DVIPSSectionPage: %d\n", pagenum) ;
  1040.       else if (! isepsf)
  1041.          (void)fprintf(bitfile, "%%%%Page: %d %d\n", pagenum, thispage) ;
  1042. #endif
  1043.    linepos = 0 ;
  1044.    numout((integer)pagenum) ;
  1045.    numout((integer)thispage-1) ;
  1046.    cmdout("bop") ;
  1047.    d = 0 ;
  1048. }
  1049.  
  1050.  
  1051.  
  1052. /*
  1053.  *   This routine ends a page.
  1054.  */
  1055. void
  1056. pageend()
  1057. {
  1058.    if (instring) {
  1059.       stringend() ;
  1060.       chrcmd('p') ;
  1061.    }
  1062.    cmdout("eop") ;
  1063. }
  1064.  
  1065. /*
  1066.  *   drawrule draws a rule at the specified position.
  1067.  *   It does nothing to save/restore the current position,
  1068.  *   or even draw the current string.  (Rules are normally
  1069.  *   set below the baseline anyway, so this saves us on
  1070.  *   output size almost always.)
  1071.  */
  1072. void
  1073. drawrule(rw, rh)
  1074.         integer rw, rh ;
  1075. {
  1076.    numout((integer)hh) ;
  1077.    numout((integer)vv) ;
  1078.    if (rw == rulex && rh == ruley)
  1079.       chrcmd('V') ;
  1080.    else {
  1081.       numout((integer)rw) ;
  1082.       numout((integer)rh) ;
  1083.       chrcmd('v') ;
  1084.       rulex = rw ;
  1085.       ruley = rh ;
  1086.    }
  1087. }
  1088.  
  1089. /*
  1090.  *   drawchar draws a character at the specified position.
  1091.  */
  1092. void
  1093. drawchar(c, cc)
  1094.         chardesctype *c ;
  1095.         int cc ;
  1096. {
  1097.    hvpos() ;
  1098.    if (lastfont != curfnt->psname) {
  1099.       fontout((int)curfnt->psname) ;
  1100.       lastfont = curfnt->psname ;
  1101.    }
  1102.    scout(cc) ;
  1103.    rhh = hh + c->pixelwidth ; /* rvv = rv */
  1104. }
  1105. /*
  1106.  *   This routine sends out the document fonts comment.
  1107.  */
  1108. void tell_needed_fonts() {
  1109.    struct header_list *hl = ps_fonts_used ;
  1110.    char *q ;
  1111.    int roomleft = -1 ;
  1112.    extern char *get_name() ;
  1113.  
  1114.    if (hl == 0)
  1115.       return ;
  1116.    while (q=get_name(&hl)) {
  1117.       if ((int)strlen(q) >= roomleft) {
  1118.          if (roomleft != -1) {
  1119.             fprintf(bitfile, "\n%%%%+") ;
  1120.             roomleft = LINELENGTH - 3 ;
  1121.          } else {
  1122.             fprintf(bitfile, "%%%%DocumentFonts:") ;
  1123.             roomleft = LINELENGTH - 16 ;
  1124.          }
  1125.       }
  1126.       fprintf(bitfile, " %s", q) ;
  1127.       roomleft -= strlen(q) + 1 ;
  1128.    }
  1129.    fprintf(bitfile, "\n") ;
  1130. }
  1131.