Annotation of researchv10no/cmd/post.src/posttek/posttek.c, revision 1.1

1.1     ! root        1: /*
        !             2:  *
        !             3:  * posttek - PostScript translator for tektronix 4014 files
        !             4:  *
        !             5:  * A program that can be used to translate tektronix 4014 files into PostScript.
        !             6:  * Most of the code was borrowed from the tektronix 4014 emulator that was written
        !             7:  * for DMDs. Things have been cleaned up some, but there's still plently that
        !             8:  * could be done.
        !             9:  *
        !            10:  * The PostScript prologue is copied from *prologue before any of the input files
        !            11:  * are translated. The program expects that the following PostScript procedures
        !            12:  * are defined in that file:
        !            13:  *
        !            14:  *     setup
        !            15:  *
        !            16:  *       mark ... setup -
        !            17:  *
        !            18:  *         Handles special initialization stuff that depends on how the program
        !            19:  *         was called. Expects to find a mark followed by key/value pairs on the
        !            20:  *         stack. The def operator is applied to each pair up to the mark, then
        !            21:  *         the default state is set up.
        !            22:  *
        !            23:  *     pagesetup
        !            24:  *
        !            25:  *       page pagesetup -
        !            26:  *
        !            27:  *         Does whatever is needed to set things up for the next page. Expects
        !            28:  *         to find the current page number on the stack.
        !            29:  *
        !            30:  *     v
        !            31:  *
        !            32:  *       mark dx1 dy1 ... dxn dyn x y v mark
        !            33:  *
        !            34:  *         Draws the vector described by the numbers on the stack. The top two
        !            35:  *         numbers are the starting point. The rest are relative displacements
        !            36:  *         from the preceeding point. Must make sure we don't put too much on
        !            37:  *         the stack!
        !            38:  *
        !            39:  *     t
        !            40:  *
        !            41:  *       x y string t -
        !            42:  *
        !            43:  *         Prints the string that's on the top of the stack starting at point
        !            44:  *         (x, y).
        !            45:  *
        !            46:  *     p
        !            47:  *
        !            48:  *       x y p -
        !            49:  *
        !            50:  *         Marks the point (x, y) with a circle whose radius varies with the
        !            51:  *         current intensity setting.
        !            52:  *
        !            53:  *     i
        !            54:  *
        !            55:  *       percent focus i -
        !            56:  *
        !            57:  *         Changes the size of the circle used to mark individual points to
        !            58:  *         percent of maximum for focused mode (focus=1) or defocused mode
        !            59:  *         (focus=0). The implementation leaves much to be desired!
        !            60:  *
        !            61:  *     l
        !            62:  *
        !            63:  *       mark array l mark
        !            64:  *
        !            65:  *         Set the line drawing mode according to the description given in array.
        !            66:  *         The arrays that describe the different line styles are declared in
        !            67:  *         STYLES (file posttek.h). The array really belongs in the prologue!
        !            68:  *
        !            69:  *     w
        !            70:  *
        !            71:  *       n w -
        !            72:  *
        !            73:  *         Adjusts the line width for vector drawing. Used to select normal (n=0)
        !            74:  *         or defocused (n=1) mode.
        !            75:  *
        !            76:  *     f
        !            77:  *
        !            78:  *       size f -
        !            79:  *
        !            80:  *         Changes the size of the font that's used to print characters in alpha
        !            81:  *         mode. size is the tektronix character width and is used to choose an
        !            82:  *         appropriate point size in the current font.
        !            83:  *
        !            84:  *     done
        !            85:  *
        !            86:  *       done
        !            87:  *
        !            88:  *         Makes sure the last page is printed. Only needed when we're printing
        !            89:  *         more than one page on each sheet of paper.
        !            90:  *
        !            91:  * The default line width is zero, which forces lines to be one pixel wide. That
        !            92:  * works well on 'write to black' engines but won't be right for 'write to white'
        !            93:  * engines. The line width can be changed using the -w option, or you can change
        !            94:  * the initialization of linewidth in the prologue.
        !            95:  *
        !            96:  * Many default values, like the magnification and orientation, are defined in 
        !            97:  * the prologue, which is where they belong. If they're changed (by options), an
        !            98:  * appropriate definition is made after the prologue is added to the output file.
        !            99:  * The -P option passes arbitrary PostScript through to the output file. Among
        !           100:  * other things it can be used to set (or change) values that can't be accessed by
        !           101:  * other options.
        !           102:  *
        !           103:  */
        !           104: 
        !           105: #include <stdio.h>
        !           106: #include <signal.h>
        !           107: #include <fcntl.h> 
        !           108: 
        !           109: #include "comments.h"                  /* PostScript file structuring comments */
        !           110: #include "gen.h"                       /* general purpose definitions */
        !           111: #include "path.h"                      /* for the prologue */
        !           112: #include "ext.h"                       /* external variable definitions */
        !           113: #include "posttek.h"                   /* control codes and other definitions */
        !           114: 
        !           115: char   *optnames = "a:c:f:m:n:o:p:w:x:y:A:C:E:J:L:P:R:DI";
        !           116: 
        !           117: char   *prologue = POSTTEK;            /* default PostScript prologue */
        !           118: char   *formfile = FORMFILE;           /* stuff for multiple pages per sheet */
        !           119: 
        !           120: int    formsperpage = 1;               /* page images on each piece of paper */
        !           121: int    copies = 1;                     /* and this many copies of each sheet */
        !           122: 
        !           123: int    charheight[] = CHARHEIGHT;      /* height */
        !           124: int    charwidth[] = CHARWIDTH;        /* and width arrays for tek characters */
        !           125: int    tekfont = TEKFONT;              /* index into charheight[] and charwidth[] */
        !           126: 
        !           127: char   intensity[] = INTENSITY;        /* special point intensity array */
        !           128: char   *styles[] = STYLES;             /* description of line styles */
        !           129: int    linestyle = 0;                  /* index into styles[] */
        !           130: int    linetype = 0;                   /* 0 for normal, 1 for defocused */
        !           131: 
        !           132: int    dispmode = ALPHA;               /* current tektronix state */
        !           133: int    points = 0;                     /* points making up the current vector */
        !           134: int    characters = 0;                 /* characters waiting to be printed */
        !           135: int    pen = UP;                       /* just for point plotting */
        !           136: int    margin = 0;                     /* left edge - ALPHA state */
        !           137: 
        !           138: Point  cursor;                         /* should be current cursor position */
        !           139: 
        !           140: Fontmap        fontmap[] = FONTMAP;            /* for translating font names */
        !           141: char   *fontname = "Courier";          /* use this PostScript font */
        !           142: 
        !           143: int    page = 0;                       /* page we're working on */
        !           144: int    printed = 0;                    /* printed this many pages */
        !           145: 
        !           146: FILE   *fp_in;                         /* read from this file */
        !           147: FILE   *fp_out = stdout;               /* and write stuff here */
        !           148: FILE   *fp_acct = NULL;                /* for accounting data */
        !           149: 
        !           150: /*****************************************************************************/
        !           151: 
        !           152: main(agc, agv)
        !           153: 
        !           154:     int                agc;
        !           155:     char       *agv[];
        !           156: 
        !           157: {
        !           158: 
        !           159: /*
        !           160:  *
        !           161:  * A simple program that can be used to translate tektronix 4014 files into
        !           162:  * PostScript. Most of the code was taken from the DMD tektronix 4014 emulator,
        !           163:  * although things have been cleaned up some.
        !           164:  *
        !           165:  */
        !           166: 
        !           167:     argv = agv;                                /* so everyone can use them */
        !           168:     argc = agc;
        !           169: 
        !           170:     prog_name = argv[0];               /* just for error messages */
        !           171: 
        !           172:     init_signals();                    /* sets up interrupt handling */
        !           173:     header();                          /* PostScript header comments */
        !           174:     options();                         /* handle the command line options */
        !           175:     setup();                           /* for PostScript */
        !           176:     arguments();                       /* followed by each input file */
        !           177:     done();                            /* print the last page etc. */
        !           178:     account();                         /* job accounting data */
        !           179: 
        !           180:     exit(x_stat);                      /* nothing could be wrong */
        !           181: 
        !           182: }   /* End of main */
        !           183: 
        !           184: /*****************************************************************************/
        !           185: 
        !           186: init_signals()
        !           187: 
        !           188: {
        !           189: 
        !           190: /*
        !           191:  *
        !           192:  * Make sure we handle interrupts.
        !           193:  *
        !           194:  */
        !           195: 
        !           196:     if ( signal(SIGINT, interrupt) == SIG_IGN )  {
        !           197:        signal(SIGINT, SIG_IGN);
        !           198:        signal(SIGQUIT, SIG_IGN);
        !           199:        signal(SIGHUP, SIG_IGN);
        !           200:     } else {
        !           201:        signal(SIGHUP, interrupt);
        !           202:        signal(SIGQUIT, interrupt);
        !           203:     }   /* End else */
        !           204: 
        !           205:     signal(SIGTERM, interrupt);
        !           206: 
        !           207: }   /* End of init_signals */
        !           208: 
        !           209: /*****************************************************************************/
        !           210: 
        !           211: header()
        !           212: 
        !           213: {
        !           214: 
        !           215:     int                ch;                     /* return value from getopt() */
        !           216:     int                old_optind = optind;    /* for restoring optind - should be 1 */
        !           217: 
        !           218: /*
        !           219:  *
        !           220:  * Scans the option list looking for things, like the prologue file, that we need
        !           221:  * right away but could be changed from the default. Doing things this way is an
        !           222:  * attempt to conform to Adobe's latest file structuring conventions. In particular
        !           223:  * they now say there should be nothing executed in the prologue, and they have
        !           224:  * added two new comments that delimit global initialization calls. Once we know
        !           225:  * where things really are we write out the job header, follow it by the prologue,
        !           226:  * and then add the ENDPROLOG and BEGINSETUP comments.
        !           227:  *
        !           228:  */
        !           229: 
        !           230:     while ( (ch = getopt(argc, argv, optnames)) != EOF )
        !           231:        if ( ch == 'L' )
        !           232:            prologue = optarg;
        !           233:        else if ( ch == '?' )
        !           234:            error(FATAL, "");
        !           235: 
        !           236:     optind = old_optind;               /* get ready for option scanning */
        !           237: 
        !           238:     fprintf(stdout, "%s", CONFORMING);
        !           239:     fprintf(stdout, "%s %s\n", VERSION, PROGRAMVERSION);
        !           240:     fprintf(stdout, "%s %s\n", DOCUMENTFONTS, ATEND);
        !           241:     fprintf(stdout, "%s %s\n", PAGES, ATEND);
        !           242:     fprintf(stdout, "%s", ENDCOMMENTS);
        !           243: 
        !           244:     if ( cat(prologue) == FALSE )
        !           245:        error(FATAL, "can't read %s", prologue);
        !           246: 
        !           247:     fprintf(stdout, "%s", ENDPROLOG);
        !           248:     fprintf(stdout, "%s", BEGINSETUP);
        !           249:     fprintf(stdout, "mark\n");
        !           250: 
        !           251: }   /* End of header */
        !           252: 
        !           253: /*****************************************************************************/
        !           254: 
        !           255: options()
        !           256: 
        !           257: {
        !           258: 
        !           259:     int                ch;                     /* value returned by getopt() */
        !           260: 
        !           261: /*
        !           262:  *
        !           263:  * Reads and processes the command line options. Added the -P option so arbitrary
        !           264:  * PostScript code can be passed through. Expect it could be useful for changing
        !           265:  * definitions in the prologue for which options have not been defined.
        !           266:  *
        !           267:  */
        !           268: 
        !           269:     while ( (ch = getopt(argc, argv, optnames)) != EOF )  {
        !           270:        switch ( ch )  {
        !           271:            case 'a':                   /* aspect ratio */
        !           272:                    fprintf(stdout, "/aspectratio %s def\n", optarg);
        !           273:                    break;
        !           274: 
        !           275:            case 'c':                   /* copies */
        !           276:                    copies = atoi(optarg);
        !           277:                    fprintf(stdout, "/#copies %s store\n", optarg);
        !           278:                    break;
        !           279: 
        !           280:            case 'f':                   /* use this PostScript font */
        !           281:                    fontname = get_font(optarg);
        !           282:                    fprintf(stdout, "/font /%s def\n", fontname);
        !           283:                    break;
        !           284: 
        !           285:            case 'm':                   /* magnification */
        !           286:                    fprintf(stdout, "/magnification %s def\n", optarg);
        !           287:                    break;
        !           288: 
        !           289:            case 'n':                   /* forms per page */
        !           290:                    formsperpage = atoi(optarg);
        !           291:                    fprintf(stdout, "%s %s\n", FORMSPERPAGE, optarg);
        !           292:                    fprintf(stdout, "/formsperpage %s def\n", optarg);
        !           293:                    break;
        !           294: 
        !           295:            case 'o':                   /* output page list */
        !           296:                    out_list(optarg);
        !           297:                    break;
        !           298: 
        !           299:            case 'p':                   /* landscape or portrait mode */
        !           300:                    if ( *optarg == 'l' )
        !           301:                        fprintf(stdout, "/landscape true def\n");
        !           302:                    else fprintf(stdout, "/landscape false def\n");
        !           303:                    break;
        !           304: 
        !           305:            case 'w':                   /* line width */
        !           306:                    fprintf(stdout, "/linewidth %s def\n", optarg);
        !           307:                    break;
        !           308: 
        !           309:            case 'x':                   /* shift horizontally */
        !           310:                    fprintf(stdout, "/xoffset %s def\n", optarg);
        !           311:                    break;
        !           312: 
        !           313:            case 'y':                   /* and vertically on the page */
        !           314:                    fprintf(stdout, "/yoffset %s def\n", optarg);
        !           315:                    break;
        !           316: 
        !           317:            case 'A':                   /* force job accounting */
        !           318:            case 'J':
        !           319:                    if ( (fp_acct = fopen(optarg, "a")) == NULL )
        !           320:                        error(FATAL, "can't open accounting file %s", optarg);
        !           321:                    break;
        !           322: 
        !           323:            case 'C':                   /* copy file straight to output */
        !           324:                    if ( cat(optarg) == FALSE )
        !           325:                        error(FATAL, "can't read %s", optarg);
        !           326:                    break;
        !           327: 
        !           328:            case 'E':                   /* text font encoding */
        !           329:                    fontencoding = optarg;
        !           330:                    break;
        !           331: 
        !           332:            case 'L':                   /* PostScript prologue file */
        !           333:                    prologue = optarg;
        !           334:                    break;
        !           335: 
        !           336:            case 'P':                   /* PostScript pass through */
        !           337:                    fprintf(stdout, "%s\n", optarg);
        !           338:                    break;
        !           339: 
        !           340:            case 'R':                   /* special global or page level request */
        !           341:                    saverequest(optarg);
        !           342:                    break;
        !           343: 
        !           344:            case 'D':                   /* debug flag */
        !           345:                    debug = ON;
        !           346:                    break;
        !           347: 
        !           348:            case 'I':                   /* ignore FATAL errors */
        !           349:                    ignore = ON;
        !           350:                    break;
        !           351: 
        !           352:            case '?':                   /* don't know the option */
        !           353:                    error(FATAL, "");
        !           354:                    break;
        !           355: 
        !           356:            default:                    /* don't know what to do for ch */
        !           357:                    error(FATAL, "missing case for option %c", ch);
        !           358:                    break;
        !           359:        }   /* End switch */
        !           360:     }  /* End while */
        !           361: 
        !           362:     argc -= optind;
        !           363:     argv += optind;
        !           364: 
        !           365: }   /* End of options */
        !           366: 
        !           367: /*****************************************************************************/
        !           368: 
        !           369: char *get_font(name)
        !           370: 
        !           371:     char       *name;                  /* name the user asked for */
        !           372: 
        !           373: {
        !           374: 
        !           375:     int                i;                      /* for looking through fontmap[] */
        !           376: 
        !           377: /*
        !           378:  *
        !           379:  * Called from options() to map a user's font name into a legal PostScript name.
        !           380:  * If the lookup fails *name is returned to the caller. That should let you choose
        !           381:  * any PostScript font.
        !           382:  *
        !           383:  */
        !           384: 
        !           385:     for ( i = 0; fontmap[i].name != NULL; i++ )
        !           386:        if ( strcmp(name, fontmap[i].name) == 0 )
        !           387:            return(fontmap[i].val);
        !           388: 
        !           389:     return(name);
        !           390: 
        !           391: }   /* End of get_font */
        !           392: 
        !           393: /*****************************************************************************/
        !           394: 
        !           395: setup()
        !           396: 
        !           397: {
        !           398: 
        !           399: /*
        !           400:  *
        !           401:  * Handles things that must be done after the options are read but before the
        !           402:  * input files are processed.
        !           403:  *
        !           404:  */
        !           405: 
        !           406:     writerequest(0, stdout);           /* global requests eg. manual feed */
        !           407:     setencoding(fontencoding);
        !           408:     fprintf(stdout, "setup\n");
        !           409: 
        !           410:     if ( formsperpage > 1 )  {
        !           411:        if ( cat(formfile) == FALSE )
        !           412:            error(FATAL, "can't read %s", formfile);
        !           413:        fprintf(stdout, "%d setupforms\n", formsperpage);
        !           414:     }  /* End if */
        !           415: 
        !           416:     fprintf(stdout, "%s", ENDSETUP);
        !           417: 
        !           418: }   /* End of setup */
        !           419: 
        !           420: /*****************************************************************************/
        !           421: 
        !           422: arguments()
        !           423: 
        !           424: {
        !           425: 
        !           426: /*
        !           427:  *
        !           428:  * Makes sure all the non-option command line arguments are processed. If we get
        !           429:  * here and there aren't any arguments left, or if '-' is one of the input files
        !           430:  * we'll process stdin.
        !           431:  *
        !           432:  */
        !           433: 
        !           434:     if ( argc < 1 )
        !           435:        statemachine(fp_in = stdin);
        !           436:     else  {                            /* at least one argument is left */
        !           437:        while ( argc > 0 )  {
        !           438:            if ( strcmp(*argv, "-") == 0 )
        !           439:                fp_in = stdin;
        !           440:            else if ( (fp_in = fopen(*argv, "r")) == NULL )
        !           441:                error(FATAL, "can't open %s", *argv);
        !           442:            statemachine(fp_in);
        !           443:            if ( fp_in != stdin )
        !           444:                fclose(fp_in);
        !           445:            argc--;
        !           446:            argv++;
        !           447:        }   /* End while */
        !           448:     }   /* End else */
        !           449: 
        !           450: }   /* End of arguments */
        !           451: 
        !           452: /*****************************************************************************/
        !           453: 
        !           454: done()
        !           455: 
        !           456: {
        !           457: 
        !           458: /*
        !           459:  *
        !           460:  * Finished with all the input files, so mark the end of the pages with a TRAILER
        !           461:  * comment, make sure the last page prints, and add things like the PAGES comment
        !           462:  * that can only be determined after all the input files have been read.
        !           463:  *
        !           464:  */
        !           465: 
        !           466:     fprintf(stdout, "%s", TRAILER);
        !           467:     fprintf(stdout, "done\n");
        !           468:     fprintf(stdout, "%s %s\n", DOCUMENTFONTS, fontname);
        !           469:     fprintf(stdout, "%s %d\n", PAGES, printed);
        !           470: 
        !           471: }   /* End of done */
        !           472: 
        !           473: /*****************************************************************************/
        !           474: 
        !           475: account()
        !           476: 
        !           477: {
        !           478: 
        !           479: /*
        !           480:  *
        !           481:  * Writes an accounting record to *fp_acct provided it's not NULL. Accounting
        !           482:  * is requested using the -A or -J options.
        !           483:  *
        !           484:  */
        !           485: 
        !           486:     if ( fp_acct != NULL )
        !           487:        fprintf(fp_acct, " print %d\n copies %d\n", printed, copies);
        !           488: 
        !           489: }   /* End of account */
        !           490: 
        !           491: /*****************************************************************************/
        !           492: 
        !           493: statemachine(fp)
        !           494: 
        !           495:     FILE       *fp;                    /* used to set fp_in */
        !           496: 
        !           497: {
        !           498: 
        !           499: /*
        !           500:  *
        !           501:  * Controls the translation of the next input file. Tektronix states (dispmode)
        !           502:  * are typically changed in control() and esc().
        !           503:  *
        !           504:  */
        !           505: 
        !           506:     redirect(-1);                      /* get ready for the first page */
        !           507:     formfeed();
        !           508:     dispmode = RESET;
        !           509: 
        !           510:     while ( 1 )
        !           511:        switch ( dispmode )  {
        !           512:            case RESET:
        !           513:                    reset();
        !           514:                    break;
        !           515: 
        !           516:            case ALPHA:
        !           517:                    alpha();
        !           518:                    break;
        !           519: 
        !           520:            case GIN:
        !           521:                    gin();
        !           522:                    break;
        !           523: 
        !           524:            case GRAPH:
        !           525:                    graph();
        !           526:                    break;
        !           527: 
        !           528:            case POINT:
        !           529:            case SPECIALPOINT:
        !           530:                    point();
        !           531:                    break;
        !           532: 
        !           533:            case INCREMENTAL:
        !           534:                    incremental();
        !           535:                    break;
        !           536: 
        !           537:            case EXIT:
        !           538:                    formfeed();
        !           539:                    return;
        !           540:        }   /* End switch */
        !           541: 
        !           542: }   /* End of statemachine */
        !           543: 
        !           544: /*****************************************************************************/
        !           545: 
        !           546: reset()
        !           547: 
        !           548: {
        !           549: 
        !           550: /*
        !           551:  *
        !           552:  * Called to reset things, typically only at the beginning of each input file.
        !           553:  *
        !           554:  */
        !           555: 
        !           556:     tekfont = -1;
        !           557:     home();
        !           558:     setfont(TEKFONT);
        !           559:     setmode(ALPHA);
        !           560: 
        !           561: }   /* End of reset */
        !           562: 
        !           563: /*****************************************************************************/
        !           564: 
        !           565: alpha()
        !           566: 
        !           567: {
        !           568: 
        !           569:     int                c;                      /* next character */
        !           570:     int                x, y;                   /* cursor will be here when we're done */
        !           571: 
        !           572: /*
        !           573:  *
        !           574:  * Takes care of printing characters in the current font.
        !           575:  *
        !           576:  */
        !           577: 
        !           578:     if ( (c = nextchar()) == OUTMODED )
        !           579:        return;
        !           580: 
        !           581:     if ( (c < 040) && ((c = control(c)) <= 0) )
        !           582:        return;
        !           583: 
        !           584:     x = cursor.x;                      /* where the cursor is right now */
        !           585:     y = cursor.y;
        !           586: 
        !           587:     switch ( c )  {
        !           588:        case DEL:
        !           589:                return;
        !           590: 
        !           591:        case BS:
        !           592:                if ((x -= charwidth[tekfont]) < margin)
        !           593:                    x = TEKXMAX - charwidth[tekfont];
        !           594:                break;
        !           595: 
        !           596:        case NL:
        !           597:                y -= charheight[tekfont];
        !           598:                break;
        !           599: 
        !           600:        case CR:
        !           601:                x = margin;
        !           602:                break;
        !           603: 
        !           604:        case VT:
        !           605:                if ((y += charheight[tekfont]) >= TEKYMAX)
        !           606:                    y = 0;
        !           607:                break;
        !           608: 
        !           609:        case HT:
        !           610:        case ' ':
        !           611:        default:
        !           612:                if ( characters++ == 0 )
        !           613:                    fprintf(fp_out, "%d %d (", cursor.x, cursor.y);
        !           614:                switch ( c )  {
        !           615:                    case '(':
        !           616:                    case ')':
        !           617:                    case '\\':
        !           618:                        putc('\\', fp_out);
        !           619: 
        !           620:                    default:
        !           621:                        putc(c, fp_out);
        !           622:                }   /* End switch */
        !           623:                x += charwidth[tekfont];
        !           624:                move(x, y);
        !           625:                break;
        !           626:     }  /* End switch */
        !           627: 
        !           628:     if (x >= TEKXMAX) {
        !           629:        x = margin;
        !           630:        y -= charheight[tekfont];
        !           631:     }  /* End if */
        !           632: 
        !           633:     if (y < 0) {
        !           634:        y = TEKYMAX - charheight[tekfont];
        !           635:        x -= margin;
        !           636:        margin = (TEKXMAX/2) - margin;
        !           637:        if ((x += margin) > TEKXMAX)
        !           638:            x -= margin;
        !           639:     }  /* End if */
        !           640: 
        !           641:     if ( y != cursor.y || x != cursor.x )
        !           642:        text();
        !           643: 
        !           644:     move(x, y);
        !           645: 
        !           646: }   /* End of alpha */
        !           647: 
        !           648: /*****************************************************************************/
        !           649: 
        !           650: graph()
        !           651: 
        !           652: {
        !           653: 
        !           654:     int                        c;              /* next character */
        !           655:     int                        b;              /* for figuring out loy */
        !           656:     int                        x, y;           /* next point in the vector */
        !           657:     static int         hix, hiy;       /* upper */
        !           658:     static int         lox, loy;       /* and lower part of the address */
        !           659:     static int         extra;          /* for extended addressing */
        !           660: 
        !           661: /*
        !           662:  *
        !           663:  * Handles things when we're in GRAPH, POINT, or SPECIALPOINT mode.
        !           664:  *
        !           665:  */
        !           666: 
        !           667:     if ((c = nextchar()) < 040) {
        !           668:        control(c);
        !           669:        return;
        !           670:     }  /* End if */
        !           671: 
        !           672:     if ((c & 0140) == 040) {           /* new hiy */
        !           673:        hiy = c & 037;
        !           674:        do
        !           675:            if (((c = nextchar()) < 040) && ((c = control(c)) == OUTMODED))
        !           676:                return;
        !           677:        while (c == 0);
        !           678:     }  /* End if */
        !           679: 
        !           680:     if ((c & 0140) == 0140) {          /* new loy */
        !           681:        b = c & 037;
        !           682:        do
        !           683:            if (((c = nextchar()) < 040) && ((c = control(c)) == OUTMODED))
        !           684:                return;
        !           685:        while (c == 0);
        !           686:        if ((c & 0140) == 0140) {       /* no, it was extra */
        !           687:            extra = b;
        !           688:            loy = c & 037;
        !           689:            do
        !           690:                if (((c = nextchar()) < 040) && ((c = control(c)) == OUTMODED))
        !           691:                    return;
        !           692:            while (c == 0);
        !           693:        } else loy = b;
        !           694:     }  /* End if */
        !           695: 
        !           696:     if ((c & 0140) == 040) {           /* new hix */
        !           697:        hix = c & 037;
        !           698:        do
        !           699:            if (((c = nextchar()) < 040) && ((c = control(c)) == OUTMODED))
        !           700:                return;
        !           701:        while (c == 0);
        !           702:     }  /* End if */
        !           703: 
        !           704:     lox = c & 037;                     /* this should be lox */
        !           705:     if (extra & 020)
        !           706:        margin = TEKXMAX/2;
        !           707: 
        !           708:     x = (hix<<7) | (lox<<2) | (extra & 03);
        !           709:     y = (hiy<<7) | (loy<<2) | ((extra & 014)>>2);
        !           710: 
        !           711:     if ( points > 100 )  {             /* don't put too much on the stack */
        !           712:        draw();
        !           713:        points = 1;
        !           714:     }  /* End if */
        !           715: 
        !           716:     if ( points++ )
        !           717:        fprintf(fp_out, "%d %d\n", cursor.x - x, cursor.y - y);
        !           718: 
        !           719:     move(x, y);                                /* adjust the cursor */
        !           720: 
        !           721: }   /* End of graph */
        !           722: 
        !           723: /*****************************************************************************/
        !           724: 
        !           725: point()
        !           726: 
        !           727: {
        !           728: 
        !           729:     int                c;                      /* next input character */
        !           730: 
        !           731: /*
        !           732:  *
        !           733:  * Special point mode permits gray scaling by varying the size of the stored
        !           734:  * point, which is controlled by an intensity character that preceeds each point
        !           735:  * address.
        !           736:  *
        !           737:  */
        !           738: 
        !           739:     if ( dispmode == SPECIALPOINT )  {
        !           740:        if ( (c = nextchar()) < 040 || c > 0175 )
        !           741:            return(control(c));
        !           742: 
        !           743:        fprintf(fp_out, "%d %d i\n", intensity[c - ' '], c & 0100);
        !           744:     }  /* End if */
        !           745: 
        !           746:     graph();
        !           747:     draw();
        !           748: 
        !           749: }   /* End of point */
        !           750: 
        !           751: /*****************************************************************************/
        !           752: 
        !           753: incremental()
        !           754: 
        !           755: {
        !           756: 
        !           757:     int                c;                      /* for the next few characters */
        !           758:     int                x, y;                   /* cursor position when we're done */
        !           759: 
        !           760: /*
        !           761:  *
        !           762:  * Handles incremental plot mode. It's entered after the RS control code and is
        !           763:  * used to mark points relative to our current position. It's typically followed
        !           764:  * by one or two bytes that set the pen state and are used to increment the
        !           765:  * current position.
        !           766:  *
        !           767:  */
        !           768: 
        !           769:     if ( (c = nextchar()) == OUTMODED )
        !           770:        return;
        !           771: 
        !           772:     if ( (c < 040) && ((c = control(c)) <= 0) )
        !           773:        return;
        !           774: 
        !           775:     x = cursor.x;                      /* where we are right now */
        !           776:     y = cursor.y;
        !           777: 
        !           778:     if ( c & 060 )
        !           779:        pen = ( c & 040 ) ? UP : DOWN;
        !           780: 
        !           781:     if ( c & 04 ) y++;
        !           782:     if ( c & 010 ) y--;
        !           783:     if ( c & 01 ) x++;
        !           784:     if ( c & 02 ) x--;
        !           785: 
        !           786:     move(x, y);
        !           787: 
        !           788:     if ( pen == DOWN )  {
        !           789:        points = 1;
        !           790:        draw();
        !           791:     }  /* End if */
        !           792: 
        !           793: }   /* End of incremental */
        !           794: 
        !           795: /*****************************************************************************/
        !           796: 
        !           797: gin()
        !           798: 
        !           799: {
        !           800: 
        !           801: /*
        !           802:  *
        !           803:  * All we really have to do for GIN mode is make sure it's properly ended.
        !           804:  *
        !           805:  */
        !           806: 
        !           807:     control(nextchar());
        !           808: 
        !           809: }   /* End of gin */
        !           810: 
        !           811: /*****************************************************************************/
        !           812: 
        !           813: control(c)
        !           814: 
        !           815:     int                c;                      /* check this control character */
        !           816: 
        !           817: {
        !           818: 
        !           819: /*
        !           820:  *
        !           821:  * Checks character c and does special things, like mode changes, that depend
        !           822:  * not only on the character, but also on the current state. If the mode changed
        !           823:  * becuase of c, OUTMODED is returned to the caller. In all other cases the
        !           824:  * return value is c or 0, if c doesn't make sense in the current mode.
        !           825:  *
        !           826:  */
        !           827: 
        !           828:     switch ( c )  {
        !           829:        case BEL:
        !           830:                return(0);
        !           831: 
        !           832:        case BS:
        !           833:        case HT:
        !           834:        case VT:
        !           835:                return(dispmode == ALPHA ? c : 0);
        !           836: 
        !           837:        case CR:
        !           838:                if ( dispmode != ALPHA )  {
        !           839:                    setmode(ALPHA);
        !           840:                    ungetc(c, fp_in);
        !           841:                    return(OUTMODED);
        !           842:                } else return(c);
        !           843: 
        !           844:        case FS:
        !           845:                if ( (dispmode == ALPHA) || (dispmode == GRAPH) )  {
        !           846:                    setmode(POINT);
        !           847:                    return(OUTMODED);
        !           848:                }   /* End if */
        !           849:                return(0);
        !           850: 
        !           851:        case GS:
        !           852:                if ( (dispmode == ALPHA) || (dispmode == GRAPH) )  {
        !           853:                    setmode(GRAPH);
        !           854:                    return(OUTMODED);
        !           855:                }   /* End if */
        !           856:                return(0);
        !           857: 
        !           858:        case NL:
        !           859:                ungetc(CR, fp_in);
        !           860:                return(dispmode == ALPHA ? c : 0);
        !           861: 
        !           862:        case RS:
        !           863:                if ( dispmode != GIN )  {
        !           864:                    setmode(INCREMENTAL);
        !           865:                    return(OUTMODED);
        !           866:                }   /* End if */
        !           867:                return(0);
        !           868: 
        !           869:        case US:
        !           870:                if ( dispmode == ALPHA )
        !           871:                    return(0);
        !           872:                setmode(ALPHA);
        !           873:                return(OUTMODED);
        !           874: 
        !           875:        case ESC:
        !           876:                return(esc());
        !           877: 
        !           878:        case OUTMODED:
        !           879:                return(c);
        !           880: 
        !           881:        default:
        !           882:                return(c < 040 ? 0 : c);
        !           883:     }  /* End switch */
        !           884: 
        !           885: }   /* End of control */
        !           886: 
        !           887: /*****************************************************************************/
        !           888: 
        !           889: esc()
        !           890: 
        !           891: {
        !           892: 
        !           893:     int                c;                      /* next input character */
        !           894:     int                ignore;                 /* skip it if nonzero */
        !           895: 
        !           896: /*
        !           897:  *
        !           898:  * Handles tektronix escape code. Called from control() whenever an ESC character
        !           899:  * is found in the input file.
        !           900:  *
        !           901:  */
        !           902: 
        !           903:     do  {
        !           904:        c = nextchar();
        !           905:        ignore = 0;
        !           906:        switch ( c )  {
        !           907:            case CAN:
        !           908:                    return(0);
        !           909: 
        !           910:            case CR:
        !           911:                    ignore = 1;
        !           912:                    break;
        !           913: 
        !           914:            case ENQ:
        !           915:                    setmode(ALPHA);
        !           916:                    return(OUTMODED);
        !           917: 
        !           918:            case ETB:
        !           919:                    return(0);
        !           920: 
        !           921:            case FF:
        !           922:                    formfeed();
        !           923:                    setmode(ALPHA);
        !           924:                    return(OUTMODED);
        !           925: 
        !           926:            case FS:
        !           927:                    if ( (dispmode == INCREMENTAL) || ( dispmode == GIN) )
        !           928:                        return(0);
        !           929:                    setmode(SPECIALPOINT);
        !           930:                    return(OUTMODED);
        !           931: 
        !           932:            case SI:
        !           933:            case SO:
        !           934:                    return(0);
        !           935: 
        !           936:            case SUB:
        !           937:                    setmode(GIN);
        !           938:                    return(OUTMODED);
        !           939: 
        !           940:            case OUTMODED:
        !           941:                    return(OUTMODED);
        !           942: 
        !           943:            case '8':
        !           944:            case '9':
        !           945:            case ':':
        !           946:            case ';':
        !           947:                    setfont(c - '8');
        !           948:                    return(0);
        !           949: 
        !           950:            default:
        !           951:                    if ( c == '?' && dispmode == GRAPH )
        !           952:                        return(DEL);
        !           953:                    if ( (c<'`') || (c>'w') )
        !           954:                        break;
        !           955:                    c -= '`';
        !           956:                    if ( (c & 010) != linetype )
        !           957:                        fprintf(fp_out, "%d w\n", (linetype = (c & 010))/010);
        !           958:                    if ( ((c + 1) & 7) >= 6 )
        !           959:                        break;
        !           960:                    if ( (c + 1) & 7 )
        !           961:                        if ( (c & 7) != linestyle )  {
        !           962:                            linestyle = c & 7;
        !           963:                            setmode(dispmode);
        !           964:                            fprintf(fp_out, "%s l\n", styles[linestyle]);
        !           965:                        }   /* End if */
        !           966:                    return(0);
        !           967:        }   /* End switch */
        !           968: 
        !           969:     } while (ignore);
        !           970: 
        !           971:     return(0);
        !           972: 
        !           973: }   /* End of esc */
        !           974: 
        !           975: /*****************************************************************************/
        !           976: 
        !           977: move(x, y)
        !           978: 
        !           979:     int                x, y;                   /* move the cursor here */
        !           980: 
        !           981: {
        !           982: 
        !           983: /*
        !           984:  *
        !           985:  * Moves the cursor to the point (x, y).
        !           986:  *
        !           987:  */
        !           988: 
        !           989:     cursor.x = x;
        !           990:     cursor.y = y;
        !           991: 
        !           992: }   /* End of move */
        !           993: 
        !           994: /*****************************************************************************/
        !           995: 
        !           996: setmode(mode)
        !           997: 
        !           998:     int                mode;                   /* this should be the new mode */
        !           999: 
        !          1000: {
        !          1001: 
        !          1002: /*
        !          1003:  *
        !          1004:  * Makes sure the current mode is properly ended and then sets dispmode to mode.
        !          1005:  *
        !          1006:  */
        !          1007: 
        !          1008:     switch ( dispmode )  {
        !          1009:        case ALPHA:
        !          1010:                text();
        !          1011:                break;
        !          1012: 
        !          1013:        case GRAPH:
        !          1014:                draw();
        !          1015:                break;
        !          1016: 
        !          1017:        case INCREMENTAL:
        !          1018:                pen = UP;
        !          1019:                break;
        !          1020:     }  /* End switch */
        !          1021: 
        !          1022:     dispmode = mode;
        !          1023: 
        !          1024: }   /* End of setmode */
        !          1025: 
        !          1026: /*****************************************************************************/
        !          1027: 
        !          1028: home()
        !          1029: 
        !          1030: {
        !          1031: 
        !          1032: /*
        !          1033:  *
        !          1034:  * Makes sure the cursor is positioned at the upper left corner of the page.
        !          1035:  *
        !          1036:  */
        !          1037: 
        !          1038:     margin = 0;
        !          1039:     move(0, TEKYMAX);
        !          1040: 
        !          1041: }   /* End of home */
        !          1042: 
        !          1043: /*****************************************************************************/
        !          1044: 
        !          1045: setfont(newfont)
        !          1046: 
        !          1047:     int                newfont;                /* use this font next */
        !          1048: 
        !          1049: {
        !          1050: 
        !          1051: /*
        !          1052:  *
        !          1053:  * Generates the call to the procedure that's responsible for changing the
        !          1054:  * tektronix font (really just the size).
        !          1055:  *
        !          1056:  */
        !          1057: 
        !          1058:     if ( newfont != tekfont )  {
        !          1059:        setmode(dispmode);
        !          1060:        fprintf(fp_out, "%d f\n", charwidth[newfont]);
        !          1061:     }  /* End if */
        !          1062: 
        !          1063:     tekfont = newfont;
        !          1064: 
        !          1065: }   /* End of setfont */
        !          1066: 
        !          1067: /*****************************************************************************/
        !          1068: 
        !          1069: text()
        !          1070: 
        !          1071: {
        !          1072: 
        !          1073: /*
        !          1074:  *
        !          1075:  * Makes sure any text we've put on the stack is printed.
        !          1076:  *
        !          1077:  */
        !          1078: 
        !          1079:     if ( dispmode == ALPHA && characters > 0 )
        !          1080:        fprintf(fp_out, ") t\n");
        !          1081: 
        !          1082:     characters = 0;
        !          1083: 
        !          1084: }   /* End of text */
        !          1085: 
        !          1086: /*****************************************************************************/
        !          1087: 
        !          1088: draw()
        !          1089: 
        !          1090: {
        !          1091: 
        !          1092: /*
        !          1093:  *
        !          1094:  * Called whenever we need to draw a vector or plot a point. Nothing will be
        !          1095:  * done if points is 0 or if it's 1 and we're in GRAPH mode.
        !          1096:  *
        !          1097:  */
        !          1098: 
        !          1099:     if ( points > 1 )                  /* it's a vector */
        !          1100:        fprintf(fp_out, "%d %d v\n", cursor.x, cursor.y);
        !          1101:     else if ( points == 1 && dispmode != GRAPH )
        !          1102:        fprintf(fp_out, "%d %d p\n", cursor.x, cursor.y);
        !          1103: 
        !          1104:     points = 0;
        !          1105: 
        !          1106: }   /* End of draw */
        !          1107: 
        !          1108: /*****************************************************************************/
        !          1109: 
        !          1110: formfeed()
        !          1111: 
        !          1112: {
        !          1113: 
        !          1114: /*
        !          1115:  *
        !          1116:  * Usually called when we've finished the last page and want to get ready for the
        !          1117:  * next one. Also used at the beginning and end of each input file, so we have to
        !          1118:  * be careful about exactly what's done.
        !          1119:  *
        !          1120:  */
        !          1121: 
        !          1122:     setmode(dispmode);                 /* end any outstanding text or graphics */
        !          1123: 
        !          1124:     if ( fp_out == stdout )            /* count the last page */
        !          1125:        printed++;
        !          1126: 
        !          1127:     fprintf(fp_out, "cleartomark\n");
        !          1128:     fprintf(fp_out, "showpage\n");
        !          1129:     fprintf(fp_out, "saveobj restore\n");
        !          1130:     fprintf(fp_out, "%s %d %d\n", ENDPAGE, page, printed);
        !          1131: 
        !          1132:     if ( ungetc(getc(fp_in), fp_in) == EOF )
        !          1133:        redirect(-1);
        !          1134:     else redirect(++page);
        !          1135: 
        !          1136:     fprintf(fp_out, "%s %d %d\n", PAGE, page, printed+1);
        !          1137:     fprintf(fp_out, "/saveobj save def\n");
        !          1138:     fprintf(fp_out, "mark\n");
        !          1139:     writerequest(printed+1, fp_out);
        !          1140:     fprintf(fp_out, "%d pagesetup\n", printed+1);
        !          1141:     fprintf(fp_out, "%d f\n", charwidth[tekfont]);
        !          1142:     fprintf(fp_out, "%s l\n", styles[linestyle]);
        !          1143: 
        !          1144:     home();
        !          1145: 
        !          1146: }   /* End of formfeed */
        !          1147: 
        !          1148: /*****************************************************************************/
        !          1149: 
        !          1150: nextchar()
        !          1151: 
        !          1152: {
        !          1153: 
        !          1154:     int                ch;                     /* next input character */
        !          1155: 
        !          1156: /*
        !          1157:  *
        !          1158:  * Reads the next character from the current input file and returns it to the
        !          1159:  * caller. When we're finished with the file dispmode is set to EXIT and OUTMODED
        !          1160:  * is returned to the caller.
        !          1161:  *
        !          1162:  */
        !          1163: 
        !          1164:     if ( (ch = getc(fp_in)) == EOF )  {
        !          1165:        setmode(EXIT);
        !          1166:        ch = OUTMODED;
        !          1167:     }  /* End if */
        !          1168: 
        !          1169:     return(ch);
        !          1170: 
        !          1171: }   /* End of nextchar */
        !          1172: 
        !          1173: /*****************************************************************************/
        !          1174: 
        !          1175: redirect(pg)
        !          1176: 
        !          1177:     int                pg;                     /* next page we're printing */
        !          1178: 
        !          1179: {
        !          1180: 
        !          1181:     static FILE        *fp_null = NULL;        /* if output is turned off */
        !          1182: 
        !          1183: /*
        !          1184:  *
        !          1185:  * If we're not supposed to print page pg, fp_out will be directed to /dev/null,
        !          1186:  * otherwise output goes to stdout.
        !          1187:  *
        !          1188:  */
        !          1189: 
        !          1190:     if ( pg >= 0 && in_olist(pg) == ON )
        !          1191:        fp_out = stdout;
        !          1192:     else if ( (fp_out = fp_null) == NULL )
        !          1193:        fp_out = fp_null = fopen("/dev/null", "w");
        !          1194: 
        !          1195: }   /* End of redirect */
        !          1196: 
        !          1197: /*****************************************************************************/
        !          1198: 

unix.superglobalmegacorp.com

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