Annotation of researchv10no/cmd/dimpress/odimpress.c, revision 1.1.1.1

1.1       root        1: 
                      2: /*
                      3:  *
                      4:  * dimpress - cleaned up and modified code borrowed from di10.
                      5:  *
                      6:  *
                      7:  * troff post-processor for Imagen printers. Output is written in
                      8:  * version 2.0 Impress, although it does still work for earlier versions.
                      9:  * Raster files in either the old format or in Imagen's Rst format can
                     10:  * be used for character generation. Drawing functions are handled by
                     11:  * the routines in file impdraw.c. I rewrote most of those routines so they
                     12:  * use the graphics primitives avaliable in version 1.9 (and later) Impress.
                     13:  * If you're printer is still running older systems you'll probably need
                     14:  * to get the original version of draw.c and use it instead.
                     15:  *
                     16:  * All the code should work properly for any printer that accepts Impress.
                     17:  * By default I've got things set up for the 8/300, but you can use the
                     18:  * -T option to select a different printer. If you choose a new printer
                     19:  * name not supported under the -T option you'll probably want to add code
                     20:  * to do the proper initialization. There really are only six variables
                     21:  * that need to be changed for different printers. They include realdev,
                     22:  * penwidth, pres, xoff, yoff, and possibly bitdir. The printer variables
                     23:  * are defined in dimpress.h (PR_INIT) and that's what's used to initialize
                     24:  * the prdata[] array. If you make changes just be sure that the list ends
                     25:  * with an entry that has its prname field set to NULL.
                     26:  *
                     27:  *
                     28:  * output language from troff:
                     29:  * all numbers are character strings
                     30:  * 
                     31:  * sn  size in points
                     32:  * fn  font as number from 1-n
                     33:  * cx  ascii character x
                     34:  * Cxyz        funny char xyz. terminated by white space
                     35:  * Hn  go to absolute horizontal position n
                     36:  * Vn  go to absolute vertical position n (down is positive)
                     37:  * hn  go n units horizontally (relative)
                     38:  * vn  ditto vertically
                     39:  * nnc move right nn, then print c (exactly 2 digits!)
                     40:  *             (this wart is an optimization that shrinks output file size
                     41:  *              about 35% and run-time about 15% while preserving ascii-ness)
                     42:  * Dt ...\n    draw operation 't':
                     43:  *     Dl x y          line from here by x,y
                     44:  *     Dc d            circle of diameter d with left side here
                     45:  *     De x y          ellipse of axes x,y with left side here
                     46:  *     Da x y r        arc counter-clockwise by x,y of radius r
                     47:  *     D~ x y x y ...  wiggly line by x,y then x,y ...
                     48:  * nb a        end of line (information only -- no action needed)
                     49:  *     b = space before line, a = after
                     50:  * p   new page begins -- set v to 0
                     51:  * #...\n      comment
                     52:  * x ...\n     device control functions:
                     53:  *     x i     init
                     54:  *     x T s   name of device is s
                     55:  *     x r n h v       resolution is n/inch
                     56:  *             h = min horizontal motion, v = min vert
                     57:  *     x p     pause (can restart)
                     58:  *     x s     stop -- done for ever
                     59:  *     x t     generate trailer
                     60:  *     x f n s font position n contains font s
                     61:  *     x H n   set character height to n
                     62:  *     x S n   set slant to N
                     63:  * 
                     64:  *     Subcommands like "i" are often spelled out like "init".
                     65:  *
                     66:  */
                     67: 
                     68: #include       <stdio.h>
                     69: #include       <signal.h>
                     70: #include       <math.h>
                     71: #include       <ctype.h>
                     72: #include       <time.h>
                     73: 
                     74: #include       "gen.h"                 /* general purpose definitions */
                     75: #include       "ext.h"                 /* external variable definitions */
                     76: #include       "init.h"                /* just used for BITDIR definition */
                     77: #include       "rast.h"                /* raster file definitions */
                     78: #include       "dev.h"                 /* typesetter and font descriptions */
                     79: #include       "impcodes.h"            /* Impress 2.0 opcode definitions */
                     80: #include       "dimpress.h"            /* defs just used by this program */
                     81: #include       "spectab.h"
                     82: 
                     83: 
                     84: /*
                     85:  *
                     86:  * A few names we'll need when we're printing files. devname[] is what troff
                     87:  * thought was going to be the output device while realdev[] is the name
                     88:  * of the printer we're really going to be using. There may be occasions when
                     89:  * we want to send the output to a given printer (*realdev) but we want to
                     90:  * use the raster tables that were built for a different one (*rastdev). If
                     91:  * rastdev isn't NULL we'll assume that this is the name of the device's
                     92:  * raster files that we want to use. In otherwords if *rastdev hasn't been
                     93:  * set by an option *realdev will be used in combination with *bitdir to
                     94:  * define *rastdir.
                     95:  *
                     96:  */
                     97: 
                     98: 
                     99: char           devname[20] = "";       /* troff's target printer */
                    100: char           *realdev = NULL;        /* name of the printer we're really using */
                    101: char           *rastdev = NULL;        /* use raster tables made for this guy */
                    102: 
                    103: 
                    104: /*
                    105:  *
                    106:  * There's a bunch of stuff we'll want to know about the raster files we're
                    107:  * planning on using for this job. The most important, obviously is where
                    108:  * they're located. The routines that access the raster files all assume
                    109:  * they're in directory *rastdir, so it better be set up right before we
                    110:  * try to print anything. I've decided to have this program build up the
                    111:  * *rastdir string from *bitdir and either *rastdev or *realdev. All this
                    112:  * stuff will be done after the options are read. One of the reasons I'm
                    113:  * doing things this way is because we could want to do something like
                    114:  * print a troff file generated for the APS-5 on an Imprint-10 using the
                    115:  * raster files built for an 8/300. While that may sound rediculous the
                    116:  * raster tables can use up a lot of disk space and we may not want to
                    117:  * waste the space keeping complete sets of raster files for two or three
                    118:  * different devices. Anyway we should be able to do something reasonable
                    119:  * no matter what devices and raster files are requested.
                    120:  *
                    121:  * *bitdir is initialized to BITDIR (file init.h) and can be changed using
                    122:  * the -B option. The raster files for a particular device, say the 8/300
                    123:  * which is being called i300, will be found in directory *bitdir/rasti300.
                    124:  * It's defined in file glob.c because resident font routines need the
                    125:  * directory.
                    126:  *
                    127:  * We'll also need to know the format of the raster files we're using before
                    128:  * we can have any characters printed. rastformat keeps track of which
                    129:  * style is being used. It's initialized in routine rastsetup() using
                    130:  * info in file *rastdir/RASTDATA - if it exists. Right now if rastsetup()
                    131:  * can't read the RASTDATA file it assumes that the raster files are the
                    132:  * old versetec format and have a resolution of 240 dots per inch. I've
                    133:  * done things this way just to make sure we can use the post-processor
                    134:  * with the old raster files without having to add an appropriate RASTDATA
                    135:  * file to the directory. Eventually it may not be a bad idea to just
                    136:  * quit if we can't read the file.
                    137:  *
                    138:  */
                    139: 
                    140: 
                    141: int            rastformat;
                    142: 
                    143: 
                    144: /*
                    145:  *
                    146:  * Although I originally had ideas about not using a RASTERLIST file, I now
                    147:  * think it's probably a pretty good idea to use one. We could get around the
                    148:  * missing size problems by linking raster files for unavailble sizes to ones
                    149:  * we really have. That approach would cost more in downloading glyphs, but
                    150:  * more we'd probably be able to place the glyphs a little better because
                    151:  * we'd be able to set the character advance separately. Anyway it's really
                    152:  * not all that clear which approach is better. I've allowed for use of a
                    153:  * RASTERLIST file (routine rastlist()) but I've also decided that if it's
                    154:  * not there we'll continue on with the program assuming we have every size
                    155:  * that jobs ask for. If the job asks for a non-existent file it will die
                    156:  * in routine getrastdata().
                    157:  *
                    158:  * The following data structures are used to keep track of any RASTLIST
                    159:  * data we may have read. If maxrast is zero then there isn't any data
                    160:  * and we'll assume, when we do the lookups, that all fonts can be printed
                    161:  * in any size.
                    162:  *
                    163:  */
                    164: 
                    165: 
                    166: int            maxrast = 0;            /* number of RASTERLIST font entries */
                    167: Sizedata       sizedata[MAXFONTS];     /* available raster size data */
                    168: 
                    169: 
                    170: /*
                    171:  *
                    172:  * Standard things needed after we've read troff's font and device tables.
                    173:  * The binary files are all built by makedev and will be looked for in the
                    174:  * target printer's dev directory located in *fontdir. Actually that's not
                    175:  * quite right. There are mapping problems, both for fonts and characters,
                    176:  * that will exist if we try and use font files for a device that don't
                    177:  * exactly map into the raster files that are being used. For example if
                    178:  * we used the character code field in the normal APS-5 font tables when
                    179:  * we print jobs generated for the APS-5 we'd be guaranteed to get garbage.
                    180:  * To get around that problem I have the post-processor first look in
                    181:  * *rastdir for the dev directory. If it's not there then we look in *fontdir.
                    182:  *
                    183:  */
                    184: 
                    185: 
                    186: struct dev     dev;                    /* DESC.out starts this way */
                    187: struct Font    *fontbase[NFONT+1];     /* starts each FONT.out file */
                    188: short          *pstab;                 /* typesetter knows these sizes */
                    189: int            nsizes = 1;             /* sizes in *pstab list */
                    190: int            nfonts;                 /* number of font positions */
                    191: int            smnt;                   /* index of first special font */
                    192: int            nchtab;                 /* number of special character names */
                    193: char           *chname;                /* special character strings */
                    194: short          *chtab;                 /* used to locate character names */
                    195: char           *fitab[NFONT+1];        /* locates char info on each font */
                    196: char           *widthtab[NFONT+1];     /* widtab would be a better name */
                    197: char           *codetab[NFONT+1];      /* codes to get characters printed */
                    198: 
                    199: 
                    200: /*
                    201:  *
                    202:  * Variables that we use to keep track of troff's requests. All these
                    203:  * guys are set from values in the input files.
                    204:  *
                    205:  */
                    206: 
                    207: 
                    208: int            size = 1;               /* current size - internal value */
                    209: int            font = 1;               /* font position we're using now */
                    210: int            hpos = 0;               /* troff's current horizontal position */
                    211: int            vpos = 0;               /* same but vertically */
                    212: int            lastw = 0;              /* width of the last input character */
                    213: int            lastc = 0;              /* and its name (or index) */
                    214: 
                    215: 
                    216: /*
                    217:  *
                    218:  * We'll also want to keep track of some of the same things, but for the
                    219:  * target printer.
                    220:  *
                    221:  */
                    222: 
                    223: 
                    224: int            lastsize = -1;          /* last internal size we used */
                    225: int            lastfont = -1;          /* last font we told printer about */
                    226: int            lastx = -1;             /* printer's current position */
                    227: int            lasty = -1;
                    228: 
                    229: 
                    230: /*
                    231:  *
                    232:  * The following structure is used to keep track of the fonts that are
                    233:  * loaded in various positions. Both fields are filled in by routine t_fp()
                    234:  * using values in the binary font files.
                    235:  *
                    236:  */
                    237: 
                    238: 
                    239: struct  {
                    240:        char    *name;                  /* name of the font loaded here */
                    241:        int     number;                 /* its internal number */
                    242: } fontname[NFONT+1];
                    243: 
                    244: 
                    245: /*
                    246:  *
                    247:  * A few variables that are really just used for drawing things. Although
                    248:  * they're declared here most are only really used in draw.c. The pen
                    249:  * width and the step sizes can be changed by options. The step sizes DX
                    250:  * and DY control how far we move horizontally or vertically between
                    251:  * adjacent dots when drawing curves. They'll have no effect if we're
                    252:  * using Impress graphics commands for all graphics. Decreasing DX and DY
                    253:  * improves pictures but increases the size and complexity of the output
                    254:  * files. Because Impress complies and prints pages on the fly you may
                    255:  * not be able to draw fairly simple figures if the step sizes are too
                    256:  * small.
                    257:  *
                    258:  */
                    259: 
                    260: 
                    261: int            drawdot = '.';          /* draw with this character */
                    262: int            drawsize = 1;           /* shrink size by this factor */
                    263: int            penwidth = 1;           /* use this as the pen diameter */
                    264: int            DX = 6;                 /* horiz step when using drawdot */
                    265: int            DY = 6;                 /* same but for vertical step */
                    266: 
                    267: 
                    268: /*
                    269:  *
                    270:  * We may want to shift things around on the output page a little. In
                    271:  * particular moving everything right on the output pages is normal because
                    272:  * the left 3/8 inch or so of each page on an Imprint-10 isn't visible.
                    273:  * All this stuff could be done more efficiently by defining a new
                    274:  * coordinate system to match the requested offsets rather than doing
                    275:  * the calculations each time. I've left things this way for now because
                    276:  * that's the way we originally did stuff in di10.
                    277:  *
                    278:  * The xoff and yoff values are in inches while the xoffset and yoffset
                    279:  * numbers are pixels. We'll set the pixel values after we're sure about
                    280:  * the target printer's resolution. xoff and yoff can be changed by options.
                    281:  * xfac and yfac are scaling factors used to convert coordinates in the
                    282:  * input files to appropiate values in the target printers coordinate
                    283:  * system. Their values are set in t_init() because we can only do it
                    284:  * properly after we've gotten the printer's resolution (from options)
                    285:  * and read the "x res" command in each input file.
                    286:  *
                    287:  */
                    288: 
                    289: 
                    290: float          xoff;                   /* shift right by this many inches */
                    291: float          yoff;                   /* and down by this much */
                    292: 
                    293: int            xoffset;                /* pixel values = xoff * pres */
                    294: int            yoffset;                /* = yoff * pres */
                    295: float          xfac = 1.0;             /* scaling factor for x */
                    296: float          yfac = 1.0;             /* scaling factor for y */
                    297: 
                    298: 
                    299: /*
                    300:  *
                    301:  * A few miscellaneous variable declarations. I've added landscape mode
                    302:  * to the post-processor. It's requested using the -l option. Might also
                    303:  * be reasonable to add a new device control command to request landscape
                    304:  * mode, although I haven't done it yet. None of this stuff will work with
                    305:  * printer resident fonts.
                    306:  *
                    307:  */
                    308: 
                    309: 
                    310: int            mode = PORTRAIT;        /* landscape or portrait mode */
                    311: int            angle = ROT_0;          /* ROT_270 for LNADSCAPE mode */
                    312: int            output = 0;             /* do we do output at all? */
                    313: int            pageno = -1;            /* output page number */
                    314: int            copies = 1;             /* ask IPR for this many */
                    315: float          aspect  = 1;            /* default aspect ratio */
                    316: int            cancenter = TRUE;       /* try to improve char placement? */
                    317: int            center = 0;             /* for alphanumeric characters only */
                    318: 
                    319: 
                    320: /*
                    321:  *
                    322:  * We'll really need to deal with three possibly different resolutions
                    323:  * when we're printing files. The first is the resolution used by troff in
                    324:  * preparing the input file. Next is the resolution of the target printer.
                    325:  * Imprint-10s are 240 and 8/300s are 300 dots per inch. Finially we'll need
                    326:  * or at least want to know the resolution of the raster files we're using
                    327:  * to print the file. Obviously we'll get the best results when all three
                    328:  * numbers agree, but no matter what we should be able to do something
                    329:  * reasonable with any set of numbers.
                    330:  *
                    331:  */
                    332: 
                    333: 
                    334: int            res;                    /* resolution assumed in input file */
                    335: int            pres;                   /* resolution of the target printer */
                    336: int            rres;                   /* raster file resolution */
                    337: 
                    338: 
                    339: /*
                    340:  *
                    341:  * The data about the different printers supported by the program is
                    342:  * stored in prdata[]. It's initialized using PR_INIT which is defined
                    343:  * in dimpress.h. The fields in structure Prdata are used to define the
                    344:  * printer name, resolution, x and y offsets (in inches), and the string
                    345:  * that should be used for *bitdir.
                    346:  *
                    347:  */
                    348: 
                    349: 
                    350: Prdata         prdata[] = PR_INIT;     /* printer data */
                    351: 
                    352: int            pr_num = PR_NUM;        /* printer we're using - index in prdata[] */
                    353: 
                    354: 
                    355: /*
                    356:  *
                    357:  * Many of the printer dependent variables can be set by several different
                    358:  * options. Most times we'll want to use the -T option, but there may be
                    359:  * occasions when we want to override one or more of the default values.
                    360:  * These variables keep track of whether we've tried to set values by other
                    361:  * options.
                    362:  *
                    363:  */
                    364: 
                    365: 
                    366: int            setpenwidth = FALSE;    /* changed by the -P option */
                    367: int            setxoff = FALSE;        /* -x option */
                    368: int            setyoff = FALSE;        /* -y option */
                    369: int            setpres = FALSE;        /* -r option */
                    370: 
                    371: 
                    372: /*
                    373:  *
                    374:  * A few variables that are really only used if we're doing accounting.
                    375:  * Much of the accounting stuff has been designed for our own use at
                    376:  * MHCC and may not suit your needs.
                    377:  *
                    378:  */
                    379: 
                    380: 
                    381: char           *acctfile = NULL;       /* append accounting record to this file */
                    382: char           *jacctfile = NULL;      /* just a page count for this job */
                    383: int            acctpages = 0;          /* charge for this many pages */
                    384: char           *username = NULL;       /* guy whose running this program */
                    385: 
                    386: 
                    387: /*
                    388:  *
                    389:  * If we're emulating another device we'll want to use the following array to
                    390:  * help map font names available on that device into PostScript fonts. It's
                    391:  * initialized using FONTMAP (file dpost.h) and may be changed in routine
                    392:  * getfontmap(). In particular if there's a file that matches the device name
                    393:  * in directory *fontdir/devpost/fontmaps, getfontmap() will use it instead of
                    394:  * the default - haven't implemented it and probably never will.
                    395:  *
                    396:  */
                    397: 
                    398: 
                    399: Fontmap        fontmap[100] = FONTMAP;         /* just for device emulation */
                    400: 
                    401: 
                    402: /*
                    403:  *
                    404:  * Output and accounting FILE definitions. If you invoke this program with
                    405:  * the -t option everything goes to stdout, otherwise it will be written
                    406:  * to *tempfile and then passed along to Imagen's spooler using IPR.
                    407:  *
                    408:  */
                    409: 
                    410: char           *tempfile = NULL;       /* output file name if no -t option used */
                    411: 
                    412: FILE           *tf = NULL;             /* and Impress output goes here */
                    413: FILE           *fp_acct = stderr;      /* accounting stuff  written here */
                    414: 
                    415: 
                    416: extern int     maxdots;                /* defined and used in draw.c */
                    417: 
                    418: 
                    419: /*****************************************************************************/
                    420: 
                    421: 
                    422: main(agc, agv)
                    423: 
                    424: 
                    425:        int     agc;
                    426:        char    *agv[];
                    427: 
                    428: 
                    429: {
                    430: 
                    431: 
                    432: /*
                    433:  *
                    434:  * Post-processor that's used to translate troff's device independent
                    435:  * output language into Impress (version 2.0 right now). A call to Imagen's
                    436:  * spooling package, through IPR, is made in print_file() provided
                    437:  * the output hasn't gone to stdout. Using the -t option or initializing
                    438:  * tf to be stdout forces output to stdout. If there are any processing
                    439:  * errors x_stat will be non-zero and done() will remove *tempfile before
                    440:  * quitting.
                    441:  *
                    442:  */
                    443: 
                    444: 
                    445:        argc = agc;                     /* global so everyone can use them */
                    446:        argv = agv;
                    447: 
                    448:        prog_name = argv[0];            /* just used for error messages */
                    449: 
                    450:        init_signals();                 /* sets up interrupt handling */
                    451:        options();                      /* command line options */
                    452:        initialize();                   /* must be done after options */
                    453:        rastsetup();                    /* set all the raster file stuff up */
                    454:        rastlist();                     /* get availble font and size list */
                    455:        resfonts(tf);                   /* setup for any resident fonts */
                    456:        acct_file();                    /* open accounting file - maybe */
                    457: 
                    458:        arguments();                    /* translate all the input files */
                    459:        t_wrapup();                     /* mark the end of job for Impress */
                    460:        print_file();                   /* print the file we just built */
                    461: 
                    462:        done();                         /* everything probably went OK */
                    463: 
                    464: }   /* End of main */
                    465: 
                    466: 
                    467: /*****************************************************************************/
                    468: 
                    469: 
                    470: init_signals()
                    471: 
                    472: 
                    473: {
                    474: 
                    475: 
                    476:        int     done();                 /* handles them if we're catching sigs */
                    477: 
                    478: 
                    479: /*
                    480:  *
                    481:  * Makes sure we handle any interrupts properly. It wasn't done right
                    482:  * in di10.
                    483:  *
                    484:  */
                    485: 
                    486: 
                    487:        if ( signal(SIGINT, done) == SIG_IGN )  {
                    488:                signal(SIGINT, SIG_IGN);
                    489:                signal(SIGQUIT, SIG_IGN);
                    490:                signal(SIGHUP, SIG_IGN);
                    491:        } else {
                    492:                signal(SIGHUP, done);
                    493:                signal(SIGQUIT, done);
                    494:        }   /* End else */
                    495: 
                    496: }   /* End of init_signals */
                    497: 
                    498: 
                    499: /*****************************************************************************/
                    500: 
                    501: 
                    502: options()
                    503: 
                    504: 
                    505: {
                    506: 
                    507: 
                    508:        int             ch;             /* option name returned from getopt */
                    509:        char            *names = "u:c:tx:y:r:a:o:p:LP:n:d:F:f:B:f:R:T:AJ:";
                    510: 
                    511:        extern char     *optarg;        /* option argument set by getopt() */
                    512:        extern int      optind;
                    513: 
                    514: 
                    515: /*
                    516:  *
                    517:  * Processes the command line options. The original stuff stuff done in
                    518:  * di10 has been changed a little. I've also used getopt() to scan the
                    519:  * options.
                    520:  *
                    521:  * The most confusing options are -B and -R. The *bitdir string is the
                    522:  * directory where we expect to find the raster file directories. They all
                    523:  * start with "rast" and end with a device name. I've got things set up so
                    524:  * that they're in /usr/lib/raster, but di10 looked for directory rasti10
                    525:  * in *fontdir (/usr/lib/font/devi10). The -B option changes the value
                    526:  * of *bitdir. If you're running DWB and want this program to replace di10
                    527:  * call it using the option "-B /usr/lib/font/devi10". The -R option
                    528:  * sets the value of string *rastdev. If that string isn't NULL then
                    529:  * "/rast*rastdev" will be appended to the end of *bitdir to locate the
                    530:  * raster file directory that we really want to use. By default rastdev is
                    531:  * NULL so *realdev will be used in its place.
                    532:  *
                    533:  * The -c option doesn't work right now. If you want to implement it you'll
                    534:  * probably just need to change the IPR system() call that's made in
                    535:  * print_file().
                    536:  *
                    537:  */
                    538: 
                    539: 
                    540:        while ( (ch = getopt(argc, argv, names)) != EOF )  {
                    541:                switch ( ch )  {
                    542:                case 'u':
                    543:                        username = optarg;
                    544:                        break;
                    545: 
                    546:                case 'c':
                    547:                        copies = atoi(optarg);
                    548:                        break;
                    549: 
                    550:                case 't':
                    551:                        tf = stdout;
                    552:                        break;
                    553: 
                    554:                case 'x':
                    555:                        xoff = atof(optarg);
                    556:                        setxoff = TRUE;
                    557:                        break;
                    558: 
                    559:                case 'y':
                    560:                        yoff = atof(optarg);
                    561:                        setyoff = TRUE;
                    562:                        break;
                    563: 
                    564: 
                    565:                case 'r':
                    566:                        pres = atoi(optarg);
                    567:                        setpres = TRUE;
                    568:                        break;
                    569: 
                    570:                case 'a':
                    571:                        aspect = atof(optarg);
                    572:                        break;
                    573: 
                    574:                case 'o':
                    575:                        out_list(optarg);
                    576:                        break;
                    577: 
                    578:                case 'p':                       /* pixels of resolution */
                    579:                        if ( (DX = DY = atoi(optarg)) <= 0 )
                    580:                                DX = DY = 1;
                    581:                        break;
                    582: 
                    583:                case 'L':                       /* landscape mode */
                    584:                        mode = LANDSCAPE;
                    585:                        break;
                    586: 
                    587:                case 'P':                       /* pen diameter for drawing */
                    588:                        if ( (penwidth = atoi(optarg)) > 20 )
                    589:                                penwidth = 20;
                    590:                        else if ( penwidth < 1 ) penwidth = 1;
                    591:                        setpenwidth = TRUE;
                    592:                        break;
                    593: 
                    594:                case 'n':                       /* a limit for drawing routines */
                    595:                        if ( (maxdots = atoi(optarg)) <= 0 )
                    596:                                maxdots = 32000;
                    597:                        break;
                    598: 
                    599:                case 'd':
                    600:                        if ( (debug = atoi(optarg)) == 0 )
                    601:                                debug = 1;
                    602:                        tf = stdout;
                    603:                        break;
                    604: 
                    605:                case 'F':                       /* font table directory */
                    606:                        fontdir = optarg;
                    607:                        break;
                    608: 
                    609:                case 'B':                       /* rast* directories found here */
                    610:                        bitdir = optarg;
                    611:                        break;
                    612: 
                    613:                case 'f':                       /* use this resident font file */
                    614:                        resfile = optarg;
                    615:                        break;
                    616: 
                    617:                case 'R':                       /* use this guys raster files */
                    618:                        rastdev = optarg;
                    619:                        break;
                    620: 
                    621:                case 'T':                       /* target printer */
                    622:                        for ( pr_num = 0; prdata[pr_num].prname != NULL; pr_num++ )
                    623:                                if ( strcmp(optarg, prdata[pr_num].prname) == 0 )
                    624:                                        break;
                    625:                        if ( prdata[pr_num].prname == NULL )
                    626:                                error(FATAL, "don't know printer %s", optarg);
                    627:                        break;
                    628: 
                    629:                /* These options were added for the MHCC */
                    630: 
                    631:                case 'A':
                    632:                        x_stat |= DO_ACCT;
                    633:                        break;
                    634: 
                    635:                case 'J':
                    636:                        jacctfile = optarg;
                    637:                        x_stat |= DO_ACCT;
                    638:                        break;
                    639: 
                    640:                case '?':
                    641:                        error(FATAL, "");
                    642:                        break;
                    643: 
                    644:                default:
                    645:                        error(FATAL, "don't know option %s", argv[1]);
                    646:                        break;
                    647:                }
                    648:        }
                    649: 
                    650:        argc -= optind;                 /* get ready for non-options args */
                    651:        argv += optind;
                    652: 
                    653: }   /* End of options */
                    654: 
                    655: 
                    656: /*****************************************************************************/
                    657: 
                    658: 
                    659: initialize()
                    660: 
                    661: 
                    662: {
                    663: 
                    664: 
                    665:        char    *mktemp();
                    666: #ifdef V9
                    667:        char    *getlogin();
                    668: #endif
                    669: 
                    670: 
                    671: /*
                    672:  *
                    673:  * Much of this stuff can only be done properly after the command line
                    674:  * options have been processed, so make sure it's called (from main())
                    675:  * after options().
                    676:  *
                    677:  */
                    678: 
                    679: #ifdef V9
                    680:        if (username == NULL && (username = getlogin()) == NULL )
                    681: #endif
                    682: #ifdef SYSV
                    683:        if ( (username = cuserid((char *) 0)) == NULL )
                    684: #endif
                    685:                username = "???";
                    686: 
                    687:        if (tf != stdout)  {
                    688:                tempfile = mktemp("/tmp/dimpXXXXX");
                    689:                if ((tf = fopen(tempfile, "w")) == NULL)
                    690:                        error(FATAL, "can't open temporary file %s", tempfile);
                    691:        }   /* End if */
                    692: 
                    693:        if ( realdev == NULL )
                    694:                realdev = prdata[pr_num].prname;
                    695: 
                    696:        if ( setpres == FALSE )
                    697:                pres = prdata[pr_num].pres;
                    698: 
                    699:        if ( setxoff == FALSE )
                    700:                xoff = prdata[pr_num].xoff;
                    701: 
                    702:        if ( setyoff == FALSE )
                    703:                yoff = prdata[pr_num].yoff;
                    704: 
                    705:        if ( setpenwidth == FALSE )
                    706:                penwidth = prdata[pr_num].penwidth;
                    707: 
                    708:        if ( bitdir == NULL )
                    709:                bitdir = prdata[pr_num].bitdir;
                    710: 
                    711:        if ( resfile == NULL )
                    712:                resfile = prdata[pr_num].prname;
                    713: 
                    714:        res = rres = pres;              /* just to be safe */
                    715: 
                    716:        xoffset = pres * xoff;          /* set the pixel offsets */
                    717:        yoffset = pres * yoff;
                    718: 
                    719: }   /* End of initialize */
                    720: 
                    721: 
                    722: /*****************************************************************************/
                    723: 
                    724: 
                    725: rastsetup()
                    726: 
                    727: 
                    728: {
                    729: 
                    730: 
                    731:        static char     rastname[100];  /* rastdir string saved here */
                    732:        char            temp[100];      /* for pathnames and reads from *fp */
                    733:        FILE            *fp;            /* RASTDATA and RASTLIST files */
                    734:        int             ch;             /* just used to skip lines in *fp */
                    735: 
                    736: 
                    737: /*
                    738:  *
                    739:  * We'll need to know a bunch of stuff about the raster files before we can
                    740:  * actually use them. First of all we need to figure out where they are.
                    741:  * Strings *bitdir and either *rastdev or *realdev will be used to initialize
                    742:  * *rastdir. Once we've got rastname set up we'll need to determine the
                    743:  * format of the raster files and their resolution. All that stuff should
                    744:  * be in file *rastdir/RASTDATA. If the file's not there or we can't read
                    745:  * it we'll assume the files are written in the old format at a resolution
                    746:  * of 240 dots per inch. I've done things this way because RASTDATA is new
                    747:  * and won't be part of the of raster file directory unless you add it.
                    748:  * This way nothing has to be done to the old raster file directory.
                    749:  *
                    750:  */
                    751: 
                    752: 
                    753:        sprintf(rastname, "%s/rast%s", bitdir, (rastdev == NULL) ? realdev : rastdev);
                    754:        rastdir = rastname;
                    755: 
                    756:        sprintf(temp, "%s/%s", rastdir, RASTDATA);
                    757:        if ( (fp = fopen(temp, "r")) == NULL )  {
                    758:                rastformat = OLD_FORMAT;
                    759:                rres = 240;
                    760:                return;
                    761:        }   /* End if */
                    762: 
                    763:        while ( fscanf(fp, "%s", temp) != EOF )
                    764:                if ( strcmp(temp, "format") == 0 )  {
                    765:                        fscanf(fp, "%s", temp);
                    766:                        if ( strcmp(temp, "old") == 0 )
                    767:                                rastformat = OLD_FORMAT;
                    768:                        else rastformat = RST_FORMAT;
                    769:                } else if ( strcmp(temp, "resolution") == 0 )
                    770:                        fscanf(fp, "%d", &rres);
                    771:                else while ( (ch = getc(fp)) != '\n'  &&  ch != EOF ) ;
                    772: 
                    773:        fclose(fp);
                    774: 
                    775: }   /* End of rastsetup */
                    776: 
                    777: 
                    778: /*****************************************************************************/
                    779: 
                    780: 
                    781: rastlist()
                    782: 
                    783: 
                    784: {
                    785: 
                    786: 
                    787:        int             n;              /* next size for current font */
                    788:        int             i;              /* next size goes here */
                    789:        char            name[100];      /* pathname for RASTERLIST file */
                    790:        FILE            *fp;
                    791: 
                    792: 
                    793: /*
                    794:  *
                    795:  * If we're not using the old format raster files we'll want to read the
                    796:  * list of available fonts and sizes in *rastdir. The file that's got all
                    797:  * the info is called RASTLIST (defined in init.h). The format is exactly
                    798:  * the same as Brian's original file. Under the old format all this stuff
                    799:  * is done in routine initfontdata().
                    800:  *
                    801:  * For now if we can't open RASTERLIST and were not using the old format
                    802:  * raster files we'll just return to the caller. That really just means
                    803:  * we'll assume we can handle any font + size request that may come our
                    804:  * way. If that's not the case we better make up a complete RASTERLIST file.
                    805:  *
                    806:  */
                    807: 
                    808: 
                    809:        if ( rastformat == OLD_FORMAT ) /* don't bother doing it here */
                    810:                return;
                    811: 
                    812:        sprintf(name, "%s/%s", rastdir, RASTLIST);
                    813:        if ( (fp = fopen(name, "r")) == NULL )
                    814:                return;
                    815: 
                    816:        while ( fscanf(fp, "%s", sizedata[maxrast].name) != EOF )  {
                    817:                i = 0;
                    818:                while ( fscanf(fp, "%d", &n) != EOF  &&  n < 100 )
                    819:                        sizedata[maxrast].sizes[i++] = n;
                    820:                sizedata[maxrast].sizes[i] = 999;
                    821:                if ( ++maxrast >= MAXFONTS )
                    822:                        error(FATAL, "too many fonts in %s", name);
                    823:        }       /* End while */
                    824: 
                    825:        fclose(fp);
                    826: 
                    827: }   /* End of rastlist */
                    828: 
                    829: 
                    830: /*****************************************************************************/
                    831: 
                    832: 
                    833: arguments()
                    834: 
                    835: 
                    836: {
                    837: 
                    838: 
                    839:        FILE    *fp;                    /* next input file */
                    840: 
                    841: 
                    842: /*
                    843:  *
                    844:  * All the rest of the command line options are input files we want to
                    845:  * translate. If we get here and there are no more arguments, or if '-' is
                    846:  * in the list of file names, we'll process stdin.
                    847:  *
                    848:  */
                    849: 
                    850: 
                    851:        if (argc < 1)
                    852:                conv(stdin);
                    853:        else
                    854:                while (argc > 0) {
                    855:                        if (strcmp(*argv, "-") == 0)
                    856:                                fp = stdin;
                    857:                        else if ((fp = fopen(*argv, "r")) == NULL)
                    858:                                error(FATAL, "can't open %s", *argv);
                    859:                        conv(fp);
                    860:                        fclose(fp);
                    861:                        argc--;
                    862:                        argv++;
                    863:                }
                    864: 
                    865: }   /* End of arguments */
                    866: 
                    867: 
                    868: /*****************************************************************************/
                    869: 
                    870: 
                    871: print_file()
                    872: 
                    873: 
                    874: {
                    875: 
                    876: 
                    877:        char    buf[BUFSIZ];            /* IPR command line built up here */
                    878: 
                    879: 
                    880: /*
                    881:  *
                    882:  * Finished with all the input files and everything the printer needs to
                    883:  * know is in FILE *tf. We'll close the file because we're all done with
                    884:  * it, and then call IPR if we haven't been writing to stdout.
                    885:  *
                    886:  */
                    887: 
                    888: 
                    889:        fclose(tf);                     /* everything's in the file */
                    890: 
                    891:        if ( tf != stdout  ||  debug )  {
                    892:                sprintf(buf, "%s -Limpress -r -o '-Downer \"'\"%s\"'\"'\", jobheader on, pagecollation on, pagereversal on\" %s 0</dev/null 1>/dev/null 2>&1 &",
                    893:                IPR, username, tempfile);
                    894:                if ( debug )
                    895:                        fprintf(stderr, "executing %s\n", buf);
                    896:                else system(buf);
                    897:        }   /* End if */
                    898: 
                    899: }   /* End of print_file */
                    900: 
                    901: 
                    902: /*****************************************************************************/
                    903: 
                    904: 
                    905: acct_file()
                    906: 
                    907: 
                    908: {
                    909: 
                    910: 
                    911: /*
                    912:  *
                    913:  * If we want to do accounting *acctfile will be the name of the file where
                    914:  * we put the accounting data. If for some reason we can't open the file
                    915:  * we'll just quit. I've called the routine from main() before anything is
                    916:  * written to the output file.
                    917:  *
                    918:  */
                    919: 
                    920: 
                    921:        if ( acctfile != NULL  &&  *acctfile != '\0' )  {
                    922:                if ( (fp_acct = fopen(acctfile, "a")) == NULL )  {
                    923:                        fp_acct = stderr;
                    924:                        x_stat |= NO_ACCTFILE;
                    925:                        error(FATAL, "can't open accounting file");
                    926:                        exit(x_stat);
                    927:                }
                    928:                if ( tf != stdout )
                    929:                        x_stat |= DO_ACCT;
                    930:        }
                    931: 
                    932: }   /* End of acct_file */
                    933: 
                    934: 
                    935: /*****************************************************************************/
                    936: 
                    937: 
                    938: account()
                    939: 
                    940: 
                    941: {
                    942: 
                    943: 
                    944:        FILE    *f;                     /* just the job's page count */
                    945: 
                    946: 
                    947: /*
                    948:  *
                    949:  * Writes an accounting record, usually to *fp_acct, for the current job.
                    950:  * All this stuff is set up for our MHCC printers. In some cases we'll
                    951:  * know most everything about the job (called with -J option) and all
                    952:  * we'll do is write a page count to *jacctfile. In other cases we'll want
                    953:  * a more complete record and all the stuff will go to *fp_acct. You'll
                    954:  * undoubtedly want to change this stuff to suit your own needs.
                    955:  *
                    956:  */
                    957: 
                    958:        if ( x_stat & DO_ACCT )  {
                    959:                if ( jacctfile == NULL || *jacctfile == '\0' )  {
                    960:                        fprintf(fp_acct, " user = %-10s", username);
                    961:                        fprintf(fp_acct, " paper = %-10d", acctpages * copies);
                    962:                        x_stat &= ~DO_ACCT;
                    963:                        fprintf(fp_acct, " exit_status = 0%-6o", x_stat);
                    964:                        fprintf(fp_acct, " type = t ");
                    965:                        if ( tf == stdout )
                    966:                                fprintf(fp_acct, "  ??");
                    967:                        fprintf(fp_acct, "\n");
                    968:                } else {
                    969:                        if ( (f = fopen(jacctfile, "a")) != NULL )  {
                    970:                                fprintf(f, "%d\n", acctpages);
                    971:                                fclose(f);
                    972:                        }
                    973:                        x_stat &= ~DO_ACCT;
                    974:                }       /* End else */
                    975:        }
                    976: 
                    977: }   /* End of account */
                    978: 
                    979: 
                    980: /*****************************************************************************/
                    981: 
                    982: 
                    983: done()
                    984: 
                    985: 
                    986: {
                    987: 
                    988: 
                    989: /*
                    990:  *
                    991:  * Finished with everything so we want to make sure accounting is handled
                    992:  * properly and the right exit status is returned to the caller. We'll also
                    993:  * delete the temporary file if x_stat != 0.
                    994:  *
                    995:  */
                    996: 
                    997: 
                    998:        account();
                    999: 
                   1000:        if ( tf != stdout  &&  x_stat != 0 )
                   1001:                unlink(tempfile);
                   1002: 
                   1003:        exit(x_stat);
                   1004: 
                   1005: }   /* End of done */
                   1006: 
                   1007: 
                   1008: /*****************************************************************************/
                   1009: 
                   1010: 
                   1011: conv(fp)
                   1012: 
                   1013: 
                   1014:        register FILE   *fp;
                   1015: 
                   1016: 
                   1017: {
                   1018: 
                   1019: 
                   1020:        register int    c, k;
                   1021:        int             m, n, i, n1, m1;
                   1022:        char            str[100], buf[300];
                   1023: 
                   1024: 
                   1025: /*
                   1026:  *
                   1027:  * Controls the translation of troff's device independent output language
                   1028:  * to Impress. Some of the commands, like slant and height, are no-ops
                   1029:  * on Imagen's bitmap printers even though routines are called to do the
                   1030:  * processing.
                   1031:  *
                   1032:  */
                   1033: 
                   1034: 
                   1035:        lineno = 1;                     /* line in current file */
                   1036:        x_stat |= FILE_STARTED;         /* we'll clear it when done with *fp */
                   1037: 
                   1038:        while ((c = getc(fp)) != EOF) {
                   1039: 
                   1040:                switch (c) {
                   1041: 
                   1042:                case '\n':              /* just count this line */
                   1043:                        lineno++;
                   1044:                        break;
                   1045: 
                   1046:                case ' ':               /* when input is text */
                   1047:                case 0:                 /* occasional noise creeps in */
                   1048:                        break;
                   1049: 
                   1050:                case '0': case '1': case '2': case '3': case '4':
                   1051:                case '5': case '6': case '7': case '8': case '9':
                   1052:                        /* two motion digits plus a character */
                   1053:                        hmot((c-'0')*10 + getc(fp)-'0');
                   1054:                        put1(getc(fp));
                   1055:                        break;
                   1056: 
                   1057:                case 'c':               /* single ascii character */
                   1058:                        put1(getc(fp));
                   1059:                        break;
                   1060: 
                   1061:                case 'C':               /* special character */
                   1062:                        fscanf(fp, "%s", str);
                   1063:                        put1s(str);
                   1064:                        break;
                   1065: 
                   1066:                case 'N':               /* character at position n */
                   1067:                        fscanf(fp, "%d", &m);
                   1068:                        oput(m);
                   1069:                        break;
                   1070: 
                   1071:                case 'D':               /* drawing function */
                   1072:                        fgets(buf, sizeof(buf), fp);
                   1073:                        lineno++;
                   1074:                        switch (buf[0]) {
                   1075:                        case 'l':       /* draw a line */
                   1076:                                sscanf(buf+1, "%d %d", &n, &m);
                   1077:                                drawline(n, m);
                   1078:                                break;
                   1079: 
                   1080:                        case 'c':       /* circle */
                   1081:                                sscanf(buf+1, "%d", &n);
                   1082:                                drawcirc(n);
                   1083:                                break;
                   1084: 
                   1085:                        case 'e':       /* ellipse */
                   1086:                                sscanf(buf+1, "%d %d", &m, &n);
                   1087:                                drawellip(m, n);
                   1088:                                break;
                   1089: 
                   1090:                        case 'a':       /* arc */
                   1091:                                sscanf(buf+1, "%d %d %d %d", &n, &m, &n1, &m1);
                   1092:                                drawarc(n, m, n1, m1);
                   1093:                                break;
                   1094: 
                   1095:                        case '~':       /* wiggly line */
                   1096:                                drawwig(buf+1);
                   1097:                                break;
                   1098: 
                   1099:                        default:
                   1100:                                error(FATAL, "unknown drawing function %s", buf);
                   1101:                                break;
                   1102:                        }
                   1103:                        break;
                   1104: 
                   1105:                case 's':                       /* use this point size */
                   1106:                        fscanf(fp, "%d", &n);   /* ignore fractional sizes */
                   1107:                        setsize(t_size(n));
                   1108:                        break;
                   1109: 
                   1110:                case 'f':                       /* use font mounted here */
                   1111:                        fscanf(fp, "%s", str);
                   1112:                        setfont(t_font(str));
                   1113:                        break;
                   1114: 
                   1115:                case 'H':                       /* absolute horizontal motion */
                   1116: /*
                   1117:  *
                   1118:  * The simple scan I've commented out didn't handle negative numbers right
                   1119:  * and believe it or not we did get jobs that asked for negative absolute
                   1120:  * positions. Even though negative absolute coordinates probably are a
                   1121:  * mistake it makes more sense to handle the numbers properly.
                   1122:  *
                   1123:                        while ((c = getc(fp)) == ' ')
                   1124:                                ;
                   1125:                        k = 0;
                   1126:                        do {
                   1127:                                k = 10 * k + c - '0';
                   1128:                        } while (isdigit(c = getc(fp)));
                   1129:                        ungetc(c, fp);
                   1130:                        hgoto(k);
                   1131:  *
                   1132:  */
                   1133:                        fscanf(fp, "%d", &n);
                   1134:                        hgoto(n);
                   1135:                        break;
                   1136: 
                   1137:                case 'h':               /* relative horizontal motion */
                   1138: /*
                   1139:  *
                   1140:  * Again the same potential problem with negative numbers exists here. In
                   1141:  * fact it makes a lot more sense to expect negative relative motions even
                   1142:  * though I never did see them. Anyway just to be safe I've made the same
                   1143:  * change - take it out if you want.
                   1144:  *
                   1145:                        while ((c = getc(fp)) == ' ')
                   1146:                                ;
                   1147:                        k = 0;
                   1148:                        do {
                   1149:                                k = 10 * k + c - '0';
                   1150:                        } while (isdigit(c = getc(fp)));
                   1151:                        ungetc(c, fp);
                   1152:                        hmot(k);
                   1153:  *
                   1154:  */
                   1155:                        fscanf(fp, "%d", &n);
                   1156:                        hmot(n);
                   1157:                        break;
                   1158: 
                   1159:                case 'w':                       /* word space */
                   1160:                        break;
                   1161: 
                   1162:                case 'V':                       /* absolute vertical position */
                   1163:                        fscanf(fp, "%d", &n);
                   1164:                        vgoto(n);
                   1165:                        break;
                   1166: 
                   1167:                case 'v':                       /* relative vertical motion */
                   1168:                        fscanf(fp, "%d", &n);
                   1169:                        vmot(n);
                   1170:                        break;
                   1171: 
                   1172:                case 'p':                       /* new page */
                   1173:                        fscanf(fp, "%d", &n);
                   1174:                        t_page(n);
                   1175:                        break;
                   1176: 
                   1177:                case 'n':                       /* end of line */
                   1178:                        while ( (c = getc(fp)) != '\n'  &&  c != EOF ) ;
                   1179:                        t_newline();
                   1180:                        lineno++;
                   1181:                        break;
                   1182: 
                   1183:                case '#':                       /* comment */
                   1184:                        while ( (c = getc(fp)) != '\n'  &&  c != EOF ) ;
                   1185:                        lineno++;
                   1186:                        break;
                   1187: 
                   1188:                case 'x':                       /* device control function */
                   1189:                        devcntrl(fp);
                   1190:                        break;
                   1191: 
                   1192:                default:
                   1193:                        error(!FATAL, "unknown input character %o %c", c, c);
                   1194:                        done();
                   1195:                }
                   1196:        }
                   1197: 
                   1198:        x_stat &= ~FILE_STARTED;
                   1199: 
                   1200: }   /* End of conv */
                   1201: 
                   1202: 
                   1203: /*****************************************************************************/
                   1204: 
                   1205: 
                   1206: devcntrl(fp)
                   1207: 
                   1208: 
                   1209:        FILE    *fp;                    /* current input file */
                   1210: 
                   1211: 
                   1212: {
                   1213: 
                   1214: 
                   1215:        char    str[20], str1[50], buf[50];
                   1216:        int     c, n, x, y;
                   1217: 
                   1218: 
                   1219: /*
                   1220:  *
                   1221:  * Called form conv() to process the rest of a device control function.
                   1222:  * There's a whole family of them and they all begin with the string
                   1223:  * "x ". The rest of the command consists of the function name followed
                   1224:  * by zero or more arguments that depend on the particular command. We've
                   1225:  * already read the "x" from the input file, that's why the routine was
                   1226:  * called. The whole rest of the input line is assumed to be part of the
                   1227:  * device control command.
                   1228:  *
                   1229:  */
                   1230: 
                   1231: 
                   1232:        fscanf(fp, "%s", str);          /* get the control function name */
                   1233: 
                   1234:        switch ( str[0] )  {            /* only the first character counts now */
                   1235:        case 'i':                       /* initialize */
                   1236:                fileinit();
                   1237:                t_init(0);
                   1238:                break;
                   1239: 
                   1240:        case 'T':                       /* device name */
                   1241:                fscanf(fp, "%s", devname);
                   1242:                break;
                   1243: 
                   1244:        case 't':                       /* trailer */
                   1245:                t_trailer();
                   1246:                break;
                   1247: 
                   1248:        case 'p':                       /* pause -- can restart */
                   1249:                t_reset('p');
                   1250:                break;
                   1251: 
                   1252:        case 's':                       /* stop */
                   1253:                t_reset('s');
                   1254:                break;
                   1255: 
                   1256:        case 'r':                       /* resolution assumed when prepared */
                   1257:                fscanf(fp, "%d", &res);
                   1258:                break;
                   1259: 
                   1260:        case 'f':                       /* load font in a position */
                   1261:                fscanf(fp, "%d %s", &n, str);
                   1262:                fgets(buf, sizeof buf, fp);     /* in case there's a filename */
                   1263:                ungetc('\n', fp);       /* fgets goes too far */
                   1264:                str1[0] = 0;    /* in case there's nothing to come in */
                   1265:                sscanf(buf, "%s", str1);
                   1266:                loadfont(n, str, str1);
                   1267:                break;
                   1268: 
                   1269:        /* these don't belong here... */
                   1270:        case 'H':                       /* char height */
                   1271:                fscanf(fp, "%d", &n);
                   1272:                t_charht(n);
                   1273:                break;
                   1274: 
                   1275:        case 'S':                       /* slant */
                   1276:                fscanf(fp, "%d", &n);
                   1277:                t_slant(n);
                   1278:                break;
                   1279: 
                   1280:        case 'I':
                   1281:        case 'B':
                   1282:                x = hpos * xfac + xoffset + .5;
                   1283:                y = vpos * yfac + yoffset + .5;
                   1284: 
                   1285:                /* force 32x32 alignment, imagen 3.2 software does this
                   1286:                ** anyway, but this should fix others
                   1287:                */
                   1288:                putc(ASETAV, tf); putint(y&~0x1f, tf);
                   1289:                putc(ASETAH, tf); putint(x&~0x1f, tf);
                   1290: 
                   1291:                if (str[0] == 'I') {
                   1292:                        fscanf(fp, "%d %s", &n, buf);
                   1293:                        iglyphpage(tf, buf, n, x&0x1f, y&0x1f);
                   1294:                } else if (str[0] == 'B') {
                   1295:                        fscanf(fp, "%d %s", &n, buf);
                   1296:                        glyphpage(tf, buf, n, x&0x1f, y&0x1f);
                   1297:                }
                   1298: 
                   1299:                /* position back where it belongs */
                   1300:                putc(ASETAV, tf); putint(y, tf); lasty = y;
                   1301:                putc(ASETAH, tf); putint(x, tf); lastx = x;
                   1302:                break;
                   1303:        }
                   1304: 
                   1305:        while ( (c = getc(fp)) != '\n'  &&  c != EOF ) ;
                   1306: 
                   1307:        lineno++;
                   1308: 
                   1309: }   /* End of devcntrl */
                   1310: 
                   1311: 
                   1312: /*****************************************************************************/
                   1313: 
                   1314: 
                   1315: fileinit()
                   1316: 
                   1317: 
                   1318: {
                   1319: 
                   1320: 
                   1321:     int                i, fin;
                   1322:     char       *filebase;
                   1323:     char       temp[100];
                   1324: 
                   1325: 
                   1326: /*
                   1327:  *
                   1328:  * Called from t_init(), which in turn is called from devcntrl(), whenever we get
                   1329:  * an "x init" command. There are a few lines of code here that set things up for
                   1330:  * emulating another device.
                   1331:  *
                   1332:  */
                   1333: 
                   1334: 
                   1335:     sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname);
                   1336:     if ( (fin = open(temp, 0)) < 0 )
                   1337:        error(FATAL, "can't open tables for %s", temp);
                   1338: 
                   1339:     read(fin, &dev, sizeof(struct dev));
                   1340: 
                   1341:     nfonts = dev.nfonts;
                   1342: 
                   1343:     if ( strcmp(devname, realdev) != 0 )  {    /* device emulation */
                   1344:        close(fin);
                   1345:        strcpy(devname, realdev);
                   1346:        sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname);
                   1347:        if ( (fin = open(temp, 0)) < 0 )
                   1348:            error(FATAL, "can't open tables for %s", temp);
                   1349:        read(fin, &dev, sizeof(struct dev));
                   1350:     }  /* End if */
                   1351: 
                   1352:     nsizes = dev.nsizes;
                   1353:     nchtab = dev.nchtab;
                   1354: 
                   1355:     if ( (filebase = malloc(dev.filesize)) == NULL )
                   1356:        error(FATAL, "no memory for description file");
                   1357: 
                   1358:     read(fin, filebase, dev.filesize); /* all at once */
                   1359: 
                   1360:     pstab = (short *) filebase;
                   1361:     chtab = pstab + nsizes + 1;
                   1362:     chname = (char *) (chtab + dev.nchtab);
                   1363: 
                   1364:     for ( i = 1; i <= nfonts; i++ )  {
                   1365:        fontbase[i] = NULL;
                   1366:        widthtab[i] = codetab[i] = fitab[i] = NULL;
                   1367:     }  /* End for */
                   1368: 
                   1369:     close(fin);
                   1370: 
                   1371: }   /* End of fileinit */
                   1372: 
                   1373: 
                   1374: /*****************************************************************************/
                   1375: 
                   1376: 
                   1377: fontprint(i)
                   1378: 
                   1379: 
                   1380:     int                i;                      /* font's index in fontbase[] */
                   1381: 
                   1382: 
                   1383: {
                   1384: 
                   1385: 
                   1386:     int                j, n;
                   1387:     char       *p;
                   1388: 
                   1389: 
                   1390: /*
                   1391:  *
                   1392:  * Just a debugging routine that dumps most of the important information about
                   1393:  * the font that's mounted in position i.
                   1394:  *
                   1395:  */
                   1396: 
                   1397: 
                   1398:     fprintf(tf, "font %d:\n", i);
                   1399: 
                   1400:     p = (char *) fontbase[i];
                   1401:     n = fontbase[i]->nwfont & BMASK;
                   1402: 
                   1403:     fprintf(tf, "base=0%o, nchars=%d, spec=%d, name=%s, widtab=0%o, fitab=0%o\n",
                   1404:            p, n, fontbase[i]->specfont, fontbase[i]->namefont, widthtab[i], fitab[i]);
                   1405: 
                   1406:     fprintf(tf, "widths:\n");
                   1407:     for ( j = 0; j <= n; j++ )  {
                   1408:        fprintf(tf, " %2d", widthtab[i][j] & BMASK);
                   1409:        if ( j % 20 == 19 ) putc('\n', tf);
                   1410:     }  /* End for */
                   1411: 
                   1412:     fprintf(tf, "\ncodetab:\n");
                   1413:     for ( j = 0; j <= n; j++ )  {
                   1414:        fprintf(tf, " %2d", codetab[i][j] & BMASK);
                   1415:        if ( j % 20 == 19 ) putc('\n', tf);
                   1416:     }  /* End for */
                   1417: 
                   1418:     fprintf(tf, "\nfitab:\n");
                   1419:     for ( j = 0; j <= dev.nchtab + 128-32; j++ )  {
                   1420:        fprintf(tf, " %2d", fitab[i][j] & BMASK);
                   1421:        if ( j % 20 == 19 ) putc('\n', tf);
                   1422:     }  /* End for */
                   1423: 
                   1424:     putc('\n', tf);
                   1425: 
                   1426: }   /* End of fontprint */
                   1427: 
                   1428: 
                   1429: /*****************************************************************************/
                   1430: 
                   1431: 
                   1432: loadfont(n, s, s1)
                   1433: 
                   1434: 
                   1435:     int                n;
                   1436:     char       *s, *s1;
                   1437: 
                   1438: 
                   1439: {
                   1440: 
                   1441: 
                   1442:     char       temp[80];
                   1443:     int                fin, nw;
                   1444: 
                   1445: 
                   1446: /*
                   1447:  *
                   1448:  * Called to to load font info for font *s on position n using the binary tables
                   1449:  * located in directory *s1 (if it's not NULL or the empty string).
                   1450:  *
                   1451:  */
                   1452: 
                   1453: 
                   1454:     if ( n < 0  ||  n > NFONT )                /* make sure it's a legal position */
                   1455:        error(FATAL, "illegal fp command %d %s", n, s);
                   1456: 
                   1457: /*
                   1458:  *
                   1459:  * If the font's already loaded on position n there's nothing to do.
                   1460:  *
                   1461:  */
                   1462: 
                   1463:     if ( fontbase[n] != NULL && strcmp(s, fontbase[n]->namefont) == 0 )
                   1464:        return;
                   1465: 
                   1466: /*
                   1467:  *
                   1468:  * If *s1 isn't NULL or the NULL string that's what we'll use for the font
                   1469:  * directory, otherwise use *fontdir.
                   1470:  *
                   1471:  */
                   1472: 
                   1473:     if ( s1 == NULL || s1[0] == '\0' )
                   1474:        sprintf(temp, "%s/dev%s/%s.out", fontdir, devname, s);
                   1475:     else sprintf(temp, "%s/%s.out", s1, s);
                   1476: 
                   1477:     if ( (fin = open(temp, 0)) < 0 )  {
                   1478:        sprintf(temp, "%s/dev%s/%s.out", fontdir, devname, mapfont(s));
                   1479:        if ( (fin = open(temp, 0)) < 0 )
                   1480:            error(FATAL, "can't open font table %s", temp);
                   1481:     }  /* End if */
                   1482: 
                   1483:     if ( fontbase[n] != NULL )         /* something's already there */
                   1484:        free(fontbase[n]);              /* so release the memory first */
                   1485: 
                   1486:     fontbase[n] = (struct Font *) malloc(3*255 + dev.nchtab + (128-32) + sizeof(struct Font));
                   1487:     if ( fontbase[n] == NULL )
                   1488:        error(FATAL, "Out of space in loadfont %s", s);
                   1489: 
                   1490:     read(fin, fontbase[n], 3*255 + nchtab+128-32 + sizeof(struct Font));
                   1491:     close(fin);
                   1492: 
                   1493:     if ( smnt == 0 && fontbase[n]->specfont == 1 )
                   1494:        smnt = n;
                   1495: 
                   1496:     nw = fontbase[n]->nwfont & BMASK;
                   1497:     widthtab[n] = (char *) fontbase[n] + sizeof(struct Font);
                   1498:     codetab[n] = (char *) widthtab[n] + 2 * nw;
                   1499:     fitab[n] = (char *) widthtab[n] + 3 * nw;
                   1500: 
                   1501:     t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
                   1502: 
                   1503:     if ( debug == ON )
                   1504:        fontprint(n);
                   1505: 
                   1506: }   /* End of loadfont */
                   1507: 
                   1508: 
                   1509: /*****************************************************************************/
                   1510: 
                   1511: 
                   1512: char *mapfont(name)
                   1513: 
                   1514: 
                   1515:     char       *name;                  /* name of the font troff wants */
                   1516: 
                   1517: 
                   1518: {
                   1519: 
                   1520: 
                   1521:     int                i;                      /* loop index for fontmap[] */
                   1522: 
                   1523: 
                   1524: /*
                   1525:  *
                   1526:  * Only called from loadfont() when we haven't been able to open the font file
                   1527:  * that troff asked for. We take the font name and map it into an appropriate
                   1528:  * substitute. If the initial lookup fails we do a simple mapping that should
                   1529:  * be good enough most of the time.
                   1530:  *
                   1531:  * This stuff should only be needed when we're emulating another printer like
                   1532:  * the APS-5.
                   1533:  *
                   1534:  */
                   1535: 
                   1536: 
                   1537:     for ( i = 0; fontmap[i].name != NULL; i++ )
                   1538:        if ( strcmp(name, fontmap[i].name) == 0 )
                   1539:            return(fontmap[i].use);
                   1540: 
                   1541:     switch ( *++name )  {
                   1542:        case 'I':
                   1543:        case 'B':
                   1544:                return(name);
                   1545: 
                   1546:        case 'X':
                   1547:                return("BI");
                   1548: 
                   1549:        default:
                   1550:                return("R");
                   1551:     }  /* End switch */
                   1552: 
                   1553: }   /* End of mapfont */
                   1554: 
                   1555: 
                   1556: /*****************************************************************************/
                   1557: 
                   1558: 
                   1559: convint(c)
                   1560: 
                   1561: 
                   1562:        unsigned char   c;
                   1563: 
                   1564: 
                   1565: {
                   1566: 
                   1567: 
                   1568: /*
                   1569:  *
                   1570:  * Converts a character to a proper 2's complement integer. Really just used
                   1571:  * on 3b's when we're reading raster tables in the old format. There's
                   1572:  * really no need to make this a separate routine - at least I don't
                   1573:  * think there is. Should just redefine CONVINT() macro so it does this
                   1574:  * stuff.
                   1575:  *
                   1576:  */
                   1577: 
                   1578: 
                   1579:        return((c & 0200) ? ((256 - c) * -1) : c);
                   1580: 
                   1581: }   /* End of convint */
                   1582: 
                   1583: 
                   1584: /*****************************************************************************/
                   1585: 
                   1586: 
                   1587: t_init(reinit)
                   1588: 
                   1589: 
                   1590:        int     reinit;
                   1591: 
                   1592: 
                   1593: {
                   1594: 
                   1595: 
                   1596:        int     i;
                   1597:        FILE    *tmpfile();
                   1598: 
                   1599: 
                   1600: /*
                   1601:  *
                   1602:  * Called to initialize the printer and associated variables. reinit will
                   1603:  * be zero when the "x init" command was found in the output file, while
                   1604:  * it will be non-zero when the routine is called to set things up for a
                   1605:  * new page.
                   1606:  *
                   1607:  */
                   1608: 
                   1609: 
                   1610:        if (! reinit) {
                   1611:                for (i = 0; i < nchtab; i++)
                   1612:                        if (strcmp(&chname[chtab[i]], "l.") == 0)
                   1613:                                break;
                   1614:                if (i < nchtab) {
                   1615:                        drawdot = i + 128;
                   1616:                        drawsize = 1;
                   1617:                } else {
                   1618:                        drawdot = '.';
                   1619:                        drawsize = 2;   /* half size */
                   1620:                }
                   1621: 
                   1622:                xfac = (float) pres / res * aspect;
                   1623:                yfac = (float) pres / res;
                   1624: 
                   1625:                putc(ASETPEN, tf);
                   1626:                putc(penwidth, tf);
                   1627: 
                   1628:                if ( mode == LANDSCAPE )  {
                   1629:                    putc(ASETHV, tf);
                   1630:                    putc(0107, tf);
                   1631:                    angle = ROT_270;
                   1632:                }   /* End if */
                   1633:        }
                   1634: 
                   1635:        hpos = vpos = 0;
                   1636:        setsize(t_size(10));    /* start somewhere */
                   1637: 
                   1638: }   /* End of t_init */
                   1639: 
                   1640: 
                   1641: /*****************************************************************************/
                   1642: 
                   1643: 
                   1644: t_page(pg)
                   1645: 
                   1646: 
                   1647: {
                   1648: 
                   1649: 
                   1650:        register int            i, j, n;
                   1651:        register unsigned       char *p;
                   1652: 
                   1653: 
                   1654: /*
                   1655:  *
                   1656:  * Get the printer and everything else ready for a new page. If the -o
                   1657:  * option has been used only selected pages will be printed. If output
                   1658:  * is ON when this routine is called we'll write the endpage Impress
                   1659:  * command to the output file. If we're supposed to be doing output for
                   1660:  * page pg we'll write the APAGE command out, and that will cause the
                   1661:  * horizontal and vertical positions (in Impress) to be set to zero. hpos
                   1662:  * and vpos are initialized in routine t_init(), although I really don't
                   1663:  * see any reason why we couldn't just skip the call and do it here.
                   1664:  *
                   1665:  */
                   1666: 
                   1667: 
                   1668:        if ( debug == ON )
                   1669:                fprintf(stderr, "t_page %d, output=%d\n", pg, output);
                   1670: 
                   1671:        pageno = pg;
                   1672: 
                   1673:        if ( output == ON )             /* doing output for last page */
                   1674:                putc(AENDP, tf);
                   1675: 
                   1676:        if ( (output = in_olist(pg)) == ON )  {         /* print this page */
                   1677:                putc(APAGE, tf);
                   1678:                acctpages++;
                   1679:        }
                   1680: 
                   1681:        lastx = lasty = -1;
                   1682:        t_init(1);                      /* setup for this page */
                   1683: 
                   1684: }   /* End of t_page */
                   1685: 
                   1686: 
                   1687: /*****************************************************************************/
                   1688: 
                   1689: 
                   1690: t_newline()
                   1691: 
                   1692: 
                   1693: {
                   1694: 
                   1695: 
                   1696: /*
                   1697:  *
                   1698:  * Read an "n a b" command in the input file and are ready to start a new
                   1699:  * line. There really isn't much else this routine can do besides set the
                   1700:  * horizontal position to zero. Anyway troff takes care of any needed
                   1701:  * positioning before it starts printing text.
                   1702:  *
                   1703:  */
                   1704: 
                   1705: 
                   1706:        hpos = 0;
                   1707: 
                   1708: }   /* End of t_newline */
                   1709: 
                   1710: 
                   1711: /*****************************************************************************/
                   1712: 
                   1713: 
                   1714: t_size(n)
                   1715: 
                   1716: 
                   1717:        int     n;                      /* convert this point size */
                   1718: 
                   1719: 
                   1720: {
                   1721: 
                   1722: 
                   1723:        int     i;
                   1724: 
                   1725: 
                   1726: /*
                   1727:  *
                   1728:  * Converts a point size into an internal size that can be used as an
                   1729:  * index into the pstab[] array. Actually the internal size is defined as
                   1730:  * one plus the index of the least upper bound of n in pstab[] or nsizes
                   1731:  * if n is larger than all the listed sizes.
                   1732:  *
                   1733:  */
                   1734: 
                   1735:        if (n <= pstab[0])
                   1736:                return(1);
                   1737:        else if (n >= pstab[nsizes-1])
                   1738:                return(nsizes);
                   1739:        for (i = 0; n > pstab[i]; i++) ;
                   1740: 
                   1741:        return(i+1);
                   1742: 
                   1743: }   /* End of t_size */
                   1744: 
                   1745: 
                   1746: /*****************************************************************************/
                   1747: 
                   1748: 
                   1749: t_charht(n)
                   1750: 
                   1751: 
                   1752:        int     n;                      /* use this as the character height */
                   1753: 
                   1754: 
                   1755: {
                   1756: 
                   1757: 
                   1758: /*
                   1759:  *
                   1760:  * Although it can be done on some typesetters, like the APS-5, it's ignored
                   1761:  * on Imagen's bitmap printers like the Imprint-10 and the 8/300. It would
                   1762:  * be absurd to keep any extra raster files around just so we could implement
                   1763:  * this command, and right now there's no Impress command to do it to
                   1764:  * downloaded glyphs.
                   1765:  *
                   1766:  */
                   1767: 
                   1768: 
                   1769: }   /* End of t_charht */
                   1770: 
                   1771: 
                   1772: /*****************************************************************************/
                   1773: 
                   1774: 
                   1775: t_slant(n)
                   1776: 
                   1777: 
                   1778:        int     n;                      /* slant characters this many degrees */
                   1779: 
                   1780: 
                   1781: {
                   1782: 
                   1783: 
                   1784: /*
                   1785:  *
                   1786:  * As with troff's height command, there's no simple way to slant characters
                   1787:  * on Imagen's bitmap printers and it's really not worth any effort to try
                   1788:  * and make it work.
                   1789:  *
                   1790:  */
                   1791: 
                   1792: 
                   1793: }   /* End of t_slant */
                   1794: 
                   1795: 
                   1796: /*****************************************************************************/
                   1797: 
                   1798: 
                   1799: t_font(s)
                   1800: 
                   1801: 
                   1802:        char    *s;
                   1803: 
                   1804: 
                   1805: {
                   1806: 
                   1807: 
                   1808:        int     n;
                   1809: 
                   1810: 
                   1811: /*
                   1812:  *
                   1813:  * Just converts the string *s into an integer and checks to make sure the
                   1814:  * number is a legal font position. If it's not we'll print an error message
                   1815:  * and then quit. di10 handled bad requests a little differently. Instead
                   1816:  * of treating mistakes as FATAL errors it would return 1 as the font
                   1817:  * number.
                   1818:  *
                   1819:  */
                   1820: 
                   1821: 
                   1822:        if ( (n = atoi(s)) < 0  ||  n > nfonts )
                   1823:                error(FATAL, "illegal font position %d", n);
                   1824: 
                   1825:        return(n);
                   1826: 
                   1827: }   /* End of t_font */
                   1828: 
                   1829: 
                   1830: /*****************************************************************************/
                   1831: 
                   1832: 
                   1833: t_reset(c)
                   1834: 
                   1835: 
                   1836:        int     c;                      /* pause or restart */
                   1837: 
                   1838: 
                   1839: {
                   1840: 
                   1841: 
                   1842: /*
                   1843:  *
                   1844:  * Called from devcntrl() when we've found an "x stop" or "x pause" command.
                   1845:  * There's really nothing we need to do for Imagen's bitmap printers, and
                   1846:  * leaving the final cleanup (ie. AEOF code etc.) to someone else means
                   1847:  * we should be able to cat a bunch of troff output files together and
                   1848:  * have them all printed properly.
                   1849:  *
                   1850:  */
                   1851: 
                   1852: 
                   1853: }   /* End of t_reset */
                   1854: 
                   1855: 
                   1856: /*****************************************************************************/
                   1857: 
                   1858: 
                   1859: t_wrapup()
                   1860: 
                   1861: 
                   1862: {
                   1863: 
                   1864: 
                   1865: /*
                   1866:  *
                   1867:  * We're finished with all the input files and all that's left to do is
                   1868:  * end the last page we were working on and then mark the end of the Impress
                   1869:  * file.
                   1870:  *
                   1871:  */
                   1872: 
                   1873: 
                   1874:        putc(AENDP, tf);
                   1875:        putc(AEOF, tf);
                   1876: 
                   1877: }   /* End of t_wrapup */
                   1878: 
                   1879: 
                   1880: /*****************************************************************************/
                   1881: 
                   1882: 
                   1883: t_trailer()
                   1884: 
                   1885: 
                   1886: {
                   1887: 
                   1888: 
                   1889: /*
                   1890:  *
                   1891:  * Called from devcntrl() when an "x trailer" command is found. There's
                   1892:  * nothing we need to do here for Imagen's printers.
                   1893:  *
                   1894:  */
                   1895: 
                   1896: 
                   1897: 
                   1898: }   /* End of t_trailer */
                   1899: 
                   1900: 
                   1901: /*****************************************************************************/
                   1902: 
                   1903: 
                   1904: hgoto(n)
                   1905: 
                   1906: 
                   1907:        int     n;                      /* where we want to be */
                   1908: 
                   1909: 
                   1910: {
                   1911: 
                   1912: 
                   1913: /*
                   1914:  *
                   1915:  * Want to be at this absolute horizontal position next - usually will
                   1916:  * get these motion commands right before printing a character.
                   1917:  *
                   1918:  */
                   1919: 
                   1920: 
                   1921:        hpos = n;
                   1922: 
                   1923: }   /* End of hgoto */
                   1924: 
                   1925: 
                   1926: /*****************************************************************************/
                   1927: 
                   1928: 
                   1929: hmot(n)
                   1930: 
                   1931: 
                   1932:        int     n;                      /* move this far from where we are */
                   1933: 
                   1934: 
                   1935: {
                   1936: 
                   1937: 
                   1938: /*
                   1939:  *
                   1940:  * Handles relative horizontal motion. troff's current positon as recorded
                   1941:  * in hpos is changed by n units.
                   1942:  *
                   1943:  */
                   1944: 
                   1945: 
                   1946:        hpos += n;
                   1947: 
                   1948: }   /* End of hmot */
                   1949: 
                   1950: 
                   1951: /*****************************************************************************/
                   1952: 
                   1953: 
                   1954: vgoto(n)
                   1955: 
                   1956: 
                   1957:        int     n;                      /* new vertical position */
                   1958: 
                   1959: 
                   1960: {
                   1961: 
                   1962: 
                   1963: /*
                   1964:  *
                   1965:  * Moves vertically in troff's coordinate system to absolute position n.
                   1966:  *
                   1967:  */
                   1968: 
                   1969: 
                   1970:        vpos = n;
                   1971: 
                   1972: }   /* End of vgoto */
                   1973: 
                   1974: 
                   1975: /*****************************************************************************/
                   1976: 
                   1977: 
                   1978: vmot(n)
                   1979: 
                   1980: 
                   1981:        int     n;                      /* move this far vertically */
                   1982: 
                   1983: 
                   1984: {
                   1985: 
                   1986: 
                   1987: /*
                   1988:  *
                   1989:  * Handles relative vertical motion of n units in troff's coordinate system.
                   1990:  *
                   1991:  */
                   1992: 
                   1993: 
                   1994:        vpos += n;
                   1995: 
                   1996: }   /* End of vmot */
                   1997: 
                   1998: 
                   1999: /*****************************************************************************/
                   2000: 
                   2001: 
                   2002: put1s(s)
                   2003: 
                   2004: 
                   2005:        register char   *s;
                   2006: 
                   2007: 
                   2008: {
                   2009: 
                   2010: 
                   2011:        static int      i = 0;          /* last one we found - usually */
                   2012: 
                   2013: 
                   2014: /*
                   2015:  *
                   2016:  * Does whatever is necessary to have special character *s printed. If we're
                   2017:  * doing output on this page we'll look the character up using chname[] and
                   2018:  * chtab[]. The first array contains all the special character names
                   2019:  * separated by '\0' that are mentioned in the typesetter's DESC file, while
                   2020:  * chname[i] points to the start of character i in chname[]. Both arrays
                   2021:  * come from the DESC.out file for printer *devname which is found in
                   2022:  * *fontdir (wherever that might be).
                   2023:  *
                   2024:  */
                   2025: 
                   2026: 
                   2027:        if ( output == OFF )
                   2028:                return;
                   2029: 
                   2030:        if ( debug )
                   2031:                printf("%s", s);
                   2032: 
                   2033:        if (strcmp(s, &chname[chtab[i]]) != 0)
                   2034:                for (i = 0; i < nchtab; i++)
                   2035:                        if (strcmp(&chname[chtab[i]], s) == 0)
                   2036:                                break;
                   2037:        if (i < nchtab)
                   2038:                put1(i + 128);
                   2039:        else
                   2040:                i = 0;
                   2041: 
                   2042: }   /* End of put1s */
                   2043: 
                   2044: 
                   2045: /*****************************************************************************/
                   2046: 
                   2047: 
                   2048: put1(c)
                   2049: 
                   2050: 
                   2051:     register int       c;              /* print this character */
                   2052: 
                   2053: 
                   2054: {
                   2055: 
                   2056: 
                   2057:     char               *pw;
                   2058:     register char      *p;
                   2059:     register int       i, j, k;
                   2060:     int                        ofont, code;
                   2061: 
                   2062: 
                   2063: /*
                   2064:  *
                   2065:  * Arranges to have character c printed. If c < 128 it's a simple ASCII character,
                   2066:  * otherwise it's a special character. We subtract 32 from c because non-graphic
                   2067:  * ASCII characters aren't included in the tables.
                   2068:  *
                   2069:  */
                   2070: 
                   2071: 
                   2072:     lastc = c;                         /* charlib() may need the real name */
                   2073:     c -= 32;
                   2074: 
                   2075:     if ( c <= 0 )  {
                   2076:        if ( debug == ON )
                   2077:            fprintf(tf, "non-exist 0%o\n", lastc);
                   2078:        return;
                   2079:     }  /* End if */
                   2080: 
                   2081:     k = ofont = font;
                   2082:     i = fitab[font][c] & BMASK;
                   2083: 
                   2084:     if ( i != 0 )  {                   /* it's on this font */
                   2085:        p = codetab[font];
                   2086:        pw = widthtab[font];
                   2087:     } else if ( smnt > 0 )  {          /* on special (we hope) */
                   2088:        for ( k=smnt, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1) )  {
                   2089:            if ( k == 0 )  continue;
                   2090:            if ( (i = fitab[k][c] & BMASK) != 0 )  {
                   2091:                p = codetab[k];
                   2092:                pw = widthtab[k];
                   2093:                setfont(k);
                   2094:                break;
                   2095:            }   /* End if */
                   2096:        }   /* End for */
                   2097:     }  /* End else */
                   2098: 
                   2099:     if ( i == 0 || (code = p[i] & BMASK) == 0 || k > nfonts )  {
                   2100:        if ( debug == ON )
                   2101:            fprintf(tf, "not found 0%o\n", lastc);
                   2102:        if ( font != ofont ) setfont(ofont);
                   2103:        return;
                   2104:     }  /* End if */
                   2105: 
                   2106:     lastw = ((pw[i] & BMASK) * pstab[size-1] + dev.unitwidth/2) / dev.unitwidth;
                   2107: 
                   2108:     if ( debug == ON )  {
                   2109:        if ( isprint(lastc) )
                   2110:            fprintf(tf, "%c %d\n", lastc, code);
                   2111:        else fprintf(tf, "%03o %d\n", lastc, code);
                   2112:     } else oput(code);
                   2113: 
                   2114:     if ( font != ofont )
                   2115:        setfont(ofont);
                   2116: 
                   2117: }   /* End of put1 */
                   2118: 
                   2119: 
                   2120: /*****************************************************************************/
                   2121: 
                   2122: 
                   2123: setsize(n)
                   2124: 
                   2125: 
                   2126:        int     n;                      /* new internal size */
                   2127: 
                   2128: 
                   2129: {
                   2130: 
                   2131: 
                   2132: /*
                   2133:  *
                   2134:  * We want to use internal size n for now, where n is an index into *pstab
                   2135:  * where we can find the closest available approximation to the requested
                   2136:  * point size.
                   2137:  *
                   2138:  */
                   2139: 
                   2140: 
                   2141:        size = n;
                   2142: 
                   2143: }   /* End of setsize */
                   2144: 
                   2145: 
                   2146: /*****************************************************************************/
                   2147: 
                   2148: 
                   2149: t_fp(n, s, si)
                   2150: 
                   2151: 
                   2152:        int     n;                      /* font position to update */
                   2153:        char    *s;                     /* it now contains this font */
                   2154:        char    *si;                    /* and this is its internal number */
                   2155: 
                   2156: 
                   2157: {
                   2158: 
                   2159: 
                   2160: /*
                   2161:  *
                   2162:  * Called when we've loaded font *s in position n. The font position info
                   2163:  * is recorded in fontname[].
                   2164:  *
                   2165:  */
                   2166: 
                   2167: 
                   2168:        fontname[n].name = s;
                   2169:        fontname[n].number = atoi(si);
                   2170:        if ( n == lastfont ) lastfont = -1;     /* force getfontdata() call */
                   2171: 
                   2172: }   /* End of t_fp */
                   2173: 
                   2174: 
                   2175: /*****************************************************************************/
                   2176: 
                   2177: 
                   2178: setfont(n)
                   2179: 
                   2180: 
                   2181:        int     n;                      /* this will be the current font */
                   2182: 
                   2183: 
                   2184: {
                   2185: 
                   2186: 
                   2187: /*
                   2188:  *
                   2189:  * Job now wants to use the font loaded in position n. The variable font
                   2190:  * keeps track of which one we're currently using. If the requested positon
                   2191:  * is out of range we'll just quit.
                   2192:  *
                   2193:  */
                   2194: 
                   2195: 
                   2196:        if ( output == OFF )
                   2197:                return;
                   2198: 
                   2199:        if (n < 0 || n > NFONT)
                   2200:                error(FATAL, "illegal font %d", n);
                   2201: 
                   2202:        font = n;
                   2203: 
                   2204: }   /* End of setfont */
                   2205: 
                   2206: 
                   2207: /*****************************************************************************/
                   2208: 
                   2209: 
                   2210: oput(c)
                   2211: 
                   2212: 
                   2213:        int     c;                      /* want to print this character */
                   2214: 
                   2215: 
                   2216: {
                   2217: 
                   2218: 
                   2219:        int             x, y;           /* current scaled position */
                   2220:        int             member;         /* glyph number for c in current family */
                   2221: 
                   2222: 
                   2223: /*
                   2224:  *
                   2225:  * Arranges to print the character whose code is c in the current font.
                   2226:  * The old and new raster file formats are supported.
                   2227:  *
                   2228:  */
                   2229: 
                   2230: 
                   2231:        if ( output == OFF )
                   2232:                return;
                   2233: 
                   2234:        if ( rastformat == OLD_FORMAT )  {
                   2235:                xychar(c, fontname[font].name, pstab[size-1], lastw, tf);
                   2236:                return;
                   2237:        }    /* End if */
                   2238: 
                   2239:        if ( font != lastfont  ||  size != lastsize )  {
                   2240:                if ( isresident(fontname[font].name) == FALSE )
                   2241:                        getrastdata(fontname[font].name, mapsize(fontname[font].name, pstab[size-1]));
                   2242:                else getresdata(fontname[font].name, mapsize(fontname[font].name, pstab[size-1]), tf);
                   2243:                lastfont = font;
                   2244:                lastsize = size;
                   2245:        }   /* End if */
                   2246: 
                   2247:        member = download(c, lastw, angle, tf);
                   2248: 
                   2249:        x = hpos * xfac + xoffset + .5;
                   2250:        y = vpos * yfac + yoffset + .5;
                   2251: 
                   2252:        if ( y != lasty )  {
                   2253:                putc(ASETAV, tf);
                   2254:                putint(y, tf);
                   2255:                lasty = y;
                   2256:        }   /* End if */
                   2257: 
                   2258:        if ( ABS(x - lastx) > SLOP )  {
                   2259:                putc(ASETAH, tf);
                   2260:                putint(x, tf);
                   2261:                lastx = x + fam->advance[member];
                   2262:        } else lastx += fam->advance[member];
                   2263: 
                   2264:        putc(member, tf);
                   2265: 
                   2266: }   /* End of oput */
                   2267: 
                   2268: 
                   2269: /*****************************************************************************/
                   2270: 
                   2271: 
                   2272: mapsize(name, ps)
                   2273: 
                   2274: 
                   2275:        char            *name;          /* name of the font */
                   2276:        int             ps;             /* point size troff wants to use */
                   2277: 
                   2278: 
                   2279: {
                   2280: 
                   2281: 
                   2282:        int             i, j;
                   2283: 
                   2284: 
                   2285: /*
                   2286:  *
                   2287:  * Uses the data that's been filled in from RASTLIST to map point size
                   2288:  * ps font font *name into the best size available in our raster tables.
                   2289:  * If no RASTLIST file was used rastsize will be zero and we'll just
                   2290:  * assume that any size that's aske for is available.
                   2291:  *
                   2292:  */
                   2293: 
                   2294: 
                   2295:        if ( maxrast == 0 )             /* don't have any size data */
                   2296:                return(ps);
                   2297: 
                   2298:        for ( i = 0; i < maxrast; i++ )
                   2299:                if ( strcmp(name, sizedata[i].name) == 0 )
                   2300:                        break;
                   2301: 
                   2302:        if ( i >= maxrast )             /* didn't find the font */
                   2303:                error(FATAL, "missing raster list data for font %s", name);
                   2304: 
                   2305:        for ( j = 1, ps = (ps * pres) / rres; ps >= sizedata[i].sizes[j]; j++ ) ;
                   2306: 
                   2307:        return(sizedata[i].sizes[--j]);
                   2308: 
                   2309: }      /* End of mapsize */
                   2310: 
                   2311: 
                   2312: /*****************************************************************************/
                   2313: 
                   2314: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.