xref: /openbsd-src/sys/dev/wsfont/wsfont.c (revision 850e275390052b330d93020bf619a739a3c277ac)
1 /*	$OpenBSD: wsfont.c,v 1.23 2008/06/26 05:42:19 ray 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 	if (newfont == NULL)
301 		return (NULL);
302 
303 	bcopy(font, newfont, sizeof *font);
304 	newfont->cookie = NULL;
305 
306 	/* Allocate a buffer big enough for the rotated font. */
307 	newstride = (font->fontheight + 7) / 8;
308 	newbits = malloc(newstride * font->fontwidth * font->numchars,
309 	    M_DEVBUF, M_WAITOK | M_ZERO);
310 	if (newbits == NULL) {
311 		free(newfont, M_DEVBUF);
312 		return (NULL);
313 	}
314 
315 	/* Rotate the font a bit at a time. */
316 	for (n = 0; n < font->numchars; n++) {
317 		char *ch = font->data + (n * font->stride * font->fontheight);
318 
319 		for (r = 0; r < font->fontheight; r++) {
320 			for (b = 0; b < font->fontwidth; b++) {
321 				unsigned char *rb;
322 
323 				rb = ch + (font->stride * r) + (b / 8);
324 				if (*rb & (0x80 >> (b % 8))) {
325 					unsigned char *rrb;
326 
327 					rrb = newbits + newstride - 1 - (r / 8)
328 					    + (n * newstride * font->fontwidth)
329 					    + (newstride * b);
330 					*rrb |= (1 << (r % 8));
331 				}
332 			}
333 		}
334 	}
335 
336 	newfont->data = newbits;
337 
338 	/* Update font sizes. */
339 	newfont->stride = newstride;
340 	newfont->fontwidth = font->fontheight;
341 	newfont->fontheight = font->fontwidth;
342 
343 	if (wsfont_add(newfont, 0) != 0) {
344 		/*
345 		 * If we seem to have rotated this font already, drop the
346 		 * new one...
347 		 */
348 		free(newbits, M_DEVBUF);
349 		free(newfont, M_DEVBUF);
350 		newfont = NULL;
351 	}
352 
353 	return (newfont);
354 }
355 
356 int
357 wsfont_rotate(int cookie)
358 {
359 	int s, ncookie;
360 	struct wsdisplay_font *font;
361 	struct font *origfont;
362 
363 	s = splhigh();
364 	origfont = wsfont_find0(cookie);
365 	splx(s);
366 
367 	font = wsfont_rotate_internal(origfont->font);
368 	if (font == NULL)
369 		return (-1);
370 
371 	ncookie = wsfont_find(font->name, font->fontwidth, font->fontheight,
372 	    font->stride);
373 
374 	return (ncookie);
375 }
376 
377 #endif	/* NRASOPS_ROTATION */
378 
379 /*
380  * Initialize list with WSFONT_BUILTIN fonts
381  */
382 void
383 wsfont_init(void)
384 {
385 	static int again;
386 	int i;
387 
388 	if (again != 0)
389 		return;
390 	again = 1;
391 
392 	for (i = 0; builtin_fonts[i].font != NULL; i++) {
393 		builtin_fonts[i].next = list;
394 		list = &builtin_fonts[i];
395 	}
396 }
397 
398 /*
399  * Find a font by cookie. Called at splhigh.
400  */
401 static struct font *
402 wsfont_find0(cookie)
403 	int cookie;
404 {
405 	struct font *ent;
406 
407 	for (ent = list; ent != NULL; ent = ent->next)
408 		if (ent->cookie == cookie)
409 			return (ent);
410 
411 	return (NULL);
412 }
413 
414 /*
415  * Find a font.
416  */
417 int
418 wsfont_find(name, width, height, stride)
419 	char *name;
420 	int width, height, stride;
421 {
422 	struct font *ent;
423 	int s;
424 
425 	s = splhigh();
426 
427 	for (ent = list; ent != NULL; ent = ent->next) {
428 		if (height != 0 && ent->font->fontheight != height)
429 			continue;
430 
431 		if (width != 0 && ent->font->fontwidth != width)
432 			continue;
433 
434 		if (stride != 0 && ent->font->stride != stride)
435 			continue;
436 
437 		if (name != NULL && strcmp(ent->font->name, name) != 0)
438 			continue;
439 
440 		splx(s);
441 		return (ent->cookie);
442 	}
443 
444 	splx(s);
445 	return (-1);
446 }
447 
448 /*
449  * Add a font to the list.
450  */
451 int
452 wsfont_add(font, copy)
453 	struct wsdisplay_font *font;
454 	int copy;
455 {
456 	static int cookiegen = 666;
457 	struct font *ent;
458 	size_t size;
459 	int s;
460 
461 	s = splhigh();
462 
463 	/* Don't allow exact duplicates */
464 	if (wsfont_find(font->name, font->fontwidth, font->fontheight,
465 	    font->stride) >= 0) {
466 		splx(s);
467 		return (-1);
468 	}
469 
470 	ent = (struct font *)malloc(sizeof *ent, M_DEVBUF, M_WAITOK);
471 
472 	ent->lockcount = 0;
473 	ent->flg = 0;
474 	ent->cookie = cookiegen++;
475 	ent->next = list;
476 	ent->prev = NULL;
477 
478 	/* Is this font statically allocated? */
479 	if (!copy) {
480 		ent->font = font;
481 		ent->flg = WSFONT_STATIC;
482 	} else {
483 		ent->font = (struct wsdisplay_font *)malloc(sizeof *ent->font,
484 		    M_DEVBUF, M_WAITOK);
485 
486 		memcpy(ent->font, font, sizeof(*ent->font));
487 
488 		size = font->fontheight * font->numchars * font->stride;
489 		ent->font->data = (void *)malloc(size, M_DEVBUF, M_WAITOK);
490 		memcpy(ent->font->data, font->data, size);
491 		ent->flg = 0;
492 	}
493 
494 	/* Now link into the list and return */
495 	list = ent;
496 	splx(s);
497 	return (0);
498 }
499 
500 /*
501  * Remove a font.
502  */
503 #ifdef notyet
504 int
505 wsfont_remove(cookie)
506 	int cookie;
507 {
508 	struct font *ent;
509 	int s;
510 
511 	s = splhigh();
512 
513 	if ((ent = wsfont_find0(cookie)) == NULL) {
514 		splx(s);
515 		return (-1);
516 	}
517 
518 	if ((ent->flg & WSFONT_BUILTIN) != 0 || ent->lockcount != 0) {
519 		splx(s);
520 		return (-1);
521 	}
522 
523 	/* Don't free statically allocated font data */
524 	if ((ent->flg & WSFONT_STATIC) != 0) {
525 		free(ent->font->data, M_DEVBUF);
526 		free(ent->font, M_DEVBUF);
527 	}
528 
529 	/* Remove from list, free entry */
530 	if (ent->prev)
531 		ent->prev->next = ent->next;
532 	else
533 		list = ent->next;
534 
535 	if (ent->next)
536 		ent->next->prev = ent->prev;
537 
538 	free(ent, M_DEVBUF);
539 	splx(s);
540 	return (0);
541 }
542 #endif
543 
544 /*
545  * Lock a given font and return new lockcount. This fails if the cookie
546  * is invalid, or if the font is already locked and the bit/byte order
547  * requested by the caller differs.
548  */
549 int
550 wsfont_lock(cookie, ptr, bitorder, byteorder)
551 	int cookie;
552 	struct wsdisplay_font **ptr;
553 	int bitorder, byteorder;
554 {
555 	struct font *ent;
556 	int s, lc;
557 
558 	s = splhigh();
559 
560 	if ((ent = wsfont_find0(cookie)) != NULL) {
561 		if (bitorder && bitorder != ent->font->bitorder) {
562 #if !defined(SMALL_KERNEL) || defined(__alpha__)
563 			if (ent->lockcount) {
564 				splx(s);
565 				return (-1);
566 			}
567 			wsfont_revbit(ent->font);
568 			ent->font->bitorder = bitorder;
569 #else
570 			splx(s);
571 			return (-1);
572 #endif
573 		}
574 
575 		if (byteorder && byteorder != ent->font->byteorder) {
576 #if !defined(SMALL_KERNEL)
577 			if (ent->lockcount) {
578 				splx(s);
579 				return (-1);
580 			}
581 			wsfont_revbyte(ent->font);
582 			ent->font->byteorder = byteorder;
583 #else
584 			splx(s);
585 			return (-1);
586 #endif
587 		}
588 
589 		lc = ++ent->lockcount;
590 		*ptr = ent->font;
591 	} else
592 		lc = -1;
593 
594 	splx(s);
595 	return (lc);
596 }
597 
598 /*
599  * Get font flags and lockcount.
600  */
601 int
602 wsfont_getflg(cookie, flg, lc)
603 	int cookie, *flg, *lc;
604 {
605 	struct font *ent;
606 	int s;
607 
608 	s = splhigh();
609 
610 	if ((ent = wsfont_find0(cookie)) != NULL) {
611 		*flg = ent->flg;
612 		*lc = ent->lockcount;
613 	}
614 
615 	splx(s);
616 	return (ent != NULL ? 0 : -1);
617 }
618 
619 /*
620  * Unlock a given font and return new lockcount.
621  */
622 int
623 wsfont_unlock(cookie)
624 	int cookie;
625 {
626 	struct font *ent;
627 	int s, lc;
628 
629 	s = splhigh();
630 
631 	if ((ent = wsfont_find0(cookie)) != NULL) {
632 		if (ent->lockcount == 0)
633 			panic("wsfont_unlock: font not locked");
634 		lc = --ent->lockcount;
635 	} else
636 		lc = -1;
637 
638 	splx(s);
639 	return (lc);
640 }
641 
642 #if !defined(SMALL_KERNEL)
643 
644 /*
645  * Unicode to font encoding mappings
646  */
647 
648 /*
649  * To save memory, font encoding tables use a two level lookup.
650  * First the high byte of the Unicode is used to lookup the level 2
651  * table, then the low byte indexes that table.  Level 2 tables that are
652  * not needed are omitted (NULL), and both level 1 and level 2 tables
653  * have base and size attributes to keep their size down.
654  */
655 
656 struct wsfont_level1_glyphmap {
657 	struct wsfont_level2_glyphmap **level2;
658 	int base;	/* High byte for first level2 entry	*/
659 	int size;	/* Number of level2 entries		*/
660 };
661 
662 struct wsfont_level2_glyphmap {
663 	int base;	/* Low byte for first character		*/
664 	int size;	/* Number of characters			*/
665 	void *chars;	/* Pointer to character number entries  */
666 	int width;	/* Size of each entry in bytes (1,2,4)  */
667 };
668 
669 #define null16			\
670 	NULL, NULL, NULL, NULL,	\
671 	NULL, NULL, NULL, NULL,	\
672 	NULL, NULL, NULL, NULL,	\
673 	NULL, NULL, NULL, NULL
674 
675 /*
676  * IBM 437 maps
677  */
678 
679 static u_int8_t
680 ibm437_chars_0[] = {
681 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
682 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
683 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
684 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
685 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
686 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
687 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
688 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
689 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
690 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
691 	255,173,155,156, 0, 157, 0,  0,  0,  0, 166,174,170, 0,  0,  0,
692 	 0, 241,253, 0,  0,  0,  0, 249, 0,  0, 167,175,172,171, 0, 168,
693 	 0,  0,  0,  0, 142,143,146,128, 0, 144, 0,  0,  0,  0,  0,  0,
694 	 0, 165, 0,  0,  0,  0, 153, 0,  0,  0,  0,  0, 154, 0,  0,  0,
695 	133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
696 	 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0,  0, 152
697 },
698 ibm437_chars_1[] = {
699 	159
700 },
701 ibm437_chars_3[] = {
702 	226, 0,  0,  0,  0, 233, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
703 	228, 0,  0, 232, 0,  0, 234, 0,  0,  0,  0,  0,  0,  0, 224,225,
704 	 0, 235,238, 0,  0,  0,  0,  0,  0, 230, 0,  0,  0, 227, 0,  0,
705 	229,231
706 },
707 ibm437_chars_32[] = {
708 	252, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
709 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
710 	 0,  0,  0,  0,  0,  0,  0,  0, 158
711 },
712 ibm437_chars_34[] = {
713 	237, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
714 	 0,  0,  0, 248,250,251, 0,  0,  0, 236, 0,  0,  0,  0,  0,  0,
715 	 0,  0,  0,  0, 239, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
716 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
717 	 0,  0,  0, 247, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
718 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,240,  0,  0,243,
719 	242
720 },
721 ibm437_chars_35[] = {
722 	169, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
723 	244,245
724 },
725 ibm437_chars_37[] = {
726 	196,205,179,186, 0,  0,  0,  0,  0,  0,  0,  0, 218,213,214,201,
727 	191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0,  0,
728 	199, 0,  0, 204,180,181, 0,  0, 182, 0,  0, 185,194, 0,  0, 209,
729 	210, 0,  0, 203,193, 0,  0, 207,208, 0,  0, 202,197, 0,  0, 216,
730 	 0,  0, 215, 0,  0,  0,  0,  0,  0,  0,  0, 206, 0,  0,  0,  0,
731 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
732 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
733 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
734 	223, 0,  0,  0, 220, 0,  0,  0, 219, 0,  0,  0, 221, 0,  0,  0,
735 	222,176,177,178, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
736 	254
737 };
738 
739 static struct wsfont_level2_glyphmap
740 ibm437_level2_0 = { 0, 256, ibm437_chars_0, 1 },
741 ibm437_level2_1 = { 146, 1, ibm437_chars_1, 1 },
742 ibm437_level2_3 = { 147, 50, ibm437_chars_3, 1 },
743 ibm437_level2_32 = { 127, 41, ibm437_chars_32, 1 },
744 ibm437_level2_34 = { 5, 97, ibm437_chars_34, 1 },
745 ibm437_level2_35 = { 16, 18, ibm437_chars_35, 1 },
746 ibm437_level2_37 = { 0, 161, ibm437_chars_37, 1 };
747 
748 static struct wsfont_level2_glyphmap *ibm437_level1[] = {
749 	&ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
750 	NULL, NULL, NULL, NULL,
751 	NULL, NULL, NULL, NULL,
752 	NULL, NULL, NULL, NULL,
753 	NULL, NULL, NULL, NULL,
754 	NULL, NULL, NULL, NULL,
755 	NULL, NULL, NULL, NULL,
756 	NULL, NULL, NULL, NULL,
757 	&ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
758 	NULL, &ibm437_level2_37
759 };
760 
761 
762 /*
763  * ISO-8859-7 maps
764  */
765 
766 static u_int8_t
767 iso7_chars_0[] = {
768 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
769 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
770 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
771 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
772 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
773 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
774 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
775 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
776 	128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
777 	144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
778 	160, 0,  0, 163, 0,  0, 166,167,168,169, 0, 171,172,173, 0,  0,
779 	176,177,178,179,180, 0,  0, 183, 0,  0,  0, 187, 0, 189
780 },
781 iso7_chars_3[] = {
782 	182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197,
783 	198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213,
784 	214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
785 	230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
786 	246,247,248,249,250,251,252,253,254, 0,  0,  0,  0,  0,  0,  0,
787 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
788 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 181
789 },
790 iso7_chars_32[] = {
791 	175, 0,  0,  0,  0, 162, 0, 161
792 };
793 
794 static struct wsfont_level2_glyphmap
795 iso7_level2_0 = { 0, 190, iso7_chars_0, 1 },
796 iso7_level2_3 = { 134, 111, iso7_chars_3, 1 },
797 iso7_level2_32 = { 20, 8, iso7_chars_32, 1 };
798 
799 static struct wsfont_level2_glyphmap *iso7_level1[] = {
800 	&iso7_level2_0, NULL, NULL, &iso7_level2_3,
801 	NULL, NULL, NULL, NULL,
802 	NULL, NULL, NULL, NULL,
803 	NULL, NULL, NULL, NULL,
804 	NULL, NULL, NULL, NULL,
805 	NULL, NULL, NULL, NULL,
806 	NULL, NULL, NULL, NULL,
807 	NULL, NULL, NULL, NULL,
808 	&iso7_level2_32
809 };
810 
811 
812 static struct wsfont_level1_glyphmap encodings[] = {
813 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_ISO */
814 	{ ibm437_level1, 0, 38 },	/* WSDISPLAY_FONTENC_IBM */
815 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_PCVT */
816 	{ iso7_level1, 0, 33 },		/* WSDISPLAY_FONTENC_ISO7 */
817 };
818 
819 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0]))
820 
821 #endif	/* !SMALL_KERNEL */
822 
823 /*
824  * Remap Unicode character to glyph
825  */
826 int
827 wsfont_map_unichar(font, c)
828 	struct wsdisplay_font *font;
829 	int c;
830 {
831 	if (font->encoding == WSDISPLAY_FONTENC_ISO)
832 		return c;
833 	else
834 #if !defined(SMALL_KERNEL)
835 	if (font->encoding < 0 || font->encoding > MAX_ENCODING)
836 		return (-1);
837 	else {
838 		int hi = (c >> 8), lo = c & 255;
839 		struct wsfont_level1_glyphmap *map1 =
840 			&encodings[font->encoding];
841 
842 		if (hi >= map1->base && hi < map1->base + map1->size) {
843 			struct wsfont_level2_glyphmap *map2 =
844 			  map1->level2[hi - map1->base];
845 
846 			if (map2 != NULL &&
847 			    lo >= map2->base && lo < map2->base + map2->size) {
848 
849 			  	lo -= map2->base;
850 
851 				switch(map2->width) {
852 				case 1:
853 					c = (((u_int8_t *)map2->chars)[lo]);
854 					break;
855 				case 2:
856 					c = (((u_int16_t *)map2->chars)[lo]);
857 					break;
858 				case 4:
859 					c = (((u_int32_t *)map2->chars)[lo]);
860 					break;
861 				}
862 
863 				if (c == 0 && lo != 0)
864 					return (-1);
865 				else
866 					return (c);
867 
868 			} else {
869 				return (-1);
870 			}
871 
872 		} else {
873 			return (-1);
874 		}
875 
876 	}
877 #else
878 	return (-1);
879 #endif	/* SMALL_KERNEL */
880 }
881