home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume24 / psroff3.0 / part01 / utils / hpinterp.c < prev   
Encoding:
C/C++ Source or Header  |  1991-10-09  |  18.0 KB  |  823 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:        interprets HPLJ sequences.
  9.  */
  10.  
  11. #ifndef    lint
  12. static char SCCSID[] =
  13.     "@(#)hpinterp.c 2.4 Copyright 91/03/13 22:44:30 Chris Lewis";
  14. #endif
  15.  
  16. /*    To install:
  17.  
  18.     hpinterp needs to know byte order in shorts.  At run time it
  19.     will attempt to figure it out.  If you get an abort, or if the
  20.     results are idiotic:
  21.  
  22.         If you are little-endian (eg: 386/pdp-11/vax), define SMALLEND.
  23.         If you are big-endian (eg: pyramid/68000), undef BIGEND.
  24.  
  25.     cc -o hpinterp hpinterp.c
  26.  
  27.     Decide on a directory where you're going to run hpinterp and
  28.     create a directory called "FONTS" (or change the defines for
  29.     BINFILE and DESCFILE to have a better path).
  30.  
  31.     usage:
  32.  
  33.         hpinterp < hpljescapefile > /tmp/output
  34.  
  35.     /tmp/output will contain an englishy *very* verbose listing
  36.     of all of the escape sequences except for the contents of
  37.     font header/download/transfer/raster sequences.
  38.  
  39.     Each font downloaded is caught into a file FONTS/f<fontnumber>
  40.     and a bit of english is saved in FONTS/f<fontnumber>.desc.
  41.     Including some character maps (range restricted by firstchar and
  42.     lastchar).  You can turn off the verbose output listing by setting
  43.     verbose to 0.  setting "debug" to 1 (if verbose is 1 too), prints
  44.     ESC<string> sequences as well as the english.
  45.  
  46.     (One of these days I'll get it to do all of this stuff by command
  47.     line options....)
  48.  */
  49. #include <stdio.h>
  50. #include <ctype.h>
  51. #undef    BIGEND
  52. #undef SMALLEND
  53. #define    dbprintf(x)    if (verbose) printf x
  54. #define    ESCAPE    0x1b
  55.  
  56. #define    uchar    unsigned char
  57. int firstchar = 0;
  58. int lastchar = 0xff;
  59.  
  60. typedef int(*FUNC)();
  61.  
  62. int lastschar;
  63. int lastfontid;
  64.  
  65. double curX = 0, curY = 0;
  66. int emitting = 0;
  67.  
  68. FILE *out = (FILE *) NULL;
  69. FILE *txtout = (FILE *) NULL;
  70. int count = 0;
  71. int verbose = 0;
  72. int debug = 0;
  73. int genps = 0;
  74. int chars = 0;
  75. int characteristic = 1;
  76. int ps_symset = 0;
  77.  
  78. short canon();
  79.  
  80. readhex(len)
  81. int len; {
  82.     while(len--) GETCHAR();
  83. }
  84.  
  85. GETCHAR() {
  86.     int c;
  87.     c = getchar();
  88. #ifdef    DEBUG
  89.     if (isprint(c))
  90.     printf("GETCHAR: %c\n", c);
  91.     else
  92.     printf("GETCHAR: %02x\n", c);
  93. #endif
  94.     return(c);
  95. }
  96.  
  97. #define    TRANSFER    1
  98. #define    TRANSPARENT    2
  99. #define    FONTHEADER    3
  100. #define    DOWNLOAD    4
  101. struct fontdesc {
  102.     short f1;
  103.     uchar f2;
  104.     uchar fd_type;
  105.     short f3;
  106.     short fd_base;
  107.     short fd_cellwidth;
  108.     short fd_cellheight;
  109.     uchar fd_orientation;
  110.     uchar fd_fixedprop;
  111.     short fd_symset;
  112.     short fd_pitch;
  113.     short fd_height;
  114.     short f4;
  115.     uchar f5;
  116.     uchar fd_style;
  117.     uchar fd_weight;
  118.     uchar fd_typeface;
  119. };
  120.  
  121. struct download {
  122.     uchar f1;
  123.     uchar f2;
  124.     uchar f3;
  125.     uchar f4;
  126.     uchar dl_orientation;
  127.     short dl_leftoffset;
  128.     short dl_topoffset;
  129.     short dl_charwidth;
  130.     short dl_charheight;
  131.     short dl_deltax;
  132.     uchar  dl_data[1];
  133. };
  134.  
  135. char    *fchcont[] = {
  136.     "Delete all fonts",
  137.     "Delete all temporary fonts",
  138.     "Delete last font ID specified",
  139.     "Delete last font ID and char code",
  140.     "Make Temp font",
  141.     "Make Perm font",
  142.     "Copy/Assign",
  143.     NULL};
  144. char *spcont[] = {
  145.     "Fixed",
  146.     "Proportional",
  147.     NULL};
  148. char *stcont[] = {
  149.     "Upright",
  150.     "Italic",
  151.     NULL};
  152. char *tfcont[] = {
  153.     "Line Printer",
  154.     "Pica",
  155.     "Elite",
  156.     "Courier",
  157.     "Helvetica",
  158.     "Times Roman",
  159.     "Gothic",
  160.     "Script",
  161.     "Prestige Elite",
  162.     "Caslon",
  163.     "Orator",
  164.     NULL};
  165. char *sgcont[] = {
  166.     "Left-most position",
  167.     "Current Cursor",
  168.     NULL};
  169. char *pscont[] = {
  170.     "Disable",
  171.     "Enable",
  172.     NULL};
  173.  
  174.  
  175. int    movex(),movey(), papinctrl(), movedx(), movedy();
  176. int    spset(), psset(), styset(), strset(), tfset();
  177.  
  178. struct intlist {
  179.     char *code;
  180.     char *name;
  181.     char **parmnames;
  182.     FUNC exec;
  183. } intlist[] = {
  184.     {"&lO",    "Orientation"},
  185.     {"(sP",    "Spacing", spcont, spset},
  186.     {"(sH",    "Pitch"},
  187.     {"(sV",    "Point Size", NULL, psset},
  188.     {"(sS",    "Style", stcont, styset},
  189.     {"(sB",    "Stroke", NULL, strset},
  190.     {"(sT",    "Typeface", tfcont, tfset},
  191.     {"&lP",    "Page Length"},
  192.     {"&lE",    "Top Margin"},
  193.     {"&lF",    "Text Length"},
  194.     {"&aL",    "Left Margin"},
  195.     {"&aM",    "Right Margin"},
  196.     {"&lC",    "Motion Index"},
  197.     {"&lD",    "Lines/Inch"},
  198.     {"*tR",    "Resolution"},
  199.     {"*rA",    "Start Graphics", sgcont},
  200.     {"*bW",    "Transfer"},
  201.     {"*rB",    "End Graphics"},
  202.     {"&aR",    "Move to Row"},
  203.     {"&aC",    "Move to Column"},
  204.     {"&aH",    "Move to Column (Decipoints)", NULL, movex},
  205.     {"&aV",    "Move to Row (Decipoints)", NULL, movey},
  206.     {"&dD",    "Underline on"},
  207.     {"&d@",    "Underline off"},
  208.     {"&pX",    "Transparent Print"},
  209.     {"&lL",    "Perf Skip", pscont},
  210.     {"&kH",    "HMI"},
  211.     {"&kS",    "Font Pitch"},
  212.     {"&kG",    "Line Termination"},
  213.     {"&sC",    "Line Wrap"},
  214.     {"&lX",    "Number of Copies"},
  215.     {"&lH",    "Paper Input Control", NULL, papinctrl},
  216.     {"*pX",    "Horizontal cursor (dots)", NULL, movedx},
  217.     {"*pY",    "Vertical cursor (dots)", NULL, movedy},
  218.     {"*cD",    "Font ID"},
  219.     {"*cE",    "Character Code"},
  220.     {"*cF",    "Font/Char control", fchcont},
  221.     {")sW",    "Create Font Header"},
  222.     {"(sW",    "Download Character"},
  223.     {"&fY",    "Macro ID"},
  224.     {"&fX",    "Macro control"},
  225.     {"&fS",    "Push/Pop"},
  226.     {"*cA",    "Horizontal Rule/Pattern Size"},
  227.     {"*cH",    "Horizontal Rule/Pattern Size"},
  228.     {"*cB",    "Vertical Rule/Pattern Size"},
  229.     {"*cV",    "Vertical Rule/Pattern Size"},
  230.     {"*cP",    "Print Rule/Pattern"},
  231.     {"*cG",    "Grey scale/pattern id"},
  232.     {"&lT",    "Job offset control"},
  233.     {NULL,NULL}
  234. };
  235.  
  236. union {
  237.     struct fontdesc b_fd;
  238.     struct download b_dl;
  239.     char b_buffer[2048];
  240. } buffer;
  241.  
  242. interp(prefix, anchor, number, suffix)
  243. char prefix, anchor, suffix;
  244. double number; {
  245.     int multi;
  246.     register int i;
  247.     char lookup[4];
  248.  
  249.     if (debug)
  250.     dbprintf(("ESC%c%c%g%c\n", prefix, anchor, number, suffix));
  251.  
  252.     if (islower(suffix))
  253.     suffix = toupper(suffix);
  254.  
  255.     sprintf(lookup, "%c%c%c", prefix, anchor, suffix);
  256.     for (i = 0; intlist[i].code; i++) {
  257.     if (0 == strcmp(intlist[i].code, lookup)) {
  258.         dbprintf(("%s:", intlist[i].name));
  259.         if (intlist[i].parmnames) {
  260.         int j;
  261.         for (j = 0; j < number; j++) {
  262.             if (!intlist[i].parmnames[j])
  263.             break;
  264.         }
  265.         if (intlist[i].parmnames[j]) {
  266.             dbprintf((" %s\n", intlist[i].parmnames[j]));
  267.         } else {
  268.             dbprintf((" %d\n", (int) number));
  269.         }
  270.         } else {
  271.         dbprintf ((" %g\n", number));
  272.         }
  273.         if (intlist[i].exec)
  274.         (*intlist[i].exec)(number);
  275.         break;
  276.     }
  277.     }
  278.  
  279.     multi = 0;
  280.     /* For parsing variable length ones */
  281.     switch(prefix) {
  282.     case '*':
  283.         if (anchor == 'b' && suffix == 'W')
  284.         multi = TRANSFER;
  285.         break;
  286.     case '&':
  287.         if (anchor == 'p' && suffix == 'X')
  288.         multi = TRANSPARENT;
  289.         break;
  290.     case ')':
  291.         if (anchor == 's' && suffix == 'W')
  292.         multi = FONTHEADER;
  293.         break;
  294.     case '(':
  295.         if (anchor == 's' && suffix == 'W')
  296.         multi = DOWNLOAD;
  297.         break;
  298.     }
  299.     if (prefix == '*' && anchor == 'c' && suffix == 'E') {
  300.     lastschar = number;
  301.     }
  302.     if (prefix == '*' && anchor == 'c' && suffix == 'D') {
  303.     lastfontid = number;
  304.     }
  305.     if (multi)
  306.     readdesc(multi, (int) number);
  307. }
  308.  
  309. #ifdef    SMALLEND
  310. #define    smallend    1
  311. #endif
  312. #ifdef    BIGEND
  313. #define    smallend    0
  314. #endif
  315.  
  316. #if    !defined(SMALLEND) && !defined(BIGEND)
  317. union    t {
  318.     char a[2];
  319.     short b;
  320. };
  321. int    smallend;
  322. #endif
  323.  
  324. short
  325. canon(v)
  326. short v; {
  327.     if (smallend) {
  328.     return(((v & 0xff) << 8) | ((v&0xff00) >> 8));
  329.     } else
  330.     return(v);
  331. }
  332.  
  333. #define    BINFILE        "FONTS/f%d"
  334. #define    DESCFILE    "FONTS/f%d.desc"
  335.  
  336. readdesc(type, bytecount)
  337. int type; int bytecount; {
  338.     int points;
  339.     char *typeface;
  340.     char *style;
  341.     char filename[1000];
  342.     switch(type) {
  343.     default:
  344.         readhex(bytecount);
  345.         break;
  346.     case DOWNLOAD:
  347.         fread((char *) &buffer, 1, bytecount, stdin);
  348.         sprintf(filename, BINFILE, lastfontid);
  349.         if (out) fclose(out);
  350.         if ((out = fopen(filename, "a")) == NULL) {
  351.         fprintf(stderr, "Can't open %s\n", filename);
  352.         out = NULL;
  353.         }
  354.         sprintf(filename, DESCFILE, lastfontid);
  355.         if (txtout) fclose(txtout);
  356.         if ((txtout = fopen(filename, "a")) == NULL) {
  357.         fprintf(stderr, "Can't open %s\n", filename);
  358.         txtout = NULL;
  359.         }
  360.         if (lastschar >= firstchar && lastschar <= lastchar) {
  361.         if (txtout) {
  362.             fprintf(txtout, "Character: %c\n", lastschar);
  363.             fprintf(txtout, "  orientation: %d\n",
  364.             buffer.b_dl.dl_orientation);
  365.             fprintf(txtout, "  leftoffset: %d\n",
  366.             canon(buffer.b_dl.dl_leftoffset));
  367.             fprintf(txtout, "  topoffset: %d\n",
  368.             canon(buffer.b_dl.dl_topoffset));
  369.             fprintf(txtout, "  charwidth: %d\n",
  370.             canon(buffer.b_dl.dl_charwidth));
  371.             fprintf(txtout, "  charheight: %d\n",
  372.             canon(buffer.b_dl.dl_charheight));
  373.             fprintf(txtout, "  deltax: %d\n",
  374.             canon(buffer.b_dl.dl_deltax));
  375.             if (chars)
  376.             plotchars(txtout, &buffer.b_dl);
  377.         }
  378.         }
  379.         if (out) {
  380.         fprintf(out, "\033*c%dE", lastschar);
  381.         fprintf(out, "\033(s%dW", bytecount);
  382.         fwrite((char *) &buffer, 1, bytecount, out);
  383.         }
  384.         break;
  385.  
  386.     case FONTHEADER:
  387.         if (txtout) fclose(txtout);
  388.         if (out) fclose(out);
  389.  
  390.         fread((char *) &buffer, 1, bytecount, stdin);
  391.         points = (double) canon(buffer.b_fd.fd_height) * 72 / 4 / 300 + .5;
  392.         switch(buffer.b_fd.fd_typeface) {
  393.         case 0: typeface = "Line Printer"; break;
  394.         case 1: typeface = "Pica"; break;
  395.         case 2: typeface = "Elite"; break;
  396.         case 3: typeface = "Courier"; break;
  397.         case 4: typeface = "Helvetica"; break;
  398.         case 5: typeface = "Times-Roman"; break;
  399.         case 6: typeface = "Gothic"; break;
  400.         case 7: typeface = "Script"; break;
  401.         case 8: typeface = "Prestige"; break;
  402.         case 9: typeface = "Caslon"; break;
  403.         case 10: typeface = "Orator"; break;
  404.         default: typeface = "               ";
  405.             sprintf(typeface, "T%d", buffer.b_fd.fd_typeface);
  406.             break;
  407.         }
  408.         switch(buffer.b_fd.fd_style) {
  409.         case 0:
  410.             style = "Upright";
  411.             break;
  412.         case 1:
  413.             style = "Italic";
  414.             break;
  415.         }
  416.         sprintf(filename, BINFILE, lastfontid);
  417.         if ((out = fopen(filename, "w")) == NULL) {
  418.         fprintf(stderr, "Can't open %s\n", filename);
  419.         out = NULL;
  420.         }
  421.         sprintf(filename, DESCFILE, lastfontid);
  422.         if ((txtout = fopen(filename, "w")) == NULL) {
  423.         fprintf(stderr, "Can't open %s\n", filename);
  424.         txtout = NULL;
  425.         }
  426.         /*fprintf(out, "\033*c%dD", lastfontid);*/
  427.         fprintf(out, "\033)s%dW", bytecount);
  428.         fwrite((char *) &buffer, 1, bytecount, out);
  429.         if (txtout) {
  430.         fprintf(txtout, "Height: %d\n", canon(buffer.b_fd.fd_height));
  431.         fprintf(txtout, "  Points (rounded): %d\n", points);
  432.         fprintf(txtout, "  Points (floating): %.2f\n",
  433.             (double) canon(buffer.b_fd.fd_height) * 72 / 4 / 300);
  434.         fprintf(txtout, "Pitch: %d\n", canon(buffer.b_fd.fd_pitch));
  435.         fprintf(txtout, "  Pitch (chars/inch): %d\n",
  436.             4 * 300 / canon(buffer.b_fd.fd_pitch));
  437.         if (buffer.b_fd.fd_fixedprop)
  438.             fprintf(txtout, "Proportional width font\n");
  439.         else
  440.             fprintf(txtout, "Fixed width font\n");
  441.         fprintf(txtout, "Stroke weight: %d\n", buffer.b_fd.fd_weight);
  442.         fprintf(txtout, "Style: %d; (%s)\n", buffer.b_fd.fd_style,
  443.             style);
  444.         fprintf(txtout, "Typeface: %d; (%s)\n", buffer.b_fd.fd_typeface,
  445.             typeface);
  446.         fprintf(txtout, "Symset: %04x; (%d%c)\n",
  447.             canon(buffer.b_fd.fd_symset),
  448.             canon(buffer.b_fd.fd_symset) >> 5,
  449.             (canon(buffer.b_fd.fd_symset) & 0x1f) + 'A' - 1);
  450.  
  451.         fprintf(txtout, "Type: %x\n", buffer.b_fd.fd_type);
  452.         fprintf(txtout, "Base: %d\n", canon(buffer.b_fd.fd_base));
  453.         fprintf(txtout, "Cellwidth: %d\n", canon(buffer.b_fd.fd_cellwidth));
  454.         fprintf(txtout, "Cellheight: %d\n", canon(buffer.b_fd.fd_cellheight));
  455.         fprintf(txtout, "Orientation: %d\n", buffer.b_fd.fd_orientation);
  456.         fprintf(txtout, "Height: %d\n", canon(buffer.b_fd.fd_height));
  457.         }
  458.     }
  459. }
  460.  
  461. plotchars(f, dl)
  462. struct download *dl;
  463. FILE *f; {
  464.     short x, y, bx, by, bytes, byteindex, bitindex, bit;
  465.     bytes = (canon(dl->dl_charwidth) + 7) / 8;
  466.     for (y = 0; y < canon(dl->dl_charheight); y++) {
  467.     fprintf(f, "        ");
  468.     for (x = 0; x < (canon(dl->dl_charwidth) + canon(dl->dl_leftoffset));
  469.         x++) {
  470.         bx = x - canon(dl->dl_leftoffset);
  471.         by = y;
  472.         if (bx >= 0) {
  473.         byteindex = bytes * by + bx / 8;
  474.         bitindex = (7 - (bx % 8));
  475.         if (dl->dl_data[byteindex] & (1 << bitindex))
  476.             bit = 'X';
  477.         else
  478.             bit = ' ';
  479.         } else
  480.         bit = ' ';
  481.         if (x == 0 && y == canon(dl->dl_topoffset))
  482.         bit = '+';
  483.         if (bit == ' ' && y == canon(dl->dl_topoffset))
  484.         bit = '=';
  485.         fputc(bit, f);
  486.     }
  487.     fputc('\n',f);
  488.     }
  489. }
  490.  
  491.  
  492. /*    We've got ESC<prefix><anchor>
  493.  *    read number/suffix pairs
  494.  */
  495. multisequence(prefix, anchor)
  496. char prefix, anchor; {
  497.     int c, neg, seendot;
  498.     double v;
  499.     while(1) {
  500.     v = 0;
  501.     seendot = 0;
  502.     neg = 1;
  503.     while(isdigit(c = GETCHAR()) || (c == '.') || (c == '-') || (c == '+')) {
  504.         if (c == '+') {
  505.         continue;
  506.         }
  507.         if (c == '.') {
  508.         seendot = 10;
  509.         continue;
  510.         }
  511.         if (c == '-') {
  512.         neg *= -1;
  513.         continue;
  514.         }
  515.         if (seendot) {
  516.         v += (double) (c - '0') / seendot;
  517.         seendot *= 10;
  518.         } else
  519.         v = v * 10 + c - '0';
  520.     }
  521.     v *= neg;
  522.     interp(prefix, anchor, v, c);
  523.     if (!islower(c))
  524.         break;
  525.     }
  526. }
  527.  
  528. printhex(buf, n)
  529. char *buf; int n; {
  530.     int i;
  531.     dbprintf(("SEQ:"));
  532.     for (i = 0; i < n; i++) {
  533.     if (isprint(buf[i]))
  534.         putchar(buf[i]);
  535.     else {
  536.         dbprintf(("\\%02x", buf[i]));
  537.     }
  538.     }
  539.     dbprintf(("\n"));
  540. }
  541.  
  542. short pts[] = {6, 7, 8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 28, 36, 4, 4};
  543. readescape() {
  544.     int c, v, v1, v2, v3;
  545.     c = GETCHAR();
  546.     switch(c) {
  547.     case '9':
  548.         dbprintf(("Clear Margins\n"));
  549.         return;
  550.     case '=':
  551.         dbprintf(("Half linefeed\n"));
  552.         return;
  553.     case 'E':
  554.         dbprintf(("Reset\n"));
  555.         return;
  556.     case 'z':
  557.         dbprintf(("Self test\n"));
  558.         return;
  559.     case 'Y':
  560.         dbprintf(("Display functions on\n"));
  561.         return;
  562.     case 'Z':
  563.         dbprintf(("Display functions off\n"));
  564.         return;
  565.     case ')':
  566.         c = GETCHAR();
  567.         if (isdigit(c)) {
  568.         v = 0;
  569.         while(isdigit(c)) {
  570.             v = v * 10 + c - '0';
  571.             c = GETCHAR();
  572.         }
  573.         switch(c) {
  574.             case 'X':
  575.             dbprintf(("Secondary font %d\n", v));
  576.             break;
  577.             case '@':
  578.             dbprintf(("Secondary font value %d\n", v));
  579.             break;
  580.             default:
  581.             dbprintf(("HUH ESC)%d%c\n", v, c));
  582.         }
  583.         return;
  584.         }
  585.         multisequence(')', c);
  586.         return;
  587.     case '(':
  588.         c = GETCHAR();
  589.         if (isdigit(c)) {
  590.         v = 0;
  591.         while(isdigit(c)) {
  592.             v = v * 10 + c - '0';
  593.             c = GETCHAR();
  594.         }
  595.         switch(c) {
  596.             case 'X':
  597.             dbprintf(("Primary font %d\n", v));
  598.             if (genps) {
  599.                 endemit();
  600.                 characteristic = 0;
  601.                 printf("/f%d findfont %d scalefont setfont\n",
  602.                 v, pts[v&0xf]);
  603.             }
  604.             break;
  605.             case '@':
  606.             dbprintf(("Primary font value %d\n", v));
  607.             break;
  608.             default:
  609.             dbprintf(("Symbol set: %d%c\n", v, c));
  610.             ps_symset = c;
  611.         }
  612.         return;
  613.         }
  614.         multisequence('(', c);
  615.         return;
  616.     case '&':
  617.         c = GETCHAR();
  618.         multisequence('&', c);
  619.         return;
  620.     case '*':
  621.         c = GETCHAR();
  622.         multisequence('*', c);
  623.         return;
  624.     default:
  625.         dbprintf(("Huh? %02x\n", c));
  626.         return;
  627.     }
  628. }
  629.  
  630. main(argc, argv)
  631. int argc; char **argv; {
  632.     int c;
  633.     extern char *optarg;
  634.  
  635. #if    !defined(BIGEND) && !defined(SMALLEND)
  636.     union t ta;
  637.     ta.a[0] = 0x01;
  638.     ta.a[1] = 0x02;
  639.     smallend = ((ta.b&0xff) == 0x01);
  640. #endif
  641.     while((c = getopt(argc, argv, "dpv")) != EOF)
  642.     switch(c) {
  643.         case 'p':
  644.         genps++;
  645.         break;
  646.         case 'v':
  647.         verbose++;
  648.         break;
  649.         case 'd':
  650.         debug++;
  651.         break;
  652.         case '?':
  653.         fprintf(stderr, "usage: hpinterp [-d][-p][-v]< file");
  654.         exit(1);
  655.     }
  656.  
  657.  
  658.     if (genps) {
  659.     printf("/M { moveto } def\n");
  660.     printf("/S { show } def\n");
  661.     }
  662.     while((c = GETCHAR()) != EOF) {
  663.     if (c == ESCAPE) {
  664.         readescape();
  665.     } else {
  666.         if (isprint(c)) {
  667.         dbprintf(("Char: %c\n", c));
  668.         } else {
  669.         dbprintf(("Char: 0x%02x\n", c));
  670.         }
  671.         emitchar(c);
  672.     }
  673.     }
  674.     if (out) fclose(out);
  675.     if (txtout) fclose(txtout);
  676.     endemit();
  677. }
  678.  
  679. movex(num)
  680. double num; {
  681.     curX = num;
  682.     endemit();
  683. }
  684.  
  685. movey(num)
  686. double num; {
  687.     curY = num;
  688.     endemit();
  689. }
  690.  
  691. movedx(num)
  692. double num; {
  693.     curX = num * 720 / 300;
  694.     endemit();
  695. }
  696.  
  697. movedy(num)
  698. double num; {
  699.     curY = num * 720 / 300;
  700.     endemit();
  701. }
  702.  
  703. emitchar(c)
  704. int c; {
  705.     if (!genps)
  706.     return;
  707.  
  708.     if (characteristic)
  709.     selchar();
  710.  
  711.     if (!emitting)
  712.     printf("%g %g M(", curX/10, (72 * 11) - (curY/10));
  713.  
  714.     emitting = 1;
  715.  
  716.     switch(c) {
  717.     case '(': case ')': case '\\':
  718.         printf("\\%c", c);
  719.         break;
  720.     default:
  721.         if (c > ' ' && c < 0x7e)
  722.         printf("%c", c);
  723.         else
  724.         printf("\\%03o", c&0xff);
  725.         break;
  726.     }
  727. }
  728.  
  729. endemit() {
  730.     if (emitting)
  731.     printf(")S\n");
  732.     emitting = 0;
  733. }
  734.  
  735. papinctrl(num)
  736. double num; {
  737.     int n = num;
  738.     if (num == 0) {
  739.     endemit();
  740.     if (genps)
  741.         printf("showpage\n");
  742.     }
  743. }
  744.  
  745. int ps_pointsize = 10;
  746. int ps_style = 1;
  747. int ps_stroke = 0;
  748. int ps_tface = 5;
  749. int ps_spacing = 0;
  750.  
  751. spset(num)
  752. double num; {
  753.     ps_spacing = num;
  754.     characteristic = 1;
  755.     endemit();
  756. }
  757. psset(num)
  758. double num; {
  759.     characteristic = 1;
  760.     ps_pointsize = num;
  761.     endemit();
  762. }
  763. styset(num)
  764. double num; {
  765.     characteristic = 1;
  766.     ps_style = num;
  767.     endemit();
  768. }
  769. strset(num)
  770. double num; {
  771.     characteristic = 1;
  772.     ps_stroke = num;
  773.     endemit();
  774. }
  775. tfset(num)
  776. double num; {
  777.     characteristic = 1;
  778.     ps_tface = num;
  779.     endemit();
  780. }
  781.  
  782. #define    TMS    "Times-Roman", "Times-Italic", "Times-Bold", "Times-BoldItalic"
  783. #define COUR    "Courier", "Courier-Oblique", "Courier-Bold",\
  784.     "Courier-BoldOblique"
  785. #define HELV    "Helvetica", "Helvetica-Oblique", "Helvetica-Bold",\
  786.     "Helvetica-BoldOblique"
  787.  
  788. #define    LAST    7
  789.  
  790. char *fonts[LAST][4] = {{COUR}, {COUR}, {COUR}, {COUR}, {HELV}, {TMS},
  791.     {COUR}};
  792.  
  793. selchar() {
  794.     int idx = 0;
  795.     char **font;
  796.     char *p;
  797. #ifdef    NEVER
  798.     printf("ps_pointsize: %d\n", ps_pointsize);
  799.     printf("ps_style: %d\n", ps_style);
  800.     printf("ps_stroke: %d\n", ps_stroke);
  801.     printf("ps_symset: %d\n", ps_symset);
  802.     printf("ps_tface: %d\n", ps_tface);
  803.     printf("ps_spacing: %d\n", ps_spacing);
  804. #endif
  805.     if (ps_tface == 4101)    /* CG Roman on LJ III */
  806.     ps_tface = 5;
  807.     if (ps_tface == 4148)    /* CG Univers (Helvetica like) Roman on LJ III */
  808.     ps_tface = 4;
  809.     if (ps_tface >= LAST || ps_tface < 0)
  810.     ps_tface = 3;
  811.     idx = 0;
  812.     if (ps_stroke > 0)
  813.     idx = 2;
  814.     if (ps_style != 0)
  815.     idx++;
  816.     if (ps_symset == 'M')
  817.     p = "Symbol";
  818.     else
  819.     p = fonts[ps_tface][idx];
  820.     printf("/%s findfont %d scalefont setfont\n", p, ps_pointsize);
  821.     characteristic = 0;
  822. }
  823.