Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <draw.h>
4
#include <event.h>
5
#include <bio.h>
6
#include "proof.h"
7
 
8
char	fname[NFONT][20];	/* font names */
9
char lastload[NFONT][20];	/* last file name prefix loaded for this font */
10
Font	*fonttab[NFONT][NSIZE];	/* pointers to fonts */
11
int	fmap[NFONT];		/* what map to use with this font */
12
 
13
static void	bufchar(Point, Subfont *, uchar *);
14
static void	loadfont(int, int);
15
static void	fontlookup(int, char *);
16
static void	buildxheight(Biobuf*);
17
static void	buildmap(Biobuf*);
18
static void	buildtroff(char *);
19
static void	addmap(int, char *, int);
20
static char	*map(Rune*, int);
21
static void	scanstr(char *, char *, char **);
22
 
23
int	specfont;	/* somehow, number of special font */
24
 
25
#define	NMAP	5
26
#define	QUICK	2048	/* char values less than this are quick to look up */
27
#define	eq(s,t)	strcmp((char *) s, (char *) t) == 0
28
 
29
int	curmap	= -1;	/* what map are we working on */
30
 
31
typedef struct Link Link;
32
struct Link	/* link names together */
33
{
34
	uchar	*name;
35
	int	val;
36
	Link	*next;
37
};
38
 
39
typedef struct Map Map;
40
struct Map	/* holds a mapping from uchar name to index */
41
{
42
	double	xheight;
43
	Rune	quick[QUICK];	/* low values get special treatment */
44
	Link	*slow;	/* other stuff goes into a link list */
45
};
46
 
47
Map	charmap[5];
48
 
49
typedef struct Fontmap Fontmap;
50
struct Fontmap	/* mapping from troff name to filename */
51
{
52
	char	*troffname;
53
	char	*prefix;
54
	int	map;		/* which charmap to use for this font */
55
	char	*fallback;	/* font to look in if can't find char here */
56
};
57
 
58
Fontmap	fontmap[100];
59
int	pos2fontmap[NFONT];	/* indexed by troff font position, gives Fontmap */
60
int	nfontmap	= 0;	/* how many are there */
61
 
62
 
63
void
64
dochar(Rune r[])
65
{
66
	char *s, *fb;
67
	Font *f;
68
	Point p;
69
	int fontno, fm, i;
70
	char buf[32];
71
 
72
	fontno = curfont;
73
	if((s = map(r, curfont)) == 0){		/* not on current font */
74
		if ((s = map(r, specfont)) != 0)	/* on special font */
75
			fontno = specfont;
76
		else{
77
			/* look for fallback */
78
			fm = pos2fontmap[curfont];
79
			fb = fontmap[fm].fallback;
80
			if(fb){
81
				/* see if fallback is mounted */
82
				for(i = 0; i < NFONT; i++){
83
					if(eq(fb, fontmap[pos2fontmap[i]].troffname)){
84
						s = map(r, i);
85
						if(s){
86
							fontno = i;
87
							goto found;
88
						}
89
					}
90
				}
91
			}
92
			/* no such char; use name itself on defont */
93
			/* this is not a general solution */
94
			p.x = hpos/DIV + xyoffset.x + offset.x;
95
			p.y = vpos/DIV + xyoffset.y + offset.y;
96
			p.y -= font->ascent;
97
			snprint(buf, sizeof buf, "%S", r);
98
			string(screen, p, display->black, ZP, font, buf);
99
			return;
100
		}
101
	}
102
    found:
103
	p.x = hpos/DIV + xyoffset.x + offset.x;
104
	p.y = vpos/DIV + xyoffset.y + offset.y;
105
	while ((f = fonttab[fontno][cursize]) == 0)
106
		loadfont(fontno, cursize);
107
	p.y -= f->ascent;
108
	dprint(2, "putting %S at %d,%d font %d, size %d\n", r, p.x, p.y, fontno, cursize);
109
	string(screen, p, display->black, ZP, f, s);
110
}
111
 
112
/* imported from libdraw/arith.c to permit an extern log2 function */
113
static int log2[] = {
114
	-1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1, 4,
115
	-1, -1, -1, -1, -1, -1, -1, 4 /* BUG */, -1, -1, -1, -1, -1, -1, -1, 5
116
};
117
 
