home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2087 / lj.c
Encoding:
C/C++ Source or Header  |  1990-12-28  |  21.3 KB  |  892 lines

  1. /*    Copyright 1985, 1986, 1987, 1988 Chris Lewis
  2.         All Rights Reserved
  3.  
  4.     Permission to copy and further distribute is freely given provided
  5.     this copyright notice remains intact and that this software is not
  6.     sold for profit.
  7.  
  8.     Project:    Generic Troff drivers
  9.     Module:        lj.c
  10.     Author:     Chris Lewis
  11.     Specs:        LaserJet driver, hacked from ps.c and lcat.c
  12.  
  13.             Without font downloading, this is LJ compatible.
  14.             Font downloading will require a LJ+, LJ500+ or
  15.             LJ II.
  16.  
  17. */
  18.  
  19. #include "defs.h"
  20.  
  21. #ifdef    LJ
  22. #include "lj.h"
  23.  
  24. #ifndef    LJF
  25. char *LJF;
  26. #endif
  27.  
  28. #ifdef    PK
  29. #include "pk.h"
  30. #endif
  31.  
  32. #if    defined(PARTIAL)
  33. #include "pkc.h"
  34. #endif
  35.  
  36. #ifndef    lint
  37. static char SCCSid[] =
  38.     "@(#)lj.c: 2.1 Copyright 90/07/18 16:51:32 Chris Lewis";
  39. #endif
  40.  
  41. struct troff2befont ljStdFont[108] = {
  42.  
  43. /*    Note on X-shift, Y-shift and point scale factor:
  44.     The first two are shifts in the baseline position of the
  45.     character, and the third is a multiplier of the point size.
  46.     If they are zero, nothing happens.  If they are non-zero,
  47.     they are first multiplied by .01, then (in the case of the
  48.     shifts), multiplied by the current points to get a shift
  49.     value in TROFF2LJ[XY] coordinates.  In the case of point scale
  50.     factor, it is multiplied by <currentpointsize> * .01 and becomes
  51.     the pointsize of the sequence to be emitted.
  52.  */
  53. /*          +-------------------------------- Troff character number
  54.         |
  55.             |    +--------------------------- N: standard fonts
  56.             |    |                            S: symbol font
  57.             |    |                            D: draw macro
  58.             |    |                            n: new font
  59.             |    |
  60.             |    |  +------------------------ X-shift: scale by deci-point*100
  61.             |    |  |
  62.             |    |  |  +--------------------- Y-shift: scale by deci-point*100
  63.             |    |  |  |
  64.             |    |  |  |  +------------------ Point-scale
  65.             |    |  |  |  |
  66.             |    |  |  |  |   +-------------- Sequence
  67.             |    |  |  |  |   |
  68.             v    v  v  v  v   v */
  69.     /*  0*/    {N, 0, 0, 0, "h"},
  70.     /*  1*/    {N, 0, 0, 0, "t"},
  71.     /*  2*/    {N, 0, 0, 0, "n"},
  72.     /*  3*/    {N, 0, 0, 0, "m"},
  73.     /*  4*/    {N, 0, 0, 0, "l"},
  74.     /*  5*/    {N, 0, 0, 0, "i"},
  75.     /*  6*/    {N, 0, 0, 0, "z"},
  76.     /*  7*/    {N, 0, 0, 0, "s"},
  77.     /*  8*/    {N, 0, 0, 0, "d"},
  78.     /*  9*/    {N, 0, 0, 0, "b"},
  79.     /* 10*/    {N, 0, 0, 0, "x"},
  80.     /* 11*/    {N, 0, 0, 0, "f"},
  81.     /* 12*/    {N, 0, 0, 0, "j"},
  82.     /* 13*/    {N, 0, 0, 0, "u"},
  83.     /* 14*/    {N, 0, 0, 0, "k"},
  84.     /* 15*/    {N, 0, 0, 0, NOC},
  85.     /* 16*/    {N, 0, 0, 0, "p"},
  86.     /* 17*/    {S, 0, 0, 0, "\366"},
  87.     /* 18*/    {N, 0, 0, 0, ";"},
  88.     /* 19*/    {N, 0, 0, 0, NOC},
  89.     /* 20*/    {N, 0, 0, 0, "a"},
  90.     /* 21*/    {N, 0, -200, 0, "_"},
  91.     /* 22*/    {N, 0, 0, 0, "c"},
  92.     /* 23*/    {N, 0, 0, 0, "`"},
  93.     /* 24*/    {N, 0, 0, 0, "e"},
  94.     /* 25*/    {N, 0, 0, 0, "'"},
  95.     /* 26*/    {N, 0, 0, 0, "o"},
  96.     /* 27*/    {N, 0, 0, 0, "\367"},
  97.     /* 28*/    {N, 0, 0, 0, "r"},
  98.     /* 29*/    {N, 0, 0, 0, "\370"},
  99.     /* 30*/    {N, 0, 0, 0, "v"},
  100.     /* 31*/    {N, 0, 0, 0, "-"},
  101.     /* 32*/    {N, 0, 0, 0, "w"},
  102.     /* 33*/    {N, 0, 0, 0, "q"},
  103.     /* 34*/    {N, 0, 0, 0, "/"},
  104.     /* 35*/    {N, 0, 0, 0, "."},
  105.     /* 36*/    {N, 0, 0, 0, "g"},
  106.     /* 37*/    {N, 0, 0, 0, "3/4"},
  107.     /* 38*/    {N, 0, 0, 0, ","},
  108.     /* 39*/    {N, 0, 0, 0, "&"},
  109.     /* 40*/    {N, 0, 0, 0, "y"},
  110.     /* 41*/    {N, 0, 0, 0, NOC},
  111.     /* 42*/    {N, 0, 0, 0, "%"},
  112.     /* 43*/    {N, 0, 0, 0, NOC},
  113.     /* 44*/    {N, 0, 0, 0, "Q"},
  114.     /* 45*/    {N, 0, 0, 0, "T"},
  115.     /* 46*/    {N, 0, 0, 0, "O"},
  116.     /* 47*/    {N, 0, 0, 0, "H"},
  117.     /* 48*/    {N, 0, 0, 0, "N"},
  118.     /* 49*/    {N, 0, 0, 0, "M"},
  119.     /* 50*/    {N, 0, 0, 0, "L"},
  120.     /* 51*/    {N, 0, 0, 0, "R"},
  121.     /* 52*/    {N, 0, 0, 0, "G"},
  122.     /* 53*/    {N, 0, 0, 0, "I"},
  123.     /* 54*/    {N, 0, 0, 0, "P"},
  124.     /* 55*/    {N, 0, 0, 0, "C"},
  125.     /* 56*/    {N, 0, 0, 0, "V"},
  126.     /* 57*/    {N, 0, 0, 0, "E"},
  127.     /* 58*/    {N, 0, 0, 0, "Z"},
  128.     /* 59*/    {N, 0, 0, 0, "D"},
  129.     /* 60*/    {N, 0, 0, 0, "B"},
  130.     /* 61*/    {N, 0, 0, 0, "S"},
  131.     /* 62*/    {N, 0, 0, 0, "Y"},
  132.     /*from here on are actually code 1-45, upper half of font */
  133.     /* 63*/    {N, 0, 0, 0, "F"},
  134.     /* 64*/    {N, 0, 0, 0, "X"},
  135.     /* 65*/    {N, 0, 0, 0, "A"},
  136.     /* 66*/    {N, 0, 0, 0, "W"},
  137.     /* 67*/    {N, 0, 0, 0, "J"},
  138.     /* 68*/    {N, 0, 0, 0, "U"},
  139.     /* 69*/    {N, 0, 0, 0, "K"},
  140.     /* 70*/    {N, 0, 0, 0, "0"},
  141.     /* 71*/    {N, 0, 0, 0, "1"},
  142.     /* 72*/    {N, 0, 0, 0, "2"},
  143.     /* 73*/    {N, 0, 0, 0, "3"},
  144.     /* 74*/    {N, 0, 0, 0, "4"},
  145.     /* 75*/    {N, 0, 0, 0, "5"},
  146.     /* 76*/    {N, 0, 0, 0, "6"},
  147.     /* 77*/    {N, 0, 0, 0, "7"},
  148.     /* 78*/    {N, 0, 0, 0, "8"},
  149.     /* 79*/    {N, 0, 0, 0, "9"},
  150.     /* 80*/    {N, 0, 0, 0, "*"},
  151.     /* 81*/    {N, 0, 0, 0, "\366"},
  152.     /* 82*/    {N, 0, 0, 0, "fi"},
  153.     /* 83*/    {N, 0, 0, 0, "fl"},
  154.     /* 84*/    {N, 0, 0, 0, "ff"},
  155.     /* 85*/    {N, 0, 0, 0, "\277"},
  156.     /* 86*/    {N, 0, 0, 0, "ffl"},
  157.     /* 87*/    {N, 0, 0, 0, "ffi"},
  158.     /* 88*/    {N, 0, 0, 0, "("},
  159.     /* 89*/    {N, 0, 0, 0, ")"},
  160.     /* 90*/    {N, 0, 0, 0, "["},
  161.     /* 91*/    {N, 0, 0, 0, "]"},
  162.     /* 92*/    {N, 0, 0, 0, "\263"},
  163.     /* 93*/    {S, 0, 0, 0, "\316"},
  164.     /* 94*/    {N, 0, 0, 0, "="},
  165.     /* 95*/    {N, 0, 0, 0, "O\br"},
  166.     /* 96*/    {N, 0, 0, 0, ":"},
  167.     /* 97*/    {N, 0, 0, 0, "+"},
  168.     /* 98*/    {N, 0, 0, 0, NOC},
  169.     /* 99*/    {N, 0, 0, 0, "!"},
  170.     /*100*/ {S, 0, 0, 0, "\314"},
  171.     /*101*/    {N, 0, 0, 0, "?"},
  172.     /*102*/ {N, 0, 0, 0, "\250"},
  173.     /*103*/    {N, 0, 0, 0, "|"},
  174.     /*104*/    {N, 0, 0, 0, NOC},
  175.     /*105*/    {S, 0, 0, 0, "\331"},
  176.     /*106*/    {S, 0, 0, 0, "\332"},
  177.     /*107*/    {N, 0, 0, 0, "$"}
  178. };
  179.  
  180. struct troff2befont ljSymFont[] = {
  181. /*          +-------------------------------- Troff character number
  182.         |
  183.             |    +--------------------------- N: standard fonts
  184.             |    |                            S: symbol font
  185.             |    |                            D: draw macro
  186.             |    |                            n: new font
  187.             |    |
  188.             |    |  +------------------------ X-shift: scale by deci-point*100
  189.             |    |  |
  190.             |    |  |  +--------------------- Y-shift: scale by deci-point*100
  191.             |    |  |  |
  192.             |    |  |  |  +------------------ Point-scale (scaled by 100)
  193.             |    |  |  |  |
  194.             |    |  |  |  |   +-------------- Sequence
  195.             |    |  |  |  |   |
  196.             v    v  v  v  v   v */
  197.     /*  0*/    {S, 0, 0, 0, "\167"},
  198.     /*  1*/    {S, 0, 0, 0, "\150"},
  199.     /*  2*/    {S, 0, 0, 0, "\155"},
  200.     /*  3*/    {S, 0, 0, 0, "\154"},
  201.     /*  4*/    {S, 0, 0, 0, "\153"},
  202.     /*  5*/    {S, 0, 0, 0, "\151"},
  203.     /*  6*/    {S, 0, 0, 0, "\146"},
  204.     /*  7*/    {S, 0, 0, 0, "\162"},
  205.     /*  8*/    {S, 0, 0, 0, "\144"},
  206.     /*  9*/    {S, 0, 0, 0, "\142"},
  207.     /* 10*/    {S, 0, 0, 0, "\156"},
  208.     /* 11*/    {S, 0, 0, 0, "\147"},
  209.     /* 12*/    {S, 0, 0, 0, "\165"},
  210.     /* 13*/    {S, 0, 0, 0, "\164"},
  211.     /* 14*/    {S, 0, 0, 0, "\152"},
  212.     /* 15*/    {S, 0, 0, 0, NOC},
  213.     /* 16*/    {S, 0, 0, 0, "\160"},
  214.     /* 17*/    {N, 0, 0, 0, "@"},
  215.     /* 18*/    {S, 0, 0, 0, "\243"},
  216.     /* 19*/    {S, 0, 0, 0, NOC},
  217.     /* 20*/    {S, 0, 0, 0, "\141"},
  218.     /* 21*/    {N, 0, 0, 0, "|"},
  219.     /* 22*/    {S, 0, 0, 0, "\166"},
  220.     /* 23*/    {N, 0, 0, 0, "\042"},
  221.     /* 24*/    {S, 0, 0, 0, "\145"},
  222.     /* 25*/    {N, 0, 0, 0, "="},
  223.     /* 26*/    {S, 0, 0, 0, "o"},
  224.     /* 27*/    {S, 0, 0, 0, "\244"},
  225.     /* 28*/    {S, 0, 0, 0, "\161"},
  226.     /* 29*/    {S, 0, 0, 0, "\241"},
  227.     /* 30*/    {S, 0, 0, 0, "\163"},
  228.     /* 31*/    {N, 0, 0, 0, "_"},
  229.     /* 32*/    {N, 0, 0, 0, "\\"},
  230.     /* 33*/    {S, 0, 0, 0, "\127"},
  231.     /* 34*/    {S, 0, 0, 0, "\177"},
  232.     /* 35*/    {S, 0, 0, 0, "\044"},
  233.     /* 36*/    {S, 0, 0, 0, "\143"},
  234.     /* 37*/    {S, 0, 0, 0, "\277"},
  235.     /* 38*/    {S, 0, 0, 0, "\046"},
  236.     /* 39*/ {S, 0, 0, 0, "\375"},
  237.     /* 40*/    {S, 0, 0, 0, "\170"},
  238.     /* 41*/    {S, 0, 0, 0, NOC},
  239.     /* 42*/    {S, 0, 0, 0, "\131"},
  240.     /* 43*/    {S, 0, 0, 0, NOC},
  241.     /* 44*/    {S, 0, 0, 0, "\125"},
  242.     /* 45*/    {S, 0, 0, 0, "\110"},
  243.     /* 46*/    {S, 0, 0, 0, "\130"},
  244.     /* 47*/    {S, 0, 0, 0, "\265"},
  245.     /* 48*/    {S, 0, 0, 0, "\260"},
  246.     /* 49*/    {S, 0, 0, 0, "\123"},
  247.     /* 50*/    {S, 0, 0, 0, "\113"},
  248.     /* 51*/    {N, 0, 0, 0, "\366"},
  249.     /* 52*/    {S, 0, 0, 0, "\103"},
  250.     /* 53*/    {S, 0, 0, 0, "\325"},
  251.     /* 54*/    {S, 0, 0, 0, "\120"},
  252.     /* 55*/    {S, 0, 0, 0, "\272"},
  253.     /* 56*/    {S, 0, 0, 0, "\273"},
  254.     /* 57*/    {N, 0, 0, 0, "~"},
  255.     /* 58*/    {S, 0, 0, 0, "\132"},
  256.     /* 59*/    {S, 0, 0, 0, "\104"},
  257.     /* 60*/    {S, 0, 0, 0, "\041"},
  258.     /* 61*/    {S, 0, 0, 0, "\122"},
  259.     /* 62*/    {S, 0, 0, 0, "\174"},
  260.     /* 63*/    {N, 0, 0, 0, ">"},
  261.     /* 64*/    {S, 0, 0, 0, "\116"},
  262.     /* 65*/    {N, 0, 0, 0, "<"},
  263.     /* 66*/    {N, 0, 0, 0, "/"},
  264.     /* 67*/    {S, 0, 0, 0, "\266"},
  265.     /* 68*/    {S, 0, 0, 0, "\124"},
  266.     /* 69*/    {S, 0, 0, 0, "\310"},
  267.     /* 70*/    {S, 0, 0, 0, "\360"},
  268.     /* 71*/    {S, 0, 0, 0, "\342"},
  269.     /* 72*/    {S, 0, 0, 0, "\365"},
  270.     /* 73*/    {S, 0, 0, 0, "\343"},
  271.     /* 74*/    {S, 0, 0, 0, "\344"},
  272.     /* 75*/    {S, 0, 0, 0, "\362"},
  273.     /* 76*/    {S, 0, 0, 0, "\363"},
  274.     /* 77*/    {S, 0, 0, 0, "\364"},
  275.     /* 78*/    {S, 0, 0, 0, "\361"},
  276.     /* 79*/    {S, 0, 0, 0, "\341"},
  277.     /* 80*/    {S, 0, 0, 0, "\340"},
  278.     /* 81*/    {S, 0, 0, 0, "\052"},
  279.     /* 82*/    {S, 0, 0, 0, "\045"},
  280.     /* 83*/    {S, 0, 0, 0, "\376"},
  281.     /* 84*/    {S, 0, 0, 0, "\134"},
  282.     /* 85*/    {S, 0, 0, 0, "\136"},
  283.     /* 86*/    {S, 0, 0, 0, "\175"},
  284.     /* 87*/    {N, 0, 0, 0, "=\b/"},
  285.     /* 88*/    {N, 0, 0, 0, "{"},
  286.     /* 89*/    {N, 0, 0, 0, "}"},
  287.     /* 90*/    {N, 0, 0, 0, "\250"},
  288.     /* 91*/    {N, 0, 0, 0, "\251"},
  289.     /* 92*/    {N, 0, 0, 0, "^"},
  290.     /* 93*/    {N, 0, 0, 0, "#"},
  291.     /* 94*/    {S, 0, 0, 0, "\373"},
  292.     /* 95*/    {S, 0, 0, 0, "\267"},
  293.     /* 96*/    {N, 0, 0, 0, "~"},
  294.     /* 97*/    {N, 0, 0, 0, "\322"},
  295.     /* 98*/    {N, 0, 0, 0, NOC},
  296.     /* 99*/    {S, 0, 0, 0, "\317"},
  297.     /*100*/    {N, -220, 0, 0, "|"},
  298.     /*101*/    {N, 0, 2, 0, "*"},
  299.     /*102*/    {S, 0, 0, 0, "\276"},
  300.     /*103*/    {S, 0, 0, 0, "\315"},
  301.     /*104*/    {S, 0, 0, 0, NOC},
  302.     /*105*/    {N, 0, 0, 0, "+"},
  303.     /*106*/    {S, 0, 0, 0, "\242"},
  304.     /*107*/    {N, 0, 0, 0, "\275"}
  305. };
  306.  
  307. int fontCount = 0;
  308.  
  309. ljPage() {
  310.     printf("\033&l0H");
  311.     pagePending = 1;
  312. }
  313.  
  314. static
  315. doPageStart() {
  316.     currentPage++;
  317.     fontCount = 0;
  318.     pagePending = 0;
  319. }
  320.  
  321. static
  322. putoct(s)
  323. char *s; {
  324.     int d;
  325.     if (strlen(s) < 3) {
  326.     fprintf(stderr, "%s: octal sequence in fonts.l[kj] bad\n", progname);
  327.     exit(1);
  328.     }
  329.     d = (*s - '0') * 64 + (*(s+1) - '0') * 8 + *(s+2) - '0';
  330.     putchar(d);
  331. }
  332.  
  333. static
  334. int
  335. ptcvt(points)
  336. int  points; {
  337.     register int r;
  338.     switch (points) {
  339.     case 6:  r = 0; break;
  340.     case 7:  r = 1; break;
  341.     case 8:  r = 2; break;
  342.     case 9:  r = 3; break;
  343.     case 10: r = 4; break;
  344.     case 11: r = 5; break;
  345.     case 12: r = 6; break;
  346.     case 14: r = 7; break;
  347.     case 16: r = 8; break;
  348.     case 18: r = 9; break;
  349.     case 20: r = 10; break;
  350.     case 22: r = 11; break;
  351.     case 24: r = 12; break;
  352.     case 28: r = 13; break;
  353.     case 36: r = 14; break;
  354.     default: r = 15; break;
  355.     }
  356.     return(r);
  357. }
  358.  
  359. /*    This function originally from Ronald Florence (ron@mlfarm),
  360.     but extensively modified for new fontFlags mechanisms.
  361.  
  362.     We'll go at most 4 points up or down.  If this fails,
  363.     we'll let the printer decide...  You may want to tweak
  364.     these arrays.
  365.  
  366.     We go up first for requested pointsizes > 10, and down
  367.     first for requested pointsizes < 10.  Seems to work best
  368.     with EQN.
  369.  */
  370.  
  371. static int
  372. bestmatch(font, points)
  373. int font, points;  {
  374.  
  375.     static int smalltry[ ] = { 0, -1, 1, -2, 2, -3, 3, -4, 4, 100 },
  376.                  bigtry[ ] = { 0, 1, 2, -1, -2, 3, 4, -4, 100 };
  377.  
  378.     register char *p;
  379.     register int *ip;
  380.  
  381.     ip = (points < 10) ? smalltry : bigtry;
  382.     p = fonttable[font].fontFlags;
  383.  
  384.     for ( ; *ip < 100; ip++)
  385.     if (p[ptcvt(points + *ip)] != 'n')
  386.         return(points + *ip);
  387.  
  388.     return (points);
  389. }
  390.  
  391. #ifdef    INCR
  392. dumpseq(font, pointidx, seq)
  393. int font, pointidx;
  394. register char *seq; {
  395.     int fn = (font << 4) + pointidx;
  396.     static int lastftid = -1;
  397.     register int c;
  398.     register struct pkc *pc = (struct pkc *) NULL;
  399.  
  400.     DBP((D_FONT, "dumpseq font: %d, idx: %d, seq: %s\n", font,
  401.     pointidx, seq));
  402.  
  403.     for (;c = (*seq)&0xff; seq++) {
  404.     if (!downchar(font, c, pointidx)) {
  405.  
  406.         for (pc = fonttable[font].map->pkfont[pointidx]->pkp_chars;
  407.         pc; pc = pc->pkc_next)
  408.         if (pc->pkc_char == c)
  409.             break;
  410.  
  411.         setdown(font, c, pointidx);
  412.  
  413.         if (!pc)
  414.         continue;
  415.  
  416.         if (lastftid != fn) {
  417.         DBP((D_FONT,"Emitting download font select (%d)\n", fn));
  418.         printf("\033*c%dD", fn);
  419.         lastftid = fn;
  420.         }
  421.  
  422.         DBP((D_FONT,"Downloading %02x\n", pc->pkc_char));
  423.         epkc_desc(pc, stdout);
  424.     } else
  425.         DBP((D_FONT,"Already downloaded %02x\n", c));
  426.     }
  427. }
  428. #endif
  429.  
  430. ljSetFont(font, selpoints, fontcode, sequence)
  431. int font, selpoints, fontcode;
  432. char *sequence; {
  433.     int points, pointidx;
  434.     register char *pf, *p;
  435.     register struct pkp *pk;
  436. #if    !defined(INCR) && defined(PK)
  437.     register struct pkc *pc;
  438. #endif
  439.     char buf[BUFSIZ];
  440. #ifndef    PARTIAL
  441.     FILE *fontfile;
  442. #endif
  443.     int count;
  444.     int ftid;
  445.  
  446. #ifdef    COMPRESS
  447.     int compressed = 0;
  448. #endif
  449.  
  450.  
  451. #ifndef    INCR
  452.     if (lastPoints == selpoints && font == lastFont)
  453.     return;
  454. #endif
  455.  
  456.     points = bestmatch(font, selpoints);
  457.     pointidx = ptcvt(points);
  458.  
  459.     pf = &fonttable[font].fontFlags[pointidx];
  460.     ftid = (font << 4) + pointidx;
  461.  
  462. #ifdef    INCR
  463. #ifdef    SFP
  464.     if (*pf == 'S' || *pf == 'P') {
  465. #else
  466.     if (*pf == 'P') {
  467. #endif
  468.     /* header downloaded, check and download individual characters */
  469.     dumpseq(font, pointidx, sequence);
  470.  
  471.     if (lastPoints != points || font != lastFont) {
  472.         DBP((D_FONT, "Selecting font %d\n", ftid));
  473.         lastPoints = points;
  474.         lastFont = font;
  475.         printf("\033(%dX", ftid);
  476.     }
  477.  
  478.     return;
  479.  
  480.     }
  481.  
  482.     if (lastPoints == selpoints && font == lastFont)
  483.     return;
  484. #endif
  485.  
  486.     lastPoints = selpoints;
  487.     lastFont = font;
  488.  
  489.     switch(*pf) {
  490. #ifdef    PK
  491.     case 'p':
  492. #ifdef    PARTIAL
  493.     case 's':
  494. #endif
  495.         sprintf(buf, "%s/%s.%d.%s", LJF,
  496.         fonttable[font].troffName, points,
  497.             (*pf == 's') ? "sfp":"pk");
  498.  
  499.         fontCount++;
  500.         if (fontCount >= MAXDLFONTS) {
  501. #ifdef    INCR
  502.         pkflush(font, pointidx);
  503. #else
  504.         fprintf(stderr, "Too many fonts (page %d), simplify!\n",
  505.             currentPage);
  506. #endif
  507.         }
  508.         DBP((D_FONT,"FONTLOAD PK font (ftid: %d) %s.%d via '%s'\n",
  509.         ftid, fonttable[font].troffName,
  510.         points, buf));
  511.  
  512.         /* Read the PK file in-core */
  513.         pk = pk_read(buf,fontcode);
  514.  
  515.         /* Set the fontid we'll use */
  516.         printf("\033*c%dd4F", ftid);
  517.  
  518.         /* Emit the SFP header */
  519.         epk_desc(pk, stdout);
  520.  
  521. #ifndef    INCR
  522.         /* Emit each character */
  523.         for (pc = pk->pkp_chars; pc; pc = pc->pkc_next) {
  524.         DBP((D_FONT,"Downloading ch %02x\n", pc->pkc_char);
  525.         epkc_desc(pc, stdout));
  526.         }
  527.  
  528.         /* Clobber in-core PK */
  529.         pk_destroy(pk);
  530. #else
  531.         fonttable[font].map->pkfont[pointidx] = pk;
  532.         dumpseq(font, pointidx, sequence);
  533. #endif
  534.  
  535.         *pf = toupper(*pf);
  536.  
  537.         /* buf */
  538.         goto setdownloaded;
  539. #else
  540.     case 'p':
  541.         fprintf(stderr,
  542.         "%s: Font %s, size: %d is a PK - PK not defined in defs.h\n",
  543.         progname, fonttable[font].troffName, selpoints);
  544.         goto setbuiltin;
  545. #endif
  546.  
  547. #ifndef    PARTIAL
  548.     case 's':
  549.         sprintf(buf, "%s/lj/%s.%d.sfp", LIBDIR, fonttable[font].troffName,
  550.         points);
  551.  
  552.         fontfile = fopen(buf, "r");
  553.  
  554. #ifdef    COMPRESS
  555.         if (!fontfile) {
  556.         sprintf(buf, "%s %s/lj/%s.%d.sfp.Z",
  557.             COMPRESS, LIBDIR, fonttable[font].troffName, points);
  558.         fontfile = popen(buf, "r");
  559.         compressed = 1;
  560.         }
  561. #endif
  562.  
  563.         if (!fontfile) {
  564.         fprintf(stderr, "%s: cannot open fontfile\n(%s)\n", progname,
  565.             buf);
  566.         goto setbuiltin;
  567.         }
  568.  
  569.         fontCount++;
  570.         if (fontCount >= MAXDLFONTS) {
  571. #ifdef    INCR
  572.         pkflush(font, pointidx);
  573. #else
  574.         fprintf(stderr, "Too many fonts (page %d), simplify!\n",
  575.             currentPage);
  576. #endif
  577.         }
  578.  
  579.         DBP((D_FONT,"Loading font (ftid: %d) %s.%d via '%s'\n",
  580.         ftid, fonttable[font].troffName,
  581.         points, buf));
  582.  
  583.         printf("\033*c%dd4F", ftid);
  584.  
  585.         while(0 < (count = fread(buf, sizeof(char), sizeof(buf), fontfile)))
  586.         fwrite(buf, sizeof(char), count, stdout);
  587.  
  588. #ifdef    COMPRESS
  589.         if (compressed) {
  590.         if (!pclose(fontfile)) {
  591.             fprintf(stderr, "%s: compress failed!\n", progname);
  592.             exit(1);
  593.         }
  594.         } else
  595. #endif
  596.         fclose(fontfile);
  597.  
  598.         *pf = toupper(*pf);
  599. #endif
  600.         /* Fall Thru */
  601.  
  602.     case 'S': case 'P':
  603.         /* Select primary font by font id */
  604.     setdownloaded:
  605.         DBP((D_FONT, "Selecting font2 %d\n", ftid));
  606.         printf("\033(%dX", ftid);
  607.         break;
  608.  
  609.     default:
  610.     setbuiltin:
  611.         *pf = 'b';
  612.  
  613.     case 'b':
  614.         /* if builtin font, select it by characteristic */
  615.         for (p = fonttable[font].fontSeq; *p; p++) {
  616.         if (*p == '\\') {
  617.             putoct(p+1);
  618.             p+=3;
  619.         } else
  620.             putchar(*p);
  621.         }
  622.         printf("\033(s%dV", points);
  623.         break;
  624.     }
  625. }
  626.  
  627. ljChar(x, y, font, points, troffChar, sequence)
  628. int x, y;
  629. int font, points, troffChar;
  630. char *sequence; {
  631.     register int nx = TROFF2LJX(x), ny = TROFF2LJY(y);
  632.     register struct troff2befont *rp;
  633.  
  634. #ifndef    OPT
  635.     sequence = (char *) NULL;
  636. #endif
  637.  
  638.     if (pagePending) {
  639.     resetState();
  640.     doPageStart();
  641.     }
  642.  
  643.     DBP((D_BEND,"BEFORE (troffChar,x,y,font,points) = (%d,%d,%d,%d,%d)\n",
  644.     troffChar, x, y, font, points));
  645.  
  646.     if (font == 3) {
  647.     rp = &be->besymfont[troffChar];
  648.     } else {
  649.     rp = &be->bestdfont[troffChar];
  650.     }
  651.  
  652.     switch(rp->t2b_font) {
  653.     /* Only fonts with "N" are subject to font translation */
  654.     case N:
  655.         if (font == 3)
  656.         font = 0;    /* Special chars are Roman */
  657.         else {
  658.         DBP((D_BEND,"ljSetChar %d->%s (%s)\n", font,
  659.             xlatetable[font]->troffName,
  660.             xlatetable[font]->fontName));
  661.         font = xlatetable[font] - fonttable;
  662.         }
  663.         break;
  664.     case S:
  665.         font = 3;
  666.         break;
  667.     case D:
  668.         break;
  669.     default:
  670.         /* Typically used when the R and S fonts don't have the
  671.            character desired, so select the font via the index
  672.            in the fonts.?? file */
  673.         font = rp->t2b_font;
  674.         break;
  675.     }
  676.  
  677.     if (!sequence)
  678.     sequence = rp->t2b_charseq;
  679.  
  680.     if (!sequence) {
  681.     fprintf(stderr, "%s: No coding for char %d in %d font\n",
  682.         progname, troffChar, font);
  683.     return;
  684.     }
  685.  
  686.     /*    We're committed now - the "if" statements avoid floating
  687.     arithmetic on slow machines */
  688.  
  689.     if (rp->t2b_scale) points *= (.01 * rp->t2b_scale);
  690.     if (rp->t2b_xc) nx += points * (.01 * rp->t2b_xc);
  691.     if (rp->t2b_yc) ny += points * (.01 * rp->t2b_yc);
  692.  
  693.     ljSetFont(font, points, rp->t2b_font, sequence);
  694.  
  695.     DBP((D_BEND,"AFTER (sequence,x,y,font,points) = (%s,%d,%d,%d,%d)\n",
  696.     sequence, nx, ny, font, points));
  697.  
  698. /*    Egads, I discovered that 42% of the time in troff2ps was spent
  699.     doing these damn conversions! */
  700.  
  701. #define    XYS    "\033&a%dh%dV%s"
  702. #define    XS    "\033&a%dH%s"
  703.  
  704.     if (lastYPos != ny) {
  705.     printf(XYS, nx, ny, sequence);
  706.     lastYPos = ny;
  707.     } else
  708.     printf(XS, nx, sequence);
  709. }
  710.  
  711. ljProlog() {
  712.     extern char *ctime();
  713.     FILE *library;
  714.     int c;
  715.     register char *p;
  716.  
  717. #ifndef    LJF
  718.     LJF = mustmalloc(strlen(LIBDIR) + 5, "ljprolog");
  719.     sprintf(LJF, "%s/lj", LIBDIR);
  720. #endif
  721.  
  722.     /* to ensure that the strings are long enough for indexing and
  723.        are sufficiently initialized */
  724.  
  725.     for (c = 0; fonttable[c].troffName; c++) {
  726.     register int i;
  727.     p = mustmalloc(20, "ljfontflags");
  728.     strncpy(p, fonttable[c].fontFlags, 16);
  729.     p[16] = '\0';
  730.     free(fonttable[c].fontFlags);
  731.     for (i = strlen(p); i < 16; i++)
  732.         p[i] = 'n';
  733.     fonttable[c].fontFlags = p;
  734.     }
  735.  
  736. #if    defined(INCR)
  737.     /* create empty downloaded-yet arrays */
  738.     for (c = 0; fonttable[c].troffName; c++) {
  739.     register int i;
  740.     for (i = 0, p = fonttable[c].fontFlags; *p; p++, i++)
  741. #ifdef    SFP
  742.         if (*p == 'p' || *p == 's') {
  743. #else
  744.         if (*p == 'p') {
  745. #endif
  746.         DBP((D_FONT, "Allocating font %d, size %d\n",
  747.             c, i));
  748.         if (!fonttable[c].map) {
  749.             fonttable[c].map = (struct downmaps *)
  750.             mustmalloc(sizeof(struct downmaps), "downmaps");
  751.         }
  752.         fonttable[c].map->nm[i] = (ETYP *) mustmalloc(ELEN *
  753.             sizeof(ETYP), "Nmaps");
  754.         fonttable[c].map->lastpage[i] = 0;
  755.         }
  756.     }
  757.  
  758. #ifdef    DEBUG
  759.     dumpmaps(1);
  760. #endif
  761.  
  762. #endif
  763.  
  764. #if    defined(PARTIAL)
  765.     /* create need-arrays */
  766.     for (c = 0; c < 108; c++)
  767.     if (ljStdFont[c].t2b_charseq != NOC)
  768.         for (p = ljStdFont[c].t2b_charseq; *p; p++)
  769.         addneedchar(ljStdFont[c].t2b_font, *p);
  770.  
  771.     for (c = 0; c < 108; c++)
  772.     if (ljSymFont[c].t2b_charseq != NOC)
  773.         for (p = ljSymFont[c].t2b_charseq; *p; p++)
  774.         addneedchar(ljSymFont[c].t2b_font, *p);
  775. #endif
  776.  
  777. #if    defined(DEBUG) && defined(PARTIAL)
  778.     dumpmaps(0);
  779. #endif
  780.  
  781.     currentPage = 0;
  782.     pagePending = 1;
  783.  
  784.     library = libopen(printer, "lib");
  785.  
  786.     ljXlate(library);
  787.     fclose(library);
  788.     doprologs();
  789. }
  790.  
  791. ljEpilog() {
  792. #if    defined(INCR)
  793.     register struct fonttable *fp;
  794.     register int i;
  795.     /* delete fonts still active that we downloaded */
  796.     for (fp = fonttable; fp->troffName; fp++)
  797.     if (fp->map)
  798.         for (i = 0; i < 14; i++)
  799.         if (fp->map->pkfont[i])
  800.             printf("\033*c%dd2F", ((fp - fonttable) << 4) + i);
  801. #endif
  802.  
  803. #if    defined(DEBUG) && defined(INCR)
  804.     dumpmaps(1);
  805. #endif
  806. }
  807.  
  808. /*    Copy the library file to the standard output, stripping
  809.     %line\n
  810.     %%%<something> is a metadirective
  811.     and converting \nnn and \xnn as you go.
  812.     Strip out line termination.
  813. */
  814.  
  815. ljXlate(library)
  816. FILE *library; {
  817.     char buf[4];
  818.     int c, i;
  819.     c = getc(library);
  820.     while(!feof(library)) {
  821.  
  822.       nextchar:
  823.  
  824.     switch(c) {
  825.         case '%':
  826.         /* strip from percent sign to end of line */
  827.         /* If line is %%%<something> pass onto interp */
  828.         if (((c = getc(library)) == '%') &&
  829.             ((c = getc(library)) == '%')) {
  830.             char buf2[4];
  831.             sprintf(buf2, ".%s", be->bename);
  832.             fgets(buf, strlen(buf), library);
  833.             interp(buf, ljXlate, buf2);
  834.             break;
  835.         }
  836.         while ((c = getc(library)) != EOF && c != '\n');
  837.         break;
  838.         case '\n':    /* throw away real newlines. */
  839.         break;
  840.         case '\\':
  841.         c = getc(library);
  842.         if (c == 'x' || c == 'X') {
  843.             i = 0;
  844.             while(1) {
  845.             c = getc(library);
  846.  
  847.             if (c == EOF || !((c >= '0' && c <= '9') ||
  848.                       (c >= 'A' && c <= 'F') ||
  849.                       (c >= 'a' && c <= 'f')))
  850.                 goto nextchar;
  851.  
  852.             buf[i++] = c;
  853.             if (i == 2) {
  854.                 buf[i] = '\0';
  855.                 sscanf(buf, "%x", &i);
  856.                 putchar(i);
  857.                 i = 0;
  858.             }
  859.             }
  860.         } else {
  861.             buf[0] = c;
  862.             i = 1;
  863.             while(1) {
  864.             c = getc(library);
  865.             if (c == EOF || c < '0' || c > '7')
  866.                 goto nextchar;
  867.             buf[i++] = c;
  868.             if (i == 3) {
  869.                 buf[i] = '\0';
  870.                 sscanf(buf, "%o", &i);
  871.                 putchar(i);
  872.                 i = 0;
  873.             }
  874.             }
  875.         }
  876.         /* NOTREACHED */
  877.  
  878.         case ' ': case '\t':
  879.         break;
  880.  
  881.         case EOF:
  882.         fprintf(stderr, "%s: Unexpected eof on ljlib\n", progname);
  883.         break;
  884.  
  885.         default:
  886.         putchar(c);
  887.     }
  888.     c = getc(library);
  889.     }
  890. }
  891. #endif
  892.