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