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