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

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