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