4 * width functions, sizes and fonts
11 int fontlab[MAXFONTS+1];
12 int cstab[MAXFONTS+1];
13 int ccstab[MAXFONTS+1];
14 int bdtab[MAXFONTS+1];
45 if (sfbits(j) == oldbits) {
50 if (i < nchnames + ALPHABET && widcache[i].fontpts == (xfont<<8) + xpts && !setwdf)
51 k = widcache[i].width;
64 * clear width cache-- s means just space
71 widcache[' '].fontpts = 0;
74 for (i=0; i<NWIDCACHE; i++)
75 widcache[i].fontpts = 0;
78 onfont(int n, int f) /* is char n on font f? */
86 if (fp->wp[n].num == n) /* ascii at front */
91 cp = &fp->wp[ALPHABET];
92 ep = &fp->wp[fp->nchars];
93 for ( ; cp < ep; cp++) /* search others */
95 return cp - &fp->wp[0];
96 /* maybe it was a \N... */
99 i = atoi(np+1); /* sscanf(np+1, "%d", &i); */
101 ep = &fp->wp[fp->nchars];
102 for ( ; cp < ep; cp++) { /* search others */
104 return cp - &fp->wp[0];
106 return -2; /* a \N that doesn't have an entry */
108 return -1; /* vanilla not found */
120 if (i == ' ') { /* a blank */
121 k = (fp->spacewidth * spacesz + 6) / 12;
122 /* this nonsense because .ss cmd uses 1/36 em as its units */
123 /* and default is 12 */
124 } else if ((n = onfont(i, xfont)) >= 0) { /* on this font at n */
127 numtabp[CT].val |= fp->wp[n].kern;
128 } else if (n == -2) { /* \N with default width */
130 k = fp->defaultwidth;
131 } else { /* not on current font */
133 k = fp->defaultwidth; /* default-size space */
136 for (ii=smnt, jj=0; jj < nfonts; jj++, ii=ii % nfonts + 1) {
137 if ((n = onfont(i, ii)) >= 0) {
138 k = fonts[ii].wp[n].wid;
142 numtabp[CT].val |= fonts[ii].wp[n].kern;
150 if (cs = cstab[xfont]) {
152 if (ccs = ccstab[xfont])
156 cs = (cs * EMPTS(x)) / 36;
158 /* was (k & BYTEMASK); since .wid is unsigned, should never happen */
160 ERROR "can't happen: negative width %d in getcw %d\n", k, i WARN;
161 k = (k * xpts + (Unitwidth / 2)) / Unitwidth;
163 widcache[i].fontpts = 0;
165 widcache[i].fontpts = (xfont<<8) + xpts;
166 widcache[i].width = k;
169 /* Unitwidth is Units/Point, where
170 /* Units is the fundamental digitization
171 /* of the character set widths, and
172 /* Point is the number of goobies in a point
173 /* e.g., for cat, Units=36, Point=6, so Unitwidth=36/6=6
174 /* In effect, it's the size at which the widths
175 /* translate directly into units.
179 void xbits(Tchar i, int bitf)
210 /* these next two functions ought to be the same in troff and nroff, */
211 /* but the data structures they search are different. */
212 /* silly historical problem. */
222 if (c == '(') { /* \(xx */
223 if ((*s++ = getach()) == 0 || (*s++ = getach()) == 0)
225 } else { /* \C'...' */
227 while ((*s = getach()) != c && *s != 0 && s < temp + sizeof(temp) - 1)
232 return chadd(temp, Troffchar, Install) | chbits; /* add name even if haven't seen it */
235 j = chadd(temp, Troffchar, Lookup);
241 return chadd(temp, Troffchar, Install) | chbits; /* add name even if haven't seen it */
246 Tchar t_setabs(void) /* set absolute char from \N'...' */
257 sprintf(temp, "%d", n); /* convert into "#n" */
258 n = chadd(temp, Number, Install);
264 * fontlab[] is a cache that contains font information
266 * fontlab[] contains the 1- or 2-character name of the
267 * font current associated with that font.
268 * fonts 1..nfonts correspond to the mounted fonts;
269 * the last of these are the special fonts.
270 * If we don't use the (named) font in one of the
271 * standard positions, we install the name in the next
272 * free slot of fontlab[] and font[].
273 * Whenever we need info about the font, we
274 * read in the data into the next free slot with getfont.
275 * The ptfont() (t10.c) routine will tell
276 * the device filter to put the font always at position
277 * zero if xfont > nfonts, so no need to change these filters.
278 * Yes, this is a bit kludgy.
280 * This gives the new specs of findft:
281 * find the font name i, where i also can be a number.
282 * Installs the font(name) i when not present
283 * returns -1 on error
294 if (isdigit(p[0])) { /* first look for numbers */
296 if (p[1] > 0 && isdigit(p[1]))
297 k = 10 * k + p[1] - '0';
298 if (k > 0 && k <= nfonts && k < smnt)
299 return(k); /* mounted font: .ft 3 */
300 if (fontlab[k] && k <= MAXFONTS) { /* translate */
301 return(k); /*number to a name */
303 fprintf(stderr, "troff: no font at position %d\n", k);
304 return(-1); /* wild number */
309 * Now we look for font names
311 for (k = 1; fontlab[k] != i; k++) {
313 return(-1); /* running out of fontlab space */
314 if (fontlab[k] == 0) { /* passed all existing names */
315 if (setfp(k, i, (char *) 0, 1) == -1)
318 fontlab[k] = i; /* install the name */
323 return(k); /* was one of the existing names */
336 i = inumb(&apts); /* this is a disaster for fractional point sizes */
350 * in olden times, it used to ignore changes to 0 or negative.
351 * this is meant to allow the requested size to be anything,
352 * in particular so eqn can generate lots of \s-3's and still
353 * get back by matching \s+3's.
370 for (j=k=0 ; pstab[j] != 0 ; j++)
371 if (abs(pstab[j]-i) < abs(pstab[k]-i))
383 for (j = 0; i > (k = pstab[j]); j++)
389 setsbits(chbits, ++j);
390 setfbits(chbits, font);
391 sps = width(' ' | chbits);
400 if (isdigit(i)) { /* \sd or \sdd */
402 if (i == 0) /* \s0 */
404 else if (i <= 3 && (ch=getch()) && isdigit(j = cbits(ch))) { /* \sdd */
405 j = 10 * i + j - '0';
409 } else if (i == '(') { /* \s(dd */
410 j = cbits(getch()) - '0';
411 j = 10 * j + cbits(getch()) - '0';
412 if (j == 0) /* \s(00 */
414 } else if (i == '+' || i == '-') { /* \s+, \s- */
416 if (isdigit(j)) { /* \s+d, \s-d */
418 } else if (j == '(') { /* \s+(dd, \s-(dd */
419 j = cbits(getch()) - '0';
420 j = 10 * j + cbits(getch()) - '0';
430 Tchar t_setht(void) /* set character height from \H'...' */
438 if (n == 0 || nonumb)
439 n = apts; /* does this work? */
443 setfbits(c, pts); /* sneaky, CHARHT font bits are size bits */
447 Tchar t_setslant(void) /* set slant from \S'...' */
476 void t_setfont(int a)
484 if (!i || i == 'P') {
488 if (/* i == 'S' || */ i == '0') /* an experiment -- why can't we change to it? */
490 if ((j = findft(i)) == -1)
491 if ((j = setfp(0, i, (char*) 0, 1)) == -1) /* try to put it in position 0 */
505 int savhp, savapts, savapts1, savfont, savfont1, savpts, savpts1;
507 base = numtabp[ST].val = numtabp[SB].val = wid = numtabp[CT].val = 0;
508 if (ismot(i = getch()))
511 savhp = numtabp[HP].val;
520 while (cbits(i = getch()) != delim && !nlflg) {
523 numtabp[HP].val += k;
525 emsz = (INCH/72) * xpts;
526 } else if (isvmot(i)) {
534 if (base < numtabp[SB].val)
535 numtabp[SB].val = base;
536 if ((k = base + emsz) > numtabp[ST].val)
539 setn1(wid, 0, (Tchar) 0);
540 numtabp[HP].val = savhp;
573 getch(); /*eat delim*/
577 i = makem(quant(n, j));
612 if (Hor > 1 && !vflag)
613 j = (j + Hor/2)/Hor * Hor;
630 if ((lf = fonts[fbits(i)].ligfont) == 0) /* font lacks ligatures */
633 if (cbits(j) == 'i' && (lf & LFI))
635 else if (cbits(j) == 'l' && (lf & LFL))
637 else if (cbits(j) == 'f' && (lf & LFF)) {
638 if ((lf & (LFFI|LFFL)) && lg != 2) {
640 if (cbits(k)=='i' && (lf&LFFI))
642 else if (cbits(k)=='l' && (lf&LFFL))
654 return(i & SFMASK | j);
683 i = 10 * i + j - '0';
685 if (i <= 0 || i > nfonts)
686 ERROR "fp: bad font position %d", i WARN;
687 else if (skip() || !(j = getrq()))
688 ERROR "fp: no font name" WARN;
689 else if (skip() || !getname())
690 setfp(i, j, (char*) 0, 1);
691 else /* 3rd argument = filename */
692 setfp(i, j, nextf, 1);
695 char *strdupl(const char *s) /* make a copy of s */
699 t = (char *) malloc(strlen(s) + 1);
701 ERROR "out of space in strdupl(%s)", s FATAL;
706 setfp(int pos, int f, char *truename, int print) /* mount font f at position pos[0...nfonts] */
708 char pathname[NS], shortname[NS], *sl;
712 strcpy(shortname, truename);
714 strcpy(shortname, (char *) unpair(f));
715 if (truename && strrchr(truename, '/')) { /* .fp 1 R dir/file: use verbatim */
716 sprintf(pathname, "%s", truename);
717 if (fonts[pos].truename)
718 free(fonts[pos].truename);
719 fonts[pos].truename = strdupl(truename);
720 } else if (truename) { /* synonym: .fp 1 R Avant */
721 sprintf(pathname, "%s/dev%s/%s", fontdir, devname, truename);
722 truename = 0; /* so doesn't get repeated by ptfpcmd */
723 } else /* vanilla: .fp 5 XX */
724 sprintf(pathname, "%s/dev%s/%s", fontdir, devname, shortname);
725 if (truename == 0 && fonts[pos].truename != 0) {
726 free(fonts[pos].truename);
727 fonts[pos].truename = 0;
729 if (getfont(pathname, pos) < 0) {
730 ERROR "Can't open font file %s", pathname WARN;
733 if (print && !ascii) {
734 ptfpcmd(pos, fonts[pos].longname, truename);
742 if (smnt == 0 && fonts[pos].specfont)
744 bdtab[pos] = cstab[pos] = ccstab[pos] = 0;
749 * .cs request; don't check legality of optional arguments
761 if (!(i = getrq()) || (i = findft(i)) < 0)
770 ccstab[i] = findps(j);
790 if (skip() || !(i = getrq()) || (j = findft(i)) == -1) {
822 dfact = INCH; /* default scaling is points! */
845 sps = width(' ' | chbits);
854 /* stores \x'...' into two successive Tchars.
855 /* the first contains HX, the second the value,
856 /* encoded as a vertical motion.
857 /* decoding is done in n2.c by pchar().
863 i = quant(atoi0(), VERT);
867 *pbp++ = MOT | VMOT | i;
869 *pbp++ = MOT | VMOT | NMOT | -i;
875 static Uchar name[3];
877 name[0] = i & SHORTMASK;
878 name[1] = (i >> SHORT) & SHORTMASK;