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