xref: /netbsd-src/sys/dev/wsfont/wsfont.c (revision d710132b4b8ce7f7cccaaf660cb16aa16b4077a0)
1 /* 	$NetBSD: wsfont.c,v 1.33 2003/02/10 14:28:21 jdolecek 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.33 2003/02/10 14:28:21 jdolecek 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)(const 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, const 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(const 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 		void *data;
367 		char *name;
368 
369 		ent->font = malloc(sizeof(struct wsdisplay_font), M_DEVBUF,
370 		    M_WAITOK);
371 		memcpy(ent->font, font, sizeof(*ent->font));
372 
373 		size = font->fontheight * font->numchars * font->stride;
374 		data = malloc(size, M_DEVBUF, M_WAITOK);
375 		memcpy(data, font->data, size);
376 		ent->font->data = data;
377 
378 		name = malloc(strlen(font->name) + 1, M_DEVBUF, M_WAITOK);
379 		strcpy(name, font->name);
380 		ent->font->name = name;
381 	}
382 
383 	TAILQ_INSERT_TAIL(&list, ent, chain);
384 	return (ent);
385 }
386 
387 int
388 wsfont_add(struct wsdisplay_font *font, int copy)
389 {
390 	struct font *ent;
391 
392 	/* Don't allow exact duplicates */
393 	if (wsfont_find(font->name, font->fontwidth, font->fontheight,
394 	    font->stride, 0, 0) >= 0)
395 		return (EEXIST);
396 
397 	ent = wsfont_add0(font, copy);
398 
399 	ident += (1 << WSFONT_IDENT_SHIFT);
400 	ent->cookie = wsfont_make_cookie(ident, font->bitorder,
401 	    font->byteorder);
402 
403 	return (0);
404 }
405 
406 int
407 wsfont_remove(int cookie)
408 {
409 	struct font *ent;
410 
411 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
412 		return (ENOENT);
413 
414 	if ((ent->flags & WSFONT_BUILTIN) != 0 || ent->lockcount != 0)
415 		return (EBUSY);
416 
417 	if ((ent->flags & WSFONT_STATIC) == 0) {
418 		free((void *)ent->font->data, M_DEVBUF);
419 		free((void *)ent->font->name, M_DEVBUF);
420 		free(ent->font, M_DEVBUF);
421 	}
422 
423 	TAILQ_REMOVE(&list, ent, chain);
424 	free(ent, M_DEVBUF);
425 
426 	return (0);
427 }
428 
429 int
430 wsfont_lock(int cookie, struct wsdisplay_font **ptr)
431 {
432 	struct font *ent, *neu;
433 	int bito, byteo;
434 
435 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) {
436 		if ((ent = wsfont_find0(cookie, WSFONT_IDENT_MASK)) == NULL)
437 			return (ENOENT);
438 
439 		bito = (cookie & WSFONT_BITO_MASK) >> WSFONT_BITO_SHIFT;
440 		byteo = (cookie & WSFONT_BYTEO_MASK) >> WSFONT_BYTEO_SHIFT;
441 
442 		if (ent->lockcount != 0) {
443 			neu = wsfont_add0(ent->font, 1);
444 			neu->flags |= WSFONT_COPY;
445 
446 			aprint_normal("wsfont: font '%s' bito %d byteo %d copied to bito %d byteo %d\n",
447 				ent->font->name,
448 				ent->font->bitorder, ent->font->byteorder,
449 				bito, byteo);
450 
451 			ent = neu;
452 		}
453 
454 		if (bito && bito != ent->font->bitorder) {
455 			wsfont_revbit(ent->font);
456 			ent->font->bitorder = bito;
457 		}
458 
459 		if (byteo && byteo != ent->font->byteorder) {
460 			wsfont_revbyte(ent->font);
461 			ent->font->byteorder = byteo;
462 		}
463 
464 		ent->cookie = cookie;
465 	}
466 
467 	ent->lockcount++;
468 	*ptr = ent->font;
469 	return (0);
470 }
471 
472 int
473 wsfont_unlock(int cookie)
474 {
475 	struct font *ent;
476 
477 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
478 		return (ENOENT);
479 
480 	if (ent->lockcount == 0)
481 		panic("wsfont_unlock: font not locked");
482 
483 	if (--ent->lockcount == 0 && (ent->flags & WSFONT_COPY) != 0)
484 		wsfont_remove(cookie);
485 
486 	return (0);
487 }
488 
489 /*
490  * Unicode to font encoding mappings
491  */
492 
493 /*
494  * To save memory, font encoding tables use a two level lookup.  First the
495  * high byte of the Unicode is used to lookup the level 2 table, then the
496  * low byte indexes that table.  Level 2 tables that are not needed are
497  * omitted (NULL), and both level 1 and level 2 tables have base and size
498  * attributes to keep their size down.
499  */
500 
501 struct wsfont_level1_glyphmap {
502 	const struct	wsfont_level2_glyphmap **level2;
503 	int	base;	/* High byte for first level2 entry	*/
504 	int	size;	/* Number of level2 entries		*/
505 };
506 
507 struct wsfont_level2_glyphmap {
508 	int	base;	/* Low byte for first character		*/
509 	int	size;	/* Number of characters			*/
510 	const void	*chars;	/* Pointer to character number entries  */
511 	int	width;	/* Size of each entry in bytes (1,2,4)  */
512 };
513 
514 #define null16			\
515 	NULL, NULL, NULL, NULL,	\
516 	NULL, NULL, NULL, NULL,	\
517 	NULL, NULL, NULL, NULL,	\
518 	NULL, NULL, NULL, NULL
519 
520 /*
521  * IBM 437 maps
522  */
523 
524 static const u_int8_t ibm437_chars_0[] = {
525 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
526 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
527 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
528 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
529 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
530 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
531 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
532 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
533 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
534 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
535 	255,173,155,156, 0, 157, 0,  0,  0,  0, 166,174,170, 0,  0,  0,
536 	 0, 241,253, 0,  0,  0,  0, 249, 0,  0, 167,175,172,171, 0, 168,
537 	 0,  0,  0,  0, 142,143,146,128, 0, 144, 0,  0,  0,  0,  0,  0,
538 	 0, 165, 0,  0,  0,  0, 153, 0,  0,  0,  0,  0, 154, 0,  0,  0,
539 	133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
540 	 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0,  0, 152
541 };
542 
543 static const u_int8_t ibm437_chars_1[] = {
544 	159
545 };
546 
547 static const u_int8_t ibm437_chars_3[] = {
548 	226, 0,  0,  0,  0, 233, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
549 	228, 0,  0, 232, 0,  0, 234, 0,  0,  0,  0,  0,  0,  0, 224,225,
550 	 0, 235,238, 0,  0,  0,  0,  0,  0, 230, 0,  0,  0, 227, 0,  0,
551 	229,231
552 };
553 
554 static const u_int8_t ibm437_chars_32[] = {
555 	252, 0,  0,  0,  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,  0,  0,  0,  0,
557 	 0,  0,  0,  0,  0,  0,  0,  0, 158
558 };
559 
560 static const u_int8_t ibm437_chars_34[] = {
561 	237, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
562 	 0,  0,  0, 248,250,251, 0,  0,  0, 236, 0,  0,  0,  0,  0,  0,
563 	 0,  0,  0,  0, 239, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
564 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
565 	 0,  0,  0, 247, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
566 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,240,  0,  0,243,
567 	242
568 };
569 
570 static const u_int8_t ibm437_chars_35[] = {
571 	169, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
572 	244,245
573 };
574 
575 static const u_int8_t ibm437_chars_37[] = {
576 	196,205,179,186, 0,  0,  0,  0,  0,  0,  0,  0, 218,213,214,201,
577 	191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0,  0,
578 	199, 0,  0, 204,180,181, 0,  0, 182, 0,  0, 185,194, 0,  0, 209,
579 	210, 0,  0, 203,193, 0,  0, 207,208, 0,  0, 202,197, 0,  0, 216,
580 	 0,  0, 215, 0,  0,  0,  0,  0,  0,  0,  0, 206, 0,  0,  0,  0,
581 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
582 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
583 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
584 	223, 0,  0,  0, 220, 0,  0,  0, 219, 0,  0,  0, 221, 0,  0,  0,
585 	222,176,177,178, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
586 	254
587 };
588 
589 static const struct wsfont_level2_glyphmap ibm437_level2_0 =
590     { 0, 256, ibm437_chars_0, 1 };
591 
592 static const struct wsfont_level2_glyphmap ibm437_level2_1 =
593     { 146, 1, ibm437_chars_1, 1 };
594 
595 static const struct wsfont_level2_glyphmap ibm437_level2_3 =
596     { 147, 50, ibm437_chars_3, 1 };
597 
598 static const struct wsfont_level2_glyphmap ibm437_level2_32 =
599     { 127, 41, ibm437_chars_32, 1 };
600 
601 static const struct wsfont_level2_glyphmap ibm437_level2_34 =
602     { 5, 97, ibm437_chars_34, 1 };
603 
604 static const struct wsfont_level2_glyphmap ibm437_level2_35 =
605     { 16, 18, ibm437_chars_35, 1 };
606 
607 static const struct wsfont_level2_glyphmap ibm437_level2_37 =
608     { 0, 161, ibm437_chars_37, 1 };
609 
610 static const struct wsfont_level2_glyphmap *ibm437_level1[] = {
611 	&ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
612 	NULL, NULL, NULL, NULL,
613 	NULL, NULL, NULL, NULL,
614 	NULL, NULL, NULL, NULL,
615 	NULL, NULL, NULL, NULL,
616 	NULL, NULL, NULL, NULL,
617 	NULL, NULL, NULL, NULL,
618 	NULL, NULL, NULL, NULL,
619 	&ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
620 	NULL, &ibm437_level2_37
621 };
622 
623 /*
624  * ISO-8859-7 maps
625  */
626 static const u_int8_t iso7_chars_0[] = {
627 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
628 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
629 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
630 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
631 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
632 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
633 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
634 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
635 	128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
636 	144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
637 	160, 0,  0, 163, 0,  0, 166,167,168,169, 0, 171,172,173, 0,  0,
638 	176,177,178,179,180, 0,  0, 183, 0,  0,  0, 187, 0, 189
639 };
640 
641 static const u_int8_t iso7_chars_3[] = {
642 	182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197,
643 	198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213,
644 	214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
645 	230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
646 	246,247,248,249,250,251,252,253,254, 0,  0,  0,  0,  0,  0,  0,
647 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
648 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 181
649 };
650 
651 static const u_int8_t iso7_chars_32[] = {
652 	175, 0,  0,  0,  0, 162, 0, 161
653 };
654 
655 static const struct wsfont_level2_glyphmap iso7_level2_0 =
656     { 0, 190, iso7_chars_0, 1 };
657 
658 static const struct wsfont_level2_glyphmap iso7_level2_3 =
659     { 134, 111, iso7_chars_3, 1 };
660 
661 static const struct wsfont_level2_glyphmap iso7_level2_32 =
662     { 20, 8, iso7_chars_32, 1 };
663 
664 static const struct wsfont_level2_glyphmap *iso7_level1[] = {
665 	&iso7_level2_0, NULL, NULL, &iso7_level2_3,
666 	NULL, NULL, NULL, NULL,
667 	NULL, NULL, NULL, NULL,
668 	NULL, NULL, NULL, NULL,
669 	NULL, NULL, NULL, NULL,
670 	NULL, NULL, NULL, NULL,
671 	NULL, NULL, NULL, NULL,
672 	NULL, NULL, NULL, NULL,
673 	&iso7_level2_32
674 };
675 
676 static const struct wsfont_level1_glyphmap encodings[] = {
677 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_ISO */
678 	{ ibm437_level1, 0, 38 },	/* WSDISPLAY_FONTENC_IBM */
679 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_PCVT */
680 	{ iso7_level1, 0, 33 },		/* WSDISPLAY_FONTENC_ISO7 */
681 };
682 
683 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0]))
684 
685 /*
686  * Remap Unicode character to glyph
687  */
688 int
689 wsfont_map_unichar(struct wsdisplay_font *font, int c)
690 {
691 	const struct wsfont_level1_glyphmap *map1;
692 	const struct wsfont_level2_glyphmap *map2;
693 	int hi, lo;
694 
695 	if (font->encoding == WSDISPLAY_FONTENC_ISO)
696 		return (c);
697 
698 	if (font->encoding < 0 || font->encoding > MAX_ENCODING)
699 		return (-1);
700 
701 	hi = (c >> 8);
702 	lo = c & 255;
703 	map1 = &encodings[font->encoding];
704 
705 	if (hi < map1->base || hi >= map1->base + map1->size)
706 		return (-1);
707 
708 	map2 = map1->level2[hi - map1->base];
709 
710 	if (map2 == NULL || lo < map2->base || lo >= map2->base + map2->size)
711 		return (-1);
712 
713 	lo -= map2->base;
714 
715 	switch(map2->width) {
716 	case 1:
717 		c = (((const u_int8_t *)map2->chars)[lo]);
718 		break;
719 	case 2:
720 		c = (((const u_int16_t *)map2->chars)[lo]);
721 		break;
722 	case 4:
723 		c = (((const u_int32_t *)map2->chars)[lo]);
724 		break;
725 	}
726 
727 	if (c == 0 && lo != 0)
728 		return (-1);
729 
730 	return (c);
731 }
732