118
static void
119
loadfont(int n, int s)
120
{
121
	char file[256];
122
	int i, fd, t, deep;
123
	static char *try[3] = {"", "times/R.", "pelm/"};
124
	Subfont *f;
125
	Font *ff;
126
 
127
	try[0] = fname[n];
128
	for (t = 0; t < 3; t++){
129
		i = s * mag * charmap[fmap[n]].xheight/0.72;	/* a pixel is 0.72 points */
130
		if (i < MINSIZE)
131
			i = MINSIZE;
132
		dprint(2, "size %d, i %d, mag %g\n", s, i, mag);
133
		for(; i >= MINSIZE; i--){
134
			/* if .font file exists, take that */
135
			snprint(file, sizeof file, "%s/%s%d.font",
136
				libfont, try[t], i);
137
			ff = openfont(display, file);
138
			if(ff != 0){
139
				fonttab[n][s] = ff;
140
				dprint(2, "using %s for font %d %d\n", file, n, s);
141
				return;
142
			}
143
			/* else look for a subfont file */
144
			for (deep = log2[screen->depth]; deep >= 0; deep--){
145
				snprint(file, sizeof file, "%s/%s%d.%d",
146
					libfont, try[t], i, deep);
147
				dprint(2, "trying %s for %d\n", file, i);
148
				if ((fd = open(file, 0)) >= 0){
149
					f = readsubfont(display, file, fd, 0);
150
					if (f == 0) {
151
						fprint(2, "can't rdsubfontfile %s: %r\n", file);
152
						exits("rdsubfont");
153
					}
154
					close(fd);
155
					ff = mkfont(f, 0);
156
					if(ff == 0){
157
						fprint(2, "can't mkfont %s: %r\n", file);
158
						exits("rdsubfont");
159
					}
160
					fonttab[n][s] = ff;
161
					dprint(2, "using %s for font %d %d\n", file, n, s);
162
					return;
163
				}
164
			}
165
		}
166
	}
167
	fprint(2, "can't find font %s.%d or substitute, quitting\n", fname[n], s);
168
	exits("no font");
169
}
170
 
171
void
172
loadfontname(int n, char *s)
173
{
174
	int i;
175
	Font *f, *g = 0;
176
 
177
	if (strcmp(s, fname[n]) == 0)
178
		return;
179
	if(fname[n] && fname[n][0]){
180
		if(lastload[n] && strcmp(lastload[n], fname[n]) == 0)
181
			return;
182
		strcpy(lastload[n], fname[n]);
183
	}
184
	fontlookup(n, s);
185
	for (i = 0; i < NSIZE; i++)
186
		if (f = fonttab[n][i]){
187
			if (f != g) {
188
				freefont(f);
189
				g = f;
190
			}
191
			fonttab[n][i] = 0;
192
		}
193
}
194
 
195
void
196
allfree(void)
197
{
198
	int i;
199
 
200
	for (i=0; i<NFONT; i++)
201
		loadfontname(i, "??");
202
}
203
 
204
 
205
void
206
readmapfile(char *file)
207
{
208
	Biobuf *fp;
209
	char *p, cmd[100];
210
 
211
	if ((fp=Bopen(file, OREAD)) == 0){
212
		fprint(2, "proof: can't open map file %s\n", file);
213
		exits("urk");
214
	}
215
	while((p=Brdline(fp, '\n')) != 0) {
216
		p[Blinelen(fp)-1] = 0;
217
		scanstr(p, cmd, 0);
218
		if(p[0]=='\0' || eq(cmd, "#"))	/* skip comments, empty */
219
			continue;
220
		else if(eq(cmd, "xheight"))
221
			buildxheight(fp);
222
		else if(eq(cmd, "map"))
223
			buildmap(fp);
224
		else if(eq(cmd, "special"))
225
			buildtroff(p);
226
		else if(eq(cmd, "troff"))
227
			buildtroff(p);
228
		else
229
			fprint(2, "weird map line %s\n", p);
230
	}
231
	Bterm(fp);
232
}
233
 
234
static void
235
buildxheight(Biobuf *fp)	/* map goes from char name to value to print via *string() */
236
{
237
	char *line;
238
 
239
	line = Brdline(fp, '\n');
240
	if(line == 0){
241
		fprint(2, "proof: bad map file\n");
242
		exits("map");
243
	}
244
	charmap[curmap].xheight = atof(line);
245
}
246
 
