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