Annotation of coherent/d/bin/nroff/output.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * output.c
                      3:  * troff
                      4:  * Back end to output device-dependent bits for troff.
                      5:  * Writes either PCL escape sequences for the Hewlett-Packard LaserJet
                      6:  * or (if pflag) PostScript.
                      7:  */
                      8: 
                      9: #include <ctype.h>
                     10: #include "roff.h"
                     11: 
                     12: extern char    *fontname();
                     13: extern char    *ndiv10();
                     14: 
                     15: /* HP LaserJet PCL. */
                     16: #define        HPLJEJECT       "\033&l0H"      /* page eject                   */
                     17: 
                     18: /* PostScript. */
                     19: #define        PSLINIT "90 rotate\n0 -612 translate\n"
                     20: #define        PSEJECT "\nshowpage\n"
                     21: #if    ZKLUDGE
                     22: #define        PSSAVE1 "/state1 save def\n"
                     23: #define        PSREST1 "state1 restore\n"
                     24: #endif
                     25: 
                     26: /*
                     27:  * Device parameters.
                     28:  */
                     29: int    ntroff  =       TROFF;          /* Programme is TROFF type      */
                     30: 
                     31: long   semmul  =       1;              /* Multiplier for em space      */
                     32: long   semdiv  =       1;              /* Divisor for em space         */
                     33: 
                     34: long   senmul  =       1;              /* Multiplier for en space      */
                     35: long   sendiv  =       2;              /* Divisor for en space         */
                     36: 
                     37: long   shrmul  =       12;             /* Horizontal resolution (mul)  */
                     38: long   shrdiv  =       5;              /* Horizontal resolution (div)  */
                     39: 
                     40: long   sinmul  =       720;            /* Multiplier for inch          */
                     41: long   sindiv  =       1;              /* Divisor for inch             */
                     42: 
                     43: long   snrmul  =       1;              /* Narrow space (mul)           */
                     44: long   snrdiv  =       6;              /* Narrow space (div)           */
                     45: 
                     46: long   svrmul  =       12;             /* Vertical resolution (mul)    */
                     47: long   svrdiv  =       5;              /* Vertical resolution (div)    */
                     48: 
                     49: /*
                     50:  * Local variables for output writer.
                     51:  */
                     52: static int     hposd;                  /* device horizontal postition  */
                     53: static int     vposd;                  /* device vertical position     */
                     54: static int     inword;                 /* in word flag for PostScript  */
                     55: static int     lastfont = -1;          /* current output font          */
                     56: 
                     57: #if    ZKLUDGE
                     58: static int     npages;                 /* Output page count            */
                     59: #endif
                     60: 
                     61: /*
                     62:  * Initialize the device.
                     63:  */
                     64: dev_init()
                     65: {
                     66: #if    ZKLUDGE
                     67:        if (Zflag)
                     68:                printf(PSSAVE1);
                     69: #endif
                     70: }
                     71: 
                     72: #if    ZKLUDGE
                     73: /*
                     74:  * Close the device.
                     75:  */
                     76: dev_close()
                     77: {
                     78:        if (Zflag != 0)
                     79:                printf(PSREST1);
                     80: }
                     81: #endif
                     82: 
                     83: /*
                     84:  * Compute the scaled width of a character:
                     85:  *     width(c) == unit(swdmul*fonwidt[c]*psz, swddiv).
                     86:  */
                     87: int
                     88: width(c) register int c;
                     89: {
                     90:        register long l;
                     91: 
                     92:        /* Watch out for sign-extension of argument! */
                     93:        l = swdmul * fonwidt[c & 0xFF] * psz;
                     94:        return (swddiv == 1) ? (int)l : (int)(l/swddiv);
                     95: }
                     96: 
                     97: /*
                     98:  * Given a font number, change to the given font.
                     99:  */
                    100: dev_font(n) register int n;
                    101: {
                    102:        register FWTAB  *fp;
                    103: 
                    104: #if    0
                    105:        fprintf(stderr, "dev_font(%d)\n", n);
                    106: #endif
                    107:        if (n >= nfonts)
                    108:                panic("bad font %d at dev_font, nfonts=%d", n, nfonts);
                    109:        curfont = n;
                    110:        addidir(DFONT, n);
                    111:        fp = fwptab[n];
                    112:        csz = fcsz[n];
                    113:        swdmul = (long)fp->f_num;
                    114:        swddiv = (long)fp->f_den;
                    115:        fonwidt = fp->f_width;
                    116:        varsp = fp->f_spacing;
                    117:        dev_ps(fpsz[n]);
                    118: }
                    119: 
                    120: /*
                    121:  * Change to the given pointsize.
                    122:  * There are several different notions of pointsize:
                    123:  *     global psz (and oldpsz) in the environment,
                    124:  *     fpsz for each font in the environment,
                    125:  *     fp->f_psz for each font, and
                    126:  *     wpsz in flushl() (see comment below).
                    127:  * The font fp->f_psz is used to initialize fpsz in the environment
                    128:  * but is subsequently unused.
                    129:  * The environment fpsz[n] gives the current pointsize for each font.
                    130:  * The environment psz is the pointsize of the current input font,
                    131:  * wpsz is the pointsize of the current output font.
                    132:  * Changing pointsize with a .ps directive or \s escape
                    133:  * changes fpsz[] for each font.
                    134:  */
                    135: dev_ps(n) register int n;
                    136: {
                    137:        if (n <= 0) {
                    138:                printe("illegal pointsize %d, ignored", n/10);
                    139:                return;
                    140:        }
                    141:        oldpsz = psz;
                    142:        psz = n;
                    143:        addidir(DPSZE, n);
                    144: 
                    145:        /* Scale space width for pointsize change. */
                    146:        if (psz != oldpsz && sszdiv != 0)
                    147:                ssz = (int)((long)sszmul * psz / sszdiv);
                    148: }
                    149: 
                    150: /*
                    151:  * Set a fixed pointsize for a font.
                    152:  */
                    153: dev_fz(font, size) char *font, size;
                    154: {
                    155:        char name[2];
                    156:        register int n;
                    157: 
                    158:        argname(font, name);
                    159:        if ((n = font_number(name, ".fz: ")) < 0)
                    160:                return;
                    161:        fwptab[n]->f_flags |= F_FIXED;
                    162:        fpsz[n] = number(size, SMPOIN, SDPOIN, fpsz[n], 0, fpsz[n]);
                    163:        if (n == curfont)
                    164:                dev_ps(fpsz[n]);
                    165: }
                    166: 
                    167: /*
                    168:  * Specify a constant size font.
                    169:  */
                    170: dev_cs(n, size) register int n, size;
                    171: {
                    172:        fcsz[n] = size;
                    173:        if (n == curfont)
                    174:                csz = size;
                    175: }
                    176: 
                    177: /*
                    178:  * Change all non-fixed font pointsizes to the given pointsize,
                    179:  * then change the current pointsize.
                    180:  */
                    181: newpsze(n) register int n;
                    182: {
                    183:        register int i;
                    184: 
                    185:        if (n <= 0) {
                    186:                printe("illegal pointsize %d, ignored", n/10);
                    187:                return;
                    188:        }
                    189:        for (i = 0; i < nfonts; i++)
                    190:                if (((fwptab[i]->f_flags) & F_FIXED) == 0) {
                    191:                        fwptab[i]->f_flags &= ~F_USED;
                    192:                        fpsz[i] = n;
                    193:                }
                    194:        dev_ps(n);
                    195: }
                    196: 
                    197: /*
                    198:  * Given a pointer to a buffer containing stream directives
                    199:  * and a pointer to the end of the buffer,
                    200:  * print the buffer.
                    201:  * The output writer maintains its own notion of current font and pointsize
                    202:  * because [nt]roff buffers output and then flushes at the end of a line;
                    203:  * the environment "curfont" is the current font for input stream processing,
                    204:  * the output writer "font" is the current output stream font.
                    205:  * The font change is implicit until a character is written in the new font.
                    206:  */
                    207: flushl(buffer, bufend) CODE *buffer, *bufend;
                    208: {
                    209:        register CODE   *cp;
                    210:        register int    code;
                    211:        int             i;
                    212:        char            *tp;
                    213:        static  FWTAB   *fp;            /* current font table entry     */
                    214:        static  int     newpage = 1;    /* new page flag                */
                    215:        static  int     hpost;          /* troff horizontal pos (u's)   */
                    216:        static  int     vpost;          /* troff vertical pos (u's)     */
                    217:        static  int     font = -1;      /* current font                 */
                    218:        static  unsigned char *wtab;    /* current font width table     */
                    219:        static  long    wnum;           /* current width numerator      */
                    220:        static  long    wden;           /* current width denominator    */
                    221:        static  int     wpsz;           /* current pointsize            */
                    222: 
                    223:        for (cp = buffer; cp < bufend; cp++) {
                    224:                code = cp->l_arg.c_code;
                    225:                i = cp->l_arg.c_iarg;
                    226:                if (pflag && is_dir(code))
                    227:                        endword();
                    228: #if    0
                    229:                fprintf(stderr, "output: code=%d arg=%d\n", code, i);
                    230: #endif
                    231:                switch (code) {
                    232:                case DNULL:                     /* null code */
                    233:                case DHYPH:                     /* place to hyphenate */
                    234:                        continue;
                    235:                case DHMOV:                     /* move horizontally */
                    236:                case DPADC:                     /* paddable character */
                    237:                        hpost += i;
                    238:                        if (hpost < 0)
                    239:                                hpost = 0;
                    240:                        continue;
                    241:                case DVMOV:                     /* move vertically */
                    242:                        vpost += i;
                    243:                        if (vpost < 0)
                    244:                                vpost = 0;
                    245:                        continue;
                    246:                case DFPOS:                     /* fix position */
                    247:                        move();
                    248:                        continue;
                    249:                case DFONT:                     /* change font */
                    250:                        if (i == font)
                    251:                                continue;       /* unchanged */
                    252:                        if ((unsigned)i >= nfonts)
                    253:                                panic("bad font %d, nfonts=%d", i, nfonts);
                    254:                        font = i;
                    255:                        fp = fwptab[font];
                    256:                        wtab = fp->f_width;
                    257:                        wpsz = fpsz[font];
                    258:                        wnum = (long)fp->f_num * wpsz;
                    259:                        wden = (long)fp->f_den;
                    260:                        continue;
                    261:                case DTRAB:                     /* transparent line */
                    262:                        tp = cp->b_arg.c_bufp;
                    263:                        while (*tp)
                    264:                                putchar(*tp++);
                    265:                        free(cp->b_arg.c_bufp);
                    266:                        continue;
                    267:                case DPSZE:                     /* change pointsize */
                    268:                        if (wpsz != i) {
                    269:                                wpsz = i;
                    270:                                wnum = (long)fp->f_num * wpsz;
                    271:                                if (pflag) {
                    272:                                        /* Mask off used bit to force rescaling */
                    273:                                        lastfont = -1;
                    274:                                        fp->f_flags &= ~F_USED;
                    275:                                } else {
                    276:                                        printf("\033(s%sV", ndiv10(wpsz));
                    277:                                }
                    278:                        }
                    279:                        continue;
                    280:                case DSPAR:                     /* space down and return */
                    281:                        hposd = hpost = 0;
                    282:                        vpost += i;
                    283:                        if (vpost < 0)
                    284:                                vpost = 0;
                    285:                        else if (vpost >= pgl) {
                    286:                                /* New page. */
                    287:                                endpage();
                    288:                                vpost %= pgl;
                    289:                                vposd = vpost;
                    290:                                newpage = 1;
                    291:                        }
                    292:                        continue;
                    293:                case DHLIN:
                    294:                case DVLIN:
                    295:                        if (code == DHLIN && i < 0) {
                    296:                                hpost += i;
                    297:                                i = -i;
                    298:                        }
                    299:                        hposd = hpost;
                    300:                        vposd = vpost;
                    301:                        move();
                    302:                        if (code == DHLIN) {
                    303:                                printf("\n%s 0 L", ndiv10(i));
                    304:                                hpost += i;
                    305:                        } else {
                    306:                                printf("\n0 %s L", ndiv10(-i));
                    307:                                vpost += i;
                    308:                        }
                    309:                        continue;
                    310:                default:                        /* print something */
                    311:                        /* Start a new page. */
                    312:                        if (newpage) {
                    313:                                if (lflag && pflag)
                    314:                                        printf(PSLINIT);
                    315:                                hposd = hpost;
                    316:                                vposd = vpost;
                    317:                                move();
                    318:                                newpage = 0;
                    319:                        }
                    320:                        /*
                    321:                         * Check whether we are on a new page.
                    322:                         * Note, the laser goes to funny places when it
                    323:                         * crosses a page boundary.
                    324:                         */
                    325:                        if (vpost >= pgl) {
                    326:                                /* New page. */
                    327:                                endpage();
                    328:                                vpost %= pgl;
                    329:                                vposd = vpost;
                    330:                                hposd = hpost;
                    331:                                newpage = 1;
                    332:                        }
                    333:                        /* Output move to new position if appropriate. */
                    334:                        if (hpost != hposd || vpost != vposd) {
                    335:                                hposd = hpost;
                    336:                                vposd = vpost;
                    337:                                move();
                    338:                        }
                    339:                        /* Change to different font. */
                    340:                        if (lastfont != font)
                    341:                                selectfont(lastfont=font, wpsz);
                    342:                        if (code == DHYPC)
                    343:                                code = '-';
                    344:                        if (code < 0 || code >= NWIDTH)
                    345:                                panic("bad directive %d", code);
                    346:                        hpost += cp->c_arg.c_move;
                    347:                        hposd += unit(wnum*wtab[code], wden);
                    348:                        i = code;
                    349:                        if (pflag && !inword)
                    350:                                startword();
                    351:                        outchar(code);
                    352:                        if (enb != 0) { /* dag's enbolden...    */
                    353:                                hposd -= unit(wnum*wtab[i], wden);
                    354:                                vposd -= enb;
                    355:                                move();
                    356:                                putchar(code);
                    357:                                hposd -= enb;
                    358:                                move();
                    359:                                putchar(code);
                    360:                                vposd += enb;
                    361:                                putchar(code);
                    362:                                hposd += (unit(wnum*wtab[i], wden) + enb);
                    363:                                move();
                    364:                        }
                    365:                }
                    366:        }
                    367: }
                    368: 
                    369: /*
                    370:  * Move horizontally and/or vertically.
                    371:  * This used to shift PCL output right to avoid printing at left border;
                    372:  * that responsibility is now left to the user.
                    373:  */
                    374: move()
                    375: {
                    376:        static int vold = -1;
                    377: 
                    378:        if (pflag) {
                    379:                /* PostScript. */
                    380:                if (inword)
                    381:                        endword();
                    382:                printf("\n%s", ndiv10(hposd+pof));
                    383:                printf(" %s M", ndiv10(pgl - vposd));
                    384:        } else {
                    385:                /* PCL. */
                    386:                if (vposd == vold)
                    387:                        printf("\033&a%dH", hposd+pof);
                    388:                else
                    389:                        printf("\033&a%dh%dV", hposd+pof, vposd);
                    390:        }
                    391:        vold = vposd;
                    392: }
                    393: 
                    394: /*
                    395:  * Select a font.
                    396:  */
                    397: selectfont(font, ptsize) int font, ptsize;
                    398: {
                    399:        register FWTAB *fp;
                    400:        register char *s;
                    401: 
                    402:        fp = fwptab[font];
                    403:        if (!pflag) {
                    404:                /* Select font via PCL. */
                    405:                printf("\033(%d%c", fp->f_symset/32, fp->f_symset%32+64); /* symbol set */
                    406:                printf("\033(s%dp", fp->f_spacing);             /* spacing */
                    407:                /* fp->f_pitch is in quarterdots/char, convert to chars/inch. */
                    408:                if (fp->f_pitch != 0)
                    409:                        printf("%sh", ndiv10(12000/fp->f_pitch)); /* pitch */
                    410:                printf("%sv", ndiv10(fpsz[font]));              /* point size */
                    411:                printf("%ds", fp->f_style);                     /* style */
                    412:                printf("%db", fp->f_weight);                    /* stroke weight */
                    413:                printf("%dT", fp->f_face);                      /* typeface */
                    414:                return;
                    415:        }
                    416:        /* Select font via PostScript. */
                    417:        if ((s = fontname(font)) == NULL)
                    418:                panic("botch: fontname(%d)", font);
                    419:        endword();
                    420:        if ((fp->f_flags & F_USED) == 0) {
                    421:                fp->f_flags |= F_USED;
                    422:                printf("\n"
                    423:                        "/font%s /%s findfont %d.%d scalefont def\n"
                    424:                        "/f%s { font%s setfont } bind def\n",
                    425:                        s, fp->f_PSname,
                    426:                        ptsize / 10, ptsize % 10,
                    427:                        s, s);
                    428:        }
                    429:        printf(" f%s", s);
                    430: }
                    431: 
                    432: /*
                    433:  * Convert e.g. 123 to "12.3" without using floating point output.
                    434:  * Return a pointer to statically allocated buffer.
                    435:  */
                    436: char *
                    437: ndiv10(n) register int n;
                    438: {
                    439:        static char buf[10];
                    440:        register char *cp;
                    441: 
                    442:        cp = buf;
                    443:        if (n < 0) {
                    444:                n = -n;
                    445:                *cp++ = '-';
                    446:        }
                    447:        if ((n % 10) == 0)
                    448:                sprintf(cp, "%d", n/10);
                    449:        else
                    450:                sprintf(cp, "%d.%d", n/10, n%10);
                    451:        return buf;
                    452: }
                    453: 
                    454: /*
                    455:  * Output a character.
                    456:  * If writing PostScript output, watch out for "()\\"
                    457:  * and expand high-bit characters to octal escapes.
                    458:  */
                    459: outchar(n) register int n;
                    460: {
                    461:        if (pflag) {
                    462:                if (n >= 128) {
                    463:                        printf("\\%03o", n);
                    464:                        return;
                    465:                } else if (n == '(' || n == ')' || n == '\\')
                    466:                        putchar('\\');
                    467:        }
                    468:        putchar(n);
                    469: }
                    470: 
                    471: startword()
                    472: {
                    473:        putchar(' ');
                    474:        putchar('(');
                    475:        inword = 1;
                    476: }
                    477: 
                    478: endword()
                    479: {
                    480:        if (inword) {
                    481:                printf(") S");
                    482:                inword = 0;
                    483:        }
                    484: }
                    485: 
                    486: endpage()
                    487: {
                    488:        if (pflag)
                    489:                endword();
                    490:        printf((pflag) ? PSEJECT : HPLJEJECT);
                    491: #if    ZKLUDGE
                    492:        if (Zflag && ++npages % Zflag == 0) {
                    493:                register int i;
                    494: 
                    495:                printf(PSREST1);
                    496:                printf(PSSAVE1);
                    497:                for (i = 0; i < nfonts; i++)
                    498:                        fwptab[i]->f_flags &= ~F_USED;
                    499:                lastfont = -1;
                    500:                dev_font(curfont);
                    501:        }
                    502: #endif
                    503: }
                    504: 
                    505: /* end of output.c */

unix.superglobalmegacorp.com

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