xref: /illumos-gate/usr/src/cmd/troff/n7.c (revision 7c478bd9)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
28 /*	  All Rights Reserved  	*/
29 
30 
31 #pragma ident	"%Z%%M%	%I%	%E% SMI"
32 
33 /*
34  * University Copyright- Copyright (c) 1982, 1986, 1988
35  * The Regents of the University of California
36  * All Rights Reserved
37  *
38  * University Acknowledgment- Portions of this document are derived from
39  * software developed by the University of California, Berkeley, and its
40  * contributors.
41  */
42 
43 #ifdef EUC
44 #ifdef NROFF
45 #include <stdlib.h>
46 #include <widec.h>
47 #include <limits.h>
48 #endif /* NROFF */
49 #endif /* EUC */
50 #include "tdef.h"
51 #ifdef NROFF
52 #include "tw.h"
53 #endif
54 #ifdef NROFF
55 #define GETCH gettch
56 tchar	gettch();
57 #endif
58 #ifndef NROFF
59 #define GETCH getch
60 #endif
61 
62 /*
63  * troff7.c
64  *
65  * text
66  */
67 
68 #include <ctype.h>
69 #ifdef EUC
70 #ifdef NROFF
71 #include <wctype.h>
72 #endif /* NROFF */
73 #endif /* EUC */
74 #include "ext.h"
75 #ifdef EUC
76 #ifdef NROFF
77 char	mbbuf2[MB_LEN_MAX + 1];
78 char	*mbbuf2p = mbbuf2;
79 tchar	mtbuf[MB_LEN_MAX + 1];
80 tchar	*mtbufp;
81 int	pendmb = 0;
82 wchar_t	cwc, owc, wceoll;
83 #endif /* NROFF */
84 #endif /* EUC */
85 int	brflg;
86 
87 tbreak()
88 {
89 	register pad, k;
90 	register tchar	*i, j;
91 	register int resol = 0;
92 #ifdef EUC
93 #ifdef NROFF
94 	register tchar	l;
95 #endif /* NROFF */
96 #endif /* EUC */
97 
98 	trap = 0;
99 	if (nb)
100 		return;
101 	if (dip == d && numtab[NL].val == -1) {
102 		newline(1);
103 		return;
104 	}
105 	if (!nc) {
106 		setnel();
107 		if (!wch)
108 			return;
109 		if (pendw)
110 			getword(1);
111 		movword();
112 	} else if (pendw && !brflg) {
113 		getword(1);
114 		movword();
115 	}
116 	*linep = dip->nls = 0;
117 #ifdef NROFF
118 	if (dip == d)
119 		horiz(po);
120 #endif
121 	if (lnmod)
122 		donum();
123 	lastl = ne;
124 	if (brflg != 1) {
125 		totout = 0;
126 	} else if (ad) {
127 		if ((lastl = ll - un) < ne)
128 			lastl = ne;
129 	}
130 	if (admod && ad && (brflg != 2)) {
131 		lastl = ne;
132 		adsp = adrem = 0;
133 		if (admod == 1)
134 			un +=  quant(nel / 2, HOR);
135 		else if (admod == 2)
136 			un += nel;
137 	}
138 	totout++;
139 	brflg = 0;
140 	if (lastl + un > dip->maxl)
141 		dip->maxl = lastl + un;
142 	horiz(un);
143 #ifdef NROFF
144 	if (adrem % t.Adj)
145 		resol = t.Hor;
146 	else
147 		resol = t.Adj;
148 #else
149 	resol = HOR;
150 #endif
151 	adrem = (adrem / resol) * resol;
152 	for (i = line; nc > 0; ) {
153 #ifndef EUC
154 		if ((cbits(j = *i++)) == ' ') {
155 #else
156 #ifndef NROFF
157 		if ((cbits(j = *i++)) == ' ') {
158 #else
159 		if ((cbits(j = *i++) & ~MBMASK) == ' ') {
160 #endif /* NROFF */
161 #endif /* EUC */
162 			pad = 0;
163 			do {
164 				pad += width(j);
165 				nc--;
166 #ifndef EUC
167 			} while ((cbits(j = *i++)) == ' ');
168 #else
169 #ifndef NROFF
170 			} while ((cbits(j = *i++)) == ' ');
171 #else
172 			} while ((cbits(j = *i++) & ~MBMASK) == ' ');
173 #endif /* NROFF */
174 #endif /* EUC */
175 			i--;
176 			pad += adsp;
177 			--nwd;
178 			if (adrem) {
179 				if (adrem < 0) {
180 					pad -= resol;
181 					adrem += resol;
182 				} else if ((totout & 01) || adrem / resol >= nwd) {
183 					pad += resol;
184 					adrem -= resol;
185 				}
186 			}
187 			pchar((tchar) WORDSP);
188 			horiz(pad);
189 		} else {
190 			pchar(j);
191 			nc--;
192 		}
193 	}
194 	if (ic) {
195 		if ((k = ll - un - lastl + ics) > 0)
196 			horiz(k);
197 		pchar(ic);
198 	}
199 	if (icf)
200 		icf++;
201 	else
202 		ic = 0;
203 	ne = nwd = 0;
204 	un = in;
205 	setnel();
206 	newline(0);
207 	if (dip != d) {
208 		if (dip->dnl > dip->hnl)
209 			dip->hnl = dip->dnl;
210 	} else {
211 		if (numtab[NL].val > dip->hnl)
212 			dip->hnl = numtab[NL].val;
213 	}
214 	for (k = ls - 1; k > 0 && !trap; k--)
215 		newline(0);
216 	spread = 0;
217 }
218 
219 donum()
220 {
221 	register i, nw;
222 	extern pchar();
223 
224 	nrbits = nmbits;
225 	nw = width('1' | nrbits);
226 	if (nn) {
227 		nn--;
228 		goto d1;
229 	}
230 	if (numtab[LN].val % ndf) {
231 		numtab[LN].val++;
232 d1:
233 		un += nw * (3 + nms + ni);
234 		return;
235 	}
236 	i = 0;
237 	if (numtab[LN].val < 100)
238 		i++;
239 	if (numtab[LN].val < 10)
240 		i++;
241 	horiz(nw * (ni + i));
242 	nform = 0;
243 	fnumb(numtab[LN].val, pchar);
244 	un += nw * nms;
245 	numtab[LN].val++;
246 }
247 
248 extern int logf;
249 text()
250 {
251 	register tchar i;
252 	static int	spcnt;
253 
254 	nflush++;
255 	numtab[HP].val = 0;
256 	if ((dip == d) && (numtab[NL].val == -1)) {
257 		newline(1);
258 		return;
259 	}
260 	setnel();
261 	if (ce || !fi) {
262 		nofill();
263 		return;
264 	}
265 	if (pendw)
266 		goto t4;
267 	if (pendt)
268 		if (spcnt)
269 			goto t2;
270 		else
271 			goto t3;
272 	pendt++;
273 	if (spcnt)
274 		goto t2;
275 	while ((cbits(i = GETCH())) == ' ') {
276 		spcnt++;
277 		numtab[HP].val += sps;
278 		widthp = sps;
279 	}
280 	if (nlflg) {
281 t1:
282 		nflush = pendt = ch = spcnt = 0;
283 		callsp();
284 		return;
285 	}
286 	ch = i;
287 	if (spcnt) {
288 t2:
289 		tbreak();
290 		if (nc || wch)
291 			goto rtn;
292 		un += spcnt * sps;
293 		spcnt = 0;
294 		setnel();
295 		if (trap)
296 			goto rtn;
297 		if (nlflg)
298 			goto t1;
299 	}
300 t3:
301 	if (spread)
302 		goto t5;
303 	if (pendw || !wch)
304 t4:
305 		if (getword(0))
306 			goto t6;
307 	if (!movword())
308 		goto t3;
309 t5:
310 	if (nlflg)
311 		pendt = 0;
312 	adsp = adrem = 0;
313 	if (ad) {
314 		if (nwd == 1)
315 			adsp = nel;
316 		else
317 			adsp = nel / (nwd - 1);
318 		adsp = (adsp / HOR) * HOR;
319 		adrem = nel - adsp*(nwd-1);
320 	}
321 	brflg = 1;
322 	tbreak();
323 	spread = 0;
324 	if (!trap)
325 		goto t3;
326 	if (!nlflg)
327 		goto rtn;
328 t6:
329 	pendt = 0;
330 	ckul();
331 rtn:
332 	nflush = 0;
333 }
334 
335 
336 nofill()
337 {
338 	register j;
339 	register tchar i;
340 
341 	if (!pendnf) {
342 		over = 0;
343 		tbreak();
344 		if (trap)
345 			goto rtn;
346 		if (nlflg) {
347 			ch = nflush = 0;
348 			callsp();
349 			return;
350 		}
351 		adsp = adrem = 0;
352 		nwd = 10000;
353 	}
354 	while ((j = (cbits(i = GETCH()))) != '\n') {
355 		if (j == ohc)
356 			continue;
357 		if (j == CONT) {
358 			pendnf++;
359 			nflush = 0;
360 			flushi();
361 			ckul();
362 			return;
363 		}
364 		j = width(i);
365 		widthp = j;
366 		numtab[HP].val += j;
367 		storeline(i, j);
368 	}
369 	if (ce) {
370 		ce--;
371 		if ((i = quant(nel / 2, HOR)) > 0)
372 			un += i;
373 	}
374 	if (!nc)
375 		storeline((tchar)FILLER, 0);
376 	brflg = 2;
377 	tbreak();
378 	ckul();
379 rtn:
380 	pendnf = nflush = 0;
381 }
382 
383 
384 callsp()
385 {
386 	register i;
387 
388 	if (flss)
389 		i = flss;
390 	else
391 		i = lss;
392 	flss = 0;
393 	casesp(i);
394 }
395 
396 
397 ckul()
398 {
399 	if (ul && (--ul == 0)) {
400 		cu = 0;
401 		font = sfont;
402 		mchbits();
403 	}
404 	if (it && (--it == 0) && itmac)
405 		control(itmac, 0);
406 }
407 
408 
409 storeline(c, w)
410 register tchar c;
411 {
412 	if (linep >= line + lnsize - 1) {
413 		if (!over) {
414 			flusho();
415 			errprint(gettext("Line overflow."));
416 			over++;
417 			c = LEFTHAND;
418 			w = -1;
419 			goto s1;
420 		}
421 		return;
422 	}
423 s1:
424 	if (w == -1)
425 		w = width(c);
426 	ne += w;
427 	nel -= w;
428 	*linep++ = c;
429 	nc++;
430 }
431 
432 
433 newline(a)
434 int	a;
435 {
436 	register i, j, nlss;
437 	int	opn;
438 
439 	if (a)
440 		goto nl1;
441 	if (dip != d) {
442 		j = lss;
443 		pchar1((tchar)FLSS);
444 		if (flss)
445 			lss = flss;
446 		i = lss + dip->blss;
447 		dip->dnl += i;
448 		pchar1((tchar)i);
449 		pchar1((tchar)'\n');
450 		lss = j;
451 		dip->blss = flss = 0;
452 		if (dip->alss) {
453 			pchar1((tchar)FLSS);
454 			pchar1((tchar)dip->alss);
455 			pchar1((tchar)'\n');
456 			dip->dnl += dip->alss;
457 			dip->alss = 0;
458 		}
459 		if (dip->ditrap && !dip->ditf && dip->dnl >= dip->ditrap && dip->dimac)
460 			if (control(dip->dimac, 0)) {
461 				trap++;
462 				dip->ditf++;
463 			}
464 		return;
465 	}
466 	j = lss;
467 	if (flss)
468 		lss = flss;
469 	nlss = dip->alss + dip->blss + lss;
470 	numtab[NL].val += nlss;
471 #ifndef NROFF
472 	if (ascii) {
473 		dip->alss = dip->blss = 0;
474 	}
475 #endif
476 	pchar1((tchar)'\n');
477 	flss = 0;
478 	lss = j;
479 	if (numtab[NL].val < pl)
480 		goto nl2;
481 nl1:
482 	ejf = dip->hnl = numtab[NL].val = 0;
483 	ejl = frame;
484 	if (donef) {
485 		if ((!nc && !wch) || ndone)
486 			done1(0);
487 		ndone++;
488 		donef = 0;
489 		if (frame == stk)
490 			nflush++;
491 	}
492 	opn = numtab[PN].val;
493 	numtab[PN].val++;
494 	if (npnflg) {
495 		numtab[PN].val = npn;
496 		npn = npnflg = 0;
497 	}
498 nlpn:
499 	if (numtab[PN].val == pfrom) {
500 		print++;
501 		pfrom = -1;
502 	} else if (opn == pto) {
503 		print = 0;
504 		opn = -1;
505 		chkpn();
506 		goto nlpn;
507 	}
508 	if (print)
509 		newpage(numtab[PN].val);	/* supposedly in a clean state so can pause */
510 	if (stop && print) {
511 		dpn++;
512 		if (dpn >= stop) {
513 			dpn = 0;
514 			dostop();
515 		}
516 	}
517 nl2:
518 	trap = 0;
519 	if (numtab[NL].val == 0) {
520 		if ((j = findn(0)) != NTRAP)
521 			trap = control(mlist[j], 0);
522 	} else if ((i = findt(numtab[NL].val - nlss)) <= nlss) {
523 		if ((j = findn1(numtab[NL].val - nlss + i)) == NTRAP) {
524 			flusho();
525 			errprint(gettext("Trap botch."));
526 			done2(-5);
527 		}
528 		trap = control(mlist[j], 0);
529 	}
530 }
531 
532 
533 findn1(a)
534 int	a;
535 {
536 	register i, j;
537 
538 	for (i = 0; i < NTRAP; i++) {
539 		if (mlist[i]) {
540 			if ((j = nlist[i]) < 0)
541 				j += pl;
542 			if (j == a)
543 				break;
544 		}
545 	}
546 	return(i);
547 }
548 
549 
550 chkpn()
551 {
552 	pto = *(pnp++);
553 	pfrom = pto>=0 ? pto : -pto;
554 	if (pto == -32767) {
555 		flusho();
556 		done1(0);
557 	}
558 	if (pto < 0) {
559 		pto = -pto;
560 		print++;
561 		pfrom = 0;
562 	}
563 }
564 
565 
566 findt(a)
567 int	a;
568 {
569 	register i, j, k;
570 
571 	k = 32767;
572 	if (dip != d) {
573 		if (dip->dimac && (i = dip->ditrap - a) > 0)
574 			k = i;
575 		return(k);
576 	}
577 	for (i = 0; i < NTRAP; i++) {
578 		if (mlist[i]) {
579 			if ((j = nlist[i]) < 0)
580 				j += pl;
581 			if ((j -= a) <= 0)
582 				continue;
583 			if (j < k)
584 				k = j;
585 		}
586 	}
587 	i = pl - a;
588 	if (k > i)
589 		k = i;
590 	return(k);
591 }
592 
593 
594 findt1()
595 {
596 	register i;
597 
598 	if (dip != d)
599 		i = dip->dnl;
600 	else
601 		i = numtab[NL].val;
602 	return(findt(i));
603 }
604 
605 
606 eject(a)
607 struct s *a;
608 {
609 	register savlss;
610 
611 	if (dip != d)
612 		return;
613 	ejf++;
614 	if (a)
615 		ejl = a;
616 	else
617 		ejl = frame;
618 	if (trap)
619 		return;
620 e1:
621 	savlss = lss;
622 	lss = findt(numtab[NL].val);
623 	newline(0);
624 	lss = savlss;
625 	if (numtab[NL].val && !trap)
626 		goto e1;
627 }
628 
629 
630 movword()
631 {
632 	register w;
633 	register tchar i, *wp;
634 	int	savwch, hys;
635 
636 	over = 0;
637 	wp = wordp;
638 	if (!nwd) {
639 #ifndef EUC
640 		while (cbits(i = *wp++) == ' ') {
641 #else
642 #ifndef NROFF
643 		while (cbits(i = *wp++) == ' ') {
644 #else
645 		while ((cbits(i = *wp++) & ~MBMASK) == ' ') {
646 #endif /* NROFF */
647 #endif /* EUC */
648 			wch--;
649 			wne -= sps;
650 		}
651 		wp--;
652 	}
653 	if (wne > nel && !hyoff && hyf && (!nwd || nel > 3 * sps) &&
654 	   (!(hyf & 02) || (findt1() > lss)))
655 		hyphen(wp);
656 	savwch = wch;
657 	hyp = hyptr;
658 	nhyp = 0;
659 	while (*hyp && *hyp <= wp)
660 		hyp++;
661 	while (wch) {
662 		if (hyoff != 1 && *hyp == wp) {
663 			hyp++;
664 			if (!wdstart || (wp > wdstart + 1 && wp < wdend &&
665 			   (!(hyf & 04) || wp < wdend - 1) &&		/* 04 => last 2 */
666 			   (!(hyf & 010) || wp > wdstart + 2))) {	/* 010 => 1st 2 */
667 				nhyp++;
668 				storeline((tchar)IMP, 0);
669 			}
670 		}
671 		i = *wp++;
672 		w = width(i);
673 		wne -= w;
674 		wch--;
675 		storeline(i, w);
676 	}
677 	if (nel >= 0) {
678 		nwd++;
679 		return(0);	/* line didn't fill up */
680 	}
681 #ifndef NROFF
682 	xbits((tchar)HYPHEN, 1);
683 #endif
684 	hys = width((tchar)HYPHEN);
685 m1:
686 	if (!nhyp) {
687 		if (!nwd)
688 			goto m3;
689 		if (wch == savwch)
690 			goto m4;
691 	}
692 	if (*--linep != IMP)
693 		goto m5;
694 	if (!(--nhyp))
695 		if (!nwd)
696 			goto m2;
697 	if (nel < hys) {
698 		nc--;
699 		goto m1;
700 	}
701 m2:
702 	if ((i = cbits(*(linep - 1))) != '-' && i != EMDASH) {
703 		*linep = (*(linep - 1) & SFMASK) | HYPHEN;
704 		w = width(*linep);
705 		nel -= w;
706 		ne += w;
707 		linep++;
708 	}
709 m3:
710 	nwd++;
711 m4:
712 	wordp = wp;
713 	return(1);	/* line filled up */
714 m5:
715 	nc--;
716 	w = width(*linep);
717 	ne -= w;
718 	nel += w;
719 	wne += w;
720 	wch++;
721 	wp--;
722 	goto m1;
723 }
724 
725 
726 horiz(i)
727 int	i;
728 {
729 	vflag = 0;
730 	if (i)
731 		pchar(makem(i));
732 }
733 
734 
735 setnel()
736 {
737 	if (!nc) {
738 		linep = line;
739 		if (un1 >= 0) {
740 			un = un1;
741 			un1 = -1;
742 		}
743 		nel = ll - un;
744 		ne = adsp = adrem = 0;
745 	}
746 }
747 
748 
749 getword(x)
750 int	x;
751 {
752 	register int j, k;
753 	register tchar i, *wp;
754 	int noword;
755 #ifdef EUC
756 #ifdef NROFF
757 	wchar_t *wddelim;
758 	char mbbuf3[MB_LEN_MAX + 1];
759 	char *mbbuf3p;
760 	int wbf, n;
761 	tchar m;
762 #endif /* NROFF */
763 #endif /* EUC */
764 
765 	noword = 0;
766 	if (x)
767 		if (pendw) {
768 			*pendw = 0;
769 			goto rtn;
770 		}
771 	if (wordp = pendw)
772 		goto g1;
773 	hyp = hyptr;
774 	wordp = word;
775 	over = wne = wch = 0;
776 	hyoff = 0;
777 #ifdef EUC
778 #ifdef NROFF
779 	mtbufp = mtbuf;
780 	if (pendmb) {
781 		while(*mtbufp) {
782 			switch(*mtbufp & MBMASK) {
783 			case LASTOFMB:
784 			case BYTE_CHR:
785 				storeword(*mtbufp++, -1);
786 				break;
787 
788 			default:
789 				storeword(*mtbufp++, 0);
790 			}
791 		}
792 		mtbufp = mtbuf;
793 		pendmb = 0;
794 		goto g1;
795 	}
796 #endif /* NROFF */
797 #endif /* EUC */
798 	while (1) {	/* picks up 1st char of word */
799 		j = cbits(i = GETCH());
800 #ifdef EUC
801 #ifdef NROFF
802 		if (multi_locale)
803 			if (collectmb(i))
804 				continue;
805 #endif /* NROFF */
806 #endif /* EUC */
807 		if (j == '\n') {
808 			wne = wch = 0;
809 			noword = 1;
810 			goto rtn;
811 		}
812 		if (j == ohc) {
813 			hyoff = 1;	/* 1 => don't hyphenate */
814 			continue;
815 		}
816 		if (j == ' ') {
817 			numtab[HP].val += sps;
818 			widthp = sps;
819 			storeword(i, sps);
820 			continue;
821 		}
822 		break;
823 	}
824 #ifdef EUC
825 #ifdef NROFF
826 	if (!multi_locale)
827 		goto a0;
828 	if (wddlm && iswprint(wceoll) && iswprint(cwc) &&
829 	    (!iswascii(wceoll) || !iswascii(cwc)) &&
830 	    !iswspace(wceoll) && !iswspace(cwc)) {
831 		wddelim = (*wddlm)(wceoll, cwc, 1);
832 		wceoll = 0;
833 		if (*wddelim != ' ') {
834 			if (!*wddelim) {
835 				storeword(((*wdbdg)(wceoll, cwc, 1) < 3) ?
836 					  ZWDELIM(1) : ZWDELIM(2), 0);
837 			} else {
838 				while (*wddelim) {
839 					if ((n = wctomb(mbbuf3, *wddelim++))
840 					    > 0) {
841 						mbbuf3[n] = 0;
842 						n--;
843 						mbbuf3p = mbbuf3 + n;
844 						while(n) {
845 							m = *(mbbuf3p-- - n--) &
846 							    0xff | MIDDLEOFMB |
847 							    ZBIT;
848 							storeword(m, 0);
849 						}
850 						m = *mbbuf3p & 0xff | LASTOFMB;
851 						storeword(m, -1);
852 					} else {
853 						storeword(' ' | chbits, sps);
854 						break;
855 					}
856 				}
857 			}
858 			spflg = 0;
859 			goto g0;
860 		}
861 	}
862 a0:
863 #endif /* NROFF */
864 #endif /* EUC */
865 	storeword(' ' | chbits, sps);
866 	if (spflg) {
867 		storeword(' ' | chbits, sps);
868 		spflg = 0;
869 	}
870 g0:
871 	if (j == CONT) {
872 		pendw = wordp;
873 		nflush = 0;
874 		flushi();
875 		return(1);
876 	}
877 	if (hyoff != 1) {
878 		if (j == ohc) {
879 			hyoff = 2;
880 			*hyp++ = wordp;
881 			if (hyp > (hyptr + NHYP - 1))
882 				hyp = hyptr + NHYP - 1;
883 			goto g1;
884 		}
885 		if (j == '-' || j == EMDASH)
886 			if (wordp > word + 1) {
887 				hyoff = 2;
888 				*hyp++ = wordp + 1;
889 				if (hyp > (hyptr + NHYP - 1))
890 					hyp = hyptr + NHYP - 1;
891 			}
892 	}
893 	j = width(i);
894 	numtab[HP].val += j;
895 #ifndef EUC
896 	storeword(i, j);
897 #else
898 #ifndef NROFF
899 	storeword(i, j);
900 #else
901 	if (multi_locale) {
902 		mtbufp = mtbuf;
903 		while(*mtbufp) {
904 			switch(*mtbufp & MBMASK) {
905 			case LASTOFMB:
906 			case BYTE_CHR:
907 				storeword(*mtbufp++, j);
908 				break;
909 
910 			default:
911 				storeword(*mtbufp++, 0);
912 			}
913 		}
914 		mtbufp = mtbuf;
915 	} else {
916 		storeword(i, j);
917 	}
918 #endif /* NROFF */
919 #endif /* EUC */
920 g1:
921 	j = cbits(i = GETCH());
922 #ifdef EUC
923 #ifdef NROFF
924 	if (multi_locale)
925 		if (collectmb(i))
926 			goto g1;
927 #endif /* NROFF */
928 #endif /* EUC */
929 	if (j != ' ') {
930 		static char *sentchar = ".?!:";	/* sentence terminators */
931 		if (j != '\n')
932 #ifdef EUC
933 #ifdef NROFF
934 			if (!multi_locale)
935 #endif /* NROFF */
936 #endif /* EUC */
937 			goto g0;
938 #ifdef EUC
939 #ifdef NROFF
940 			else {
941 				if (!wdbdg || (iswascii(cwc) && iswascii(owc)))
942 					goto g0;
943 				if ((wbf = (*wdbdg)(owc, cwc, 1)) < 5) {
944 					pendmb++;
945 					storeword((wbf < 3) ? ZWDELIM(1) :
946 						  ZWDELIM(2), 0);
947 					*wordp = 0;
948 					goto rtn;
949 				} else goto g0;
950 			}
951 #endif /* NROFF */
952 #endif /* EUC */
953 		wp = wordp-1;	/* handle extra space at end of sentence */
954 		while (wp >= word) {
955 			j = cbits(*wp--);
956 			if (j=='"' || j=='\'' || j==')' || j==']' || j=='*' || j==DAGGER)
957 				continue;
958 			for (k = 0; sentchar[k]; k++)
959 				if (j == sentchar[k]) {
960 					spflg++;
961 					break;
962 				}
963 			break;
964 		}
965 	}
966 #ifdef EUC
967 #ifdef NROFF
968 	wceoll = owc;
969 #endif /* NROFF */
970 #endif /* EUC */
971 	*wordp = 0;
972 	numtab[HP].val += sps;
973 rtn:
974 	for (wp = word; *wp; wp++) {
975 		j = cbits(*wp);
976 		if (j == ' ')
977 			continue;
978 		if (!ischar(j) || (!isdigit(j) && j != '-'))
979 			break;
980 	}
981 	if (*wp == 0)	/* all numbers, so don't hyphenate */
982 		hyoff = 1;
983 	wdstart = 0;
984 	wordp = word;
985 	pendw = 0;
986 	*hyp++ = 0;
987 	setnel();
988 	return(noword);
989 }
990 
991 
992 storeword(c, w)
993 register tchar c;
994 register int	w;
995 {
996 
997 	if (wordp >= &word[WDSIZE - 3]) {
998 		if (!over) {
999 			flusho();
1000 			errprint(gettext("Word overflow."));
1001 			over++;
1002 			c = LEFTHAND;
1003 			w = -1;
1004 			goto s1;
1005 		}
1006 		return;
1007 	}
1008 s1:
1009 	if (w == -1)
1010 		w = width(c);
1011 	widthp = w;
1012 	wne += w;
1013 	*wordp++ = c;
1014 	wch++;
1015 }
1016 
1017 
1018 #ifdef NROFF
1019 tchar gettch()
1020 {
1021 	extern int c_isalnum;
1022 	tchar i;
1023 	int j;
1024 
1025 	i = getch();
1026 	j = cbits(i);
1027 	if (ismot(i) || fbits(i) != ulfont)
1028 		return(i);
1029 	if (cu) {
1030 		if (trtab[j] == ' ') {
1031 			setcbits(i, '_');
1032 			setfbits(i, FT);	/* default */
1033 		}
1034 		return(i);
1035 	}
1036 	/* should test here for characters that ought to be underlined */
1037 	/* in the old nroff, that was the 200 bit on the width! */
1038 	/* for now, just do letters, digits and certain special chars */
1039 	if (j <= 127) {
1040 		if (!isalnum(j))
1041 			setfbits(i, FT);
1042 	} else {
1043 		if (j < c_isalnum)
1044 			setfbits(i, FT);
1045 	}
1046 	return(i);
1047 }
1048 
1049 
1050 #endif
1051 #ifdef EUC
1052 #ifdef NROFF
1053 collectmb(i)
1054 tchar	i;
1055 {
1056 	int busy;
1057 
1058 	*mtbufp++ = i;
1059 	*mbbuf2p++ = i & BYTEMASK;
1060 	*mtbufp = *mbbuf2p = 0;
1061 	if (ismot(i)) {
1062 		mtbufp = mtbuf;
1063 		mbbuf2p = mbbuf2;
1064 		owc = 0;
1065 		cwc = 0;
1066 		return(busy = 0);
1067 	}
1068 	if ((i & MBMASK) == MIDDLEOFMB) {
1069 		if (mtbufp <= (mtbuf + MB_CUR_MAX)) {
1070 			busy = 1;
1071 		} else {
1072 			*(mtbufp - 1) &= ~MBMASK;
1073 			goto gotmb;
1074 		}
1075 	} else {
1076 		if ((i & MBMASK) == LASTOFMB)
1077 			*(mtbufp - 1) &= ~MBMASK;
1078 gotmb:
1079 		mtbufp = mtbuf;
1080 		owc = cwc;
1081 		if (mbtowc(&cwc, mbbuf2, MB_CUR_MAX) <= 0) {
1082 			mtbufp = mtbuf;
1083 			while (*mtbufp) {
1084 				setcbits(*mtbufp, (*mtbufp & 0x1ff));
1085 				mtbufp++;
1086 			}
1087 			mtbufp = mtbuf;
1088 		}
1089 		mbbuf2p = mbbuf2;
1090 		busy = 0;
1091 	}
1092 	return(busy);
1093 }
1094 
1095 
1096 #endif /* NROFF */
1097 #endif /* EUC */
1098