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