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