1 /* $MirOS: src/usr.bin/oldroff/nroff/n7.c,v 1.4 2008/11/08 23:04:41 tg Exp $ */
2 
3 /*-
4  * Copyright (c) 1979, 1980, 1981, 1986, 1988, 1990, 1991, 1992
5  *     The Regents of the University of California.
6  * Copyright (C) Caldera International Inc.  2001-2002.
7  * Copyright (c) 2003, 2004
8  *	Thorsten "mirabilos" Glaser <tg@mirbsd.org>
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms,
12  * with or without modification, are permitted provided
13  * that the following conditions are met:
14  *
15  * Redistributions of source code and documentation must retain
16  * the above copyright notice, this list of conditions and the
17  * following disclaimer.  Redistributions in binary form must
18  * reproduce the above copyright notice, this list of conditions
19  * and the following disclaimer in the documentation and/or other
20  * materials provided with the distribution.
21  *
22  * All advertising materials mentioning features or use of this
23  * software must display the following acknowledgement:
24  *   This product includes software developed or owned by
25  *   Caldera International, Inc.
26  *
27  * Neither the name of Caldera International, Inc. nor the names
28  * of other contributors may be used to endorse or promote products
29  * derived from this software without specific prior written permission.
30  *
31  * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
32  * INTERNATIONAL, INC. AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
33  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35  * ARE DISCLAIMED.  IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
36  * LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
37  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
38  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
39  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
40  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
41  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
42  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43  */
44 
45 #ifndef lint
46 static char sccsid[] = "@(#)n7.c	4.6 (Berkeley) 5/2/91";
47 #endif /* not lint */
48 
49 #include "tdef.h"
50 extern
51 #include "d.h"
52 extern
53 #include "v.h"
54 #ifdef NROFF
55 extern
56 #include "tw.h"
57 #endif
58 #include "sdef.h"
59 #ifdef NROFF
60 #define GETCH gettch
61 #endif
62 #ifndef NROFF
63 #define GETCH getch
64 #endif
65 
66 /*
67 troff7.c
68 
69 text
70 */
71 
72 extern struct s *frame, *stk;
73 extern struct s *ejl;
74 
75 extern int pl;
76 extern int trap;
77 extern int flss;
78 extern int npnflg;
79 extern int npn;
80 extern int stop;
81 extern int nflush;
82 extern int ejf;
83 extern int ascii;
84 extern int donef;
85 extern int nc;
86 extern int wch;
87 extern int dpn;
88 extern int ndone;
89 extern int lss;
90 extern int pto;
91 extern int pfrom;
92 extern int print;
93 extern int nlistx[NTRAP];
94 extern int mlist[NTRAP];
95 extern int *pnp;
96 extern int nb;
97 extern int ic;
98 extern int icf;
99 extern int ics;
100 extern int ne;
101 extern int ll;
102 extern int un;
103 extern int un1;
104 extern int in;
105 extern int ls;
106 extern int spread;
107 extern int totout;
108 extern int nwd;
109 extern int *pendw;
110 extern int *linep;
111 extern int line[];
112 extern int lastl;
113 extern int ch;
114 extern int ce;
115 extern int fi;
116 extern int nlflg;
117 extern int pendt;
118 extern int sps;
119 extern int adsp;
120 extern int pendnf;
121 extern int over;
122 extern int adrem;
123 extern int nel;
124 extern int ad;
125 extern int ohc;
126 extern int hyoff;
127 extern int nhyp;
128 extern int spflg;
129 extern int word[];
130 extern int *wordp;
131 extern int wne;
132 extern int chbits;
133 extern int cwidth;
134 extern int widthp;
135 extern int hyf;
136 extern int xbitf;
137 extern int vflag;
138 extern int ul;
139 extern int cu;
140 extern int font;
141 extern int sfont;
142 extern int it;
143 extern int itmac;
144 extern int *hyptr[NHYP];
145 extern int **hyp;
146 extern int *wdstart, *wdend;
147 extern int lnmod;
148 extern int admod;
149 extern int nn;
150 extern int nms;
151 extern int ndf;
152 extern int ni;
153 extern int nform;
154 extern int lnsize;
155 extern int po;
156 extern int ulbit;
157 extern int *vlist;
158 extern int nrbits;
159 extern int nmbits;
160 extern char trtab[];
161 extern int xxx;
162 int brflg;
163 
tbreak()164 tbreak(){
165 	register *i, j, pad;
166 	int res;
167 
168 	trap = 0;
169 	if(nb)return;
170 	if((dip == d) && (v.nl == -1)){
171 		newline(1);
172 		return;
173 	}
174 	if(!nc){
175 		setnel();
176 		if(!wch)return;
177 		if(pendw)getword(1);
178 		movword();
179 	}else if(pendw && !brflg){
180 		getword(1);
181 		movword();
182 	}
183 	*linep = dip->nls = 0;
184 #ifdef NROFF
185 	if(dip == d)horiz(po);
186 #endif
187 	if(lnmod)donum();
188 	lastl = ne;
189 	if(brflg != 1){
190 		totout = 0;
191 	}else if(ad){
192 		if((lastl = (ll - un)) < ne)lastl = ne;
193 	}
194 	if(admod && ad && (brflg != 2)){
195 		lastl = ne;
196 		adsp = adrem = 0;
197 #ifdef NROFF
198 		if(admod == 1)un +=  quant(nel/2,t.Adj);
199 #endif
200 #ifndef NROFF
201 		if(admod == 1)un += nel/2;
202 #endif
203 		else if(admod ==2)un += nel;
204 	}
205 	totout++;
206 	brflg = 0;
207 	if((lastl+un) > dip->maxl)dip->maxl = (lastl+un);
208 	horiz(un);
209 #ifdef NROFF
210 	if(adrem%t.Adj)res = t.Hor; else res = t.Adj;
211 #endif
212 	for(i = line;nc > 0;){
213 		if(((j = *i++) & CMASK) == ' '){
214 			pad = 0;
215 			do{
216 				pad += width(j);
217 				nc--;
218 			  }while(((j = *i++) & CMASK) == ' ');
219 			i--;
220 			pad += adsp;
221 			--nwd;
222 			if(adrem){
223 				if(adrem < 0){
224 #ifdef NROFF
225 					pad -= res;
226 					adrem += res;
227 				}else if((totout&01) ||
228 					((adrem/res)>=(nwd))){
229 					pad += res;
230 					adrem -= res;
231 #endif
232 #ifndef NROFF
233 					pad--;
234 					adrem++;
235 				}else{
236 					pad++;
237 					adrem--;
238 #endif
239 				}
240 			}
241 			horiz(pad);
242 		}else{
243 			pchar(j);
244 			nc--;
245 		}
246 	}
247 	if(ic){
248 		if((j = ll - un - lastl + ics) > 0)horiz(j);
249 		pchar(ic);
250 	}
251 	if(icf)icf++;
252 		else ic = 0;
253 	ne = nwd = 0;
254 	un = in;
255 	setnel();
256 	newline(0);
257 	if(dip != d){if(dip->dnl > dip->hnl)dip->hnl = dip->dnl;}
258 	else{if(v.nl > dip->hnl)dip->hnl = v.nl;}
259 	for(j=ls-1; (j >0) && !trap; j--)newline(0);
260 	spread = 0;
261 }
donum()262 donum(){
263 	register i, nw;
264 	extern pchar();
265 
266 	nrbits = nmbits;
267 	nw = width('1' | nrbits);
268 	if(nn){
269 		nn--;
270 		goto d1;
271 	}
272 	if(v.ln%ndf){
273 		v.ln++;
274 	d1:
275 		un += nw*(3+nms+ni);
276 		return;
277 	}
278 	i = 0;
279 	if(v.ln<100)i++;
280 	if(v.ln<10)i++;
281 	horiz(nw*(ni+i));
282 	nform = 0;
283 	fnumb(v.ln,pchar);
284 	un += nw*nms;
285 	v.ln++;
286 }
text()287 text(){
288 	register i;
289 	static int spcnt;
290 
291 	nflush++;
292 	if((dip == d) && (v.nl == -1)){newline(1); return;}
293 	setnel();
294 	if(ce || !fi){
295 		nofill();
296 		return;
297 	}
298 	if(pendw)goto t4;
299 	if(pendt)if(spcnt)goto t2; else goto t3;
300 	pendt++;
301 	if(spcnt)goto t2;
302 	while(((i = GETCH()) & CMASK) == ' ')spcnt++;
303 	if(nlflg){
304 	t1:
305 		nflush = pendt = ch = spcnt = 0;
306 		callsp();
307 		return;
308 	}
309 	ch = i;
310 	if(spcnt){
311 	t2:
312 		tbreak();
313 		if(nc || wch)goto rtn;
314 		un += spcnt*sps;
315 		spcnt = 0;
316 		setnel();
317 		if(trap)goto rtn;
318 		if(nlflg)goto t1;
319 	}
320 t3:
321 	if(spread)goto t5;
322 	if(pendw || !wch)
323 	t4:
324 		if(getword(0))goto t6;
325 	if(!movword())goto t3;
326 t5:
327 	if(nlflg)pendt = 0;
328 	adsp = adrem = 0;
329 	if(ad){
330 /* jfr */	if (nwd==1) adsp=nel; else adsp=nel/(nwd-1);
331 #ifdef NROFF
332 		adsp = (adsp/t.Adj)*t.Adj;
333 #endif
334 		adrem = nel - adsp*(nwd-1);
335 	}
336 	brflg = 1;
337 	tbreak();
338 	spread = 0;
339 	if(!trap)goto t3;
340 	if(!nlflg)goto rtn;
341 t6:
342 	pendt = 0;
343 	ckul();
344 rtn:
345 	nflush = 0;
346 }
nofill()347 nofill(){
348 	register i, j;
349 
350 	if(!pendnf){
351 		over = 0;
352 		tbreak();
353 		if(trap)goto rtn;
354 		if(nlflg){
355 			ch = nflush = 0;
356 			callsp();
357 			return;
358 		}
359 		adsp = adrem = 0;
360 		nwd = 10000;
361 	}
362 	while((j = ((i = GETCH()) & CMASK)) != '\n'){
363 		if(j == ohc)continue;
364 		if(j == CONT){
365 			pendnf++;
366 			nflush = 0;
367 			flushi();
368 			ckul();
369 			return;
370 		}
371 		storeline(i,-1);
372 	}
373 	if(ce){
374 		ce--;
375 		if((i=quant(nel/2,HOR)) > 0)un += i;
376 	}
377 	if(!nc)storeline(FILLER,0);
378 	brflg = 2;
379 	tbreak();
380 	ckul();
381 rtn:
382 	pendnf = nflush = 0;
383 }
callsp()384 callsp(){
385 	register i;
386 
387 	if(flss)i = flss; else i = lss;
388 	flss = 0;
389 	casesp(i);
390 }
ckul()391 ckul(){
392 	if(ul && (--ul == 0)){
393 			cu = 0;
394 			font = sfont;
395 			mchbits();
396 	}
397 	if(it && (--it == 0) && itmac)control(itmac,0);
398 }
storeline(c,w)399 storeline(c,w){
400 	register i;
401 
402 	if((c & CMASK) == JREG){
403 		if((i=findr(c>>BYTE)) != -1)vlist[i] = ne;
404 		return;
405 	}
406 	if(linep >= (line + lnsize - 1)){
407 		if(!over){
408 			prstrfl("Line overflow.\n");
409 			over++;
410 		c = 0343;
411 		w = -1;
412 		goto s1;
413 		}
414 		return;
415 	}
416 s1:
417 	if(w == -1)w = width(c);
418 	ne += w;
419 	nel -= w;
420 /*
421  *	if( cu && !(c & MOT) && (trtab[(c & CMASK)] == ' '))
422  *		c = ((c & ~ulbit) & ~CMASK) | '_';
423  */
424 	*linep++ = c;
425 	nc++;
426 }
newline(a)427 newline(a)
428 int a;
429 {
430 	register i, j, nlss;
431 	int opn;
432 
433 	if(a)goto nl1;
434 	if(dip != d){
435 		j = lss;
436 		pchar1(FLSS);
437 		if(flss)lss = flss;
438 		i = lss + dip->blss;
439 		dip->dnl += i;
440 		pchar1(i);
441 		pchar1('\n');
442 		lss = j;
443 		dip->blss = flss = 0;
444 		if(dip->alss){
445 			pchar1(FLSS);
446 			pchar1(dip->alss);
447 			pchar1('\n');
448 			dip->dnl += dip->alss;
449 			dip->alss = 0;
450 		}
451 		if(dip->ditrap && !dip->ditf &&
452 			(dip->dnl >= dip->ditrap) && dip->dimac)
453 			if(control(dip->dimac,0)){trap++; dip->ditf++;}
454 		return;
455 	}
456 	j = lss;
457 	if(flss)lss = flss;
458 	nlss = dip->alss + dip->blss + lss;
459 	v.nl += nlss;
460 #ifndef NROFF
461 	if(ascii){dip->alss = dip->blss = 0;}
462 #endif
463 	pchar1('\n');
464 	flss = 0;
465 	lss = j;
466 	if(v.nl < pl)goto nl2;
467 nl1:
468 	ejf = dip->hnl = v.nl = 0;
469 	ejl = frame;
470 	if(donef == 1){
471 		if((!nc && !wch) || ndone)done1(0);
472 		ndone++;
473 		donef = 0;
474 		if(frame == stk)nflush++;
475 	}
476 	opn = v.pn;
477 	v.pn++;
478 	if(npnflg){
479 		v.pn = npn;
480 		npn = npnflg = 0;
481 	}
482 nlpn:
483 	if(v.pn == pfrom){
484 		print++;
485 	}else if(opn == pto || v.pn > pto){
486 		print = 0;
487 		chkpn();
488 		goto nlpn;
489 		}
490 	if(stop && print){
491 		dpn++;
492 		if(dpn >= stop){
493 			dpn = 0;
494 			dostop();
495 		}
496 	}
497 nl2:
498 	trap = 0;
499 	if(v.nl == 0){
500 		if((j = findn(0)) != NTRAP)
501 			trap = control(mlist[j],0);
502 	} else if((i = findt(v.nl-nlss)) <= nlss){
503 		if((j = findn1(v.nl-nlss+i)) == NTRAP){
504 			prstrfl("Trap botch.\n");
505 			done2(-5);
506 		}
507 		trap = control(mlist[j],0);
508 	}
509 }
findn1(a)510 findn1(a)
511 int a;
512 {
513 	register i, j;
514 
515 	for(i=0; i<NTRAP; i++){
516 		if(mlist[i]){
517 			if((j = nlistx[i]) < 0)j += pl;
518 			if(j == a)break;
519 		}
520 	}
521 	return(i);
522 }
chkpn()523 chkpn(){
524 	pfrom = pto = *(pnp++);
525 	if(pto == -1){
526 		flusho();
527 		done1(0);
528 	}
529 	if(pto == -2){
530 		print++;
531 		pfrom = 0;
532 		pto = 10000;
533 	}
534 	else if(pto & MOT){
535 		print++;
536 		pto &= ~MOT;
537 		pfrom = 0;
538 	}
539 }
findt(a)540 findt(a)
541 int a;
542 {
543 	register i, j, k;
544 
545 	k = 32767;
546 	if(dip != d){
547 		if(dip->dimac && ((i = dip->ditrap -a) > 0))k = i;
548 		return(k);
549 	}
550 	for(i=0; i<NTRAP; i++){
551 		if(mlist[i]){
552 			if((j = nlistx[i]) < 0)j += pl;
553 			if((j -= a)  <=  0)continue;
554 			if(j < k)k = j;
555 		}
556 	}
557 	i = pl - a;
558 	if(k > i)k = i;
559 	return(k);
560 }
findt1()561 findt1(){
562 	register i;
563 
564 	if(dip != d)i = dip->dnl;
565 		else i = v.nl;
566 	return(findt(i));
567 }
568 eject(a)
569 struct s *a;
570 {
571 	register savlss;
572 
573 	if(dip != d)return;
574 	ejf++;
575 	if(a)ejl = a;
576 		else ejl = frame;
577 	if(trap)return;
578 e1:
579 	savlss = lss;
580 	lss = findt(v.nl);
581 	newline(0);
582 	lss = savlss;
583 	if(v.nl && !trap)goto e1;
584 }
movword()585 movword(){
586 	register i, w, *wp;
587 	int savwch, hys;
588 
589 	over = 0;
590 	wp = wordp;
591 	if(!nwd){
592 		while(((i = *wp++) & CMASK) == ' '){
593 			wch--;
594 			wne -= width(i);
595 		}
596 		wp--;
597 	}
598 	if((wne > nel) &&
599 	   !hyoff && hyf &&
600 	   (!nwd || (nel > 3*sps)) &&
601 	   (!(hyf & 02) || (findt1() > lss))
602 	  )hyphen(wp);
603 	savwch = wch;
604 	hyp = hyptr;
605 	nhyp = 0;
606 	while(*hyp && (*hyp <= wp))hyp++;
607 	while(wch){
608 		if((hyoff != 1) && (*hyp == wp)){
609 			hyp++;
610 			if(!wdstart ||
611 			   ((wp > (wdstart+1)) &&
612 			    (wp < wdend) &&
613 			    (!(hyf & 04) || (wp < (wdend-1))) &&
614 			    (!(hyf & 010) || (wp > (wdstart+2)))
615 			   )
616 			  ){
617 				nhyp++;
618 				storeline(IMP,0);
619 			}
620 		}
621 		i = *wp++;
622 		w = width(i);
623 		wne -= w;
624 		wch--;
625 		storeline(i,w);
626 	}
627 	if(nel >= 0){
628 		nwd++;
629 		return(0);
630 	}
631 	xbitf = 1;
632 	hys = width(0200); /*hyphen*/
633 m1:
634 	if(!nhyp){
635 		if(!nwd)goto m3;
636 		if(wch == savwch)goto m4;
637 	}
638 	if(*--linep != IMP)goto m5;
639 	if(!(--nhyp))
640 		if(!nwd)goto m2;
641 	if(nel < hys){
642 		nc--;
643 		goto m1;
644 	}
645 m2:
646 	if(((i = *(linep-1) & CMASK) != '-') &&
647 	   (i != 0203)
648 	  ){
649 	*linep = (*(linep-1) & ~CMASK) | 0200;
650 	w = width(*linep);
651 	nel -= w;
652 	ne += w;
653 	linep++;
654 /*
655 	hsend();
656 */
657 	}
658 m3:
659 	nwd++;
660 m4:
661 	wordp = wp;
662 	return(1);
663 m5:
664 	nc--;
665 	w = width(*linep);
666 	ne -= w;
667 	nel += w;
668 	wne += w;
669 	wch++;
670 	wp--;
671 	goto m1;
672 }
horiz(i)673 horiz(i)
674 int i;
675 {
676 	vflag = 0;
677 	if(i)pchar(makem(i));
678 }
setnel()679 setnel(){
680 	if(!nc){
681 		linep = line;
682 		if(un1 >= 0){
683 			un = un1;
684 			un1 = -1;
685 		}
686 		nel = ll - un;
687 		ne = adsp = adrem = 0;
688 	}
689 }
getword(x)690 getword(x)
691 int x;
692 {
693 	register i, j, swp;
694 	int noword;
695 
696 	noword = 0;
697 	if(x)if(pendw){
698 		*pendw = 0;
699 		goto rtn;
700 	}
701 	if(wordp = pendw)goto g1;
702 	hyp = hyptr;
703 	wordp = word;
704 	over = wne = wch = 0;
705 	hyoff = 0;
706 	while(1){
707 		j = (i = GETCH()) & CMASK;
708 		if(j == '\n'){
709 			wne = wch = 0;
710 			noword = 1;
711 			goto rtn;
712 		}
713 		if(j == ohc){
714 			hyoff = 1;
715 			continue;
716 		}
717 		if(j == ' '){
718 			storeword(i,width(i));	/* XXX */
719 			continue;
720 		}
721 		break;
722 	}
723 	swp = widthp;
724 	storeword(' ' | chbits, -1);
725 	if(spflg > 0){
726 		storeword(' ' | chbits, -1);
727 		spflg = 0;
728 	}
729 	widthp = swp;
730 g0:
731 	if(j == CONT){
732 		pendw = wordp;
733 		nflush = 0;
734 		flushi();
735 		return(1);
736 	}
737 	if(hyoff != 1){
738 		if(j == ohc){
739 			hyoff = 2;
740 			*hyp++ = wordp;
741 			if(hyp > (hyptr+NHYP-1))hyp = hyptr+NHYP-1;
742 			goto g1;
743 		}
744 		if((j == '-') ||
745 		   (j == 0203) /*3/4 Em dash*/
746 		  )if(wordp > word+1){
747 			hyoff = 2;
748 			*hyp++ = wordp + 1;
749 			if(hyp > (hyptr+NHYP-1))hyp = hyptr+NHYP-1;
750 		}
751 	}
752 	storeword(i,width(i));	/* XXX */
753 g1:
754 	j = (i = GETCH()) & CMASK;
755 	if(j != ' '){
756 		if(j != '\n')goto g0;
757 		j = *(wordp-1) & CMASK;
758 		if((spflg >= 0) &&
759 		  ((j == '.') ||
760 		   (j == '!') ||
761 		   (j == '?')))spflg++;
762 	}
763 	*wordp = 0;
764 rtn:
765 	wdstart = 0;
766 	wordp = word;
767 	pendw = 0;
768 	*hyp++ = 0;
769 	setnel();
770 	return(noword);
771 }
storeword(c,w)772 storeword(c,w)
773 int c, w;
774 {
775 
776 	if(wordp >= &word[WDSIZE - 1]){
777 		if(!over){
778 			prstrfl("Word overflow.\n");
779 			over++;
780 			c = 0343;
781 			w = -1;
782 		goto s1;
783 		}
784 		return;
785 	}
786 s1:
787 	if(w == -1)w = width(c);
788 	wne += w;
789 	*wordp++ = c;
790 	wch++;
791 }
792 #ifdef NROFF
793 extern char trtab[];
gettch()794 gettch(){
795 	register int i, j;
796 
797 	if(!((i = getch()) & MOT) && (i & ulbit)){
798 		j = i&CMASK;
799 		if(cu && (trtab[j] == ' '))
800 			i = ((i & ~ulbit)& ~CMASK) | '_';
801 		if(!cu && (j>32) && (j<0370) && !(*t.codetab[j-32] & 0200))
802 			i &= ~ulbit;
803 	}
804 	return(i);
805 }
806 #endif
807