Introduction
Introduction Statistics Contact Development Disclaimer Help
t6.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
t6.c (15468B)
---
1 /*
2 * t6.c
3 *
4 * width functions, sizes and fonts
5 */
6
7 #include "tdef.h"
8 #include "fns.h"
9 #include "ext.h"
10
11 int fontlab[MAXFONTS+1];
12 int cstab[MAXFONTS+1];
13 int ccstab[MAXFONTS+1];
14 int bdtab[MAXFONTS+1];
15 int sbold = 0;
16
17 int
18 t_width(Tchar j)
19 {
20 int i, k;
21
22 if (iszbit(j))
23 return 0;
24 if (ismot(j)) {
25 if (isvmot(j))
26 return(0);
27 k = absmot(j);
28 if (isnmot(j))
29 k = -k;
30 return(k);
31 }
32 i = cbits(j);
33 if (i < ' ') {
34 if (i == '\b')
35 return(-widthp);
36 if (i == PRESC)
37 i = eschar;
38 else if (i == HX)
39 return(0);
40 }
41 if (i == ohc)
42 return(0);
43 i = trtab[i];
44 if (i < ' ')
45 return(0);
46 if (sfbits(j) == oldbits) {
47 xfont = pfont;
48 xpts = ppts;
49 } else
50 xbits(j, 0);
51 if (i < nchnames + ALPHABET && widcache[i].fontpts == (xfont<<8)…
52 k = widcache[i].width;
53 else {
54 k = getcw(i);
55 if (bd)
56 k += (bd - 1) * HOR;
57 if (cs)
58 k = cs;
59 }
60 widthp = k;
61 return(k);
62 }
63
64 /*
65 * clear width cache-- s means just space
66 */
67 void zapwcache(int s)
68 {
69 int i;
70
71 if (s) {
72 widcache[' '].fontpts = 0;
73 return;
74 }
75 for (i=0; i<NWIDCACHE; i++)
76 widcache[i].fontpts = 0;
77 }
78
79 int
80 onfont(int n, int f) /* is char n on font f? */
81 {
82 int i;
83 Font *fp = &fonts[f];
84 Chwid *cp, *ep;
85 char *np;
86
87 if (n < ALPHABET) {
88 if (fp->wp[n].num == n) /* ascii at front */
89 return n;
90 else
91 return -1;
92 }
93 cp = &fp->wp[ALPHABET];
94 ep = &fp->wp[fp->nchars];
95 for ( ; cp < ep; cp++) /* search others */
96 if (cp->num == n)
97 return cp - &fp->wp[0];
98 /* maybe it was a \N... */
99 np = chname(n);
100 if (*np == Number) {
101 i = atoi(np+1); /* sscanf(np+1, "%d", &i)…
102 cp = &fp->wp[0];
103 ep = &fp->wp[fp->nchars];
104 for ( ; cp < ep; cp++) { /* search others */
105 if (cp->code == i)
106 return cp - &fp->wp[0];
107 }
108 return -2; /* a \N that doesn't have an entry */
109 }
110 return -1; /* vanilla not found */
111 }
112
113 int
114 getcw(int i)
115 {
116 int k, n, x;
117 Font *fp;
118 int nocache = 0;
119 if (i < ' ')
120 return 0;
121 bd = 0;
122 fp = &fonts[xfont];
123 if (i == ' ') { /* a blank */
124 k = (fp->spacewidth * spacesz + 6) / 12;
125 /* this nonsense because .ss cmd uses 1/36 em as its uni…
126 /* and default is 12 */
127 } else if ((n = onfont(i, xfont)) >= 0) { /* on this font…
128 k = fp->wp[n].wid;
129 if (setwdf)
130 numtabp[CT].val |= fp->wp[n].kern;
131 } else if (n == -2) { /* \N with default width */
132
133 k = fp->defaultwidth;
134 } else { /* not on current font */
135 nocache = 1;
136 k = fp->defaultwidth; /* default-size space */
137 if (smnt) {
138 int ii, jj;
139 for (ii=smnt, jj=0; jj < nfonts; jj++, ii=ii % n…
140 if ((n = onfont(i, ii)) >= 0) {
141 k = fonts[ii].wp[n].wid;
142 if (xfont == sbold)
143 bd = bdtab[ii];
144 if (setwdf)
145 numtabp[CT].val |= fonts…
146 break;
147 }
148 }
149 }
150 }
151 if (!bd)
152 bd = bdtab[xfont];
153 if (cs = cstab[xfont]) {
154 nocache = 1;
155 if (ccs = ccstab[xfont])
156 x = ccs;
157 else
158 x = xpts;
159 cs = (cs * EMPTS(x)) / 36;
160 }
161 /* was (k & BYTEMASK); since .wid is unsigned, should never hap…
162 if (k < 0)
163 ERROR "can't happen: negative width %d in getcw %d\n", k…
164 k = (k * xpts + (Unitwidth / 2)) / Unitwidth;
165 if (nocache|bd)
166 widcache[i].fontpts = 0;
167 else {
168 widcache[i].fontpts = (xfont<<8) + xpts;
169 widcache[i].width = k;
170 }
171 return(k);
172 /* Unitwidth is Units/Point, where
173 /* Units is the fundamental digitization
174 /* of the character set widths, and
175 /* Point is the number of goobies in a point
176 /* e.g., for cat, Units=36, Point=6, so Unitwidth=36/6=6
177 /* In effect, it's the size at which the widths
178 /* translate directly into units.
179 */
180 }
181
182 void xbits(Tchar i, int bitf)
183 {
184 int k;
185
186 if(TROFF) {
187 xfont = fbits(i);
188 k = sbits(i);
189 if(k) {
190 xpts = pstab[k-1];
191 oldbits = sfbits(i);
192 pfont = xfont;
193 ppts = xpts;
194 return;
195 }
196 switch(bitf) {
197 case 0:
198 xfont = font;
199 xpts = pts;
200 break;
201 case 1:
202 xfont = pfont;
203 xpts = ppts;
204 break;
205 case 2:
206 xfont = mfont;
207 xpts = mpts;
208 }
209 }
210 }
211
212
213 /* these next two functions ought to be the same in troff and nroff, */
214 /* but the data structures they search are different. */
215 /* silly historical problem. */
216
217
218 Tchar t_setch(int c)
219 {
220 int j;
221 char temp[50];
222 char *s;
223
224 j = 0;
225 s = temp;
226 if (c == '(') { /* \(xx */
227 if ((*s++ = getach()) == 0 || (*s++ = getach()) == 0)
228 return(0);
229 } else { /* \C'...' */
230 c = getach();
231 while ((*s = getach()) != c && *s != 0 && s < temp + siz…
232 s++;
233 }
234 *s = '\0';
235 #ifdef UNICODE
236 return chadd(temp, Troffchar, Install) | chbits; /* add name eve…
237 #else
238 if (NROFF) {
239 j = chadd(temp, Troffchar, Lookup);
240 if ( j == -1)
241 return 0;
242 else
243 return j | chbits;
244 } else
245 return chadd(temp, Troffchar, Install) | chbits; /* add …
246
247 #endif /*UNICODE*/
248 }
249
250 Tchar t_setabs(void) /* set absolute char from \N'...' */
251 {
252 int n;
253 char temp[10];
254
255 getch(); /* delim */
256 n = 0;
257 n = inumb(&n);
258 getch(); /* delim */
259 if (nonumb)
260 return 0;
261 sprintf(temp, "%d", n); /* convert into "#n" */
262 n = chadd(temp, Number, Install);
263 return n | chbits;
264 }
265
266
267 /*
268 * fontlab[] is a cache that contains font information
269 * for each font.
270 * fontlab[] contains the 1- or 2-character name of the
271 * font current associated with that font.
272 * fonts 1..nfonts correspond to the mounted fonts;
273 * the last of these are the special fonts.
274 * If we don't use the (named) font in one of the
275 * standard positions, we install the name in the next
276 * free slot of fontlab[] and font[].
277 * Whenever we need info about the font, we
278 * read in the data into the next free slot with getfont.
279 * The ptfont() (t10.c) routine will tell
280 * the device filter to put the font always at position
281 * zero if xfont > nfonts, so no need to change these filters.
282 * Yes, this is a bit kludgy.
283 *
284 * This gives the new specs of findft:
285 * find the font name i, where i also can be a number.
286 * Installs the font(name) i when not present
287 * returns -1 on error
288 */
289
290 int
291 t_findft(int i)
292 {
293 int k;
294 Uchar *p;
295
296 p = unpair(i);
297
298 if (isdigit(p[0])) { /* first look for numbers */
299 k = p[0] - '0';
300 if (p[1] > 0 && isdigit(p[1]))
301 k = 10 * k + p[1] - '0';
302 if (k > 0 && k <= nfonts && k < smnt)
303 return(k); /* mounted font: .ft 3 */
304 if (fontlab[k] && k <= MAXFONTS) { /* translate */
305 return(k); /*number to a …
306 } else {
307 fprintf(stderr, "troff: no font at position %d\n…
308 return(-1); /* wild number */
309 }
310 }
311
312 /*
313 * Now we look for font names
314 */
315 for (k = 1; fontlab[k] != i; k++) {
316 if (k > MAXFONTS)
317 return(-1); /* running out of fontlab spa…
318 if (fontlab[k] == 0) { /* passed all existing nam…
319 if (setfp(k, i, (char *) 0, 1) == -1)
320 return(-1);
321 else {
322 fontlab[k] = i; /* install the na…
323 return(k);
324 }
325 }
326 }
327 return(k); /* was one of the existing nam…
328 }
329
330
331 void caseps(void)
332 {
333 int i;
334
335 if (TROFF) {
336 if(skip())
337 i = apts1;
338 else {
339 noscale++;
340 i = inumb(&apts); /* this is a disaster f…
341 noscale = 0;
342 if(nonumb)
343 i = apts1;
344 }
345 casps1(i);
346 }
347 }
348
349
350 void casps1(int i)
351 {
352
353 /*
354 * in olden times, it used to ignore changes to 0 or negative.
355 * this is meant to allow the requested size to be anything,
356 * in particular so eqn can generate lots of \s-3's and still
357 * get back by matching \s+3's.
358
359 if (i <= 0)
360 return;
361 */
362 apts1 = apts;
363 apts = i;
364 pts1 = pts;
365 pts = findps(i);
366 mchbits();
367 }
368
369 int
370 findps(int i)
371 {
372 int j, k;
373
374 for (j=k=0 ; pstab[j] != 0 ; j++)
375 if (abs(pstab[j]-i) < abs(pstab[k]-i))
376 k = j;
377
378 return(pstab[k]);
379 }
380
381
382 void t_mchbits(void)
383 {
384 int i, j, k;
385
386 i = pts;
387 for (j = 0; i > (k = pstab[j]); j++)
388 if (!k) {
389 j--;
390 break;
391 }
392 chbits = 0;
393 setsbits(chbits, ++j);
394 setfbits(chbits, font);
395 sps = width(' ' | chbits);
396 zapwcache(1);
397 }
398
399 void t_setps(void)
400 {
401 int i, j;
402
403 j = 0;
404 i = cbits(getch());
405 if (isdigit(i)) { /* \sd or \sdd */
406 i -= '0';
407 if (i == 0) /* \s0 */
408 j = apts1;
409 else if (i <= 3 && (ch=getch()) && isdigit(j = cbits(ch)…
410 j = 10 * i + j - '0';
411 ch = 0;
412 } else /* \sd */
413 j = i;
414 } else if (i == '(') { /* \s(dd */
415 j = cbits(getch()) - '0';
416 j = 10 * j + cbits(getch()) - '0';
417 if (j == 0) /* \s(00 */
418 j = apts1;
419 } else if (i == '+' || i == '-') { /* \s+, \s- */
420 j = cbits(getch());
421 if (isdigit(j)) { /* \s+d, \s-d */
422 j -= '0';
423 } else if (j == '(') { /* \s+(dd, \s-(dd …
424 j = cbits(getch()) - '0';
425 j = 10 * j + cbits(getch()) - '0';
426 }
427 if (i == '-')
428 j = -j;
429 j += apts;
430 }
431 casps1(j);
432 }
433
434
435 Tchar t_setht(void) /* set character height from \H'...' …
436 {
437 int n;
438 Tchar c;
439
440 getch();
441 n = inumb(&apts);
442 getch();
443 if (n == 0 || nonumb)
444 n = apts; /* does this work? */
445 c = CHARHT;
446 c |= ZBIT;
447 setsbits(c, n);
448 setfbits(c, pts); /* sneaky, CHARHT font bits are size bi…
449 return(c);
450 }
451
452 Tchar t_setslant(void) /* set slant from \S'...' */
453 {
454 int n;
455 Tchar c;
456
457 getch();
458 n = 0;
459 n = inumb(&n);
460 getch();
461 if (nonumb)
462 n = 0;
463 c = SLANT;
464 c |= ZBIT;
465 setsfbits(c, n+180);
466 return(c);
467 }
468
469
470 void caseft(void)
471 {
472 if (!TROFF) {
473 n_caseft();
474 return;
475 }
476 skip();
477 setfont(1);
478 }
479
480
481 void t_setfont(int a)
482 {
483 int i, j;
484
485 if (a)
486 i = getrq();
487 else
488 i = getsn();
489 if (!i || i == 'P') {
490 j = font1;
491 goto s0;
492 }
493 if (/* i == 'S' || */ i == '0') /* an experiment -- why c…
494 return;
495 if ((j = findft(i)) == -1)
496 if ((j = setfp(0, i, (char*) 0, 1)) == -1) /* try…
497 return;
498 s0:
499 font1 = font;
500 font = j;
501 mchbits();
502 }
503
504
505 void t_setwd(void)
506 {
507 int base, wid;
508 Tchar i;
509 int delim, emsz, k;
510 int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1;
511
512 base = numtabp[ST].val = numtabp[SB].val = wid = numtabp[CT].val…
513 if (ismot(i = getch()))
514 return;
515 delim = cbits(i);
516 savhp = numtabp[HP].val;
517 numtabp[HP].val = 0;
518 savapts = apts;
519 savapts1 = apts1;
520 savfont = font;
521 savfont1 = font1;
522 savpts = pts;
523 savpts1 = pts1;
524 setwdf++;
525 while (cbits(i = getch()) != delim && !nlflg) {
526 k = width(i);
527 wid += k;
528 numtabp[HP].val += k;
529 if (!ismot(i)) {
530 emsz = (INCH/72) * xpts;
531 } else if (isvmot(i)) {
532 k = absmot(i);
533 if (isnmot(i))
534 k = -k;
535 base -= k;
536 emsz = 0;
537 } else
538 continue;
539 if (base < numtabp[SB].val)
540 numtabp[SB].val = base;
541 if ((k = base + emsz) > numtabp[ST].val)
542 numtabp[ST].val = k;
543 }
544 setn1(wid, 0, (Tchar) 0);
545 numtabp[HP].val = savhp;
546 apts = savapts;
547 apts1 = savapts1;
548 font = savfont;
549 font1 = savfont1;
550 pts = savpts;
551 pts1 = savpts1;
552 mchbits();
553 setwdf = 0;
554 }
555
556
557 Tchar t_vmot(void)
558 {
559 dfact = lss;
560 vflag++;
561 return t_mot();
562 }
563
564
565 Tchar t_hmot(void)
566 {
567 dfact = EM;
568 return t_mot();
569 }
570
571
572 Tchar t_mot(void)
573 {
574 int j, n;
575 Tchar i;
576
577 j = HOR;
578 getch(); /*eat delim*/
579 if (n = atoi0()) {
580 if (vflag)
581 j = VERT;
582 i = makem(quant(n, j));
583 } else
584 i = 0;
585 getch();
586 vflag = 0;
587 dfact = 1;
588 return(i);
589 }
590
591
592 Tchar t_sethl(int k)
593 {
594 int j;
595 Tchar i;
596
597 j = EM / 2;
598 if (k == 'u')
599 j = -j;
600 else if (k == 'r')
601 j = -2 * j;
602 vflag++;
603 i = makem(j);
604 vflag = 0;
605 return(i);
606 }
607
608
609 Tchar t_makem(int i)
610 {
611 Tchar j;
612
613 if (i >= 0)
614 j = i;
615 else
616 j = -i;
617 if (Hor > 1 && !vflag)
618 j = (j + Hor/2)/Hor * Hor;
619 j |= MOT;
620 if (i < 0)
621 j |= NMOT;
622 if (vflag)
623 j |= VMOT;
624 return(j);
625 }
626
627
628 Tchar getlg(Tchar i)
629 {
630 Tchar j, k;
631 int lf;
632
633 if (!TROFF)
634 return i;
635 if ((lf = fonts[fbits(i)].ligfont) == 0) /* font lacks ligatures…
636 return(i);
637 j = getch0();
638 if (cbits(j) == 'i' && (lf & LFI))
639 j = LIG_FI;
640 else if (cbits(j) == 'l' && (lf & LFL))
641 j = LIG_FL;
642 else if (cbits(j) == 'f' && (lf & LFF)) {
643 if ((lf & (LFFI|LFFL)) && lg != 2) {
644 k = getch0();
645 if (cbits(k)=='i' && (lf&LFFI))
646 j = LIG_FFI;
647 else if (cbits(k)=='l' && (lf&LFFL))
648 j = LIG_FFL;
649 else {
650 *pbp++ = k;
651 j = LIG_FF;
652 }
653 } else
654 j = LIG_FF;
655 } else {
656 *pbp++ = j;
657 j = i;
658 }
659 return(i & SFMASK | j);
660 }
661
662
663 void caselg(void)
664 {
665
666 if(TROFF) {
667 skip();
668 lg = atoi0();
669 if (nonumb)
670 lg = 1;
671 }
672 }
673
674 void casefp(void)
675 {
676 int i, j;
677
678 if (!TROFF) {
679 n_casefp();
680 return;
681 }
682 skip();
683 i = cbits(getch());
684 if (isdigit(i)) {
685 i -= '0';
686 j = cbits(getch());
687 if (isdigit(j))
688 i = 10 * i + j - '0';
689 }
690 if (i <= 0 || i > nfonts)
691 ERROR "fp: bad font position %d", i WARN;
692 else if (skip() || !(j = getrq()))
693 ERROR "fp: no font name" WARN;
694 else if (skip() || !getname())
695 setfp(i, j, (char*) 0, 1);
696 else /* 3rd argument = filename */
697 setfp(i, j, nextf, 1);
698 }
699
700 char *strdupl(const char *s) /* make a copy of s */
701 {
702 char *t;
703
704 t = (char *) malloc(strlen(s) + 1);
705 if (t == NULL)
706 ERROR "out of space in strdupl(%s)", s FATAL;
707 strcpy(t, s);
708 return t;
709 }
710
711 int
712 setfp(int pos, int f, char *truename, int print) /* mount font f …
713 {
714 char pathname[NS], shortname[NS], *sl;
715
716 sl = (char*)0;
717 zapwcache(0);
718 if (truename)
719 strcpy(shortname, truename);
720 else
721 strcpy(shortname, (char *) unpair(f));
722 if (truename && strrchr(truename, '/')) { /* .fp 1 R dir/…
723 sprintf(pathname, "%s", truename);
724 if (fonts[pos].truename)
725 free(fonts[pos].truename);
726 fonts[pos].truename = strdupl(truename);
727 } else if (truename) { /* synonym: .fp 1 …
728 sprintf(pathname, "%s/dev%s/%s", fontdir, devname, truen…
729 truename = 0; /* so doesn't get repeated by ptfpc…
730 } else /* vanilla: .fp 5 …
731 sprintf(pathname, "%s/dev%s/%s", fontdir, devname, short…
732 if (truename == 0 && fonts[pos].truename != 0) {
733 free(fonts[pos].truename);
734 fonts[pos].truename = 0;
735 }
736 if (getfont(pathname, pos) < 0) {
737 ERROR "Can't open font file %s", pathname WARN;
738 return -1;
739 }
740 if (print && !ascii) {
741 ptfpcmd(pos, fonts[pos].longname, truename);
742 ptfont();
743 }
744 if (pos == smnt) {
745 smnt = 0;
746 sbold = 0;
747 }
748 fontlab[pos] = f;
749 if (smnt == 0 && fonts[pos].specfont)
750 smnt = pos;
751 bdtab[pos] = cstab[pos] = ccstab[pos] = 0;
752 return pos;
753 }
754
755 /*
756 * .cs request; don't check legality of optional arguments
757 */
758 void casecs(void)
759 {
760 int i, j;
761
762 if (TROFF) {
763 int savtr = trace;
764
765 trace = 0;
766 noscale++;
767 skip();
768 if (!(i = getrq()) || (i = findft(i)) < 0)
769 goto rtn;
770 skip();
771 cstab[i] = atoi0();
772 skip();
773 j = atoi0();
774 if(nonumb)
775 ccstab[i] = 0;
776 else
777 ccstab[i] = findps(j);
778 rtn:
779 zapwcache(0);
780 noscale = 0;
781 trace = savtr;
782 }
783 }
784
785
786 void casebd(void)
787 {
788 int i, j, k;
789
790 j=0;
791 if (!TROFF) {
792 n_casebd();
793 return;
794 }
795 zapwcache(0);
796 k = 0;
797 bd0:
798 if (skip() || !(i = getrq()) || (j = findft(i)) == -1) {
799 if (k)
800 goto bd1;
801 else
802 return;
803 }
804 if (j == smnt) {
805 k = smnt;
806 goto bd0;
807 }
808 if (k) {
809 sbold = j;
810 j = k;
811 }
812 bd1:
813 skip();
814 noscale++;
815 bdtab[j] = atoi0();
816 noscale = 0;
817 }
818
819
820 void casevs(void)
821 {
822 int i;
823
824 if (!TROFF) {
825 n_casevs();
826 return;
827 }
828 skip();
829 vflag++;
830 dfact = INCH; /* default scaling is points! */
831 dfactd = 72;
832 res = VERT;
833 i = inumb(&lss);
834 if (nonumb)
835 i = lss1;
836 if (i < VERT)
837 i = VERT;
838 lss1 = lss;
839 lss = i;
840 }
841
842
843 void casess(void)
844 {
845 int i;
846
847 if(TROFF) {
848 noscale++;
849 skip();
850 if(i = atoi0()) {
851 spacesz = i & 0177;
852 zapwcache(0);
853 sps = width(' ' | chbits);
854 }
855 noscale = 0;
856 }
857 }
858
859
860 Tchar t_xlss(void)
861 {
862 /* stores \x'...' into two successive Tchars.
863 /* the first contains HX, the second the value,
864 /* encoded as a vertical motion.
865 /* decoding is done in n2.c by pchar().
866 */
867 int i;
868
869 getch();
870 dfact = lss;
871 i = quant(atoi0(), VERT);
872 dfact = 1;
873 getch();
874 if (i >= 0)
875 *pbp++ = MOT | VMOT | i;
876 else
877 *pbp++ = MOT | VMOT | NMOT | -i;
878 return(HX);
879 }
880
881 Uchar *unpair(int i)
882 {
883 static Uchar name[3];
884
885 name[0] = i & SHORTMASK;
886 name[1] = (i >> SHORT) & SHORTMASK;
887 name[2] = 0;
888 return name;
889 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.