Annotation of researchv10no/cmd/postscript/postdaisy/postdaisy.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *
                      3:  * postdaisy - PostScript translator for Diablo 1640 files.
                      4:  *
                      5:  * A program that translates Diablo 1640 files into PostScript. Absolutely nothing
                      6:  * is guaranteed. Quite a few things haven't been implemented, and what's been
                      7:  * done isn't well tested. Most of the documentation used to write this program
                      8:  * was taken from the 'Diablo Emulator' section of a recent Imagen manual.
                      9:  *
                     10:  * Some of document comments that are generated may not be right. Most of the test
                     11:  * files I used produced a trailing blank page. I've put a check in formfeed() that
                     12:  * won't print the last page if it doesn't contain any text, but PAGES comments may
                     13:  * not be right. The DOCUMENTFONTS comment will also be wrong if auto underline or
                     14:  * bold printing have been turned on by escape commands.
                     15:  *
                     16:  * The brute force approach used to implement horizontal and vertical tabs leaves
                     17:  * much to be desired, and may not work for very small initial hmi and vmi values.
                     18:  * At the very least I should have used malloc() to get space for the two tabstop
                     19:  * arrays after hmi and vmi are known!
                     20:  *
                     21:  * Reverse printing mode hasn't been tested at all, but what's here should be
                     22:  * close even though it's not efficient.
                     23:  *
                     24:  * The PostScript prologue is copied from *prologue before any of the input files
                     25:  * are translated. The program expects that the following PostScript procedures
                     26:  * are defined in that file:
                     27:  *
                     28:  *     setup
                     29:  *
                     30:  *       mark ... setup -
                     31:  *
                     32:  *         Handles special initialization stuff that depends on how this program
                     33:  *         was called. Expects to find a mark followed by key/value pairs on the
                     34:  *         stack. The def operator is applied to each pair up to the mark, then
                     35:  *         the default state is set up.
                     36:  *
                     37:  *     pagesetup
                     38:  *
                     39:  *       page pagesetup -
                     40:  *
                     41:  *         Does whatever is needed to set things up for the next page. Expects to
                     42:  *         find the current page number on the stack.
                     43:  *
                     44:  *     t
                     45:  *
                     46:  *       mark str1 x1 str2 x2 ... strn xn y hmi t mark
                     47:  *
                     48:  *         Handles all the text on the stack. Characters in the strings are
                     49:  *         printed using hmi as the character advance, and all strings are at
                     50:  *         vertical position y. Each string is begins at the horizontal position
                     51:  *         that preceeds it.
                     52:  *
                     53:  *     f
                     54:  *
                     55:  *       font f -
                     56:  *
                     57:  *         Use font f, where f is the full PostScript font name. Only used when
                     58:  *         we switch to auto underline (Courier-Italic) or bold (Courier-Bold)
                     59:  *         printing.
                     60:  *
                     61:  *     done
                     62:  *
                     63:  *       done
                     64:  *
                     65:  *         Makes sure the last page is printed. Only needed when we're printing
                     66:  *         more than one page on each sheet of paper.
                     67:  *
                     68:  * Many default values, like the magnification and orientation, are defined in 
                     69:  * the prologue, which is where they belong. If they're changed (by options), an
                     70:  * appropriate definition is made after the prologue is added to the output file.
                     71:  * The -P option passes arbitrary PostScript through to the output file. Among
                     72:  * other things it can be used to set (or change) values that can't be accessed by
                     73:  * other options.
                     74:  *
                     75:  */
                     76: 
                     77: #include <stdio.h>
                     78: #include <signal.h>
                     79: #include <ctype.h>
                     80: #include <fcntl.h>
                     81: 
                     82: #include "comments.h"                  /* PostScript file structuring comments */
                     83: #include "gen.h"                       /* general purpose definitions */
                     84: #include "path.h"                      /* for the prologue */
                     85: #include "ext.h"                       /* external variable declarations */
                     86: #include "postdaisy.h"                 /* a few special definitions */
                     87: 
                     88: char   *optnames = "a:c:f:h:l:m:n:o:p:r:s:v:x:y:A:C:E:J:L:P:DI";
                     89: 
                     90: char   *prologue = POSTDAISY;          /* default PostScript prologue */
                     91: char   *formfile = FORMFILE;           /* stuff for multiple pages per sheet */
                     92: 
                     93: int    formsperpage = 1;               /* page images on each piece of paper */
                     94: int    copies = 1;                     /* and this many copies of each sheet */
                     95: 
                     96: char   htabstops[COLUMNS];             /* horizontal */
                     97: char   vtabstops[ROWS];                /* and vertical tabs */
                     98: 
                     99: int    res = RES;                      /* input file resolution - sort of */
                    100: 
                    101: int    hmi = HMI;                      /* horizontal motion index - 1/120 inch */
                    102: int    vmi = VMI;                      /* vertical motion index - 1/48 inch */
                    103: int    ohmi = HMI;                     /* original hmi */
                    104: int    ovmi = VMI;                     /* and vmi - for tabs and char size */
                    105: 
                    106: int    hpos = 0;                       /* current horizontal */
                    107: int    vpos = 0;                       /* and vertical position */
                    108: 
                    109: int    lastx = -1;                     /* printer's last horizontal */
                    110: int    lasty = -1;                     /* and vertical position */
                    111: int    lasthmi = -1;                   /* hmi for current text strings */
                    112: 
                    113: int    lastc = -1;                     /* last printed character */
                    114: int    prevx = -1;                     /* at this position */
                    115: 
                    116: int    leftmargin = LEFTMARGIN;        /* page margins */
                    117: int    rightmargin = RIGHTMARGIN;
                    118: int    topmargin = TOPMARGIN;
                    119: int    bottommargin = BOTTOMMARGIN;
                    120: 
                    121: int    stringcount = 0;                /* number of strings on the stack */
                    122: int    stringstart = 1;                /* column where current one starts */
                    123: int    advance = 1;                    /* -1 if in backward print mode */
                    124: 
                    125: int    lfiscr = OFF;                   /* line feed implies carriage return */
                    126: int    crislf = OFF;                   /* carriage return implies line feed */
                    127: 
                    128: int    linespp = 0;                    /* lines per page if it's positive */
                    129: int    markedpage = FALSE;             /* helps prevent trailing blank page */
                    130: int    page = 0;                       /* page we're working on */
                    131: int    printed = 0;                    /* printed this many pages */
                    132: 
                    133: Fontmap        fontmap[] = FONTMAP;            /* for translating font names */
                    134: char   *fontname = "Courier";          /* use this PostScript font */
                    135: int    shadowprint = OFF;              /* automatic bold printing if ON */
                    136: 
                    137: FILE   *fp_in;                         /* read from this file */
                    138: FILE   *fp_out = stdout;               /* and write stuff here */
                    139: FILE   *fp_acct = NULL;                /* for accounting data */
                    140: 
                    141: /*****************************************************************************/
                    142: 
                    143: main(agc, agv)
                    144: 
                    145:     int                agc;
                    146:     char       *agv[];
                    147: 
                    148: {
                    149: 
                    150: /*
                    151:  *
                    152:  * A simple program that translates Diablo 1640 files into PostScript. Nothing
                    153:  * is guaranteed - the program not well tested and doesn't implement everything.
                    154:  *
                    155:  */
                    156: 
                    157:     argc = agc;                                /* other routines may want them */
                    158:     argv = agv;
                    159: 
                    160:     prog_name = argv[0];               /* really just for error messages */
                    161: 
                    162:     init_signals();                    /* sets up interrupt handling */
                    163:     header();                          /* PostScript header comments */
                    164:     options();                         /* handle the command line options */
                    165:     setup();                           /* for PostScript */
                    166:     arguments();                       /* followed by each input file */
                    167:     done();                            /* print the last page etc. */
                    168:     account();                         /* job accounting data */
                    169: 
                    170:     exit(x_stat);                      /* not much could be wrong */
                    171: 
                    172: }   /* End of main */
                    173: 
                    174: /*****************************************************************************/
                    175: 
                    176: init_signals()
                    177: 
                    178: {
                    179: 
                    180: /*
                    181:  *
                    182:  * Makes sure we handle interrupts.
                    183:  *
                    184:  */
                    185: 
                    186:     if ( signal(SIGINT, interrupt) == SIG_IGN )  {
                    187:        signal(SIGINT, SIG_IGN);
                    188:        signal(SIGQUIT, SIG_IGN);
                    189:        signal(SIGHUP, SIG_IGN);
                    190:     } else {
                    191:        signal(SIGHUP, interrupt);
                    192:        signal(SIGQUIT, interrupt);
                    193:     }   /* End else */
                    194: 
                    195:     signal(SIGTERM, interrupt);
                    196: 
                    197: }   /* End of init_signals */
                    198: 
                    199: /*****************************************************************************/
                    200: 
                    201: header()
                    202: 
                    203: {
                    204: 
                    205:     int                ch;                     /* return value from getopt() */
                    206:     int                old_optind = optind;    /* for restoring optind - should be 1 */
                    207: 
                    208: /*
                    209:  *
                    210:  * Scans the option list looking for things, like the prologue file, that we need
                    211:  * right away but could be changed from the default. Doing things this way is an
                    212:  * attempt to conform to Adobe's latest file structuring conventions. In particular
                    213:  * they now say there should be nothing executed in the prologue, and they have
                    214:  * added two new comments that delimit global initialization calls. Once we know
                    215:  * where things really are we write out the job header, follow it by the prologue,
                    216:  * and then add the ENDPROLOG and BEGINSETUP comments.
                    217:  *
                    218:  */
                    219: 
                    220:     while ( (ch = getopt(argc, argv, optnames)) != EOF )
                    221:        if ( ch == 'L' )
                    222:            prologue = optarg;
                    223:        else if ( ch == '?' )
                    224:            error(FATAL, "");
                    225: 
                    226:     optind = old_optind;               /* get ready for option scanning */
                    227: 
                    228:     fprintf(stdout, "%s", CONFORMING);
                    229:     fprintf(stdout, "%s %s\n", VERSION, PROGRAMVERSION);
                    230:     fprintf(stdout, "%s %s\n", DOCUMENTFONTS, ATEND);
                    231:     fprintf(stdout, "%s %s\n", PAGES, ATEND);
                    232:     fprintf(stdout, "%s", ENDCOMMENTS);
                    233: 
                    234:     if ( cat(prologue) == FALSE )
                    235:        error(FATAL, "can't read %s", prologue);
                    236: 
                    237:     if ( DOROUND )
                    238:        cat(ROUNDPAGE);
                    239: 
                    240:     fprintf(stdout, "%s", ENDPROLOG);
                    241:     fprintf(stdout, "%s", BEGINSETUP);
                    242:     fprintf(stdout, "mark\n");
                    243: 
                    244: }   /* End of header */
                    245: 
                    246: /*****************************************************************************/
                    247: 
                    248: options()
                    249: 
                    250: {
                    251: 
                    252:     int                ch;                     /* return value from getopt() */
                    253:     int                n;                      /* for CR and LF modes */
                    254: 
                    255: /*
                    256:  *
                    257:  * Reads and processes the command line options. Added the -P option so arbitrary
                    258:  * PostScript code can be passed through. Expect it could be useful for changing
                    259:  * definitions in the prologue for which options have not been defined.
                    260:  *
                    261:  * Although any PostScript font can be used, things will only work for constant
                    262:  * width fonts.
                    263:  *
                    264:  */
                    265: 
                    266:     while ( (ch = getopt(argc, argv, optnames)) != EOF )  {
                    267:        switch ( ch )  {
                    268:            case 'a':                   /* aspect ratio */
                    269:                    fprintf(stdout, "/aspectratio %s def\n", optarg);
                    270:                    break;
                    271: 
                    272:            case 'c':                   /* copies */
                    273:                    copies = atoi(optarg);
                    274:                    fprintf(stdout, "/#copies %s store\n", optarg);
                    275:                    break;
                    276: 
                    277:            case 'f':                   /* use this PostScript font */
                    278:                    fontname = get_font(optarg);
                    279:                    fprintf(stdout, "/font /%s def\n", fontname);
                    280:                    break;
                    281: 
                    282:            case 'h':                   /* default character spacing */
                    283:                    ohmi = hmi = atoi(optarg) * HSCALE;
                    284:                    fprintf(stdout, "/hmi %s def\n", optarg);
                    285:                    break;
                    286: 
                    287:            case 'l':                   /* lines per page */
                    288:                    linespp = atoi(optarg);
                    289:                    break;
                    290: 
                    291:            case 'm':                   /* magnification */
                    292:                    fprintf(stdout, "/magnification %s def\n", optarg);
                    293:                    break;
                    294: 
                    295:            case 'n':                   /* forms per page */
                    296:                    formsperpage = atoi(optarg);
                    297:                    fprintf(stdout, "%s %s\n", FORMSPERPAGE, optarg);
                    298:                    fprintf(stdout, "/formsperpage %s def\n", optarg);
                    299:                    break;
                    300: 
                    301:            case 'o':                   /* output page list */
                    302:                    out_list(optarg);
                    303:                    break;
                    304: 
                    305:            case 'p':                   /* landscape or portrait mode */
                    306:                    if ( *optarg == 'l' )
                    307:                        fprintf(stdout, "/landscape true def\n");
                    308:                    else fprintf(stdout, "/landscape false def\n");
                    309:                    break;
                    310: 
                    311:            case 'r':                   /* set CR and LF modes */
                    312:                    n = atoi(optarg);
                    313:                    if ( n & 01 )
                    314:                        lfiscr = ON;
                    315:                    else lfiscr = OFF;
                    316:                    if ( n & 02 )
                    317:                        crislf = ON;
                    318:                    else crislf = OFF;
                    319:                    break;
                    320: 
                    321:            case 's':                   /* point size */
                    322:                    fprintf(stdout, "/pointsize %s def\n", optarg);
                    323:                    break;
                    324: 
                    325:            case 'v':                   /* default line spacing */
                    326:                    ovmi = vmi = atoi(optarg) * VSCALE;
                    327:                    break;
                    328: 
                    329:            case 'x':                   /* shift things horizontally */
                    330:                    fprintf(stdout, "/xoffset %s def\n", optarg);
                    331:                    break;
                    332: 
                    333:            case 'y':                   /* and vertically on the page */
                    334:                    fprintf(stdout, "/yoffset %s def\n", optarg);
                    335:                    break;
                    336: 
                    337:            case 'A':                   /* force job accounting */
                    338:            case 'J':
                    339:                    if ( (fp_acct = fopen(optarg, "a")) == NULL )
                    340:                        error(FATAL, "can't open accounting file %s", optarg);
                    341:                    break;
                    342: 
                    343:            case 'C':                   /* copy file straight to output */
                    344:                    if ( cat(optarg) == FALSE )
                    345:                        error(FATAL, "can't read %s", optarg);
                    346:                    break;
                    347: 
                    348:            case 'E':                   /* text font encoding */
                    349:                    fontencoding = optarg;
                    350:                    break;
                    351: 
                    352:            case 'L':                   /* PostScript prologue file */
                    353:                    prologue = optarg;
                    354:                    break;
                    355: 
                    356:            case 'P':                   /* PostScript pass through */
                    357:                    fprintf(stdout, "%s\n", optarg);
                    358:                    break;
                    359: 
                    360:            case 'R':                   /* special global or page level request */
                    361:                    saverequest(optarg);
                    362:                    break;
                    363: 
                    364:            case 'D':                   /* debug flag */
                    365:                    debug = ON;
                    366:                    break;
                    367: 
                    368:            case 'I':                   /* ignore FATAL errors */
                    369:                    ignore = ON;
                    370:                    break;
                    371: 
                    372:            case '?':                   /* don't understand the option */
                    373:                    error(FATAL, "");
                    374:                    break;
                    375: 
                    376:            default:                    /* don't know what to do for ch */
                    377:                    error(FATAL, "missing case for option %c\n", ch);
                    378:                    break;
                    379:        }   /* End switch */
                    380:     }   /* End while */
                    381: 
                    382:     argc -= optind;                    /* get ready for non-option args */
                    383:     argv += optind;
                    384: 
                    385: }   /* End of options */
                    386: 
                    387: /*****************************************************************************/
                    388: 
                    389: char *get_font(name)
                    390: 
                    391:     char       *name;                  /* name the user asked for */
                    392: 
                    393: {
                    394: 
                    395:     int                i;                      /* for looking through fontmap[] */
                    396: 
                    397: /*
                    398:  *
                    399:  * Called from options() to map a user's font name into a legal PostScript name.
                    400:  * If the lookup fails *name is returned to the caller. That should let you choose
                    401:  * any PostScript font, although things will only work well for constant width
                    402:  * fonts.
                    403:  *
                    404:  */
                    405: 
                    406:     for ( i = 0; fontmap[i].name != NULL; i++ )
                    407:        if ( strcmp(name, fontmap[i].name) == 0 )
                    408:            return(fontmap[i].val);
                    409: 
                    410:     return(name);
                    411: 
                    412: }   /* End of get_font */
                    413: 
                    414: /*****************************************************************************/
                    415: 
                    416: setup()
                    417: 
                    418: {
                    419: 
                    420: /*
                    421:  *
                    422:  * Handles things that must be done after the options are read but before the
                    423:  * input files are processed.
                    424:  *
                    425:  */
                    426: 
                    427:     writerequest(0, stdout);           /* global requests eg. manual feed */
                    428:     setencoding(fontencoding);
                    429:     fprintf(stdout, "setup\n");
                    430: 
                    431:     if ( formsperpage > 1 )  {
                    432:        if ( cat(formfile) == FALSE )
                    433:            error(FATAL, "can't read %s", formfile);
                    434:        fprintf(stdout, "%d setupforms\n", formsperpage);
                    435:     }  /* End if */
                    436: 
                    437:     fprintf(stdout, "%s", ENDSETUP);
                    438: 
                    439: }   /* End of setup */
                    440: 
                    441: /*****************************************************************************/
                    442: 
                    443: arguments()
                    444: 
                    445: {
                    446: 
                    447: /*
                    448:  *
                    449:  * Makes sure all the non-option command line arguments are processed. If we get
                    450:  * here and there aren't any arguments left, or if '-' is one of the input files
                    451:  * we'll process stdin.
                    452:  *
                    453:  */
                    454: 
                    455:     fp_in = stdin;
                    456: 
                    457:     if ( argc < 1 )
                    458:        text();
                    459:     else {                             /* at least one argument is left */
                    460:        while ( argc > 0 )  {
                    461:            if ( strcmp(*argv, "-") == 0 )
                    462:                fp_in = stdin;
                    463:            else if ( (fp_in = fopen(*argv, "r")) == NULL )
                    464:                error(FATAL, "can't open %s", *argv);
                    465:            text();
                    466:            if ( fp_in != stdin )
                    467:                fclose(fp_in);
                    468:            argc--;
                    469:            argv++;
                    470:        }   /* End while */
                    471:     }   /* End else */
                    472: 
                    473: }   /* End of arguments */
                    474: 
                    475: /*****************************************************************************/
                    476: 
                    477: done()
                    478: 
                    479: {
                    480: 
                    481: /*
                    482:  *
                    483:  * Finished with all the input files, so mark the end of the pages, make sure the
                    484:  * last page is printed, and restore the initial environment.
                    485:  *
                    486:  */
                    487: 
                    488:     fprintf(stdout, "%s", TRAILER);
                    489:     fprintf(stdout, "done\n");
                    490:     fprintf(stdout, "%s %s\n", DOCUMENTFONTS, fontname);
                    491:     fprintf(stdout, "%s %d\n", PAGES, printed);
                    492: 
                    493: }   /* End of done */
                    494: 
                    495: /*****************************************************************************/
                    496: 
                    497: account()
                    498: 
                    499: {
                    500: 
                    501: /*
                    502:  *
                    503:  * Writes an accounting record to *fp_acct provided it's not NULL. Accounting
                    504:  * is requested using the -A or -J options.
                    505:  *
                    506:  */
                    507: 
                    508:     if ( fp_acct != NULL )
                    509:        fprintf(fp_acct, " print %d\n copies %d\n", printed, copies);
                    510: 
                    511: }   /* End of account */
                    512: 
                    513: /*****************************************************************************/
                    514: 
                    515: text()
                    516: 
                    517: {
                    518: 
                    519:     int                ch;                     /* next input character */
                    520: 
                    521: /*
                    522:  *
                    523:  * Translates the next input file into PostScript. The redirect(-1) call forces
                    524:  * the initial output to go to /dev/null - so the stuff formfeed() does at the
                    525:  * end of each page doesn't go to stdout.
                    526:  *
                    527:  */
                    528: 
                    529:     redirect(-1);                      /* get ready for the first page */
                    530:     formfeed();                                /* force PAGE comment etc. */
                    531:     inittabs();
                    532: 
                    533:     while ( (ch = getc(fp_in)) != EOF )
                    534:        switch ( ch )  {
                    535:            case '\010':                /* backspace */
                    536:                    backspace();
                    537:                    break;
                    538: 
                    539:            case '\011':                /* horizontal tab */
                    540:                    htab();
                    541:                    break;
                    542: 
                    543:            case '\012':                /* new line */
                    544:                    linefeed();
                    545:                    break;
                    546: 
                    547:            case '\013':                /* vertical tab */
                    548:                    vtab();
                    549:                    break;
                    550: 
                    551:            case '\014':                /* form feed */
                    552:                    formfeed();
                    553:                    break;
                    554: 
                    555:            case '\015':                /* carriage return */
                    556:                    carriage();
                    557:                    break;
                    558: 
                    559:            case '\016':                /* extended character set - SO */
                    560:                    break;
                    561: 
                    562:            case '\017':                /* extended character set - SI */
                    563:                    break;
                    564: 
                    565:            case '\031':                /* next char from supplementary set */
                    566:                    break;
                    567: 
                    568:            case '\033':                /* 2 or 3 byte escape sequence */
                    569:                    escape();
                    570:                    break;
                    571: 
                    572:            default:
                    573:                    oput(ch);
                    574:                    break;
                    575:        }   /* End switch */
                    576: 
                    577:     formfeed();                                /* next file starts on a new page? */
                    578: 
                    579: }   /* End of text */
                    580: 
                    581: /*****************************************************************************/
                    582: 
                    583: inittabs()
                    584: 
                    585: {
                    586: 
                    587:     int                i;                      /* loop index */
                    588: 
                    589: /*
                    590:  *
                    591:  * Initializes the horizontal and vertical tab arrays. The way tabs are handled is
                    592:  * quite inefficient and may not work for all initial hmi or vmi values.
                    593:  *
                    594:  */
                    595: 
                    596:     for ( i = 0; i < COLUMNS; i++ )
                    597:        htabstops[i] = ((i % 8) == 0) ? ON : OFF;
                    598: 
                    599:     for ( i = 0; i < ROWS; i++ )
                    600:        vtabstops[i] = ((i * ovmi) > BOTTOMMARGIN) ? ON : OFF;
                    601: 
                    602: }   /* End of inittabs */
                    603: 
                    604: /*****************************************************************************/
                    605: 
                    606: cleartabs()
                    607: 
                    608: {
                    609: 
                    610:     int                i;                      /* loop index */
                    611: 
                    612: /*
                    613:  *
                    614:  * Clears all horizontal and vertical tab stops.
                    615:  *
                    616:  */
                    617: 
                    618:     for ( i = 0; i < ROWS; i++ )
                    619:        htabstops[i] = OFF;
                    620: 
                    621:     for ( i = 0; i < COLUMNS; i++ )
                    622:        vtabstops[i] = OFF;
                    623: 
                    624: }   /* End of cleartabs */
                    625: 
                    626: /*****************************************************************************/
                    627: 
                    628: formfeed()
                    629: 
                    630: {
                    631: 
                    632: /*
                    633:  *
                    634:  * Called whenever we've finished with the last page and want to get ready for the
                    635:  * next one. Also used at the beginning and end of each input file, so we have to
                    636:  * be careful about what's done. I've added a simple test before the showpage that
                    637:  * should eliminate the extra blank page that was put out at the end of many jobs,
                    638:  * but the PAGES comments may be wrong.
                    639:  *
                    640:  */
                    641: 
                    642:     if ( fp_out == stdout )            /* count the last page */
                    643:        printed++;
                    644: 
                    645:     endline();                         /* print the last line */
                    646: 
                    647:     fprintf(fp_out, "cleartomark\n");
                    648:     if ( feof(fp_in) == 0 || markedpage == TRUE )
                    649:        fprintf(fp_out, "showpage\n");
                    650:     fprintf(fp_out, "saveobj restore\n");
                    651:     fprintf(fp_out, "%s %d %d\n", ENDPAGE, page, printed);
                    652: 
                    653:     if ( ungetc(getc(fp_in), fp_in) == EOF )
                    654:        redirect(-1);
                    655:     else redirect(++page);
                    656: 
                    657:     fprintf(fp_out, "%s %d %d\n", PAGE, page, printed+1);
                    658:     fprintf(fp_out, "/saveobj save def\n");
                    659:     fprintf(fp_out, "mark\n");
                    660:     writerequest(printed+1, fp_out);
                    661:     fprintf(fp_out, "%d pagesetup\n", printed+1);
                    662: 
                    663:     vgoto(topmargin);
                    664:     hgoto(leftmargin);
                    665: 
                    666:     markedpage = FALSE;
                    667: 
                    668: }   /* End of formfeed */
                    669: 
                    670: /*****************************************************************************/
                    671: 
                    672: linefeed()
                    673: 
                    674: {
                    675: 
                    676:     int                line = 0;               /* current line - based on ovmi */
                    677: 
                    678: /*
                    679:  *
                    680:  * Adjust our current vertical position. If we've passed the bottom of the page
                    681:  * or exceeded the number of lines per page, print it and go to the upper left
                    682:  * corner of the next page. This routine is also called from carriage() if crislf
                    683:  * is ON.
                    684:  *
                    685:  */
                    686: 
                    687:     vmot(vmi);
                    688: 
                    689:     if ( lfiscr == ON )
                    690:        hgoto(leftmargin);
                    691: 
                    692:     if ( linespp > 0 )                 /* means something so see where we are */
                    693:        line = vpos / ovmi + 1;
                    694: 
                    695:     if ( vpos > bottommargin || line > linespp )
                    696:        formfeed();
                    697: 
                    698: }   /* End of linefeed */
                    699: 
                    700: /*****************************************************************************/
                    701: 
                    702: carriage()
                    703: 
                    704: {
                    705: 
                    706: /*
                    707:  *
                    708:  * Handles carriage return character. If crislf is ON we'll generate a line feed
                    709:  * every time we get a carriage return character.
                    710:  *
                    711:  */
                    712: 
                    713:     if ( shadowprint == ON )           /* back to normal mode */
                    714:        changefont(fontname);
                    715: 
                    716:     advance = 1;
                    717:     shadowprint = OFF;
                    718: 
                    719:     hgoto(leftmargin);
                    720: 
                    721:     if ( crislf == ON )
                    722:        linefeed();
                    723: 
                    724: }   /* End of carriage */
                    725: 
                    726: /*****************************************************************************/
                    727: 
                    728: htab()
                    729: 
                    730: {
                    731: 
                    732:     int                col;                    /* 'column' we'll be at next */
                    733:     int                i;                      /* loop index */
                    734: 
                    735: /*
                    736:  *
                    737:  * Tries to figure out where the next tab stop is. Wasn't positive about this
                    738:  * one, since hmi can change. I'll assume columns are determined by the original
                    739:  * value of hmi. That fixes them on the page, which seems to make more sense than
                    740:  * letting them float all over the place.
                    741:  *
                    742:  */
                    743: 
                    744:     endline();
                    745: 
                    746:     col = hpos/ohmi + 1;
                    747:     for ( i = col; i < ROWS; i++ )
                    748:        if ( htabstops[i] == ON )  {
                    749:            col = i;
                    750:            break;
                    751:        }   /* End if */
                    752: 
                    753:     hgoto(col * ohmi);
                    754:     lastx = hpos;
                    755: 
                    756: }   /* End of htab */
                    757: 
                    758: /*****************************************************************************/
                    759: 
                    760: vtab()
                    761: 
                    762: {
                    763: 
                    764:     int                line;                   /* line we'll be at next */
                    765:     int                i;                      /* loop index */
                    766: 
                    767: /*
                    768:  *
                    769:  * Looks for the next vertical tab stop in the vtabstops[] array and moves to that
                    770:  * line. If we don't find a tab we'll just move down one line - shouldn't happen.
                    771:  *
                    772:  */
                    773: 
                    774:     endline();
                    775: 
                    776:     line = vpos/ovmi + 1;
                    777:     for ( i = line; i < COLUMNS; i++ )
                    778:        if ( vtabstops[i] == ON )  {
                    779:            line = i;
                    780:            break;
                    781:        }   /* End if */
                    782: 
                    783:     vgoto(line * ovmi);
                    784: 
                    785: }   /* End of vtab */
                    786: 
                    787: /*****************************************************************************/
                    788: 
                    789: backspace()
                    790: 
                    791: {
                    792: 
                    793: /*
                    794:  *
                    795:  * Moves backwards a distance equal to the current value of hmi, but don't go
                    796:  * past the left margin.
                    797:  *
                    798:  */
                    799: 
                    800:     endline();
                    801: 
                    802:     if ( hpos - leftmargin >= hmi )
                    803:        hmot(-hmi);
                    804:     else hgoto(leftmargin);            /* maybe just ignore the backspace?? */
                    805: 
                    806:     lastx = hpos;
                    807: 
                    808: }   /* End of backspace */
                    809: 
                    810: /*****************************************************************************/
                    811: 
                    812: escape()
                    813: 
                    814: {
                    815: 
                    816:     int                ch;                     /* control character */
                    817: 
                    818: /*
                    819:  *
                    820:  * Handles special codes that are expected to follow an escape character. The
                    821:  * initial escape character is followed by one or two bytes.
                    822:  *
                    823:  */
                    824: 
                    825:     switch ( ch = getc(fp_in) ) {
                    826:        case 'T':                       /* top margin */
                    827:                topmargin = vpos;
                    828:                break;
                    829: 
                    830:        case 'L':                       /* bottom margin */
                    831:                bottommargin = vpos;
                    832:                break;
                    833: 
                    834:        case 'C':                       /* clear top and bottom margins */
                    835:                bottommargin = BOTTOMMARGIN;
                    836:                topmargin = TOPMARGIN;
                    837:                break;
                    838: 
                    839:        case '9':                       /* left margin */
                    840:                leftmargin = hpos;
                    841:                break;
                    842: 
                    843:        case '0':                       /* right margin */
                    844:                rightmargin = hpos;
                    845:                break;
                    846: 
                    847:        case '1':                       /* set horizontal tab */
                    848:                htabstops[hpos/ohmi] = ON;
                    849:                break;
                    850: 
                    851:        case '8':                       /* clear horizontal tab at hpos */
                    852:                htabstops[hpos/ohmi] = OFF;
                    853:                break;
                    854: 
                    855:        case '-':                       /* set vertical tab */
                    856:                vtabstops[vpos/ovmi] = ON;
                    857:                break;
                    858: 
                    859:        case '2':                       /* clear all tabs */
                    860:                cleartabs();
                    861:                break;
                    862: 
                    863:        case '\014':                    /* set lines per page */
                    864:                linespp = getc(fp_in);
                    865:                break;
                    866: 
                    867:        case '\037':                    /* set hmi to next byte minus 1 */
                    868:                hmi = HSCALE * (getc(fp_in) - 1);
                    869:                break;
                    870: 
                    871:        case 'S':                       /* reset hmi to default */
                    872:                hmi = ohmi;
                    873:                break;
                    874: 
                    875:        case '\011':                    /* move to column given by next byte */
                    876:                hgoto((getc(fp_in)-1) * ohmi);
                    877:                break;
                    878: 
                    879:        case '?':                       /* do carriage return after line feed */
                    880:                lfiscr = ON;
                    881:                break;
                    882: 
                    883:        case '!':                       /* don't generate carriage return */
                    884:                lfiscr = OFF;
                    885:                break;
                    886: 
                    887:        case '5':                       /* forward print mode */
                    888:                advance = 1;
                    889:                break;
                    890: 
                    891:        case '6':                       /* backward print mode */
                    892:                advance = -1;
                    893:                break;
                    894: 
                    895:        case '\036':                    /* set vmi to next byte minus 1 */
                    896:                vmi = VSCALE * (getc(fp_in) - 1);
                    897:                break;
                    898: 
                    899:        case '\013':                    /* move to line given by next byte */
                    900:                vgoto((getc(fp_in)-1) * ovmi);
                    901:                break;
                    902: 
                    903:        case 'U':                       /* positive half line feed */
                    904:                vmot(vmi/2);
                    905:                break;
                    906: 
                    907:        case 'D':                       /* negative half line feed */
                    908:                vmot(-vmi/2);
                    909:                break;
                    910: 
                    911:        case '\012':                    /* negative line feed */
                    912:                vmot(-vmi);
                    913:                break;
                    914: 
                    915:        case '\015':                    /* clear all margins */
                    916:                bottommargin = BOTTOMMARGIN;
                    917:                topmargin = TOPMARGIN;
                    918:                leftmargin = BOTTOMMARGIN;
                    919:                rightmargin = RIGHTMARGIN;
                    920:                break;
                    921: 
                    922:        case 'E':                       /* auto underscore - use italic font */
                    923:                changefont("/Courier-Oblique");
                    924:                break;
                    925: 
                    926:        case 'R':                       /* disable auto underscore */
                    927:                changefont(fontname);
                    928:                break;
                    929: 
                    930:        case 'O':                       /* bold/shadow printing */
                    931:        case 'W':
                    932:                changefont("/Courier-Bold");
                    933:                shadowprint = ON;
                    934:                break;
                    935: 
                    936:        case '&':                       /* disable bold printing */
                    937:                changefont(fontname);
                    938:                shadowprint = OFF;
                    939:                break;
                    940: 
                    941:        case '/':                       /* ignored 2 byte escapes */
                    942:        case '\\':
                    943:        case '<':
                    944:        case '>':
                    945:        case '%':
                    946:        case '=':
                    947:        case '.':
                    948:        case '4':
                    949:        case 'A':
                    950:        case 'B':
                    951:        case 'M':
                    952:        case 'N':
                    953:        case 'P':
                    954:        case 'Q':
                    955:        case 'X':
                    956:        case '\010':
                    957:                break;
                    958: 
                    959:        case ',':                       /* ignored 3 byte escapes */
                    960:        case '\016':
                    961:        case '\021':
                    962:                getc(fp_in);
                    963:                break;
                    964: 
                    965:        case '3':                       /* graphics mode - should quit! */
                    966:        case '7':
                    967:        case 'G':
                    968:        case 'V':
                    969:        case 'Y':
                    970:        case 'Z':
                    971:                error(FATAL, "graphics mode is not implemented");
                    972:                break;
                    973: 
                    974:        default:
                    975:                error(FATAL, "missing case for escape o%o\n", ch);
                    976:                break;
                    977:     }  /* End switch */
                    978: 
                    979: }   /* End of escape */
                    980: 
                    981: /*****************************************************************************/
                    982: 
                    983: vmot(n)
                    984: 
                    985:     int                n;                      /* move this far vertically */
                    986: 
                    987: {
                    988: 
                    989: /*
                    990:  *
                    991:  * Move vertically n units from where we are.
                    992:  *
                    993:  */
                    994: 
                    995:     vpos += n;
                    996: 
                    997: }   /* End of vmot */
                    998: 
                    999: /*****************************************************************************/
                   1000: 
                   1001: vgoto(n)
                   1002: 
                   1003:     int                n;                      /* new vertical position */
                   1004: 
                   1005: {
                   1006: 
                   1007: /*
                   1008:  *
                   1009:  * Moves to absolute vertical position n.
                   1010:  *
                   1011:  */
                   1012: 
                   1013:     vpos = n;
                   1014: 
                   1015: }   /* End of vgoto */
                   1016: 
                   1017: /*****************************************************************************/
                   1018: 
                   1019: hmot(n)
                   1020: 
                   1021:     int                n;                      /* move this horizontally */
                   1022: 
                   1023: {
                   1024: 
                   1025: /*
                   1026:  *
                   1027:  * Moves horizontally n units from our current position.
                   1028:  *
                   1029:  */
                   1030: 
                   1031:     hpos += n * advance;
                   1032: 
                   1033:     if ( hpos < leftmargin )
                   1034:        hpos = leftmargin;
                   1035: 
                   1036: }   /* End of hmot */
                   1037: 
                   1038: /*****************************************************************************/
                   1039: 
                   1040: hgoto(n)
                   1041: 
                   1042:     int                n;                      /* go to this horizontal position */
                   1043: 
                   1044: {
                   1045: 
                   1046: /*
                   1047:  *
                   1048:  * Moves to absolute horizontal position n.
                   1049:  *
                   1050:  */
                   1051: 
                   1052:     hpos = n;
                   1053: 
                   1054: }   /* End of hgoto */
                   1055: 
                   1056: /*****************************************************************************/
                   1057: 
                   1058: changefont(name)
                   1059: 
                   1060:     char       *name;
                   1061: 
                   1062: {
                   1063: 
                   1064: /*
                   1065:  *
                   1066:  * Changes the current font. Used to get in and out of auto underscore and bold
                   1067:  * printing.
                   1068:  *
                   1069:  */
                   1070: 
                   1071:     endline();
                   1072:     fprintf(fp_out, "%s f\n", name);
                   1073: 
                   1074: }   /* End of changefont */
                   1075: 
                   1076: /*****************************************************************************/
                   1077: 
                   1078: startline()
                   1079: 
                   1080: {
                   1081: 
                   1082: /*
                   1083:  *
                   1084:  * Called whenever we want to be certain we're ready to start pushing characters
                   1085:  * into an open string on the stack. If stringcount is positive we've already
                   1086:  * started, so there's nothing to do. The first string starts in column 1.
                   1087:  *
                   1088:  */
                   1089: 
                   1090:     if ( stringcount < 1 )  {
                   1091:        putc('(', fp_out);
                   1092:        stringstart = lastx = hpos;
                   1093:        lasty = vpos;
                   1094:        lasthmi = hmi;
                   1095:        lastc = -1;
                   1096:        prevx = -1;
                   1097:        stringcount = 1;
                   1098:     }  /* End if */
                   1099: 
                   1100: }   /* End of startline */
                   1101: 
                   1102: /*****************************************************************************/
                   1103: 
                   1104: endline()
                   1105: 
                   1106: {
                   1107: 
                   1108: /*
                   1109:  *
                   1110:  * Generates a call to the PostScript procedure that processes the text on the
                   1111:  * the stack - provided stringcount is positive.
                   1112:  *
                   1113:  */
                   1114: 
                   1115:     if ( stringcount > 0 )
                   1116:        fprintf(fp_out, ")%d %d %d t\n", stringstart, lasty, lasthmi);
                   1117: 
                   1118:     stringcount = 0;
                   1119: 
                   1120: }   /* End of endline */
                   1121: 
                   1122: /*****************************************************************************/
                   1123: 
                   1124: endstring()
                   1125: 
                   1126: {
                   1127: 
                   1128: /*
                   1129:  *
                   1130:  * Takes the string we've been working on and adds it to the output file. Called
                   1131:  * when we need to adjust our horizontal position before starting a new string.
                   1132:  * Also called from endline() when we're done with the current line.
                   1133:  *
                   1134:  */
                   1135: 
                   1136:     if ( stringcount > 0 )  {
                   1137:        fprintf(fp_out, ")%d(", stringstart);
                   1138:        lastx = stringstart = hpos;
                   1139:        stringcount++;
                   1140:     }  /* End if */
                   1141: 
                   1142: }   /* End of endstring */
                   1143: 
                   1144: /*****************************************************************************/
                   1145: 
                   1146: oput(ch)
                   1147: 
                   1148:     int                ch;                     /* next output character */
                   1149: 
                   1150: {
                   1151: 
                   1152: /*
                   1153:  *
                   1154:  * Responsible for adding all printing characters from the input file to the
                   1155:  * open string on top of the stack. The only other characters that end up in
                   1156:  * that string are the quotes required for special characters. Reverse printing
                   1157:  * mode hasn't been tested but it should be close. hpos and lastx should disagree
                   1158:  * each time (except after startline() does something), and that should force a
                   1159:  * call to endstring() for every character.
                   1160:  *
                   1161:  */
                   1162: 
                   1163:     if ( stringcount > 100 )           /* don't put too much on the stack */
                   1164:        endline();
                   1165: 
                   1166:     if ( vpos != lasty )
                   1167:        endline();
                   1168: 
                   1169:     if ( advance == -1 )               /* for reverse printing - move first */
                   1170:        hmot(hmi);
                   1171: 
                   1172:     startline();
                   1173: 
                   1174:     if ( lastc != ch || hpos != prevx )  {
                   1175:        if ( lastx != hpos )
                   1176:            endstring();
                   1177: 
                   1178:        if ( isascii(ch) && isprint(ch) ) {
                   1179:            if ( ch == '\\' || ch == '(' || ch == ')' )
                   1180:                putc('\\', fp_out);
                   1181:            putc(ch, fp_out);
                   1182:        } else fprintf(fp_out, "\\%.3o", ch & 0377);
                   1183: 
                   1184:        lastc = ch;
                   1185:        prevx = hpos;
                   1186:        lastx += lasthmi;
                   1187:     }  /* End if */
                   1188: 
                   1189:     if ( advance != -1 )
                   1190:        hmot(hmi);
                   1191: 
                   1192:     markedpage = TRUE;
                   1193: 
                   1194: }   /* End of oput */
                   1195: 
                   1196: /*****************************************************************************/
                   1197: 
                   1198: redirect(pg)
                   1199: 
                   1200:     int                pg;                     /* next page we're printing */
                   1201: 
                   1202: {
                   1203: 
                   1204:     static FILE        *fp_null = NULL;        /* if output is turned off */
                   1205: 
                   1206: /*
                   1207:  *
                   1208:  * If we're not supposed to print page pg, fp_out will be directed to /dev/null,
                   1209:  * otherwise output goes to stdout.
                   1210:  *
                   1211:  */
                   1212: 
                   1213:     if ( pg >= 0 && in_olist(pg) == ON )
                   1214:        fp_out = stdout;
                   1215:     else if ( (fp_out = fp_null) == NULL )
                   1216:        fp_out = fp_null = fopen("/dev/null", "w");
                   1217: 
                   1218: }   /* End of redirect */
                   1219: 
                   1220: /*****************************************************************************/
                   1221: 

unix.superglobalmegacorp.com

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