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