xref: /plan9/sys/src/cmd/proof/font.c (revision bacfa46c74e1c310aff15aef9cb6bc4e6302513a)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <event.h>
53e12c5d1SDavid du Colombier #include <bio.h>
63e12c5d1SDavid du Colombier #include "proof.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier char	fname[NFONT][20];	/* font names */
97dd7cddfSDavid du Colombier char lastload[NFONT][20];	/* last file name prefix loaded for this font */
103e12c5d1SDavid du Colombier Font	*fonttab[NFONT][NSIZE];	/* pointers to fonts */
113e12c5d1SDavid du Colombier int	fmap[NFONT];		/* what map to use with this font */
123e12c5d1SDavid du Colombier 
133e12c5d1SDavid du Colombier static void	bufchar(Point, Subfont *, uchar *);
143e12c5d1SDavid du Colombier static void	loadfont(int, int);
153e12c5d1SDavid du Colombier static void	fontlookup(int, char *);
16219b2ee8SDavid du Colombier static void	buildxheight(Biobuf*);
173e12c5d1SDavid du Colombier static void	buildmap(Biobuf*);
183e12c5d1SDavid du Colombier static void	buildtroff(char *);
193e12c5d1SDavid du Colombier static void	addmap(int, char *, int);
20219b2ee8SDavid du Colombier static char	*map(Rune*, int);
213e12c5d1SDavid du Colombier static void	scanstr(char *, char *, char **);
223e12c5d1SDavid du Colombier 
233e12c5d1SDavid du Colombier int	specfont;	/* somehow, number of special font */
243e12c5d1SDavid du Colombier 
25219b2ee8SDavid du Colombier #define	NMAP	5
26219b2ee8SDavid du Colombier #define	QUICK	2048	/* char values less than this are quick to look up */
27219b2ee8SDavid du Colombier #define	eq(s,t)	strcmp((char *) s, (char *) t) == 0
28219b2ee8SDavid du Colombier 
29219b2ee8SDavid du Colombier int	curmap	= -1;	/* what map are we working on */
30219b2ee8SDavid du Colombier 
31219b2ee8SDavid du Colombier typedef struct Link Link;
32219b2ee8SDavid du Colombier struct Link	/* link names together */
333e12c5d1SDavid du Colombier {
34219b2ee8SDavid du Colombier 	uchar	*name;
35219b2ee8SDavid du Colombier 	int	val;
36219b2ee8SDavid du Colombier 	Link	*next;
37219b2ee8SDavid du Colombier };
38219b2ee8SDavid du Colombier 
39219b2ee8SDavid du Colombier typedef struct Map Map;
40219b2ee8SDavid du Colombier struct Map	/* holds a mapping from uchar name to index */
41219b2ee8SDavid du Colombier {
42219b2ee8SDavid du Colombier 	double	xheight;
43219b2ee8SDavid du Colombier 	Rune	quick[QUICK];	/* low values get special treatment */
44219b2ee8SDavid du Colombier 	Link	*slow;	/* other stuff goes into a link list */
45219b2ee8SDavid du Colombier };
46219b2ee8SDavid du Colombier 
47219b2ee8SDavid du Colombier Map	charmap[5];
48219b2ee8SDavid du Colombier 
49219b2ee8SDavid du Colombier typedef struct Fontmap Fontmap;
50219b2ee8SDavid du Colombier struct Fontmap	/* mapping from troff name to filename */
51219b2ee8SDavid du Colombier {
52219b2ee8SDavid du Colombier 	char	*troffname;
53219b2ee8SDavid du Colombier 	char	*prefix;
54219b2ee8SDavid du Colombier 	int	map;		/* which charmap to use for this font */
55219b2ee8SDavid du Colombier 	char	*fallback;	/* font to look in if can't find char here */
56219b2ee8SDavid du Colombier };
57219b2ee8SDavid du Colombier 
58219b2ee8SDavid du Colombier Fontmap	fontmap[100];
59219b2ee8SDavid du Colombier int	pos2fontmap[NFONT];	/* indexed by troff font position, gives Fontmap */
60219b2ee8SDavid du Colombier int	nfontmap	= 0;	/* how many are there */
61219b2ee8SDavid du Colombier 
62219b2ee8SDavid du Colombier 
63219b2ee8SDavid du Colombier void
dochar(Rune r[])64219b2ee8SDavid du Colombier dochar(Rune r[])
65219b2ee8SDavid du Colombier {
66219b2ee8SDavid du Colombier 	char *s, *fb;
673e12c5d1SDavid du Colombier 	Font *f;
683e12c5d1SDavid du Colombier 	Point p;
69219b2ee8SDavid du Colombier 	int fontno, fm, i;
70bfe6f914SDavid du Colombier 	char buf[32];
713e12c5d1SDavid du Colombier 
723e12c5d1SDavid du Colombier 	fontno = curfont;
73219b2ee8SDavid du Colombier 	if((s = map(r, curfont)) == 0){		/* not on current font */
74219b2ee8SDavid du Colombier 		if ((s = map(r, specfont)) != 0)	/* on special font */
753e12c5d1SDavid du Colombier 			fontno = specfont;
76219b2ee8SDavid du Colombier 		else{
77219b2ee8SDavid du Colombier 			/* look for fallback */
78219b2ee8SDavid du Colombier 			fm = pos2fontmap[curfont];
79219b2ee8SDavid du Colombier 			fb = fontmap[fm].fallback;
80219b2ee8SDavid du Colombier 			if(fb){
81219b2ee8SDavid du Colombier 				/* see if fallback is mounted */
82219b2ee8SDavid du Colombier 				for(i = 0; i < NFONT; i++){
83219b2ee8SDavid du Colombier 					if(eq(fb, fontmap[pos2fontmap[i]].troffname)){
84219b2ee8SDavid du Colombier 						s = map(r, i);
85219b2ee8SDavid du Colombier 						if(s){
86219b2ee8SDavid du Colombier 							fontno = i;
87219b2ee8SDavid du Colombier 							goto found;
88219b2ee8SDavid du Colombier 						}
89219b2ee8SDavid du Colombier 					}
90219b2ee8SDavid du Colombier 				}
91219b2ee8SDavid du Colombier 			}
923e12c5d1SDavid du Colombier 			/* no such char; use name itself on defont */
93219b2ee8SDavid du Colombier 			/* this is not a general solution */
943e12c5d1SDavid du Colombier 			p.x = hpos/DIV + xyoffset.x + offset.x;
953e12c5d1SDavid du Colombier 			p.y = vpos/DIV + xyoffset.y + offset.y;
963e12c5d1SDavid du Colombier 			p.y -= font->ascent;
97bfe6f914SDavid du Colombier 			snprint(buf, sizeof buf, "%S", r);
987dd7cddfSDavid du Colombier 			string(screen, p, display->black, ZP, font, buf);
993e12c5d1SDavid du Colombier 			return;
1003e12c5d1SDavid du Colombier 		}
1013e12c5d1SDavid du Colombier 	}
102219b2ee8SDavid du Colombier     found:
1033e12c5d1SDavid du Colombier 	p.x = hpos/DIV + xyoffset.x + offset.x;
1043e12c5d1SDavid du Colombier 	p.y = vpos/DIV + xyoffset.y + offset.y;
1053e12c5d1SDavid du Colombier 	while ((f = fonttab[fontno][cursize]) == 0)
1063e12c5d1SDavid du Colombier 		loadfont(fontno, cursize);
1073e12c5d1SDavid du Colombier 	p.y -= f->ascent;
108219b2ee8SDavid du Colombier 	dprint(2, "putting %S at %d,%d font %d, size %d\n", r, p.x, p.y, fontno, cursize);
1097dd7cddfSDavid du Colombier 	string(screen, p, display->black, ZP, f, s);
1103e12c5d1SDavid du Colombier }
1113e12c5d1SDavid du Colombier 
112*bacfa46cSDavid du Colombier /* imported from libdraw/arith.c to permit an extern log2 function */
113*bacfa46cSDavid du Colombier static int log2[] = {
114*bacfa46cSDavid du Colombier 	-1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4,
115*bacfa46cSDavid du Colombier 	-1, -1, -1, -1, -1, -1, -1, 4 /* BUG */, -1, -1, -1, -1, -1, -1, -1, 5
116*bacfa46cSDavid du Colombier };
1173e12c5d1SDavid du Colombier 
1183e12c5d1SDavid du Colombier static void
loadfont(int n,int s)1193e12c5d1SDavid du Colombier loadfont(int n, int s)
1203e12c5d1SDavid du Colombier {
121bfe6f914SDavid du Colombier 	char file[256];
1227dd7cddfSDavid du Colombier 	int i, fd, t, deep;
1233e12c5d1SDavid du Colombier 	static char *try[3] = {"", "times/R.", "pelm/"};
1243e12c5d1SDavid du Colombier 	Subfont *f;
1253e12c5d1SDavid du Colombier 	Font *ff;
1263e12c5d1SDavid du Colombier 
1273e12c5d1SDavid du Colombier 	try[0] = fname[n];
1283e12c5d1SDavid du Colombier 	for (t = 0; t < 3; t++){
129219b2ee8SDavid du Colombier 		i = s * mag * charmap[fmap[n]].xheight/0.72;	/* a pixel is 0.72 points */
1303e12c5d1SDavid du Colombier 		if (i < MINSIZE)
1313e12c5d1SDavid du Colombier 			i = MINSIZE;
1323e12c5d1SDavid du Colombier 		dprint(2, "size %d, i %d, mag %g\n", s, i, mag);
133219b2ee8SDavid du Colombier 		for(; i >= MINSIZE; i--){
134219b2ee8SDavid du Colombier 			/* if .font file exists, take that */
135bfe6f914SDavid du Colombier 			snprint(file, sizeof file, "%s/%s%d.font",
136bfe6f914SDavid du Colombier 				libfont, try[t], i);
1377dd7cddfSDavid du Colombier 			ff = openfont(display, file);
138219b2ee8SDavid du Colombier 			if(ff != 0){
139219b2ee8SDavid du Colombier 				fonttab[n][s] = ff;
140219b2ee8SDavid du Colombier 				dprint(2, "using %s for font %d %d\n", file, n, s);
141219b2ee8SDavid du Colombier 				return;
142219b2ee8SDavid du Colombier 			}
143219b2ee8SDavid du Colombier 			/* else look for a subfont file */
1447dd7cddfSDavid du Colombier 			for (deep = log2[screen->depth]; deep >= 0; deep--){
145bfe6f914SDavid du Colombier 				snprint(file, sizeof file, "%s/%s%d.%d",
146bfe6f914SDavid du Colombier 					libfont, try[t], i, deep);
1473e12c5d1SDavid du Colombier 				dprint(2, "trying %s for %d\n", file, i);
1483e12c5d1SDavid du Colombier 				if ((fd = open(file, 0)) >= 0){
1497dd7cddfSDavid du Colombier 					f = readsubfont(display, file, fd, 0);
1503e12c5d1SDavid du Colombier 					if (f == 0) {
1513e12c5d1SDavid du Colombier 						fprint(2, "can't rdsubfontfile %s: %r\n", file);
1523e12c5d1SDavid du Colombier 						exits("rdsubfont");
1533e12c5d1SDavid du Colombier 					}
1543e12c5d1SDavid du Colombier 					close(fd);
1553e12c5d1SDavid du Colombier 					ff = mkfont(f, 0);
1563e12c5d1SDavid du Colombier 					if(ff == 0){
1573e12c5d1SDavid du Colombier 						fprint(2, "can't mkfont %s: %r\n", file);
1583e12c5d1SDavid du Colombier 						exits("rdsubfont");
1593e12c5d1SDavid du Colombier 					}
1603e12c5d1SDavid du Colombier 					fonttab[n][s] = ff;
1613e12c5d1SDavid du Colombier 					dprint(2, "using %s for font %d %d\n", file, n, s);
1623e12c5d1SDavid du Colombier 					return;
1633e12c5d1SDavid du Colombier 				}
1643e12c5d1SDavid du Colombier 			}
1653e12c5d1SDavid du Colombier 		}
166219b2ee8SDavid du Colombier 	}
1673e12c5d1SDavid du Colombier 	fprint(2, "can't find font %s.%d or substitute, quitting\n", fname[n], s);
1683e12c5d1SDavid du Colombier 	exits("no font");
1693e12c5d1SDavid du Colombier }
1703e12c5d1SDavid du Colombier 
1713e12c5d1SDavid du Colombier void
loadfontname(int n,char * s)1723e12c5d1SDavid du Colombier loadfontname(int n, char *s)
1733e12c5d1SDavid du Colombier {
1743e12c5d1SDavid du Colombier 	int i;
1753e12c5d1SDavid du Colombier 	Font *f, *g = 0;
1763e12c5d1SDavid du Colombier 
1773e12c5d1SDavid du Colombier 	if (strcmp(s, fname[n]) == 0)
1783e12c5d1SDavid du Colombier 		return;
1797dd7cddfSDavid du Colombier 	if(fname[n] && fname[n][0]){
1807dd7cddfSDavid du Colombier 		if(lastload[n] && strcmp(lastload[n], fname[n]) == 0)
1817dd7cddfSDavid du Colombier 			return;
1827dd7cddfSDavid du Colombier 		strcpy(lastload[n], fname[n]);
1837dd7cddfSDavid du Colombier 	}
1843e12c5d1SDavid du Colombier 	fontlookup(n, s);
1853e12c5d1SDavid du Colombier 	for (i = 0; i < NSIZE; i++)
1863e12c5d1SDavid du Colombier 		if (f = fonttab[n][i]){
1873e12c5d1SDavid du Colombier 			if (f != g) {
1887dd7cddfSDavid du Colombier 				freefont(f);
1893e12c5d1SDavid du Colombier 				g = f;
1903e12c5d1SDavid du Colombier 			}
1913e12c5d1SDavid du Colombier 			fonttab[n][i] = 0;
1923e12c5d1SDavid du Colombier 		}
1933e12c5d1SDavid du Colombier }
1943e12c5d1SDavid du Colombier 
1953e12c5d1SDavid du Colombier void
allfree(void)1963e12c5d1SDavid du Colombier allfree(void)
1973e12c5d1SDavid du Colombier {
1983e12c5d1SDavid du Colombier 	int i;
1993e12c5d1SDavid du Colombier 
2003e12c5d1SDavid du Colombier 	for (i=0; i<NFONT; i++)
2013e12c5d1SDavid du Colombier 		loadfontname(i, "??");
2023e12c5d1SDavid du Colombier }
2033e12c5d1SDavid du Colombier 
2043e12c5d1SDavid du Colombier 
2053e12c5d1SDavid du Colombier void
readmapfile(char * file)2063e12c5d1SDavid du Colombier readmapfile(char *file)
2073e12c5d1SDavid du Colombier {
2083e12c5d1SDavid du Colombier 	Biobuf *fp;
2093e12c5d1SDavid du Colombier 	char *p, cmd[100];
2103e12c5d1SDavid du Colombier 
2113e12c5d1SDavid du Colombier 	if ((fp=Bopen(file, OREAD)) == 0){
2123e12c5d1SDavid du Colombier 		fprint(2, "proof: can't open map file %s\n", file);
2133e12c5d1SDavid du Colombier 		exits("urk");
2143e12c5d1SDavid du Colombier 	}
2153e12c5d1SDavid du Colombier 	while((p=Brdline(fp, '\n')) != 0) {
2163e12c5d1SDavid du Colombier 		p[Blinelen(fp)-1] = 0;
2173e12c5d1SDavid du Colombier 		scanstr(p, cmd, 0);
2183e12c5d1SDavid du Colombier 		if(p[0]=='\0' || eq(cmd, "#"))	/* skip comments, empty */
2193e12c5d1SDavid du Colombier 			continue;
220219b2ee8SDavid du Colombier 		else if(eq(cmd, "xheight"))
221219b2ee8SDavid du Colombier 			buildxheight(fp);
2223e12c5d1SDavid du Colombier 		else if(eq(cmd, "map"))
2233e12c5d1SDavid du Colombier 			buildmap(fp);
2243e12c5d1SDavid du Colombier 		else if(eq(cmd, "special"))
2253e12c5d1SDavid du Colombier 			buildtroff(p);
2263e12c5d1SDavid du Colombier 		else if(eq(cmd, "troff"))
2273e12c5d1SDavid du Colombier 			buildtroff(p);
2283e12c5d1SDavid du Colombier 		else
2293e12c5d1SDavid du Colombier 			fprint(2, "weird map line %s\n", p);
2303e12c5d1SDavid du Colombier 	}
231219b2ee8SDavid du Colombier 	Bterm(fp);
232219b2ee8SDavid du Colombier }
233219b2ee8SDavid du Colombier 
234219b2ee8SDavid du Colombier static void
buildxheight(Biobuf * fp)235219b2ee8SDavid du Colombier buildxheight(Biobuf *fp)	/* map goes from char name to value to print via *string() */
236219b2ee8SDavid du Colombier {
237219b2ee8SDavid du Colombier 	char *line;
238219b2ee8SDavid du Colombier 
239219b2ee8SDavid du Colombier 	line = Brdline(fp, '\n');
240219b2ee8SDavid du Colombier 	if(line == 0){
241219b2ee8SDavid du Colombier 		fprint(2, "proof: bad map file\n");
242219b2ee8SDavid du Colombier 		exits("map");
243219b2ee8SDavid du Colombier 	}
244219b2ee8SDavid du Colombier 	charmap[curmap].xheight = atof(line);
2453e12c5d1SDavid du Colombier }
2463e12c5d1SDavid du Colombier 
2473e12c5d1SDavid du Colombier static void
buildmap(Biobuf * fp)2483e12c5d1SDavid du Colombier buildmap(Biobuf *fp)	/* map goes from char name to value to print via *string() */
2493e12c5d1SDavid du Colombier {
2503e12c5d1SDavid du Colombier 	uchar *p, *line, ch[100];
2513e12c5d1SDavid du Colombier 	int val;
252219b2ee8SDavid du Colombier 	Rune r;
2533e12c5d1SDavid du Colombier 
2543e12c5d1SDavid du Colombier 	curmap++;
255219b2ee8SDavid du Colombier 	if(curmap >= NMAP){
256219b2ee8SDavid du Colombier 		fprint(2, "proof: out of char maps; recompile\n");
257219b2ee8SDavid du Colombier 		exits("charmap");
258219b2ee8SDavid du Colombier 	}
2593e12c5d1SDavid du Colombier 	while ((line = Brdline(fp, '\n'))!= 0){
2603e12c5d1SDavid du Colombier 		if (line[0] == '\n')
2613e12c5d1SDavid du Colombier 			return;
2623e12c5d1SDavid du Colombier 		line[Blinelen(fp)-1] = 0;
2633e12c5d1SDavid du Colombier 		scanstr((char *) line, (char *) ch, (char **) &p);
2643e12c5d1SDavid du Colombier 		if (ch[0] == '\0') {
2657dd7cddfSDavid du Colombier 			fprint(2, "bad map file line '%s'\n", (char*)line);
2663e12c5d1SDavid du Colombier 			continue;
2673e12c5d1SDavid du Colombier 		}
2683e12c5d1SDavid du Colombier 		val = strtol((char *) p, 0, 10);
2697dd7cddfSDavid du Colombier dprint(2, "buildmap %s (%x %x) %s %d\n", (char*)ch, ch[0], ch[1], (char*)p, val);
270219b2ee8SDavid du Colombier 		chartorune(&r, (char*)ch);
271219b2ee8SDavid du Colombier 		if(utflen((char*)ch)==1 && r<QUICK)
272219b2ee8SDavid du Colombier 			charmap[curmap].quick[r] = val;
273219b2ee8SDavid du Colombier 		else
2743e12c5d1SDavid du Colombier 			addmap(curmap, strdup((char *) ch), val);	/* put somewhere else */
2753e12c5d1SDavid du Colombier 	}
2763e12c5d1SDavid du Colombier }
2773e12c5d1SDavid du Colombier 
2783e12c5d1SDavid du Colombier static void
addmap(int n,char * s,int val)2793e12c5d1SDavid du Colombier addmap(int n, char *s, int val)	/* stick a new link on */
2803e12c5d1SDavid du Colombier {
2813e12c5d1SDavid du Colombier 	Link *p = (Link *) malloc(sizeof(Link));
282219b2ee8SDavid du Colombier 	Link *prev = charmap[n].slow;
2833e12c5d1SDavid du Colombier 
2843e12c5d1SDavid du Colombier 	if(p == 0)
2853e12c5d1SDavid du Colombier 		exits("out of memory in addmap");
2863e12c5d1SDavid du Colombier 	p->name = (uchar *) s;
2873e12c5d1SDavid du Colombier 	p->val = val;
288219b2ee8SDavid du Colombier 	p->next = prev;
289219b2ee8SDavid du Colombier 	charmap[n].slow = p;
2903e12c5d1SDavid du Colombier }
2913e12c5d1SDavid du Colombier 
2923e12c5d1SDavid du Colombier static void
buildtroff(char * buf)2933e12c5d1SDavid du Colombier buildtroff(char *buf)	/* map troff names into bitmap filenames */
2943e12c5d1SDavid du Colombier {				/* e.g., R -> times/R., I -> times/I., etc. */
295219b2ee8SDavid du Colombier 	char *p, cmd[100], name[200], prefix[400], fallback[100];
2963e12c5d1SDavid du Colombier 
2973e12c5d1SDavid du Colombier 	scanstr(buf, cmd, &p);
2983e12c5d1SDavid du Colombier 	scanstr(p, name, &p);
2993e12c5d1SDavid du Colombier 	scanstr(p, prefix, &p);
300219b2ee8SDavid du Colombier 	while(*p!=0 && isspace(*p))
301219b2ee8SDavid du Colombier 		p++;
302219b2ee8SDavid du Colombier 	if(*p != 0){
303219b2ee8SDavid du Colombier 		scanstr(p, fallback, &p);
304219b2ee8SDavid du Colombier 		fontmap[nfontmap].fallback = strdup(fallback);
305219b2ee8SDavid du Colombier 	}else
306219b2ee8SDavid du Colombier 		fontmap[nfontmap].fallback = 0;
3073e12c5d1SDavid du Colombier 	fontmap[nfontmap].troffname = strdup(name);
3083e12c5d1SDavid du Colombier 	fontmap[nfontmap].prefix = strdup(prefix);
3093e12c5d1SDavid du Colombier 	fontmap[nfontmap].map = curmap;
310bfe6f914SDavid du Colombier 	dprint(2, "troff name %s is bitmap %s map %d in slot %d fallback %s\n",
311bfe6f914SDavid du Colombier 		name, prefix, curmap, nfontmap, fontmap[nfontmap].fallback?
312bfe6f914SDavid du Colombier 		fontmap[nfontmap].fallback: "<null>");
3133e12c5d1SDavid du Colombier 	nfontmap++;
3143e12c5d1SDavid du Colombier }
3153e12c5d1SDavid du Colombier 
3163e12c5d1SDavid du Colombier static void
fontlookup(int n,char * s)3173e12c5d1SDavid du Colombier fontlookup(int n, char *s)	/* map troff name of s into position n */
3183e12c5d1SDavid du Colombier {
3193e12c5d1SDavid du Colombier 	int i;
3203e12c5d1SDavid du Colombier 
3213e12c5d1SDavid du Colombier 	for(i = 0; i < nfontmap; i++)
3223e12c5d1SDavid du Colombier 		if (eq(s, fontmap[i].troffname)) {
3233e12c5d1SDavid du Colombier 			strcpy(fname[n], fontmap[i].prefix);
3243e12c5d1SDavid du Colombier 			fmap[n] = fontmap[i].map;
325219b2ee8SDavid du Colombier 			pos2fontmap[n] = i;
3263e12c5d1SDavid du Colombier 			if (eq(s, "S"))
3273e12c5d1SDavid du Colombier 				specfont = n;
3283e12c5d1SDavid du Colombier 			dprint(2, "font %d %s is %s\n", n, s, fname[n]);
3293e12c5d1SDavid du Colombier 			return;
3303e12c5d1SDavid du Colombier 		}
3313e12c5d1SDavid du Colombier 	/* god help us if this font isn't there */
3323e12c5d1SDavid du Colombier }
3333e12c5d1SDavid du Colombier 
3343e12c5d1SDavid du Colombier 
335219b2ee8SDavid du Colombier static char *
map(Rune rp[],int font)336219b2ee8SDavid du Colombier map(Rune rp[], int font)	/* figure out mapping for char in this font */
3373e12c5d1SDavid du Colombier {
338219b2ee8SDavid du Colombier 	static char s[100];
339bfe6f914SDavid du Colombier 	unsigned m;
340bfe6f914SDavid du Colombier 	char c[32];
3413e12c5d1SDavid du Colombier 	Link *p;
342219b2ee8SDavid du Colombier 	Rune r;
3433e12c5d1SDavid du Colombier 
344bfe6f914SDavid du Colombier 	if((unsigned)font >= NFONT) {
345bfe6f914SDavid du Colombier 		dprint(2, "map: font %ud >= NFONT (%d)\n", font, NFONT);
346bfe6f914SDavid du Colombier 		return 0;
347bfe6f914SDavid du Colombier 	}
348bfe6f914SDavid du Colombier 	m = fmap[font];
349bfe6f914SDavid du Colombier 	if(m >= nelem(charmap)) {
350bfe6f914SDavid du Colombier 		dprint(2, "map: fmap[font] %ud >= nelem(charmap) (%d)\n",
351bfe6f914SDavid du Colombier 			m, nelem(charmap));
352bfe6f914SDavid du Colombier 		return 0;
353bfe6f914SDavid du Colombier 	}
354219b2ee8SDavid du Colombier 	if(rp[1] == 0 && rp[0] < QUICK)		/* fast lookup */
355bfe6f914SDavid du Colombier 		r = charmap[m].quick[rp[0]];
356219b2ee8SDavid du Colombier 	else {			/* high-valued or compound character name */
357bfe6f914SDavid du Colombier 		snprint(c, sizeof c, "%S", rp);
358219b2ee8SDavid du Colombier 		r = 0;
359bfe6f914SDavid du Colombier 		for (p = charmap[m].slow; p; p = p->next)
360219b2ee8SDavid du Colombier 			if(eq(c, p->name)){
361219b2ee8SDavid du Colombier 				r = p->val;
362219b2ee8SDavid du Colombier 				break;
363219b2ee8SDavid du Colombier 			}
364219b2ee8SDavid du Colombier 	}
365219b2ee8SDavid du Colombier 	if(r == 0){	/* not there */
366219b2ee8SDavid du Colombier 		dprint(2, "didn't find %S font# %d\n", rp, font);
3673e12c5d1SDavid du Colombier 		return 0;
3683e12c5d1SDavid du Colombier 	}
369219b2ee8SDavid du Colombier 	dprint(2, "map %S to %s font# %d\n", rp, s, font);
370219b2ee8SDavid du Colombier 	s[runetochar(s, &r)] = 0;
3713e12c5d1SDavid du Colombier 	return s;
3723e12c5d1SDavid du Colombier }
3733e12c5d1SDavid du Colombier 
3743e12c5d1SDavid du Colombier static void
scanstr(char * s,char * ans,char ** ep)3753e12c5d1SDavid du Colombier scanstr(char *s, char *ans, char **ep)
3763e12c5d1SDavid du Colombier {
3773e12c5d1SDavid du Colombier 	for (; isspace((uchar) *s); s++)
3783e12c5d1SDavid du Colombier 		;
379219b2ee8SDavid du Colombier 	for (; *s!=0 && !isspace((uchar) *s); )
3803e12c5d1SDavid du Colombier 		*ans++ = *s++;
3813e12c5d1SDavid du Colombier 	*ans = 0;
3823e12c5d1SDavid du Colombier 	if (ep)
3833e12c5d1SDavid du Colombier 		*ep = s;
3843e12c5d1SDavid du Colombier }
385