Annotation of coherent/b/bin/troff/process.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * process.c
                      3:  * nroff/Troff.
                      4:  * Formatting.
                      5:  * This source module does the serious work.
                      6:  * Environmental variables:
                      7:  *     nlinptr points to next location in linebuf[]
                      8:  *     nlinsiz contains current horizontal size of linebuf[]
                      9:  *     nlindir contains non-space directive count
                     10:  *     llinsiz contains horizontal size to end of last word which fits
                     11:  *     tlinsiz contains horizontal size to previous tab (before expansion)
                     12:  * Very confusing, the way the buffering works should be cleaned up eventually.
                     13:  */
                     14: 
                     15: #include <ctype.h>
                     16: #include "roff.h"
                     17: 
                     18: #define        CHYPHEN '-'                             /* hyphenation character */
                     19: 
                     20: /*
                     21:  * Make sure there is space to add another command.
                     22:  */
                     23: chkcode()
                     24: {
                     25:        if (nlinptr >= &linebuf[LINSIZE])
                     26:                panic("line buffer overflow");
                     27: }
                     28: 
                     29: /* Flush buffered data to avoid buffer overflow. */
                     30: flush(hpos) register int hpos;
                     31: {
                     32:        if (hpos)
                     33:                hormove(-hpos);         /* reset output writer position to margin */
                     34:        if (cdivp == mdivp)
                     35:                flushl(linebuf, nlinptr);
                     36:        else
                     37:                flushd(linebuf, nlinptr);
                     38:        setline();                      /* reset buffer pointers */
                     39:        if (hpos)
                     40:                hormove(hpos);          /* restore horizontal position */
                     41: }
                     42: 
                     43: /*
                     44:  * Add a character.
                     45:  * Bump the directive count and nlinsiz.
                     46:  */
                     47: addchar(f, w) int f; register int w;
                     48: {
                     49:        chkcode();
                     50:        nlinptr->c_arg.c_code = f & 0xFF;
                     51:        nlinptr++->c_arg.c_move = w;
                     52:        nlindir++;
                     53:        nlinsiz += w;
                     54:        spcnt = 0;
                     55: }
                     56: 
                     57: /*
                     58:  * Add a directive which takes an integer argument.
                     59:  */
                     60: addidir(d, i)
                     61: {
                     62:        chkcode();
                     63:        nlinptr->l_arg.c_code = d;
                     64:        nlinptr++->l_arg.c_iarg = i;
                     65:        spcnt = 0;
                     66: }
                     67: 
                     68: /*
                     69:  * Add a transparent buffer directive.
                     70:  */
                     71: addtrab(bp) char *bp;
                     72: {
                     73:        chkcode();
                     74:        nlinptr->b_arg.c_code = DTRAB;
                     75:        nlinptr++->b_arg.c_bufp = bp;
                     76: }
                     77: 
                     78: /*
                     79:  * Process input, formatting text.
                     80:  */
                     81: process()
                     82: {
                     83:        register int c, w;
                     84:        REG *rp;
                     85:        int lastc, n;
                     86:        char charbuf[CBFSIZE], name[2];
                     87:        unsigned char *cp;
                     88: 
                     89:        c = '\n';
                     90:        for (;;) {
                     91:                lastc = c;
                     92:                c = getf(1);
                     93:        next:
                     94:                switch (c) {
                     95:                case EOF:               /* End of file */
                     96:                        dprintd(DBGFILE|DBGPROC, ".end of file\n");
                     97:                        return;
                     98:                case EBEG:              /* Open brace \{ */
                     99:                case EEND:              /* Close brace \} */
                    100:                        continue;       /* ignore braces in plain text */
                    101:                case EESC:              /* Printable version of escape */
                    102:                        dprintd(DBGPROC, ".printable escape\n");
                    103:                        character(esc);
                    104:                        continue;
                    105:                case EACA:              /* Acute accent */
                    106:                        dprintd(DBGPROC, ".acute accent\n");
                    107:                        character('\'');
                    108:                        continue;
                    109:                case EGRA:              /* Grave accent */
                    110:                        dprintd(DBGPROC, ".grave accent\n");
                    111:                        character('`');
                    112:                        continue;
                    113:                case EMIN:              /* Minus sign */
                    114:                        dprintd(DBGPROC, ".minus sign\n");
                    115:                        character('-');
                    116:                        continue;
                    117:                case EUNP:              /* Unpaddable space */
                    118:                        dprintd(DBGPROC, ".unpaddable space\n");
                    119:                        hormove(ssz);
                    120:                        continue;
                    121:                case EM06:              /* 1/6 em (narrow space) */
                    122:                        dprintd(DBGPROC, ".narrow space\n");
                    123:                        hormove(unit(SMNARS, SDNARS));
                    124:                        continue;
                    125:                case EM12:              /* 1/12 em (half narrow space) */
                    126:                        dprintd(DBGPROC, ".half narrow space\n");
                    127:                        hormove(unit(SMNARS, SDNARS*2));
                    128:                        continue;
                    129:                case ENOP:              /* Zero width character */
                    130:                        dprintd(DBGPROC, ".zero width character\n");
                    131:                        continue;
                    132:                case ETLI:              /* Transparent line indicator */
                    133:                        dprintd(DBGPROC, ".transparent line indicator\n");
                    134:                        for (cp = charbuf; ; c = *cp++ = getl(0)) {
                    135:                                if (c == '\n' || cp == &charbuf[CBFSIZE-1]) {
                    136:                                        *cp = '\0';
                    137:                                        addtrab(duplstr(charbuf));
                    138:                                        if (c == '\n')
                    139:                                                break;
                    140:                                        cp = charbuf;
                    141:                                }
                    142:                        }
                    143:                        continue;
                    144:                case EHYP:              /* Potential hyphenation break */
                    145:                        dprintd(DBGPROC, ".hyphen break\n");
                    146:                        addidir(DHYPH, 0);
                    147:                        continue;
                    148:                case EBRA:              /* Bracket building function */
                    149:                        dprintd(DBGPROC, ".bracket building\n");
                    150: #if    1
                    151:                        printu("bracket building");             /* $$TO_DO$$ */
                    152:                        continue;
                    153: #else
                    154:                        /*
                    155:                         * The following does not work with special characters
                    156:                         * which include font escape sequences.
                    157:                         */
                    158:                        scandel(charbuf, CBFSIZE);
                    159:                        for (w = 0, cp = charbuf; *cp; cp++) {
                    160:                                n = width(trantab[*cp]);
                    161:                                if (n > w)
                    162:                                        w = n;                  /* max width */
                    163:                        }
                    164:                        n = cp - charbuf;                       /* count */
                    165:                        vermove(unit(-SMVEMS * (n - 1), SDVEMS * 2));
                    166:                        for (cp = charbuf; *cp; cp++) {
                    167:                                addchar(trantab[*cp], 0);
                    168:                                vermove(unit(SMVEMS, SDVEMS));
                    169:                        }
                    170:                        vermove(unit(-SMVEMS * (n + 1), SDVEMS * 2));
                    171:                        hormove(w);
                    172:                        continue;
                    173: #endif
                    174:                case EINT:              /* Interrupt text processing */
                    175:                        dprintd(DBGPROC, ".interrupt proc\n");
                    176:                        if ((c=getf(0)) != '\n')
                    177:                                goto next;
                    178:                        continue;
                    179:                case EVNF:              /* 1/2 em vertical motion */
                    180:                        dprintd(DBGPROC, ".half vertical\n");
                    181:                        vermove(unit(SMVEMS, SDVEMS*2));
                    182:                        continue;
                    183:                case EFON:              /* Change font */
                    184:                        if ((c=getf(0)) != '(') {
                    185:                                name[0] = c;
                    186:                                name[1] = '\0';
                    187:                        } else {
                    188:                                name[0] = getf(0);
                    189:                                name[1] = getf(0);
                    190:                        }
                    191:                        dprint3(DBGPROC, ".font change to %c%c\n", name[0], name[1]);
                    192:                        setfont(name, 1);
                    193:                        continue;
                    194:                case EHMT:              /* Local horizontal motion */
                    195:                        n = scandel(charbuf, CBFSIZE) ? numb(charbuf, SMEMSP, SDEMSP) : 0;
                    196:                        dprint2(DBGPROC, ".local horiz motion = %d\n", n);
                    197:                        hormove(n);
                    198:                        continue;
                    199:                case EMAR:              /* Mark horizontal input place */
                    200:                        name[0] = c = getf(0);
                    201:                        name[1] = '\0';
                    202:                        dprint3(DBGPROC, ".mark horizontal input in %c at %d\n", c, nlinsiz);
                    203:                        rp = getnreg(name);
                    204:                        rp->n_reg.r_nval = nlinsiz;
                    205:                        continue;
                    206:                case EHLF:              /* Horizontal line drawing function */
                    207:                        n = scandel(charbuf, CBFSIZE) ? numb(charbuf, 1L, 1L) : 0;
                    208:                        dprint2(DBGPROC, ".horiz line %d\n", n);
                    209:                        draw_line(n, 1);
                    210:                        continue;
                    211:                case EVLF:              /* Vertical line drawing function */
                    212:                        n = scandel(charbuf, CBFSIZE) ? numb(charbuf, 1L, 1L) : 0;
                    213:                        dprint2(DBGPROC, ".vert line %d\n", n);
                    214:                        draw_line(n, 0);
                    215:                        continue;
                    216:                case EOVS:              /* Overstrike */
                    217:                        dprintd(DBGPROC, ".overstrike\n");
                    218:                        scandel(charbuf, CBFSIZE);
                    219:                        for (w = 0, cp = charbuf; *cp; cp++) {
                    220:                                n = width(trantab[*cp]);
                    221:                                if (n > w)
                    222:                                        w = n;                  /* max width */
                    223:                        }
                    224:                        for (cp = charbuf; *cp; cp++) {
                    225:                                n = width(trantab[*cp]);
                    226:                                hormove((w-n)/2);
                    227:                                addchar(trantab[*cp], 0);       /* centered */
                    228:                                hormove((n-w)/2);
                    229:                        }
                    230:                        hormove(w);
                    231:                        continue;
                    232:                case ESPR:              /* Break and spread output line */
                    233:                        dprintd(DBGPROC, ".break and spread\n");
                    234:                        wordbreak(DNULL);
                    235:                        linebreak(1);
                    236:                        continue;
                    237:                case EVRM:              /* Reverse 1 em vertically */
                    238:                        dprintd(DBGPROC, ".reverse vertical\n");
                    239:                        vermove(unit(-SMVEMS, SDVEMS));
                    240:                        continue;
                    241:                case EPSZ:              /* Change pointsize */
                    242:                        dprintd(DBGPROC, ".pointsize change\n");
                    243:                        if (scanoptdel(charbuf, CBFSIZE)) {
                    244:                                n = number(charbuf, SMPOIN, SDPOIN, psz, 0, oldpsz);
                    245:                                if (n == 0)
                    246:                                        n = oldpsz;
                    247:                                newpsze(n);
                    248:                        }
                    249:                        continue;
                    250:                case EVRN:              /* Reverse 1 en vertically */
                    251:                        dprintd(DBGPROC, ".reverse 1 en vert\n");
                    252:                        vermove(unit(-SMVEMS, SDVEMS*2));
                    253:                        continue;
                    254:                case EVMT:              /* Local vertical motion */
                    255:                        n = scandel(charbuf, CBFSIZE) ? number(charbuf, SMUNIT, SDUNIT, 0, 1, 0) : 0;
                    256:                        dprint2(DBGPROC, ".local vert move %d\n", n);
                    257:                        vermove(n);
                    258:                        continue;
                    259:                case EXLS:              /* Extra line spacing */
                    260:                        n = scandel(charbuf, CBFSIZE) ? number(charbuf, SMUNIT, SDUNIT, 0, 1, 0) : 0;
                    261:                        dprint2(DBGPROC, ".extra line space %d\n", n);
                    262:                        if (n < 0) {
                    263:                                if (-n > preexls)
                    264:                                        preexls = -n;
                    265:                        } else {
                    266:                                if (n > posexls)
                    267:                                        posexls = n;
                    268:                        }
                    269:                        continue;
                    270:                case EZWD:              /* Print character with zero width */
                    271:                        dprintd(DBGPROC, ".print with zero width\n");
                    272:                        addchar(trantab[getf(0)], 0);
                    273:                        continue;
                    274:                case ECOD:              /* Processed text */
                    275:                        dprintd(DBGPROC, ".processed text\n");
                    276:                        c = diverse();
                    277:                        lastc = '\n';
                    278:                        goto next;
                    279:                case '\001':
                    280:                case ELDR:
                    281:                        dprintd(DBGPROC, ".leader character\n");
                    282:                        wordbreak(DHMOV);
                    283:                        movetab(ldc);
                    284:                        continue;
                    285:                case '\t':
                    286:                case ETAB:
                    287:                        dprintd(DBGPROC, ".tab\n");
                    288:                        wordbreak(DHMOV);
                    289:                        movetab(tbc);
                    290:                        continue;
                    291:                case '\n':
                    292:                        dprintd(DBGPROC, ".newline\n");
                    293:                        wordbreak(DPADC);
                    294:                        switch (lastc) {
                    295:                        case '\n':
                    296:                                setbreak();
                    297:                                nlindir++;
                    298:                                setbreak();
                    299:                                break;
                    300:                        case '.':
                    301:                        case '!':
                    302:                        case '?':
                    303:                                pad(2 * ssz);
                    304:                                break;
                    305:                        default:
                    306:                                pad(ssz);
                    307:                        }
                    308:                        if (fill == 0 || cec != 0) {
                    309:                                linebreak(1);
                    310:                                if (cec != 0)
                    311:                                        --cec;
                    312:                        }
                    313:                        if (ulc) {
                    314:                                if (--ulc == 0)
                    315:                                        setfontnum(ufp, 1);
                    316:                        }
                    317:                        if (inpltrc) {
                    318:                                if (--inpltrc == 0)
                    319:                                        execute(inptrap);
                    320:                        }
                    321:                        continue;
                    322:                case ' ':
                    323:                        if (lastc == '\n')
                    324:                                setbreak();
                    325:                        else
                    326:                                wordbreak(DPADC);
                    327:                        if (fill || varsp) {
                    328:                                pad(ssz);
                    329:                                continue;
                    330:                        }
                    331:                case EDWS:              /* Digit width space */
                    332:                        dprintd(DBGPROC, ".digit width space\n");
                    333:                        hormove(width('0'));
                    334:                        continue;
                    335:                default:
                    336:                        if (lastc == '\n') {
                    337:                                if (c == ccc) {
                    338:                                        request();
                    339:                                        c = '\n';
                    340:                                        continue;
                    341:                                } else if (c == nbc) {
                    342:                                        nbrflag = 1;
                    343:                                        request();
                    344:                                        nbrflag = 0;
                    345:                                        c = '\n';
                    346:                                        continue;
                    347:                                }
                    348:                        }
                    349: #if    0
                    350:                        /* Ignore non-ASCII characters. */
                    351:                        if (!isascii(c))
                    352:                                continue;
                    353: #endif
                    354:                        character(trantab[c]);
                    355:                }
                    356:        }
                    357: }
                    358: 
                    359: /*
                    360:  * Draw a horizontal (if hflag) or vertical (if !hflag) line of given length.
                    361:  * This does not handle line drawing with characters other than '_' or '|';
                    362:  * to make it do so, modify number() to store a pointer past the last used char.
                    363:  * If len is positive, draw right or draw down.
                    364:  * If len is negative, move horizontally and then draw right, or draw up.
                    365:  */
                    366: draw_line(len, hflag) register int len; int hflag;
                    367: {
                    368:        register int c, move, hmove, vmove, hpos, negflag, count, excess, savfont;
                    369: 
                    370:        if (len == 0)
                    371:                return;                         /* no work */
                    372:        hpos = nlinsiz;                         /* current horizontal position */
                    373:        if (hflag && len > 0)
                    374:                hpos += len;                    /* hpos after line drawn */
                    375: 
                    376: #if    1
                    377:        /*
                    378:         * Implement PostScript lines with PostScript.
                    379:         * If conditionalized out, troff -p uses character line drawing.
                    380:         */
                    381:        if (pflag) {
                    382:                addidir((hflag) ? DHLIN : DVLIN, len);
                    383:                flush(hpos);
                    384:                return;
                    385:        }
                    386: #endif
                    387:        negflag = (len < 0);                    /* movement is negative */
                    388:        if (negflag)
                    389:                len = -len;                     /* absolute length */
                    390:        savfont = curfont;
                    391:        dev_font(ufn);                          /* use underline font */
                    392:        if (hflag) {
                    393:                /* Horizontal line. */
                    394:                c = '_';                        /* character */
                    395:                move = hmove = width(c);        /* horizontal movement */
                    396:                vmove = 0;                      /* vertical movement */
                    397:        } else {
                    398:                /* Vertical line. */
                    399:                c = '|';                        /* character */
                    400:                hmove = 0;                      /* effective width */
                    401:                move = vmove = unit(SMVEMS, SDVEMS);    /* movement */
                    402:                hormove(-width(c)/2);           /* center the '|' */
                    403:                if (!negflag)
                    404:                        vermove(vmove);         /* start below current pos */
                    405:        }
                    406:        count = len / move;                     /* number of full chars */
                    407:        excess = len % move;                    /* remainder */
                    408:        if (negflag) {
                    409:                if (hflag)
                    410:                        hormove(-len);          /* back up horizontally */
                    411:                else {
                    412:                        vmove = -vmove;         /* draw vertical line upward */
                    413:                        excess = -excess;
                    414:                }
                    415:        }
                    416: 
                    417:        /* Output single '_' or '|' characters, move appropriately. */
                    418:        while (count--) {
                    419:                addchar(c, hmove);
                    420:                if (vmove)
                    421:                        vermove(vmove);
                    422:        }
                    423: 
                    424:        /* Fudge last character position for remaining excess. */
                    425:        if (excess != 0) {
                    426:                if (hflag)
                    427:                        hormove(excess - hmove);
                    428:                else
                    429:                        vermove(excess - vmove);
                    430:                addchar(c, hmove);
                    431:                if (vmove)
                    432:                        vermove(vmove);
                    433:        }
                    434: 
                    435:        /* Adjust final position. */
                    436:        if (!hflag) {
                    437:                hormove(width(c)/2);
                    438:                if (!negflag)
                    439:                        vermove(-vmove);
                    440:        }
                    441: 
                    442:        /* Restore original font. */
                    443:        dev_font(savfont);
                    444: 
                    445:        /* Flush to avoid buffer overflow. */
                    446:        flush(hpos);
                    447: }
                    448: 
                    449: /*
                    450:  * Horizontal move code.
                    451:  */
                    452: hormove(n)
                    453: int    n;
                    454: {
                    455:        addidir(DHMOV, n);
                    456:        nlinsiz += n;
                    457: }
                    458: 
                    459: /*
                    460:  * Vertical move code.
                    461:  */
                    462: vermove(n)
                    463: int    n;
                    464: {
                    465:        addidir(DVMOV, n);
                    466:        cdivp->d_rpos += n;
                    467: }
                    468: 
                    469: /*
                    470:  * Character code.
                    471:  */
                    472: character(f) register int f;
                    473: {
                    474:        register int w;
                    475:        CODE *cp;
                    476: 
                    477:        /* Should this complain about 0-width characters?  Silent for now. */
                    478:        w = width(f);                           /* scaled width */
                    479:        dprint3(DBGCHAR, "** char ='%c', width = %d\n", f, w);
                    480:        if (csz != 0 && csz != w) {
                    481:                /*
                    482:                 * Constant width desired.
                    483:                 * Adjust previous character width so this character
                    484:                 * ends up centered in the constant width space.
                    485:                 */
                    486:                w = (csz-w) / 2;                /* previous char width adjust */
                    487:                cp = llinptr - 1;
                    488:                if (cp >= linebuf && is_char(cp->c_arg.c_code))
                    489:                        cp->c_arg.c_move += w;
                    490:                else
                    491:                        hormove(w);
                    492:                w = csz - w;                    /* current char width adjust */
                    493:        }
                    494:        addchar(f, w);                          /* output a character */
                    495: }
                    496: 
                    497: /*
                    498:  * Read text from a diversion.
                    499:  * Whoever thought up the way diversions work in NROFF/TROFF
                    500:  * should have done something else.
                    501:  */
                    502: int
                    503: diverse()
                    504: {
                    505:        register int code, arg;
                    506:        int c, lastcode, cvls, clsp;
                    507:        char *tp;
                    508: 
                    509:        lastcode = ' ';
                    510:        for (c = ECOD;  c == ECOD;  c = getf(1)) {
                    511:                code = codeval.l_arg.c_code;
                    512:                arg = codeval.l_arg.c_iarg;
                    513: #if    0
                    514:                fprintf(stderr, "diverse(): code=%d arg=%d\n", code, arg);
                    515: #endif
                    516:                switch (code) {
                    517:                case DSPAR:
                    518:                        if (arg==0) {
                    519:                                break;          /* discard empty newline codes */
                    520:                        } else if (fill) {
                    521:                                wordbreak(DPADC);
                    522:                                padspace(lastcode);
                    523:                        } else {
                    524:                                wordbreak(DNULL);
                    525:                                cvls = vls;
                    526:                                clsp = lsp;
                    527:                                vls = 0;
                    528:                                lsp = 1;
                    529:                                linebreak(1);
                    530:                                vls = cvls;
                    531:                                lsp = clsp;
                    532:                                sspace(arg);
                    533:                        }
                    534:                        if (inpltrc && --inpltrc == 0)
                    535:                                execute(inptrap);
                    536:                        break;
                    537:                case DPADC:
                    538:                        wordbreak(DPADC);
                    539:                        if (fill)
                    540:                                padspace(lastcode);
                    541:                        else
                    542:                                pad(arg);
                    543:                        break;
                    544:                case DHYPC:
                    545:                        if (fill) {
                    546:                                register int    c;
                    547:        
                    548:                                addidir(DHYPH, 0);
                    549:                                while ((c=getf(0))==ECOD
                    550:                                 && codeval.l_arg.c_code==DSPAR
                    551:                                 && codeval.l_arg.c_iarg==0 )
                    552:                                        ;
                    553:                                if (c!=ECOD || codeval.l_arg.c_code!=DSPAR)
                    554:                                        panic("cannot dehyphenate");
                    555:                        } else {
                    556:                                nlindir++;
                    557:                                addidir(code, arg);
                    558:                                nlinsiz += arg;
                    559:                        }
                    560:                        break;
                    561:                case DHMOV:
                    562:                        nlinsiz += arg;
                    563:                        /* fall through... */
                    564:                case DNULL:
                    565:                case DVMOV:
                    566:                case DHYPH:
                    567:                        addidir(code, arg);
                    568:                        break;
                    569:                case DFONT:
                    570:                        dev_font(arg);
                    571:                        break;
                    572:                case DPSZE:
                    573:                        dev_ps(arg);
                    574:                        break;
                    575:                case DTRAB:
                    576:                        tp = codeval.b_arg.c_bufp;
                    577:                        adscore(tp);
                    578:                        strp->x3.s_srel = tp;
                    579:                        break;
                    580:                default:
                    581:                        addchar(code, codeval.c_arg.c_move);
                    582:                        break;
                    583:                }
                    584:                lastcode = code;
                    585:        }
                    586:        return c;
                    587: }
                    588: 
                    589: pad(n) register int n;
                    590: {
                    591:        llinptr->l_arg.c_iarg += n;
                    592:        nlinsiz += n;
                    593:        spcnt += n;
                    594: }
                    595: 
                    596: padspace(lastcode) int lastcode;
                    597: {
                    598:        switch (lastcode) {
                    599:        case '!':
                    600:        case '?':
                    601:        case '.':
                    602:                pad(2 * ssz);
                    603:                break;
                    604:        default:
                    605:                pad(ssz);
                    606:                break;
                    607:        }
                    608: }
                    609: 
                    610: /*
                    611:  * End the current line and left justify it.
                    612:  */
                    613: setbreak()
                    614: {
                    615:        register int savfill;
                    616: 
                    617: #if    0
                    618:        fprintf(stderr, "setbreak()\n");
                    619: #endif
                    620:        if (nbrflag)
                    621:                return;
                    622:        wordbreak(DNULL);
                    623:        savfill = fill;
                    624:        fill = 0;
                    625:        linebreak(1);
                    626:        fill = savfill;
                    627: }
                    628: 
                    629: /*
                    630:  * End the current word.  The given directive type is added onto
                    631:  * the end of the line.
                    632:  */
                    633: wordbreak(dir) int dir;
                    634: {
                    635:        int n, s, d;
                    636: 
                    637: #if    0
                    638:        fprintf(stderr, "wordbreak(%d)\n", dir);
                    639: #endif
                    640:        if (nlindir == llindir)
                    641:                return;
                    642:        if (llinptr == linebuf)
                    643:                setwork();
                    644:        else if (fill != 0 && nlinsiz > lln) {
                    645:                n = nlinptr - (llinptr+1);
                    646:                s = nlinsiz - llinsiz - llinptr->l_arg.c_iarg;
                    647:                d = nlindir - llindir;
                    648:                if (hyp==0 || (hypf = fitword(&n, &s, &d))==0)
                    649:                        copystr(wordbuf, llinptr+1, sizeof (CODE), n);
                    650:                if (n > WORSIZE)
                    651:                        panic("word buffer overflow");
                    652:                linebreak(0);
                    653:                hypf = 0;
                    654:                copystr(nlinptr, wordbuf, sizeof (CODE), n);
                    655:                nlinptr += n;
                    656:                nlinsiz += s;
                    657:                nlindir += d;
                    658:                setwork();
                    659:        }
                    660:        if (mrc != '\0')                /* Added by dag */
                    661:                mrch = mrc;
                    662:        llinptr = nlinptr;
                    663:        llinsiz = nlinsiz;
                    664:        llindir = nlindir;
                    665:        addidir(dir, 0);
                    666: }
                    667: 
                    668: /*
                    669:  * Set up working parameters for the line.
                    670:  */
                    671: setwork()
                    672: {
                    673:        if (tif)
                    674:                tif = 0;
                    675:        else
                    676:                tin = ind;
                    677:        linebuf[0].l_arg.c_iarg += tin;
                    678:        llinsiz += tin;
                    679:        nlinsiz += tin;
                    680:        tlinsiz += tin;
                    681: }
                    682: 
                    683: /*
                    684:  * Try to hyphenate and fit the last word in a line.
                    685:  * This routine is really part of the routine 'wordbreak'.
                    686:  * The arguments are pointers to variables in 'wordbreak'.
                    687:  */
                    688: fitword(np, sp, dp) int *dp; int *sp; int *np;
                    689: {
                    690:        CODE *wp;
                    691:        int hflag, b1, b2, h, d, s, n, sav;
                    692:        register CODE *cp;
                    693:        register int c;
                    694:        register char *hp;
                    695: 
                    696:        hyphen(wp=llinptr+1, nlinptr);
                    697:        h = width(CHYPHEN);
                    698:        b1 = nlinsiz - lln;
                    699:        b2 = b1 + h;
                    700:        d = 0;
                    701:        s = 0;
                    702:        n = 0;
                    703:        cp = nlinptr;
                    704:        hp = &hyphbuf[nlinptr-wp];
                    705:        for (;;) {
                    706:                if (--cp < wp)
                    707:                        return 0;
                    708:                c = cp->l_arg.c_code;
                    709:                if (cp>wp && c==CHYPHEN && s>=b1) {
                    710:                        hflag = 0;
                    711:                        break;
                    712:                }
                    713:                if (*--hp) {
                    714:                        if (s >= b2) {
                    715:                                hflag = 1;
                    716:                                break;
                    717:                        }
                    718:                }
                    719:                if (is_char(c)) {
                    720:                        d++;
                    721:                        s += cp->c_arg.c_move;
                    722:                        continue;
                    723:                }
                    724:                if (c==DHMOV || c==DPADC) {
                    725:                        s += cp->l_arg.c_iarg;
                    726:                        continue;
                    727:                }
                    728:        }
                    729:        n = nlinptr - ++cp;
                    730:        copystr(wordbuf, cp, sizeof (CODE), n);
                    731:        llinptr = cp;
                    732:        llinsiz = nlinsiz - s;
                    733:        llindir = nlindir - d;
                    734:        if (hflag) {
                    735:                nlinptr = llinptr;
                    736:                sav = nlinsiz;
                    737:                addchar(CHYPHEN, h);
                    738:                nlinsiz = sav;
                    739:                llinptr = nlinptr;
                    740:                llinsiz += h;
                    741:                llindir = nlindir;
                    742:        }
                    743:        *dp = d;
                    744:        *sp = s;
                    745:        *np = n;
                    746:        return 1;
                    747: }
                    748: 
                    749: /*
                    750:  * End the current line.
                    751:  * This must be called after calling wordbreak.
                    752:  */
                    753: linebreak(flag) int flag;
                    754: {
                    755:        int slsiz, sldir;
                    756:        CODE *slptr;
                    757: 
                    758: #if    0
                    759:        fprintf(stderr, "linebreak() llindir=%d\n", llindir);
                    760: #endif
                    761:        if (llindir == 0) {
                    762:                if (nlinptr != llinptr)
                    763:                        lineflush();
                    764:                return;
                    765:        }
                    766:        movetab(EOF);
                    767:        justify();
                    768:        if (mrch != '\0' && llinsiz != 0) {
                    769: 
                    770:                /* Output margin character at mar from right margin. */
                    771:                slsiz = nlinsiz;
                    772:                sldir = nlindir;
                    773:                slptr = nlinptr;
                    774:                nlinsiz = llinsiz;
                    775:                nlinptr = llinptr;
                    776:                nlindir = llindir;
                    777: #if    0
                    778:                /* Debug print-out to stderr */
                    779:                fprintf(stderr, "margin char %c %d %d %d %d\n",
                    780:                        mrch, mar, lln, llinsiz, (lln-llinsiz) + mar);
                    781: #endif
                    782:                hormove((lln - llinsiz) + mar);
                    783:                character(mrch);
                    784:                llinsiz = nlinsiz;
                    785:                llindir = nlindir;
                    786:                llinptr = nlinptr;
                    787:                nlinsiz = slsiz;
                    788:                nlindir = sldir;
                    789:                nlinptr = slptr;
                    790:                mrch = '\0';
                    791:        }
                    792:        if (llinsiz > cdivp->d_maxw)
                    793:                cdivp->d_maxw = llinsiz;
                    794:        sspace(preexls);
                    795:        if (cdivp == mdivp) {
                    796:                n_reg = llinsiz - linebuf[0].l_arg.c_iarg;
                    797:                /* Kludge nroff output page offset; for troff, cf. output.c. */
                    798:                if (ntroff == NROFF)
                    799:                        linebuf[0].l_arg.c_iarg += pof;
                    800:                flushl(linebuf, llinptr);
                    801:                nsm = 0;
                    802:        } else
                    803:                flushd(linebuf, llinptr);
                    804:        if (flag && nlinptr != llinptr)
                    805:                lineflush();
                    806:        a_reg = posexls;
                    807:        setline();
                    808:        lspace(vls+posexls);
                    809:        nrnlreg->n_reg.r_nval = mdivp->d_rpos;
                    810:        sspace((lsp-1)*vls);
                    811: }
                    812: 
                    813: /*
                    814:  * The unflushed part of a buffered line can contain significant directives,
                    815:  * notably pointsize and font changes.
                    816:  * This flushes directives which would otherwise get ignored.
                    817:  * There must be a better way...
                    818:  */
                    819: lineflush()
                    820: {
                    821:        register CODE *cp;
                    822: 
                    823:        for (cp = llinptr; cp < nlinptr; cp++) {
                    824:                switch(cp->l_arg.c_code) {
                    825:                case DFONT:     break;
                    826:                case DPSZE:     break;
                    827:                default:        continue;
                    828:                }
                    829:                if (cdivp == mdivp)
                    830:                        flushl(cp, cp+1);
                    831:                else
                    832:                        flushd(cp, cp+1);
                    833:        }
                    834:        setline();
                    835: }
                    836: 
                    837: /*
                    838:  * Justify the current line.
                    839:  */
                    840: justify()
                    841: {
                    842:        register CODE *cp, *cp0;
                    843:        int t;
                    844:        register int n, r;
                    845: 
                    846:        n = cec ? CJUS : (fill==0 || adm==0) ? LJUS : adj;
                    847: #if    0
                    848:        fprintf(stderr, "justify() lln=%d llinsiz=%d n=%d\n", lln, llinsiz, n);
                    849: #endif
                    850:        switch (n) {
                    851:        case LJUS:
                    852:                n = 0;
                    853:                break;
                    854:        case CJUS:
                    855:                n = (lln-llinsiz) / 2;
                    856:                break;
                    857:        case RJUS:
                    858:                n = lln - llinsiz;
                    859:                break;
                    860:        case FJUS:
                    861:                r = 0;
                    862:                /*
                    863:                 * Walk backward through the line looking for horizontal move.
                    864:                 * If found, do not pad characters to its left.
                    865:                 */
                    866:                for (cp0 = llinptr-1; cp0 > linebuf; cp0--)
                    867:                         if (cp0->l_arg.c_code == DHMOV)
                    868:                                break;
                    869:                for (cp = cp0; cp < llinptr; cp++)
                    870:                        if (cp->l_arg.c_code == DPADC)
                    871:                                r++;            /* paddable character count */
                    872:                if (r == 0)
                    873:                        return;                 /* no paddable characters */
                    874:                n = lln - llinsiz;              /* padding required */
                    875: 
                    876:                /*
                    877:                 * Because tabs get expanded ex post facto,
                    878:                 * a tab in fill mode can make the line grow too large.
                    879:                 * If the line requires negative padding, tough matzohs.
                    880:                 * Avoid tabs in fill mode!
                    881:                 */
                    882:                if (n < 0)
                    883:                        return;
                    884:                t = n%r;                        /* padding remainder */
                    885:                n = 1 + n/r;                    /* starting pad amount */
                    886:                r = t;                          /* to do before decrementing */
                    887:                for (cp = cp0; cp < llinptr; cp++) {
                    888:                        if (cp->l_arg.c_code != DPADC)
                    889:                                continue;
                    890:                        if (r-- == 0)
                    891:                                --n;            /* decrement padding amount */
                    892:                        cp->l_arg.c_iarg += n;  /* pad by n */
                    893:                }
                    894:                llinsiz = lln;                  /* dag for mrc/mrch */
                    895:                return;
                    896:        }
                    897:        llinsiz += n;                           /* dag for mrc/mrch */
                    898:        linebuf[0].l_arg.c_iarg += n;
                    899: }
                    900: 
                    901: /*
                    902:  * Tab to the next tab stop, filling intermediate space with character c.
                    903:  * Because center and right justified tab spacing is determined by the
                    904:  * text following the tab, the code determines the spacing for
                    905:  * the tab before the one entered; arg c==EOF is passed
                    906:  * at the end of a line to finish up the final tab stop.
                    907:  * This must be called right after calling wordbreak().
                    908:  */
                    909: movetab(c) int c;
                    910: {
                    911:        register TAB *tp;
                    912:        int n, w, d2, savfont, ls;
                    913:        register int d, d1;
                    914:        register int pos;
                    915: 
                    916:        ls = (nlinsiz != llinsiz) ? nlinsiz : llinsiz;
                    917:        if (spcnt) {
                    918:                /* Adjust for space padding following tab. */
                    919:                llinsiz -= spcnt;
                    920:                ls -= spcnt;
                    921:        }
                    922:        tp = tabptr;
                    923:        pos = tp->t_pos;
                    924:        if (cdivp == mdivp)
                    925:                pos += tin;             /* relative to indent */
                    926: #if    0
                    927:        fprintf(stderr, "movetab(%d) tab#%d ltabchr=%d pos=%d tlinsiz=%d ls=%d\n",
                    928:                c, tabptr-tab, ltabchr, pos, tlinsiz, ls);
                    929: #endif
                    930:        switch (tp->t_jus) {
                    931:        case LJUS:
                    932:                d = pos - tlinsiz;
                    933:                break;
                    934:        case CJUS:
                    935:                d = pos - (ls+tlinsiz)/2;
                    936:                break;
                    937:        case RJUS:
                    938:                d = pos - ls;
                    939:                break;
                    940:        case NJUS:
                    941:                llinptr->l_arg.c_iarg += ssz;
                    942:                return;
                    943:        }
                    944:        if (ltabchr == 0) {
                    945:                /* Blank tabs. */
                    946:                tlinptr->l_arg.c_iarg += d;
                    947:        } else {
                    948:                /* Leader dots or nonblank tabs. */
                    949:                if ((n = nlinptr - (tlinptr+1)) > WORSIZE)
                    950:                        panic("word buffer overflow");
                    951:                copystr(wordbuf, tlinptr+1, sizeof (CODE), n);  /* save */
                    952:                nlinptr = tlinptr + 1;
                    953:                savfont = curfont;
                    954:                dev_font(tfn);                          /* tab font */
                    955:                if ((w = tbs) == 0)
                    956:                        w = width(ltabchr);             /* tab char width */
                    957:                if ((d2 = (d1 = tlinsiz) % w) != 0) {
                    958:                        /* Futz start position to tab char width multiple. */
                    959:                        d1 += w-d2;
                    960:                        tlinptr->l_arg.c_iarg += w-d2;
                    961:                }
                    962:                d2 = tlinsiz + d;                       /* end position */
                    963:                while ((d1 += w) <= d2)
                    964:                        addchar(ltabchr, w);            /* write a tab char */
                    965:                addidir(DHMOV, d2-(d1-w));              /* skip remaining space */
                    966:                dev_font(savfont);                      /* restore font */
                    967:                if (nlinptr+n >= &linebuf[LINSIZE])
                    968:                        panic("line buffer overflow");
                    969:                copystr(nlinptr, wordbuf, sizeof (CODE), n);    /* restore */
                    970:                llinptr = nlinptr += n;
                    971:                --llinptr;
                    972:        }
                    973:        tlinsiz = nlinsiz = llinsiz += d;
                    974:        tlinptr = llinptr;
                    975:        if (c == EOF)
                    976:                return;
                    977:        ls = (cdivp == mdivp) ? llinsiz-tin : llinsiz;
                    978:        while ((++tp)->t_jus != NJUS && tp->t_pos <= ls)
                    979:                ;
                    980:        tabptr = tp;
                    981:        ltabchr = c;
                    982: }
                    983: 
                    984: /*
                    985:  * Initialize line data for a new line.
                    986:  */
                    987: setline()
                    988: {
                    989: #if    0
                    990:        fprintf(stderr, "setline()\n");
                    991: #endif
                    992:        llinptr = nlinptr = tlinptr = linebuf;
                    993:        llinsiz = nlinsiz = tlinsiz = 0;
                    994:        llindir = nlindir = 0;
                    995:        tabptr = tab;
                    996:        ltabchr = '\0';
                    997:        preexls = posexls = 0;
                    998:        addidir(DHMOV, 0);
                    999: }
                   1000: 
                   1001: /* end of process.c */

unix.superglobalmegacorp.com

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