home *** CD-ROM | disk | FTP | other *** search
/ Mega CD-ROM 1 / megacd_rom_1.zip / megacd_rom_1 / POSTSCRI / DVIPS54.ZIP / DVIPS / OUTPUT.C < prev    next >
C/C++ Source or Header  |  1990-11-25  |  15KB  |  609 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 "structures.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 FILE *search() ;
  15. extern char *getenv() ;
  16. extern void fonttableout() ;
  17. extern void makepsname() ;
  18. /*
  19.  *   These are the external variables used by these routines.
  20.  */
  21. extern integer hh, vv ;
  22. extern fontdesctype *curfnt ;
  23. extern FILE *bitfile ;
  24. extern char *oname ;
  25. extern Boolean reverse ;
  26. extern Boolean removecomments ;
  27. extern Boolean sendcontrolD, disablecomments, multiplesects ;
  28. extern Boolean usesPSfonts, headers_off ;
  29. extern Boolean safetyenclose ;
  30. extern int numcopies ;
  31. extern int totalpages ;
  32. extern integer pagenum ;
  33. extern Boolean manualfeed ;
  34. extern int landscape ;
  35. extern int quiet ;
  36. extern int prettycolumn ;
  37. extern int actualdpi ;
  38. extern char *iname ;
  39. extern char *paperfmt ;
  40. extern char *headerpath ;
  41. extern char errbuf[] ;
  42. extern shalfword linepos ;
  43. extern char *figpath ;
  44. extern struct header_list *ps_fonts_used ;
  45. extern char banner[] ;
  46. /*
  47.  *   We need a few statics to take care of things.
  48.  */
  49. static integer rhh, rvv ;
  50. static int instring ;
  51. static Boolean lastspecial = 1 ;
  52. static shalfword d ;
  53. static Boolean popened = 0 ;
  54. int lastfont ; /* exported to dospecial to fix rotate.tex problem */
  55. static void chrcmd();                   /* just a forward declaration */
  56. static char strbuffer[LINELENGTH + 20], *strbp = strbuffer ;
  57. static struct {
  58.     char *format;
  59.     int width, height;
  60. } paper_types[] = {
  61.     { "letter",  612,  792 },        /* 8.5 x 11 */
  62.     { "legal",   612, 1008 },        /* 8.5 x 14 */
  63.     { "ledger",  792, 1224 },        /* 11 x 17 */
  64.     { "a4",     596,  843 },        /* 210mm x 297mm */
  65.     { "a3",      843, 1192 } };        /* 297mm x 420mm */
  66. /*
  67.  *   This routine copies a file down the pipe.  Search path uses the
  68.  *   header path.
  69.  */
  70. static int infigure ;
  71. void
  72. copyfile(s)
  73.         char *s ;
  74. {
  75.    FILE *f ;
  76.    int c, prevc = '\n' ;
  77.  
  78.    switch (infigure) {
  79.    case 1:
  80.       f = search(figpath, s, READ) ;
  81.       (void)sprintf(errbuf, "Couldn't find figure file %s; continuing", s) ;
  82.       break ;
  83.    default:
  84.       f = search(headerpath, s, READ) ;
  85.       (void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
  86.       break ;
  87. #ifndef VMS
  88. #ifndef MSDOS
  89.    case 2:
  90.       f = popen(s, "r") ;
  91.       (void)sprintf(errbuf, "Failure to execute %s; continuing", s) ;
  92.       break;
  93. #endif
  94. #endif
  95.    }
  96.    if (f==NULL)
  97.       error(errbuf) ;
  98.    else {
  99.       if (! quiet) {
  100.          if (strlen(s) + prettycolumn > 76) {
  101.             fprintf(stderr, "\n") ;
  102.             prettycolumn = 0 ;
  103.          }
  104.          (void)fprintf(stderr, "<%s>", s) ;
  105.          (void)fflush(stderr) ;
  106.          prettycolumn += 2 + strlen(s) ;
  107.       }
  108.       if (linepos != 0)
  109.          (void)putc('\n', bitfile) ;
  110.       if (! disablecomments)
  111.          if (infigure)
  112.             (void)fprintf(bitfile, "%%%%BeginDocument: %s\n", s) ;
  113.          else
  114.             (void)fprintf(bitfile, "%%%%BeginProcSet: %s\n", s) ;
  115.       while ((c=getc(f))!=EOF && c != 4) {
  116.          if (! removecomments && c == '%' && prevc == '\n') {/* skip comments */
  117.             while ((c=getc(f))!=EOF) {
  118.                if (c=='\n')
  119.                   break ;
  120.             }
  121.          } else
  122.             (void)putc(c, bitfile) ;
  123.          prevc = c ;
  124.       }
  125.       if (prevc != '\n')
  126.          (void)putc('\n', bitfile) ;
  127.       linepos = 0 ;
  128. #ifndef VMS
  129. #ifndef MSDOS
  130.       if (infigure == 2)
  131.          (void)pclose(f) ;
  132.       else
  133. #endif
  134. #endif
  135.          (void)fclose(f) ;
  136.       if (!disablecomments)
  137.          if (infigure)
  138.             (void)fprintf(bitfile, "%%%%EndDocument\n") ;
  139.          else
  140.             (void)fprintf(bitfile, "%%%%EndProcSet\n") ;
  141.    }
  142. }
  143.  
  144. /*
  145.  *   For included PostScript graphics, we use the above routine, but
  146.  *   with no fatal error message.
  147.  */
  148. void figcopyfile(s, systemtype)
  149. char *s ;
  150. int systemtype ;
  151. {
  152.    infigure = systemtype ? 2 : 1 ;
  153.    copyfile(s) ;
  154.    infigure = 0 ;
  155. }
  156.  
  157. /*
  158.  *   This next routine writes out a `special' character.  In this case,
  159.  *   we simply put it out, since any special character terminates the
  160.  *   preceding token.
  161.  */
  162. void
  163. specialout(c)
  164.         char c ;
  165. {
  166.    if (linepos >= LINELENGTH) {
  167.       (void)putc('\n', bitfile) ;
  168.       linepos = 0 ;
  169.    }
  170.    (void)putc(c, bitfile) ;
  171.    linepos++ ;
  172.    lastspecial = 1 ;
  173. }
  174.  
  175. void
  176. stringend()
  177. {
  178.    if (linepos + instring >= LINELENGTH - 2) {
  179.       (void)putc('\n', bitfile) ;
  180.       linepos = 0 ;
  181.    }
  182.    (void)putc('(', bitfile) ;
  183.    *strbp = 0 ;
  184.    (void)fputs(strbuffer, bitfile) ;
  185.    (void)putc(')', bitfile) ;
  186.    linepos += instring + 2 ;
  187.    lastspecial = 1 ;
  188.    instring = 0 ;
  189.    strbp = strbuffer ;
  190. }
  191.  
  192. void
  193. scout(c)   /* string character out */
  194.         char c ;
  195. {
  196. /*
  197.  *   Is there room in the buffer?  LINELENGTH-6 is used because we
  198.  *   need room for (, ), and a possible four-byte string \000, for
  199.  *   instance.  If it is too long, we send out the string.
  200.  */
  201.    if (instring > LINELENGTH-6) {
  202.       stringend() ;
  203.       chrcmd('p') ;
  204.    }
  205.    if (c<' ' || c>126 || c=='%') {
  206.       *strbp++ = '\\' ;
  207.       *strbp++ = '0' + ((c >> 6) & 3) ;
  208.       *strbp++ = '0' + ((c >> 3) & 7) ;
  209.       *strbp++ = '0' + (c & 7) ;
  210.       instring += 4 ;
  211.    } else if (c == '(' || c == ')' || c == '\\') {
  212.       *strbp++ = '\\' ;
  213.       *strbp++ = c ;
  214.       instring += 2 ;
  215.    } else {
  216.       *strbp++ = c ;
  217.       instring++ ;
  218.    }
  219. }
  220.  
  221. void
  222. cmdout(s)
  223.         char *s ;
  224. {
  225.    int l ;
  226.  
  227.    /* hack added by dorab */
  228.    if (instring) {
  229.         stringend();
  230.         chrcmd('p');
  231.    }
  232.    l = strlen(s) ;
  233.    if ((! lastspecial && linepos >= LINELENGTH - 20) ||
  234.            linepos + l >= LINELENGTH) {
  235.       (void)putc('\n', bitfile) ;
  236.       linepos = 0 ;
  237.       lastspecial = 1 ;
  238.    } else if (! lastspecial) {
  239.       (void)putc(' ', bitfile) ;
  240.       linepos++ ;
  241.    }
  242.    (void)fputs(s, bitfile) ;
  243.    linepos += l ;
  244.    lastspecial = 0 ;
  245. }
  246.  
  247.  
  248. static void
  249. chrcmd(c)
  250.         char c ;
  251. {
  252.    if ((! lastspecial && linepos >= LINELENGTH - 20) ||
  253.        linepos + 2 > LINELENGTH) {
  254.       (void)putc('\n', bitfile) ;
  255.       linepos = 0 ;
  256.       lastspecial = 1 ;
  257.    } else if (! lastspecial) {
  258.       (void)putc(' ', bitfile) ;
  259.       linepos++ ;
  260.    }
  261.    (void)putc(c, bitfile) ;
  262.    linepos++ ;
  263.    lastspecial = 0 ;
  264. }
  265.  
  266. void
  267. floatout(n)
  268.         float n ;
  269. {
  270.    char buf[20] ;
  271.  
  272.    (void)sprintf(buf, "%.2f", n) ;
  273.    cmdout(buf) ;
  274. }
  275.  
  276. void
  277. numout(n)
  278.         integer n ;
  279. {
  280.    char buf[10] ;
  281.  
  282.    (void)sprintf(buf, "%ld", n) ;
  283.    cmdout(buf) ;
  284. }
  285.  
  286. void
  287. mhexout(p, len)
  288. register unsigned char *p ;
  289. register long len ;
  290. {
  291.    register char *hexchar = "0123456789ABCDEF" ;
  292.    register int n, k ;
  293.  
  294.    while (len > 0) {
  295.       if (linepos > LINELENGTH - 2) {
  296.          (void)putc('\n', bitfile) ;
  297.          linepos = 0 ;
  298.       }
  299.       k = (LINELENGTH - linepos) >> 1 ;
  300.       if (k > len)
  301.          k = len ;
  302.       len -= k ;
  303.       linepos += (k << 1) ;
  304.       while (k--) {
  305.          n = *p++ ;
  306.          (void)putc(hexchar[n >> 4], bitfile) ;
  307.          (void)putc(hexchar[n & 15], bitfile) ;
  308.       }
  309.    }
  310. }
  311.  
  312. void
  313. fontout(n)
  314.         int n ;
  315. {
  316.    char buf[6] ;
  317.  
  318.    if (instring) {
  319.       stringend() ;
  320.       chrcmd('p') ;
  321.    }
  322.    makepsname(buf, n) ;
  323.    cmdout(buf) ;
  324. }
  325.  
  326. void
  327. hvpos()
  328. {
  329.    if (rvv != vv) {
  330.       if (instring) {
  331.          stringend() ;
  332.          numout(hh) ;
  333.          numout(vv) ;
  334.          chrcmd('y') ;
  335.       } else if (rhh != hh) {
  336.          numout(hh) ;
  337.          numout(vv) ;
  338.          chrcmd('a') ;
  339.       } else { /* hard to get this case, but it's there when you need it! */
  340.          numout(vv - rvv) ;
  341.          chrcmd('x') ;
  342.       }
  343.       rvv = vv ;
  344.    } else if (rhh != hh) {
  345.       if (instring) {
  346.          stringend() ;
  347.          if (hh - rhh < 5 && rhh - hh < 5) {
  348.             chrcmd((char)('p' + hh - rhh)) ;
  349.          } else if (hh - rhh < d + 5 && rhh - hh < 5 - d) {
  350.             chrcmd((char)('g' + hh - rhh - d)) ;
  351.             d = hh - rhh ;
  352.          } else {
  353.             numout(hh - rhh) ;
  354.             chrcmd('b') ;
  355.             d = hh - rhh ;
  356.          }
  357.       } else {
  358.          numout(hh - rhh) ;
  359.          chrcmd('w') ;
  360.       }
  361.    }
  362.    rhh = hh ;
  363. }
  364.  
  365. /*
  366.  *   initprinter opens the bitfile and writes the initialization sequence
  367.  *   to it.
  368.  */
  369. void newline()
  370. {
  371.    if (linepos != 0) {
  372.       (void)fprintf(bitfile, "\n") ;
  373.       linepos = 0 ;
  374.    }
  375.    lastspecial = 1 ;
  376. }
  377.  
  378. void
  379. nlcmdout(s)
  380.         char *s ;
  381. {
  382.    newline() ;
  383.    cmdout(s) ;
  384.    newline() ;
  385. }
  386.  
  387. void
  388. initprinter()
  389. {
  390.    void tell_needed_fonts() ;
  391.    int i;
  392.    if (*oname != 0) {
  393. /*
  394.  *   We check to see if the first character is a exclamation
  395.  *   point, and popen if so.
  396.  */
  397.       if (*oname == '!' || *oname == '|') {
  398. #ifdef MSDOS
  399.             error("! can't open output pipe") ;
  400. #else
  401. #ifdef VMS
  402.             error("! can't open output pipe") ;
  403. #else
  404.          if ((bitfile=popen(oname+1, "w"))==NULL)
  405.             error("! couldn't open output pipe") ;
  406.          else
  407.             popened = 1 ;
  408. #endif
  409. #endif
  410.       } else {
  411.          if ((bitfile=fopen(oname,"w"))==NULL)
  412.             error("! couldn't open PostScript file") ;
  413.       }
  414.    } else {
  415.       bitfile = stdout ;
  416.    }
  417.    if (disablecomments)
  418.       (void)fprintf(bitfile,
  419.              "%%!PS (but not EPSF; comments have been disabled)\n") ;
  420.    else {
  421.       if (multiplesects)
  422.          (void)fprintf(bitfile,
  423.              "%%!PS (but not EPSF because of memory limits)\n") ;
  424.       else  (void)fprintf(bitfile, "%%!PS-Adobe-2.0\n") ;
  425.       (void)fprintf(bitfile, "%%%%Creator: %s", banner + 8) ;
  426.       if (*iname)
  427.          (void)fprintf(bitfile, "%%%%Title: %s\n", iname) ;
  428.       (void)fprintf(bitfile, "%%%%Pages: %d %d\n", totalpages, 1 - 2*reverse) ;
  429.       for (i=0; i<sizeof(paper_types)/sizeof(paper_types[0]); ++i)
  430.          if (strcmp(paperfmt,paper_types[i].format)==0)
  431.              (void)fprintf(bitfile, "%%%%BoundingBox: 0 0 %d %d\n",
  432.                  paper_types[i].width, paper_types[i].height) ;
  433.       tell_needed_fonts() ;
  434.       (void)fprintf(bitfile, "%%%%EndComments\n") ;
  435.    }
  436.    if (safetyenclose)
  437.       (void)fprintf(bitfile, "/SafetyEnclosure save def\n") ;
  438.    if (! headers_off)
  439.       send_headers() ;
  440. }
  441.  
  442. static int endprologsent ;
  443. void setup() {
  444.    newline() ;
  445.    if (endprologsent == 0 && !disablecomments) {
  446.       fonttableout() ;
  447.       (void)fprintf(bitfile, "%%%%EndProlog\n") ;
  448.       (void)fprintf(bitfile, "%%%%BeginSetup\n") ;
  449.       (void)fprintf(bitfile, "%%%%Feature: *Resolution %d\n", DPI) ;
  450.       if (manualfeed)
  451.          (void)fprintf(bitfile, "%%%%Feature: *ManualFeed True\n") ;
  452.    }
  453.    cmdout("TeXDict") ;
  454.    cmdout("begin") ;
  455.    {
  456.       char pft[100] ;
  457.       strcpy(pft, "@") ;
  458.       if (landscape)
  459.          strcat(pft, "landscape") ;
  460.       else
  461.          strcat(pft, paperfmt) ;
  462.       strcat(pft, " /") ;
  463.       strcat(pft, paperfmt) ;
  464.       strcat(pft, " where {pop ") ;
  465.       strcat(pft, paperfmt) ;
  466.       strcat(pft, "} if") ;
  467.       cmdout(pft) ;
  468.    }
  469.    if (manualfeed) cmdout("@manualfeed") ;
  470.    if (numcopies != 1) {
  471.       numout((integer)numcopies) ;
  472.       cmdout("@copies") ;
  473.    }
  474.    if (endprologsent == 0 && !disablecomments) {
  475.       newline() ;
  476.       endprologsent = 1 ;
  477.       (void)fprintf(bitfile, "%%%%EndSetup\n") ;
  478.    }
  479.  
  480. }
  481. /*
  482.  *   cleanprinter is the antithesis of the above routine.
  483.  */
  484. void
  485. cleanprinter()
  486. {
  487.    (void)fprintf(bitfile, "\n") ;
  488.    (void)fprintf(bitfile, "userdict /end-hook known{end-hook}if\n") ;
  489.    if (safetyenclose)
  490.       (void)fprintf(bitfile, "SafetyEnclosure restore\n") ;
  491.    if (!disablecomments)
  492.       (void)fprintf(bitfile, "%%%%EOF\n") ;
  493.    if (sendcontrolD)
  494.       (void)putc(4, bitfile) ;
  495. #ifndef MSDOS
  496. #ifndef VMS
  497.    if (popened)
  498.       (void)pclose(bitfile) ;
  499. #endif
  500. #endif
  501.    if (popened == 0)
  502.       (void)fclose(bitfile) ;
  503.    bitfile = NULL ;
  504. }
  505.  
  506. /* this tells dvips that it has no clue where it is. */
  507. static int thispage = 0 ;
  508. static integer rulex, ruley ;
  509. void psflush() {
  510.    rulex = ruley = rhh = rvv = -314159265 ;
  511.    lastfont = -1 ;
  512. }
  513. /*
  514.  *   pageinit initializes the output variables.
  515.  */
  516. void
  517. pageinit()
  518. {
  519.    psflush() ;
  520.    newline() ;
  521.    if (!disablecomments && !multiplesects)
  522.       (void)fprintf(bitfile, "%%%%Page: %ld %d\n", pagenum, ++thispage) ;
  523.    linepos = 0 ;
  524.    cmdout("bop") ;
  525.    d = 0 ;
  526. }
  527.  
  528.  
  529.  
  530. /*
  531.  *   This routine ends a page.
  532.  */
  533. void
  534. pageend()
  535. {
  536.    if (instring) {
  537.       stringend() ;
  538.       chrcmd('p') ;
  539.    }
  540.    cmdout("eop") ;
  541. }
  542.  
  543. /*
  544.  *   drawrule draws a rule at the specified position.
  545.  *   It does nothing to save/restore the current position,
  546.  *   or even draw the current string.  (Rules are normally
  547.  *   set below the baseline anyway, so this saves us on
  548.  *   output size almost always.)
  549.  */
  550. void
  551. drawrule(rw, rh)
  552.         integer rw, rh ;
  553. {
  554.    numout((integer)hh) ;
  555.    numout((integer)vv) ;
  556.    if (rw == rulex && rh == ruley)
  557.       chrcmd('V') ;
  558.    else {
  559.       numout((integer)rw) ;
  560.       numout((integer)rh) ;
  561.       chrcmd('v') ;
  562.       rulex = rw ;
  563.       ruley = rh ;
  564.    }
  565. }
  566.  
  567. /*
  568.  *   drawchar draws a character at the specified position.
  569.  */
  570. void
  571. drawchar(c, cc)
  572.         chardesctype *c ;
  573.         int cc ;
  574. {
  575.    hvpos() ;
  576.    if (lastfont != curfnt->psname) {
  577.       fontout((int)curfnt->psname) ;
  578.       lastfont = curfnt->psname ;
  579.    }
  580.    scout(cc) ;
  581.    rhh = hh + c->pixelwidth ; /* rvv = rv */
  582. }
  583. /*
  584.  *   This routine sends out the document fonts comment.
  585.  */
  586. void tell_needed_fonts() {
  587.    struct header_list *hl = ps_fonts_used ;
  588.    char *q ;
  589.    int roomleft = -1 ;
  590.    extern char *get_name() ;
  591.  
  592.    if (hl == 0)
  593.       return ;
  594.    while (q=get_name(&hl)) {
  595.       if ((int)strlen(q) >= roomleft) {
  596.          if (roomleft != -1) {
  597.             fprintf(bitfile, "\n%%%%+") ;
  598.             roomleft = LINELENGTH - 3 ;
  599.          } else {
  600.             fprintf(bitfile, "%%%%DocumentFonts:") ;
  601.             roomleft = LINELENGTH - 16 ;
  602.          }
  603.       }
  604.       fprintf(bitfile, " %s", q) ;
  605.       roomleft -= strlen(q) + 1 ;
  606.    }
  607.    fprintf(bitfile, "\n") ;
  608. }
  609.