Annotation of coherent/d/bin/lpr/hp.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * hp.c
                      3:  * 11/13/90
                      4:  * Hewlett Packard LaserJet printer filter.
                      5:  * Translate page format and nroff font information
                      6:  * into HP LaserJet printer escape sequences (PCL).
                      7:  * Usage: hp [-acflr] [-in] [-pn] [-tn] [file ...]
                      8:  * Options:
                      9:  *     -a      Use HP font acute accent character for '\''; default is '\''.
                     10:  *     -c      Font cartridge not available, use underline for italics.
                     11:  *     -f      [Archaic] Print pages in normal order; this is now the default.
                     12:  *     -in     Set left margin (indent) to n; default is 0.
                     13:  *     -l      Print in landscape mode; default is portrait mode.
                     14:  *     -pn     Set text length to n; default is NLINES, i.e. 66.
                     15:  *     -r      Print pages in reverse order (for LaserJet I).
                     16:  *             [Writes to temp FILE 'output', then readback() rewrites
                     17:  *             temp file to stdout with pages reversed.]
                     18:  *     -tn     Set top margin to n; default is 0.
                     19:  * Exit status is 0 if successful, 1 if error, 2 if interrupted.
                     20:  *
                     21:  * Edit history:
                     22:  *     3/21/85 (jtk) -- Changed so that pages were printed in reverse order,
                     23:  *             and fixed bug where trailing lines with only
                     24:  *             non-blank character were deleted.
                     25:  *     4/09/85 (ella) -- Changed so that pages were printed in
                     26:  *             the landscape mode with the pitch 16.66, and 
                     27:  *             fixed bug where underlining in the landscape mode
                     28:  *             and/or !cartridge wasn't ever terminated.
                     29:  *             Incorporated rma's fix (-a option) to reflect the
                     30:  *             manual page and properly process acute accents:
                     31:  *             default: straight (apostrophe), with -a: slanted
                     32:  *             (single quote).
                     33:  *             Included all available options into Usage message.
                     34:  *     10/31/90 (norm) -- fixed the brain damage regarding
                     35:  *             formfeeds. Change default to printing pages in
                     36:  *             order since almost all printers do.  Close any
                     37:  *             files that we open. Guess that shows how much testing
                     38:  *             was done by the author...
                     39:  *     11/7/90 (steve) -- Reordered and rewrote text extensively
                     40:  *             for legibility, hopefully no substantive changes.
                     41:  */
                     42: 
                     43: #include <stdio.h>
                     44: #include <signal.h>
                     45: 
                     46: extern long    ftell();
                     47: 
                     48: /* Miscellany. */
                     49: #define        VERSION         "1.3"
                     50: #define        ACCENTACUTE     0xA8
                     51: #define        ACCENTGRAVE     0xA9
                     52: #define        LINESZ          512
                     53: #define        NLINES          66
                     54: #define        NPAGES          1000
                     55: #define        USAGEMSG        "Usage: hp [ -acflr ] [ -in ] [ -pn ] [ -tn ] [ file ... ]"
                     56: 
                     57: /* Fonts. */
                     58: #define        ROMAN_F         0               /* all except below means Roman */
                     59: #define        BOLD_F          1               /* "x\bx" means bold 'x' */
                     60: #define        ITALIC_F        2               /* "_\bx" means italic '_' */
                     61: 
                     62: /* HP Printer Control Language (PCL) commands. */
                     63: /* These are printf() format strings, some require additional arguments. */
                     64: #define        HMOVEFWD        "\033&a+%dH"
                     65: #define        HMOVEBACK       "\033&a-%dH"
                     66: #define        LANDSCAPE       "\033&l%dO"     /* arg 0==portrait, 1==landscape */
                     67: #define        LEFTMARGIN      "\033&a%dL"
                     68: #define        LINESPACING     "\033&l%dD"
                     69: #define        MOVETOCOL       "\033&a%dC"
                     70: #define        PAGELENGTH      "\033&l%dP"
                     71: #define        PITCH16         "\033(s16.66H"  /* pitch 16.66 cpi */
                     72: #define        RESET           "\033E"
                     73: #define        STROKEWEIGHT    "\033(s%dB"
                     74: #define        STYLE           "\033(s%dS"
                     75: #define        STYLEWEIGHT     "\033(s%ds%dB"
                     76: #define        TEXTLENGTH      "\033&l%dF"
                     77: #define        TOPMARGIN       "\033&l%dE"
                     78: #define        UNDEROFF        "\033&d@"
                     79: #define        UNDERON         "\033&dD"
                     80: 
                     81: /* Forward. */
                     82: #if    0
                     83: void   debug();
                     84: #endif
                     85: void   done();
                     86: void   fakebold();
                     87: void   fatal();
                     88: int    hasFF();
                     89: void   initialize();
                     90: void   newfont();
                     91: int    nonblank();
                     92: void   printfile();
                     93: void   printline();
                     94: void   readback();
                     95: void   trap();
                     96: void   usage();
                     97: 
                     98: /* Globals. */
                     99: int    aflag;                  /* Accent flag                          */
                    100: char   *argv0;                 /* Command name for error messages      */
                    101: int    cartridge = 1;          /* Font cartridge is available          */
                    102: int    font = ROMAN_F;         /* Current font                         */
                    103: int    landscape;              /* 0 for portrait mode, 1 for landscape */
                    104: int    leftmargin;             /* Left margin                          */
                    105: int    linespacing = 6;        /* Vertical lines per inch              */
                    106: int    nfiles;                 /* Number of files to print             */
                    107: int    npages;                 /* Number of pages marked on input      */
                    108: FILE   *output = NULL;         /* FILE containing unreversed pages     */
                    109: char   page[NLINES][LINESZ];   /* Current page buffer                  */
                    110: long   pageaddr[NPAGES];       /* Seek pointers to top of output pages */
                    111: int    quit;                   /* Signal to interrupt program          */
                    112: int    rflag;                  /* Reverse page order                   */
                    113: char   tempfile[20];           /* Temporary file name                  */
                    114: int    textlength = NLINES;    /* Text length -- must satisfy          */
                    115:                                /*      textlength <= NLINES-topmargin  */
                    116: int    topmargin;              /* Top margin                           */
                    117: 
                    118: main(argc, argv) int argc; char *argv[];
                    119: {
                    120:        /* Process arguments. */
                    121:        argv0 = argv[0];
                    122:        argc--;
                    123:        argv++;
                    124:        while (argc > 0)  {
                    125:                switch(**argv)  {
                    126:                case '-':
                    127:                        switch(*++*argv)  {
                    128:                        case 'a':
                    129:                                aflag = 1;
                    130:                                break;
                    131:                        case 'c':
                    132:                                cartridge = 0;
                    133:                                break;
                    134:                        case 'f':
                    135:                                /* Recognized for historical reasons, ignore. */
                    136:                                break;
                    137:                        case 'i':
                    138:                                leftmargin = atoi(++*argv);
                    139:                                break;
                    140:                        case 'l':
                    141:                                landscape = 1;
                    142:                                linespacing = 8;
                    143:                                break;
                    144:                        case 'p':
                    145:                                textlength = atoi(++*argv);
                    146:                                break;
                    147:                        case 'r':
                    148:                                rflag = 1;
                    149:                                break;
                    150:                        case 't':
                    151:                                topmargin = atoi(++*argv);
                    152:                                break;
                    153:                        case 'V':
                    154:                                fprintf(stderr, "%s: V%s\n", argv0, VERSION);
                    155:                                break;
                    156:                        default:
                    157:                                usage();
                    158:                                break;
                    159:                        }
                    160:                        break;
                    161:                default:
                    162:                        if (nfiles++ == 0)
                    163:                                initialize();
                    164:                        printfile(*argv);
                    165:                        break;
                    166:                }
                    167:                argv++;
                    168:                argc--;
                    169:        }
                    170: 
                    171:        /* If no command line files, process stdin. */
                    172:        if (nfiles == 0) {
                    173:                initialize();
                    174:                printfile(NULL);
                    175:        }
                    176: 
                    177:        /* Done. */
                    178:        if (rflag)
                    179:                readback();
                    180:        done(0);
                    181: }
                    182: 
                    183: #if    0
                    184: /*
                    185:  * Print debugging output to file "hp.db".
                    186:  */
                    187: /* VARARGS */
                    188: void
                    189: debug(s) char *s;
                    190: {
                    191:        register FILE *fp;
                    192: 
                    193:        if ((fp = fopen("hp.db", "ar")) == NULL)
                    194:                return;
                    195:        fprintf(fp, "hp: %r\n" &s);
                    196:        fclose(fp);
                    197: }
                    198: #endif
                    199: 
                    200: /*
                    201:  * Finish up.  Remove temporary file if it has been opened, then exit.
                    202:  */
                    203: void
                    204: done(status) int status;
                    205: {
                    206:        printf(RESET);
                    207:        if (output != NULL) {
                    208:                fclose(output);
                    209:                if (output != stdout)
                    210:                        unlink(tempfile);
                    211:        }
                    212:        exit(status);
                    213: }
                    214: 
                    215: /*
                    216:  * Fake boldface of given character when font not available.
                    217:  */
                    218: void
                    219: fakebold(c) register int c;
                    220: {
                    221:        register int d;
                    222: 
                    223:        if (font != ROMAN_F)
                    224:                newfont(ROMAN_F);               /* terminate previous font */
                    225:        d = (landscape) ? 7 : 8;                /* decipoint distance */
                    226:        putc(c, output);                        /* print it */
                    227:        fprintf(output, MOVETOCOL, -1);         /* move back one column */
                    228:        fprintf(output, HMOVEFWD, d);           /* and forward d decipoints */
                    229:        putc(c, output);                        /* print it again */
                    230:        fprintf(output, HMOVEBACK, d);          /* and move back d decipoints */
                    231: }
                    232: 
                    233: /*
                    234:  * Print a fatal error message and die.
                    235:  */
                    236: /* VARARGS */
                    237: void
                    238: fatal(s) char *s;
                    239: {
                    240:        fprintf(stderr, "%s: %r\n", argv0, &s);
                    241:        done(1);
                    242: }
                    243: 
                    244: /*
                    245:  * Test whether string s contains a formfeed.
                    246:  */
                    247: int
                    248: hasFF(s) register char *s;
                    249: {
                    250:        register char c;
                    251: 
                    252:        while (c = *s++)
                    253:                if (c == '\f')
                    254:                        return 1;
                    255:        return 0;
                    256: }
                    257: 
                    258: /*
                    259:  * Set interrupt trap and initialize the printer.
                    260:  * Open temporary file if rflag is specified,
                    261:  * otherwise output just goes to stdout.
                    262:  */
                    263: void
                    264: initialize()
                    265: {
                    266:        /* Trap SIGINT to set quit flag. */
                    267:        signal(SIGINT, trap);
                    268: 
                    269:        /* HP initialization. */
                    270:        printf(RESET);
                    271:        if (landscape)
                    272:                printf(PITCH16);
                    273:        printf(LANDSCAPE, landscape);
                    274:        printf(PAGELENGTH, NLINES);
                    275:        printf(LINESPACING, linespacing);
                    276:        printf(TOPMARGIN, topmargin);
                    277:        printf(TEXTLENGTH, textlength);
                    278:        printf(LEFTMARGIN, leftmargin);
                    279: 
                    280:        /* Initialize output file. */
                    281:        if (quit)
                    282:                done(2);
                    283:        if (rflag) {
                    284:                sprintf(tempfile, "/tmp/hptmp.%d", getpid());
                    285:                if ((output = fopen(tempfile, "wr")) == NULL)
                    286:                        fatal("cannot open temporary file \"%s\"", tempfile);
                    287:        } else 
                    288:                output = stdout;
                    289: }
                    290: 
                    291: /* 
                    292:  * Change to a new font.
                    293:  * For each of the three fonts (ROMAN_F, BOLD_F, ITALIC_F),
                    294:  * this routine prints the font escape appropriate to the given configuration.
                    295:  * There are currently four possible printer configurations:
                    296:  *     normal  portrait  && cartridge
                    297:  *     -l      landscape && cartridge
                    298:  *     -c      portrait  && no cartridge
                    299:  *     -c -l   landscape && no cartridge
                    300:  * In the first case, do bold and italic with style and weight changes.
                    301:  * bold is faked from printline() per-character in the other cases,
                    302:  * italic is underlined Roman in the other cases.
                    303:  */
                    304: void
                    305: newfont(new) int new;
                    306: {
                    307:        static int style = 0;           /* initial style == upright */
                    308:        static int weight = 0;          /* initial weight == medium */
                    309:        static int under = 0;           /* initial underline state == off */
                    310:        register int newstyle, newweight, newunder;
                    311: 
                    312:        if (font == new)
                    313:                return;                                 /* unchanged */
                    314:        font = new;
                    315:        newstyle = newweight = newunder = 0;            /* defaults */
                    316:        switch(font) {
                    317:        case ROMAN_F:
                    318:                break;                                  /* upright medium */
                    319:        case BOLD_F:
                    320:                newweight = 1;                          /* bold */
                    321:                break;
                    322:        case ITALIC_F:
                    323:                if (cartridge && !landscape) {
                    324:                        newstyle = 1;                   /* italic */
                    325:                        newweight = -1;                 /* weight -1 */
                    326:                } else
                    327:                        newunder = 1;           /* underlined upright medium */
                    328:                break;
                    329:        default:
                    330:                fatal("unrecognized font type %d", font);
                    331:                break;
                    332:        }
                    333:        if (under != newunder) {
                    334:                under = newunder;
                    335:                fprintf(output, (under) ? UNDERON : UNDEROFF);
                    336:        }
                    337:        if (style != newstyle && weight != newweight) {
                    338:                style = newstyle;
                    339:                weight = newweight;
                    340:                fprintf(output, STYLEWEIGHT, style, weight);
                    341:        } else if (style != newstyle) {
                    342:                style = newstyle;
                    343:                fprintf(output, STYLE, style);
                    344:        } else if (weight != newweight) {
                    345:                weight = newweight;
                    346:                fprintf(output, STROKEWEIGHT, weight);
                    347:        }
                    348: }
                    349: 
                    350: /*
                    351:  * Return 1 if line s is not blank.
                    352:  */
                    353: int
                    354: nonblank(s) register char *s;
                    355: {
                    356:        register int c;
                    357: 
                    358:        while ((c = *s) == ' ' || c == '\t')
                    359:                s++;
                    360:        return (c != '\0' && c != '\n' && c != '\f');
                    361: }
                    362: 
                    363: /*
                    364:  * Print a file.
                    365:  * NULL means stdin.
                    366:  */
                    367: void
                    368: printfile(file) char *file;
                    369: {
                    370:        FILE *fp;
                    371:        register int i;
                    372:        int last, end;
                    373: 
                    374:        if (file == NULL)
                    375:                fp = stdin;
                    376:        else if ((fp = fopen(file, "r")) == NULL)
                    377:                fatal("cannot open file \"%s\"", file);
                    378: 
                    379:        if (font != ROMAN_F)
                    380:                newfont(ROMAN_F);
                    381:        for (end = 0; !end; ) {
                    382:                if (rflag) {
                    383:                        if (npages >= NPAGES)
                    384:                                fatal("more than %d pages", NPAGES);
                    385:                        pageaddr[npages++] = ftell(output);
                    386:                }
                    387:                for (i = 0; i < NLINES; i++) {
                    388:                        if (fgets(&page[i][0], LINESZ, fp) == NULL) {
                    389:                                if (i == 0) {
                    390:                                        npages--;       /* last page empty */
                    391:                                        return;
                    392:                                }
                    393:                                end = 1;
                    394:                                break;
                    395:                        } else if (hasFF(page[i])) {    /* formfeed seen */
                    396:                                ++i;
                    397:                                break;
                    398:                        }
                    399:                }
                    400:                for (last = --i; last >= 0; --last)
                    401:                        if (nonblank(page[last]))
                    402:                                break;                  /* nonblank line */
                    403:                for (i = 0; i <= last; i++)
                    404:                        printline(page[i]);
                    405:                putc('\r', output);
                    406:                if (last < NLINES - 1)
                    407:                        putc('\f', output);
                    408:        }
                    409:        if (file != NULL)
                    410:                fclose(fp);
                    411: }
                    412: 
                    413: /*
                    414:  * Print one line, substituting special characters from the HP character set.
                    415:  */
                    416: void
                    417: printline(cp) register char *cp;
                    418: {
                    419:        register int c1, c2, new;
                    420:        char *s;
                    421: 
                    422:        /* Replace accents with equivalents from the extended character set. */
                    423:        for (s = cp; *s != '\0'; ++s) {
                    424:                if (*s == '\'' && aflag)
                    425:                        *s = ACCENTACUTE;
                    426:                else if (*s == '`')
                    427:                        *s = ACCENTGRAVE;
                    428:        }
                    429: 
                    430:        /* Look for nroff font sequences. */
                    431:        while ((c1 = *cp++) != '\0') {
                    432: 
                    433:                /* Check for the interrupt signal. */
                    434:                if (quit)
                    435:                        done(2);
                    436: 
                    437:                /* By default, Roman c1 gets printed at the end of this loop. */
                    438:                new = ROMAN_F;
                    439:                if (c1 == '\f')
                    440:                        return;         /* chars after FF on line get eaten */
                    441:                else if (c1 == ' ' || c1 == '\t')
                    442:                        new = font;     /* no font change on whitespace */
                    443:                else if (c1 == '_') {
                    444:                        if ((c2 = *cp++) == '\b') {
                    445:                                /* "_\bx" means italic x. */
                    446:                                new = ITALIC_F;
                    447:                                c1 = *cp++;
                    448:                        } else
                    449:                                cp--;           /* put back c2 */
                    450:                } else if ((c2 = *cp++) == '\b') {
                    451:                        if ((c2 = *cp++) == c1) {
                    452:                                /* "x\bx" means bold x. */
                    453:                                if (!cartridge || landscape) {
                    454:                                        fakebold(c1);   /* fake it */
                    455:                                        continue;
                    456:                                } else
                    457:                                        new = BOLD_F;
                    458:                        } else
                    459:                                cp -= 2;        /* put back '\b' and c2 */
                    460:                } else
                    461:                        cp--;                   /* put back c2 */
                    462:                if (font != new)
                    463:                        newfont(new);           /* font change */
                    464:                putc(c1, output);               /* print c1 in new font */
                    465:        }
                    466: }
                    467: 
                    468: /*
                    469:  * Copy the temporary file to stdout with the pages in reverse order.
                    470:  */
                    471: void
                    472: readback()
                    473: {
                    474:        char c;
                    475: 
                    476:        while (--npages >= 0) {
                    477:                /* Check for interrupt signal at each page. */
                    478:                if (quit)
                    479:                        done(2);
                    480:                fseek(output, pageaddr[npages], 0);
                    481:                while ((c = getc(output)) != '\f')
                    482:                        putchar(c);
                    483:                putchar(c);
                    484:        }
                    485: }
                    486: 
                    487: /*
                    488:  * Set quit flag when interrupt signal is received.
                    489:  */
                    490: void
                    491: trap()
                    492: {
                    493:        quit = 1;
                    494: }
                    495: 
                    496: /*
                    497:  * Print a usage message and die.
                    498:  */
                    499: void
                    500: usage()
                    501: {
                    502:        fprintf(stderr, "%s\n", USAGEMSG);
                    503:        exit(1);
                    504: }
                    505: 
                    506: /* end of hp.c */

unix.superglobalmegacorp.com

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