home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume24 / psroff3.0 / part04 / ps.c < prev   
Encoding:
C/C++ Source or Header  |  1991-10-09  |  19.5 KB  |  753 lines

  1. /*
  2.     Copyright 1985, 1986, 1987, 1988, 1989, 1990, 1991 Chris Lewis
  3.         All Rights Reserved
  4.  
  5.     See the LICENSE file for a full description of restrictions under which
  6.     this software is provided.
  7.  
  8.     Function:        PostScript driver
  9.  */
  10.  
  11. #include "defs.h"
  12.  
  13. #ifdef    PS
  14. #include "ps.h"
  15.  
  16. #ifndef    lint
  17. static char SCCSid[] =
  18.     "@(#)ps.c: 2.12 Copyright 91/03/25 23:20:43 Chris Lewis";
  19. #endif
  20.  
  21. /*    ps.c will generate some additional "print" commands to cause
  22.     the printer to "print" back who did the job, and how long it
  23.     took.  define NOCHATTER if you don't want this.
  24.  */
  25. static long charCount;
  26.  
  27. #ifdef    FORM
  28. static char Overlay[100] = {""};
  29. #endif
  30.  
  31. #define    USED    01
  32.  
  33. struct troff2befont psStdFont[108] = {
  34.  
  35. /*    Note on X-shift, Y-shift and point scale factor:
  36.     The first two are shifts in the baseline position of the
  37.     character, and the third is a multiplier of the point size.
  38.     If they are zero, nothing happens.  If they are non-zero,
  39.     they are first multiplied by .01, then (in the case of the
  40.     shifts), multiplied by the current points to get a shift
  41.     value in TROFF2PS[XY] coordinates.  In the case of point scale
  42.     factor, it is multiplied by <currentpointsize> * .01 and becomes
  43.     the pointsize of the sequence to be emitted.
  44.  */
  45. /*          +-------------------------------- Troff character number
  46.         |
  47.             |    +--------------------------- N: standard fonts
  48.             |    |                            S: symbol font
  49.             |    |                            D: draw macro
  50.             |    |                            n: new font
  51.             |    |
  52.             |    |  +------------------------ X-shift
  53.             |    |  |                         Note: positive is right.
  54.             |    |  |
  55.             |    |  |  +--------------------- Y-shift
  56.             |    |  |  |                      Note: positive is up.
  57.             |    |  |  |
  58.             |    |  |  |  +------------------ Point scale factor
  59.             |    |  |  |  |
  60.             |    |  |  |  |   +-------------- Sequence
  61.             |    |  |  |  |   |
  62.             v    v  v  v  v   v */
  63.     /*  0*/    {N, 0, 0, 0, "h"},
  64.     /*  1*/    {N, 0, 0, 0, "t"},
  65.     /*  2*/    {N, 0, 0, 0, "n"},
  66.     /*  3*/    {N, 0, 0, 0, "m"},
  67.     /*  4*/    {N, 0, 0, 0, "l"},
  68.     /*  5*/    {N, 0, 0, 0, "i"},
  69.     /*  6*/    {N, 0, 0, 0, "z"},
  70.     /*  7*/    {N, 0, 0, 0, "s"},
  71.     /*  8*/    {N, 0, 0, 0, "d"},
  72.     /*  9*/    {N, 0, 0, 0, "b"},
  73.     /* 10*/    {N, 0, 0, 0, "x"},
  74.     /* 11*/    {N, 0, 0, 0, "f"},
  75.     /* 12*/    {N, 0, 0, 0, "j"},
  76.     /* 13*/    {N, 0, 0, 0, "u"},
  77.     /* 14*/    {N, 0, 0, 0, "k"},
  78.     /* 15*/    {N, 0, 0, 0, NOC},
  79.     /* 16*/    {N, 0, 0, 0, "p"},
  80.     /* 17*/    {D, 0, 0, 0, "do34em"},
  81.     /* 18*/    {N, 0, 0, 0, ";"},
  82.     /* 19*/    {N, 0, 0, 0, NOC},
  83.     /* 20*/    {N, 0, 0, 0, "a"},
  84.     /* 21*/    {N, 0, 0, 0, "_"},
  85.     /* 22*/    {N, 0, 0, 0, "c"},
  86.     /* 23*/    {N, 0, 0, 0, "`"},
  87.     /* 24*/    {N, 0, 0, 0, "e"},
  88.     /* 25*/    {N, 0, 0, 0, "'"},
  89.     /* 26*/    {N, 0, 0, 0, "o"},
  90.     /* 27*/    {D, 0, 0, 0, "do14"},
  91.     /* 28*/    {N, 0, 0, 0, "r"},
  92.     /* 29*/    {D, 0, 0, 0, "do12"},
  93.     /* 30*/    {N, 0, 0, 0, "v"},
  94.     /* 31*/    {N, 0, 0, 0, "-"},
  95.     /* 32*/    {N, 0, 0, 0, "w"},
  96.     /* 33*/    {N, 0, 0, 0, "q"},
  97.     /* 34*/    {N, 0, 0, 0, "/"},
  98.     /* 35*/    {N, 0, 0, 0, "."},
  99.     /* 36*/    {N, 0, 0, 0, "g"},
  100.     /* 37*/    {D, 0, 0, 0, "do34"},
  101.     /* 38*/    {N, 0, 0, 0, ","},
  102.     /* 39*/    {N, 0, 0, 0, "&"},
  103.     /* 40*/    {N, 0, 0, 0, "y"},
  104.     /* 41*/    {N, 0, 0, 0, NOC},
  105.     /* 42*/    {N, 0, 0, 0, "%"},
  106.     /* 43*/    {N, 0, 0, 0, NOC},
  107.     /* 44*/    {N, 0, 0, 0, "Q"},
  108.     /* 45*/    {N, 0, 0, 0, "T"},
  109.     /* 46*/    {N, 0, 0, 0, "O"},
  110.     /* 47*/    {N, 0, 0, 0, "H"},
  111.     /* 48*/    {N, 0, 0, 0, "N"},
  112.     /* 49*/    {N, 0, 0, 0, "M"},
  113.     /* 50*/    {N, 0, 0, 0, "L"},
  114.     /* 51*/    {N, 0, 0, 0, "R"},
  115.     /* 52*/    {N, 0, 0, 0, "G"},
  116.     /* 53*/    {N, 0, 0, 0, "I"},
  117.     /* 54*/    {N, 0, 0, 0, "P"},
  118.     /* 55*/    {N, 0, 0, 0, "C"},
  119.     /* 56*/    {N, 0, 0, 0, "V"},
  120.     /* 57*/    {N, 0, 0, 0, "E"},
  121.     /* 58*/    {N, 0, 0, 0, "Z"},
  122.     /* 59*/    {N, 0, 0, 0, "D"},
  123.     /* 60*/    {N, 0, 0, 0, "B"},
  124.     /* 61*/    {N, 0, 0, 0, "S"},
  125.     /* 62*/    {N, 0, 0, 0, "Y"},
  126.     /* 63*/    {N, 0, 0, 0, "F"},
  127.     /* 64*/    {N, 0, 0, 0, "X"},
  128.     /* 65*/    {N, 0, 0, 0, "A"},
  129.     /* 66*/    {N, 0, 0, 0, "W"},
  130.     /* 67*/    {N, 0, 0, 0, "J"},
  131.     /* 68*/    {N, 0, 0, 0, "U"},
  132.     /* 69*/    {N, 0, 0, 0, "K"},
  133.     /* 70*/    {N, 0, 0, 0, "0"},
  134.     /* 71*/    {N, 0, 0, 0, "1"},
  135.     /* 72*/    {N, 0, 0, 0, "2"},
  136.     /* 73*/    {N, 0, 0, 0, "3"},
  137.     /* 74*/    {N, 0, 0, 0, "4"},
  138.     /* 75*/    {N, 0, 0, 0, "5"},
  139.     /* 76*/    {N, 0, 0, 0, "6"},
  140.     /* 77*/    {N, 0, 0, 0, "7"},
  141.     /* 78*/    {N, 0, 0, 0, "8"},
  142.     /* 79*/    {N, 0, 0, 0, "9"},
  143.     /* 80*/    {N, 0, 0, 0, "*"},
  144.     /* 81*/    {N, 0, 0, 0, "\261"},
  145.     /* 82*/    {N, 0, 0, 0, "\256"},
  146.     /* 83*/    {N, 0, 0, 0, "\257"},
  147.     /* 84*/    {D, 0, 0, 0, "doff"},
  148.     /* 85*/    {N, 0, 0, 0, "\242"},
  149.     /* 86*/    {D, 0, 0, 0, "doFl"},
  150.     /* 87*/    {D, 0, 0, 0, "doFi"},
  151.     /* 88*/    {N, 0, 0, 0, "("},
  152.     /* 89*/    {N, 0, 0, 0, ")"},
  153.     /* 90*/    {N, 0, 0, 0, "["},
  154.     /* 91*/    {N, 0, 0, 0, "]"},
  155.     /* 92*/    {S, 0, 0, 0, "\260"},
  156.     /* 93*/    {N, 0, 0, 0, "\262"},
  157.     /* 94*/    {N, 0, 0, 0, "="},
  158.     /* 95*/    {S, 0, 0, 0, "\322"},
  159.     /* 96*/    {N, 0, 0, 0, ":"},
  160.     /* 97*/    {N, 0, 0, 0, "+"},
  161.     /* 98*/    {N, 0, 0, 0, NOC},
  162.     /* 99*/    {N, 0, 0, 0, "!"},
  163.     /*100*/    {N, 0, 0, 0, "\267"},
  164.     /*101*/    {N, 0, 0, 0, "?"},
  165.     /*102*/    {S, 0, 0, 0, "\242"},
  166.     /*103*/    {N, -60, 0, 0, "|"},
  167.     /*104*/    {N, 0, 0, 0, NOC},
  168.     /*105*/    {S, 0, 0, 0, "\323"},
  169.     /*106*/    {D, 0, 0, 0, "dosq"},
  170.     /*107*/    {N, 0, 0, 0, "$"},
  171.     };
  172.  
  173. struct troff2befont psSymFont[] = {
  174. /*          +-------------------------------- Troff character number
  175.         |
  176.             |    +--------------------------- N: standard fonts
  177.             |    |                            S: symbol font
  178.             |    |                            D: draw macro
  179.             |    |                            n: new font
  180.             |    |
  181.             |    |  +------------------------ X-shift (scaled by point)
  182.             |    |  |                         Note: positive is right.
  183.             |    |  |
  184.             |    |  |  +--------------------- Y-shift (scaled by point)
  185.             |    |  |  |                      Note: positive is up.
  186.             |    |  |  |
  187.             |    |  |  |  +------------------ Point scale factor
  188.             |    |  |  |  |
  189.             |    |  |  |  |   +-------------- Sequence
  190.             |    |  |  |  |   |
  191.             v    v  v  v  v   v */
  192.     /*  0*/    {S, 0, 0, 0, "\171"},
  193.     /*  1*/    {S, 0, 0, 0, "\161"},
  194.     /*  2*/    {S, 0, 0, 0, "\156"},
  195.     /*  3*/    {S, 0, 0, 0, "\155"},
  196.     /*  4*/    {S, 0, 0, 0, "\154"},
  197.     /*  5*/    {S, 0, 0, 0, "\151"},
  198.     /*  6*/    {S, 0, 0, 0, "\172"},
  199.     /*  7*/    {S, 0, 0, 0, "\163"},
  200.     /*  8*/    {S, 0, 0, 0, "\144"},
  201.     /*  9*/    {S, 0, 0, 0, "\142"},
  202.     /* 10*/    {S, 0, 0, 0, "\170"},
  203.     /* 11*/    {S, 0, 0, 0, "\150"},
  204.     /* 12*/    {S, 0, 0, 0, "\146"},
  205.     /* 13*/    {S, 0, 0, 0, "\165"},
  206.     /* 14*/    {S, 0, 0, 0, "\153"},
  207.     /* 15*/    {S, 0, 0, 0, NOC},
  208.     /* 16*/    {S, 0, 0, 0, "\160"},
  209.     /* 17*/    {N, 0, 0, 0, "@"},
  210.     /* 18*/    {S, 0, 0, 0, "\257"},
  211.     /* 19*/    {S, 0, 0, 0, NOC},
  212.     /* 20*/    {S, 0, 0, 0, "\141"},
  213.     /* 21*/    {S, 0, 0, 0, "\174"},
  214.     /* 22*/    {S, 0, 0, 0, "\143"},
  215.     /* 23*/    {N, 0, 0, 0, "\042"},
  216.     /* 24*/    {S, 0, 0, 0, "\145"},
  217.     /* 25*/    {S, 0, 0, 0, "\075"},
  218.     /* 26*/    {S, 0, 0, 0, "\157"},
  219.     /* 27*/    {S, 0, 0, 0, "\254"},
  220.     /* 28*/    {S, 0, 0, 0, "\162"},
  221.     /* 29*/    {S, 0, 0, 0, "\255"},
  222.     /* 30*/    {S, 0, 0, 0, "\164"},
  223.     /* 31*/    {4, 0, 0, 0, "O"},
  224.     /* 32*/    {N, 0, 0, 0, "\134"},
  225.     /* 33*/    {S, 0, 0, 0, "\131"},
  226.     /* 34*/    {D, 0, 0, 0, "BellSymbol"},
  227.     /* 35*/    {S, 0, 0, 0, "\245"},
  228.     /* 36*/    {S, 0, 0, 0, "\147"},
  229.     /* 37*/    {S, 0, 0, 0, "\312"},
  230.     /* 38*/    {S, 0, 0, 0, "\265"},
  231.     /* 39*/    {S, 0, 0, 0, "\336"},
  232.     /* 40*/    {S, 0, 0, 0, "\167"},
  233.     /* 41*/    {S, 0, 0, 0, NOC},
  234.     /* 42*/    {S, 0, 0, 0, "\321"},
  235.     /* 43*/    {S, 0, 0, 0, NOC},
  236.     /* 44*/    {S, 0, 0, 0, "\106"},
  237.     /* 45*/    {S, 0, 0, 0, "\121"},
  238.     /* 46*/    {S, 0, 0, 0, "\127"},
  239.     /* 47*/    {S, 0, 0, 0, "\310"},
  240.     /* 48*/    {4, 0, 0, 0, "M"},
  241.     /* 49*/    {S, 0, 0, 0, "\126"},
  242.     /* 50*/    {S, 0, 0, 0, "\114"},
  243.     /* 51*/    {S, 0, 0, 0, "\055"},
  244.     /* 52*/    {S, 0, 0, 0, "\107"},
  245.     /* 53*/    {S, 0, 0, 0, "\362"},
  246.     /* 54*/    {S, 0, 0, 0, "\120"},
  247.     /* 55*/    {S, 0, 0, 0, "\314"},
  248.     /* 56*/    {S, 0, 0, 0, "\311"},
  249.     /* 57*/    {N, 0, 0, 0, "\176"},
  250.     /* 58*/    {S, 0, 0, 0, "\266"},
  251.     /* 59*/    {S, 0, 0, 0, "\104"},
  252.     /* 60*/    {S, 0, 0, 0, "\326"},
  253.     /* 61*/    {S, 0, 0, 0, "\123"},
  254.     /* 62*/    {S, 0, 0, 0, "\273"},
  255.     /* 63*/    {S, 0, 0, 0, "\076"},
  256.     /* 64*/    {S, 0, 0, 0, "\130"},
  257.     /* 65*/    {S, 0, 0, 0, "\074"},
  258.     /* 66*/    {S, 0, 0, 0, "\244"},
  259.     /* 67*/    {S, 0, 0, 0, "\307"},
  260.     /* 68*/    {S, 0, 0, 0, "\125"},
  261.     /* 69*/    {S, 0, 0, 0, "\330"},
  262.     /* 70*/    {4, 0, 0, 0, "J"},
  263.     /* 71*/    {4, 0, 0, 0, "B"},
  264.     /* 72*/    {4, 0, 0, 0, "A"},
  265.     /* 73*/    {4, 0, 0, 0, "C"},
  266.     /* 74*/    {4, 0, 0, 0, "D"},
  267.     /* 75*/    {4, 0, 0, 0, "E"},
  268.     /* 76*/    {4, 0, 0, 0, "F"},
  269.     /* 77*/    {4, 0, 0, 0, "G"},
  270.     /* 78*/    {4, 0, 0, 0, "K"},
  271.     /* 79*/    {4, 0, 0, 0, "I"},
  272.     /* 80*/    {4, 0, 0, 0, "H"},
  273.     /* 81*/    {S, 0, 0, 0, "\264"},
  274.     /* 82*/    {S, 0, 0, 0, "\270"},
  275.     /* 83*/    {S, 0, 0, 0, "\261"},
  276.     /* 84*/    {S, 0, 0, 0, "\243"},
  277.     /* 85*/    {S, 0, 0, 0, "\263"},
  278.     /* 86*/    {S, 0, 0, 0, "\272"},
  279.     /* 87*/    {S, 0, 0, 0, "\271"},
  280.     /* 88*/    {S, 0, 0, 0, "\173"},
  281.     /* 89*/    {S, 0, 0, 0, "\175"},
  282.     /* 90*/    {N, 0, 0, 0, "\302"},
  283.     /* 91*/    {N, 0, 0, 0, "\301"},
  284.     /* 92*/    {N, 0, 0, 0, "\303"},
  285.     /* 93*/    {N, 0, 0, 0, "\043"},
  286.     /* 94*/    {S, 0, 0, 0, "\334"},
  287.     /* 95*/    {S, 0, 0, 0, "\316"},
  288.     /* 96*/    {N, 0, 0, 0, "\304"},
  289.     /* 97*/    {S, 0, 0, 0, "\306"},
  290.     /* 98*/    {S, 0, 0, 0, NOC},
  291.     /* 99*/    {N, 0, 0, 0, "\263"},
  292.     /*100*/    {4, 0, 0, 0, "L"},
  293.     /*101*/    {S, 0, 0, 0, "\052"},
  294.     /*102*/    {S, 0, 0, 0, "\315"},
  295.     /*103*/    {4, 0, 0, 0, "N"},
  296.     /*104*/    {S, 0, 0, 0, NOC},
  297.     /*105*/    {S, 0, 0, 0, "\053"},
  298.     /*106*/    {S, 0, 0, 0, "\256"},
  299.     /*107*/    {N, 0, 0, 0, "\247"},
  300. };
  301.  
  302. psPage() {
  303.     if (!currentPage)
  304.     return;
  305.     printf("hits misses\n");
  306.     printf("PageSave restore\n");
  307.     printf("/misses exch def /hits exch def\n");
  308.     printf("ShowPage\n");
  309.     pagePending = 1;
  310. }
  311.  
  312. static
  313. doPageStart() {
  314.     currentPage++;
  315.     printf("%%%%Page: ? %d\n", currentPage);
  316. #ifdef    FORM
  317.     printf("/Form { %s } def\n",
  318.     Overlay[0] == '+' ? (Overlay[0] = '\0', Overlay+1) : Overlay);
  319. #endif
  320.     printf("/PageSave save def\n");
  321.     pagePending = 0;
  322.     printf("StartPage\n");
  323. }
  324.  
  325. psSetFont(font, points)
  326. int font, points; {
  327.     if (lastPoints != points || font != lastFont) {
  328.     struct fonttable *fp = &fonttable[font];
  329.     if (fp->fontSeq && *fp->fontSeq && !(fp->flags&USED)) {
  330.         char buffer[512];
  331.         int n;
  332.         FILE *f = fopen(fp->fontSeq, "r");
  333.         if (!f) {
  334.         fprintf(stderr, "%s: cannot open fontfile %s\n",
  335.             progname, fp->fontSeq);
  336.         } else {
  337.         DBP((D_BEND,"Downloading %s\n", fp->fontSeq));
  338.         while((n = fread(buffer, 1, sizeof(buffer), f)) > 0) {
  339.             fwrite(buffer, 1, n, stdout);
  340.         }
  341.         fclose(f);
  342.         }
  343.     }
  344.  
  345.     fp->flags |= USED;
  346. #ifdef    FONTMACRO
  347.     printf("/%s %d SetFont\n", fp->fontName, points);
  348. #else
  349.     printf("/%s dup /curFont exch def findfont\n",
  350.         fp->fontName);
  351.     printf("%d dup /curPoints exch def scalefont setfont\n", points);
  352. #endif
  353.     lastPoints = points;
  354.     lastFont = font;
  355.     }
  356. }
  357.  
  358. psChar(x, y, font, points, troffChar, sequence)
  359. int x, y;
  360. int font, points, troffChar;
  361. register char *sequence; {
  362.     register int nx = TROFF2PSX(x), ny = TROFF2PSY(y);
  363.     register struct troff2befont *rp;
  364.  
  365.     if (pagePending) {
  366.     resetState();
  367.     doPageStart();
  368.     }
  369.  
  370.     charCount++;
  371.  
  372.     DBP((D_BEND,"BEFORE (troffChar,x,y,font,points) = (%d,%d,%d,%d,%d)\n",
  373.     troffChar, x, y, font, points));
  374.     if (font < 0) {
  375.     font = -font-1;
  376.     rp = &extchars[troffChar];
  377.     } else if (font == symidx)
  378.     rp = &be->besymfont[troffChar];
  379.     else
  380.     rp = &be->bestdfont[troffChar];
  381.  
  382.     switch(rp->t2b_font) {
  383.     /* Only fonts with "N" are subject to font translation */
  384.     case N:
  385.         if (font == symidx)
  386.         font = 0;    /* Special chars are Courier */
  387.         else {
  388.         DBP((D_BEND,"psSetChar %d->%s (%s)\n", font,
  389.             xlatetable[font]->troffName,
  390.             xlatetable[font]->fontName));
  391.         font = xlatetable[font] - fonttable;
  392.         }
  393.         break;
  394.     case S:
  395.         font = 3;
  396.         break;
  397.     case D:
  398.         break;
  399.     default:
  400.         /* Typically used when the R and S fonts don't have the
  401.            character desired, so select the font via the index
  402.            in the fonts.?? file */
  403.         font = rp->t2b_font;
  404.         break;
  405.     }
  406.  
  407.     skipfontset:
  408.  
  409.     if (!sequence)
  410.     sequence = rp->t2b_charseq;
  411.  
  412.     if (!sequence) {
  413.     fprintf(stderr, "No coding for %d\n", troffChar);
  414.     return;
  415.     }
  416.  
  417.     /*    We're committed now - the "if" statements avoid floating
  418.     arithmetic on slow machines */
  419.  
  420.     if (rp->t2b_scale) points *= (.01 * rp->t2b_scale);
  421.     if (rp->t2b_xc) nx += points * (.01 * rp->t2b_xc);
  422.     if (rp->t2b_yc) ny += points * (.01 * rp->t2b_yc);
  423.  
  424.     psSetFont(font, points);
  425.  
  426.     DBP((D_BEND,"AFTER (sequence,x,y,font,points) = (%s,%d,%d,%d,%d)\n",
  427.     sequence, nx, ny, font, points));
  428.  
  429.     if (rp->t2b_font == D) {
  430.     emitnums(nx);
  431.     emitnums(ny);
  432.     putnl(sequence);
  433.     } else {
  434.     emitnum(nx);
  435.     if (lastYPos != ny) {
  436.         putchar(' ');
  437.         emitnum(ny);
  438.     }
  439.     putchar('(');
  440.     while(*sequence) {
  441.         if ((*sequence)&0x80)
  442.         printf("\\%03o", (*sequence++)&0xff);
  443.         else if (*sequence == '(' || *sequence == ')' ||
  444.         *sequence == '\\')
  445.         printf("\\%c", *sequence++);
  446.         else
  447.         putchar(*sequence++);
  448.     }
  449.     putchar(')');
  450.     if (lastYPos != ny) {
  451.         lastYPos = ny;
  452.         putchar('Y');
  453.     } else
  454.         putchar('X');
  455.     putchar('\n');
  456.     }
  457. }
  458.  
  459. /*    Specialized emit routine:
  460.     outputs number divided by PSSCALEFACTOR, rounded to the first
  461.     decimal place without using floats/double
  462.  */
  463. emitnums(val)
  464. register int val; {
  465.     emitnum(val);
  466.     putchar(' ');
  467. }
  468. emitnum(val)
  469. register int val; {
  470.     register int neg;
  471.     if (val < 0) {
  472.     neg = 1;
  473.     val = -val;
  474.     } else {
  475.     neg = 0;
  476.     }
  477.     if (neg)
  478.     putchar('-');
  479.     printf("%d", val / PSSCALEFACTOR);
  480.     val = ((val % PSSCALEFACTOR) * 10 /*+ (PSSCALEFACTOR / 2)*/) /
  481.     PSSCALEFACTOR;
  482.     if (val)
  483.     printf(".%d", val);
  484. }
  485. putnl(s)
  486. char *s; {
  487.     fputs(s, stdout);
  488.     putchar('\n');
  489. }
  490.  
  491. extern char nodename[];
  492.  
  493. psProlog() {
  494.     extern char *ctime();
  495.     extern char *strchr();
  496. #ifdef    DIT
  497.     extern int indtres;
  498. #endif
  499.     char buffer[30];
  500.     FILE *library;
  501.     long curtime;
  502.  
  503.     currentPage = 0;
  504.     pagePending = 1;
  505.  
  506.     library = libopen(printer, "lib");
  507.  
  508.     time(&curtime);
  509.     strcpy(buffer, ctime(&curtime));
  510.     *strchr(buffer, '\n') = '\0';
  511.     getnodename();
  512.  
  513.     printf("%%!PS-Adobe-1.0\n");
  514.     printf("%%%%Title: (stdin)\n");
  515.     printf("%%%%Creator: %s %s\n", progname, shortversion);
  516.     printf("%%%%PsroffVersion: %s\n", version);
  517.     printf("%%%%CreationDate: %s\n", buffer);
  518.     printf("%%%%For: %s\n", username);
  519.     printf("%%%%Pages: (atend)\n");
  520.     printf("%%%%DocumentFonts: (atend)\n");
  521.     printf("%%%%EndComments\n");
  522.     printf("/GlobalSave save def\n");
  523.     printf("/hits 0 def /misses 0 def\n");
  524.     /* special backends (eg: psfig) need this */
  525.     printf("/resolution %d def\n",
  526. #ifdef    DIT
  527.     ditroff? indtres:
  528. #endif
  529.     TROFFRESOLUTION);
  530. #ifndef    NOCHATTER
  531.     /* compatibility with behandler.ps */
  532.     printf("statusdict /jobname (%s@%s %s %s %s) def\n",
  533.     username, nodename, buffer, progname, shortversion);
  534.     printf("(%s@%s %s %s %s\\n) print\n", username, nodename, buffer,
  535.     progname, shortversion);
  536.     printf("flush\n");
  537. #endif
  538.     printf("usertime /btime exch def\n");
  539.     psXlate(library);
  540.     doprologs();
  541.     printf("%%%%EndProlog\n");
  542.     fclose(library);
  543. }
  544.  
  545. psEpilog() {
  546.     int i;
  547.     if (!currentPage)
  548.     return;
  549.     printf("%%%%Trailer\n");
  550.     if (metrics)
  551.     printf("%d metrics\n", charCount);
  552. #ifndef    NOCHATTER
  553.     printf("(Execution time (seconds): ) print\n");
  554.     printf("usertime btime sub 0.001 mul (          ) cvs print\n");
  555.     printf("(; Pages: %d) print\n", currentPage);
  556.     printf("(\\n) print\n");
  557.     printf("flush\n");
  558. #endif
  559.     /* If in display postscript */
  560.     printf("DPS? { (^D to exit\\n) print } if\n");
  561.     printf("GlobalSave restore\n");
  562.     printf("%%%%DocumentFonts:");
  563.     for (i = 0; i < MAXFONTS; i++)
  564.     if (fonttable[i].flags&USED)
  565.         printf(" %s", fonttable[i].fontName);
  566.     printf("\n");
  567.     printf("%%%%Pages: %d\n", currentPage);
  568. #ifndef    NOCONTROLD
  569.     fputs(pstrailer, stdout);
  570. #endif
  571. }
  572.  
  573. psXlate(library)
  574. FILE *library; {
  575.     char buf[512];
  576.     while (fgets(buf, sizeof(buf), library))
  577.     if (0 == strncmp(buf, "%%%", 3))
  578.         interp(&buf[3], psXlate, "ps");
  579.     else
  580.         /* some backends don't like extra %! - eg: PageView */
  581.         if (0 == strncmp(buf, "%!", 2)) {
  582.         buf[1] = '%';
  583.         fputs(&buf[1], stdout);
  584.         } else
  585.         fputs(buf, stdout);
  586. }
  587.  
  588. psOverlay(overlay)
  589. char *overlay; {
  590. #ifdef    FORM
  591.     strcpy(Overlay, overlay);
  592.     printf("%%%%%%Form set: %s\n", Overlay);
  593. #endif
  594. }
  595.  
  596. #ifdef    INSPECIAL
  597.  
  598. static
  599. require(need, have, cmd, string)
  600. int need, have;
  601. char *cmd, *string; {
  602.     if (need != have) {
  603.     fprintf(stderr, "%s: need %d argument%s to draw a %s (%s)\n",
  604.         progname, need, need == 1? "": "s", cmd, string);
  605.     return(1);
  606.     } else
  607.     return(0);
  608. }
  609.  
  610. /*    Do ditroff drawing command in s from origX,origY.
  611.     If opcode 0 just moveto
  612.  */
  613. psDraw(origX, origY, opcode, ctindex, numbers, saves)
  614. int origX, origY;
  615. int opcode;
  616. char *saves;
  617. int ctindex;
  618. short *numbers; {
  619.  
  620.     int i, fill = 0;
  621.     static float curfill = 0;
  622.     int curthick = 1;
  623.  
  624.     /* map absolute beginning position. */
  625.     origX = TROFF2PSX(origX);
  626.     origY = TROFF2PSY(origY);
  627.  
  628.     switch (opcode) {
  629.     case 'f':
  630.         if (ctindex == 2)
  631.         ctindex = 1;
  632.         if (!require(1, ctindex, "set fill", saves))
  633.         curfill = (double) numbers[0] / 1000;
  634.         return;
  635.     case 't':
  636.         if (ctindex == 2)
  637.         ctindex = 1;
  638.         if (!require(1, ctindex, "set thick", saves))
  639.         curthick = numbers[0];
  640.         return;
  641.     }
  642.     if (opcode)
  643.     putnl("newpath");
  644.     emitnums(origX);
  645.     emitnums(origY);
  646.     putnl("moveto");
  647.     if (!opcode)
  648.     return;
  649.  
  650.     DBP((D_CAT, "psDraw: (%d,%d): %s\n", origX, origY, saves));
  651.  
  652.     switch (opcode) {
  653.     case 'C':
  654.         if (ctindex == 2)
  655.         ctindex = 1;
  656.     case 'E':
  657.     case 'P':
  658.         fill = 1;
  659.         if (opcode != 'P')
  660.         break;
  661.     case 'l':
  662.     case 'a':
  663.     case 'p':
  664.     case '~':
  665.         for (i = 1; i < ctindex; i += 2)
  666.         numbers[i] = -numbers[i];
  667.     }
  668.     switch(opcode) {
  669.     case 'l':
  670.         if (require(2, ctindex, "line", saves))
  671.         return;
  672.         DBP((D_CAT, "drawline: %d, %d\n", numbers[0], numbers[1]));
  673.         emitnums((int) numbers[0]);
  674.         emitnums((int) numbers[1]);
  675.         putnl("rlineto");
  676.         break;
  677.     case 'a':
  678.         if (require(4, ctindex, "arc", saves))
  679.         return;
  680.         for (i = 0; i < 4; i++) {
  681.         emitnums(numbers[i]);
  682.         }
  683.         putnl("Arc");
  684.         break;
  685.     case 'C':
  686.     case 'c':
  687.         if (require(1, ctindex, "circle", saves))
  688.         return;
  689.         numbers[1] = numbers[0];
  690.         ctindex++;
  691.     case 'E':
  692.     case 'e':
  693.         if (require(2, ctindex, "ellipse", saves))
  694.         return;
  695.         DBP((D_CAT, "drawellipse: %d, %d\n", numbers[0], numbers[1]));
  696.         emitnums((int) numbers[0]);
  697.         emitnums((int) numbers[1]);
  698.         putnl("Ellipse");
  699.         break;
  700.     case 'P':
  701.     case 'p':
  702.         if (ctindex&1) {
  703.         fprintf(stderr, "%s: even number of points for polygon: %s\n",
  704.             progname, saves);
  705.         break;
  706.         }
  707.         for (i = 0; i < ctindex; i += 2) {
  708.         emitnums((int) numbers[i]);
  709.         emitnums((int) numbers[i+1]);
  710.         putnl("rlineto");
  711.         }
  712.         putnl(" closepath");
  713.         break;
  714.     case '~':
  715.         if (ctindex < 4) {
  716.         fprintf(stderr, "%s: too few points to spline: %s\n",
  717.             progname, saves);
  718.         break;
  719.         }
  720.         emitnums(numbers[0]/2);
  721.         emitnums(numbers[1]/2);
  722.         putnl("rlineto");
  723.         /* NUM/DEN should be between 0 and 1; the closer it is to 1
  724.         the tighter the curve will be to the guiding lines; 2/3
  725.         is the standard value */
  726. #define    NUM    2
  727. #define    DEN    3
  728.         for (i = 0; i < ctindex - 2; i += 2) {
  729.         emitnums((numbers[i]*NUM)/(2*DEN));
  730.         emitnums((numbers[i + 1]*NUM)/(2*DEN));
  731.         emitnums(numbers[i]/2 + (numbers[i + 2]*(DEN - NUM))/(2*DEN));
  732.         emitnums(numbers[i + 1]/2 + (numbers[i + 3]*(DEN - NUM))/(2*DEN));
  733.         emitnums((numbers[i] - numbers[i]/2) + numbers[i + 2]/2);
  734.         emitnums((numbers[i + 1] - numbers[i + 1]/2) + numbers[i + 3]/2);
  735.         putnl("rcurveto");
  736.         }
  737.         emitnums(numbers[ctindex - 2] - numbers[ctindex - 2]/2);
  738.         emitnums(numbers[ctindex - 1] - numbers[ctindex - 1]/2);
  739.         putnl("rlineto");
  740.         break;
  741.     default:
  742.         fprintf(stderr, "%s: invalid draw code %c (%s)\n", progname, opcode,
  743.         saves);
  744.         break;
  745.     }
  746.     if (fill)
  747.     printf("%.3f dofill\n", curfill);
  748.     else
  749.     printf("%d dost\n", curthick);
  750. }
  751. #endif
  752. #endif /* PS */
  753.