xref: /netbsd-src/sys/dev/wsfont/wsfont.c (revision b8c616269f5ebf18ab2e35cb8099d683130a177c)
1 /* 	$NetBSD: wsfont.c,v 1.30 2003/01/12 13:12:42 tsutsui Exp $	*/
2 
3 /*-
4  * Copyright (c) 1999, 2000, 2001, 2002 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Andrew Doran.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  * 3. All advertising materials mentioning features or use of this software
19  *    must display the following acknowledgement:
20  *	This product includes software developed by the NetBSD
21  *	Foundation, Inc. and its contributors.
22  * 4. Neither the name of The NetBSD Foundation nor the names of its
23  *    contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  */
38 
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: wsfont.c,v 1.30 2003/01/12 13:12:42 tsutsui Exp $");
41 
42 #include "opt_wsfont.h"
43 
44 #include <sys/param.h>
45 #include <sys/systm.h>
46 #include <sys/time.h>
47 #include <sys/malloc.h>
48 #include <sys/queue.h>
49 
50 #include <dev/wscons/wsdisplayvar.h>
51 #include <dev/wscons/wsconsio.h>
52 #include <dev/wsfont/wsfont.h>
53 
54 #undef HAVE_FONT
55 
56 #ifdef FONT_QVSS8x15
57 #define HAVE_FONT 1
58 #include <dev/wsfont/qvss8x15.h>
59 #endif
60 
61 #ifdef FONT_GALLANT12x22
62 #define HAVE_FONT 1
63 #include <dev/wsfont/gallant12x22.h>
64 #endif
65 
66 #ifdef FONT_LUCIDA16x29
67 #define HAVE_FONT 1
68 #include <dev/wsfont/lucida16x29.h>
69 #endif
70 
71 #ifdef FONT_VT220L8x8
72 #define HAVE_FONT 1
73 #include <dev/wsfont/vt220l8x8.h>
74 #endif
75 
76 #ifdef FONT_VT220L8x10
77 #define HAVE_FONT 1
78 #include <dev/wsfont/vt220l8x10.h>
79 #endif
80 
81 #ifdef FONT_VT220L8x16
82 #define HAVE_FONT 1
83 #include <dev/wsfont/vt220l8x16.h>
84 #endif
85 
86 #ifdef FONT_VT220ISO8x16
87 #define HAVE_FONT 1
88 #include <dev/wsfont/vt220iso8x16.h>
89 #endif
90 
91 #ifdef FONT_SONY8x16
92 #define HAVE_FONT 1
93 #include <dev/wsfont/sony8x16.h>
94 #endif
95 
96 #ifdef FONT_SONY12x24
97 #define HAVE_FONT 1
98 #include <dev/wsfont/sony12x24.h>
99 #endif
100 
101 #ifdef FONT_OMRON12x20
102 #define HAVE_FONT 1
103 #include <dev/wsfont/omron12x20.h>
104 #endif
105 
106 /* Make sure we always have at least one font. */
107 #ifndef HAVE_FONT
108 #define HAVE_FONT 1
109 #define FONT_BOLD8x16 1
110 #endif
111 
112 #ifdef FONT_BOLD8x16
113 #include <dev/wsfont/bold8x16.h>
114 #endif
115 
116 #define	WSFONT_IDENT_MASK	0xffffff00
117 #define	WSFONT_IDENT_SHIFT	8
118 #define	WSFONT_BITO_MASK	0x000000f0
119 #define	WSFONT_BITO_SHIFT	4
120 #define	WSFONT_BYTEO_MASK	0x0000000f
121 #define	WSFONT_BYTEO_SHIFT	0
122 
123 #define WSFONT_BUILTIN	0x01	/* In wsfont.c */
124 #define WSFONT_STATIC	0x02	/* Font structures not malloc()ed */
125 #define WSFONT_COPY	0x04	/* Copy of existing font in table */
126 
127 /* Placeholder struct used for linked list */
128 struct font {
129 	TAILQ_ENTRY(font) chain;
130 	struct	wsdisplay_font *font;
131 	u_int	lockcount;
132 	u_int	cookie;
133 	u_int	flags;
134 };
135 
136 /* Our list of built-in fonts */
137 static struct font builtin_fonts[] = {
138 #ifdef FONT_BOLD8x16
139 	{ { NULL }, &bold8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN  },
140 #endif
141 #ifdef FONT_ISO8x16
142 	{ { NULL }, &iso8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
143 #endif
144 #ifdef FONT_COURIER11x18
145 	{ { NULL }, &courier11x18, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
146 #endif
147 #ifdef FONT_GALLANT12x22
148 	{ { NULL }, &gallant12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
149 #endif
150 #ifdef FONT_LUCIDA16x29
151 	{ { NULL }, &lucida16x29, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
152 #endif
153 #ifdef FONT_QVSS8x15
154 	{ { NULL }, &qvss8x15, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
155 #endif
156 #ifdef FONT_VT220L8x8
157 	{ { NULL }, &vt220l8x8, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
158 #endif
159 #ifdef FONT_VT220L8x10
160 	{ { NULL }, &vt220l8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
161 #endif
162 #ifdef FONT_VT220L8x16
163 	{ { NULL }, &vt220l8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
164 #endif
165 #ifdef FONT_VT220ISO8x16
166 	{ { NULL }, &vt220iso8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
167 #endif
168 #ifdef FONT_SONY8x16
169 	{ { NULL }, &sony8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
170 #endif
171 #ifdef FONT_SONY12x24
172 	{ { NULL }, &sony12x24, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
173 #endif
174 #ifdef FONT_OMRON12x20
175 	{ { NULL }, &omron12x20, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
176 #endif
177 	{ { NULL }, NULL, 0, 0, 0 },
178 };
179 
180 static TAILQ_HEAD(,font)	list;
181 static int	ident;
182 
183 /* Reverse the bit order in a byte */
184 static const u_char reverse[256] = {
185 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
186 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
187 	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
188 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
189 	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
190 	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
191 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
192 	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
193 	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
194 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
195 	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
196 	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
197 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
198 	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
199 	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
200 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
201 	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
202 	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
203 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
204 	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
205 	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
206 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
207 	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
208 	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
209 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
210 	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
211 	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
212 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
213 	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
214 	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
215 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
216 	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
217 };
218 
219 static struct	font *wsfont_find0(int, int);
220 static struct	font *wsfont_add0(struct wsdisplay_font *, int);
221 static void	wsfont_revbit(struct wsdisplay_font *);
222 static void	wsfont_revbyte(struct wsdisplay_font *);
223 static int __inline__ wsfont_make_cookie(int, int, int);
224 
225 static int __inline__
226 wsfont_make_cookie(int ident, int bito, int byteo)
227 {
228 
229 	return ((ident & WSFONT_IDENT_MASK) |
230 	    (bito << WSFONT_BITO_SHIFT) |
231 	    (byteo << WSFONT_BYTEO_SHIFT));
232 }
233 
234 static void
235 wsfont_revbit(struct wsdisplay_font *font)
236 {
237 	u_char *p, *m;
238 
239 	p = (u_char *)font->data;
240 	m = p + font->stride * font->numchars * font->fontheight;
241 
242 	for (; p < m; p++)
243 		*p = reverse[*p];
244 }
245 
246 static void
247 wsfont_revbyte(struct wsdisplay_font *font)
248 {
249 	int x, l, r, nr;
250 	u_char *rp;
251 
252 	if (font->stride == 1)
253 		return;
254 
255 	rp = (u_char *)font->data;
256 	nr = font->numchars * font->fontheight;
257 
258 	while (nr--) {
259 		l = 0;
260 		r = font->stride - 1;
261 
262 		while (l < r) {
263 			x = rp[l];
264 			rp[l] = rp[r];
265 			rp[r] = x;
266 			l++, r--;
267 		}
268 
269 		rp += font->stride;
270 	}
271 }
272 
273 void
274 wsfont_enum(void (*cb)(char *, int, int, int))
275 {
276 	struct wsdisplay_font *f;
277 	struct font *ent;
278 
279 	TAILQ_FOREACH(ent, &list, chain) {
280 		f = ent->font;
281 		cb(f->name, f->fontwidth, f->fontheight, f->stride);
282 	}
283 }
284 
285 void
286 wsfont_init(void)
287 {
288 	struct font *ent;
289 	static int again;
290 	int i;
291 
292 	if (again != 0)
293 		return;
294 	again = 1;
295 
296 	TAILQ_INIT(&list);
297 	ent = builtin_fonts;
298 
299 	for (i = 0; builtin_fonts[i].font != NULL; i++, ent++) {
300 		ident += (1 << WSFONT_IDENT_SHIFT);
301 		ent->cookie = wsfont_make_cookie(ident,
302 		    ent->font->bitorder, ent->font->byteorder);
303 		TAILQ_INSERT_TAIL(&list, ent, chain);
304 	}
305 }
306 
307 static struct font *
308 wsfont_find0(int cookie, int mask)
309 {
310 	struct font *ent;
311 
312 	TAILQ_FOREACH(ent, &list, chain) {
313 		if ((ent->cookie & mask) == (cookie & mask))
314 			return (ent);
315 	}
316 
317 	return (NULL);
318 }
319 
320 int
321 wsfont_matches(struct wsdisplay_font *font, char *name,
322 	       int width, int height, int stride)
323 {
324 
325 	if (height != 0 && font->fontheight != height)
326 		return (0);
327 
328 	if (width != 0 && font->fontwidth != width)
329 		return (0);
330 
331 	if (stride != 0 && font->stride != stride)
332 		return (0);
333 
334 	if (name != NULL && strcmp(font->name, name) != 0)
335 		return (0);
336 
337 	return (1);
338 }
339 
340 int
341 wsfont_find(char *name, int width, int height, int stride, int bito, int byteo)
342 {
343 	struct font *ent;
344 
345 	TAILQ_FOREACH(ent, &list, chain) {
346 		if (wsfont_matches(ent->font, name, width, height, stride))
347 			return (wsfont_make_cookie(ent->cookie, bito, byteo));
348 	}
349 
350 	return (-1);
351 }
352 
353 static struct font *
354 wsfont_add0(struct wsdisplay_font *font, int copy)
355 {
356 	struct font *ent;
357 	size_t size;
358 
359 	ent = malloc(sizeof(struct font), M_DEVBUF, M_WAITOK | M_ZERO);
360 
361 	/* Is this font statically allocated? */
362 	if (!copy) {
363 		ent->font = font;
364 		ent->flags = WSFONT_STATIC;
365 	} else {
366 		ent->font = malloc(sizeof(struct wsdisplay_font), M_DEVBUF,
367 		    M_WAITOK);
368 		memcpy(ent->font, font, sizeof(*ent->font));
369 
370 		size = font->fontheight * font->numchars * font->stride;
371 		ent->font->data = malloc(size, M_DEVBUF, M_WAITOK);
372 		memcpy(ent->font->data, font->data, size);
373 
374 		ent->font->name = malloc(strlen(font->name) + 1, M_DEVBUF,
375 		    M_WAITOK);
376 		strcpy(ent->font->name, font->name);
377 	}
378 
379 	TAILQ_INSERT_TAIL(&list, ent, chain);
380 	return (ent);
381 }
382 
383 int
384 wsfont_add(struct wsdisplay_font *font, int copy)
385 {
386 	struct font *ent;
387 
388 	/* Don't allow exact duplicates */
389 	if (wsfont_find(font->name, font->fontwidth, font->fontheight,
390 	    font->stride, 0, 0) >= 0)
391 		return (EEXIST);
392 
393 	ent = wsfont_add0(font, copy);
394 
395 	ident += (1 << WSFONT_IDENT_SHIFT);
396 	ent->cookie = wsfont_make_cookie(ident, font->bitorder,
397 	    font->byteorder);
398 
399 	return (0);
400 }
401 
402 int
403 wsfont_remove(int cookie)
404 {
405 	struct font *ent;
406 
407 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
408 		return (ENOENT);
409 
410 	if ((ent->flags & WSFONT_BUILTIN) != 0 || ent->lockcount != 0)
411 		return (EBUSY);
412 
413 	if ((ent->flags & WSFONT_STATIC) == 0) {
414 		free(ent->font->data, M_DEVBUF);
415 		free(ent->font->name, M_DEVBUF);
416 		free(ent->font, M_DEVBUF);
417 	}
418 
419 	TAILQ_REMOVE(&list, ent, chain);
420 	free(ent, M_DEVBUF);
421 
422 	return (0);
423 }
424 
425 int
426 wsfont_lock(int cookie, struct wsdisplay_font **ptr)
427 {
428 	struct font *ent, *neu;
429 	int bito, byteo;
430 
431 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) {
432 		if ((ent = wsfont_find0(cookie, WSFONT_IDENT_MASK)) == NULL)
433 			return (ENOENT);
434 
435 		if (ent->lockcount != 0) {
436 			neu = wsfont_add0(ent->font, 1);
437 			neu->flags |= WSFONT_COPY;
438 			ent = neu;
439 		}
440 
441 		bito = (cookie & WSFONT_BITO_MASK) >> WSFONT_BITO_SHIFT;
442 		byteo = (cookie & WSFONT_BYTEO_MASK) >> WSFONT_BYTEO_SHIFT;
443 
444 		if (bito && bito != ent->font->bitorder) {
445 			wsfont_revbit(ent->font);
446 			ent->font->bitorder = bito;
447 		}
448 
449 		if (byteo && byteo != ent->font->byteorder) {
450 			wsfont_revbyte(ent->font);
451 			ent->font->byteorder = byteo;
452 		}
453 
454 		ent->cookie = cookie;
455 	}
456 
457 	ent->lockcount++;
458 	*ptr = ent->font;
459 	return (0);
460 }
461 
462 int
463 wsfont_unlock(int cookie)
464 {
465 	struct font *ent;
466 
467 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
468 		return (ENOENT);
469 
470 	if (ent->lockcount == 0)
471 		panic("wsfont_unlock: font not locked");
472 
473 	if (--ent->lockcount == 0 && (ent->flags & WSFONT_COPY) != 0)
474 		wsfont_remove(cookie);
475 
476 	return (0);
477 }
478 
479 /*
480  * Unicode to font encoding mappings
481  */
482 
483 /*
484  * To save memory, font encoding tables use a two level lookup.  First the
485  * high byte of the Unicode is used to lookup the level 2 table, then the
486  * low byte indexes that table.  Level 2 tables that are not needed are
487  * omitted (NULL), and both level 1 and level 2 tables have base and size
488  * attributes to keep their size down.
489  */
490 
491 struct wsfont_level1_glyphmap {
492 	const struct	wsfont_level2_glyphmap **level2;
493 	int	base;	/* High byte for first level2 entry	*/
494 	int	size;	/* Number of level2 entries		*/
495 };
496 
497 struct wsfont_level2_glyphmap {
498 	int	base;	/* Low byte for first character		*/
499 	int	size;	/* Number of characters			*/
500 	const void	*chars;	/* Pointer to character number entries  */
501 	int	width;	/* Size of each entry in bytes (1,2,4)  */
502 };
503 
504 #define null16			\
505 	NULL, NULL, NULL, NULL,	\
506 	NULL, NULL, NULL, NULL,	\
507 	NULL, NULL, NULL, NULL,	\
508 	NULL, NULL, NULL, NULL
509 
510 /*
511  * IBM 437 maps
512  */
513 
514 static const u_int8_t ibm437_chars_0[] = {
515 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
516 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
517 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
518 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
519 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
520 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
521 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
522 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
523 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
524 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
525 	255,173,155,156, 0, 157, 0,  0,  0,  0, 166,174,170, 0,  0,  0,
526 	 0, 241,253, 0,  0,  0,  0, 249, 0,  0, 167,175,172,171, 0, 168,
527 	 0,  0,  0,  0, 142,143,146,128, 0, 144, 0,  0,  0,  0,  0,  0,
528 	 0, 165, 0,  0,  0,  0, 153, 0,  0,  0,  0,  0, 154, 0,  0,  0,
529 	133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
530 	 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0,  0, 152
531 };
532 
533 static const u_int8_t ibm437_chars_1[] = {
534 	159
535 };
536 
537 static const u_int8_t ibm437_chars_3[] = {
538 	226, 0,  0,  0,  0, 233, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
539 	228, 0,  0, 232, 0,  0, 234, 0,  0,  0,  0,  0,  0,  0, 224,225,
540 	 0, 235,238, 0,  0,  0,  0,  0,  0, 230, 0,  0,  0, 227, 0,  0,
541 	229,231
542 };
543 
544 static const u_int8_t ibm437_chars_32[] = {
545 	252, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
546 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
547 	 0,  0,  0,  0,  0,  0,  0,  0, 158
548 };
549 
550 static const u_int8_t ibm437_chars_34[] = {
551 	237, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
552 	 0,  0,  0, 248,250,251, 0,  0,  0, 236, 0,  0,  0,  0,  0,  0,
553 	 0,  0,  0,  0, 239, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
554 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
555 	 0,  0,  0, 247, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
556 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,240,  0,  0,243,
557 	242
558 };
559 
560 static const u_int8_t ibm437_chars_35[] = {
561 	169, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
562 	244,245
563 };
564 
565 static const u_int8_t ibm437_chars_37[] = {
566 	196,205,179,186, 0,  0,  0,  0,  0,  0,  0,  0, 218,213,214,201,
567 	191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0,  0,
568 	199, 0,  0, 204,180,181, 0,  0, 182, 0,  0, 185,194, 0,  0, 209,
569 	210, 0,  0, 203,193, 0,  0, 207,208, 0,  0, 202,197, 0,  0, 216,
570 	 0,  0, 215, 0,  0,  0,  0,  0,  0,  0,  0, 206, 0,  0,  0,  0,
571 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
572 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
573 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
574 	223, 0,  0,  0, 220, 0,  0,  0, 219, 0,  0,  0, 221, 0,  0,  0,
575 	222,176,177,178, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
576 	254
577 };
578 
579 static const struct wsfont_level2_glyphmap ibm437_level2_0 =
580     { 0, 256, ibm437_chars_0, 1 };
581 
582 static const struct wsfont_level2_glyphmap ibm437_level2_1 =
583     { 146, 1, ibm437_chars_1, 1 };
584 
585 static const struct wsfont_level2_glyphmap ibm437_level2_3 =
586     { 147, 50, ibm437_chars_3, 1 };
587 
588 static const struct wsfont_level2_glyphmap ibm437_level2_32 =
589     { 127, 41, ibm437_chars_32, 1 };
590 
591 static const struct wsfont_level2_glyphmap ibm437_level2_34 =
592     { 5, 97, ibm437_chars_34, 1 };
593 
594 static const struct wsfont_level2_glyphmap ibm437_level2_35 =
595     { 16, 18, ibm437_chars_35, 1 };
596 
597 static const struct wsfont_level2_glyphmap ibm437_level2_37 =
598     { 0, 161, ibm437_chars_37, 1 };
599 
600 static const struct wsfont_level2_glyphmap *ibm437_level1[] = {
601 	&ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
602 	NULL, NULL, NULL, NULL,
603 	NULL, NULL, NULL, NULL,
604 	NULL, NULL, NULL, NULL,
605 	NULL, NULL, NULL, NULL,
606 	NULL, NULL, NULL, NULL,
607 	NULL, NULL, NULL, NULL,
608 	NULL, NULL, NULL, NULL,
609 	&ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
610 	NULL, &ibm437_level2_37
611 };
612 
613 /*
614  * ISO-8859-7 maps
615  */
616 static const u_int8_t iso7_chars_0[] = {
617 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
618 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
619 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
620 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
621 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
622 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
623 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
624 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
625 	128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
626 	144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
627 	160, 0,  0, 163, 0,  0, 166,167,168,169, 0, 171,172,173, 0,  0,
628 	176,177,178,179,180, 0,  0, 183, 0,  0,  0, 187, 0, 189
629 };
630 
631 static const u_int8_t iso7_chars_3[] = {
632 	182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197,
633 	198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213,
634 	214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
635 	230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
636 	246,247,248,249,250,251,252,253,254, 0,  0,  0,  0,  0,  0,  0,
637 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
638 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 181
639 };
640 
641 static const u_int8_t iso7_chars_32[] = {
642 	175, 0,  0,  0,  0, 162, 0, 161
643 };
644 
645 static const struct wsfont_level2_glyphmap iso7_level2_0 =
646     { 0, 190, iso7_chars_0, 1 };
647 
648 static const struct wsfont_level2_glyphmap iso7_level2_3 =
649     { 134, 111, iso7_chars_3, 1 };
650 
651 static const struct wsfont_level2_glyphmap iso7_level2_32 =
652     { 20, 8, iso7_chars_32, 1 };
653 
654 static const struct wsfont_level2_glyphmap *iso7_level1[] = {
655 	&iso7_level2_0, NULL, NULL, &iso7_level2_3,
656 	NULL, NULL, NULL, NULL,
657 	NULL, NULL, NULL, NULL,
658 	NULL, NULL, NULL, NULL,
659 	NULL, NULL, NULL, NULL,
660 	NULL, NULL, NULL, NULL,
661 	NULL, NULL, NULL, NULL,
662 	NULL, NULL, NULL, NULL,
663 	&iso7_level2_32
664 };
665 
666 static const struct wsfont_level1_glyphmap encodings[] = {
667 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_ISO */
668 	{ ibm437_level1, 0, 38 },	/* WSDISPLAY_FONTENC_IBM */
669 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_PCVT */
670 	{ iso7_level1, 0, 33 },		/* WSDISPLAY_FONTENC_ISO7 */
671 };
672 
673 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0]))
674 
675 /*
676  * Remap Unicode character to glyph
677  */
678 int
679 wsfont_map_unichar(struct wsdisplay_font *font, int c)
680 {
681 	const struct wsfont_level1_glyphmap *map1;
682 	const struct wsfont_level2_glyphmap *map2;
683 	int hi, lo;
684 
685 	if (font->encoding == WSDISPLAY_FONTENC_ISO)
686 		return (c);
687 
688 	if (font->encoding < 0 || font->encoding > MAX_ENCODING)
689 		return (-1);
690 
691 	hi = (c >> 8);
692 	lo = c & 255;
693 	map1 = &encodings[font->encoding];
694 
695 	if (hi < map1->base || hi >= map1->base + map1->size)
696 		return (-1);
697 
698 	map2 = map1->level2[hi - map1->base];
699 
700 	if (map2 == NULL || lo < map2->base || lo >= map2->base + map2->size)
701 		return (-1);
702 
703 	lo -= map2->base;
704 
705 	switch(map2->width) {
706 	case 1:
707 		c = (((const u_int8_t *)map2->chars)[lo]);
708 		break;
709 	case 2:
710 		c = (((const u_int16_t *)map2->chars)[lo]);
711 		break;
712 	case 4:
713 		c = (((const u_int32_t *)map2->chars)[lo]);
714 		break;
715 	}
716 
717 	if (c == 0 && lo != 0)
718 		return (-1);
719 
720 	return (c);
721 }
722