Blob
1 #define _BSD_SOURCE 1 /* isascii */2 #define _DEFAULT_SOURCE 13 #include "tdef.h"4 #include "fns.h"5 #include "ext.h"7 #ifdef STRICT8 /* not in ANSI or POSIX */9 #define isascii(a) ((a) >= 0 && (a) <= 127)10 #endif12 #define GETCH gettch13 Tchar gettch(void);16 /*17 * troff7.c18 *19 * text20 */22 int brflg;24 void tbreak(void)25 {26 int pad, k;27 Tchar *i, j;28 int resol;29 int un0 = un;31 trap = 0;32 if (nb)33 return;34 if (dip == d && numtabp[NL].val == -1) {35 newline(1);36 return;37 }38 if (!nc) {39 setnel();40 if (!wch)41 return;42 if (pendw)43 getword(1);44 movword();45 } else if (pendw && !brflg) {46 getword(1);47 movword();48 }49 *linep = dip->nls = 0;50 if (NROFF && dip == d)51 horiz(po);52 if (lnmod)53 donum();54 lastl = ne;55 if (brflg != 1) {56 totout = 0;57 } else if (ad) {58 if ((lastl = ll - un) < ne)59 lastl = ne;60 }61 if (admod && ad && (brflg != 2)) {62 lastl = ne;63 adsp = adrem = 0;64 if (admod == 1)65 un += quant(nel / 2, HOR);66 else if (admod == 2)67 un += nel;68 }69 totout++;70 brflg = 0;71 if (lastl + un > dip->maxl)72 dip->maxl = lastl + un;73 horiz(un);74 if (NROFF) {75 if (adrem % t.Adj)76 resol = t.Hor;77 else78 resol = t.Adj;79 } else80 resol = HOR;82 lastl = ne + (nwd-1) * adsp + adrem;83 for (i = line; nc > 0; ) {84 if ((cbits(j = *i++)) == ' ') {85 pad = 0;86 do {87 pad += width(j);88 nc--;89 } while ((cbits(j = *i++)) == ' ');90 i--;91 pad += adsp;92 --nwd;93 if (adrem) {94 if (adrem < 0) {95 pad -= resol;96 adrem += resol;97 } else if ((totout & 01) || adrem / resol >= nwd) {98 pad += resol;99 adrem -= resol;100 }101 }102 pchar((Tchar) WORDSP);103 horiz(pad);104 } else {105 pchar(j);106 nc--;107 }108 }109 if (ic) {110 if ((k = ll - un0 - lastl + ics) > 0)111 horiz(k);112 pchar(ic);113 }114 if (icf)115 icf++;116 else117 ic = 0;118 ne = nwd = 0;119 un = in;120 setnel();121 newline(0);122 if (dip != d) {123 if (dip->dnl > dip->hnl)124 dip->hnl = dip->dnl;125 } else {126 if (numtabp[NL].val > dip->hnl)127 dip->hnl = numtabp[NL].val;128 }129 for (k = ls - 1; k > 0 && !trap; k--)130 newline(0);131 spread = 0;132 }134 void donum(void)135 {136 int i, nw;137 int lnv = numtabp[LN].val;139 nrbits = nmbits;140 nw = width('1' | nrbits);141 if (nn) {142 nn--;143 goto d1;144 }145 if (lnv % ndf) {146 numtabp[LN].val++;147 d1:148 un += nw * (nmwid + nms + ni);149 return;150 }151 i = 0;152 do { /* count digits in numtabp[LN].val */153 i++;154 } while ((lnv /= 10) > 0);155 horiz(nw * (ni + max(nmwid-i, 0)));156 nform = 0;157 fnumb(numtabp[LN].val, pchar);158 un += nw * nms;159 numtabp[LN].val++;160 }163 void text(void)164 {165 Tchar i;166 static int spcnt;168 nflush++;169 numtabp[HP].val = 0;170 if ((dip == d) && (numtabp[NL].val == -1)) {171 newline(1);172 return;173 }174 setnel();175 if (ce || !fi) {176 nofill();177 return;178 }179 if (pendw)180 goto t4;181 if (pendt)182 if (spcnt)183 goto t2;184 else185 goto t3;186 pendt++;187 if (spcnt)188 goto t2;189 while ((cbits(i = GETCH())) == ' ') {190 spcnt++;191 numtabp[HP].val += sps;192 widthp = sps;193 }194 if (nlflg) {195 t1:196 nflush = pendt = ch = spcnt = 0;197 callsp();198 return;199 }200 ch = i;201 if (spcnt) {202 t2:203 tbreak();204 if (nc || wch)205 goto rtn;206 un += spcnt * sps;207 spcnt = 0;208 setnel();209 if (trap)210 goto rtn;211 if (nlflg)212 goto t1;213 }214 t3:215 if (spread)216 goto t5;217 if (pendw || !wch)218 t4:219 if (getword(0))220 goto t6;221 if (!movword())222 goto t3;223 t5:224 if (nlflg)225 pendt = 0;226 adsp = adrem = 0;227 if (ad) {228 if (nwd == 1)229 adsp = nel;230 else231 adsp = nel / (nwd - 1);232 adsp = (adsp / HOR) * HOR;233 adrem = nel - adsp*(nwd-1);234 }235 brflg = 1;236 tbreak();237 spread = 0;238 if (!trap)239 goto t3;240 if (!nlflg)241 goto rtn;242 t6:243 pendt = 0;244 ckul();245 rtn:246 nflush = 0;247 }250 void nofill(void)251 {252 int j;253 Tchar i;255 if (!pendnf) {256 over = 0;257 tbreak();258 if (trap)259 goto rtn;260 if (nlflg) {261 ch = nflush = 0;262 callsp();263 return;264 }265 adsp = adrem = 0;266 nwd = 10000;267 }268 while ((j = (cbits(i = GETCH()))) != '\n') {269 if (j == ohc)270 continue;271 if (j == CONT) {272 pendnf++;273 nflush = 0;274 flushi();275 ckul();276 return;277 }278 j = width(i);279 widthp = j;280 numtabp[HP].val += j;281 storeline(i, j);282 }283 if (ce) {284 ce--;285 if ((i = quant(nel / 2, HOR)) > 0)286 un += i;287 }288 if (!nc)289 storeline((Tchar)FILLER, 0);290 brflg = 2;291 tbreak();292 ckul();293 rtn:294 pendnf = nflush = 0;295 }298 void callsp(void)299 {300 int i;302 if (flss)303 i = flss;304 else305 i = lss;306 flss = 0;307 casesp1(i);308 }311 void ckul(void)312 {313 if (ul && (--ul == 0)) {314 cu = 0;315 font = sfont;316 mchbits();317 }318 if (it && --it == 0 && itmac)319 control(itmac, 0);320 }323 void storeline(Tchar c, int w)324 {325 int diff;327 if (linep >= line + lnsize - 2) {328 lnsize += LNSIZE;329 diff = linep - line;330 if (( line = (Tchar *)realloc((char *)line, lnsize * sizeof(Tchar))) != NULL) {331 if (linep && diff)332 linep = line + diff;333 } else {334 if (over) {335 return;336 } else {337 flusho();338 ERROR "Line overflow." WARN;339 over++;340 *linep++ = LEFTHAND;341 w = width(LEFTHAND);342 nc++;343 c = '\n';344 }345 }346 }347 *linep++ = c;348 ne += w;349 nel -= w;350 nc++;351 }354 void newline(int a)355 {356 int i, j, nlss;357 int opn;359 nlss = 0;360 if (a)361 goto nl1;362 if (dip != d) {363 j = lss;364 pchar1((Tchar)FLSS);365 if (flss)366 lss = flss;367 i = lss + dip->blss;368 dip->dnl += i;369 pchar1((Tchar)i);370 pchar1((Tchar)'\n');371 lss = j;372 dip->blss = flss = 0;373 if (dip->alss) {374 pchar1((Tchar)FLSS);375 pchar1((Tchar)dip->alss);376 pchar1((Tchar)'\n');377 dip->dnl += dip->alss;378 dip->alss = 0;379 }380 if (dip->ditrap && !dip->ditf && dip->dnl >= dip->ditrap && dip->dimac)381 if (control(dip->dimac, 0)) {382 trap++;383 dip->ditf++;384 }385 return;386 }387 j = lss;388 if (flss)389 lss = flss;390 nlss = dip->alss + dip->blss + lss;391 numtabp[NL].val += nlss;392 if (TROFF && ascii) {393 dip->alss = dip->blss = 0;394 }395 pchar1((Tchar)'\n');396 flss = 0;397 lss = j;398 if (numtabp[NL].val < pl)399 goto nl2;400 nl1:401 ejf = dip->hnl = numtabp[NL].val = 0;402 ejl = frame;403 if (donef) {404 if ((!nc && !wch) || ndone)405 done1(0);406 ndone++;407 donef = 0;408 if (frame == stk)409 nflush++;410 }411 opn = numtabp[PN].val;412 numtabp[PN].val++;413 if (npnflg) {414 numtabp[PN].val = npn;415 npn = npnflg = 0;416 }417 nlpn:418 if (numtabp[PN].val == pfrom) {419 print++;420 pfrom = -1;421 } else if (opn == pto) {422 print = 0;423 opn = -1;424 chkpn();425 goto nlpn;426 }427 if (print)428 ptpage(numtabp[PN].val); /* supposedly in a clean state so can pause */429 if (stop && print) {430 dpn++;431 if (dpn >= stop) {432 dpn = 0;433 ptpause();434 }435 }436 nl2:437 trap = 0;438 if (numtabp[NL].val == 0) {439 if ((j = findn(0)) != NTRAP)440 trap = control(mlist[j], 0);441 } else if ((i = findt(numtabp[NL].val - nlss)) <= nlss) {442 if ((j = findn1(numtabp[NL].val - nlss + i)) == NTRAP) {443 flusho();444 ERROR "Trap botch." WARN;445 done2(-5);446 }447 trap = control(mlist[j], 0);448 }449 }451 int452 findn1(int a)453 {454 int i, j;456 for (i = 0; i < NTRAP; i++) {457 if (mlist[i]) {458 if ((j = nlist[i]) < 0)459 j += pl;460 if (j == a)461 break;462 }463 }464 return(i);465 }468 void chkpn(void)469 {470 pto = *(pnp++);471 pfrom = pto>=0 ? pto : -pto;472 if (pto == -INT_MAX) {473 flusho();474 done1(0);475 }476 if (pto < 0) {477 pto = -pto;478 print++;479 pfrom = 0;480 }481 }483 int484 findt(int a)485 {486 int i, j, k;488 k = INT_MAX;489 if (dip != d) {490 if (dip->dimac && (i = dip->ditrap - a) > 0)491 k = i;492 return(k);493 }494 for (i = 0; i < NTRAP; i++) {495 if (mlist[i]) {496 if ((j = nlist[i]) < 0)497 j += pl;498 if ((j -= a) <= 0)499 continue;500 if (j < k)501 k = j;502 }503 }504 i = pl - a;505 if (k > i)506 k = i;507 return(k);508 }510 int511 findt1(void)512 {513 int i;515 if (dip != d)516 i = dip->dnl;517 else518 i = numtabp[NL].val;519 return(findt(i));520 }523 void eject(Stack *a)524 {525 int savlss;527 if (dip != d)528 return;529 ejf++;530 if (a)531 ejl = a;532 else533 ejl = frame;534 if (trap)535 return;536 e1:537 savlss = lss;538 lss = findt(numtabp[NL].val);539 newline(0);540 lss = savlss;541 if (numtabp[NL].val && !trap)542 goto e1;543 }545 int546 movword(void)547 {548 int w;549 Tchar i, *wp;550 int savwch, hys;552 over = 0;553 wp = wordp;554 if (!nwd) {555 while (cbits(*wp++) == ' ') {556 wch--;557 wne -= sps;558 }559 wp--;560 }561 if (wne > nel && !hyoff && hyf && (!nwd || nel > 3 * sps) &&562 (!(hyf & 02) || (findt1() > lss)))563 hyphen(wp);564 savwch = wch;565 hyp = hyptr;566 nhyp = 0;567 while (*hyp && *hyp <= wp)568 hyp++;569 while (wch) {570 if (hyoff != 1 && *hyp == wp) {571 hyp++;572 if (!wdstart || (wp > wdstart + 1 && wp < wdend &&573 (!(hyf & 04) || wp < wdend - 1) && /* 04 => last 2 */574 (!(hyf & 010) || wp > wdstart + 2))) { /* 010 => 1st 2 */575 nhyp++;576 storeline((Tchar)IMP, 0);577 }578 }579 i = *wp++;580 w = width(i);581 wne -= w;582 wch--;583 storeline(i, w);584 }585 if (nel >= 0) {586 nwd++;587 return(0); /* line didn't fill up */588 }589 if (TROFF)590 xbits((Tchar)HYPHEN, 1);591 hys = width((Tchar)HYPHEN);592 m1:593 if (!nhyp) {594 if (!nwd)595 goto m3;596 if (wch == savwch)597 goto m4;598 }599 if (*--linep != IMP)600 goto m5;601 if (!(--nhyp))602 if (!nwd)603 goto m2;604 if (nel < hys) {605 nc--;606 goto m1;607 }608 m2:609 if ((i = cbits(*(linep - 1))) != '-' && i != EMDASH) {610 *linep = (*(linep - 1) & SFMASK) | HYPHEN;611 w = width(*linep);612 nel -= w;613 ne += w;614 linep++;615 }616 m3:617 nwd++;618 m4:619 wordp = wp;620 return(1); /* line filled up */621 m5:622 nc--;623 w = width(*linep);624 ne -= w;625 nel += w;626 wne += w;627 wch++;628 wp--;629 goto m1;630 }633 void horiz(int i)634 {635 vflag = 0;636 if (i)637 pchar(makem(i));638 }641 void setnel(void)642 {643 if (!nc) {644 linep = line;645 if (un1 >= 0) {646 un = un1;647 un1 = -1;648 }649 nel = ll - un;650 ne = adsp = adrem = 0;651 }652 }654 int655 getword(int x)656 {657 int j, k;658 Tchar i, *wp;659 int noword;660 int obits;662 j = 0;663 noword = 0;664 if (x)665 if (pendw) {666 *pendw = 0;667 goto rtn;668 }669 if (wordp = pendw)670 goto g1;671 hyp = hyptr;672 wordp = word;673 over = wne = wch = 0;674 hyoff = 0;675 obits = chbits;676 while (1) { /* picks up 1st char of word */677 j = cbits(i = GETCH());678 if (j == '\n') {679 wne = wch = 0;680 noword = 1;681 goto rtn;682 }683 if (j == ohc) {684 hyoff = 1; /* 1 => don't hyphenate */685 continue;686 }687 if (j == ' ') {688 numtabp[HP].val += sps;689 widthp = sps;690 storeword(i, sps);691 continue;692 }693 break;694 }695 storeword(' ' | obits, sps);696 if (spflg) {697 storeword(' ' | obits, sps);698 spflg = 0;699 }700 g0:701 if (j == CONT) {702 pendw = wordp;703 nflush = 0;704 flushi();705 return(1);706 }707 if (hyoff != 1) {708 if (j == ohc) {709 hyoff = 2;710 *hyp++ = wordp;711 if (hyp > hyptr + NHYP - 1)712 hyp = hyptr + NHYP - 1;713 goto g1;714 }715 if (((j == '-' || j == EMDASH)) && !(i & ZBIT)) /* zbit avoids \X */716 if (wordp > word + 1) {717 hyoff = 2;718 *hyp++ = wordp + 1;719 if (hyp > hyptr + NHYP - 1)720 hyp = hyptr + NHYP - 1;721 }722 }723 j = width(i);724 numtabp[HP].val += j;725 storeword(i, j);726 g1:727 j = cbits(i = GETCH());728 if (j != ' ') {729 static char *sentchar = ".?!"; /* sentence terminators */730 if (j != '\n')731 goto g0;732 wp = wordp-1; /* handle extra space at end of sentence */733 while (wp >= word) {734 j = cbits(*wp--);735 if (j=='"' || j=='\'' || j==')' || j==']' || j=='*' || j==DAGGER)736 continue;737 for (k = 0; sentchar[k]; k++)738 if (j == sentchar[k]) {739 spflg++;740 break;741 }742 break;743 }744 }745 *wordp = 0;746 numtabp[HP].val += sps;747 rtn:748 for (wp = word; *wp; wp++) {749 if (ismot(j))750 break; /* drechsler */751 j = cbits(*wp);752 if (j == ' ')753 continue;754 if (!(isascii(j) && isdigit(j)) && j != '-')755 break;756 }757 if (*wp == 0) /* all numbers, so don't hyphenate */758 hyoff = 1;759 wdstart = 0;760 wordp = word;761 pendw = 0;762 *hyp++ = 0;763 setnel();764 return(noword);765 }768 void storeword(Tchar c, int w)769 {770 Tchar *savp;771 int i;773 if (wordp >= word + wdsize - 2) {774 wdsize += WDSIZE;775 savp = word;776 if (( word = (Tchar *)realloc((char *)word, wdsize * sizeof(Tchar))) != NULL) {777 if (wordp)778 wordp = word + (wordp - savp);779 if (pendw)780 pendw = word + (pendw - savp);781 if (wdstart)782 wdstart = word + (wdstart - savp);783 if (wdend)784 wdend = word + (wdend - savp);785 for (i = 0; i < NHYP; i++)786 if (hyptr[i])787 hyptr[i] = word + (hyptr[i] - savp);788 } else {789 if (over) {790 return;791 } else {792 flusho();793 ERROR "Word overflow." WARN;794 over++;795 c = LEFTHAND;796 w = width(LEFTHAND);797 }798 }799 }800 widthp = w;801 wne += w;802 *wordp++ = c;803 wch++;804 }807 Tchar gettch(void)808 {809 extern int c_isalnum;810 Tchar i;811 int j;813 if (TROFF)814 return getch();816 i = getch();817 j = cbits(i);818 if (ismot(i) || fbits(i) != ulfont)819 return(i);820 if (cu) {821 if (trtab[j] == ' ') {822 setcbits(i, '_');823 setfbits(i, FT); /* default */824 }825 return(i);826 }827 /* should test here for characters that ought to be underlined */828 /* in the old nroff, that was the 200 bit on the width! */829 /* for now, just do letters, digits and certain special chars */830 if (j <= 127) {831 if (!isalnum(j))832 setfbits(i, FT);833 } else {834 if (j < c_isalnum)835 setfbits(i, FT);836 }837 return(i);838 }