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