Blob


1 #define _BSD_SOURCE 1 /* isascii */
2 #include "tdef.h"
3 #include "fns.h"
4 #include "ext.h"
6 #ifdef STRICT
7 /* not in ANSI or POSIX */
8 #define isascii(a) ((a) >= 0 && (a) <= 127)
9 #endif
11 #define GETCH gettch
12 Tchar gettch(void);
15 /*
16 * troff7.c
17 *
18 * text
19 */
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 else
77 resol = t.Adj;
78 } else
79 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 }
101 pchar((Tchar) WORDSP);
102 horiz(pad);
103 } else {
104 pchar(j);
105 nc--;
108 if (ic) {
109 if ((k = ll - un0 - lastl + ics) > 0)
110 horiz(k);
111 pchar(ic);
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;
128 for (k = ls - 1; k > 0 && !trap; k--)
129 newline(0);
130 spread = 0;
133 void donum(void)
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;
144 if (lnv % ndf) {
145 numtabp[LN].val++;
146 d1:
147 un += nw * (nmwid + nms + ni);
148 return;
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++;
162 void text(void)
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;
173 setnel();
174 if (ce || !fi) {
175 nofill();
176 return;
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;
193 if (nlflg) {
194 t1:
195 nflush = pendt = ch = spcnt = 0;
196 callsp();
197 return;
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;
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);
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;
249 void nofill(void)
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;
264 adsp = adrem = 0;
265 nwd = 10000;
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;
277 j = width(i);
278 widthp = j;
279 numtabp[HP].val += j;
280 storeline(i, j);
282 if (ce) {
283 ce--;
284 if ((i = quant(nel / 2, HOR)) > 0)
285 un += i;
287 if (!nc)
288 storeline((Tchar)FILLER, 0);
289 brflg = 2;
290 tbreak();
291 ckul();
292 rtn:
293 pendnf = nflush = 0;
297 void callsp(void)
299 int i;
301 if (flss)
302 i = flss;
303 else
304 i = lss;
305 flss = 0;
306 casesp1(i);
310 void ckul(void)
312 if (ul && (--ul == 0)) {
313 cu = 0;
314 font = sfont;
315 mchbits();
317 if (it && --it == 0 && itmac)
318 control(itmac, 0);
322 void storeline(Tchar c, int w)
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';
346 *linep++ = c;
347 ne += w;
348 nel -= w;
349 nc++;
353 void newline(int a)
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;
379 if (dip->ditrap && !dip->ditf && dip->dnl >= dip->ditrap && dip->dimac)
380 if (control(dip->dimac, 0)) {
381 trap++;
382 dip->ditf++;
384 return;
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;
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++;
410 opn = numtabp[PN].val;
411 numtabp[PN].val++;
412 if (npnflg) {
413 numtabp[PN].val = npn;
414 npn = npnflg = 0;
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;
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();
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);
446 trap = control(mlist[j], 0);
450 int
451 findn1(int a)
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;
463 return(i);
467 void chkpn(void)
469 pto = *(pnp++);
470 pfrom = pto>=0 ? pto : -pto;
471 if (pto == -INT_MAX) {
472 flusho();
473 done1(0);
475 if (pto < 0) {
476 pto = -pto;
477 print++;
478 pfrom = 0;
482 int
483 findt(int a)
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);
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;
503 i = pl - a;
504 if (k > i)
505 k = i;
506 return(k);
509 int
510 findt1(void)
512 int i;
514 if (dip != d)
515 i = dip->dnl;
516 else
517 i = numtabp[NL].val;
518 return(findt(i));
522 void eject(Stack *a)
524 int savlss;
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;
544 int
545 movword(void)
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;
558 wp--;
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);
578 i = *wp++;
579 w = width(i);
580 wne -= w;
581 wch--;
582 storeline(i, w);
584 if (nel >= 0) {
585 nwd++;
586 return(0); /* line didn't fill up */
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;
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;
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++;
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;
632 void horiz(int i)
634 vflag = 0;
635 if (i)
636 pchar(makem(i));
640 void setnel(void)
642 if (!nc) {
643 linep = line;
644 if (un1 >= 0) {
645 un = un1;
646 un1 = -1;
648 nel = ll - un;
649 ne = adsp = adrem = 0;
653 int
654 getword(int x)
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;
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;
682 if (j == ohc) {
683 hyoff = 1; /* 1 => don't hyphenate */
684 continue;
686 if (j == ' ') {
687 numtabp[HP].val += sps;
688 widthp = sps;
689 storeword(i, sps);
690 continue;
692 break;
694 storeword(' ' | obits, sps);
695 if (spflg) {
696 storeword(' ' | obits, sps);
697 spflg = 0;
699 g0:
700 if (j == CONT) {
701 pendw = wordp;
702 nflush = 0;
703 flushi();
704 return(1);
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;
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;
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;
741 break;
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;
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);
767 void storeword(Tchar c, int w)
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);
799 widthp = w;
800 wne += w;
801 *wordp++ = c;
802 wch++;
806 Tchar gettch(void)
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 */
824 return(i);
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);
836 return(i);