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