Annotation of researchv10no/cmd/picasso/dpost.c, revision 1.1

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

unix.superglobalmegacorp.com

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