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

1.1       root        1: /*
                      2:  * prps.c
                      3:  * 7/10/92
                      4:  * Produce PostScript pages containing input files.
                      5:  * By default, each page has a header line and text enclosed in a box.
                      6:  * See usage() for usage and options.
                      7:  * Requires fp output: cc prps.c -f
                      8:  */
                      9: 
                     10: #include <stdio.h>
                     11: #include <time.h>
                     12: #if    COHERENT
                     13: #include <sys/types.h>
                     14: #endif
                     15: 
                     16: /* Manifest constants. */
                     17: #define        VERSION         "2.3"
                     18: #define        DEFFONT         "Courier"       /* default font                 */
                     19: #define        DEFFONTB        "-Bold"         /* default boldface font suffix */
                     20: #define        DEFFONTI        "-Oblique"      /* default italic font suffix   */
                     21: #define        DEFFONTR        ""              /* default Roman font suffix    */
                     22: #define        DEFPTSIZE       10              /* default point size           */
                     23: #define        DEFPTSIZEL2     8               /* default point size with -l2  */
                     24: #define        DEFTAB          8               /* default tab setting          */
                     25: #define        NBUF            512             /* buffer size                  */
                     26: #define        PAGEDX          8.5             /* page width                   */
                     27: 
                     28: /* Macros. */
                     29: #define        inch(d) ((int)((d) * 72))       /* (double)d inches to (int)pts */
                     30: 
                     31: /* Forward. */
                     32: void   fatal();
                     33: void   file();
                     34: int    font_of();
                     35: char   *Foption();
                     36: void   init();
                     37: int    printline();
                     38: char   *PSstring();
                     39: void   usage();
                     40: 
                     41: /* External. */
                     42: double atof();
                     43: char   *index();
                     44: 
                     45: /* Global. */
                     46: char   *argv0;                         /* Command name.                */
                     47: int    bflag;                          /* Suppress box.                */
                     48: char   buf[NBUF];                      /* Input buffer.                */
                     49: char   buf2[NBUF];                     /* Buffer for PSstring.         */
                     50: char   buf3[NBUF];                     /* Buffer for printline.        */
                     51: char   curfont;                        /* Current font ('R','B','I').  */
                     52: int    dodate = 1;                     /* Display local date/time      */
                     53: char   *fontname = DEFFONT;            /* Font name.                   */
                     54: char   *fontBsuffix = DEFFONTB;        /* Boldace font suffix.         */
                     55: char   *fontIsuffix = DEFFONTI;        /* Italic font suffix.          */
                     56: char   *fontRsuffix = DEFFONTR;        /* Roman font suffix.           */
                     57: int    hflag;                          /* Suppress header.             */
                     58: char   *hdrname = NULL;                /* Name for header line.        */
                     59: int    indent;                         /* Indent.                      */
                     60: int    lflag;                          /* Landscape mode.              */
                     61: int    nlines;                         /* Lines per page.              */
                     62: double ptsize;                         /* Point size.                  */
                     63: int    rhpage;                         /* Right-hand page flag.        */
                     64: int    skip;                           /* Output pages to skip.        */
                     65: int    tab = DEFTAB;                   /* Tab setting.                 */
                     66: 
                     67: /*
                     68:  * Output page format.
                     69:  * The page format is hardwired into this table for now;
                     70:  * the page is assumed to be 8.5 x 11, or 11 x 8.5 in landscape mode.
                     71:  * The format[] array is indexed by lflag:
                     72:  *     0       portrait mode
                     73:  *     1       landscape mode
                     74:  *     2       landscape mode, two side-by-side pages per output page
                     75:  */
                     76: struct pformat {
                     77:        double  p_boxx;                 /* box ll x     */
                     78:        double  p_boxy;                 /* box ll y     */
                     79:        double  p_boxdx;                /* box width    */
                     80:        double  p_boxdy;                /* box height   */
                     81:        double  p_hdry;                 /* header y     */
                     82:        double  p_textx;                /* text x       */
                     83:        double  p_textdy;               /* text height  */
                     84: } format[3] = {
                     85:       /*  boxx boxy  boxdx boxdy  hdry   textx textdy */
                     86:        { .75, .50,  7.250, 9.750, 10.500, 1.000, 9.175 },
                     87:        { .50, .50, 10.000, 7.125,  7.875,  .750, 6.750 },
                     88:        { .25, .25,  5.125, 7.500,  7.950,  .375, 7.400 }
                     89: };
                     90: 
                     91: main(argc, argv) int argc; char *argv[];
                     92: {
                     93:        register char *s;
                     94:        register char c;
                     95: 
                     96:        /* Process command line options. */
                     97:        argv0 = argv[0];
                     98:        while (argc > 1 && (argv[1][0] == '-' || argv[1][0] == '+')) {
                     99:                s = &argv[1][1];
                    100:                if (argv[1][0] == '+') {
                    101:                        skip = atoi(s);
                    102:                        --argc;
                    103:                        ++argv;
                    104:                        continue;
                    105:                }
                    106:                while ((c = *s++) != '\0') {
                    107:                        switch(c) {
                    108:                        case 'b':
                    109:                                ++bflag;
                    110:                                continue;
                    111:                        case 'd':
                    112:                                dodate = 0;
                    113:                                continue;
                    114:                        case 'f':
                    115:                                fontname = s;
                    116:                                break;
                    117:                        case 'F':
                    118:                                if (*s == 's') {
                    119:                                        if ((c = *++s) == 'B')
                    120:                                                fontBsuffix = ++s;
                    121:                                        else if (c == 'I')
                    122:                                                fontIsuffix = ++s;
                    123:                                        else if (c == 'R')
                    124:                                                fontRsuffix = ++s;
                    125:                                        else
                    126:                                                fatal("option \"-Fs\" must be followed by [RBI] and suffix");
                    127:                                        break;
                    128:                                } else
                    129:                                        s = Foption(s);
                    130:                                continue;
                    131:                        case 'h':
                    132:                                ++hflag;
                    133:                                continue;
                    134:                        case 'i':
                    135:                                indent = atoi(s);
                    136:                                if (indent < 0)
                    137:                                        fatal("illegal \"-i\" argument");
                    138:                                break;
                    139:                        case 'l':
                    140:                                lflag = 1;
                    141:                                if (*s == '2') {
                    142:                                        lflag = 2;
                    143:                                        ++s;
                    144:                                }
                    145:                                continue;
                    146:                        case 'n':
                    147:                                hdrname = s;
                    148:                                break;
                    149:                        case 'p':
                    150:                                nlines = atoi(s);
                    151:                                if (nlines < 1)
                    152:                                        fatal("illegal \"-p\" argument");
                    153:                                break;
                    154:                        case 't':
                    155:                                tab = atoi(s);
                    156:                                if (tab < 2)
                    157:                                        fatal("tab setting must be 2 or larger");
                    158:                                break;
                    159:                        case 'V':
                    160:                                fprintf(stderr, "%s: V%s\n", argv0, VERSION);
                    161:                                continue;
                    162:                        default:
                    163:                                if (c >= '1' && c <= '9') {
                    164:                                        ptsize = atof(--s);
                    165:                                        break;
                    166:                                }
                    167:                                /* else fall through... */
                    168:                        case '?':
                    169:                                usage();
                    170:                                break;
                    171:                        }
                    172:                        while (*++s)
                    173:                                ;                       /* scan to end of arg */
                    174:                }
                    175:                --argc;
                    176:                ++argv;
                    177:        }
                    178: 
                    179:        /* Process input files. */
                    180:        init();
                    181:        if (argc == 1)
                    182:                file(NULL);
                    183:        else
                    184:                while (--argc > 0)
                    185:                        file(*++argv);
                    186:        if (lflag == 2 && rhpage)
                    187:                printf("endpage\n");
                    188:        printf("state restore\n");
                    189: 
                    190:        /* Done. */
                    191:        exit(0);
                    192: }
                    193: 
                    194: /*
                    195:  * Cry and die.
                    196:  */
                    197: /* VARARGS */
                    198: void
                    199: fatal(args) char *args;
                    200: {
                    201:        fprintf(stderr, "%s: %r\n", argv0, &args);
                    202:        exit(1);
                    203: }
                    204: 
                    205: /*
                    206:  * Process a file.
                    207:  */
                    208: void
                    209: file(name) char *name;
                    210: {
                    211:        register FILE *fp;
                    212:        register int line, page;
                    213:        time_t t;
                    214: 
                    215:        if (name == NULL)
                    216:                fp = stdin;
                    217:        else if ((fp = fopen(name, "r")) == NULL)
                    218:                fatal("cannot open \"%s\"", name);
                    219: 
                    220:        /* Define name and date fields for header line. */
                    221:        if (!hflag) {
                    222:                printf("/hdrname %s def\n",
                    223:                        PSstring((hdrname != NULL) ? hdrname : 
                    224:                                 (name != NULL)    ? name    : ""));
                    225:                time(&t);
                    226:                printf("/hdrdate %s def\n\n",
                    227:                        dodate  ? PSstring(asctime(localtime(&t)))
                    228:                                : PSstring(""));
                    229:        }
                    230: 
                    231:        /* Process the file. */
                    232:        if (skip) {
                    233:                if (lflag == 2)
                    234:                        skip &= ~1;             /* round down to even */
                    235:                for (page = 0; page < skip; page++) {
                    236:                        for (line = 0; line < nlines; line++) {
                    237:                                if (fgets(buf, NBUF, fp) == NULL)
                    238:                                        break;
                    239:                                if (index(buf, '\f') != NULL)
                    240:                                        break;
                    241:                        }
                    242:                }
                    243:        }
                    244:        line = 0;
                    245:        page = skip + 1;
                    246:        while (fgets(buf, NBUF, fp) != NULL) {
                    247:                if (line++ == 0) {
                    248:                        /* Start of page. */
                    249:                        printf("%% Page %d.\n", page);
                    250:                        if (!hflag)
                    251:                                printf("/hdrpage (Page %d, line %d) def\n",
                    252:                                        page, (page-1)*nlines+1);
                    253:                        if (lflag == 2)
                    254:                                printf("%chpage\n", (rhpage) ? 'r' : 'l');
                    255:                        else
                    256:                                printf("startpage\n");
                    257:                        curfont = 'R';          /* startpage sets Roman */
                    258:                }
                    259:                if (printline() || line == nlines) {
                    260:                        /* End of page. */
                    261:                        if (lflag == 2 && !rhpage != 0)
                    262:                                putchar('\n');
                    263:                        else
                    264:                                printf("endpage\n\n");
                    265:                        page++;
                    266:                        line = 0;
                    267:                        rhpage = !rhpage;
                    268:                }
                    269:        }
                    270:        if (line != 0) {
                    271:                if (lflag != 2 || rhpage)
                    272:                        printf("endpage\n\n");
                    273:                rhpage = !rhpage;
                    274:        }
                    275: 
                    276:        if (name != NULL)
                    277:                fclose(fp);
                    278: }
                    279: 
                    280: /*
                    281:  * Return the font ('R', 'I', 'B', or 'W') of the non-NUL character *s.
                    282:  * Return 'W' for whitespace, which always leaves font unchanged.
                    283:  */
                    284: int
                    285: font_of(s) register char *s;
                    286: {
                    287:        register char c1, c3;
                    288: 
                    289:        if ((c1 = *s) == ' ' || c1 == '\t' || c1 == '\n')
                    290:                return 'W';
                    291:        if (*++s != '\b')
                    292:                return 'R';             /* Not "x\bx" nor "_\bx", i.e. Roman */
                    293:        if ((c3 = *++s) == '\0')
                    294:                return 'R';             /* unlikely */
                    295:        if (c1 == '_')
                    296:                return 'I';             /* Italic */
                    297:        return ((c1 == c3) ? 'B' : 'R');        /* Bold or unlikely Roman */
                    298: }
                    299: 
                    300: /*
                    301:  * Process a -F command line font specification.
                    302:  * Return a pointer past the last character used.
                    303:  */
                    304: char *
                    305: Foption(s) register char *s;
                    306: {
                    307:        register char c;
                    308: 
                    309:        switch (c = *s++) {
                    310:        case 'A':
                    311:                fontname = "AvantGarde";
                    312:                fontBsuffix = "-Demi";
                    313:                fontIsuffix = "-BookOblique";
                    314:                fontRsuffix = "-Book";
                    315:                break;
                    316:        case 'B':
                    317:                fontname = "Bookman";
                    318:                fontBsuffix = "-Demi";
                    319:                fontIsuffix = "-LightItalic";
                    320:                fontRsuffix = "-Light";
                    321:                break;
                    322:        case 'H':
                    323:                fontname = "Helvetica";
                    324:                break;
                    325:        case 'N':
                    326:                fontname = "Helvetica-Narrow";
                    327:                break;
                    328:        case 'P':
                    329:                fontname = "Palatino";
                    330:                goto lab;
                    331:        case 'S':
                    332:                fontname = "NewCenturySchlbk";
                    333:                goto lab;
                    334:        case 'T':
                    335:                fontname = "Times";
                    336: lab:
                    337:                fontIsuffix = "-Italic";
                    338:                fontRsuffix = "-Roman";
                    339:                break;
                    340:        default:
                    341:                fatal("option \"-F\" must be followed by 's' or by one of [ABHNPST]");
                    342:                break;
                    343:        }
                    344:        return s;
                    345: }
                    346: 
                    347: /*
                    348:  * Initialize PostScript program.
                    349:  */
                    350: void
                    351: init()
                    352: {
                    353:        register struct pformat *p;
                    354:        double d, hdrx, hdrdx, texty;
                    355:        int n;
                    356: 
                    357:        p = &format[lflag];
                    358:        hdrx = p->p_boxx;
                    359:        hdrdx = p->p_boxdx;
                    360:        if (hflag) {
                    361:                /* Reclaim the space reserved for the header. */
                    362:                d = p->p_hdry - p->p_boxdy - p->p_boxy; /* added height */
                    363:                p->p_boxdy += d;
                    364:                p->p_textdy += d;
                    365:        }
                    366: 
                    367:        /* Determine the point size and text lines per page. */
                    368:        /* lines = inches * points/inch / points/line */
                    369:        if (ptsize == 0 && nlines == 0)         /* neither specified */
                    370:                ptsize = (lflag == 2) ? DEFPTSIZEL2 : DEFPTSIZE;
                    371:        else if (ptsize == 0)                   /* nlines specified */
                    372:                ptsize = p->p_textdy * 72 / nlines;
                    373:        else if (nlines != 0) {                 /* both specified */
                    374:                n = p->p_textdy * 72 / ptsize;
                    375:                if (n < nlines) {
                    376:                        fprintf(stderr, "%s: Warning: -p argument ignored (too large for point size)\n",
                    377:                                argv0);
                    378:                        nlines = n;
                    379:                }
                    380:        }
                    381:        if (nlines == 0)
                    382:                nlines = p->p_textdy * 72 / ptsize;
                    383: 
                    384:        /* Center text in the box. */
                    385:        p->p_textdy = ptsize * nlines / 72;     /* adjust length for roundoff */
                    386:        texty = p->p_boxy + p->p_boxdy - (p->p_boxdy - p->p_textdy) / 2;
                    387: 
                    388:        /* PostScript globals. */
                    389:        printf(
                    390:                "%% Global definitions.\n"
                    391:                "/state save def\n"
                    392:                "/FS { findfont ptsize scalefont } bind def\n"
                    393:                "/S { show } bind def\n"
                    394:                );
                    395:        printf("/ptsize %.2f def\n", ptsize);
                    396:        printf("/fontH /%s findfont %d scalefont def\n",
                    397:                DEFFONT, (lflag==2) ? DEFPTSIZEL2 : DEFPTSIZE);
                    398:        printf("/fontR /%s%s FS def\n", fontname, fontRsuffix);
                    399:        printf("/fontB /%s%s FS def\n", fontname, fontBsuffix);
                    400:        printf("/fontI /%s%s FS def\n", fontname, fontIsuffix);
                    401:        printf(
                    402:                "/fH {fontH setfont} bind def\n"
                    403:                "/fR {fontR setfont} bind def\n"
                    404:                "/fB {fontB setfont} bind def\n"
                    405:                "/fI {fontI setfont} bind def\n"
                    406:                );
                    407:        putchar('\n');
                    408: 
                    409:        /* PostScript routines. */
                    410:        printf("%% Routines.\n");
                    411:        if (!bflag)
                    412:                printf(
                    413:                        "/box\t%% boxdx boxdy boxx boxy box -\n"
                    414:                        "{\n"
                    415:                        "\tnewpath\n"
                    416:                        "\tmoveto\n"
                    417:                        "\texch dup 0 rlineto\n"
                    418:                        "\texch 0 exch rlineto\n"
                    419:                        "\tneg 0 rlineto\n"
                    420:                        "\tclosepath\n"
                    421:                        "\tclip\n"
                    422:                        "\t0.02 setlinewidth\n"
                    423:                        "\tstroke\n"
                    424:                        "} bind def\n"
                    425:                        );
                    426:        printf("/endpage {grestore showpage} bind def\n");
                    427:        if (!hflag) {
                    428:                printf(
                    429:                        "/hdr\t%% Uses hdrname, hdrdate, hdrpage.\n"
                    430:                        "{\n"
                    431:                        "\tgsave\n"
                    432:                        "\tfH\n"
                    433:                        );
                    434:                printf("\t%d %d translate 0 0 moveto\n",
                    435:                        inch(hdrx), inch(p->p_hdry));
                    436:                printf("\thdrname S\n");
                    437:                printf("\t%d hdrdate stringwidth pop 2 div sub %d neg moveto\n",
                    438:                        inch(hdrdx/2), (lflag==2) ? DEFPTSIZEL2 : DEFPTSIZE);
                    439:                printf("\thdrdate S\n");
                    440:                printf("\t%d hdrpage stringwidth pop sub 0 moveto\n",
                    441:                        inch(hdrdx));
                    442:                printf(
                    443:                        "\thdrpage S\n"
                    444:                        "\tgrestore\n"
                    445:                        "} bind def\n"
                    446:                        );
                    447:        }
                    448:        if (indent) {
                    449:                printf("/indent fR (");
                    450:                for (n = indent; n--; )
                    451:                        putchar(' ');
                    452:                printf(") stringwidth pop def\n");
                    453:        }
                    454:        if (lflag == 2)
                    455:                printf("/lhpage {90 rotate 0 %d translate startpage} bind def\n",
                    456:                        inch(-PAGEDX));
                    457:        printf("/nl {0 %.2f translate 0 0 moveto} bind def\n", -ptsize);
                    458:        printf("/BS { stringwidth pop neg 0 rmoveto } bind def\n");
                    459:        printf("/N {show nl} bind def\n");
                    460:        if (lflag == 2)
                    461:                printf("/rhpage {grestore %d 0 translate startpage} bind def\n",
                    462:                        inch(p->p_boxx + p->p_boxdx));
                    463:        printf("/startpage {\n");
                    464:        printf("\tgsave\n");
                    465:        if (lflag == 1)
                    466:                printf("\t90 rotate 0 %d translate\n", inch(-PAGEDX));
                    467:        if (!hflag)
                    468:                printf("\thdr\n");
                    469:        if (!bflag)
                    470:                printf("\t%d %d %d %d box\n",
                    471:                        inch(p->p_boxdx), inch(p->p_boxdy),
                    472:                        inch(p->p_boxx), inch(p->p_boxy));
                    473:        printf("\t%d%s %d translate\n",
                    474:                inch(p->p_textx),
                    475:                (indent) ? " indent add" : "",
                    476:                inch(texty) - (int)ptsize);
                    477:        printf("\t0 0 moveto\n\tfR\n} bind def\n");
                    478:        printf("\n%% Text.\n");
                    479: }
                    480: 
                    481: /*
                    482:  * Print a line of text from buf[].
                    483:  * This would be one line of code without the font handling.
                    484:  */
                    485: printline()
                    486: {
                    487:        register char *s, *cp;
                    488:        char c;
                    489:        int new;
                    490:        int found_ff = 0;               /* saw formfeed in input stream */
                    491: 
                    492:        s = buf;                        /* input pointer */
                    493:        cp = buf3;                      /* output string pointer */
                    494:        while ((c = *s) != '\0' && c != '\n') {
                    495:                if (c == '\f') {
                    496:                        /* Formfeed. */
                    497:                        ++found_ff;
                    498:                        ++s;
                    499:                        continue;
                    500:                } else if (c == '\b') {
                    501:                        /* Backspace. */
                    502:                        if (cp != buf3) {
                    503:                                *cp-- = '\0';
                    504:                                c = *cp;                /* last char printed */
                    505:                                printf("%s S ", PSstring(buf3));
                    506:                                cp = buf3;
                    507:                        } else
                    508:                                c = ' ';                /* at start of line */
                    509:                        printf("(%c) BS ", c);          /* backspace */
                    510:                        ++s;
                    511:                        continue;
                    512:                }
                    513:                new = font_of(s);
                    514:                if (new != curfont && new != 'W') {
                    515:                        /* Font change. */
                    516:                        if (cp != buf3) {
                    517:                                *cp = '\0';
                    518:                                printf("%s S ", PSstring(buf3));
                    519:                                cp = buf3;
                    520:                        }
                    521:                        printf("f%c ", new);    /* switch to new font */
                    522:                        curfont = new;
                    523:                }
                    524:                if (new == 'R' || new == 'W')
                    525:                        s++;
                    526:                else {
                    527:                        s += 2;                 /* skip 2 if bold or italic */
                    528:                        c = *s++;               /* third gives the char */
                    529:                        if (new == 'B') {
                    530:                                /* Watch for Unix braindamage "c\bc\bc", GOK. */
                    531:                                while (*s == '\b' && *(s+1) == c)
                    532:                                        s += 2;
                    533:                        }
                    534:                }
                    535:                *cp++ = c;                      /* store the character */
                    536:        }
                    537:        if (cp != buf3) {
                    538:                *cp = '\0';
                    539:                printf("%s N\n", PSstring(buf3));
                    540:        } else
                    541:                printf("nl\n");
                    542:        return found_ff;
                    543: }
                    544: 
                    545: /*
                    546:  * Convert string cp to PostScript string in buf2[].
                    547:  * PostScript understands tabs but the tab stops it uses seem screwy,
                    548:  * so this routine expands tabs for now.
                    549:  * The tab expansion here assumes the string starts at the left margin.
                    550:  */
                    551: char *
                    552: PSstring(cp) register char *cp;
                    553: {
                    554:        register char *s, c;
                    555:        register int col;
                    556: 
                    557:        col = 1;                        /* current output column */
                    558:        s = buf2;
                    559:        *s++ = '(';
                    560:        while ((c = *cp++) != '\n' && c != '\0') {
                    561:                if (c == '\t') {
                    562:                        do {
                    563:                                *s++ = ' ';
                    564:                        } while ((col++ % tab) != 0);
                    565:                } else {
                    566:                        if (c == '(' || c == ')' || c == '\\')
                    567:                                *s++ = '\\';
                    568:                        *s++ = c;
                    569:                        ++col;
                    570:                }
                    571:        }
                    572:        *s++ = ')';
                    573:        *s = '\0';
                    574:        return buf2;
                    575: }
                    576: 
                    577: /*
                    578:  * Print a usage message and die.
                    579:  */
                    580: void
                    581: usage()
                    582: {
                    583:        fprintf(stderr,
                    584: "Usage: prps [ options ] [ file ... ]\n"
                    585: "Options:\n"
                    586: "\t+n\tSkip first n pages of output.\n"
                    587: "\t-n\tUse point size n (default: 10).\n"
                    588: "\t-b\tSuppress the box around the page text.\n"
                    589: "\t-d\tSuppress printing the date and time.\n"
                    590: "\t-ffont\tUse the given font name (default: Courier).\n"
                    591: "\t-FX\tUse font X, which must be [ABHNPST].\n"
                    592: "\t-FsXsfx\tUse sfx as suffix for font X, which must be [RBI].\n"
                    593: "\t\tDefault suffixes are \"\" (R), \"-Bold\" (B), \"-Oblique\" (I).\n"
                    594: "\t-h\tSuppress the header line.\n"
                    595: "\t-in\tIndent by an additional n spaces.\n"
                    596: "\t-l\tLandscape mode (default: portrait).\n"
                    597: "\t-l2\tLandscape mode, two pages per output page.\n"
                    598: "\t-nhead\tUse the given name instead of filename in the header line.\n"
                    599: "\t-pn\tPrint n lines of text per output page.\n"
                    600: "\t-tn\tSet tab stops to every n characters (default: 8).\n"
                    601:                );
                    602:        exit(1);
                    603: }
                    604: 
                    605: /* end of prps.c */

unix.superglobalmegacorp.com

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