home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume3 / laserjet / part2 / hp.c
Encoding:
C/C++ Source or Header  |  1986-11-30  |  27.8 KB  |  1,240 lines

  1. /* vi:se ts=4 sw=4 wm=0: */
  2. static char *RCSid =
  3.         "$Header: hp.c,v 1.1.1.9 85/08/17 15:53:35 ron Exp $";
  4.  
  5. /*
  6.  * hp.c - Copyright (c) 1985 by Ron Saad (ron1!ron)
  7.  * All Rights Reserved.
  8.  *
  9.  * This code maybe freely distributed in source
  10.  * for non commercial purposes.
  11.  * Please keep this notice intact.
  12.  */
  13.  
  14. /*
  15.  * $Log:    hp.c,v $
  16.  * Revision 1.1.1.9  85/08/17  15:53:35  ron
  17.  * As usual, just 'one more thing ..' - moved the
  18.  * size cheating code to where it belongs - just before
  19.  * the file gets read in.
  20.  * still to do:
  21.  * make vgoto adjust the height to scale for not having a full
  22.  * 11 inches, otherwise get bogus page feeds.
  23.  * 
  24.  * Revision 1.1.1.8  85/08/15  14:50:29  ron
  25.  * this seems to be the version going out to mod.sources
  26.  * (if they'll take it).
  27.  * 
  28.  * Revision 1.1.1.7  85/08/07  23:13:06  ron
  29.  * this is probably a usable version of the laserjet driver. it loads
  30.  * bit maps for special fonts and for sizes that are not on the cartridge,
  31.  * and has the basis for enhancement - it still needs a LOT of work:
  32.  * CLEANING UP!
  33.  * recognition of vfont/rasti10 by f_magic - add field to FINFO
  34.  *     and use to decide on height/width of character, positioning, etc.
  35.  * add code tables for rasti10 bit maps.
  36.  * etc
  37.  * 
  38.  * Revision 1.1.1.6  85/08/04  12:38:56  ron
  39.  * added font info table, changed font reads to a fseek followed
  40.  * by charater data reads. still need to add code tables for rasti10
  41.  * and distinguish between rasti10 and vfont. add field to finfo based
  42.  * on the f_magic and enforce f_magic. find out why vfont produces
  43.  * poorly placed characters.
  44.  * has not yet been tested.
  45.  * 
  46.  * Revision 1.1.1.5  85/08/02  14:08:40  ron
  47.  * adding a font info table so that we can use more than
  48.  * one bit-map at a time without constantly loading/unloading
  49.  * files. may also change the loading to an fseek followed by a read to
  50.  * minimize file access since most of the bit-map stuff are done
  51.  * for only a few characters.
  52.  * therefore keep this "pre-change" version b4 i destroy it ...
  53.  * 
  54.  * Revision 1.1.1.4  85/07/28  15:07:33  ron
  55.  * works. is confined to one size - next step is size changes. rule
  56.  * is done wrong - comes out too low - should use bit map.
  57.  * knows about differences between vfont and rasti10 - i.e. adding
  58.  * 1 bit and 1 row when needed.
  59.  * 
  60.  * Revision 1.1.1.3  85/07/21  16:28:51  ron
  61.  * first attempt at adding the special font as a raster
  62.  * map and dump'n out bit maps when appropriate.
  63.  * 
  64.  * Revision 1.1.1.2  85/07/19  12:24:15  ron
  65.  * took out the 'optimization'. it does work, i.e. cuts file size,
  66.  * imaging time etc, but the spacing of the laserjet is much larger
  67.  * than what troff thinks it is.
  68.  * 
  69.  * Revision 1.1.1.1  85/07/10  10:26:06  ron
  70.  * gave up on eliminating hpos for now. may try again
  71.  * later.
  72.  * 
  73.  * Revision 1.1.0.2  85/07/10  08:38:59  ron
  74.  * ok, put in a fudge to do hflush() only if it's not
  75.  * a sequence of characters.
  76.  * 
  77.  * Revision 1.1.0.1  85/07/10  08:30:23  ron
  78.  * the numbering in rcs is ridiculous. anyway, this is the 'starting'
  79.  * file for this 'branch'. goal is to eliminate as many horiz position
  80.  * as possible, since this takes forever on the laserjet. next try
  81.  * is to let the printer do the spacing in every case where
  82.  * we have just printed a sequence of 2hor-mot-digits+char and
  83.  * have another one immediately following.
  84.  * 
  85.  * 
  86.  */
  87.  
  88.  
  89. #include    <stdio.h>
  90. #include    <signal.h>
  91. #include    <ctype.h>
  92. #include    <strings.h>
  93.  
  94. #include "glyph.h"
  95. #include "asctab.h"
  96. #include "spectab.h"
  97.  
  98. int    output    = 0;    /* do we do output at all? */
  99. int    pgindex    = 0;    /* output page list if > 0 */
  100. int    pagelist[20];    /* pairs of page numbers */
  101.  
  102.  
  103.  
  104. #define    FATAL    1
  105. int    dbg    = 0;
  106.  
  107. #define    dprintf    if (dbg) fprintf
  108. #define    dinfoprint    if (dbg) finfoprint
  109.  
  110. int    res    = 720;
  111.     /* input assumed computed according */
  112.     /* to this resolution (actually 723) */
  113.     /* initial value to avoid 0 divide */
  114.  
  115. char    *dfltdir    = "/usr/lib/vfont";
  116.  
  117. char    *fontdir    = "/usr/lib/font";
  118. char    *vfontdir    = "/usr/lib/vfont";
  119. char    *rfontdir    = "/usr/src/cmd/text/troff.d/devi10/rasti10";
  120.  
  121. extern char devname[];
  122.  
  123. int    want_siz = 10;    /* convenient defaults */
  124. int    crnt_siz = 10;
  125.  
  126. int    c_fnt_indx = 0;
  127. int cartridge = 1;
  128.  
  129. #define    NUMFONTS    8
  130.  
  131. /*
  132.  * the purpose for this array is to have more than one size
  133.  * of a font available at a time. this is not handled properly now,
  134.  * the entry is just replaced, causing some unnecessary i/o to
  135.  * take place. when it's done correctly, the character info structures
  136.  * will only need to be read once and this thing will work faster.
  137.  * (it will never be fast - the laserjet is too slow in processing
  138.  * the positioning commands/bit maps to be REALLY useful).
  139.  * Also, presently, the c_fnt_indx always corresponds to the font
  140.  * position used. The inclusion of f_numb field is to make this 
  141.  * unnecessary, to enable switching font files without abandoning
  142.  * their entries/info.
  143.  */
  144. struct FINFO {
  145.     int f_numb;
  146.     /*
  147.      * 0 means not currently used, otherwise
  148.      * this is the position 'loaded' on
  149.      */
  150.     char f_name[30];    /* name.size */
  151.     struct c_param * f_chp;
  152.     /* really points to the first element in
  153.      * a 256 array of structs, so we can have
  154.      * the character info for all members of 
  155.      * this font without re-reading the file
  156.      */
  157.     FILE * f_ptr;
  158. }    finfo[NUMFONTS] = {
  159.     1,    "R.10",    NULL,    NULL,
  160.     2,    "B.10",    NULL,    NULL,
  161.     3,    "I.10",    NULL,    NULL,
  162.     4,        "",    NULL,    NULL,
  163.     5,        "",    NULL,    NULL,
  164.     6,        "",    NULL,    NULL,
  165.     7,        "",    NULL,    NULL,
  166.     8,        "",    NULL,    NULL
  167. };
  168.  
  169. FILE *fp = stdin;    /* input file pointer */
  170.  
  171.  
  172. main(argc, argv)
  173. char *argv[];
  174. {
  175.     char buf[BUFSIZ];
  176.     int done();
  177.  
  178.     setbuf(stdout, buf);
  179.     while (argc > 1 && argv[1][0] == '-') {
  180.         switch (argv[1][1]) {
  181.         case 'o':
  182.             outlist(&argv[1][2]);
  183.             break;
  184.         case 'd':
  185.             dbg = atoi(&argv[1][2]);
  186.             if (dbg == 0) dbg = 1;
  187.             break;
  188.         }
  189.         argc--;
  190.         argv++;
  191.     }
  192.  
  193.     if (argc <= 1)
  194.         dofile(stdin);
  195.     else
  196.         while (--argc > 0) {
  197.             if (strcmp(*++argv, "-") == 0)
  198.                 fp = stdin;
  199.             else if ((fp = fopen(*argv, "r")) == NULL)
  200.                 error(FATAL, "can't open %s", *argv);
  201.             dofile(fp);
  202.             fclose(fp);
  203.         }
  204.     done();
  205. }
  206.  
  207. outlist(s)    /* process list of page numbers to be printed */
  208. char *s;
  209. {
  210.     int start, finish, i;
  211.  
  212.     pgindex = 0;
  213.     while (*s) {
  214.         for (start = 0; isdigit(*s); start = start * 10 +*s++ - '0');
  215.         finish = start;
  216.         if (*s == '-'){
  217.         s++;
  218.         for (finish = 0; isdigit(*s); finish = finish * 10 +*s++ - '0');
  219.         }
  220.         if (finish==0)    finish = 9999;
  221.  
  222.         pagelist[pgindex++] = start;
  223.         pagelist[pgindex++] = finish;
  224.         if (*s != '\0')
  225.             s++;
  226.     }
  227.     pagelist[pgindex] = 0;
  228.     if (dbg)
  229.         for (i=0; i<pgindex; i += 2)
  230.             printf("%3d %3d\n", pagelist[i], pagelist[i+1]);
  231. }
  232.  
  233. in_olist(n)    /* is page n in pagelist? */
  234. int n;
  235. {
  236.     int i;
  237.  
  238.     if (pgindex == 0)
  239.         return(1);    /* everything is included */
  240.     for (i = 0; i < pgindex; i += 2)
  241.         if (n >= pagelist[i] && n <= pagelist[i+1])
  242.             return(1);
  243.     return(0);
  244. }
  245.  
  246.  
  247. dofile(fp)
  248. register FILE *fp;
  249. {
  250.     register int c, k;
  251.     int m, n, n1, m1;
  252.     char str[100], buf[300];
  253.  
  254.     while ((c = getc(fp)) != EOF) {
  255.         switch (c) {
  256.         case '\n':    /* when input is text */
  257.         case ' ':
  258.         case 0:        /* occasional noise creeps in */
  259.             break;
  260.         case '0': case '1': case '2': case '3': case '4':
  261.         case '5': case '6': case '7': case '8': case '9':
  262.             /* two motion digits plus a character */
  263.             hmot((c-'0')*10 + getc(fp)-'0');
  264.             put1(getc(fp));
  265.             break;
  266.         case 'c':    /* single ascii character */
  267.             put1(getc(fp));
  268.             break;
  269.         case 'C':    /* 'funny' character */
  270.             fscanf(fp, "%s", str);
  271. #ifdef DEBUG
  272.             dprintf(stderr, "%s", str);
  273. #endif
  274.             put1s(str);
  275.             break;
  276.         case 't':    /* straight text */
  277.             fgets(buf, sizeof(buf), fp);
  278.             t_text(buf);
  279.             break;
  280.         case 'D':    /* draw function - not done yet */
  281.             fgets(buf, sizeof(buf), fp);
  282.             switch (buf[0]) {
  283.             case 'l':    /* draw a line */
  284.                 sscanf(buf+1, "%d %d", &n, &m);
  285.                 drawline(n, m, ".");
  286.                 break;
  287.             case 'c':    /* circle */
  288.                 sscanf(buf+1, "%d", &n);
  289.                 drawcirc(n);
  290.                 break;
  291.             case 'e':    /* ellipse */
  292.                 sscanf(buf+1, "%d %d", &m, &n);
  293.                 drawellip(m, n);
  294.                 break;
  295.             case 'a':    /* arc */
  296.                 sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
  297.                 drawarc(n, m, n1, m1);
  298.                 break;
  299.             case '~':    /* wiggly line */
  300.                 drawwig(buf+1);
  301.                 break;
  302.             default:
  303.                 error(FATAL, "unknown drawing function %s", buf);
  304.                 break;
  305.             }
  306.             break;
  307.         case 's':
  308.             fscanf(fp, "%d", &n);    /* ignore fractional sizes */
  309. #ifdef DEBUG
  310.             dprintf(stderr, "%d", n);
  311. #endif
  312.             setsize(t_size(n));
  313.             break;
  314.         case 'f':
  315.             fscanf(fp, "%s", str);
  316. #ifdef DEBUG
  317.             dprintf(stderr, "%s", str);
  318. #endif
  319.             setfont(t_font(str));
  320.             break;
  321.         case 'H':    /* absolute horizontal motion */
  322.             while ((c = getc(fp)) == ' ')
  323.                 ;
  324.             for (k = c-'0'; isdigit(c = getc(fp)); k = 10*k+c-'0');
  325.             ungetc(c, fp);
  326.             hgoto(k);
  327.             break;
  328.         case 'h':    /* relative horizontal motion */
  329.             while ((c = getc(fp)) == ' ')
  330.                 ;
  331.             for (k = c-'0'; isdigit(c = getc(fp)); k = 10*k+c-'0');
  332.             ungetc(c, fp);
  333.             hmot(k);
  334.             break;
  335.         case 'w':    /* word space */
  336.             /* should either ignore this or space over
  337.             the right character width, not just space */
  338.             putc(' ', stdout);
  339.             break;
  340.         case 'V':
  341.             while ((c = getc(fp)) == ' ')
  342.                 ;
  343.             for (n = c-'0'; isdigit(c = getc(fp)); n = 10*n+c-'0');
  344.             ungetc(c, fp);
  345. #ifdef DEBUG
  346.             dprintf(stderr, "%d", n);
  347. #endif
  348.             vgoto(n);
  349.             break;
  350.         case 'v':
  351.             while ((c = getc(fp)) == ' ')
  352.                 ;
  353.             for (n = c-'0'; isdigit(c = getc(fp)); n = 10*n+c-'0');
  354.             ungetc(c, fp);
  355. #ifdef DEBUG
  356.             dprintf(stderr, "%d", n);
  357. #endif
  358.             vmot(n);
  359.             break;
  360.         case 'p':    /* new page */
  361.             fscanf(fp, "%d", &n);
  362. #ifdef DEBUG
  363.             dprintf(stderr, "%d", n);
  364. #endif
  365.             t_page(n);
  366.             break;
  367.         case 'n':    /* end of line */
  368.             while (getc(fp) != '\n')
  369.                 ;
  370.             t_newline();
  371.             break;
  372.         case '#':    /* comment */
  373.             while (getc(fp) != '\n')
  374.                 ;
  375.             break;
  376.         case 'x':    /* device control */
  377.             device(fp);
  378.             break;
  379.         default:
  380.             error(!FATAL, "unknown input character %o %c", c, c);
  381.             done();
  382.         }
  383.     }
  384. }
  385.  
  386. device(fp)    /* interpret device control functions */
  387. FILE *fp;
  388. {
  389.     char str[20];
  390.     int n;
  391.  
  392.     fscanf(fp, "%s", str);
  393. #ifdef DEBUG
  394.     dprintf(stderr, "%s", str);
  395. #endif
  396.     switch (str[0]) {
  397.     case 'i':    /* initialize */
  398.         fileinit();
  399.         t_init(0);
  400.         break;
  401.     case 'T':    /* device name */
  402.         fscanf(fp, "%s", devname);
  403. #ifdef DEBUG
  404.         dprintf(stderr, "%s", devname);
  405. #endif
  406.         /* gets ignored anyway */
  407.         break;
  408.     case 't':    /* trailer */
  409.         t_trailer();
  410.         break;
  411.     case 'p':    /* pause -- can restart */
  412.         t_reset('p');
  413.         break;
  414.     case 's':    /* stop */
  415.         t_reset('s');
  416.         break;
  417.     case 'r':    /* resolution assumed when prepared */
  418.         fscanf(fp, "%d", &res);
  419. #ifdef DEBUG
  420.         dprintf(stderr, "%d", res);
  421. #endif
  422.         break;
  423.     case 'f':    /* font used */
  424.         fscanf(fp, "%d %s", &n, str);
  425. #ifdef DEBUG
  426.         dprintf(stderr, "%d %s", n, str);
  427. #endif
  428.         loadfont(n, str);
  429.         break;
  430.     }
  431.     while (getc(fp) != '\n')    /* skip rest of input line */
  432.         ;
  433. }
  434.  
  435.  
  436. fileinit()    /* read in font and code files, etc. */
  437. {
  438.     /*
  439.      * don't do anything here since the first commands
  440.      * in any output from troff are font load commands and
  441.      * we'll do them there anyway
  442.      */
  443. }
  444.  
  445. fontprint(i)    /* debugging print of font i (1,...NUMFONTS) */
  446. {
  447.     /*
  448.      * I'm too lazy - add this if you want - it's just
  449.      * a simple loop, e.g for (i=0; i<256; call raster)
  450.      */
  451. }
  452.  
  453. loadcode(n, nw)
  454. /* load codetab on position n (0...NUMFONTS); #chars is nw */
  455. /* someday will get added when i discover where the tables */
  456. /* are, or if i create them from my font dumps.            */
  457. int n, nw;
  458. {
  459. /*
  460.  * do we know how the code tables are organized?
  461.  * the code positions are different (of course ...) for vfont
  462.  * and for the AT&T DWB fonts (the imagen rasters).
  463.  * we need a way to distinguish between the raster files
  464.  * not based on their names, and f_magic, as far as i remember,
  465.  * is not consistent. either find a 'smart' way to do this, or
  466.  * go over ALL the font files and force f_magic to 0436 for vfont
  467.  * and to something else for rasti10. then we can have independent
  468.  * code tables and add them to the FINFO structures, so that we
  469.  * can find find a character FAST.
  470.  * P.S. - i think the maxx, maxy, and xtend fields are ALWAYS 0 on
  471.  * the rasti10 stuff, and ALWAYS initialized to something normal in
  472.  * vfont, so that may be a solution.
  473.  */
  474. }
  475.  
  476. cheat_size(n)
  477. int n;
  478. {
  479.     register int * siz;
  480.     static int av_siz [] = {
  481.         6, 7, 8, 9, 10, 11, 12,
  482.         14, 16, 18, 20, 22, 24,
  483.         28, 36, 0
  484.     };
  485.  
  486.     n = (int)(n*1.33);
  487.         /*
  488.          * is vfont for 200 dpi?
  489.          * this seems to give a good size ratio
  490.          * but can change to fit your mood ...
  491.          * it's not exact anyway cause of cheatsize().
  492.          */
  493.  
  494.     for (siz=av_siz; (*siz != 0) && (n > *siz); siz++)
  495.         ;
  496.     return ((*siz == 0) ? *--siz : *siz);
  497. }
  498.  
  499. loadfont(pos, s)
  500.     /* load font info for font s on position n (1...NUMFONTS) */
  501. int pos;
  502. char *s;
  503. {
  504.     /*
  505.      * read in a font here from the library - just the header
  506.      * and the c_param structures. we'll do an fseek and read
  507.      * for the characters separately.
  508.      * call t_fp to update the table of fonts and see if we
  509.      * already have the info we need, and check if not on cartridge.
  510.      *
  511.      * there should be
  512.      * space for more than one font since troff seems to enjoy
  513.      * changing point sizes on the fly ..
  514.      */
  515.  
  516.     char    filename[100];
  517.     struct f_header   fh;
  518.     register int     i;
  519.     char tmpname[30];
  520.     struct c_param * chpalloc();
  521.  
  522. #ifdef DEBUG
  523.     dinfoprint("loadfont entered");
  524. #endif
  525.     sprintf(tmpname, "%s.%d", s, want_siz);
  526.     i = t_fp(pos, tmpname);
  527.     if       ((strcmp(tmpname,"R.10")==0)
  528.         || (strcmp(tmpname,"I.10")==0)
  529.         || (strcmp(tmpname,"B.10")==0)) {
  530.                 cartridge  = 1;
  531.                 c_fnt_indx = i;
  532.                 crnt_siz = want_siz;
  533. #ifdef DEBUG
  534.                 dinfoprint("loadfont");
  535. #endif
  536.                 return;
  537.     }
  538.     sprintf(tmpname, "%s.%d", s, cheat_size(want_siz));
  539.     /* 
  540.      * cheat with the size here. maybe should use
  541.      * (int)(want_siz/0.8) or (int)(want_siz/0.67)
  542.      * to compensate - check
  543.      * availability of these sizes b4 u try it
  544.      */
  545.         /* this is the font we want */
  546.     if (finfo[i].f_ptr != NULL){
  547.         /* found it, and the file has already been read */
  548.         cartridge  = 0;
  549.         c_fnt_indx = i;
  550.         crnt_siz = want_siz;
  551. #ifdef DEBUG
  552.         dinfoprint("loadfont");
  553. #endif
  554.         return;
  555.     }
  556.     /*
  557.      * found an entry, but it hasn't been read yet - alloc
  558.      * mem if needed, file gets read at end of else clause.
  559.      */
  560.     cartridge  = 0;
  561.     c_fnt_indx = i;
  562.     crnt_siz = want_siz;
  563.     if (finfo[c_fnt_indx].f_chp == NULL)
  564.         if ((finfo[c_fnt_indx].f_chp = chpalloc()) == NULL)
  565.             error(FATAL,"couldn't allocate memory");
  566.             /* does not return */
  567.     /*
  568.      * we now have a spot in finfo[c_fnt_indx]
  569.      * either because we found an entry that hasn't 
  570.      * been read in,
  571.      * or because we replaced an old entry. so now
  572.      * we read in the information from the font file.
  573.      */
  574.         
  575.  
  576.     sprintf(filename, "%s/%s", dfltdir, tmpname);
  577.     finfo[c_fnt_indx].f_ptr = fopen (filename, "r");
  578.     if (finfo[c_fnt_indx].f_ptr == NULL) {
  579.         error (!FATAL, "font file - can't open %s", filename);
  580.         finfo[c_fnt_indx].f_name[0] = '\0';
  581.         c_fnt_indx = 0;
  582. #ifdef DEBUG
  583.         dinfoprint("loadfont");
  584. #endif
  585.         return;
  586.     }
  587. #ifdef DEBUG
  588.     dprintf (stderr, "font file %s\n", filename);
  589. #endif
  590.  
  591.     fread (&fh, sizeof (struct f_header), 1, finfo[c_fnt_indx].f_ptr);
  592.     /*
  593.      * not used at the time. may need it later on since we have
  594.      * to distinguish between berkeley vfont and dwb rasti10
  595.      * files, so might stuff a different magic number and stick
  596.      * an indicator into the finfo structure.
  597.      */
  598.     fread (finfo[c_fnt_indx].f_chp,
  599.             sizeof (struct c_param), 256, finfo[c_fnt_indx].f_ptr);
  600.     crnt_siz = want_siz;
  601. #ifdef DEBUG
  602.     dinfoprint("loadfont");
  603. #endif
  604. }
  605.  
  606.  
  607.  
  608.  
  609. char    devname[20]    = "hp2686A";
  610.     /* (Laserjet) - not used anywhere */
  611. int hpos, vpos;
  612.  
  613. t_init(reinit)    /* initialize device */
  614. int reinit;
  615. {
  616.  
  617.     fflush(stdout);
  618.     hpos = vpos = 0;
  619. }
  620.  
  621. t_page(n)    /* do whatever new page functions */
  622. {
  623.     hpos = vpos = 0;
  624.     if (output == 0) {
  625.         output = in_olist(n);
  626.         t_init(1);
  627.         return;
  628.     }
  629.     putpage();
  630.     fflush(stdout);
  631. }
  632.  
  633. putpage()
  634. {
  635.     putchar('\f');
  636. }
  637.  
  638. t_newline()    /* do whatever for the end of a line */
  639. {
  640.     putchar('\n');
  641.     /*
  642.      * not really needed, but good for breaking up
  643.      * output file (debugging, modifying).
  644.      */
  645.     hpos = 0;
  646. }
  647.  
  648. t_size(n)
  649. int n;
  650. {
  651.     return(n);
  652. }
  653.  
  654. t_font(s)    /* convert string to internal font number */
  655. char *s;
  656. {
  657.     /* will have to choose which font to read
  658.     into the tables so be careful here */
  659.     return(atoi(s));
  660. }
  661.  
  662. t_text(s)    /* print string s as text */
  663. char *s;
  664. {
  665.     int c, wspc;
  666.     char str[100];
  667.  
  668.     if (!output)
  669.         return;
  670.     while ((c = *s++) != '\n') {
  671.         if (c == '\\') {
  672.             switch (c = *s++) {
  673.             case '\\':
  674.             case 'e':
  675.                 put1('\\');
  676.                 break;
  677.             case '(':
  678.                 str[0] = *s++;
  679.                 str[1] = *s++;
  680.                 str[2] = '\0';
  681.                 put1s(str);
  682.                 break;
  683.             }
  684.         } else {
  685.             put1(c);
  686.         }
  687.         wspc = crnt_siz*300./72.; /* an 'em's worth? */
  688.         hmot(wspc);
  689.     }
  690. }
  691.  
  692. t_reset(c)
  693. {
  694.  
  695.     output = 1;
  696.     if (c == 's'){
  697.         printf("\033E");
  698.         t_page(9999);
  699.         }
  700.     fflush(stdout);
  701. }
  702.  
  703. t_trailer()
  704. {
  705. }
  706.  
  707. hgoto(n)
  708. {
  709.     hpos = n;    /* this is where we want to be */
  710.             /* before printing a character, */
  711.             /* have to make sure it's true */
  712. }
  713.  
  714. hmot(n)    /* generate n units of horizontal motion */
  715. int n;
  716. {
  717.     hpos += n;
  718. }
  719.  
  720. hflush()    /* actual horizontal output occurs here */
  721. {
  722.     printf("\033&a%dH",hpos);
  723. }
  724.  
  725. vgoto(n)
  726. {
  727.     static int oldvpos = 0;
  728.  
  729.     vpos = n;
  730.     if (vpos != oldvpos){
  731.         printf("\033&a%dV",vpos);
  732.         oldvpos = vpos;
  733.         }
  734. }
  735.  
  736. vmot(n)    /* generate n units of vertical motion */
  737. int n;
  738. {
  739.     vgoto(vpos + n);    /* ignores rounding */
  740. }
  741.  
  742. put1s(s)    /* s is a funny char name */
  743. char *s;
  744. {
  745.     register int i, j;
  746.     register char *p;
  747.     extern char *asctab[];
  748.         /* is only good for the fonts on the cartridge
  749.          * need a codetable for the raster dumps.
  750.          */
  751.     extern char *spectab[];
  752.         /* names of chars on S font- index of name = index of
  753.          * c_param so easy to find raster map
  754.          */
  755.     static char prev[10] = "";
  756.     static int previ;
  757.     static char prevs[10] = "";
  758.     static int prevsi;
  759.     char tmpname[30];
  760.     int o_fnt_indx;
  761.     int o_cartridge;
  762.  
  763.     if (!output)
  764.         return;
  765.  
  766. #ifdef DEBUG
  767.     dinfoprint("put1s entered");
  768. #endif
  769.     if (strcmp(s, prev) != 0) {
  770.         previ = -1;
  771.         for (i = 0; asctab[i] != 0; i += 2)
  772.             if (strcmp(asctab[i], s) == 0) {
  773.                 strcpy(prev, s);
  774.                 previ = i;
  775.                 break;
  776.             }
  777.     }
  778.     if (previ >= 0) {
  779.         hflush(); vgoto(vpos);
  780.         /*
  781.          * should only use this for the cartridge fonts, but since
  782.          * don't have a codetable yet for the rasters, use this
  783.          * anyway - it will come out in the wrong font and size
  784.          * but it's at least viewable.
  785.          */
  786.         for (p = asctab[previ+1]; *p; p++)
  787.             putc(*p, stdout);
  788.  
  789. #ifdef DEBUG
  790.         dprintf(stderr,"ascii character %s, font is %s\n",
  791.                 asctab[previ], finfo[c_fnt_indx].f_name);
  792.  
  793.         dinfoprint("put1s");
  794. #endif
  795.         return;
  796.     } else
  797.         prev[0] = 0;
  798.  
  799.  
  800.     if (strcmp(s, prevs) != 0) {
  801.         prevsi = -1;
  802.         for (i = 0; i<128; i++)
  803.             if (strcmp(spectab[i], s) == 0) {
  804.                 strcpy(prevs, s);
  805.                 prevsi = i;
  806.                 break;
  807.             }
  808.     }
  809.     if (prevsi >= 0) {
  810.         for (i=0; i<NUMFONTS; i++){
  811.             if (finfo[i].f_numb == 6) break;
  812.             }
  813.         if (i >= NUMFONTS) error(FATAL,"nothing mounted on position 6");
  814.         /* may add a s_fnt_indx to get around this */
  815.  
  816. #ifdef DEBUG
  817.     dprintf(stderr,"special character %s, font on position 6 is %s\n",
  818.                 spectab[prevsi], finfo[i].f_name);
  819. #endif
  820.  
  821.         o_fnt_indx = c_fnt_indx;
  822.         o_cartridge = cartridge;
  823.  
  824.         if ((p = index(finfo[i].f_name,'.'))==0)
  825.             error(FATAL,"finfo entry screwed up");
  826.  
  827.         /* size check - may need new file */
  828.  
  829.         if (atoi(++p)!=want_siz) {
  830.             for (j=0; (tmpname[j]=finfo[i].f_name[j])!='.' ;j++);
  831.             tmpname[j]='\0';
  832.             /* copy the font name up to the '.' into tmpname */
  833.  
  834.             loadfont(finfo[i].f_numb, tmpname);
  835.             /* do a new load on position 6 for new size */
  836.             /* this will change c_fnt_indx and */
  837.             /* cartridge indicator, so need to restore. */
  838.             i = c_fnt_indx;
  839.  
  840. #ifdef DEBUG
  841.         dprintf(stderr,
  842.             "put1s - needed size change, current font pos %d has %s\n",
  843.                 finfo[c_fnt_indx].f_numb, finfo[c_fnt_indx].f_name);
  844. #endif
  845.         }
  846.         else {
  847.             /* 
  848.              * we didn't call loadfont since size was ok,
  849.              * but raster looks at c_fnt_indx to get a file
  850.              * pointer, so change it here and reset later.
  851.              * dirty, lousy code - redo this whole section
  852.              */
  853.              c_fnt_indx = i;
  854.         }
  855.  
  856. #ifdef DEBUG
  857.         dinfoprint("put1s");
  858. #endif
  859.         raster(finfo[i].f_chp+prevsi);
  860.  
  861.         cartridge = o_cartridge;
  862.         c_fnt_indx = o_fnt_indx;
  863.  
  864. #ifdef DEBUG
  865.         dprintf(stderr,
  866.             "put1s - restored old font, position %d has %s\n",
  867.                 finfo[c_fnt_indx].f_numb, finfo[c_fnt_indx].f_name);
  868.  
  869.         dinfoprint("put1s");
  870. #endif
  871.         return;
  872.     } else
  873.         prevs[0] = 0;
  874. #ifdef DEBUG
  875.         dinfoprint("put1s");
  876. #endif
  877. }
  878.  
  879.  
  880. put1(c)    /* output char c */
  881. int c;
  882. {
  883.     register char * pt;    /* finds the size of the current font */
  884.  
  885.     if (!output)
  886.         return;
  887.     vgoto(vpos);
  888.     /*
  889.     horiz position gets flushed if it's not a 
  890.     'nnc' sequence, in which case we try to let 
  891.     the laserjet handle the spacing
  892.     */
  893.     /*
  894.     Cancel the above - the laserjet's spacing is too
  895.     wide for troff. it doesn't look as nice either. while
  896.     this cuts file size & xmission time, we need a better
  897.     solution, i.e. width tables, etc.
  898.     */
  899.         hflush();
  900.  
  901.     /*
  902.      * the following is SLOW and messy. find a better
  903.      * way of knowing what the size is. yuck.
  904.      */
  905.  
  906. #ifdef DEBUG
  907.     dinfoprint("put1 entered");
  908. #endif
  909.  
  910.     if ((pt = index(finfo[c_fnt_indx].f_name,'.'))==0)
  911.         error(FATAL,"finfo entry screwed up");
  912.  
  913.     if (atoi(++pt)!=want_siz) {
  914.         /* copy the font name up to the '.' into tmpname */
  915.         setfont(finfo[c_fnt_indx].f_numb);
  916.             /* do a new load since we lost our size */
  917.  
  918. #ifdef DEBUG
  919.         dprintf(stderr,
  920.             "put1 - needed size change, current font pos %d has %s\n",
  921.                 finfo[c_fnt_indx].f_numb, finfo[c_fnt_indx].f_name);
  922. #endif
  923.     }
  924.  
  925. #ifdef DEBUG
  926.     dinfoprint("put1");
  927. #endif
  928.     if (cartridge) putc(c, stdout);
  929.     else {
  930.         raster(finfo[c_fnt_indx].f_chp+c);
  931.         /* only good for vfont, dwb needs a code table */
  932.     }
  933. #ifdef DEBUG
  934.     dinfoprint("put1");
  935. #endif
  936. }
  937.  
  938. setsize(n)    /* set point size to n (internal) */
  939. int n;
  940. {
  941. #ifdef DEBUG
  942.     dprintf(stderr,"going to point size %d\n",n);
  943. #endif
  944.     want_siz = n;
  945. }
  946.  
  947. t_fp(n, s)    /* font position n now contains font s */
  948. int n;
  949. char *s;    /* s is a name.size combination */
  950. {
  951.     register int ind;
  952.  
  953. #ifdef DEBUG
  954.     dinfoprint("t_fp entered");
  955. #endif
  956.     for (ind = 0; ind < NUMFONTS; ind++){
  957.         if (finfo[ind].f_numb == n){
  958.             if (strcmp(finfo[ind].f_name, s)==0){
  959. #ifdef DEBUG
  960.                 dinfoprint("t_fp");
  961. #endif
  962.                 return(ind);    /* already there */
  963.                 }
  964.             else {
  965.                 strcpy(finfo[ind].f_name, s);
  966.                 if (finfo[ind].f_ptr != NULL)
  967.                     fclose(finfo[ind].f_ptr);
  968.                 finfo[ind].f_ptr = NULL;
  969. #ifdef DEBUG
  970.                 dinfoprint("t_fp");
  971. #endif
  972.                 return(ind);
  973.             }
  974.         }
  975.     }
  976. #ifdef DEBUG
  977.     dinfoprint("t_fp");
  978. #endif
  979.     error(FATAL, "can't mount %s, pos %d doesn't exist", s, n);
  980.     /* NOTREACHED */
  981. }
  982.  
  983. setfont(n)    /* set font to n */
  984. int n;
  985. {
  986.     register int ind;
  987.     register char * pt;
  988.     char tmpname[30];    /* just a convenience */
  989.  
  990. #ifdef DEBUG
  991.     dinfoprint("setfont entered");
  992.     dprintf(stderr,"request for font on position %d\n",n);
  993. #endif
  994.  
  995.     for (ind = 0; ind < NUMFONTS; ind++){
  996.             if (finfo[ind].f_numb == n) break;
  997.             }
  998.     if (ind >= NUMFONTS)
  999.         error(FATAL, "nothing mounted on position %d", n);
  1000.  
  1001.     c_fnt_indx = ind;
  1002.     crnt_siz = want_siz;
  1003.  
  1004.     cartridge = 0;
  1005.  
  1006.     /*
  1007.      * check the size of the mounted font and make
  1008.      * sure its what we want, otherwise call loadfont
  1009.      */
  1010.     if ((pt = index(finfo[c_fnt_indx].f_name,'.'))==0)
  1011.         error(FATAL,"finfo entry screwed up");
  1012.  
  1013.     if (atoi(++pt)!=want_siz) {
  1014.         for (ind=0;
  1015.             (tmpname[ind]=finfo[c_fnt_indx].f_name[ind])!='.' ;ind++);
  1016.         tmpname[ind]='\0';
  1017.         /* copy the font name up to the '.' into tmpname */
  1018.         loadfont(finfo[c_fnt_indx].f_numb, tmpname);
  1019.             /* do a new load since we lost our size */
  1020.  
  1021. #ifdef DEBUG
  1022.         dprintf(stderr,
  1023.         "setfont - needed size change, current font pos %d has %s\n",
  1024.                 finfo[c_fnt_indx].f_numb, finfo[c_fnt_indx].f_name);
  1025. #endif
  1026.     }
  1027.  
  1028.     strcpy(tmpname, finfo[c_fnt_indx].f_name);
  1029.     if (strcmp(tmpname,"R.10")==0){
  1030.         printf("\033&l0O\033(0U\033(s1p10v0s0b5T");
  1031.         /* Times Roman medium upright (portrait) */
  1032.         cartridge  = 1;
  1033. #ifdef DEBUG
  1034.     dprintf(stderr,"set font to %s\n", finfo[c_fnt_indx].f_name);
  1035.     dinfoprint("setfont");
  1036. #endif
  1037.         return;
  1038.     }
  1039.     if (strcmp(tmpname,"I.10")==0){
  1040.         printf("\033&l0O\033(0U\033(s1p10v1s0b5T");
  1041.         /* Times Roman medium italic (portrait) */
  1042.         cartridge  = 1;
  1043. #ifdef DEBUG
  1044.     dprintf(stderr,"set font to %s\n", finfo[c_fnt_indx].f_name);
  1045.     dinfoprint("setfont");
  1046. #endif
  1047.         return;
  1048.     }
  1049.     if (strcmp(tmpname,"B.10")==0) {
  1050.         printf("\033&l0O\033(0U\033(s1p10v0s1b5T");
  1051.         /* Times Roman bold upright (portrait) */
  1052.         cartridge  = 1;
  1053. #ifdef DEBUG
  1054.     dprintf(stderr,"set font to %s\n", finfo[c_fnt_indx].f_name);
  1055.     dinfoprint("setfont");
  1056. #endif
  1057.         return;
  1058.     }
  1059.  
  1060.     if (finfo[c_fnt_indx].f_ptr==NULL) {
  1061.         for (ind=0;
  1062.             (tmpname[ind]=finfo[c_fnt_indx].f_name[ind])!='.' ;ind++);
  1063.         tmpname[ind]='\0';
  1064.         /* copy the font name up to the '.' into tmpname */
  1065.         loadfont(finfo[c_fnt_indx].f_numb, tmpname);
  1066.             /* do a new load since we lost our size */
  1067.  
  1068. #ifdef DEBUG
  1069.         dprintf(stderr,
  1070.         "setfont - got a NULL fptr, current font pos %d has %s\n",
  1071.                 finfo[c_fnt_indx].f_numb, finfo[c_fnt_indx].f_name);
  1072. #endif
  1073.     }
  1074.  
  1075. #ifdef DEBUG
  1076.     dprintf(stderr,"set font to %s\n", finfo[c_fnt_indx].f_name);
  1077.     dinfoprint("setfont");
  1078. #endif
  1079. }
  1080.  
  1081. done()
  1082. {
  1083.     output = 1;
  1084.     putpage();
  1085.     fflush(stdout);
  1086.     exit(0);
  1087. }
  1088.  
  1089. raster (chp)
  1090. struct c_param    * chp;
  1091. {
  1092.     int    height, width, bytewidth;
  1093.     int lsrres = 300;
  1094.     int    i, j;
  1095.     long    p;
  1096.     FILE * fp;    /* just a convenience */
  1097.  
  1098.     if ((fp = finfo[c_fnt_indx].f_ptr)==NULL){
  1099.         /* fseek dumps core on a NULL file pointer */
  1100.         error(!FATAL,"raster: called with a NULL file pointer, %s",
  1101.                     "ignoring request");
  1102.         return;
  1103.     }
  1104.  
  1105.     height = (int) ckint (chp->c_up) + (int) ckint (chp->c_down);
  1106.     width = (int) ckint (chp->c_left) + (int) ckint (chp->c_right);
  1107.     bytewidth = (width+7)/8;
  1108.  
  1109.     if ((height*bytewidth)!=chp->c_size){
  1110.         /*
  1111.          * brain damage - system V and /usr/lib/vfont don't
  1112.          * agree on whether size is left+right or 1 bit bigger.
  1113.          * same for height (# of rows in bit map).
  1114.          *
  1115.          * change this thing to use f_magic somehow. (or the
  1116.          * presence/absence of normal numbers in maxx, maxy, etc
  1117.          */
  1118.         fprintf(stderr,
  1119.             "width & height don't match, trying rasti10 format ... ");
  1120.         width += 1;
  1121.         height += 1;
  1122.         bytewidth = (width+7)/8;
  1123.             if ((height*bytewidth)!=chp->c_size)
  1124.                 fprintf(stderr, "FAILED - BAD FONT FILE\n");
  1125.             else
  1126.                 fprintf(stderr, "ok\n");
  1127.     }
  1128. #ifdef DEBUG
  1129.     else dprintf(stderr, "width & height match\n");
  1130. #endif
  1131.  
  1132.     p = F_OFFSET + chp->c_addr;
  1133.     if (fseek(fp, p, 0) == -1)
  1134.         error(FATAL, "seek failed on file %s offset %d",
  1135.                 finfo[c_fnt_indx].f_name, p);
  1136.                 /* does not return */
  1137.  
  1138. #define    CNV(x)    ((int)((723./lsrres)*(x)))
  1139.  
  1140.     vgoto (vpos - CNV(chp->c_up));
  1141.     hgoto (hpos + 24 - CNV(chp->c_left)); hflush();
  1142.     /*
  1143.      * the 24 is because the laserjet's letters are not
  1144.      * placed where troff thinks they are. they seem to be
  1145.      * in the lower left corner of the character cell instead of
  1146.      * at the baseline - probably need to adjust
  1147.      * the height too, but do that later.
  1148.      * Why 24? why not? got a better number?
  1149.      */
  1150.     printf ("\033*t%dR",lsrres);
  1151.     printf ("\033*r1A");
  1152.  
  1153.     for (i = 0; i < height; i++) {
  1154.         if (p >= F_OFFSET + chp->c_addr + chp->c_size){
  1155.             error(!FATAL, "ran out of bit map data");
  1156.             /* does return, but don't fail in the middle
  1157.              * of an esc seqence - spit it out first, then
  1158.              * complain.
  1159.              */
  1160.             break;
  1161.         }
  1162.         printf ("\033*b%dW", (int) ((width + 7) / 8));
  1163.         for (j = 0; j < width; j += 8) {
  1164.             putchar (getc(fp));
  1165.             ++p;
  1166.         }
  1167.     }
  1168.     printf ("\033*rB");
  1169.     vgoto (vpos + CNV(chp->c_up));
  1170.     hgoto (hpos -24 + CNV(chp->c_left)); hflush();
  1171. }
  1172. int     ckint (n)
  1173. char    n;
  1174. {
  1175. #ifdef u3b
  1176.     int     i;
  1177.     if ((int) n > 0177) {
  1178.         i = (int) n;
  1179.         i = (256 - i) * -1;
  1180.     }
  1181.     else {
  1182.         i = (int) n;
  1183.     }
  1184.     return (i);
  1185. #else
  1186.     return ((int) n);
  1187. #endif
  1188. }
  1189.  
  1190. drawline(n, m, s) int n,m; char * s; {}
  1191. drawcirc(n) int n; {}
  1192. drawellip(m, n) int n,m; {}
  1193. drawarc(n, m, n1, m1) int n,m,n1,m1; {}
  1194. drawwig(buf) char * buf; {}
  1195.  
  1196. get1c(fp)
  1197. FILE * fp;
  1198. {
  1199.     register int c;
  1200.     c = getc(fp);
  1201.     fputc(c, stderr);
  1202.     return(c);
  1203. }
  1204. struct c_param *
  1205. chpalloc()
  1206. {
  1207.     char * calloc();
  1208.     register int i;
  1209.     register struct c_param * tmptr;
  1210.  
  1211.     /* give it 3 shots, otherwise die */
  1212.     for (i=0; i<3; i++){
  1213.         if ((tmptr=(struct c_param *)
  1214.                 calloc(256, sizeof(struct c_param)))!=NULL)
  1215.                     return(tmptr);
  1216.     }
  1217.     return (tmptr);    /* NULL cast into right pointer */
  1218. }
  1219.  
  1220. error(f, s, a1, a2, a3, a4, a5, a6, a7) {
  1221.     fprintf(stderr, "hp: ");
  1222.     fprintf(stderr, s, a1, a2, a3, a4, a5, a6, a7);
  1223.     fprintf(stderr, "\n");
  1224.     if (f)
  1225.         exit(1);
  1226. }
  1227.  
  1228. finfoprint(m)
  1229. char * m;
  1230. {
  1231.     register struct FINFO * i;
  1232.  
  1233.     fprintf(stderr, "%s: crnt_siz %d want_siz %d cartridge %d\n",
  1234.                 m, crnt_siz, want_siz, cartridge);
  1235.     for (i=finfo; i < finfo + NUMFONTS; i++)
  1236.         fprintf(stderr, "pos %d name %30s chp %s fptr %s\n",
  1237.             i->f_numb, i->f_name, (i->f_chp ? "alloc" : "null"),
  1238.             (i->f_ptr ? "open" : "null"));
  1239. }
  1240.