1 #include "tdef.h"
2 #include "fns.h"
3 #include "ext.h"
4
5 #ifdef STRICT
6 /* not in ANSI or POSIX */
7 #undef isascii
8 #define isascii(a) ((a) >= 0 && (a) <= 127)
9 #endif
10
11 #define GETCH gettch
12 Tchar gettch(void);
13
14
15 /*
16 * troff7.c
17 *
18 * text
19 */
20
21 int brflg;
22
tbreak(void)23 void tbreak(void)
24 {
25 int pad, k;
26 Tchar *i, j;
27 int resol;
28 int un0 = un;
29
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 else
77 resol = t.Adj;
78 } else
79 resol = HOR;
80
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 else
116 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 }
132
donum(void)133 void donum(void)
134 {
135 int i, nw;
136 int lnv = numtabp[LN].val;
137
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 }
160
161
text(void)162 void text(void)
163 {
164 Tchar i;
165 static int spcnt;
166
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 else
184 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 else
230 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 }
247
248
nofill(void)249 void nofill(void)
250 {
251 int j;
252 Tchar i;
253
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 }
295
296
callsp(void)297 void callsp(void)
298 {
299 int i;
300
301 if (flss)
302 i = flss;
303 else
304 i = lss;
305 flss = 0;
306 casesp1(i);
307 }
308
309
ckul(void)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 }
320
321
storeline(Tchar c,int w)322 void storeline(Tchar c, int w)
323 {
324 int diff;
325
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 }
351
352
newline(int a)353 void newline(int a)
354 {
355 int i, j, nlss;
356 int opn;
357
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 }
449
450
findn1(int a)451 findn1(int a)
452 {
453 int i, j;
454
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 }
465
466
chkpn(void)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 }
481
482
findt(int a)483 findt(int a)
484 {
485 int i, j, k;
486
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 }
508
509
findt1(void)510 findt1(void)
511 {
512 int i;
513
514 if (dip != d)
515 i = dip->dnl;
516 else
517 i = numtabp[NL].val;
518 return(findt(i));
519 }
520
521
eject(Stack * a)522 void eject(Stack *a)
523 {
524 int savlss;
525
526 if (dip != d)
527 return;
528 ejf++;
529 if (a)
530 ejl = a;
531 else
532 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 }
543
544
movword(void)545 movword(void)
546 {
547 int w;
548 Tchar i, *wp;
549 int savwch, hys;
550
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 }
630
631
horiz(int i)632 void horiz(int i)
633 {
634 vflag = 0;
635 if (i)
636 pchar(makem(i));
637 }
638
639
setnel(void)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 }
652
653
getword(int x)654 getword(int x)
655 {
656 int j, k;
657 Tchar i, *wp;
658 int noword;
659 int obits;
660
661 j = 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 }
764
765
storeword(Tchar c,int w)766 void storeword(Tchar c, int w)
767 {
768 Tchar *savp;
769 int i;
770
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 }
803
804
gettch(void)805 Tchar gettch(void)
806 {
807 extern int c_isalnum;
808 Tchar i;
809 int j;
810
811 if (TROFF)
812 return getch();
813
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 }
837