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

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

unix.superglobalmegacorp.com

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