Annotation of researchv10no/cmd/post.src/postdaisy/postdaisy.c, revision 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.