|
|
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: switch (n) { ! 848: case LJUS: ! 849: n = 0; ! 850: break; ! 851: case CJUS: ! 852: n = (lln-llinsiz) / 2; ! 853: break; ! 854: case RJUS: ! 855: n = lln - llinsiz; ! 856: break; ! 857: case FJUS: ! 858: r = 0; ! 859: /* ! 860: * Walk backward through the line looking for horizontal move. ! 861: * If found, do not pad characters to its left. ! 862: */ ! 863: for (cp0 = llinptr-1; cp0 > linebuf; cp0--) ! 864: if (cp0->l_arg.c_code == DHMOV) ! 865: break; ! 866: for (cp = cp0; cp < llinptr; cp++) ! 867: if (cp->l_arg.c_code == DPADC) ! 868: r++; /* paddable character count */ ! 869: if (r == 0) ! 870: return; /* no paddable characters */ ! 871: n = lln - llinsiz; /* padding required */ ! 872: ! 873: /* ! 874: * Because tabs get expanded ex post facto, ! 875: * a tab in fill mode can make the line grow too large. ! 876: * If the line requires negative padding, tough matzohs. ! 877: * Avoid tabs in fill mode! ! 878: */ ! 879: if (n < 0) ! 880: return; ! 881: t = n%r; /* padding remainder */ ! 882: n = 1 + n/r; /* starting pad amount */ ! 883: r = t; /* to do before decrementing */ ! 884: for (cp = cp0; cp < llinptr; cp++) { ! 885: if (cp->l_arg.c_code != DPADC) ! 886: continue; ! 887: if (r-- == 0) ! 888: --n; /* decrement padding amount */ ! 889: cp->l_arg.c_iarg += n; /* pad by n */ ! 890: } ! 891: llinsiz = lln; /* dag for mrc/mrch */ ! 892: return; ! 893: } ! 894: llinsiz += n; /* dag for mrc/mrch */ ! 895: linebuf[0].l_arg.c_iarg += n; ! 896: } ! 897: ! 898: /* ! 899: * Tab to the next tab stop, filling intermediate space with character c. ! 900: * Because center and right justified tab spacing is determined by the ! 901: * text following the tab, the code determines the spacing for ! 902: * the tab before the one entered; arg c==EOF is passed ! 903: * at the end of a line to finish up the final tab stop. ! 904: * This must be called right after calling wordbreak(). ! 905: */ ! 906: movetab(c) int c; ! 907: { ! 908: register TAB *tp; ! 909: int n, w, d2, savfont, ls; ! 910: register int d, d1; ! 911: register int pos; ! 912: ! 913: ls = (nlinsiz != llinsiz) ? nlinsiz : llinsiz; ! 914: if (spcnt) { ! 915: /* Adjust for space padding following tab. */ ! 916: llinsiz -= spcnt; ! 917: ls -= spcnt; ! 918: } ! 919: tp = tabptr; ! 920: pos = tp->t_pos; ! 921: if (cdivp == mdivp) ! 922: pos += tin; /* relative to indent */ ! 923: #if 0 ! 924: fprintf(stderr, "movetab(%d) tab#%d ltabchr=%d pos=%d tlinsiz=%d ls=%d\n", ! 925: c, tabptr-tab, ltabchr, pos, tlinsiz, ls); ! 926: #endif ! 927: switch (tp->t_jus) { ! 928: case LJUS: ! 929: d = pos - tlinsiz; ! 930: break; ! 931: case CJUS: ! 932: d = pos - (ls+tlinsiz)/2; ! 933: break; ! 934: case RJUS: ! 935: d = pos - ls; ! 936: break; ! 937: case NJUS: ! 938: llinptr->l_arg.c_iarg += ssz; ! 939: return; ! 940: } ! 941: if (ltabchr == 0) { ! 942: /* Blank tabs. */ ! 943: tlinptr->l_arg.c_iarg += d; ! 944: } else { ! 945: /* Leader dots or nonblank tabs. */ ! 946: if ((n = nlinptr - (tlinptr+1)) > WORSIZE) ! 947: panic("word buffer overflow"); ! 948: copystr(wordbuf, tlinptr+1, sizeof (CODE), n); /* save */ ! 949: nlinptr = tlinptr + 1; ! 950: savfont = curfont; ! 951: dev_font(tfn); /* tab font */ ! 952: if ((w = tbs) == 0) ! 953: w = width(ltabchr); /* tab char width */ ! 954: if ((d2 = (d1 = tlinsiz) % w) != 0) { ! 955: /* Futz start position to tab char width multiple. */ ! 956: d1 += w-d2; ! 957: tlinptr->l_arg.c_iarg += w-d2; ! 958: } ! 959: d2 = tlinsiz + d; /* end position */ ! 960: while ((d1 += w) <= d2) ! 961: addchar(ltabchr, w); /* write a tab char */ ! 962: addidir(DHMOV, d2-(d1-w)); /* skip remaining space */ ! 963: dev_font(savfont); /* restore font */ ! 964: if (nlinptr+n >= &linebuf[LINSIZE]) ! 965: panic("line buffer overflow"); ! 966: copystr(nlinptr, wordbuf, sizeof (CODE), n); /* restore */ ! 967: llinptr = nlinptr += n; ! 968: --llinptr; ! 969: } ! 970: tlinsiz = nlinsiz = llinsiz += d; ! 971: tlinptr = llinptr; ! 972: if (c == EOF) ! 973: return; ! 974: ls = (cdivp == mdivp) ? llinsiz-tin : llinsiz; ! 975: while ((++tp)->t_jus != NJUS && tp->t_pos <= ls) ! 976: ; ! 977: tabptr = tp; ! 978: ltabchr = c; ! 979: } ! 980: ! 981: /* ! 982: * Initialize line data for a new line. ! 983: */ ! 984: setline() ! 985: { ! 986: #if 0 ! 987: fprintf(stderr, "setline()\n"); ! 988: #endif ! 989: llinptr = nlinptr = tlinptr = linebuf; ! 990: llinsiz = nlinsiz = tlinsiz = 0; ! 991: llindir = nlindir = 0; ! 992: tabptr = tab; ! 993: ltabchr = '\0'; ! 994: preexls = posexls = 0; ! 995: addidir(DHMOV, 0); ! 996: } ! 997: ! 998: /* end of process.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.