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