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 int 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. */
221 if (c
== '(') { /* \(xx */
222 if ((*s
++ = getach()) == 0 || (*s
++ = getach()) == 0)
224 } else { /* \C'...' */
226 while ((*s
= getach()) != c
&& *s
!= 0 && s
< temp
+ sizeof(temp
) - 1)
231 return chadd(temp
, Troffchar
, Install
) | chbits
; /* add name even if haven't seen it */
234 j
= chadd(temp
, Troffchar
, Lookup
);
240 return chadd(temp
, Troffchar
, Install
) | chbits
; /* add name even if haven't seen it */
245 Tchar
t_setabs(void) /* set absolute char from \N'...' */
256 sprintf(temp
, "%d", n
); /* convert into "#n" */
257 n
= chadd(temp
, Number
, Install
);
263 * fontlab[] is a cache that contains font information
265 * fontlab[] contains the 1- or 2-character name of the
266 * font current associated with that font.
267 * fonts 1..nfonts correspond to the mounted fonts;
268 * the last of these are the special fonts.
269 * If we don't use the (named) font in one of the
270 * standard positions, we install the name in the next
271 * free slot of fontlab[] and font[].
272 * Whenever we need info about the font, we
273 * read in the data into the next free slot with getfont.
274 * The ptfont() (t10.c) routine will tell
275 * the device filter to put the font always at position
276 * zero if xfont > nfonts, so no need to change these filters.
277 * Yes, this is a bit kludgy.
279 * This gives the new specs of findft:
280 * find the font name i, where i also can be a number.
281 * Installs the font(name) i when not present
282 * returns -1 on error
293 if (isdigit(p
[0])) { /* first look for numbers */
295 if (p
[1] > 0 && isdigit(p
[1]))
296 k
= 10 * k
+ p
[1] - '0';
297 if (k
> 0 && k
<= nfonts
&& k
< smnt
)
298 return k
; /* mounted font: .ft 3 */
299 if (fontlab
[k
] && k
<= MAXFONTS
) { /* translate */
300 return k
; /*number to a name */
302 fprintf(stderr
, "troff: no font at position %d\n", k
);
303 return -1; /* wild number */
308 * Now we look for font names
310 for (k
= 1; fontlab
[k
] != i
; k
++) {
312 return -1; /* running out of fontlab space */
313 if (fontlab
[k
] == 0) { /* passed all existing names */
314 if (setfp(k
, i
, (char *) 0, 1) == -1)
317 fontlab
[k
] = i
; /* install the name */
322 return k
; /* was one of the existing names */
335 i
= inumb(&apts
); /* this is a disaster for fractional point sizes */
349 * in olden times, it used to ignore changes to 0 or negative.
350 * this is meant to allow the requested size to be anything,
351 * in particular so eqn can generate lots of \s-3's and still
352 * get back by matching \s+3's.
369 for (j
= k
= 0; pstab
[j
] != 0; j
++)
370 if (abs(pstab
[j
]-i
) < abs(pstab
[k
]-i
))
382 for (j
= 0; i
> (k
= pstab
[j
]); j
++)
388 setsbits(chbits
, ++j
);
389 setfbits(chbits
, font
);
390 sps
= width(' ' | chbits
);
399 if (isdigit(i
)) { /* \sd or \sdd */
401 if (i
== 0) /* \s0 */
403 else if (i
<= 3 && (ch
=getch()) && isdigit(j
= cbits(ch
))) { /* \sdd */
404 j
= 10 * i
+ j
- '0';
408 } else if (i
== '(') { /* \s(dd */
409 j
= cbits(getch()) - '0';
410 j
= 10 * j
+ cbits(getch()) - '0';
411 if (j
== 0) /* \s(00 */
413 } else if (i
== '+' || i
== '-') { /* \s+, \s- */
415 if (isdigit(j
)) { /* \s+d, \s-d */
417 } else if (j
== '(') { /* \s+(dd, \s-(dd */
418 j
= cbits(getch()) - '0';
419 j
= 10 * j
+ cbits(getch()) - '0';
429 Tchar
t_setht(void) /* set character height from \H'...' */
437 if (n
== 0 || nonumb
)
438 n
= apts
; /* does this work? */
442 setfbits(c
, pts
); /* sneaky, CHARHT font bits are size bits */
446 Tchar
t_setslant(void) /* set slant from \S'...' */
475 void t_setfont(int a
)
483 if (!i
|| i
== 'P') {
487 if (/* i == 'S' || */ i
== '0') /* an experiment -- why can't we change to it? */
489 if ((j
= findft(i
)) == -1)
490 if ((j
= setfp(0, i
, (char*) 0, 1)) == -1) /* try to put it in position 0 */
504 int savhp
, savapts
, savapts1
, savfont
, savfont1
, savpts
, savpts1
;
506 base
= numtabp
[ST
].val
= numtabp
[SB
].val
= wid
= numtabp
[CT
].val
= 0;
507 if (ismot(i
= getch()))
510 savhp
= numtabp
[HP
].val
;
519 while (cbits(i
= getch()) != delim
&& !nlflg
) {
522 numtabp
[HP
].val
+= k
;
524 emsz
= (INCH
/72) * xpts
;
525 } else if (isvmot(i
)) {
533 if (base
< numtabp
[SB
].val
)
534 numtabp
[SB
].val
= base
;
535 if ((k
= base
+ emsz
) > numtabp
[ST
].val
)
538 setn1(wid
, 0, (Tchar
) 0);
539 numtabp
[HP
].val
= savhp
;
572 getch(); /*eat delim*/
576 i
= makem(quant(n
, j
));
611 if (Hor
> 1 && !vflag
)
612 j
= (j
+ Hor
/2)/Hor
* Hor
;
629 if ((lf
= fonts
[fbits(i
)].ligfont
) == 0) /* font lacks ligatures */
632 if (cbits(j
) == 'i' && (lf
& LFI
))
634 else if (cbits(j
) == 'l' && (lf
& LFL
))
636 else if (cbits(j
) == 'f' && (lf
& LFF
)) {
637 if ((lf
& (LFFI
|LFFL
)) && lg
!= 2) {
639 if (cbits(k
)=='i' && (lf
&LFFI
))
641 else if (cbits(k
)=='l' && (lf
&LFFL
))
653 return(i
& SFMASK
| j
);
682 i
= 10 * i
+ j
- '0';
684 if (i
<= 0 || i
> nfonts
)
685 ERROR
"fp: bad font position %d", i WARN
;
686 else if (skip() || !(j
= getrq()))
687 ERROR
"fp: no font name" WARN
;
688 else if (skip() || !getname())
689 setfp(i
, j
, (char*) 0, 1);
690 else /* 3rd argument = filename */
691 setfp(i
, j
, nextf
, 1);
694 char *strdupl(const char *s
) /* make a copy of s */
698 t
= (char *) malloc(strlen(s
) + 1);
700 ERROR
"out of space in strdupl(%s)", s FATAL
;
705 int setfp(int pos
, int f
, char *truename
, int print
) /* mount font f at position pos[0...nfonts] */
707 char pathname
[NS
], shortname
[NS
];
711 strcpy(shortname
, truename
);
713 strcpy(shortname
, (char *) unpair(f
));
714 if (truename
&& strrchr(truename
, '/')) { /* .fp 1 R dir/file: use verbatim */
715 sprintf(pathname
, "%s", truename
);
716 if (fonts
[pos
].truename
)
717 free(fonts
[pos
].truename
);
718 fonts
[pos
].truename
= strdupl(truename
);
719 } else if (truename
) { /* synonym: .fp 1 R Avant */
720 sprintf(pathname
, "%s/dev%s/%s", fontdir
, devname
, truename
);
721 truename
= 0; /* so doesn't get repeated by ptfpcmd */
722 } else /* vanilla: .fp 5 XX */
723 sprintf(pathname
, "%s/dev%s/%s", fontdir
, devname
, shortname
);
724 if (truename
== 0 && fonts
[pos
].truename
!= 0) {
725 free(fonts
[pos
].truename
);
726 fonts
[pos
].truename
= 0;
728 if (getfont(pathname
, pos
) < 0) {
729 ERROR
"Can't open font file %s", pathname WARN
;
732 if (print
&& !ascii
) {
733 ptfpcmd(pos
, fonts
[pos
].longname
, truename
);
741 if (smnt
== 0 && fonts
[pos
].specfont
)
743 bdtab
[pos
] = cstab
[pos
] = ccstab
[pos
] = 0;
748 * .cs request; don't check legality of optional arguments
760 if (!(i
= getrq()) || (i
= findft(i
)) < 0)
769 ccstab
[i
] = findps(j
);
789 if (skip() || !(i
= getrq()) || (j
= findft(i
)) == -1) {
821 dfact
= INCH
; /* default scaling is points! */
844 sps
= width(' ' | chbits
);
853 /* stores \x'...' into two successive Tchars.
854 * the first contains HX, the second the value,
855 * encoded as a vertical motion.
856 * decoding is done in n2.c by pchar().
862 i
= quant(atoi0(), VERT
);
866 *pbp
++ = MOT
| VMOT
| i
;
868 *pbp
++ = MOT
| VMOT
| NMOT
| -i
;
874 static Uchar name
[3];
876 name
[0] = i
& SHORTMASK
;
877 name
[1] = (i
>> SHORT
) & SHORTMASK
;