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

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

unix.superglobalmegacorp.com

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