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