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