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