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