Annotation of researchv10no/cmd/dimpress/dimpress.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:        /* name should be no more than L_FNAME characters */
                    817:        while ( fscanf(fp, "%10s", sizedata[maxrast].name) != EOF )  {
                    818:                i = 0;
                    819:                while ( fscanf(fp, "%d", &n) != EOF  &&  n < 100 )
                    820:                        sizedata[maxrast].sizes[i++] = n;
                    821:                sizedata[maxrast].sizes[i] = 999;
                    822:                if ( ++maxrast >= MAXFONTS )
                    823:                        error(FATAL, "too many fonts in %s", name);
                    824:        }       /* End while */
                    825: 
                    826:        fclose(fp);
                    827: 
                    828: }   /* End of rastlist */
                    829: 
                    830: 
                    831: /*****************************************************************************/
                    832: 
                    833: 
                    834: arguments()
                    835: 
                    836: 
                    837: {
                    838: 
                    839: 
                    840:        FILE    *fp;                    /* next input file */
                    841: 
                    842: 
                    843: /*
                    844:  *
                    845:  * All the rest of the command line options are input files we want to
                    846:  * translate. If we get here and there are no more arguments, or if '-' is
                    847:  * in the list of file names, we'll process stdin.
                    848:  *
                    849:  */
                    850: 
                    851: 
                    852:        if (argc < 1)
                    853:                conv(stdin);
                    854:        else
                    855:                while (argc > 0) {
                    856:                        if (strcmp(*argv, "-") == 0)
                    857:                                fp = stdin;
                    858:                        else if ((fp = fopen(*argv, "r")) == NULL)
                    859:                                error(FATAL, "can't open %s", *argv);
                    860:                        conv(fp);
                    861:                        fclose(fp);
                    862:                        argc--;
                    863:                        argv++;
                    864:                }
                    865: 
                    866: }   /* End of arguments */
                    867: 
                    868: 
                    869: /*****************************************************************************/
                    870: 
                    871: 
                    872: print_file()
                    873: 
                    874: 
                    875: {
                    876: 
                    877: 
                    878:        char    buf[BUFSIZ];            /* IPR command line built up here */
                    879: 
                    880: 
                    881: /*
                    882:  *
                    883:  * Finished with all the input files and everything the printer needs to
                    884:  * know is in FILE *tf. We'll close the file because we're all done with
                    885:  * it, and then call IPR if we haven't been writing to stdout.
                    886:  *
                    887:  */
                    888: 
                    889: 
                    890:        fclose(tf);                     /* everything's in the file */
                    891: 
                    892:        if ( tf != stdout  ||  debug )  {
                    893:                sprintf(buf, "%s -Limpress -r -o '-Downer \"'\"%s\"'\"'\", jobheader on, pagecollation on, pagereversal on\" %s 0</dev/null 1>/dev/null 2>&1 &",
                    894:                IPR, username, tempfile);
                    895:                if ( debug )
                    896:                        fprintf(stderr, "executing %s\n", buf);
                    897:                else system(buf);
                    898:        }   /* End if */
                    899: 
                    900: }   /* End of print_file */
                    901: 
                    902: 
                    903: /*****************************************************************************/
                    904: 
                    905: 
                    906: acct_file()
                    907: 
                    908: 
                    909: {
                    910: 
                    911: 
                    912: /*
                    913:  *
                    914:  * If we want to do accounting *acctfile will be the name of the file where
                    915:  * we put the accounting data. If for some reason we can't open the file
                    916:  * we'll just quit. I've called the routine from main() before anything is
                    917:  * written to the output file.
                    918:  *
                    919:  */
                    920: 
                    921: 
                    922:        if ( acctfile != NULL  &&  *acctfile != '\0' )  {
                    923:                if ( (fp_acct = fopen(acctfile, "a")) == NULL )  {
                    924:                        fp_acct = stderr;
                    925:                        x_stat |= NO_ACCTFILE;
                    926:                        error(FATAL, "can't open accounting file");
                    927:                        exit(x_stat);
                    928:                }
                    929:                if ( tf != stdout )
                    930:                        x_stat |= DO_ACCT;
                    931:        }
                    932: 
                    933: }   /* End of acct_file */
                    934: 
                    935: 
                    936: /*****************************************************************************/
                    937: 
                    938: 
                    939: account()
                    940: 
                    941: 
                    942: {
                    943: 
                    944: 
                    945:        FILE    *f;                     /* just the job's page count */
                    946: 
                    947: 
                    948: /*
                    949:  *
                    950:  * Writes an accounting record, usually to *fp_acct, for the current job.
                    951:  * All this stuff is set up for our MHCC printers. In some cases we'll
                    952:  * know most everything about the job (called with -J option) and all
                    953:  * we'll do is write a page count to *jacctfile. In other cases we'll want
                    954:  * a more complete record and all the stuff will go to *fp_acct. You'll
                    955:  * undoubtedly want to change this stuff to suit your own needs.
                    956:  *
                    957:  */
                    958: 
                    959:        if ( x_stat & DO_ACCT )  {
                    960:                if ( jacctfile == NULL || *jacctfile == '\0' )  {
                    961:                        fprintf(fp_acct, " user = %-10s", username);
                    962:                        fprintf(fp_acct, " paper = %-10d", acctpages * copies);
                    963:                        x_stat &= ~DO_ACCT;
                    964:                        fprintf(fp_acct, " exit_status = 0%-6o", x_stat);
                    965:                        fprintf(fp_acct, " type = t ");
                    966:                        if ( tf == stdout )
                    967:                                fprintf(fp_acct, "  ??");
                    968:                        fprintf(fp_acct, "\n");
                    969:                } else {
                    970:                        if ( (f = fopen(jacctfile, "a")) != NULL )  {
                    971:                                fprintf(f, "%d\n", acctpages);
                    972:                                fclose(f);
                    973:                        }
                    974:                        x_stat &= ~DO_ACCT;
                    975:                }       /* End else */
                    976:        }
                    977: 
                    978: }   /* End of account */
                    979: 
                    980: 
                    981: /*****************************************************************************/
                    982: 
                    983: 
                    984: done()
                    985: 
                    986: 
                    987: {
                    988: 
                    989: 
                    990: /*
                    991:  *
                    992:  * Finished with everything so we want to make sure accounting is handled
                    993:  * properly and the right exit status is returned to the caller. We'll also
                    994:  * delete the temporary file if x_stat != 0.
                    995:  *
                    996:  */
                    997: 
                    998: 
                    999:        account();
                   1000: 
                   1001:        if ( tf != stdout  &&  x_stat != 0 )
                   1002:                unlink(tempfile);
                   1003: 
                   1004:        exit(x_stat);
                   1005: 
                   1006: }   /* End of done */
                   1007: 
                   1008: 
                   1009: /*****************************************************************************/
                   1010: 
                   1011: 
                   1012: conv(fp)
                   1013: 
                   1014: 
                   1015:        register FILE   *fp;
                   1016: 
                   1017: 
                   1018: {
                   1019: 
                   1020: 
                   1021:        register int    c, k;
                   1022:        int             m, n, i, n1, m1;
                   1023:        char            str[100];
                   1024: 
                   1025: 
                   1026: /*
                   1027:  *
                   1028:  * Controls the translation of troff's device independent output language
                   1029:  * to Impress. Some of the commands, like slant and height, are no-ops
                   1030:  * on Imagen's bitmap printers even though routines are called to do the
                   1031:  * processing.
                   1032:  *
                   1033:  */
                   1034: 
                   1035: 
                   1036:        lineno = 1;                     /* line in current file */
                   1037:        x_stat |= FILE_STARTED;         /* we'll clear it when done with *fp */
                   1038: 
                   1039:        while ((c = getc(fp)) != EOF) {
                   1040: 
                   1041:                switch (c) {
                   1042: 
                   1043:                case '\n':              /* just count this line */
                   1044:                        lineno++;
                   1045:                        break;
                   1046: 
                   1047:                case ' ':               /* when input is text */
                   1048:                case 0:                 /* occasional noise creeps in */
                   1049:                        break;
                   1050: 
                   1051:                case '0': case '1': case '2': case '3': case '4':
                   1052:                case '5': case '6': case '7': case '8': case '9':
                   1053:                        /* two motion digits plus a character */
                   1054:                        hmot((c-'0')*10 + getc(fp)-'0');
                   1055:                        put1(getc(fp));
                   1056:                        break;
                   1057: 
                   1058:                case 'c':               /* single ascii character */
                   1059:                        put1(getc(fp));
                   1060:                        break;
                   1061: 
                   1062:                case 'C':               /* special character */
                   1063:                        fscanf(fp, "%s", str);
                   1064:                        put1s(str);
                   1065:                        break;
                   1066: 
                   1067:                case 'N':               /* character at position n */
                   1068:                        fscanf(fp, "%d", &m);
                   1069:                        oput(m);
                   1070:                        break;
                   1071: 
                   1072:                case 'D':               /* drawing function */
                   1073:                        lineno++;
                   1074:                        switch ((c=getc(fp))) {
                   1075:                        case 'p':       /* draw a path */
                   1076:                                while (fscanf(fp, "%d %d", &n, &m) == 2)
                   1077:                                        drawline(n, m);
                   1078:                                break;
                   1079: 
                   1080:                        case 'l':       /* draw a line */
                   1081:                                fscanf(fp, "%d %d %c", &n, &m, &n1);
                   1082:                                drawline(n, m);
                   1083:                                break;
                   1084: 
                   1085:                        case 'c':       /* circle */
                   1086:                                fscanf(fp, "%d", &n);
                   1087:                                drawcirc(n);
                   1088:                                break;
                   1089: 
                   1090:                        case 'e':       /* ellipse */
                   1091:                                fscanf(fp, "%d %d", &m, &n);
                   1092:                                drawellip(m, n);
                   1093:                                break;
                   1094: 
                   1095:                        case 'a':       /* arc */
                   1096:                                fscanf(fp, "%d %d %d %d", &n, &m, &n1, &m1);
                   1097:                                drawarc(n, m, n1, m1);
                   1098:                                break;
                   1099: 
                   1100:                        case 'q':       /* spline */
                   1101:                                drawspline(fp, 1);
                   1102:                                break;
                   1103: 
                   1104:                        case '~':       /* wiggly line */
                   1105:                                drawspline(fp, 2);
                   1106:                                break;
                   1107: 
                   1108:                        default:
                   1109:                                error(FATAL, "unknown drawing function %c", c);
                   1110:                                break;
                   1111:                        }
                   1112:                        break;
                   1113: 
                   1114:                case 's':                       /* use this point size */
                   1115:                        fscanf(fp, "%d", &n);   /* ignore fractional sizes */
                   1116:                        setsize(t_size(n));
                   1117:                        break;
                   1118: 
                   1119:                case 'f':                       /* use font mounted here */
                   1120:                        fscanf(fp, "%s", str);
                   1121:                        setfont(t_font(str));
                   1122:                        break;
                   1123: 
                   1124:                case 'H':                       /* absolute horizontal motion */
                   1125: /*
                   1126:  *
                   1127:  * The simple scan I've commented out didn't handle negative numbers right
                   1128:  * and believe it or not we did get jobs that asked for negative absolute
                   1129:  * positions. Even though negative absolute coordinates probably are a
                   1130:  * mistake it makes more sense to handle the numbers properly.
                   1131:  *
                   1132:                        while ((c = getc(fp)) == ' ')
                   1133:                                ;
                   1134:                        k = 0;
                   1135:                        do {
                   1136:                                k = 10 * k + c - '0';
                   1137:                        } while (isdigit(c = getc(fp)));
                   1138:                        ungetc(c, fp);
                   1139:                        hgoto(k);
                   1140:  *
                   1141:  */
                   1142:                        fscanf(fp, "%d", &n);
                   1143:                        hgoto(n);
                   1144:                        break;
                   1145: 
                   1146:                case 'h':               /* relative horizontal motion */
                   1147: /*
                   1148:  *
                   1149:  * Again the same potential problem with negative numbers exists here. In
                   1150:  * fact it makes a lot more sense to expect negative relative motions even
                   1151:  * though I never did see them. Anyway just to be safe I've made the same
                   1152:  * change - take it out if you want.
                   1153:  *
                   1154:                        while ((c = getc(fp)) == ' ')
                   1155:                                ;
                   1156:                        k = 0;
                   1157:                        do {
                   1158:                                k = 10 * k + c - '0';
                   1159:                        } while (isdigit(c = getc(fp)));
                   1160:                        ungetc(c, fp);
                   1161:                        hmot(k);
                   1162:  *
                   1163:  */
                   1164:                        fscanf(fp, "%d", &n);
                   1165:                        hmot(n);
                   1166:                        break;
                   1167: 
                   1168:                case 'w':                       /* word space */
                   1169:                        break;
                   1170: 
                   1171:                case 'V':                       /* absolute vertical position */
                   1172:                        fscanf(fp, "%d", &n);
                   1173:                        vgoto(n);
                   1174:                        break;
                   1175: 
                   1176:                case 'v':                       /* relative vertical motion */
                   1177:                        fscanf(fp, "%d", &n);
                   1178:                        vmot(n);
                   1179:                        break;
                   1180: 
                   1181:                case 'p':                       /* new page */
                   1182:                        fscanf(fp, "%d", &n);
                   1183:                        t_page(n);
                   1184:                        break;
                   1185: 
                   1186:                case 'n':                       /* end of line */
                   1187:                        while ( (c = getc(fp)) != '\n'  &&  c != EOF ) ;
                   1188:                        t_newline();
                   1189:                        lineno++;
                   1190:                        break;
                   1191: 
                   1192:                case '#':                       /* comment */
                   1193:                        while ( (c = getc(fp)) != '\n'  &&  c != EOF ) ;
                   1194:                        lineno++;
                   1195:                        break;
                   1196: 
                   1197:                case 'x':                       /* device control function */
                   1198:                        devcntrl(fp);
                   1199:                        break;
                   1200: 
                   1201:                default:
                   1202:                        error(!FATAL, "unknown input character %o %c", c, c);
                   1203:                        done();
                   1204:                }
                   1205:        }
                   1206: 
                   1207:        x_stat &= ~FILE_STARTED;
                   1208: 
                   1209: }   /* End of conv */
                   1210: 
                   1211: 
                   1212: /*****************************************************************************/
                   1213: 
                   1214: 
                   1215: devcntrl(fp)
                   1216: 
                   1217: 
                   1218:        FILE    *fp;                    /* current input file */
                   1219: 
                   1220: 
                   1221: {
                   1222: 
                   1223: 
                   1224:        char    str[20], str1[50], buf[50];
                   1225:        int     c, n, x, y;
                   1226: 
                   1227: 
                   1228: /*
                   1229:  *
                   1230:  * Called from conv() to process the rest of a device control function.
                   1231:  * There's a whole family of them and they all begin with the string
                   1232:  * "x ". The rest of the command consists of the function name followed
                   1233:  * by zero or more arguments that depend on the particular command. We've
                   1234:  * already read the "x" from the input file, that's why the routine was
                   1235:  * called. The whole rest of the input line is assumed to be part of the
                   1236:  * device control command.
                   1237:  *
                   1238:  */
                   1239: 
                   1240: 
                   1241:        fscanf(fp, "%s", str);          /* get the control function name */
                   1242: 
                   1243:        switch ( str[0] )  {            /* only the first character counts now */
                   1244:        case 'i':                       /* initialize */
                   1245:                fileinit();
                   1246:                t_init(0);
                   1247:                break;
                   1248: 
                   1249:        case 'T':                       /* device name */
                   1250:                fscanf(fp, "%s", devname);
                   1251:                break;
                   1252: 
                   1253:        case 't':                       /* trailer */
                   1254:                t_trailer();
                   1255:                break;
                   1256: 
                   1257:        case 'p':                       /* pause -- can restart */
                   1258:                t_reset('p');
                   1259:                break;
                   1260: 
                   1261:        case 's':                       /* stop */
                   1262:                t_reset('s');
                   1263:                break;
                   1264: 
                   1265:        case 'r':                       /* resolution assumed when prepared */
                   1266:                fscanf(fp, "%d", &res);
                   1267:                break;
                   1268: 
                   1269:        case 'f':                       /* load font in a position */
                   1270:                fscanf(fp, "%d %s", &n, str);
                   1271:                fgets(buf, sizeof buf, fp);     /* in case there's a filename */
                   1272:                ungetc('\n', fp);       /* fgets goes too far */
                   1273:                str1[0] = 0;    /* in case there's nothing to come in */
                   1274:                sscanf(buf, "%s", str1);
                   1275:                loadfont(n, str, str1);
                   1276:                break;
                   1277: 
                   1278:        /* these don't belong here... */
                   1279:        case 'H':                       /* char height */
                   1280:                fscanf(fp, "%d", &n);
                   1281:                t_charht(n);
                   1282:                break;
                   1283: 
                   1284:        case 'S':                       /* slant */
                   1285:                fscanf(fp, "%d", &n);
                   1286:                t_slant(n);
                   1287:                break;
                   1288: 
                   1289:        case 'I':
                   1290:        case 'B':
                   1291:                x = hpos * xfac + xoffset + .5;
                   1292:                y = vpos * yfac + yoffset + .5;
                   1293: 
                   1294:                /* force 32x32 alignment, imagen 3.2 software does this
                   1295:                ** anyway, but this should fix others
                   1296:                */
                   1297:                putc(ASETAV, tf); putint(y&~0x1f, tf);
                   1298:                putc(ASETAH, tf); putint(x&~0x1f, tf);
                   1299: 
                   1300:                if (str[0] == 'I') {
                   1301:                        fscanf(fp, "%d %s", &n, buf);
                   1302:                        iglyphpage(tf, buf, n, x&0x1f, y&0x1f);
                   1303:                } else if (str[0] == 'B') {
                   1304:                        fscanf(fp, "%d %s", &n, buf);
                   1305:                        glyphpage(tf, buf, n, x&0x1f, y&0x1f);
                   1306:                }
                   1307: 
                   1308:                /* position back where it belongs */
                   1309:                putc(ASETAV, tf); putint(y, tf); lasty = y;
                   1310:                putc(ASETAH, tf); putint(x, tf); lastx = x;
                   1311:                break;
                   1312: 
                   1313:        case 'X':
                   1314:                fscanf(fp, "%s", str);  /* line style */
                   1315:                break;
                   1316:        }
                   1317: 
                   1318:        while ( (c = getc(fp)) != '\n'  &&  c != EOF ) ;
                   1319: 
                   1320:        lineno++;
                   1321: 
                   1322: }   /* End of devcntrl */
                   1323: 
                   1324: 
                   1325: /*****************************************************************************/
                   1326: 
                   1327: 
                   1328: fileinit()
                   1329: 
                   1330: 
                   1331: {
                   1332: 
                   1333: 
                   1334:     int                i, fin;
                   1335:     char       *filebase;
                   1336:     char       temp[100];
                   1337: 
                   1338: 
                   1339: /*
                   1340:  *
                   1341:  * Called from t_init(), which in turn is called from devcntrl(), whenever we get
                   1342:  * an "x init" command. There are a few lines of code here that set things up for
                   1343:  * emulating another device.
                   1344:  *
                   1345:  */
                   1346: 
                   1347: 
                   1348:     sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname);
                   1349:     if ( (fin = open(temp, 0)) < 0 )
                   1350:        error(FATAL, "can't open tables for %s", temp);
                   1351: 
                   1352:     read(fin, &dev, sizeof(struct dev));
                   1353: 
                   1354:     nfonts = dev.nfonts;
                   1355: 
                   1356:     if ( strcmp(devname, realdev) != 0 )  {    /* device emulation */
                   1357:        close(fin);
                   1358:        strcpy(devname, realdev);
                   1359:        sprintf(temp, "%s/dev%s/DESC.out", fontdir, devname);
                   1360:        if ( (fin = open(temp, 0)) < 0 )
                   1361:            error(FATAL, "can't open tables for %s", temp);
                   1362:        read(fin, &dev, sizeof(struct dev));
                   1363:     }  /* End if */
                   1364: 
                   1365:     nsizes = dev.nsizes;
                   1366:     nchtab = dev.nchtab;
                   1367: 
                   1368:     if ( (filebase = malloc(dev.filesize)) == NULL )
                   1369:        error(FATAL, "no memory for description file");
                   1370: 
                   1371:     read(fin, filebase, dev.filesize); /* all at once */
                   1372: 
                   1373:     pstab = (short *) filebase;
                   1374:     chtab = pstab + nsizes + 1;
                   1375:     chname = (char *) (chtab + dev.nchtab);
                   1376: 
                   1377:     for ( i = 1; i <= nfonts; i++ )  {
                   1378:        fontbase[i] = NULL;
                   1379:        widthtab[i] = codetab[i] = fitab[i] = NULL;
                   1380:     }  /* End for */
                   1381: 
                   1382:     close(fin);
                   1383: 
                   1384: }   /* End of fileinit */
                   1385: 
                   1386: 
                   1387: /*****************************************************************************/
                   1388: 
                   1389: 
                   1390: fontprint(i)
                   1391: 
                   1392: 
                   1393:     int                i;                      /* font's index in fontbase[] */
                   1394: 
                   1395: 
                   1396: {
                   1397: 
                   1398: 
                   1399:     int                j, n;
                   1400:     char       *p;
                   1401: 
                   1402: 
                   1403: /*
                   1404:  *
                   1405:  * Just a debugging routine that dumps most of the important information about
                   1406:  * the font that's mounted in position i.
                   1407:  *
                   1408:  */
                   1409: 
                   1410: 
                   1411:     fprintf(tf, "font %d:\n", i);
                   1412: 
                   1413:     p = (char *) fontbase[i];
                   1414:     n = fontbase[i]->nwfont & BMASK;
                   1415: 
                   1416:     /* name should be no more than L_FNAME characters long */
                   1417:     fprintf(tf, "base=0%o, nchars=%d, spec=%d, name=%.10s, widtab=0%o, fitab=0%o\n",
                   1418:            p, n, fontbase[i]->specfont, fontbase[i]->namefont, widthtab[i], fitab[i]);
                   1419: 
                   1420:     fprintf(tf, "widths:\n");
                   1421:     for ( j = 0; j <= n; j++ )  {
                   1422:        fprintf(tf, " %2d", widthtab[i][j] & BMASK);
                   1423:        if ( j % 20 == 19 ) putc('\n', tf);
                   1424:     }  /* End for */
                   1425: 
                   1426:     fprintf(tf, "\ncodetab:\n");
                   1427:     for ( j = 0; j <= n; j++ )  {
                   1428:        fprintf(tf, " %2d", codetab[i][j] & BMASK);
                   1429:        if ( j % 20 == 19 ) putc('\n', tf);
                   1430:     }  /* End for */
                   1431: 
                   1432:     fprintf(tf, "\nfitab:\n");
                   1433:     for ( j = 0; j <= dev.nchtab + 128-32; j++ )  {
                   1434:        fprintf(tf, " %2d", fitab[i][j] & BMASK);
                   1435:        if ( j % 20 == 19 ) putc('\n', tf);
                   1436:     }  /* End for */
                   1437: 
                   1438:     putc('\n', tf);
                   1439: 
                   1440: }   /* End of fontprint */
                   1441: 
                   1442: 
                   1443: /*****************************************************************************/
                   1444: 
                   1445: 
                   1446: loadfont(n, s, s1)
                   1447: 
                   1448: 
                   1449:     int                n;
                   1450:     char       *s, *s1;
                   1451: 
                   1452: 
                   1453: {
                   1454: 
                   1455: 
                   1456:     char       temp[80];
                   1457:     int                fin, nw;
                   1458: 
                   1459: 
                   1460: /*
                   1461:  *
                   1462:  * Called to to load font info for font *s on position n using the binary tables
                   1463:  * located in directory *s1 (if it's not NULL or the empty string).
                   1464:  *
                   1465:  */
                   1466: 
                   1467: 
                   1468:     if ( n < 0  ||  n > NFONT )                /* make sure it's a legal position */
                   1469:        error(FATAL, "illegal fp command %d %s", n, s);
                   1470: 
                   1471: /*
                   1472:  *
                   1473:  * If the font's already loaded on position n there's nothing to do.
                   1474:  *
                   1475:  */
                   1476: 
                   1477:     if ( fontbase[n] != NULL && strncmp(s, fontbase[n]->namefont, L_FNAME) == 0 )
                   1478:        return;
                   1479: 
                   1480: /*
                   1481:  *
                   1482:  * If *s1 isn't NULL or the NULL string that's what we'll use for the font
                   1483:  * directory, otherwise use *fontdir.
                   1484:  *
                   1485:  */
                   1486: 
                   1487:     if ( s1 == NULL || s1[0] == '\0' )
                   1488:        sprintf(temp, "%s/dev%s/%.10s.out", fontdir, devname, s);
                   1489:     else sprintf(temp, "%s/%.10s.out", s1, s);
                   1490: 
                   1491:     if ( (fin = open(temp, 0)) < 0 )  {
                   1492:        sprintf(temp, "%s/dev%s/%.10s.out", fontdir, devname, mapfont(s));
                   1493:        if ( (fin = open(temp, 0)) < 0 )
                   1494:            error(FATAL, "can't open font table %s", temp);
                   1495:     }  /* End if */
                   1496: 
                   1497:     if ( fontbase[n] != NULL )         /* something's already there */
                   1498:        free(fontbase[n]);              /* so release the memory first */
                   1499: 
                   1500:     fontbase[n] = (struct Font *) malloc(3*255 + dev.nchtab + (128-32) + sizeof(struct Font));
                   1501:     if ( fontbase[n] == NULL )
                   1502:        error(FATAL, "Out of space in loadfont %s", s);
                   1503: 
                   1504:     read(fin, fontbase[n], 3*255 + nchtab+128-32 + sizeof(struct Font));
                   1505:     close(fin);
                   1506: 
                   1507:     if ( smnt == 0 && fontbase[n]->specfont == 1 )
                   1508:        smnt = n;
                   1509: 
                   1510:     nw = fontbase[n]->nwfont & BMASK;
                   1511:     widthtab[n] = (char *) fontbase[n] + sizeof(struct Font);
                   1512:     codetab[n] = (char *) widthtab[n] + 2 * nw;
                   1513:     fitab[n] = (char *) widthtab[n] + 3 * nw;
                   1514: 
                   1515:     t_fp(n, fontbase[n]->namefont, fontbase[n]->intname);
                   1516: 
                   1517:     if ( debug == ON )
                   1518:        fontprint(n);
                   1519: 
                   1520: }   /* End of loadfont */
                   1521: 
                   1522: 
                   1523: /*****************************************************************************/
                   1524: 
                   1525: 
                   1526: char *mapfont(name)
                   1527: 
                   1528: 
                   1529:     char       *name;                  /* name of the font troff wants */
                   1530: 
                   1531: 
                   1532: {
                   1533: 
                   1534: 
                   1535:     int                i;                      /* loop index for fontmap[] */
                   1536: 
                   1537: 
                   1538: /*
                   1539:  *
                   1540:  * Only called from loadfont() when we haven't been able to open the font file
                   1541:  * that troff asked for. We take the font name and map it into an appropriate
                   1542:  * substitute. If the initial lookup fails we do a simple mapping that should
                   1543:  * be good enough most of the time.
                   1544:  *
                   1545:  * This stuff should only be needed when we're emulating another printer like
                   1546:  * the APS-5.
                   1547:  *
                   1548:  */
                   1549: 
                   1550: 
                   1551:     for ( i = 0; fontmap[i].name != NULL && i < L_FNAME; i++ )
                   1552:        if ( strncmp(name, fontmap[i].name, L_FNAME) == 0 )
                   1553:            return(fontmap[i].use);
                   1554: 
                   1555:     switch ( *++name )  {
                   1556:        case 'I':
                   1557:        case 'B':
                   1558:                return(name);
                   1559: 
                   1560:        case 'X':
                   1561:                return("BI");
                   1562: 
                   1563:        default:
                   1564:                return("R");
                   1565:     }  /* End switch */
                   1566: 
                   1567: }   /* End of mapfont */
                   1568: 
                   1569: 
                   1570: /*****************************************************************************/
                   1571: 
                   1572: 
                   1573: convint(c)
                   1574: 
                   1575: 
                   1576:        unsigned char   c;
                   1577: 
                   1578: 
                   1579: {
                   1580: 
                   1581: 
                   1582: /*
                   1583:  *
                   1584:  * Converts a character to a proper 2's complement integer. Really just used
                   1585:  * on 3b's when we're reading raster tables in the old format. There's
                   1586:  * really no need to make this a separate routine - at least I don't
                   1587:  * think there is. Should just redefine CONVINT() macro so it does this
                   1588:  * stuff.
                   1589:  *
                   1590:  */
                   1591: 
                   1592: 
                   1593:        return((c & 0200) ? ((256 - c) * -1) : c);
                   1594: 
                   1595: }   /* End of convint */
                   1596: 
                   1597: 
                   1598: /*****************************************************************************/
                   1599: 
                   1600: 
                   1601: t_init(reinit)
                   1602: 
                   1603: 
                   1604:        int     reinit;
                   1605: 
                   1606: 
                   1607: {
                   1608: 
                   1609: 
                   1610:        int     i;
                   1611:        FILE    *tmpfile();
                   1612: 
                   1613: 
                   1614: /*
                   1615:  *
                   1616:  * Called to initialize the printer and associated variables. reinit will
                   1617:  * be zero when the "x init" command was found in the output file, while
                   1618:  * it will be non-zero when the routine is called to set things up for a
                   1619:  * new page.
                   1620:  *
                   1621:  */
                   1622: 
                   1623: 
                   1624:        if (! reinit) {
                   1625:                for (i = 0; i < nchtab; i++)
                   1626:                        if (strcmp(&chname[chtab[i]], "l.") == 0)
                   1627:                                break;
                   1628:                if (i < nchtab) {
                   1629:                        drawdot = i + 128;
                   1630:                        drawsize = 1;
                   1631:                } else {
                   1632:                        drawdot = '.';
                   1633:                        drawsize = 2;   /* half size */
                   1634:                }
                   1635: 
                   1636:                xfac = (float) pres / res * aspect;
                   1637:                yfac = (float) pres / res;
                   1638: 
                   1639:                putc(ASETPEN, tf);
                   1640:                putc(penwidth, tf);
                   1641: 
                   1642:                if ( mode == LANDSCAPE )  {
                   1643:                    putc(ASETHV, tf);
                   1644:                    putc(0107, tf);
                   1645:                    angle = ROT_270;
                   1646:                }   /* End if */
                   1647:        }
                   1648: 
                   1649:        hpos = vpos = 0;
                   1650:        setsize(t_size(10));    /* start somewhere */
                   1651: 
                   1652: }   /* End of t_init */
                   1653: 
                   1654: 
                   1655: /*****************************************************************************/
                   1656: 
                   1657: 
                   1658: t_page(pg)
                   1659: 
                   1660: 
                   1661: {
                   1662: 
                   1663: 
                   1664:        register int            i, j, n;
                   1665:        register unsigned       char *p;
                   1666: 
                   1667: 
                   1668: /*
                   1669:  *
                   1670:  * Get the printer and everything else ready for a new page. If the -o
                   1671:  * option has been used only selected pages will be printed. If output
                   1672:  * is ON when this routine is called we'll write the endpage Impress
                   1673:  * command to the output file. If we're supposed to be doing output for
                   1674:  * page pg we'll write the APAGE command out, and that will cause the
                   1675:  * horizontal and vertical positions (in Impress) to be set to zero. hpos
                   1676:  * and vpos are initialized in routine t_init(), although I really don't
                   1677:  * see any reason why we couldn't just skip the call and do it here.
                   1678:  *
                   1679:  */
                   1680: 
                   1681: 
                   1682:        if ( debug == ON )
                   1683:                fprintf(stderr, "t_page %d, output=%d\n", pg, output);
                   1684: 
                   1685:        pageno = pg;
                   1686: 
                   1687:        if ( output == ON )             /* doing output for last page */
                   1688:                putc(AENDP, tf);
                   1689: 
                   1690:        if ( (output = in_olist(pg)) == ON )  {         /* print this page */
                   1691:                putc(APAGE, tf);
                   1692:                acctpages++;
                   1693:        }
                   1694: 
                   1695:        lastx = lasty = -1;
                   1696:        t_init(1);                      /* setup for this page */
                   1697: 
                   1698: }   /* End of t_page */
                   1699: 
                   1700: 
                   1701: /*****************************************************************************/
                   1702: 
                   1703: 
                   1704: t_newline()
                   1705: 
                   1706: 
                   1707: {
                   1708: 
                   1709: 
                   1710: /*
                   1711:  *
                   1712:  * Read an "n a b" command in the input file and are ready to start a new
                   1713:  * line. There really isn't much else this routine can do besides set the
                   1714:  * horizontal position to zero. Anyway troff takes care of any needed
                   1715:  * positioning before it starts printing text.
                   1716:  *
                   1717:  */
                   1718: 
                   1719: 
                   1720:        hpos = 0;
                   1721: 
                   1722: }   /* End of t_newline */
                   1723: 
                   1724: 
                   1725: /*****************************************************************************/
                   1726: 
                   1727: 
                   1728: t_size(n)
                   1729: 
                   1730: 
                   1731:        int     n;                      /* convert this point size */
                   1732: 
                   1733: 
                   1734: {
                   1735: 
                   1736: 
                   1737:        int     i;
                   1738: 
                   1739: 
                   1740: /*
                   1741:  *
                   1742:  * Converts a point size into an internal size that can be used as an
                   1743:  * index into the pstab[] array. Actually the internal size is defined as
                   1744:  * one plus the index of the least upper bound of n in pstab[] or nsizes
                   1745:  * if n is larger than all the listed sizes.
                   1746:  *
                   1747:  */
                   1748: 
                   1749:        if (n <= pstab[0])
                   1750:                return(1);
                   1751:        else if (n >= pstab[nsizes-1])
                   1752:                return(nsizes);
                   1753:        for (i = 0; n > pstab[i]; i++) ;
                   1754: 
                   1755:        return(i+1);
                   1756: 
                   1757: }   /* End of t_size */
                   1758: 
                   1759: 
                   1760: /*****************************************************************************/
                   1761: 
                   1762: 
                   1763: t_charht(n)
                   1764: 
                   1765: 
                   1766:        int     n;                      /* use this as the character height */
                   1767: 
                   1768: 
                   1769: {
                   1770: 
                   1771: 
                   1772: /*
                   1773:  *
                   1774:  * Although it can be done on some typesetters, like the APS-5, it's ignored
                   1775:  * on Imagen's bitmap printers like the Imprint-10 and the 8/300. It would
                   1776:  * be absurd to keep any extra raster files around just so we could implement
                   1777:  * this command, and right now there's no Impress command to do it to
                   1778:  * downloaded glyphs.
                   1779:  *
                   1780:  */
                   1781: 
                   1782: 
                   1783: }   /* End of t_charht */
                   1784: 
                   1785: 
                   1786: /*****************************************************************************/
                   1787: 
                   1788: 
                   1789: t_slant(n)
                   1790: 
                   1791: 
                   1792:        int     n;                      /* slant characters this many degrees */
                   1793: 
                   1794: 
                   1795: {
                   1796: 
                   1797: 
                   1798: /*
                   1799:  *
                   1800:  * As with troff's height command, there's no simple way to slant characters
                   1801:  * on Imagen's bitmap printers and it's really not worth any effort to try
                   1802:  * and make it work.
                   1803:  *
                   1804:  */
                   1805: 
                   1806: 
                   1807: }   /* End of t_slant */
                   1808: 
                   1809: 
                   1810: /*****************************************************************************/
                   1811: 
                   1812: 
                   1813: t_font(s)
                   1814: 
                   1815: 
                   1816:        char    *s;
                   1817: 
                   1818: 
                   1819: {
                   1820: 
                   1821: 
                   1822:        int     n;
                   1823: 
                   1824: 
                   1825: /*
                   1826:  *
                   1827:  * Just converts the string *s into an integer and checks to make sure the
                   1828:  * number is a legal font position. If it's not we'll print an error message
                   1829:  * and then quit. di10 handled bad requests a little differently. Instead
                   1830:  * of treating mistakes as FATAL errors it would return 1 as the font
                   1831:  * number.
                   1832:  *
                   1833:  */
                   1834: 
                   1835: 
                   1836:        if ( (n = atoi(s)) < 0  ||  n > nfonts )
                   1837:                error(FATAL, "illegal font position %d", n);
                   1838: 
                   1839:        return(n);
                   1840: 
                   1841: }   /* End of t_font */
                   1842: 
                   1843: 
                   1844: /*****************************************************************************/
                   1845: 
                   1846: 
                   1847: t_reset(c)
                   1848: 
                   1849: 
                   1850:        int     c;                      /* pause or restart */
                   1851: 
                   1852: 
                   1853: {
                   1854: 
                   1855: 
                   1856: /*
                   1857:  *
                   1858:  * Called from devcntrl() when we've found an "x stop" or "x pause" command.
                   1859:  * There's really nothing we need to do for Imagen's bitmap printers, and
                   1860:  * leaving the final cleanup (ie. AEOF code etc.) to someone else means
                   1861:  * we should be able to cat a bunch of troff output files together and
                   1862:  * have them all printed properly.
                   1863:  *
                   1864:  */
                   1865: 
                   1866: 
                   1867: }   /* End of t_reset */
                   1868: 
                   1869: 
                   1870: /*****************************************************************************/
                   1871: 
                   1872: 
                   1873: t_wrapup()
                   1874: 
                   1875: 
                   1876: {
                   1877: 
                   1878: 
                   1879: /*
                   1880:  *
                   1881:  * We're finished with all the input files and all that's left to do is
                   1882:  * end the last page we were working on and then mark the end of the Impress
                   1883:  * file.
                   1884:  *
                   1885:  */
                   1886: 
                   1887: 
                   1888:        putc(AENDP, tf);
                   1889:        putc(AEOF, tf);
                   1890: 
                   1891: }   /* End of t_wrapup */
                   1892: 
                   1893: 
                   1894: /*****************************************************************************/
                   1895: 
                   1896: 
                   1897: t_trailer()
                   1898: 
                   1899: 
                   1900: {
                   1901: 
                   1902: 
                   1903: /*
                   1904:  *
                   1905:  * Called from devcntrl() when an "x trailer" command is found. There's
                   1906:  * nothing we need to do here for Imagen's printers.
                   1907:  *
                   1908:  */
                   1909: 
                   1910: 
                   1911: 
                   1912: }   /* End of t_trailer */
                   1913: 
                   1914: 
                   1915: /*****************************************************************************/
                   1916: 
                   1917: 
                   1918: hgoto(n)
                   1919: 
                   1920: 
                   1921:        int     n;                      /* where we want to be */
                   1922: 
                   1923: 
                   1924: {
                   1925: 
                   1926: 
                   1927: /*
                   1928:  *
                   1929:  * Want to be at this absolute horizontal position next - usually will
                   1930:  * get these motion commands right before printing a character.
                   1931:  *
                   1932:  */
                   1933: 
                   1934: 
                   1935:        hpos = n;
                   1936: 
                   1937: }   /* End of hgoto */
                   1938: 
                   1939: 
                   1940: /*****************************************************************************/
                   1941: 
                   1942: 
                   1943: hmot(n)
                   1944: 
                   1945: 
                   1946:        int     n;                      /* move this far from where we are */
                   1947: 
                   1948: 
                   1949: {
                   1950: 
                   1951: 
                   1952: /*
                   1953:  *
                   1954:  * Handles relative horizontal motion. troff's current positon as recorded
                   1955:  * in hpos is changed by n units.
                   1956:  *
                   1957:  */
                   1958: 
                   1959: 
                   1960:        hpos += n;
                   1961: 
                   1962: }   /* End of hmot */
                   1963: 
                   1964: 
                   1965: /*****************************************************************************/
                   1966: 
                   1967: 
                   1968: vgoto(n)
                   1969: 
                   1970: 
                   1971:        int     n;                      /* new vertical position */
                   1972: 
                   1973: 
                   1974: {
                   1975: 
                   1976: 
                   1977: /*
                   1978:  *
                   1979:  * Moves vertically in troff's coordinate system to absolute position n.
                   1980:  *
                   1981:  */
                   1982: 
                   1983: 
                   1984:        vpos = n;
                   1985: 
                   1986: }   /* End of vgoto */
                   1987: 
                   1988: 
                   1989: /*****************************************************************************/
                   1990: 
                   1991: 
                   1992: vmot(n)
                   1993: 
                   1994: 
                   1995:        int     n;                      /* move this far vertically */
                   1996: 
                   1997: 
                   1998: {
                   1999: 
                   2000: 
                   2001: /*
                   2002:  *
                   2003:  * Handles relative vertical motion of n units in troff's coordinate system.
                   2004:  *
                   2005:  */
                   2006: 
                   2007: 
                   2008:        vpos += n;
                   2009: 
                   2010: }   /* End of vmot */
                   2011: 
                   2012: 
                   2013: /*****************************************************************************/
                   2014: 
                   2015: 
                   2016: put1s(s)
                   2017: 
                   2018: 
                   2019:        register char   *s;
                   2020: 
                   2021: 
                   2022: {
                   2023: 
                   2024: 
                   2025:        static int      i = 0;          /* last one we found - usually */
                   2026: 
                   2027: 
                   2028: /*
                   2029:  *
                   2030:  * Does whatever is necessary to have special character *s printed. If we're
                   2031:  * doing output on this page we'll look the character up using chname[] and
                   2032:  * chtab[]. The first array contains all the special character names
                   2033:  * separated by '\0' that are mentioned in the typesetter's DESC file, while
                   2034:  * chname[i] points to the start of character i in chname[]. Both arrays
                   2035:  * come from the DESC.out file for printer *devname which is found in
                   2036:  * *fontdir (wherever that might be).
                   2037:  *
                   2038:  */
                   2039: 
                   2040: 
                   2041:        if ( output == OFF )
                   2042:                return;
                   2043: 
                   2044:        if ( debug )
                   2045:                printf("%s", s);
                   2046: 
                   2047:        if (strcmp(s, &chname[chtab[i]]) != 0)
                   2048:                for (i = 0; i < nchtab; i++)
                   2049:                        if (strcmp(&chname[chtab[i]], s) == 0)
                   2050:                                break;
                   2051:        if (i < nchtab)
                   2052:                put1(i + 128);
                   2053:        else
                   2054:                i = 0;
                   2055: 
                   2056: }   /* End of put1s */
                   2057: 
                   2058: 
                   2059: /*****************************************************************************/
                   2060: 
                   2061: 
                   2062: put1(c)
                   2063: 
                   2064: 
                   2065:     register int       c;              /* print this character */
                   2066: 
                   2067: 
                   2068: {
                   2069: 
                   2070: 
                   2071:     char               *pw;
                   2072:     register char      *p;
                   2073:     register int       i, j, k;
                   2074:     int                        ofont, code;
                   2075: 
                   2076: 
                   2077: /*
                   2078:  *
                   2079:  * Arranges to have character c printed. If c < 128 it's a simple ASCII character,
                   2080:  * otherwise it's a special character. We subtract 32 from c because non-graphic
                   2081:  * ASCII characters aren't included in the tables.
                   2082:  *
                   2083:  */
                   2084: 
                   2085: 
                   2086:     lastc = c;                         /* charlib() may need the real name */
                   2087:     c -= 32;
                   2088: 
                   2089:     if ( c <= 0 )  {
                   2090:        if ( debug == ON )
                   2091:            fprintf(tf, "non-exist 0%o\n", lastc);
                   2092:        return;
                   2093:     }  /* End if */
                   2094: 
                   2095:     k = ofont = font;
                   2096:     i = fitab[font][c] & BMASK;
                   2097: 
                   2098:     if ( i != 0 )  {                   /* it's on this font */
                   2099:        p = codetab[font];
                   2100:        pw = widthtab[font];
                   2101:     } else if ( smnt > 0 )  {          /* on special (we hope) */
                   2102:        for ( k=smnt, j=0; j <= nfonts; j++, k = (k+1) % (nfonts+1) )  {
                   2103:            if ( k == 0 )  continue;
                   2104:            if ( (i = fitab[k][c] & BMASK) != 0 )  {
                   2105:                p = codetab[k];
                   2106:                pw = widthtab[k];
                   2107:                setfont(k);
                   2108:                break;
                   2109:            }   /* End if */
                   2110:        }   /* End for */
                   2111:     }  /* End else */
                   2112: 
                   2113:     if ( i == 0 || (code = p[i] & BMASK) == 0 || k > nfonts )  {
                   2114:        if ( debug == ON )
                   2115:            fprintf(tf, "not found 0%o\n", lastc);
                   2116:        if ( font != ofont ) setfont(ofont);
                   2117:        return;
                   2118:     }  /* End if */
                   2119: 
                   2120:     lastw = ((pw[i] & BMASK) * pstab[size-1] + dev.unitwidth/2) / dev.unitwidth;
                   2121: 
                   2122:     if ( debug == ON )  {
                   2123:        if ( isprint(lastc) )
                   2124:            fprintf(tf, "%c %d\n", lastc, code);
                   2125:        else fprintf(tf, "%03o %d\n", lastc, code);
                   2126:     } else oput(code);
                   2127: 
                   2128:     if ( font != ofont )
                   2129:        setfont(ofont);
                   2130: 
                   2131: }   /* End of put1 */
                   2132: 
                   2133: 
                   2134: /*****************************************************************************/
                   2135: 
                   2136: 
                   2137: setsize(n)
                   2138: 
                   2139: 
                   2140:        int     n;                      /* new internal size */
                   2141: 
                   2142: 
                   2143: {
                   2144: 
                   2145: 
                   2146: /*
                   2147:  *
                   2148:  * We want to use internal size n for now, where n is an index into *pstab
                   2149:  * where we can find the closest available approximation to the requested
                   2150:  * point size.
                   2151:  *
                   2152:  */
                   2153: 
                   2154: 
                   2155:        size = n;
                   2156: 
                   2157: }   /* End of setsize */
                   2158: 
                   2159: 
                   2160: /*****************************************************************************/
                   2161: 
                   2162: 
                   2163: t_fp(n, s, si)
                   2164: 
                   2165: 
                   2166:        int     n;                      /* font position to update */
                   2167:        char    *s;                     /* it now contains this font */
                   2168:        char    *si;                    /* and this is its internal number */
                   2169: 
                   2170: 
                   2171: {
                   2172: 
                   2173: 
                   2174: /*
                   2175:  *
                   2176:  * Called when we've loaded font *s in position n. The font position info
                   2177:  * is recorded in fontname[].
                   2178:  *
                   2179:  */
                   2180: 
                   2181: 
                   2182:        fontname[n].name = s;
                   2183:        fontname[n].number = atoi(si);
                   2184:        if ( n == lastfont ) lastfont = -1;     /* force getfontdata() call */
                   2185: 
                   2186: }   /* End of t_fp */
                   2187: 
                   2188: 
                   2189: /*****************************************************************************/
                   2190: 
                   2191: 
                   2192: setfont(n)
                   2193: 
                   2194: 
                   2195:        int     n;                      /* this will be the current font */
                   2196: 
                   2197: 
                   2198: {
                   2199: 
                   2200: 
                   2201: /*
                   2202:  *
                   2203:  * Job now wants to use the font loaded in position n. The variable font
                   2204:  * keeps track of which one we're currently using. If the requested positon
                   2205:  * is out of range we'll just quit.
                   2206:  *
                   2207:  */
                   2208: 
                   2209: 
                   2210:        if ( output == OFF )
                   2211:                return;
                   2212: 
                   2213:        if (n < 0 || n > NFONT)
                   2214:                error(FATAL, "illegal font %d", n);
                   2215: 
                   2216:        font = n;
                   2217: 
                   2218: }   /* End of setfont */
                   2219: 
                   2220: 
                   2221: /*****************************************************************************/
                   2222: 
                   2223: 
                   2224: oput(c)
                   2225: 
                   2226: 
                   2227:        int     c;                      /* want to print this character */
                   2228: 
                   2229: 
                   2230: {
                   2231: 
                   2232: 
                   2233:        int             x, y;           /* current scaled position */
                   2234:        int             member;         /* glyph number for c in current family */
                   2235: 
                   2236: 
                   2237: /*
                   2238:  *
                   2239:  * Arranges to print the character whose code is c in the current font.
                   2240:  * The old and new raster file formats are supported.
                   2241:  *
                   2242:  */
                   2243: 
                   2244: 
                   2245:        if ( output == OFF )
                   2246:                return;
                   2247: 
                   2248:        if ( rastformat == OLD_FORMAT )  {
                   2249:                xychar(c, fontname[font].name, pstab[size-1], lastw, tf);
                   2250:                return;
                   2251:        }    /* End if */
                   2252: 
                   2253:        if ( font != lastfont  ||  size != lastsize )  {
                   2254:                if ( isresident(fontname[font].name) == FALSE )
                   2255:                        getrastdata(fontname[font].name, mapsize(fontname[font].name, pstab[size-1]));
                   2256:                else getresdata(fontname[font].name, mapsize(fontname[font].name, pstab[size-1]), tf);
                   2257:                lastfont = font;
                   2258:                lastsize = size;
                   2259:        }   /* End if */
                   2260: 
                   2261:        member = download(c, lastw, angle, tf);
                   2262: 
                   2263:        x = hpos * xfac + xoffset + .5;
                   2264:        y = vpos * yfac + yoffset + .5;
                   2265: 
                   2266:        if ( y != lasty )  {
                   2267:                putc(ASETAV, tf);
                   2268:                putint(y, tf);
                   2269:                lasty = y;
                   2270:        }   /* End if */
                   2271: 
                   2272:        if ( ABS(x - lastx) > SLOP )  {
                   2273:                putc(ASETAH, tf);
                   2274:                putint(x, tf);
                   2275:                lastx = x + fam->advance[member];
                   2276:        } else lastx += fam->advance[member];
                   2277: 
                   2278:        putc(member, tf);
                   2279: 
                   2280: }   /* End of oput */
                   2281: 
                   2282: 
                   2283: /*****************************************************************************/
                   2284: 
                   2285: 
                   2286: mapsize(name, ps)
                   2287:        char            *name;          /* name of the font */
                   2288:        int             ps;             /* point size troff wants to use */
                   2289: {
                   2290:        int             i, j;
                   2291: /*
                   2292:  * Uses the data that's been filled in from RASTLIST to map point size
                   2293:  * ps font font *name into the best size available in our raster tables.
                   2294:  * If no RASTLIST file was used rastsize will be zero and we'll just
                   2295:  * assume that any size that's aske for is available.
                   2296:  */
                   2297:        if ( maxrast == 0 )             /* don't have any size data */
                   2298:                return(ps);
                   2299: 
                   2300:        for ( i = 0; i < maxrast; i++ )
                   2301:                if ( strncmp(name, sizedata[i].name, L_FNAME) == 0 )
                   2302:                        break;
                   2303: 
                   2304:        if ( i >= maxrast )             /* didn't find the font */
                   2305:                error(FATAL, "missing raster list data for font %s", name);
                   2306: 
                   2307:        for ( j = 1, ps = (ps * pres) / rres; ps >= sizedata[i].sizes[j]; j++ ) ;
                   2308: 
                   2309:        return(sizedata[i].sizes[--j]);
                   2310: 
                   2311: }      /* End of mapsize */
                   2312: 
                   2313: 
                   2314: /*****************************************************************************/
                   2315: 
                   2316: 

unix.superglobalmegacorp.com

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