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