247
static void
248
buildmap(Biobuf *fp)	/* map goes from char name to value to print via *string() */
249
{
250
	uchar *p, *line, ch[100];
251
	int val;
252
	Rune r;
253
 
254
	curmap++;
255
	if(curmap >= NMAP){
256
		fprint(2, "proof: out of char maps; recompile\n");
257
		exits("charmap");
258
	}
259
	while ((line = Brdline(fp, '\n'))!= 0){
260
		if (line[0] == '\n')
261
			return;
262
		line[Blinelen(fp)-1] = 0;
263
		scanstr((char *) line, (char *) ch, (char **) &p);
264
		if (ch[0] == '\0') {
265
			fprint(2, "bad map file line '%s'\n", (char*)line);
266
			continue;
267
		}
268
		val = strtol((char *) p, 0, 10);
269
dprint(2, "buildmap %s (%x %x) %s %d\n", (char*)ch, ch[0], ch[1], (char*)p, val);
270
		chartorune(&r, (char*)ch);
271
		if(utflen((char*)ch)==1 && r<QUICK)
272
			charmap[curmap].quick[r] = val;
273
		else
274
			addmap(curmap, strdup((char *) ch), val);	/* put somewhere else */
275
	}
276
}
277
 
278
static void
279
addmap(int n, char *s, int val)	/* stick a new link on */
280
{
281
	Link *p = (Link *) malloc(sizeof(Link));
282
	Link *prev = charmap[n].slow;
283
 
284
	if(p == 0)
285
		exits("out of memory in addmap");
286
	p->name = (uchar *) s;
287
	p->val = val;
288
	p->next = prev;
289
	charmap[n].slow = p;
290
}
291
 
292
static void
293
buildtroff(char *buf)	/* map troff names into bitmap filenames */
294
{				/* e.g., R -> times/R., I -> times/I., etc. */
295
	char *p, cmd[100], name[200], prefix[400], fallback[100];
296
 
297
	scanstr(buf, cmd, &p);
298
	scanstr(p, name, &p);
299
	scanstr(p, prefix, &p);
300
	while(*p!=0 && isspace(*p))
301
		p++;
302
	if(*p != 0){
303
		scanstr(p, fallback, &p);
304
		fontmap[nfontmap].fallback = strdup(fallback);
305
	}else
306
		fontmap[nfontmap].fallback = 0;
307
	fontmap[nfontmap].troffname = strdup(name);
308
	fontmap[nfontmap].prefix = strdup(prefix);
309
	fontmap[nfontmap].map = curmap;
310
	dprint(2, "troff name %s is bitmap %s map %d in slot %d fallback %s\n",
311
		name, prefix, curmap, nfontmap, fontmap[nfontmap].fallback?
312
		fontmap[nfontmap].fallback: "<null>");
313
	nfontmap++;
314
}
315
 
316
static void
317
fontlookup(int n, char *s)	/* map troff name of s into position n */
318
{
319
	int i;
320
 
321
	for(i = 0; i < nfontmap; i++)
322
		if (eq(s, fontmap[i].troffname)) {
323
			strcpy(fname[n], fontmap[i].prefix);
324
			fmap[n] = fontmap[i].map;
325
			pos2fontmap[n] = i;
326
			if (eq(s, "S"))
327
				specfont = n;
328
			dprint(2, "font %d %s is %s\n", n, s, fname[n]);
329
			return;
330
		}
331
	/* god help us if this font isn't there */
332
}
333
 
334
 
335
static char *
336
map(Rune rp[], int font)	/* figure out mapping for char in this font */
337
{
338
	static char s[100];
339
	unsigned m;
340
	char c[32];
341
	Link *p;
342
	Rune r;
343
 
344
	if((unsigned)font >= NFONT) {
345
		dprint(2, "map: font %ud >= NFONT (%d)\n", font, NFONT);
346
		return 0;
347
	}
348
	m = fmap[font];
349
	if(m >= nelem(charmap)) {
350
		dprint(2, "map: fmap[font] %ud >= nelem(charmap) (%d)\n",
351
			m, nelem(charmap));
352
		return 0;
353
	}
354
	if(rp[1] == 0 && rp[0] < QUICK)		/* fast lookup */
355
		r = charmap[m].quick[rp[0]];
356
	else {			/* high-valued or compound character name */
357
		snprint(c, sizeof c, "%S", rp);
358
		r = 0;
359
		for (p = charmap[m].slow; p; p = p->next)
360
			if(eq(c, p->name)){
361
				r = p->val;
362
				break;
363
			}
364
	}
365
	if(r == 0){	/* not there */
366
		dprint(2, "didn't find %S font# %d\n", rp, font);
367
		return 0;
368
	}
369
	dprint(2, "map %S to %s font# %d\n", rp, s, font);
370
	s[runetochar(s, &r)] = 0;
371
	return s;
372
}
373
 
374
static void
375
scanstr(char *s, char *ans, char **ep)
376
{
377
	for (; isspace((uchar) *s); s++)
378
		;
379
	for (; *s!=0 && !isspace((uchar) *s); )
380
		*ans++ = *s++;
381
	*ans = 0;
382
	if (ep)
383
		*ep = s;
384
}