Annotation of researchv10no/cmd/post.src/dpost/dpost.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *
        !             3:  * dpost - troff post-processor for PostScript printers.
        !             4:  *
        !             5:  * A program that translates output generated by the device independent troff
        !             6:  * into PostScript. Much was borrowed from dimpress and dps (formally dlzw),
        !             7:  * and even though the code has changed, credit has to be given to Richard
        !             8:  * Flood for his early work on the PostScript driver.
        !             9:  *
        !            10:  * The big change is in the font table routines. The old binary format and
        !            11:  * makedev are gone. dpost and troff now read ASCII tables, and both skip
        !            12:  * unrecognized entries in the ASCII tables. That means problems, like where
        !            13:  * to put the real name of the PostScript font, have disappeared. The added
        !            14:  * flexibility means some overhead translating the ASCII tables, but the
        !            15:  * overhead isn't too bad.
        !            16:  *
        !            17:  * dpost can also now calculate a reasonably tight BoundingBox, which helps
        !            18:  * picture inclusion. The calculations, by default, are disabled. Couldn't
        !            19:  * justify the overhead for a comment, particularly one that's only needed
        !            20:  * occasionally. Use the -B option to get the comment.
        !            21:  *
        !            22:  * Output produced by dpost is still nonconforming. Definitions made in pages
        !            23:  * and exported to the job's global environment are the primary problem. It's
        !            24:  * an efficient approach, but means pages are not independent. Violations are
        !            25:  * bracketed by %%BeginGlobal and %%EndGlobal comments and can be pulled into
        !            26:  * the prologue by utility programs (like postreverse) that recognize the new
        !            27:  * comments.
        !            28:  *
        !            29:  * The program handles files formatted for any device, although the best and
        !            30:  * most efficient output is generated when the font and description files
        !            31:  * match PostScript's resident fonts. Emulation is relatively expensive, and
        !            32:  * can produce output files that are more than twice the size of the input
        !            33:  * files.
        !            34:  *
        !            35:  * Several different methods can be used to encode lines of text. What's done
        !            36:  * depends on the value assigned to encoding. Print time should decrease as
        !            37:  * encoding increases (up to MAXENCODING). Setting encoding to 3 (or higher)
        !            38:  * is not normally recommended. It's fast and produces very compact output,
        !            39:  * but rounding errors in troff's width tables can accumulate and lead to a
        !            40:  * ragged right margin. encoding can be changed on the command line using the
        !            41:  * -e option.
        !            42:  *
        !            43:  * PostScript fonts don't support all of troff's characters. Some are built
        !            44:  * by special PostScript procedures in directory *fontdir/devpost/charlib.
        !            45:  * The charlib approach is not meant to replace user defined fonts. It was
        !            46:  * a quick implementation designed to handle characters that aren't used
        !            47:  * often - charlib should not be overused! The charlib lookup is triggered
        !            48:  * when a character in a font table is assigned a code less than 32.
        !            49:  *
        !            50:  * Most defaults are set in the prologue, but can be changed by options. The
        !            51:  * -P option passes arbitrary PostScript into the setup section of the output
        !            52:  * file. It can be used to set (or change) values that can't be accessed by
        !            53:  * other options. For example,
        !            54:  *
        !            55:  *     dpost -P'/useclippath false def' file > file.ps
        !            56:  *
        !            57:  * defines useclippath to be false. Everything passed through using the -P
        !            58:  * (-C to copy a file) options become part of the job's global environment.
        !            59:  * Definitions override defaults in the prologue.
        !            60:  *
        !            61:  * dpost expects to find the following procedures in the prologue:
        !            62:  *
        !            63:  *     setup
        !            64:  *
        !            65:  *       mark ... setup -
        !            66:  *
        !            67:  *         Initialization procedure mainly responsible for setting up an
        !            68:  *         appropriate coordinate system.
        !            69:  *
        !            70:  *     pagesetup
        !            71:  *
        !            72:  *       page pagesetup -
        !            73:  *
        !            74:  *         Called at the start of each page, immediately after the page
        !            75:  *         level save. Argument is the current page number.
        !            76:  *
        !            77:  *     setdecoding
        !            78:  *
        !            79:  *       num setdecoding -
        !            80:  *
        !            81:  *         Select the decoding procedure used to print text strings encoded
        !            82:  *         by dpost. num is whatever has been assigned to encoding.
        !            83:  *
        !            84:  *     f
        !            85:  *
        !            86:  *       size font f -
        !            87:  *
        !            88:  *         Set the font and size used for character imaging. The font name
        !            89:  *         argument is (normally) the name troff used. Mapping to the real
        !            90:  *         PostScript font name is made using the fontname field in the
        !            91:  *         ASCII width tables.
        !            92:  *
        !            93:  *     m
        !            94:  *
        !            95:  *       x y m -
        !            96:  *
        !            97:  *         Move to point (x, y). Not used for positioning words in text
        !            98:  *         strings.
        !            99:  *
        !           100:  *     t
        !           101:  *
        !           102:  *       mark text t mark
        !           103:  *
        !           104:  *         Everything on the stack (up to the mark) is treated as a line
        !           105:  *         of text to be decoded and printed. What's on the stack depends
        !           106:  *         on encoding.
        !           107:  *
        !           108:  *     w
        !           109:  *
        !           110:  *       string x y w -
        !           111:  *
        !           112:  *         Print a single word starting at position (x, y). Only used in
        !           113:  *         the more complicated encoding schemes, like the ones based on
        !           114:  *         widthshow.
        !           115:  *
        !           116:  *     done
        !           117:  *
        !           118:  *         Make sure the last page prints. Always called, but only needed
        !           119:  *         when printing more than one page on each sheet of paper.
        !           120:  *
        !           121:  * output language from troff:
        !           122:  * all numbers are character strings
        !           123:  * 
        !           124:  * sn  size in points
        !           125:  * fn  font as number from 1-n
        !           126:  * cx  ascii character x
        !           127:  * Cxyz        funny char xyz. terminated by white space
        !           128:  * Hn  go to absolute horizontal position n
        !           129:  * Vn  go to absolute vertical position n (down is positive)
        !           130:  * hn  go n units horizontally (relative)
        !           131:  * vn  ditto vertically
        !           132:  * nnc move right nn, then print c (exactly 2 digits!)
        !           133:  *             (this wart is an optimization that shrinks output file size
        !           134:  *              about 35% and run-time about 15% while preserving ascii-ness)
        !           135:  * Dt ...\n    draw operation 't':
        !           136:  *     Dl x y          line from here by x,y
        !           137:  *     Dc d            circle of diameter d with left side here
        !           138:  *     De x y          ellipse of axes x,y with left side here
        !           139:  *     Da x1 y1 x2 y2  arc counter-clockwise from current point (x, y) to
        !           140:  *                     (x + x1 + x2, y + y1 + y2)
        !           141:  *     D~ x y x y ...  wiggly line by x,y then x,y ...
        !           142:  * nb a        end of line (information only -- no action needed)
        !           143:  *     b = space before line, a = after
        !           144:  * p   new page begins -- set v to 0
        !           145:  * #...\n      comment
        !           146:  * x ...\n     device control functions:
        !           147:  *     x i     init
        !           148:  *     x T s   name of device is s
        !           149:  *     x r n h v       resolution is n/inch
        !           150:  *             h = min horizontal motion, v = min vert
        !           151:  *     x p     pause (can restart)
        !           152:  *     x s     stop -- done forever
        !           153:  *     x t     generate trailer
        !           154:  *     x f n s font position n contains font s
        !           155:  *     x H n   set character height to n
        !           156:  *     x S n   set slant to N
        !           157:  * 
        !           158:  *     Subcommands like "i" are often spelled out like "init".
        !           159:  *
        !           160:  */
        !           161: 
        !           162: #include       <stdio.h>
        !           163: #include       <fcntl.h>
        !           164: #include       <signal.h>
        !           165: #include       <math.h>
        !           166: #include       <ctype.h>
        !           167: #include       <time.h>
        !           168: 
        !           169: #include       "comments.h"            /* structuring comments */
        !           170: #include       "gen.h"                 /* general purpose definitions */
        !           171: #include       "path.h"                /* prologue and a few other files */
        !           172: #include       "ext.h"                 /* external variable declarations */
        !           173: #include       "font.h"                /* font table definitions */
        !           174: #include       "dpost.h"               /* a few definitions just used here */
        !           175: #include       "motion.h"              /* positioning macros */
        !           176: 
        !           177: char   *prologue = DPOST;              /* the PostScript prologue */
        !           178: char   *colorfile = COLOR;             /* color support */
        !           179: char   *drawfile = DRAW;               /* drawing routines */
        !           180: char   *formfile = FORMFILE;           /* multiple pages on each sheet */
        !           181: char   *baselinefile = BASELINE;       /* for text along curved baseline */
        !           182: 
        !           183: char   *fontdir = FONTDIR;             /* font table directories */
        !           184: char   *hostfontdir = NULL;            /* host resident font directory */
        !           185: 
        !           186: char   *realdev = DEVNAME;             /* use these width tables */
        !           187: char   devname[20] = "";               /* job formatted for this device */
        !           188: Fontmap        fontmap[] = FONTMAP;            /* font translation table - emulation */
        !           189: char   *useencoding = NULL;            /* text font encoding - from -E option */
        !           190: 
        !           191: int    copies = 1;                     /* copies of each sheet */
        !           192: int    printed = 0;                    /* pages processed and printed */
        !           193: int    formsperpage = 1;               /* pages on each sheet of paper */
        !           194: int    picflag = ON;                   /* enable/disable picture inclusion */
        !           195: 
        !           196: int    encoding = DFLTENCODING;        /* how text is translated to PostScript */
        !           197: int    realencoding = DFLTENCODING;    /* where we started */
        !           198: int    maxencoding = MAXENCODING;      /* max that users can select */
        !           199: 
        !           200: int    landscape = FALSE;              /* for BoundingBox calculations only */
        !           201: double magnification = 1.0;
        !           202: double xoffset = 0.0;
        !           203: double yoffset = 0.0;
        !           204: 
        !           205: int    smnt;                           /* special fonts start here */
        !           206: int    devres;                         /* device resolution */
        !           207: int    unitwidth;                      /* and unitwidth - from DESC file */
        !           208: 
        !           209: char   downloaded[MAXCH+32+ALPHABET];  /* status of charlib characters */
        !           210: 
        !           211: int    nfonts = 0;                     /* number of font positions */
        !           212: int    size = 10;                      /* current point size */
        !           213: int    font = 0;                       /* and font position */
        !           214: int    hpos = 0;                       /* where troff wants to be */
        !           215: int    vpos = 0;
        !           216: float  lastw = 0;                      /* width of the last input character */
        !           217: int    lastc = 0;                      /* its name (or index) - for charlib() */
        !           218: 
        !           219: int    fontheight = 0;                 /* points from x H ... */
        !           220: int    fontslant = 0;                  /* angle from x S ... */
        !           221: 
        !           222: int    res;                            /* resolution assumed in input file */
        !           223: float  widthfac = 1.0;                 /* for emulation = res/devres */
        !           224: 
        !           225: int    lastsize = -1;                  /* for tracking printer's current size */
        !           226: int    lastfont = -1;                  /* current font */
        !           227: float  lastx = -1;                     /* and current position */
        !           228: int    lasty = -1;
        !           229: int    lastend;                        /* where last character on this line was */
        !           230: 
        !           231: int    seenpage = FALSE;               /* expect fonts are now all mounted */
        !           232: int    gotspecial = FALSE;             /* append special fonts - emulation */
        !           233: 
        !           234: float  pointslop = SLOP;               /* horizontal error in points */
        !           235: int    slop;                           /* and machine units */
        !           236: int    rvslop;                         /* to extend box in reverse video mode */
        !           237: 
        !           238: int    textcount = 0;                  /* strings accumulated so far */
        !           239: int    stringstart = 0;                /* where the next one starts */
        !           240: int    spacecount = 0;                 /* spaces in current string */
        !           241: 
        !           242: Line   line[MAXSTACK+3];               /* data about words accumulated so far */
        !           243: char   strings[STRINGSPACE];           /* strings temporarily saved here */
        !           244: char   *strptr;                        /* next free slot in strings[] */
        !           245: 
        !           246: FILE   *tf = NULL;                     /* most output goes here */
        !           247: FILE   *fp_acct = NULL;                /* accounting file */
        !           248: 
        !           249: char   *optnames = "a:c:e:m:n:o:p:tw:x:y:A:BC:E:J:F:H:L:OP:R:S:T:DI";
        !           250: 
        !           251: extern int     gotcolor;               /* read *colorfile when TRUE */
        !           252: extern Font    fonts[];                /* data about every font we see */
        !           253: extern Font    *mount[];               /* troff mounts fonts here */
        !           254: 
        !           255: /*****************************************************************************/
        !           256: 
        !           257: main(agc, agv)
        !           258: 
        !           259:     int                agc;
        !           260:     char       *agv[];
        !           261: 
        !           262: {
        !           263: 
        !           264: /*
        !           265:  *
        !           266:  * Translates output from troff into PostScript. Input files must be formatted
        !           267:  * for the same device. Each input file begins on a new page.
        !           268:  *
        !           269:  */
        !           270: 
        !           271:     argc = agc;                                /* global so everyone can use them */
        !           272:     argv = agv;
        !           273: 
        !           274:     prog_name = argv[0];               /* for error messages */
        !           275: 
        !           276:     init_signals();                    /* interrupt handling */
        !           277:     header();                          /* structuring comments */
        !           278:     options();                         /* command line options */
        !           279:     arguments();                       /* translate the input files */
        !           280:     done();                            /* add trailing comments etc. */
        !           281:     account();                         /* job accounting data */
        !           282: 
        !           283:     exit(x_stat);
        !           284: 
        !           285: }   /* End of main */
        !           286: 
        !           287: /*****************************************************************************/
        !           288: 
        !           289: init_signals()
        !           290: 
        !           291: {
        !           292: 
        !           293: /*
        !           294:  *
        !           295:  * Make sure we handle interrupts.
        !           296:  *
        !           297:  */
        !           298: 
        !           299:     if ( signal(SIGINT, interrupt) == SIG_IGN ) {
        !           300:        signal(SIGINT, SIG_IGN);
        !           301:        signal(SIGQUIT, SIG_IGN);
        !           302:        signal(SIGHUP, SIG_IGN);
        !           303:     } else {
        !           304:        signal(SIGHUP, interrupt);
        !           305:        signal(SIGQUIT, interrupt);
        !           306:     }   /* End else */
        !           307: 
        !           308:     signal(SIGTERM, interrupt);
        !           309: 
        !           310: }   /* End of init_signals */
        !           311: 
        !           312: /*****************************************************************************/
        !           313: 
        !           314: header()
        !           315: 
        !           316: {
        !           317: 
        !           318:     int                ch;
        !           319:     int                old_optind = optind;
        !           320: 
        !           321: /*
        !           322:  *
        !           323:  * Scan the option list for things needed now (e.g. prologue file), but could
        !           324:  * be changed from defaults. An attempt to follow to Adobe's 2.0 structuring
        !           325:  * conventions.
        !           326:  *
        !           327:  */
        !           328: 
        !           329:     while ( (ch = getopt(argc, argv, optnames)) != EOF )
        !           330:        if ( ch == 'L' )
        !           331:            setpaths(optarg);
        !           332:        else if ( ch == 'B' )
        !           333:            dobbox = TRUE;
        !           334:        else if ( ch == '?' )
        !           335:            error(FATAL, "");
        !           336: 
        !           337:     optind = old_optind;               /* restored for options() */
        !           338: 
        !           339:     fprintf(stdout, "%s", NONCONFORMING);
        !           340:     fprintf(stdout, "%s %s\n", VERSION, PROGRAMVERSION);
        !           341:     fprintf(stdout, "%s %s\n", DOCUMENTFONTS, ATEND);
        !           342:     fprintf(stdout, "%s %s\n", PAGES, ATEND);
        !           343:     if ( dobbox == TRUE )
        !           344:        fprintf(stdout, "%s %s\n", BOUNDINGBOX, ATEND);
        !           345:     fprintf(stdout, "%s", ENDCOMMENTS);
        !           346: 
        !           347:     if ( cat(prologue) == FALSE )
        !           348:        error(FATAL, "can't read %s", prologue);
        !           349: 
        !           350:     if ( DOROUND )
        !           351:        cat(ROUNDPAGE);
        !           352: 
        !           353:     fprintf(stdout, "%s", ENDPROLOG);
        !           354:     fprintf(stdout, "%s", BEGINSETUP);
        !           355:     fprintf(stdout, "mark\n");
        !           356: 
        !           357: }   /* End of header */
        !           358: 
        !           359: /*****************************************************************************/
        !           360: 
        !           361: options()
        !           362: 
        !           363: {
        !           364: 
        !           365:     int                ch;
        !           366: 
        !           367:     extern char        *optarg;
        !           368:     extern int optind;
        !           369: 
        !           370: /*
        !           371:  *
        !           372:  * Command line options - there are too many!
        !           373:  *
        !           374:  */
        !           375: 
        !           376:     while ( (ch = getopt(argc, argv, optnames)) != EOF ) {
        !           377:        switch ( ch ) {
        !           378:            case 'a':                   /* aspect ratio */
        !           379:                    fprintf(stdout, "/aspectratio %s def\n", optarg);
        !           380:                    break;
        !           381: 
        !           382:            case 'c':                   /* number of copies */
        !           383:                    copies = atoi(optarg);
        !           384:                    fprintf(stdout, "/#copies %s store\n", optarg);
        !           385:                    break;
        !           386: 
        !           387:            case 'e':                   /* select the encoding scheme */
        !           388:                    if ( (encoding = atoi(optarg)) < 0 || encoding > MAXENCODING )
        !           389:                        encoding = DFLTENCODING;
        !           390:                    realencoding = encoding;
        !           391:                    break;
        !           392: 
        !           393:            case 'm':                   /* magnification */
        !           394:                    magnification = atof(optarg);
        !           395:                    fprintf(stdout, "/magnification %s def\n", optarg);
        !           396:                    break;
        !           397: 
        !           398:            case 'n':                   /* forms per page */
        !           399:                    formsperpage = atoi(optarg);
        !           400:                    fprintf(stdout, "%s %s\n", FORMSPERPAGE, optarg);
        !           401:                    fprintf(stdout, "/formsperpage %s def\n", optarg);
        !           402:                    break;
        !           403: 
        !           404:            case 'o':                   /* output page list */
        !           405:                    out_list(optarg);
        !           406:                    break;
        !           407: 
        !           408:            case 'p':                   /* landscape or portrait mode */
        !           409:                    landscape = (*optarg == 'l') ? TRUE : FALSE;
        !           410:                    if ( landscape == TRUE )
        !           411:                        fprintf(stdout, "/landscape true def\n");
        !           412:                    else fprintf(stdout, "/landscape false def\n");
        !           413:                    break;
        !           414: 
        !           415:            case 't':                   /* compatibility */
        !           416:                    break;
        !           417: 
        !           418:            case 'w':                   /* line width - for drawing */
        !           419:                    fprintf(stdout, "/linewidth %s def\n", optarg);
        !           420:                    break;
        !           421: 
        !           422:            case 'x':                   /* shift horizontally */
        !           423:                    xoffset = atof(optarg);
        !           424:                    fprintf(stdout, "/xoffset %s def\n", optarg);
        !           425:                    break;
        !           426: 
        !           427:            case 'y':                   /* shift vertically */
        !           428:                    yoffset = atof(optarg);
        !           429:                    fprintf(stdout, "/yoffset %s def\n", optarg);
        !           430:                    break;
        !           431: 
        !           432:            case 'A':                   /* job accounting */
        !           433:            case 'J':
        !           434:                    if ( (fp_acct = fopen(optarg, "a")) == NULL )
        !           435:                        error(FATAL, "can't open accounting file %s", optarg);
        !           436:                    break;
        !           437: 
        !           438:            case 'B':                   /* enable BoundingBox calculations */
        !           439:                    dobbox = TRUE;
        !           440:                    fprintf(stdout, "/rotation 1 def\n");
        !           441:                    fprintf(stdout, "/gotpagebbox true def\n");
        !           442:                    break;
        !           443: 
        !           444:            case 'C':                   /* copy file to output */
        !           445:                    if ( cat(optarg) == FALSE )
        !           446:                        error(FATAL, "can't read %s", optarg);
        !           447:                    break;
        !           448: 
        !           449:            case 'E':                   /* text font encoding - override DESC */
        !           450:                    useencoding = optarg;
        !           451:                    break;
        !           452: 
        !           453:            case 'F':                   /* font table directory */
        !           454:                    fontdir = optarg;
        !           455:                    break;
        !           456: 
        !           457:            case 'H':                   /* host resident font directory */
        !           458:                    hostfontdir = optarg;
        !           459:                    break;
        !           460: 
        !           461:            case 'L':                   /* prologue file */
        !           462:                    setpaths(optarg);   /* already been done in header() */
        !           463:                    break;
        !           464: 
        !           465:            case 'O':                   /* disable picture inclusion */
        !           466:                    picflag = OFF;
        !           467:                    break;
        !           468: 
        !           469:            case 'P':                   /* copy string to output */
        !           470:                    fprintf(stdout, "%s\n", optarg);
        !           471:                    break;
        !           472: 
        !           473:            case 'R':                   /* global or page level request */
        !           474:                    saverequest(optarg);
        !           475:                    break;
        !           476: 
        !           477:            case 'S':                   /* horizontal position error */
        !           478:                    if ( (pointslop = atof(optarg)) < 0 )
        !           479:                        pointslop = 0;
        !           480:                    break;
        !           481: 
        !           482:            case 'T':                   /* target printer */
        !           483:                    realdev = optarg;
        !           484:                    break;
        !           485: 
        !           486:            case 'D':                   /* debug flag */
        !           487:                    debug = ON;
        !           488:                    tf = stdout;
        !           489:                    break;
        !           490: 
        !           491:            case 'I':                   /* ignore FATAL errors */
        !           492:                    ignore = ON;
        !           493:                    break;
        !           494: 
        !           495:            case '?':                   /* don't know the option */
        !           496:                    error(FATAL, "");
        !           497:                    break;
        !           498: 
        !           499:            default:
        !           500:                    error(FATAL, "missing case for option %c", ch);
        !           501:                    break;
        !           502:        }   /* End switch */
        !           503:     }  /* End while */
        !           504: 
        !           505:     argc -= optind;
        !           506:     argv += optind;
        !           507: 
        !           508: }   /* End of options */
        !           509: 
        !           510: /*****************************************************************************/
        !           511: 
        !           512: setpaths(name)
        !           513: 
        !           514:     char       *name;
        !           515: 
        !           516: {
        !           517: 
        !           518:     char       *path;
        !           519: 
        !           520: /*
        !           521:  *
        !           522:  * Extends the -L option to permit modification of more than just the prologue
        !           523:  * file pathname. Syntax is -Lpath or -Lname:path. For debugging and development
        !           524:  * only!
        !           525:  *
        !           526:  */
        !           527: 
        !           528:     for ( path = name; *path; path++ )
        !           529:        if ( *path == ':' || *path == ' ' ) {
        !           530:            while ( *path == ':' || *path == ' ' ) path++;
        !           531:            break;
        !           532:        }   /* End if */
        !           533: 
        !           534:     if ( *path == '\0' )               /* didn't find "name:" prefix */
        !           535:        path = name;
        !           536: 
        !           537:     if ( path == name || strncmp(name, "prologue", strlen("prologue")) == 0 )
        !           538:        prologue = path;
        !           539:     else if ( strncmp(name, "draw", strlen("draw")) == 0 )
        !           540:        drawfile = path;
        !           541:     else if ( strncmp(name, "color", strlen("color")) == 0 )
        !           542:        colorfile = path;
        !           543:     else if ( strncmp(name, "form", strlen("form")) == 0 )
        !           544:        formfile = path;
        !           545:     else if ( strncmp(name, "baseline", strlen("baseline")) == 0 )
        !           546:        baselinefile = path;
        !           547: 
        !           548: }   /* End of setpaths */
        !           549: 
        !           550: /*****************************************************************************/
        !           551: 
        !           552: setup()
        !           553: 
        !           554: {
        !           555: 
        !           556:     double     t;
        !           557: 
        !           558: /*
        !           559:  *
        !           560:  * Job and BoundingBox initialization. Called once from t_init() - must know
        !           561:  * the resolution before generating the PostScript call to setup. dpost only
        !           562:  * includes an encoding file if it's set in the DESC file or requested with
        !           563:  * the -E option.
        !           564:  *
        !           565:  */
        !           566: 
        !           567:     writerequest(0, stdout);           /* global requests e.g. manual feed */
        !           568:     fprintf(stdout, "/resolution %d def\n", res);
        !           569:     if ( useencoding != NULL || fontencoding != NULL )
        !           570:        setencoding((useencoding != NULL) ? useencoding : fontencoding);
        !           571:     fprintf(stdout, "setup\n");
        !           572:     fprintf(stdout, "%d setdecoding\n", realencoding);
        !           573: 
        !           574:     if ( formsperpage > 1 ) {          /* multiple pages */
        !           575:        if ( cat(formfile) == FALSE )
        !           576:            error(FATAL, "can't read %s", formfile);
        !           577:        fprintf(stdout, "%d setupforms\n", formsperpage);
        !           578:     }  /* End if */
        !           579: 
        !           580:     fprintf(stdout, "%s", ENDSETUP);
        !           581: 
        !           582:     if ( dobbox == TRUE ) {            /* ctm[] - must agree with prologue */
        !           583:        translate(pagewidth/2.0, pageheight/2.0);
        !           584:        if ( landscape == TRUE ) {
        !           585:            rotate(90.0);
        !           586:            t = pagewidth;
        !           587:            pagewidth = pageheight;
        !           588:            pageheight = t;
        !           589:        }   /* End if */
        !           590:        translate(-pagewidth/2.0, pageheight/2.0);
        !           591:        translate(72.0 * xoffset, -72.0 * yoffset);
        !           592:        scale(magnification, magnification);
        !           593:        scale(72.0/devres, 72.0/devres);
        !           594:     }  /* End if */
        !           595: 
        !           596: }   /* End of setup */
        !           597: 
        !           598: /*****************************************************************************/
        !           599: 
        !           600: arguments()
        !           601: 
        !           602: {
        !           603: 
        !           604:     FILE       *fp;
        !           605: 
        !           606: /*
        !           607:  *
        !           608:  * Everything else is an input file. No arguments or '-' means stdin.
        !           609:  *
        !           610:  */
        !           611: 
        !           612:     if ( argc < 1 )
        !           613:        conv(stdin);
        !           614:     else
        !           615:        while ( argc > 0 ) {
        !           616:            if ( strcmp(*argv, "-") == 0 )
        !           617:                fp = stdin;
        !           618:            else if ( (fp = fopen(*argv, "r")) == NULL )
        !           619:                error(FATAL, "can't open %s", *argv);
        !           620:            conv(fp);
        !           621:            if ( fp != stdin )
        !           622:                fclose(fp);
        !           623:            argc--;
        !           624:            argv++;
        !           625:        }   /* End while */
        !           626: 
        !           627: }   /* End of arguments */
        !           628: 
        !           629: /*****************************************************************************/
        !           630: 
        !           631: done()
        !           632: 
        !           633: {
        !           634: 
        !           635:     int                i;
        !           636:     int                n;
        !           637: 
        !           638: /*
        !           639:  *
        !           640:  * Force out the last page and add trailing comments.
        !           641:  *
        !           642:  */
        !           643: 
        !           644:     fprintf(stdout, "%s", TRAILER);
        !           645:     fprintf(stdout, "done\n");
        !           646:     fprintf(stdout, "%s %d\n", PAGES, printed);
        !           647: 
        !           648:     for ( i = 0, n = 0; i < MAXFONTS+1; i++ )
        !           649:        if ( (fonts[i].flags & USED) && fonts[i].fontname != NULL ) {
        !           650:            if ( n++ == 0 )
        !           651:                fprintf(stdout, "%s", DOCUMENTFONTS);
        !           652:            else if ( (n - 1) % 8 == 0 )
        !           653:                fprintf(stdout, "\n%s", CONTINUECOMMENT);
        !           654:            fprintf(stdout, " %s", fonts[i].fontname);
        !           655:        }   /* End if */
        !           656:     if ( n > 0 )
        !           657:        putc('\n', stdout);
        !           658: 
        !           659:     if ( dobbox == TRUE )
        !           660:        writebbox(stdout, BOUNDINGBOX, 10);
        !           661: 
        !           662: }   /* End of done */
        !           663: 
        !           664: /*****************************************************************************/
        !           665: 
        !           666: account()
        !           667: 
        !           668: {
        !           669: 
        !           670: /*
        !           671:  *
        !           672:  * Accounting record to fp_acct - provided it's not NULL.
        !           673:  *
        !           674:  */
        !           675: 
        !           676:     if ( fp_acct != NULL )
        !           677:        fprintf(fp_acct, " print %d\n copies %d\n", printed, copies);
        !           678: 
        !           679: }   /* End of account */
        !           680: 
        !           681: /*****************************************************************************/
        !           682: 
        !           683: conv(fp)
        !           684: 
        !           685:     register FILE      *fp;
        !           686: 
        !           687: {
        !           688: 
        !           689:     register int       c;
        !           690:     int                        m, n, n1, m1;
        !           691:     char               str[50];
        !           692: 
        !           693: /*
        !           694:  *
        !           695:  * Read troff output from file fp and translate it into PostScript. The final
        !           696:  * t_page() call means input files start on a new page.
        !           697:  *
        !           698:  */
        !           699: 
        !           700:     redirect(-1);                      /* do output only after a page command */
        !           701:     lineno = 1;
        !           702: 
        !           703:     while ((c = getc(fp)) != EOF) {
        !           704:        switch (c) {
        !           705:            case '\n':                  /* just count this line */
        !           706:                    lineno++;
        !           707:                    break;
        !           708: 
        !           709:            case ' ':                   /* when input is text */
        !           710:            case 0:                     /* occasional noise creeps in */
        !           711:                    break;
        !           712: 
        !           713:            case '0': case '1': case '2': case '3': case '4':
        !           714:            case '5': case '6': case '7': case '8': case '9':
        !           715:                    /* two motion digits plus a character */
        !           716:                    hmot((c-'0')*10 + getc(fp)-'0');
        !           717:                    put1(getc(fp));
        !           718:                    break;
        !           719: 
        !           720:            case 'c':                   /* single ascii character */
        !           721:                    put1(getc(fp));
        !           722:                    break;
        !           723: 
        !           724:            case 'C':                   /* special character */
        !           725:                    fscanf(fp, "%s", str);
        !           726:                    put1(chindex(str));
        !           727:                    break;
        !           728: 
        !           729:            case 'N':                   /* character at position n */
        !           730:                    fscanf(fp, "%d", &m);
        !           731:                    flushtext();
        !           732:                    oput(m);
        !           733:                    break;
        !           734: 
        !           735:            case 'D':                   /* drawing functions */
        !           736:                    flushtext();
        !           737:                    getdraw();
        !           738:                    if ( size != lastsize )
        !           739:                        t_sf();
        !           740:                    switch ((c=getc(fp))) {
        !           741:                        case 'p':       /* draw a path */
        !           742:                            while (fscanf(fp, "%d %d", &n, &m) == 2)
        !           743:                                drawline(n, m);
        !           744:                            lineno++;
        !           745:                            break;
        !           746: 
        !           747:                        case 'l':       /* draw a line */
        !           748:                            fscanf(fp, "%d %d %c", &n, &m, &n1);
        !           749:                            drawline(n, m);
        !           750:                            break;
        !           751: 
        !           752:                        case 'c':       /* circle */
        !           753:                            fscanf(fp, "%d", &n);
        !           754:                            drawcirc(n);
        !           755:                            break;
        !           756: 
        !           757:                        case 'e':       /* ellipse */
        !           758:                            fscanf(fp, "%d %d", &m, &n);
        !           759:                            drawellip(m, n);
        !           760:                            break;
        !           761: 
        !           762:                        case 'a':       /* counter-clockwise arc */
        !           763:                        case 'A':       /* clockwise arc */
        !           764:                            fscanf(fp, "%d %d %d %d", &n, &m, &n1, &m1);
        !           765:                            drawarc(n, m, n1, m1, c);
        !           766:                            break;
        !           767: 
        !           768:                        case 'q':       /* spline without end points */
        !           769:                            drawspline(fp, 1);
        !           770:                            lineno++;
        !           771:                            break;
        !           772: 
        !           773:                        case '~':       /* wiggly line */
        !           774:                            drawspline(fp, 2);
        !           775:                            lineno++;
        !           776:                            break;
        !           777: 
        !           778:                        default:
        !           779:                            error(FATAL, "unknown drawing function %c", c);
        !           780:                            break;
        !           781:                    }   /* End switch */
        !           782:                    break;
        !           783: 
        !           784:            case 's':                   /* use this point size */
        !           785:                    fscanf(fp, "%d", &size);    /* ignore fractional sizes */
        !           786:                    break;
        !           787: 
        !           788:            case 'f':                   /* use font mounted here */
        !           789:                    fscanf(fp, "%s", str);
        !           790:                    setfont(t_font(str));
        !           791:                    break;
        !           792: 
        !           793:            case 'H':                   /* absolute horizontal motion */
        !           794:                    fscanf(fp, "%d", &n);
        !           795:                    hgoto(n);
        !           796:                    break;
        !           797: 
        !           798:            case 'h':                   /* relative horizontal motion */
        !           799:                    fscanf(fp, "%d", &n);
        !           800:                    hmot(n);
        !           801:                    break;
        !           802: 
        !           803:            case 'w':                   /* word space */
        !           804:                    break;
        !           805: 
        !           806:            case 'V':                   /* absolute vertical position */
        !           807:                    fscanf(fp, "%d", &n);
        !           808:                    vgoto(n);
        !           809:                    break;
        !           810: 
        !           811:            case 'v':                   /* relative vertical motion */
        !           812:                    fscanf(fp, "%d", &n);
        !           813:                    vmot(n);
        !           814:                    break;
        !           815: 
        !           816:            case 'p':                   /* new page */
        !           817:                    fscanf(fp, "%d", &n);
        !           818:                    t_page(n);
        !           819:                    break;
        !           820: 
        !           821:            case 'n':                   /* end of line */
        !           822:                    while ( (c = getc(fp)) != '\n' && c != EOF ) ;
        !           823:                    hgoto(0);
        !           824:                    lineno++;
        !           825:                    break;
        !           826: 
        !           827:            case '#':                   /* comment */
        !           828:                    while ( (c = getc(fp)) != '\n' && c != EOF ) ;
        !           829:                    lineno++;
        !           830:                    break;
        !           831: 
        !           832:            case 'x':                   /* device control function */
        !           833:                    devcntrl(fp);
        !           834:                    lineno++;
        !           835:                    break;
        !           836: 
        !           837:            default:
        !           838:                    error(FATAL, "unknown input character %o %c", c, c);
        !           839:                    done();
        !           840:        }   /* End switch */
        !           841:     }  /* End while */
        !           842: 
        !           843:     t_page(-1);                                /* print the last page */
        !           844:     flushtext();
        !           845: 
        !           846: }   /* End of conv */
        !           847: 
        !           848: /*****************************************************************************/
        !           849: 
        !           850: devcntrl(fp)
        !           851: 
        !           852:     FILE       *fp;
        !           853: 
        !           854: {
        !           855: 
        !           856:     char       str[50], buf[256], str1[100];
        !           857:     int                c, n;
        !           858: 
        !           859: /*
        !           860:  *
        !           861:  * Interpret device control commands, ignoring any we don't recognize. The
        !           862:  * "x X ..." commands are a device dependent collection generated by troff's
        !           863:  * \X'...' request.
        !           864:  *
        !           865:  */
        !           866: 
        !           867:     fscanf(fp, "%s", str);
        !           868: 
        !           869:     switch ( str[0] ) {
        !           870:        case 'f':                       /* load font in a position */
        !           871:                fscanf(fp, "%d %s", &n, str);
        !           872:                fgets(buf, sizeof buf, fp);     /* in case there's a filename */
        !           873:                ungetc('\n', fp);       /* fgets() goes too far */
        !           874:                str1[0] = '\0';         /* in case there's nothing to come in */
        !           875:                sscanf(buf, "%s", str1);
        !           876:                loadfont(n, str, str1);
        !           877:                break;
        !           878: 
        !           879:        case 'i':                       /* initialize */
        !           880:                t_init();
        !           881:                break;
        !           882: 
        !           883:        case 'p':                       /* pause */
        !           884:                break;
        !           885: 
        !           886:        case 'r':                       /* resolution assumed when prepared */
        !           887:                fscanf(fp, "%d", &res);
        !           888:                break;
        !           889: 
        !           890:        case 's':                       /* stop */
        !           891:        case 't':                       /* trailer */
        !           892:                flushtext();
        !           893:                break;
        !           894: 
        !           895:        case 'H':                       /* char height */
        !           896:                fscanf(fp, "%d", &n);
        !           897:                t_charht(n);
        !           898:                break;
        !           899: 
        !           900:        case 'S':                       /* slant */
        !           901:                fscanf(fp, "%d", &n);
        !           902:                t_slant(n);
        !           903:                break;
        !           904: 
        !           905:        case 'T':                       /* device name */
        !           906:                fscanf(fp, "%s", devname);
        !           907:                break;
        !           908: 
        !           909:        case 'X':                       /* copy through - from troff */
        !           910:                fscanf(fp, " %[^: \n]:", str);
        !           911:                fgets(buf, sizeof(buf), fp);
        !           912:                ungetc('\n', fp);
        !           913:                if ( strcmp(str, "PI") == 0 || strcmp(str, "PictureInclusion") == 0 )
        !           914:                    picture(buf);
        !           915:                else if ( strcmp(str, "InlinePicture") == 0 )
        !           916:                    inlinepic(fp, buf);
        !           917:                else if ( strcmp(str, "BeginPath") == 0 )
        !           918:                    beginpath(buf, FALSE);
        !           919:                else if ( strcmp(str, "DrawPath") == 0 )
        !           920:                    drawpath(buf, FALSE);
        !           921:                else if ( strcmp(str, "BeginObject") == 0 )
        !           922:                    beginpath(buf, TRUE);
        !           923:                else if ( strcmp(str, "EndObject") == 0 )
        !           924:                    drawpath(buf, TRUE);
        !           925:                else if ( strcmp(str, "NewBaseline") == 0 )
        !           926:                    newbaseline(buf);
        !           927:                else if ( strcmp(str, "DrawText") == 0 )
        !           928:                    drawtext(buf);
        !           929:                else if ( strcmp(str, "SetText") == 0 )
        !           930:                    settext(buf);
        !           931:                else if ( strcmp(str, "SetColor") == 0 ) {
        !           932:                    newcolor(buf);
        !           933:                    setcolor();
        !           934:                } else if ( strcmp(str, "INFO") == 0 ) {
        !           935:                    flushtext();
        !           936:                    fprintf(tf, "%%INFO%s", buf);
        !           937:                } else if ( strcmp(str, "PS") == 0 || strcmp(str, "PostScript") == 0 ) {
        !           938:                    flushtext();
        !           939:                    fprintf(tf, "%s", buf);
        !           940:                } else if ( strcmp(str, "ExportPS") == 0 ) {    /* dangerous!! */
        !           941:                    if ( tf == stdout ) {
        !           942:                        restore();
        !           943:                        fprintf(tf, "%s", buf);
        !           944:                        save();
        !           945:                    }   /* End if */
        !           946:                }   /* End else */
        !           947:                break;
        !           948:     }  /* End switch */
        !           949: 
        !           950:     while ( (c = getc(fp)) != '\n' && c != EOF ) ;
        !           951: 
        !           952: }   /* End of devcntrl */
        !           953: 
        !           954: /*****************************************************************************/
        !           955: 
        !           956: loadfont(m, f, name)
        !           957: 
        !           958:     int                m;
        !           959:     char       *f;
        !           960:     char       *name;
        !           961: 
        !           962: {
        !           963: 
        !           964:     char       path[150];
        !           965: 
        !           966: /*
        !           967:  *
        !           968:  * Load position m with font f. Font file pathname is *fontdir/dev*realdev/*f
        !           969:  * or name, if name isn't empty. Use mapfont() to replace the missing font
        !           970:  * if we're emulating another device, name is empty, and the first mount
        !           971:  * fails.
        !           972:  *
        !           973:  */
        !           974: 
        !           975:     if ( name[0] == '\0' )
        !           976:        sprintf(path, "%s/dev%s/%s", fontdir, realdev, f);
        !           977:     else sprintf(path, "%s", name);
        !           978: 
        !           979:     if ( mountfont(path, m) == -1 ) {
        !           980:        if ( name[0] == '\0' ) {
        !           981:            sprintf(path, "%s/dev%s/%s", fontdir, realdev, mapfont(f));
        !           982:            if ( mountfont(path, m) == -1 ) {
        !           983:                sprintf(path, "%s/dev%s/%s", fontdir, realdev, f);
        !           984:                error(FATAL, "can't load %s at %d", path, m);
        !           985:            }   /* End if */
        !           986:        } else error(FATAL, "can't load %s at %d", path, m);
        !           987:     }  /* End if */
        !           988: 
        !           989:     if ( smnt == 0 && mount[m]->specfont )
        !           990:        smnt = m;
        !           991: 
        !           992:     if ( m == lastfont )               /* force a call to t_sf() */
        !           993:        lastfont = -1;
        !           994: 
        !           995:     if ( m > nfonts ) {                        /* got more positions */
        !           996:        nfonts = m;
        !           997:        gotspecial = FALSE;
        !           998:     }  /* End if */
        !           999: 
        !          1000: }   /* End of loadfont */
        !          1001: 
        !          1002: /*****************************************************************************/
        !          1003: 
        !          1004: char *mapfont(name)
        !          1005: 
        !          1006:     char       *name;
        !          1007: 
        !          1008: {
        !          1009: 
        !          1010:     int                i;
        !          1011: 
        !          1012: /*
        !          1013:  *
        !          1014:  * Map a missing font name into one that should be available. Only used when
        !          1015:  * we're emulating another device and the first mount fails. Consider deleting
        !          1016:  * this routine.
        !          1017:  *
        !          1018:  */
        !          1019: 
        !          1020:     for ( i = 0; fontmap[i].name != NULL; i++ )
        !          1021:        if ( strcmp(name, fontmap[i].name) == 0 )
        !          1022:            return(fontmap[i].use);
        !          1023: 
        !          1024:     switch ( *++name ) {
        !          1025:        case 'I': return("I");
        !          1026:        case 'B': return("B");
        !          1027:        case 'X': return("BI");
        !          1028:        default:  return("R");
        !          1029:     }  /* End switch */
        !          1030: 
        !          1031: }   /* End of mapfont */
        !          1032: 
        !          1033: /*****************************************************************************/
        !          1034: 
        !          1035: loadspecial()
        !          1036: 
        !          1037: {
        !          1038: 
        !          1039: /*
        !          1040:  *
        !          1041:  * Fix - later.
        !          1042:  *
        !          1043:  */
        !          1044: 
        !          1045:     gotspecial = TRUE;
        !          1046: 
        !          1047: }   /* End of loadspecial */
        !          1048: 
        !          1049: /*****************************************************************************/
        !          1050: 
        !          1051: t_init()
        !          1052: 
        !          1053: {
        !          1054: 
        !          1055:     char       path[150];
        !          1056:     static int initialized = FALSE;
        !          1057: 
        !          1058: /*
        !          1059:  *
        !          1060:  * Finish initialization - just read an "x init" command. Assumes we already
        !          1061:  * know the input file resolution.
        !          1062:  *
        !          1063:  */
        !          1064: 
        !          1065:     flushtext();                       /* moved - for cat'ed troff files */
        !          1066: 
        !          1067:     if ( initialized == FALSE ) {
        !          1068:        if ( strcmp(devname, realdev) ) {
        !          1069:            sprintf(path, "%s/dev%s/DESC", fontdir, devname);
        !          1070:            if ( checkdesc(path) )
        !          1071:                realdev = devname;
        !          1072:        }   /* End if */
        !          1073: 
        !          1074:        sprintf(path, "%s/dev%s/DESC", fontdir, realdev);
        !          1075:        if ( getdesc(path) == -1 )
        !          1076:            error(FATAL, "can't open %s", path);
        !          1077:        nfonts = 0;
        !          1078:        gotspecial = FALSE;
        !          1079:        widthfac = (float) res /devres;
        !          1080:        slop = pointslop * res / POINTS + .5;
        !          1081:        rvslop = res * .025;
        !          1082:        setup();
        !          1083:        initialized = TRUE;
        !          1084:     }  /* End if */
        !          1085: 
        !          1086:     hpos = vpos = 0;
        !          1087:     size = 10;
        !          1088:     reset();
        !          1089: 
        !          1090: }   /* End of t_init */
        !          1091: 
        !          1092: /*****************************************************************************/
        !          1093: 
        !          1094: t_page(pg)
        !          1095: 
        !          1096:     int                pg;
        !          1097: 
        !          1098: {
        !          1099: 
        !          1100:     static int lastpg = 0;
        !          1101: 
        !          1102: /*
        !          1103:  *
        !          1104:  * Finish the previous page and get ready for the next one. End page output
        !          1105:  * goes to /dev/null at the start of each input file. Start page output goes
        !          1106:  * to /dev/null at the end of each input file.
        !          1107:  *
        !          1108:  * Consider doing showpage after page level restore (as Adobe recommends). If
        !          1109:  * the order is changed use restore() and save(). forms.ps will likely also
        !          1110:  * need fixing.
        !          1111:  *
        !          1112:  */
        !          1113: 
        !          1114:     if ( tf == stdout )
        !          1115:        printed++;
        !          1116: 
        !          1117:     flushtext();                       /* just in case */
        !          1118: 
        !          1119:     fprintf(tf, "cleartomark\n");
        !          1120:     fprintf(tf, "showpage\n");
        !          1121:     fprintf(tf, "saveobj restore\n");
        !          1122:     if ( dobbox == TRUE )
        !          1123:        writebbox(tf, PAGEBOUNDINGBOX, 10);
        !          1124:     fprintf(tf, "%s %d %d\n", ENDPAGE, lastpg, printed);
        !          1125: 
        !          1126:     redirect(pg);
        !          1127: 
        !          1128:     fprintf(tf, "%s %d %d\n", PAGE, pg, printed+1);
        !          1129:     if ( dobbox == TRUE )
        !          1130:        fprintf(tf, "%s %s\n", PAGEBOUNDINGBOX, ATEND);
        !          1131:     fprintf(tf, "/saveobj save def\n");
        !          1132:     fprintf(tf, "mark\n");
        !          1133:     writerequest(printed+1, tf);
        !          1134:     fprintf(tf, "%d pagesetup\n", printed+1);
        !          1135: 
        !          1136:     if ( encoding != realencoding )
        !          1137:        fprintf(tf, "%d setdecoding\n", encoding);
        !          1138: 
        !          1139:     if ( gotcolor == TRUE )
        !          1140:        setcolor();
        !          1141: 
        !          1142:     lastpg = pg;                       /* for the next ENDPAGE comment */
        !          1143:     hpos = vpos = 0;                   /* get ready for the next page */
        !          1144:     reset();                           /* force position and font stuff - later */
        !          1145: 
        !          1146:     seenpage = TRUE;
        !          1147: 
        !          1148: }   /* End of t_page */
        !          1149: 
        !          1150: /*****************************************************************************/
        !          1151: 
        !          1152: t_font(s)
        !          1153: 
        !          1154:     char       *s;
        !          1155: 
        !          1156: {
        !          1157: 
        !          1158:     int                n;
        !          1159: 
        !          1160: /*
        !          1161:  *
        !          1162:  * Converts the string *s into an integer and checks to make sure it's a legal
        !          1163:  * font position. Also arranges to mount all the special fonts after the last
        !          1164:  * legitimate font (by calling loadspecial()), provided it hasn't already been
        !          1165:  * done.
        !          1166:  *
        !          1167:  */
        !          1168: 
        !          1169:     n = atoi(s);
        !          1170: 
        !          1171:     if ( seenpage == TRUE ) {
        !          1172:        if ( n < 0 || n > nfonts )
        !          1173:            error(FATAL, "illegal font position %d", n);
        !          1174: 
        !          1175:        if ( gotspecial == FALSE )
        !          1176:            loadspecial();
        !          1177:     }  /* End if */
        !          1178: 
        !          1179:     return(n);
        !          1180: 
        !          1181: }   /* End of t_font */
        !          1182: 
        !          1183: /*****************************************************************************/
        !          1184: 
        !          1185: setfont(m)
        !          1186: 
        !          1187:     int                m;
        !          1188: 
        !          1189: {
        !          1190: 
        !          1191: /*
        !          1192:  *
        !          1193:  * Use the font mounted at position m. Bounds checks are probably unnecessary.
        !          1194:  * Changing the font and size used by the printer is handled in t_sf().
        !          1195:  *
        !          1196:  */
        !          1197: 
        !          1198:     if ( m < 0 || m > MAXFONTS )
        !          1199:        error(FATAL, "illegal font %d", m);
        !          1200:     font = m;
        !          1201: 
        !          1202: }   /* End of setfont */
        !          1203: 
        !          1204: /*****************************************************************************/
        !          1205: 
        !          1206: t_sf()
        !          1207: 
        !          1208: {
        !          1209: 
        !          1210:     Font       *fpos;
        !          1211:     char       temp[150];
        !          1212: 
        !          1213: /*
        !          1214:  *
        !          1215:  * Force a new font or size. Generates name definitions for fonts that haven't
        !          1216:  * been named, grabs host resident font files and keeps track of the fonts used
        !          1217:  * by this job. When necessary also adjusts the font's height and slant. Should
        !          1218:  * only be called immediately before printing a character.
        !          1219:  *
        !          1220:  */
        !          1221: 
        !          1222:     if ( tf == stdout && mounted(font) ) {
        !          1223:        flushtext();
        !          1224: 
        !          1225:        fpos = mount[font];
        !          1226:        if ( (fpos->flags & USED) == 0 ) {
        !          1227:            if ( (fpos->flags & NAMED) == 0 && fpos->fontname != NULL ) {
        !          1228:                sprintf(temp, "/%s /%s def\n", fpos->name, fpos->fontname);
        !          1229:                exportstring(temp);
        !          1230:                fpos->flags |= NAMED;           /* unnecessary */
        !          1231:            }   /* End if */
        !          1232: 
        !          1233:            if ( hostfontdir != NULL ) {
        !          1234:                sprintf(temp, "%s/%s", hostfontdir, fpos->name);
        !          1235:                exportfile(temp);
        !          1236:            }   /* End if */
        !          1237:        }   /* End if */
        !          1238: 
        !          1239:        fprintf(tf, "%d %s f\n", size, fpos->name);
        !          1240:        if ( fontheight != 0 || fontslant != 0 )
        !          1241:            fprintf(tf, "%d %d changefont\n", fontslant, (fontheight != 0) ? fontheight : size);
        !          1242: 
        !          1243:        lastfont = font;
        !          1244:        lastsize = size;
        !          1245:        fpos->flags |= USED;
        !          1246:     }  /* End if */
        !          1247: 
        !          1248: }   /* End of t_sf */
        !          1249: 
        !          1250: /*****************************************************************************/
        !          1251: 
        !          1252: t_charht(n)
        !          1253: 
        !          1254:     int                n;
        !          1255: 
        !          1256: {
        !          1257: 
        !          1258: /*
        !          1259:  *
        !          1260:  * Set character height to n points. Disabled if n is 0 or the current size.
        !          1261:  *
        !          1262:  */
        !          1263: 
        !          1264:     fontheight = (n == size) ? 0 : n;
        !          1265:     lastfont = -1;
        !          1266: 
        !          1267: }   /* End of t_charht */
        !          1268: 
        !          1269: /*****************************************************************************/
        !          1270: 
        !          1271: t_slant(n)
        !          1272: 
        !          1273:     int                n;
        !          1274: 
        !          1275: {
        !          1276: 
        !          1277: /*
        !          1278:  *
        !          1279:  * Set slant to n degrees. Disable slanting if n is 0.
        !          1280:  *
        !          1281:  */
        !          1282: 
        !          1283:     fontslant = n;
        !          1284:     lastfont = -1;
        !          1285: 
        !          1286: }   /* End of t_slant */
        !          1287: 
        !          1288: /*****************************************************************************/
        !          1289: 
        !          1290: xymove(x, y)
        !          1291: 
        !          1292:     int                x, y;
        !          1293: 
        !          1294: {
        !          1295: 
        !          1296: /*
        !          1297:  *
        !          1298:  * Make the the printer and post-processor agree about the current position.
        !          1299:  *
        !          1300:  */
        !          1301: 
        !          1302:     flushtext();
        !          1303: 
        !          1304:     hgoto(x);
        !          1305:     vgoto(y);
        !          1306: 
        !          1307:     fprintf(tf, "%d %d m\n", hpos, vpos);
        !          1308: 
        !          1309:     lastx = hpos;
        !          1310:     lasty = vpos;
        !          1311: 
        !          1312: }   /* End of xymove */
        !          1313: 
        !          1314: /*****************************************************************************/
        !          1315: 
        !          1316: put1(c)
        !          1317: 
        !          1318:     register int       c;
        !          1319: 
        !          1320: {
        !          1321: 
        !          1322:     register int       i;
        !          1323:     register int       j;
        !          1324:     register int       k;
        !          1325:     int                        code;
        !          1326:     int                        ofont;
        !          1327: 
        !          1328: /*
        !          1329:  *
        !          1330:  * Print character c. ASCII if c < ALPHABET, otherwise it's special. Look for
        !          1331:  * c in the current font, then in others starting at the first special font.
        !          1332:  * Save c in lastc so it's available when oput() runs. Restore original font
        !          1333:  * before leaving.
        !          1334:  *
        !          1335:  */
        !          1336: 
        !          1337:     lastc = c;                         /* charlib() needs name not code */
        !          1338:     if ( (c -= 32) <= 0 )
        !          1339:        return;
        !          1340: 
        !          1341:     k = ofont = font;
        !          1342: 
        !          1343:     if ( (i = onfont(lastc, k)) == -1 && smnt > 0 )
        !          1344:        for ( k = smnt, j = 0; j < nfonts; j++, k = k % nfonts + 1 ) {
        !          1345:            if ( (i = onfont(lastc, k)) != -1 ) {
        !          1346:                setfont(k);
        !          1347:                break;
        !          1348:            }   /* End if */
        !          1349:        }   /* End for */
        !          1350: 
        !          1351:     if ( i != -1 && (code = mount[k]->wp[i].code) != 0 ) {
        !          1352:        lastw = widthfac * (((int)mount[k]->wp[i].wid * size + unitwidth/2) / unitwidth);
        !          1353:        oput(code);
        !          1354:     }  /* End if */
        !          1355: 
        !          1356:     if ( font != ofont )
        !          1357:        setfont(ofont);
        !          1358: 
        !          1359: }   /* End of put1 */
        !          1360: 
        !          1361: /*****************************************************************************/
        !          1362: 
        !          1363: oput(c)
        !          1364: 
        !          1365:     int                c;
        !          1366: 
        !          1367: {
        !          1368: 
        !          1369:     double     llx, lly, urx, ury;     /* boundingbox corners */
        !          1370: 
        !          1371: /*
        !          1372:  *
        !          1373:  * Arranges to print the character whose code is c in the current font. All the
        !          1374:  * actual positioning is done here, in charlib(), or in the drawing routines.
        !          1375:  *
        !          1376:  */
        !          1377: 
        !          1378:     if ( textcount > MAXSTACK )                /* don't put too much on the stack? */
        !          1379:        flushtext();
        !          1380: 
        !          1381:     if ( font != lastfont || size != lastsize )
        !          1382:        t_sf();
        !          1383: 
        !          1384:     if ( vpos != lasty )
        !          1385:        endline();
        !          1386: 
        !          1387:     starttext();
        !          1388: 
        !          1389:     if ( ABS(hpos - lastx) > slop )
        !          1390:        endstring();
        !          1391: 
        !          1392:     if ( isascii(c) && isprint(c) )
        !          1393:        switch ( c ) {
        !          1394:            case '(':
        !          1395:            case ')':
        !          1396:            case '\\':
        !          1397:                    addchar('\\');
        !          1398: 
        !          1399:            default:
        !          1400:                    addchar(c);
        !          1401:        }   /* End switch */
        !          1402:     else if ( c > 040 )
        !          1403:        addoctal(c);
        !          1404:     else charlib(c);
        !          1405: 
        !          1406:     if ( dobbox == TRUE ) {
        !          1407:        llx = lastx;
        !          1408:        lly = -(vpos + 0.5 * (devres * size / 72.0));
        !          1409:        urx = lastx + lastw;
        !          1410:        ury = -(vpos - (devres * size / 72.0));
        !          1411:        cover(llx, lly);
        !          1412:        cover(urx, ury);
        !          1413:     }  /* End if */
        !          1414: 
        !          1415:     lastx += lastw;
        !          1416: 
        !          1417: }   /* End of oput */
        !          1418: 
        !          1419: /*****************************************************************************/
        !          1420: 
        !          1421: starttext()
        !          1422: 
        !          1423: {
        !          1424: 
        !          1425: /*
        !          1426:  * Called whenever we want to be sure we're ready to start collecting characters
        !          1427:  * for the next call to PostScript procedure t (ie. the one that prints them). If
        !          1428:  * textcount is positive we've already started, so there's nothing to do. The more
        !          1429:  * complicated encoding schemes save text strings in the strings[] array and need
        !          1430:  * detailed information about the strings when they're written to the output file
        !          1431:  * in flushtext().
        !          1432:  *
        !          1433:  */
        !          1434: 
        !          1435:     if ( textcount < 1 ) {
        !          1436:        switch ( encoding ) {
        !          1437:            case 0:
        !          1438:            case 1:
        !          1439:                putc('(', tf);
        !          1440:                break;
        !          1441: 
        !          1442:            case 2:
        !          1443:            case 3:
        !          1444:                strptr = strings;
        !          1445:                spacecount = 0;
        !          1446:                line[1].str = strptr;
        !          1447:                line[1].dx = 0;
        !          1448:                line[1].spaces = 0;
        !          1449:                line[1].start = hpos;
        !          1450:                line[1].width = 0;
        !          1451:                break;
        !          1452: 
        !          1453:            case MAXENCODING+1:                 /* reverse video */
        !          1454:                if ( lastend == -1 )
        !          1455:                    lastend = hpos;
        !          1456:                putc('(', tf);
        !          1457:                break;
        !          1458: 
        !          1459:            case MAXENCODING+2:                 /* follow a funny baseline */
        !          1460:                putc('(', tf);
        !          1461:                break;
        !          1462:        }   /* End switch */
        !          1463: 
        !          1464:        textcount = 1;
        !          1465:        lastx = stringstart = hpos;
        !          1466:     }  /* End if */
        !          1467: 
        !          1468: }   /* End of starttext */
        !          1469: 
        !          1470: /*****************************************************************************/
        !          1471: 
        !          1472: flushtext()
        !          1473: 
        !          1474: {
        !          1475: 
        !          1476:     int                i;
        !          1477: 
        !          1478: /*
        !          1479:  *
        !          1480:  * Generates a call to the PostScript procedure that processes all the text we've
        !          1481:  * accumulated - provided textcount is positive.
        !          1482:  *
        !          1483:  */
        !          1484: 
        !          1485:     if ( textcount > 0 ) {
        !          1486:        switch ( encoding ) {
        !          1487:            case 0:
        !          1488:                fprintf(tf, ")%d t\n", stringstart);
        !          1489:                break;
        !          1490: 
        !          1491:            case 1:
        !          1492:                fprintf(tf, ")%d %d t\n", stringstart, lasty);
        !          1493:                break;
        !          1494: 
        !          1495:            case 2:
        !          1496:                *strptr = '\0';
        !          1497:                line[textcount].width = lastx - line[textcount].start;
        !          1498:                if ( spacecount != 0 || textcount != 1 ) {
        !          1499:                    for ( i = textcount; i > 0; i-- )
        !          1500:                        fprintf(tf, "(%s)%d %d", line[i].str, line[i].spaces, line[i].width);
        !          1501:                    fprintf(tf, " %d %d %d t\n", textcount, stringstart, lasty);
        !          1502:                } else fprintf(tf, "(%s)%d %d w\n", line[1].str, stringstart, lasty);
        !          1503:                break;
        !          1504: 
        !          1505:            case 3:
        !          1506:                *strptr = '\0';
        !          1507:                if ( spacecount != 0 || textcount != 1 ) {
        !          1508:                    for ( i = textcount; i > 0; i-- )
        !          1509:                        fprintf(tf, "(%s)%d", line[i].str, line[i].dx);
        !          1510:                    fprintf(tf, " %d %d %d t\n", textcount, stringstart, lasty);
        !          1511:                } else fprintf(tf, "(%s)%d %d w\n", line[1].str, stringstart, lasty);
        !          1512:                break;
        !          1513: 
        !          1514:            case MAXENCODING+1:
        !          1515:                fprintf(tf, ")%d ", stringstart);
        !          1516:                fprintf(tf, "%d %d drawrvbox ", lastend - rvslop, (int)(lastx + .5) + rvslop);
        !          1517:                fprintf(tf, "t\n", stringstart);
        !          1518:                lastend = (lastx + .5) + 2 * rvslop;
        !          1519:                break;
        !          1520: 
        !          1521:            case MAXENCODING+2:
        !          1522:                fprintf(tf, ")%d %d t\n", stringstart, lasty);
        !          1523:                break;
        !          1524:        }   /* End switch */
        !          1525:     }  /* End if */
        !          1526: 
        !          1527:     textcount = 0;
        !          1528: 
        !          1529: }   /* End of flushtext */
        !          1530: 
        !          1531: /*****************************************************************************/
        !          1532: 
        !          1533: endstring()
        !          1534: 
        !          1535: {
        !          1536: 
        !          1537:     int                dx;
        !          1538: 
        !          1539: /*
        !          1540:  *
        !          1541:  * Horizontal positions are out of sync. End the last open string, adjust the
        !          1542:  * printer's position, and start a new string. Assumes we've already started
        !          1543:  * accumulating text.
        !          1544:  *
        !          1545:  */
        !          1546: 
        !          1547:     switch ( encoding ) {
        !          1548:        case 0:
        !          1549:        case 1:
        !          1550:            fprintf(tf, ")%d(", stringstart);
        !          1551:            textcount++;
        !          1552:            lastx = stringstart = hpos;
        !          1553:            break;
        !          1554: 
        !          1555:        case 2:
        !          1556:        case 3:
        !          1557:            dx = hpos - lastx;
        !          1558:            if ( spacecount++ == 0 )
        !          1559:                line[textcount].dx = dx;
        !          1560:            if ( line[textcount].dx != dx ) {
        !          1561:                *strptr++ = '\0';
        !          1562:                line[textcount].width = lastx - line[textcount].start;
        !          1563:                line[++textcount].str = strptr;
        !          1564:                *strptr++ = ' ';
        !          1565:                line[textcount].dx = dx;
        !          1566:                line[textcount].start = lastx;
        !          1567:                line[textcount].width = 0;
        !          1568:                line[textcount].spaces = 1;
        !          1569:            } else {
        !          1570:                *strptr++ = ' ';
        !          1571:                line[textcount].spaces++;
        !          1572:            }   /* End else */
        !          1573:            lastx += dx;
        !          1574:            break;
        !          1575: 
        !          1576:        case MAXENCODING+1:
        !          1577:            fprintf(tf, ")%d(", stringstart);
        !          1578:            textcount++;
        !          1579:            lastx = stringstart = hpos;
        !          1580:            break;
        !          1581: 
        !          1582:        case MAXENCODING+2:
        !          1583:            flushtext();
        !          1584:            starttext();
        !          1585:            break;
        !          1586:     }  /* End switch */
        !          1587: 
        !          1588: }   /* End of endstring */
        !          1589: 
        !          1590: /*****************************************************************************/
        !          1591: 
        !          1592: endline()
        !          1593: 
        !          1594: {
        !          1595: 
        !          1596: /*
        !          1597:  *
        !          1598:  * The vertical position has changed. Dump any accumulated text, then adjust
        !          1599:  * the printer's vertical position.
        !          1600:  *
        !          1601:  */
        !          1602: 
        !          1603:     flushtext();
        !          1604: 
        !          1605:     if ( encoding == 0 || encoding == MAXENCODING+1 )
        !          1606:        fprintf(tf, "%d %d m\n", hpos, vpos);
        !          1607: 
        !          1608:     lastx = stringstart = lastend = hpos;
        !          1609:     lasty = vpos;
        !          1610: 
        !          1611: }   /* End of endline */
        !          1612: 
        !          1613: /*****************************************************************************/
        !          1614: 
        !          1615: addchar(c)
        !          1616: 
        !          1617:     int                c;
        !          1618: 
        !          1619: {
        !          1620: 
        !          1621: /*
        !          1622:  *
        !          1623:  * Does whatever is needed to add character c to the current string.
        !          1624:  *
        !          1625:  */
        !          1626: 
        !          1627:     switch ( encoding ) {
        !          1628:        case 0:
        !          1629:        case 1:
        !          1630:            putc(c, tf);
        !          1631:            break;
        !          1632: 
        !          1633:        case 2:
        !          1634:        case 3:
        !          1635:            *strptr++ = c;
        !          1636:            break;
        !          1637: 
        !          1638:        case MAXENCODING+1:
        !          1639:        case MAXENCODING+2:
        !          1640:            putc(c, tf);
        !          1641:            break;
        !          1642:     }  /* End switch */
        !          1643: 
        !          1644: }   /* End of addchar */
        !          1645: 
        !          1646: /*****************************************************************************/
        !          1647: 
        !          1648: addoctal(c)
        !          1649: 
        !          1650:     int                c;
        !          1651: 
        !          1652: {
        !          1653: 
        !          1654: /*
        !          1655:  *
        !          1656:  * Add c to the current string as an octal escape.
        !          1657:  *
        !          1658:  */
        !          1659: 
        !          1660:     switch ( encoding ) {
        !          1661:        case 0:
        !          1662:        case 1:
        !          1663:            fprintf(tf, "\\%o", c);
        !          1664:            break;
        !          1665: 
        !          1666:        case 2:
        !          1667:        case 3:
        !          1668:            sprintf(strptr, "\\%o", c);
        !          1669:            strptr += strlen(strptr);
        !          1670:            break;
        !          1671: 
        !          1672:        case MAXENCODING+1:
        !          1673:        case MAXENCODING+2:
        !          1674:            fprintf(tf, "\\%o", c);
        !          1675:            break;
        !          1676:     }  /* End switch */
        !          1677: 
        !          1678: }   /* End of addoctal */
        !          1679: 
        !          1680: /*****************************************************************************/
        !          1681: 
        !          1682: charlib(code)
        !          1683: 
        !          1684:     int                code;                   /* either 1 or 2 */
        !          1685: 
        !          1686: {
        !          1687: 
        !          1688:     char       *name;                  /* name of the character */
        !          1689:     char       tname[10];              /* in case it's a single ASCII character */
        !          1690:     char       temp[150];
        !          1691: 
        !          1692: /*
        !          1693:  *
        !          1694:  * Called from oput() for characters having codes less than 040. Special files
        !          1695:  * that define PostScript procedures for certain characters can be found in
        !          1696:  * directory *fontdir/devpost/charlib. If there's a file that has the same name as
        !          1697:  * the character we're trying to print it's copied to the output file, otherwise
        !          1698:  * nothing, except some positioning, is done.
        !          1699:  *
        !          1700:  * All character definitions are only made once. Subsequent requests to print the
        !          1701:  * character generate a call to a procedure that begins with the prefix build_ and
        !          1702:  * ends with the character's name. Special characters that are assigned codes
        !          1703:  * other than 1 are assumed to have additional data files that should be copied
        !          1704:  * to the output file immediately after the build_ call. Those data files should
        !          1705:  * end in the suffix .map, and usually will be a hex representation of a bitmap.
        !          1706:  *
        !          1707:  */
        !          1708: 
        !          1709:     flushtext();
        !          1710: 
        !          1711:     if ( lastc < ALPHABET ) {          /* ASCII character */
        !          1712:        sprintf(tname, "%.3o", lastc);
        !          1713:        name = tname;
        !          1714:     } else name = chname(lastc);
        !          1715: 
        !          1716:     if ( downloaded[lastc] == 0 ) {
        !          1717:        sprintf(temp, "%s/dev%s/charlib/%s", fontdir, realdev, name);
        !          1718:        if ( exportfile(temp) == TRUE ) {
        !          1719:            downloaded[lastc] = 1;
        !          1720:            t_sf();
        !          1721:        }   /* End if */
        !          1722:     }  /* End if */
        !          1723: 
        !          1724:     if ( downloaded[lastc] == 1 ) {
        !          1725:        xymove(hpos, vpos);
        !          1726:        fprintf(tf, "%d build_%s\n", (int) lastw, name);
        !          1727:        if ( code != 1 ) {              /* get the bitmap or whatever */
        !          1728:            sprintf(temp, "%s/dev%s/charlib/%s.map", fontdir, realdev, name);
        !          1729:            if ( access(temp, 04) == 0 && tf == stdout )
        !          1730:                cat(temp);
        !          1731:        }   /* End if */
        !          1732:        fprintf(tf, "%d %d m\n", stringstart = hpos + lastw, vpos);
        !          1733:     }  /* End if */
        !          1734: 
        !          1735: }   /* End of charlib */
        !          1736: 
        !          1737: /*****************************************************************************/
        !          1738: 
        !          1739: reset()
        !          1740: 
        !          1741: {
        !          1742: 
        !          1743: /*
        !          1744:  *
        !          1745:  * Reset variables that keep track of the printer's current position, size and
        !          1746:  * font. Eventually forces things back in sync before oput() prints the next
        !          1747:  * character.
        !          1748:  *
        !          1749:  */
        !          1750: 
        !          1751:     lastx = -(slop + 1);
        !          1752:     lasty = -1;
        !          1753:     lastfont = lastsize = -1;
        !          1754: 
        !          1755: }   /* End of reset */
        !          1756: 
        !          1757: /*****************************************************************************/
        !          1758: 
        !          1759: resetpos()
        !          1760: 
        !          1761: {
        !          1762: 
        !          1763: /*
        !          1764:  *
        !          1765:  * Reset the position tracking variables. Forces oput() to get positions back
        !          1766:  * in sync before printing the next character.
        !          1767:  *
        !          1768:  */
        !          1769: 
        !          1770:     lastx = -(slop + 1);
        !          1771:     lasty = -1;
        !          1772: 
        !          1773: }   /* End of resetpos */
        !          1774: 
        !          1775: /*****************************************************************************/
        !          1776: 
        !          1777: save()
        !          1778: 
        !          1779: {
        !          1780: 
        !          1781: /*
        !          1782:  *
        !          1783:  * Save the current PostScript environment. Initialize things that may have
        !          1784:  * disappeared after the preceeding restore.
        !          1785:  *
        !          1786:  */
        !          1787: 
        !          1788:     fprintf(tf, "/saveobj save def\n");
        !          1789:     fprintf(tf, "mark\n");
        !          1790: 
        !          1791:     if ( encoding != realencoding )
        !          1792:        fprintf(tf, "%d setdecoding\n", encoding);
        !          1793: 
        !          1794:     if ( gotcolor == TRUE )            /* prevent getcolor() recursion */
        !          1795:        setcolor();
        !          1796: 
        !          1797: }   /* End of save */
        !          1798: 
        !          1799: /*****************************************************************************/
        !          1800: 
        !          1801: restore()
        !          1802: 
        !          1803: {
        !          1804: 
        !          1805: /*
        !          1806:  *
        !          1807:  * Restore the previous PostScript environment.
        !          1808:  *
        !          1809:  */
        !          1810: 
        !          1811:     flushtext();
        !          1812:     fprintf(tf, "cleartomark\n");
        !          1813:     fprintf(tf, "saveobj restore\n");
        !          1814:     reset();
        !          1815: 
        !          1816: }   /* End of restore */
        !          1817: 
        !          1818: /*****************************************************************************/
        !          1819: 
        !          1820: exportfile(path)
        !          1821: 
        !          1822:     char       *path;
        !          1823: 
        !          1824: {
        !          1825: 
        !          1826:     int                val = FALSE;
        !          1827: 
        !          1828: /*
        !          1829:  *
        !          1830:  * Exports the contents of file path to the global environment. Returns TRUE
        !          1831:  * if we're doing output (i.e. tf == stdout) and the copy worked.
        !          1832:  *
        !          1833:  */
        !          1834: 
        !          1835:     if ( tf == stdout && access(path, 04) == 0 ) {
        !          1836:        restore();
        !          1837:        fprintf(tf, "%s", BEGINGLOBAL);
        !          1838:        val = cat(path);
        !          1839:        fprintf(tf, "%s", ENDGLOBAL);
        !          1840:        save();
        !          1841:     }  /* End if */
        !          1842: 
        !          1843:     return(val);
        !          1844: 
        !          1845: }   /* End of exportfile */
        !          1846: 
        !          1847: /*****************************************************************************/
        !          1848: 
        !          1849: exportstring(str)
        !          1850: 
        !          1851:     char       *str;
        !          1852: 
        !          1853: {
        !          1854: 
        !          1855: /*
        !          1856:  *
        !          1857:  * Exports string str to the global environment. No return value needed yet.
        !          1858:  *
        !          1859:  */
        !          1860: 
        !          1861:     if ( tf == stdout && str != NULL && *str != '\0' ) {
        !          1862:        restore();
        !          1863:        fprintf(tf, "%s", BEGINGLOBAL);
        !          1864:        fprintf(tf, "%s", str);
        !          1865:        fprintf(tf, "%s", ENDGLOBAL);
        !          1866:        save();
        !          1867:     }  /* End if */
        !          1868: 
        !          1869: }   /* End of exportstring */
        !          1870: 
        !          1871: /*****************************************************************************/
        !          1872: 
        !          1873: redirect(pg)
        !          1874: 
        !          1875:     int                pg;
        !          1876: 
        !          1877: {
        !          1878: 
        !          1879:     static FILE        *fp_null = NULL;
        !          1880: 
        !          1881: /*
        !          1882:  *
        !          1883:  * If we're not supposed to print page pg, tf will be directed to /dev/null,
        !          1884:  * otherwise output goes to stdout.
        !          1885:  *
        !          1886:  */
        !          1887: 
        !          1888:     if ( pg >= 0 && in_olist(pg) == ON )
        !          1889:        tf = stdout;
        !          1890:     else if ( (tf = fp_null) == NULL )
        !          1891:        tf = fp_null = fopen("/dev/null", "w");
        !          1892: 
        !          1893: }   /* End of redirect */
        !          1894: 
        !          1895: /*****************************************************************************/
        !          1896: 

unix.superglobalmegacorp.com

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