home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume24 / psroff3.0 / part05 / troff2.c
Encoding:
C/C++ Source or Header  |  1991-10-09  |  16.8 KB  |  788 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:        CAT Troff interpreter front end and mainline
  9.  */
  10.  
  11. #include "defs.h"
  12.  
  13. #ifndef    lint
  14. static char SCCSid[] =
  15.     "@(#)troff2.c: 2.15 Copyright 91/03/25 23:20:47 Chris Lewis";
  16. #endif
  17.  
  18. #define    ESC    0x80
  19. #define    FLASH    0x00
  20. #define    CONTROL    0x40
  21. #define    LEAD    0x60
  22. #define    SIZE    0x50
  23.  
  24. #define    DOWN    0
  25. #define    UP    1
  26. #define    LOWER    2
  27. #define    UPPER    3
  28. #define    FORWARD    4
  29. #define    BACKWARD 5
  30.  
  31. #ifdef    BSDHACK
  32. int    magnify_lead = 0;
  33. #endif
  34.  
  35. char ptab[15] = { 7, 8, 10, 11, 12, 14, 18, 9, 6, 16, 20, 22, 24, 28, 36};
  36. int    points, font;
  37.  
  38. int    xpos, ypos;
  39.  
  40. #ifdef    VDEBUG
  41. char *words[] = {
  42.     "down", "up", "lower", "upper", "forward", "backwards"
  43.     };
  44. #endif
  45.  
  46.  
  47. #define    CTOINT(val,sig)    ((~c)&sig)
  48.  
  49. int pagelength;
  50. int pageoffset;
  51. int pageyoffset;
  52.  
  53. char *version, *shortversion;
  54.  
  55. int dumpflag = 0;
  56.  
  57. #define    CFONT (((mag == UPPER)<<2)|((rail == UPPER)<<1)|(tilt==DOWN))
  58. #ifdef    FONT4
  59. #define    calcfont    font = (CFONT >> 1)
  60. #else
  61. #define    calcfont    font = CFONT
  62. #endif
  63.  
  64. char *progname;
  65. char *printer;
  66. char *device = {"alw"};
  67. char **prologs = (char **) NULL;
  68. char *pstrailer = "\004";
  69. #define    PROCHUNK    20
  70. int procount;
  71.  
  72. #ifdef    L_cuserid
  73. #define    nmMAX    L_cuserid
  74. #else
  75. #define    nmMAX    16
  76. #endif
  77.  
  78. char username[nmMAX];
  79.  
  80. double calc();
  81.  
  82. char *driver = "ps";
  83. #ifdef    OPT
  84. char *widthtables = (char *)NULL;
  85. char *widthptr;
  86. int optimize = 0;
  87. #endif
  88.  
  89. extern char *realloc();
  90.  
  91. #define    OPTLIST    "d:O:Y:T:VD:l:MR:P::zp:W:ZNS"
  92.  
  93. /*    On 386/ix 1.0.6 profiling has a bug in it that leaves
  94.     two extra longs on the stack between the stack frame and
  95.     arguments on entry to main */
  96. #ifdef    PROFBUG
  97.  
  98. main(j1, j2, argc, argv)
  99. long j1, j2;
  100. int argc;
  101. char **argv; {
  102.  
  103. #else
  104.  
  105. main(argc, argv)
  106. int    argc;
  107. char    **argv; {
  108.  
  109. #endif
  110.     register int nc, c;
  111.     register int units;
  112.     register int rail, mag, tilt, half, escape, lead;
  113.  
  114.     extern int getopt();
  115.     extern char *optarg;
  116.  
  117. #ifdef    L_cuserid
  118.     extern char *cuserid();
  119.  
  120.     (void) cuserid(username);
  121.     if (!username[0])
  122. #else
  123.  
  124.     extern char *getlogin();
  125.  
  126.     progname = getlogin();
  127.     if (progname)
  128.         strcpy(username, progname);
  129.     else
  130.         /* I could read /etc/passwd, but hell, why? */
  131. #endif
  132.         sprintf(username, "uid=%d", getuid());
  133.  
  134.     /* some compilers complain about floating point in initializers... */
  135.     pagelength = DEFPL * TROFFRESOLUTION;
  136.     pageoffset = DEFOFF * TROFFRESOLUTION;
  137.     pageyoffset = DEFYOFF * TROFFRESOLUTION;
  138.  
  139.     progname = strrchr(argv[0], '/');
  140.     if (progname)
  141.         progname++;
  142.     else
  143.         progname = argv[0];
  144.  
  145.     version = T2VERSION + 4;
  146.     shortversion = strchr(version, '-') + 2;
  147.  
  148.     while((c = getopt(argc, argv, OPTLIST)) != EOF)
  149.         switch (c) {
  150.         case 'S':
  151.             pstrailer = "stop\n";
  152.             break;
  153. #ifdef    OPT
  154.         case 'Z':
  155.             optimize = 1;
  156.             break;
  157.         case 'W':
  158.             widthtables = mustmalloc(strlen(optarg) + 10, "widthname");
  159.             strcpy(widthtables, optarg);
  160.             strcat(widthtables, "/");
  161.             break;
  162. #else
  163.         case 'Z':
  164.         case 'W':
  165.             fprintf(stderr,
  166.             "%s: optimization disabled; -Z/-W ignored (%s)\n",
  167.             progname, "see OPT in defs.h");
  168.             break;
  169. #endif
  170.         case 'P':
  171.             if (!prologs) {
  172.             prologs = (char **) mustmalloc(PROCHUNK * sizeof(char*),
  173.                 "prologs");
  174.             procount = 0;
  175.             }
  176.             prologs[procount++] = optarg;
  177.             /* insert the null */
  178.             if ((procount % PROCHUNK) == 0) {
  179.             prologs = (char **) realloc((char *) prologs,
  180.                 (procount + PROCHUNK) * sizeof(char *));
  181.             }
  182.             prologs[procount] = (char *) NULL;
  183.             break;
  184.         case 'p':
  185.             printer = optarg;
  186.             break;
  187.         case 'd':
  188.             device = optarg;
  189.             break;
  190.         case 'z':
  191.             dumpflag++;
  192.             break;
  193.         case 'T':
  194.             driver = optarg;
  195.             break;
  196.         case 'R':
  197. #if    defined(DT)
  198.             {
  199.             extern int dtresolution;
  200.             dtresolution = atoi(optarg);
  201.             if (dtresolution == 0) {
  202.                 fprintf(stderr, "%s: Invalid resolution: %s\n",
  203.                 progname, optarg);
  204.                 exit(1);
  205.             }
  206.             }
  207.             break;
  208. #else
  209.             fprintf(stderr, "%s: Resolution not supported\n",
  210.             progname);
  211.             exit(1);
  212. #endif
  213.         case 'N':
  214. #ifdef    DIT
  215.             ditroff = 1;
  216.             break;
  217. #else
  218.             fprintf(stderr, "%s: ditroff frontend not configured\n");
  219.             exit(1);
  220. #endif
  221.         case 'M':
  222.             metrics = 1;
  223.             break;
  224.         case 'V':
  225.             printf("%s: %s\n", progname, version);
  226.             exit(0);
  227.         case 'D':
  228. #ifdef    DEBUG
  229.             setdebug(optarg, "diagnostics");
  230.             break;
  231. #else
  232.             fprintf(stderr, "%s: DEBUG disabled - recompile\n",
  233.             progname);
  234.             exit(1);
  235. #endif
  236.         case 'O':
  237.             pageoffset = calc(optarg);
  238.             break;
  239.         case 'Y':
  240.             pageyoffset = calc(optarg);
  241.             break;
  242.         case 'l':
  243.             pagelength = calc(optarg);
  244.             if (pagelength == 0) {
  245.             fprintf(stderr, "%s: Bad pagelength %s\n", progname,
  246.                 optarg);
  247.             exit(1);
  248.             }
  249.             break;
  250.         case '?':
  251.         default:
  252.             usage();
  253.             exit(1);
  254.         }
  255.  
  256.     getdriver(driver);
  257.  
  258.     if (!printer)
  259.         printer = driver;
  260.  
  261. #ifdef    OPT
  262.     if (!widthtables) {
  263.         widthtables = mustmalloc(strlen(driver) + strlen(FONTDIR) + 20,
  264.         "widthname");
  265.         sprintf(widthtables, "%s/%s/", FONTDIR, driver);
  266.     }
  267.     widthptr = widthtables + strlen(widthtables);
  268. #endif
  269.  
  270.     loadfont(be->bestdfont, be->besymfont);
  271. #ifdef    DEBUG
  272.     if (debug & D_SPEC) {
  273.         for (c = 0; c < procount; c++) {
  274.         DBP((D_SPEC, "Prolog %d: %s\n", c, prologs[c]));
  275.         }
  276.     }
  277. #endif
  278.  
  279.     if (dumpflag) {
  280.  
  281.         printf("Font table:\n\n");
  282.         for (c = 0; fonttable[c].tab[0]; c++)
  283.         printf("%-3s %-20s %-20s %-20s\n",
  284.             fonttable[c].tab[0],
  285.             fonttable[c].tab[1],
  286.             fonttable[c].tab[2],
  287.             fonttable[c].tab[3]);
  288.  
  289.         dumptables(be);
  290.         exit(0);
  291.     }
  292.  
  293. #ifdef    DIT
  294.     if (ditroff) {
  295.         dit();
  296. #ifdef    OPT
  297.         canonflush();
  298. #endif
  299.         if (be->bepage)
  300.         (*be->bepage)();
  301.         if (be->beepilog)
  302.         (*be->beepilog) ();
  303.         exit(0);
  304.     }
  305. #endif
  306.  
  307.     if (be->beprolog)
  308.         (*be->beprolog)();
  309.  
  310.     resetState();
  311.  
  312.     /* An Initialize sequence *usually* comes in first, but what the
  313.         hey ... */
  314.     xpos = 0;
  315.     ypos = -153;
  316.     escape = FORWARD;
  317.     lead = FORWARD;
  318.     half = LOWER;
  319.     rail = LOWER;
  320.     mag = LOWER;
  321.     tilt = DOWN;
  322.     calcfont;
  323.  
  324.     while ((c = getc(stdin)) != EOF) {
  325.         switch(c) {
  326.         case 0x00:
  327.             DBP((D_CAT,"NOP\n"));
  328.             break;
  329.         /* Flash (print character) codes */
  330.         case 0x01: case 0x02: case 0x03: case 0x04:
  331.         case 0x05: case 0x06: case 0x07: case 0x08:
  332.         case 0x09: case 0x0a: case 0x0b: case 0x0c:
  333.         case 0x0d: case 0x0e: case 0x0f: case 0x10:
  334.         case 0x11: case 0x12: case 0x13: case 0x14:
  335.         case 0x15: case 0x16: case 0x17: case 0x18:
  336.         case 0x19: case 0x1a: case 0x1b: case 0x1c:
  337.         case 0x1d: case 0x1e: case 0x1f: case 0x20:
  338.         case 0x21: case 0x22: case 0x23: case 0x24:
  339.         case 0x25: case 0x26: case 0x27: case 0x28:
  340.         case 0x29: case 0x2a: case 0x2b: case 0x2c:
  341.         case 0x2d: case 0x2e: case 0x2f: case 0x30:
  342.         case 0x31: case 0x32: case 0x33: case 0x34:
  343.         case 0x35: case 0x36: case 0x37: case 0x38:
  344.         case 0x39: case 0x3a: case 0x3b: case 0x3c:
  345.         case 0x3d: case 0x3e: case 0x3f:
  346.             /* This is terribly kludgey:
  347.                 In 432 units per inch, 4752 is 11 inches.
  348.                 When we go beyond this, we subtract 4752
  349.                 continually until we're back in range.
  350.             */
  351.             while (ypos >= pagelength) {
  352.                    ypos -= pagelength;
  353.                 DBP((D_CAT,"Page break\n"));
  354.                 if (be->bepage)
  355.                 (*be->bepage) ();
  356.             }
  357.             /*c = c&0x3f;    Isn't necessary */
  358.             /*    Find the C/A/T code */
  359.             if (half == UPPER) {
  360.                 if (c > 46) {
  361.                 fprintf(stderr, "%s: Illegal upper flash: %d\n",
  362.                     progname, c);
  363.                 exit(1);
  364.                 }
  365.                 nc = c + 62;
  366.             } else
  367.                 nc = c - 1;
  368.  
  369.             DBP((D_CAT,"nc=%d;pnts=%d;x,y=%d,%d;fnt=%d;\n",
  370.                 nc,points,xpos,ypos,font));
  371. #ifdef    VDEBUG
  372.             DBP((D_CAT,"  rail=%s;mag=%s;tilt=%s;half=%s\n",
  373.                 words[rail], words[mag],words[tilt], words[half]));
  374. #endif
  375.  
  376. #ifdef OPT
  377.             canoninsert(xpos, ypos, font, points, nc);
  378. #else
  379.             if (be->beputchar)
  380.                 (*be->beputchar)(xpos, ypos, font, points, nc,
  381.                 (char *) NULL);
  382. #endif
  383.  
  384.             break;
  385.         /* Control codes */
  386.         case 0x40:
  387.             DBP((D_CAT,"Initialize\n"));
  388.             xpos = 0;
  389.             ypos = -153;
  390.             escape = FORWARD;
  391.             lead = FORWARD;
  392.             half = LOWER;
  393.             rail = LOWER;
  394.             mag = LOWER;
  395.             tilt = DOWN;
  396.             calcfont;
  397.             break;
  398.         case 0x41:
  399.             DBP((D_CAT,"Rail lower\n"));
  400.             rail = LOWER;
  401.             calcfont;
  402.             break;
  403.         case 0x42:
  404.             DBP((D_CAT,"Rail upper\n"));
  405.             rail = UPPER;
  406.             calcfont;
  407.             break;
  408.         case 0x43:
  409.             DBP((D_CAT,"Mag upper\n"));
  410.             mag = UPPER;
  411.             calcfont;
  412.             break;
  413.         case 0x44:
  414.             DBP((D_CAT,"Mag lower\n"));
  415.             mag = LOWER;
  416.             calcfont;
  417.             break;
  418.         case 0x45:
  419.             DBP((D_CAT,"half lower\n"));
  420.             half = LOWER;
  421.             break;
  422.         case 0x46:
  423.             DBP((D_CAT,"half upper\n"));
  424.             half = UPPER;
  425.             break;
  426.         case 0x47:
  427.             DBP((D_CAT,"Escape forward\n"));
  428.             escape = FORWARD;
  429.             break;
  430.         case 0x48:
  431.             DBP((D_CAT,"Escape backward\n"));
  432.             escape = BACKWARD;
  433.             break;
  434.         case 0x49:
  435.             DBP((D_CAT,"STOP\n"));
  436.             break;
  437.         case 0x4a:
  438.             DBP((D_CAT,"Lead forward\n"));
  439.             lead = FORWARD;
  440.             break;
  441.         case 0x4b:
  442.             DBP((D_CAT,"Software cut!\n"));
  443.             break;
  444.         case 0x4c:
  445.             DBP((D_CAT,"Lead backward\n"));
  446.             lead = BACKWARD;
  447.             break;
  448.         case 0x4d:
  449. #ifdef    SPECIAL
  450. #define    SPSIZ    256
  451.             {
  452.                 static char specialbuf[SPSIZ], *sbp;
  453.                 sbp = specialbuf;
  454. #ifdef    OPT
  455.                 canonflush();
  456. #endif
  457.                 while((c = getc(stdin)) != EOF && c != '\n') {
  458.                 if (!c)    /* some troff's add NOP's when
  459.                        the internal output buffer is
  460.                        flushed */
  461.                     continue;
  462.                 if (sbp < &specialbuf[SPSIZ]-2)
  463.                 *sbp++ = c;
  464.                 }
  465.                 *sbp = '\0';
  466.  
  467.                 DBP((D_SPEC,"SPECIAL SEQUENCE: %s!\n", specialbuf));
  468.                 dospecial(specialbuf);
  469.                 break;
  470.             }
  471. #else
  472.             fprintf(stderr, "%s: Illegal C/A/T code - %s\n",
  473.                 progname, "special sequences are disabled");
  474.             exit(1);
  475. #endif
  476. #ifdef    BSDHACK
  477.         case 0x4e:
  478.             magnify_lead = 1;
  479.             break;
  480. #endif
  481. #ifdef    FONT8
  482.         case 0x4e:
  483.             DBP((D_CAT,"Tilt up\n"));
  484.             tilt = UP;
  485.             calcfont;
  486.             break;
  487.         case 0x4f:
  488.             DBP((D_CAT,"Tilt down\n"));
  489.             tilt = DOWN;
  490.             calcfont;
  491.             break;
  492. #endif
  493.  
  494.         /* Size changes */
  495.         case 0x50: case 0x51: case 0x52: case 0x53:
  496.         case 0x54: case 0x55: case 0x56: case 0x57:
  497.         case 0x58: case 0x59: case 0x5a: case 0x5b:
  498.         case 0x5c: case 0x5d: case 0x5e: case 0x5f:
  499.             /* basic code is the points = ptab[c] line.
  500.                The rest of the brain-damage is due to the
  501.                fact that switching from some of the fonts
  502.                to some of the others blow the horizontal
  503.                position - see the cat(5) manual page
  504.                about single vs. doubler point sizes. */
  505.             {    static lastc = 0;
  506.             c &= 0xf;
  507.             points = ptab[c];
  508.  
  509.             DBP((D_CAT,"SPoints:%d;lastc:%5d;c:%d;xpos:%d\n",
  510.                 points, lastc, c, xpos));
  511.             if (lastc <= 8 && c > 8) /* single -> doubler */
  512.                 xpos -= 55;
  513.             else if (lastc > 8 && c <= 8) /* doubler -> single */
  514.                 xpos += 55;
  515.  
  516.             DBP((D_CAT,"EPoints:%d;lastc:%5d;c:%d;xpos:%d\n",
  517.                 points, lastc, c, xpos));
  518.             lastc = c;
  519.             break;
  520.             }
  521.         /* Lead (vertical motion) codes */
  522.         case 0x60: case 0x61: case 0x62: case 0x63:
  523.         case 0x64: case 0x65: case 0x66: case 0x67:
  524.         case 0x68: case 0x69: case 0x6a: case 0x6b:
  525.         case 0x6c: case 0x6d: case 0x6e: case 0x6f:
  526.         case 0x70: case 0x71: case 0x72: case 0x73:
  527.         case 0x74: case 0x75: case 0x76: case 0x77:
  528.         case 0x78: case 0x79: case 0x7a: case 0x7b:
  529.         case 0x7c: case 0x7d: case 0x7e: case 0x7f:
  530.  
  531. #ifdef    OPT
  532.             canonflush();
  533. #endif
  534.  
  535.             DBP((D_CAT,"Lead(vertical) %02x\n", c&0x1f));
  536.             units = CTOINT(c,0x1f);
  537. #ifdef    BSDHACK
  538.             if (magnify_lead) {
  539.                 units *= 64;
  540.                 magnify_lead = 0;
  541.             }
  542. #endif
  543.             if (lead == FORWARD)
  544.                 ypos += 3*units;
  545.             else
  546.                 ypos -= 3*units;
  547.             break;
  548.         /* Escape (horizontal motion) codes */
  549.         case 0x80: case 0x81: case 0x82: case 0x83:
  550. #ifndef lint
  551.         case 0x84: case 0x85: case 0x86: case 0x87:
  552.         case 0x88: case 0x89: case 0x8a: case 0x8b:
  553.         case 0x8c: case 0x8d: case 0x8e: case 0x8f:
  554.         case 0x90: case 0x91: case 0x92: case 0x93:
  555.         case 0x94: case 0x95: case 0x96: case 0x97:
  556.         case 0x98: case 0x99: case 0x9a: case 0x9b:
  557.         case 0x9c: case 0x9d: case 0x9e: case 0x9f:
  558.         case 0xa0: case 0xa1: case 0xa2: case 0xa3:
  559.         case 0xa4: case 0xa5: case 0xa6: case 0xa7:
  560.         case 0xa8: case 0xa9: case 0xaa: case 0xab:
  561.         case 0xac: case 0xad: case 0xae: case 0xaf:
  562.         case 0xb0: case 0xb1: case 0xb2: case 0xb3:
  563.         case 0xb4: case 0xb5: case 0xb6: case 0xb7:
  564.         case 0xb8: case 0xb9: case 0xba: case 0xbb:
  565.         case 0xbc: case 0xbd: case 0xbe: case 0xbf:
  566.         case 0xc0: case 0xc1: case 0xc2: case 0xc3:
  567.         case 0xc4: case 0xc5: case 0xc6: case 0xc7:
  568.         case 0xc8: case 0xc9: case 0xca: case 0xcb:
  569.         case 0xcc: case 0xcd: case 0xce: case 0xcf:
  570.         case 0xd0: case 0xd1: case 0xd2: case 0xd3:
  571.         case 0xd4: case 0xd5: case 0xd6: case 0xd7:
  572.         case 0xd8: case 0xd9: case 0xda: case 0xdb:
  573.         case 0xdc: case 0xdd: case 0xde: case 0xdf:
  574.         case 0xe0: case 0xe1: case 0xe2: case 0xe3:
  575.         case 0xe4: case 0xe5: case 0xe6: case 0xe7:
  576.         case 0xe8: case 0xe9: case 0xea: case 0xeb:
  577.         case 0xec: case 0xed: case 0xee: case 0xef:
  578.         case 0xf0: case 0xf1: case 0xf2: case 0xf3:
  579.         case 0xf4: case 0xf5: case 0xf6: case 0xf7:
  580.         case 0xf8: case 0xf9: case 0xfa: case 0xfb:
  581.         case 0xfc: case 0xfd: case 0xfe:
  582. #endif
  583.  
  584.             units = CTOINT(c,0x7f);
  585.             if (escape == FORWARD)
  586.                 xpos += units;
  587.             else
  588.                 xpos -= units;
  589.             DBP((D_CAT,"ESC (hor): %02x\n", c&0x7f));
  590.             break;
  591.  
  592.         case 0xff:
  593.             DBP((D_CAT,"Illegal: %02x\n", c));
  594.             break;
  595.         }
  596.     }
  597. #ifdef    OPT
  598.     canonflush();
  599. #endif
  600.     if (be->bepage)
  601.         (*be->bepage)();
  602.     if (be->beepilog)
  603.         (*be->beepilog) ();
  604.     exit(0);
  605.     /* NOTREACHED */
  606. }
  607.  
  608. usage() {
  609.     fprintf(stderr, "usage: %s [-Ttype][-V]\n", progname);
  610.     fprintf(stderr, "  ... see troff2ps manpage for full description of %s\n",
  611.     OPTLIST);
  612. }
  613.  
  614. double
  615. calc(s)
  616. register char *s; {
  617.     double retval = 0.0;
  618.     char scale;
  619.     switch (sscanf(s, "%lf%c", &retval, &scale)) {
  620.     case 0:
  621.     case EOF:
  622.         retval = 0.0;
  623.     case 1:
  624.         retval *= TROFFRESOLUTION; /* default is inches */
  625.         break;
  626.     case 2:
  627.         switch(scale) {
  628.         default:
  629.             fprintf(stderr, "%s: bad scale %c\n", progname, scale);
  630.             retval = 0.0;
  631.         case 'i':
  632.             retval *= TROFFRESOLUTION;
  633.         case 'u':
  634.             break;
  635.         case 'c':
  636.             retval *= TROFFRESOLUTION * 50. / 127.;
  637.             break;
  638.         case 'p':
  639.             retval *= 6.;    /* points */
  640.             break;
  641.         case 'P':
  642.             retval *= 72.;    /* Picas */
  643.             break;
  644.         }
  645.         break;
  646.     }
  647.     return(retval);
  648. }
  649.  
  650. #ifdef    SPECIAL
  651.  
  652. dospecial(string)
  653. char *string; {
  654.     char buffer[512];
  655.     register struct cattab *p;
  656.     extern struct cattab *ditsearch();
  657.  
  658.     buffer[0] = '\0';
  659.  
  660.     DBP((D_SPEC,"Dospecial: (%d) %s\n", strlen(string), string));
  661.     while (*string)
  662.     switch(*string) {
  663.         case 'D': {
  664.         short values[100];
  665.         int opcode, ct, newx, newy, i;
  666.  
  667.         if (!(opcode = drawparse(&ct, values, &string[1])))
  668.             break;
  669.         newx = specXPos;
  670.         newy = specYPos;
  671.         if (opcode == 'e' || opcode == 'E')
  672.             newx += values[0];
  673.         else if (opcode != 't' && opcode != 'f') {
  674.             for (i = 0; i < ct/2; i++) {
  675.             newx += values[i*2];
  676.             newy += values[i*2+1];
  677.             }
  678.             if (i*2 < ct)
  679.             newx += values[i*2];
  680.         }
  681.  
  682. DBP((D_CAT, "Draw: xpos,ypos,opcode,ct,special = %d,%d,%d,%d,%s\n",
  683.     xpos, ypos, opcode, ct, string));
  684.  
  685.         if (be->bedraw)
  686.             (be->bedraw)(specXPos, specYPos, opcode, ct, values,
  687.             string);
  688.         specXPos = newx;
  689.         specYPos = newy;
  690.         *string = '\0';
  691.         return;
  692.         }
  693.         case 'C':
  694.  
  695.         if (extcount && !spctab)
  696.             fixtab();
  697.  
  698.         string++;
  699.         if (strlen(string) == 1)
  700.             p = dittab[(*string)&0xff];
  701.         else
  702.             p = ditsearch(string);
  703.  
  704.         if (!p) {
  705.             fprintf(stderr,
  706.             "%s: don't know this character: %s\n", progname,
  707.             string);
  708.             if (be->beputchar)
  709.             (*be->beputchar)(specXPos, specYPos, font, points, 0,
  710.                 string);
  711.         } else {
  712.             if (be->beputchar) {
  713.             if (p->ch_wididx == NTC) /* extended character */
  714.                 (be->beputchar)(specXPos, specYPos,
  715.                 p->ch_set == N ? -font-1: -symidx-1,
  716.                 points, p->ch_catidx,
  717.                 extchars[p->ch_catidx].t2b_charseq);
  718.             else
  719.                 (be->beputchar)(specXPos, specYPos,
  720.                 p->ch_set == N ? font: symidx,
  721.                 points, p->ch_catidx, (char *) NULL);
  722.             }
  723.         }
  724.  
  725.         *string = '\0';
  726.         return;
  727.  
  728.         case 'E':
  729.         fprintf(stderr, "%s\n", string+1);
  730.         *string = '\0';
  731.         return;
  732.  
  733.         case 'p':
  734.         case 'P':
  735.         if (be->bedraw)
  736.             (*be->bedraw)(specXPos, specYPos, NULL);
  737.         if (be->bepassthru)
  738.             (*be->bepassthru)(string+1);
  739.         else
  740.             printf("%s\n", string+1);
  741.         /* reset driver state! */
  742.         resetState();
  743.         *string = '\0';
  744.         return;
  745.  
  746.         case 'S':
  747.         system(string+1);
  748.         /* reset driver state! */
  749.         resetState();
  750.         *string = '\0';
  751.         return;
  752.  
  753.         case 'F':
  754.         if (be->befontsel)
  755.             (*be->befontsel)(*(string+1), string+2);
  756.         *string ='\0';
  757.         return;
  758. #ifdef    FORM
  759.         case 'L':
  760.         strcpy(buffer+2, string+1);
  761.         buffer[1] = '+';
  762.         *string = '\0';
  763.         string = buffer;
  764.         case 'O':
  765.         if (be->beoverlay)
  766.             (*be->beoverlay)(string+1);
  767.         *string = '\0';
  768.         return;
  769. #endif
  770.         case 'i':
  771.         strcpy(buffer, "b");
  772.  
  773.         case 'f':
  774.         case 'I':
  775.         strcat(buffer, "include ");
  776.         strcat(buffer, string+1);
  777.         interp(buffer, (be->bexlat && *string == 'F') ? be->bexlat:
  778.             FNULL, driver);
  779.         return;
  780.  
  781.         default:
  782.         fprintf(stderr, "%s: Illegal special sequence %s\n", progname, string);
  783.         return;
  784.     }
  785. }
  786.  
  787. #endif
  788.