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