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