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

unix.superglobalmegacorp.com

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