wsfont.c revision 1.25
1/*	$OpenBSD: wsfont.c,v 1.25 2010/05/23 15:04:19 deraadt 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 */
120struct 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 */
130static 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 */
170static 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
207static struct font *wsfont_find0(int);
208
209#if !defined(SMALL_KERNEL) || defined(__alpha__)
210
211/*
212 * Reverse the bit order of a font
213 */
214static void	wsfont_revbit(struct wsdisplay_font *);
215static void
216wsfont_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 */
235static void	wsfont_revbyte(struct wsdisplay_font *);
236static void
237wsfont_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 */
269void
270wsfont_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
289struct wsdisplay_font *wsfont_rotate_internal(struct wsdisplay_font *);
290
291struct wsdisplay_font *
292wsfont_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
350int
351wsfont_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 */
376void
377wsfont_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 */
395static struct font *
396wsfont_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 */
411int
412wsfont_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 */
445int
446wsfont_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
498int
499wsfont_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 */
543int
544wsfont_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 */
595int
596wsfont_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 */
616int
617wsfont_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
650struct 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
656struct 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
673static u_int8_t
674ibm437_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},
692ibm437_chars_1[] = {
693	159
694},
695ibm437_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},
701ibm437_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},
706ibm437_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},
715ibm437_chars_35[] = {
716	169, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
717	244,245
718},
719ibm437_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
733static struct wsfont_level2_glyphmap
734ibm437_level2_0 = { 0, 256, ibm437_chars_0, 1 },
735ibm437_level2_1 = { 146, 1, ibm437_chars_1, 1 },
736ibm437_level2_3 = { 147, 50, ibm437_chars_3, 1 },
737ibm437_level2_32 = { 127, 41, ibm437_chars_32, 1 },
738ibm437_level2_34 = { 5, 97, ibm437_chars_34, 1 },
739ibm437_level2_35 = { 16, 18, ibm437_chars_35, 1 },
740ibm437_level2_37 = { 0, 161, ibm437_chars_37, 1 };
741
742static 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
760static u_int8_t
761iso7_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},
775iso7_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},
784iso7_chars_32[] = {
785	175, 0,  0,  0,  0, 162, 0, 161
786};
787
788static struct wsfont_level2_glyphmap
789iso7_level2_0 = { 0, 190, iso7_chars_0, 1 },
790iso7_level2_3 = { 134, 111, iso7_chars_3, 1 },
791iso7_level2_32 = { 20, 8, iso7_chars_32, 1 };
792
793static 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
806static 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 */
820int
821wsfont_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