xref: /netbsd-src/sys/dev/wsfont/wsfont.c (revision 27578b9aac214cc7796ead81dcc5427e79d5f2a0)
1 /* 	$NetBSD: wsfont.c,v 1.21 2001/09/03 17:04:11 drochner 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.21 2001/09/03 17:04:11 drochner 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 __P((int));
191 static void	wsfont_revbit __P((struct wsdisplay_font *));
192 static void	wsfont_revbyte __P((struct wsdisplay_font *));
193 
194 /*
195  * Reverse the bit order of a font
196  */
197 static void
198 wsfont_revbit(font)
199 	struct wsdisplay_font *font;
200 {
201 	u_char *p, *m;
202 
203 	p = (u_char *)font->data;
204 	m = p + font->stride * font->numchars * font->fontheight;
205 
206 	for (; p < m; p++)
207 		*p = reverse[*p];
208 }
209 
210 /*
211  * Reverse the byte order of a font
212  */
213 static void
214 wsfont_revbyte(font)
215 	struct wsdisplay_font *font;
216 {
217 	int x, l, r, nr;
218 	u_char *rp;
219 
220 	if (font->stride == 1)
221 		return;
222 
223 	rp = (u_char *)font->data;
224 	nr = font->numchars * font->fontheight;
225 
226 	while (nr--) {
227 		l = 0;
228 		r = font->stride - 1;
229 
230 		while (l < r) {
231 			x = rp[l];
232 			rp[l] = rp[r];
233 			rp[r] = x;
234 			l++, r--;
235 		}
236 
237 		rp += font->stride;
238 	}
239 }
240 
241 /*
242  * Enumarate the list of fonts
243  */
244 void
245 wsfont_enum(cb)
246 	void (*cb) __P((char *, int, int, int));
247 {
248 	struct wsdisplay_font *f;
249 	struct font *ent;
250 	int s;
251 
252 	s = splhigh();
253 
254 	for (ent = list; ent; ent = ent->next) {
255 		f = ent->font;
256 		cb(f->name, f->fontwidth, f->fontheight, f->stride);
257 	}
258 
259 	splx(s);
260 }
261 
262 /*
263  * Initialize list with WSFONT_BUILTIN fonts
264  */
265 void
266 wsfont_init(void)
267 {
268 	static int again;
269 	int i;
270 
271 	if (again != 0)
272 		return;
273 	again = 1;
274 
275 	for (i = 0; builtin_fonts[i].font != NULL; i++) {
276 		builtin_fonts[i].next = list;
277 		list = &builtin_fonts[i];
278 	}
279 }
280 
281 /*
282  * Find a font by cookie. Called at splhigh.
283  */
284 static struct font *
285 wsfont_find0(cookie)
286 	int cookie;
287 {
288 	struct font *ent;
289 
290 	for (ent = list; ent != NULL; ent = ent->next)
291 		if (ent->cookie == cookie)
292 			return (ent);
293 
294 	return (NULL);
295 }
296 
297 int
298 wsfont_matches(font, name, width, height, stride)
299 	struct wsdisplay_font *font;
300 	char *name;
301 	int width, height, stride;
302 {
303 
304 	if (height != 0 && font->fontheight != height)
305 		return (0);
306 
307 	if (width != 0 && font->fontwidth != width)
308 		return (0);
309 
310 	if (stride != 0 && font->stride != stride)
311 		return (0);
312 
313 	if (name != NULL && strcmp(font->name, name) != 0)
314 		return (0);
315 
316 	return (1);
317 }
318 
319 /*
320  * Find a font.
321  */
322 int
323 wsfont_find(name, width, height, stride)
324 	char *name;
325 	int width, height, stride;
326 {
327 	struct font *ent;
328 	int s;
329 
330 	s = splhigh();
331 
332 	for (ent = list; ent != NULL; ent = ent->next) {
333 		if (wsfont_matches(ent->font, name, width, height, stride)) {
334 			splx(s);
335 			return (ent->cookie);
336 		}
337 	}
338 
339 	splx(s);
340 	return (-1);
341 }
342 
343 /*
344  * Add a font to the list.
345  */
346 int
347 wsfont_add(font, copy)
348 	struct wsdisplay_font *font;
349 	int copy;
350 {
351 	static int cookiegen = 666;
352 	struct font *ent;
353 	size_t size;
354 	int s;
355 
356 	s = splhigh();
357 
358 	/* Don't allow exact duplicates */
359 	if (wsfont_find(font->name, font->fontwidth, font->fontheight,
360 	    font->stride) >= 0) {
361 		splx(s);
362 		return (EEXIST);
363 	}
364 
365 	MALLOC(ent, struct font *, sizeof *ent, M_DEVBUF, M_WAITOK);
366 
367 	ent->lockcount = 0;
368 	ent->flg = 0;
369 	ent->cookie = cookiegen++;
370 	ent->next = list;
371 	ent->prev = NULL;
372 
373 	/* Is this font statically allocated? */
374 	if (!copy) {
375 		ent->font = font;
376 		ent->flg = WSFONT_STATIC;
377 	} else {
378 		MALLOC(ent->font, struct wsdisplay_font *, sizeof *ent->font,
379 		    M_DEVBUF, M_WAITOK);
380 		memcpy(ent->font, font, sizeof(*ent->font));
381 
382 		size = font->fontheight * font->numchars * font->stride;
383 		MALLOC(ent->font->data, void *, size, M_DEVBUF, M_WAITOK);
384 		memcpy(ent->font->data, font->data, size);
385 		MALLOC(ent->font->name, char *, strlen(font->name) + 1,
386 		       M_DEVBUF, M_WAITOK);
387 		strcpy(ent->font->name, font->name);
388 		ent->flg = 0;
389 	}
390 
391 	/* Now link into the list and return */
392 	list = ent;
393 	splx(s);
394 	return (0);
395 }
396 
397 /*
398  * Remove a font.
399  */
400 int
401 wsfont_remove(cookie)
402 	int cookie;
403 {
404 	struct font *ent;
405 	int s;
406 
407 	s = splhigh();
408 
409 	if ((ent = wsfont_find0(cookie)) == NULL) {
410 		splx(s);
411 		return (ENOENT);
412 	}
413 
414 	if ((ent->flg & WSFONT_BUILTIN) != 0 || ent->lockcount != 0) {
415 		splx(s);
416 		return (EBUSY);
417 	}
418 
419 	/* Don't free statically allocated font data */
420 	if ((ent->flg & WSFONT_STATIC) != 0) {
421 		FREE(ent->font->data, M_DEVBUF);
422 		FREE(ent->font->name, M_DEVBUF);
423 		FREE(ent->font, M_DEVBUF);
424 	}
425 
426 	/* Remove from list, free entry */
427 	if (ent->prev)
428 		ent->prev->next = ent->next;
429 	else
430 		list = ent->next;
431 
432 	if (ent->next)
433 		ent->next->prev = ent->prev;
434 
435 	FREE(ent, M_DEVBUF);
436 	splx(s);
437 	return (0);
438 }
439 
440 /*
441  * Lock a given font and return new lockcount. This fails if the cookie
442  * is invalid, or if the font is already locked and the bit/byte order
443  * requested by the caller differs.
444  */
445 int
446 wsfont_lock(cookie, ptr, bitorder, byteorder)
447 	int cookie;
448 	struct wsdisplay_font **ptr;
449 	int bitorder, byteorder;
450 {
451 	struct font *ent;
452 	int s, lc;
453 
454 	s = splhigh();
455 
456 	if ((ent = wsfont_find0(cookie)) != NULL) {
457 		if (bitorder && bitorder != ent->font->bitorder) {
458 			if (ent->lockcount) {
459 				splx(s);
460 				return (-1);
461 			}
462 			wsfont_revbit(ent->font);
463 			ent->font->bitorder = bitorder;
464 		}
465 
466 		if (byteorder && byteorder != ent->font->byteorder) {
467 			if (ent->lockcount) {
468 				splx(s);
469 				return (-1);
470 			}
471 			wsfont_revbyte(ent->font);
472 			ent->font->byteorder = byteorder;
473 		}
474 
475 		lc = ++ent->lockcount;
476 		*ptr = ent->font;
477 	} else
478 		lc = -1;
479 
480 	splx(s);
481 	return (lc);
482 }
483 
484 /*
485  * Get font flags and lockcount.
486  */
487 int
488 wsfont_getflg(cookie, flg, lc)
489 	int cookie, *flg, *lc;
490 {
491 	struct font *ent;
492 	int s;
493 
494 	s = splhigh();
495 
496 	if ((ent = wsfont_find0(cookie)) != NULL) {
497 		*flg = ent->flg;
498 		*lc = ent->lockcount;
499 	}
500 
501 	splx(s);
502 	return (ent != NULL ? 0 : -1);
503 }
504 
505 /*
506  * Unlock a given font and return new lockcount.
507  */
508 int
509 wsfont_unlock(cookie)
510 	int cookie;
511 {
512 	struct font *ent;
513 	int s, lc;
514 
515 	s = splhigh();
516 
517 	if ((ent = wsfont_find0(cookie)) != NULL) {
518 		if (ent->lockcount == 0)
519 			panic("wsfont_unlock: font not locked\n");
520 		lc = --ent->lockcount;
521 	} else
522 		lc = -1;
523 
524 	splx(s);
525 	return (lc);
526 }
527 
528 
529 /*
530  * Unicode to font encoding mappings
531  */
532 
533 /*
534  * To save memory, font encoding tables use a two level lookup.
535  * First the high byte of the Unicode is used to lookup the level 2
536  * table, then the low byte indexes that table.  Level 2 tables that are
537  * not needed are omitted (NULL), and both level 1 and level 2 tables
538  * have base and size attributes to keep their size down.
539  */
540 
541 struct wsfont_level1_glyphmap {
542 	struct wsfont_level2_glyphmap **level2;
543 	int base;	/* High byte for first level2 entry	*/
544 	int size;	/* Number of level2 entries		*/
545 };
546 
547 struct wsfont_level2_glyphmap {
548 	int base;	/* Low byte for first character		*/
549 	int size;	/* Number of characters			*/
550 	void *chars;	/* Pointer to character number entries  */
551 	int width;	/* Size of each entry in bytes (1,2,4)  */
552 };
553 
554 #define null16			\
555 	NULL, NULL, NULL, NULL,	\
556 	NULL, NULL, NULL, NULL,	\
557 	NULL, NULL, NULL, NULL,	\
558 	NULL, NULL, NULL, NULL
559 
560 /*
561  * IBM 437 maps
562  */
563 
564 static u_int8_t
565 ibm437_chars_0[] = {
566 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
567 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
568 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
569 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
570 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
571 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
572 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
573 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
574 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
575 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
576 	255,173,155,156, 0, 157, 0,  0,  0,  0, 166,174,170, 0,  0,  0,
577 	 0, 241,253, 0,  0,  0,  0, 249, 0,  0, 167,175,172,171, 0, 168,
578 	 0,  0,  0,  0, 142,143,146,128, 0, 144, 0,  0,  0,  0,  0,  0,
579 	 0, 165, 0,  0,  0,  0, 153, 0,  0,  0,  0,  0, 154, 0,  0,  0,
580 	133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
581 	 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0,  0, 152
582 },
583 ibm437_chars_1[] = {
584 	159
585 },
586 ibm437_chars_3[] = {
587 	226, 0,  0,  0,  0, 233, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
588 	228, 0,  0, 232, 0,  0, 234, 0,  0,  0,  0,  0,  0,  0, 224,225,
589 	 0, 235,238, 0,  0,  0,  0,  0,  0, 230, 0,  0,  0, 227, 0,  0,
590 	229,231
591 },
592 ibm437_chars_32[] = {
593 	252, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
594 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
595 	 0,  0,  0,  0,  0,  0,  0,  0, 158
596 },
597 ibm437_chars_34[] = {
598 	237, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
599 	 0,  0,  0, 248,250,251, 0,  0,  0, 236, 0,  0,  0,  0,  0,  0,
600 	 0,  0,  0,  0, 239, 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, 247, 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,240,  0,  0,243,
604 	242
605 },
606 ibm437_chars_35[] = {
607 	169, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
608 	244,245
609 },
610 ibm437_chars_37[] = {
611 	196,205,179,186, 0,  0,  0,  0,  0,  0,  0,  0, 218,213,214,201,
612 	191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0,  0,
613 	199, 0,  0, 204,180,181, 0,  0, 182, 0,  0, 185,194, 0,  0, 209,
614 	210, 0,  0, 203,193, 0,  0, 207,208, 0,  0, 202,197, 0,  0, 216,
615 	 0,  0, 215, 0,  0,  0,  0,  0,  0,  0,  0, 206, 0,  0,  0,  0,
616 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
617 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
618 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
619 	223, 0,  0,  0, 220, 0,  0,  0, 219, 0,  0,  0, 221, 0,  0,  0,
620 	222,176,177,178, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
621 	254
622 };
623 
624 static struct wsfont_level2_glyphmap
625 ibm437_level2_0 = { 0, 256, ibm437_chars_0, 1 },
626 ibm437_level2_1 = { 146, 1, ibm437_chars_1, 1 },
627 ibm437_level2_3 = { 147, 50, ibm437_chars_3, 1 },
628 ibm437_level2_32 = { 127, 41, ibm437_chars_32, 1 },
629 ibm437_level2_34 = { 5, 97, ibm437_chars_34, 1 },
630 ibm437_level2_35 = { 16, 18, ibm437_chars_35, 1 },
631 ibm437_level2_37 = { 0, 161, ibm437_chars_37, 1 };
632 
633 static struct wsfont_level2_glyphmap *ibm437_level1[] = {
634 	&ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
635 	NULL, NULL, NULL, NULL,
636 	NULL, NULL, NULL, NULL,
637 	NULL, NULL, NULL, NULL,
638 	NULL, NULL, NULL, NULL,
639 	NULL, NULL, NULL, NULL,
640 	NULL, NULL, NULL, NULL,
641 	NULL, NULL, NULL, NULL,
642 	&ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
643 	NULL, &ibm437_level2_37
644 };
645 
646 
647 /*
648  * ISO-8859-7 maps
649  */
650 
651 static u_int8_t
652 iso7_chars_0[] = {
653 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
654 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
655 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
656 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
657 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
658 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
659 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
660 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
661 	128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
662 	144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
663 	160, 0,  0, 163, 0,  0, 166,167,168,169, 0, 171,172,173, 0,  0,
664 	176,177,178,179,180, 0,  0, 183, 0,  0,  0, 187, 0, 189
665 },
666 iso7_chars_3[] = {
667 	182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197,
668 	198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213,
669 	214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
670 	230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
671 	246,247,248,249,250,251,252,253,254, 0,  0,  0,  0,  0,  0,  0,
672 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
673 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 181
674 },
675 iso7_chars_32[] = {
676 	175, 0,  0,  0,  0, 162, 0, 161
677 };
678 
679 static struct wsfont_level2_glyphmap
680 iso7_level2_0 = { 0, 190, iso7_chars_0, 1 },
681 iso7_level2_3 = { 134, 111, iso7_chars_3, 1 },
682 iso7_level2_32 = { 20, 8, iso7_chars_32, 1 };
683 
684 static struct wsfont_level2_glyphmap *iso7_level1[] = {
685 	&iso7_level2_0, NULL, NULL, &iso7_level2_3,
686 	NULL, NULL, NULL, NULL,
687 	NULL, NULL, NULL, NULL,
688 	NULL, NULL, NULL, NULL,
689 	NULL, NULL, NULL, NULL,
690 	NULL, NULL, NULL, NULL,
691 	NULL, NULL, NULL, NULL,
692 	NULL, NULL, NULL, NULL,
693 	&iso7_level2_32
694 };
695 
696 static struct wsfont_level1_glyphmap encodings[] = {
697 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_ISO */
698 	{ ibm437_level1, 0, 38 },	/* WSDISPLAY_FONTENC_IBM */
699 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_PCVT */
700 	{ iso7_level1, 0, 33 },		/* WSDISPLAY_FONTENC_ISO7 */
701 };
702 
703 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0]))
704 
705 /*
706  * Remap Unicode character to glyph
707  */
708 int
709 wsfont_map_unichar(font, c)
710 	struct wsdisplay_font *font;
711 	int c;
712 {
713 	if (font->encoding == WSDISPLAY_FONTENC_ISO) {
714 
715 		return c;
716 
717 	} else if (font->encoding < 0 || font->encoding > MAX_ENCODING) {
718 
719 		return (-1);
720 
721 	} else {
722 
723 		int hi = (c >> 8), lo = c & 255;
724 		struct wsfont_level1_glyphmap *map1 =
725 			&encodings[font->encoding];
726 
727 		if (hi >= map1->base && hi < map1->base + map1->size) {
728 			struct wsfont_level2_glyphmap *map2 =
729 			  map1->level2[hi - map1->base];
730 
731 			if (map2 != NULL &&
732 			    lo >= map2->base && lo < map2->base + map2->size) {
733 
734 			  	lo -= map2->base;
735 
736 				switch(map2->width) {
737 				 case 1:
738 				   c = (((u_int8_t *)map2->chars)[lo]);
739 				   break;
740 				 case 2:
741 				   c = (((u_int16_t *)map2->chars)[lo]);
742 				   break;
743 				 case 4:
744 				   c = (((u_int32_t *)map2->chars)[lo]);
745 				   break;
746 				}
747 
748 				if (c == 0 && lo != 0)
749 					return (-1);
750 				else
751 					return (c);
752 
753 			} else {
754 				return (-1);
755 			}
756 
757 		} else {
758 			return (-1);
759 		}
760 
761 	}
762 
763 }
764