Home | History | Annotate | Line # | Download | only in wsfont
wsfont.c revision 1.50.12.2
      1 /* 	$NetBSD: wsfont.c,v 1.50.12.2 2012/04/05 21:33:34 mrg 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  *
     19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  * POSSIBILITY OF SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 __KERNEL_RCSID(0, "$NetBSD: wsfont.c,v 1.50.12.2 2012/04/05 21:33:34 mrg Exp $");
     34 
     35 #include "opt_wsfont.h"
     36 
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/time.h>
     40 #include <sys/malloc.h>
     41 #include <sys/queue.h>
     42 
     43 #include <dev/wscons/wsdisplayvar.h>
     44 #include <dev/wscons/wsconsio.h>
     45 #include <dev/wsfont/wsfont.h>
     46 
     47 #include "wsfont_glue.h"	/* NRASOPS_ROTATION */
     48 
     49 #undef HAVE_FONT
     50 
     51 #ifdef FONT_QVSS8x15
     52 #define HAVE_FONT 1
     53 #include <dev/wsfont/qvss8x15.h>
     54 #endif
     55 
     56 #ifdef FONT_GALLANT12x22
     57 #define HAVE_FONT 1
     58 #include <dev/wsfont/gallant12x22.h>
     59 #endif
     60 
     61 #ifdef FONT_LUCIDA16x29
     62 #define HAVE_FONT 1
     63 #include <dev/wsfont/lucida16x29.h>
     64 #endif
     65 
     66 #ifdef FONT_VT220L8x8
     67 #define HAVE_FONT 1
     68 #include <dev/wsfont/vt220l8x8.h>
     69 #endif
     70 
     71 #ifdef FONT_VT220L8x10
     72 #define HAVE_FONT 1
     73 #include <dev/wsfont/vt220l8x10.h>
     74 #endif
     75 
     76 #ifdef FONT_VT220L8x16
     77 #define HAVE_FONT 1
     78 #include <dev/wsfont/vt220l8x16.h>
     79 #endif
     80 
     81 #ifdef FONT_VT220ISO8x8
     82 #define HAVE_FONT 1
     83 #include <dev/wsfont/vt220iso8x8.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 #ifdef FONT_DEJAVU_SANS_MONO12x22
    119 #include <dev/wsfont/DejaVu_Sans_Mono_12x22.h>
    120 #endif
    121 
    122 #ifdef FONT_DROID_SANS_MONO12x22
    123 #include <dev/wsfont/Droid_Sans_Mono_12x22.h>
    124 #endif
    125 
    126 #ifdef FONT_DROID_SANS_MONO9x18
    127 #include <dev/wsfont/Droid_Sans_Mono_9x18.h>
    128 #endif
    129 
    130 /* Make sure we always have at least one bitmap font. */
    131 #ifndef HAVE_FONT
    132 #define HAVE_FONT 1
    133 #define FONT_BOLD8x16 1
    134 #endif
    135 
    136 #ifdef FONT_BOLD8x16
    137 #include <dev/wsfont/bold8x16.h>
    138 #endif
    139 
    140 #define	WSFONT_IDENT_MASK	0xffffff00
    141 #define	WSFONT_IDENT_SHIFT	8
    142 #define	WSFONT_BITO_MASK	0x000000f0
    143 #define	WSFONT_BITO_SHIFT	4
    144 #define	WSFONT_BYTEO_MASK	0x0000000f
    145 #define	WSFONT_BYTEO_SHIFT	0
    146 
    147 #define WSFONT_BUILTIN	0x01	/* In wsfont.c */
    148 #define WSFONT_STATIC	0x02	/* Font structures not malloc()ed */
    149 #define WSFONT_COPY	0x04	/* Copy of existing font in table */
    150 
    151 /* Placeholder struct used for linked list */
    152 struct font {
    153 	TAILQ_ENTRY(font) chain;
    154 	struct	wsdisplay_font *font;
    155 	u_int	lockcount;
    156 	u_int	cookie;
    157 	u_int	flags;
    158 };
    159 
    160 /* Our list of built-in fonts */
    161 static struct font builtin_fonts[] = {
    162 #ifdef FONT_BOLD8x16
    163 	{ { NULL, NULL }, &bold8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN  },
    164 #endif
    165 #ifdef FONT_ISO8x16
    166 	{ { NULL, NULL }, &iso8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    167 #endif
    168 #ifdef FONT_COURIER11x18
    169 	{ { NULL, NULL }, &courier11x18, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    170 #endif
    171 #ifdef FONT_GALLANT12x22
    172 	{ { NULL, NULL }, &gallant12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    173 #endif
    174 #ifdef FONT_LUCIDA16x29
    175 	{ { NULL, NULL }, &lucida16x29, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    176 #endif
    177 #ifdef FONT_QVSS8x15
    178 	{ { NULL, NULL }, &qvss8x15, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    179 #endif
    180 #ifdef FONT_VT220L8x8
    181 	{ { NULL, NULL }, &vt220l8x8, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    182 #endif
    183 #ifdef FONT_VT220L8x10
    184 	{ { NULL, NULL }, &vt220l8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    185 #endif
    186 #ifdef FONT_VT220L8x16
    187 	{ { NULL, NULL }, &vt220l8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    188 #endif
    189 #ifdef FONT_VT220ISO8x8
    190 	{ { NULL, NULL }, &vt220iso8x8, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    191 #endif
    192 #ifdef FONT_VT220ISO8x16
    193 	{ { NULL, NULL }, &vt220iso8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    194 #endif
    195 #ifdef FONT_VT220KOI8x10_KOI8_R
    196 	{ { NULL, NULL }, &vt220kr8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    197 #endif
    198 #ifdef FONT_VT220KOI8x10_KOI8_U
    199 	{ { NULL, NULL }, &vt220ku8x10, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    200 #endif
    201 #ifdef FONT_SONY8x16
    202 	{ { NULL, NULL }, &sony8x16, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    203 #endif
    204 #ifdef FONT_SONY12x24
    205 	{ { NULL, NULL }, &sony12x24, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    206 #endif
    207 #ifdef FONT_OMRON12x20
    208 	{ { NULL, NULL }, &omron12x20, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    209 #endif
    210 #ifdef FONT_DEJAVU_SANS_MONO12x22
    211 	{ { NULL, NULL }, &DejaVu_Sans_Mono_12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    212 #endif
    213 #ifdef FONT_DROID_SANS_MONO12x22
    214 	{ { NULL, NULL }, &Droid_Sans_Mono_12x22, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    215 #endif
    216 #ifdef FONT_DROID_SANS_MONO9x18
    217 	{ { NULL, NULL }, &Droid_Sans_Mono_9x18, 0, 0, WSFONT_STATIC | WSFONT_BUILTIN },
    218 #endif
    219 	{ { NULL, NULL }, NULL, 0, 0, 0 },
    220 };
    221 
    222 static TAILQ_HEAD(,font)	list;
    223 static int	ident;
    224 
    225 /* Reverse the bit order in a byte */
    226 static const u_char reverse[256] = {
    227 	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
    228 	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
    229 	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
    230 	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
    231 	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
    232 	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
    233 	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
    234 	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
    235 	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
    236 	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
    237 	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
    238 	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
    239 	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
    240 	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
    241 	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
    242 	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
    243 	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
    244 	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
    245 	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
    246 	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
    247 	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
    248 	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
    249 	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
    250 	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
    251 	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
    252 	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
    253 	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
    254 	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
    255 	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
    256 	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
    257 	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
    258 	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
    259 };
    260 
    261 static struct	font *wsfont_find0(int, int);
    262 static struct	font *wsfont_add0(struct wsdisplay_font *, int);
    263 static void	wsfont_revbit(struct wsdisplay_font *);
    264 static void	wsfont_revbyte(struct wsdisplay_font *);
    265 
    266 int
    267 wsfont_make_cookie(int cident, int bito, int byteo)
    268 {
    269 
    270 	return ((cident & WSFONT_IDENT_MASK) |
    271 	    (bito << WSFONT_BITO_SHIFT) |
    272 	    (byteo << WSFONT_BYTEO_SHIFT));
    273 }
    274 
    275 static void
    276 wsfont_revbit(struct wsdisplay_font *font)
    277 {
    278 	u_char *p, *m;
    279 
    280 	p = (u_char *)font->data;
    281 	m = p + font->stride * font->numchars * font->fontheight;
    282 
    283 	for (; p < m; p++)
    284 		*p = reverse[*p];
    285 }
    286 
    287 static void
    288 wsfont_revbyte(struct wsdisplay_font *font)
    289 {
    290 	int x, l, r, nr;
    291 	u_char *rp;
    292 
    293 	if (font->stride == 1)
    294 		return;
    295 
    296 	rp = (u_char *)font->data;
    297 	nr = font->numchars * font->fontheight;
    298 
    299 	while (nr--) {
    300 		l = 0;
    301 		r = font->stride - 1;
    302 
    303 		while (l < r) {
    304 			x = rp[l];
    305 			rp[l] = rp[r];
    306 			rp[r] = x;
    307 			l++, r--;
    308 		}
    309 
    310 		rp += font->stride;
    311 	}
    312 }
    313 
    314 void
    315 wsfont_enum(void (*cb)(const char *, int, int, int))
    316 {
    317 	struct wsdisplay_font *f;
    318 	struct font *ent;
    319 
    320 	TAILQ_FOREACH(ent, &list, chain) {
    321 		f = ent->font;
    322 		cb(f->name, f->fontwidth, f->fontheight, f->stride);
    323 	}
    324 }
    325 
    326 #if NRASOPS_ROTATION > 0
    327 
    328 struct wsdisplay_font *wsfont_rotate_cw_internal(struct wsdisplay_font *);
    329 struct wsdisplay_font *wsfont_rotate_ccw_internal(struct wsdisplay_font *);
    330 
    331 struct wsdisplay_font *
    332 wsfont_rotate_cw_internal(struct wsdisplay_font *font)
    333 {
    334 	int b, n, r, namelen, newstride;
    335 	struct wsdisplay_font *newfont;
    336 	char *newname, *newbits;
    337 
    338 	/* Duplicate the existing font... */
    339 	newfont = malloc(sizeof(*font), M_DEVBUF, M_WAITOK);
    340 	if (newfont == NULL)
    341 		return (NULL);
    342 
    343 	*newfont = *font;
    344 
    345 	namelen = strlen(font->name) + 4;
    346 	newname = malloc(namelen, M_DEVBUF, M_WAITOK);
    347 	strlcpy(newname, font->name, namelen);
    348 	strlcat(newname, "cw", namelen);
    349 	newfont->name = newname;
    350 
    351 	/* Allocate a buffer big enough for the rotated font. */
    352 	newstride = (font->fontheight + 7) / 8;
    353 	newbits = malloc(newstride * font->fontwidth * font->numchars,
    354 	    M_DEVBUF, M_WAITOK|M_ZERO);
    355 	if (newbits == NULL) {
    356 		free(newfont, M_DEVBUF);
    357 		return (NULL);
    358 	}
    359 
    360 	/* Rotate the font a bit at a time. */
    361 	for (n = 0; n < font->numchars; n++) {
    362 		unsigned char *ch = (unsigned char *)font->data +
    363 		    (n * font->stride * font->fontheight);
    364 
    365 		for (r = 0; r < font->fontheight; r++) {
    366 			for (b = 0; b < font->fontwidth; b++) {
    367 				unsigned char *rb;
    368 
    369 				rb = ch + (font->stride * r) + (b / 8);
    370 				if (*rb & (0x80 >> (b % 8))) {
    371 					unsigned char *rrb;
    372 
    373 					rrb = newbits + newstride - 1 - (r / 8)
    374 					    + (n * newstride * font->fontwidth)
    375 					    + (newstride * b);
    376 					*rrb |= (1 << (r % 8));
    377 				}
    378 			}
    379 		}
    380 	}
    381 
    382 	newfont->data = newbits;
    383 
    384 	/* Update font sizes. */
    385 	newfont->stride = newstride;
    386 	newfont->fontwidth = font->fontheight;
    387 	newfont->fontheight = font->fontwidth;
    388 
    389 	if (wsfont_add(newfont, 0) != 0) {
    390 		/*
    391 		 * If we seem to have rotated this font already, drop the
    392 		 * new one...
    393 		 */
    394 		free(newbits, M_DEVBUF);
    395 		free(newfont, M_DEVBUF);
    396 		newfont = NULL;
    397 	}
    398 
    399 	return (newfont);
    400 }
    401 
    402 struct wsdisplay_font *
    403 wsfont_rotate_ccw_internal(struct wsdisplay_font *font)
    404 {
    405 	int b, n, r, namelen, newstride;
    406 	struct wsdisplay_font *newfont;
    407 	char *newname, *newbits;
    408 
    409 	/* Duplicate the existing font... */
    410 	newfont = malloc(sizeof(*font), M_DEVBUF, M_WAITOK);
    411 	if (newfont == NULL)
    412 		return (NULL);
    413 
    414 	*newfont = *font;
    415 
    416 	namelen = strlen(font->name) + 4;
    417 	newname = malloc(namelen, M_DEVBUF, M_WAITOK);
    418 	strlcpy(newname, font->name, namelen);
    419 	strlcat(newname, "ccw", namelen);
    420 	newfont->name = newname;
    421 
    422 	/* Allocate a buffer big enough for the rotated font. */
    423 	newstride = (font->fontheight + 7) / 8;
    424 	newbits = malloc(newstride * font->fontwidth * font->numchars,
    425 	    M_DEVBUF, M_WAITOK|M_ZERO);
    426 	if (newbits == NULL) {
    427 		free(newfont, M_DEVBUF);
    428 		return (NULL);
    429 	}
    430 
    431 	/* Rotate the font a bit at a time. */
    432 	for (n = 0; n < font->numchars; n++) {
    433 		unsigned char *ch = (unsigned char *)font->data +
    434 		    (n * font->stride * font->fontheight);
    435 
    436 		for (r = 0; r < font->fontheight; r++) {
    437 			for (b = 0; b < font->fontwidth; b++) {
    438 				unsigned char *rb;
    439 
    440 				rb = ch + (font->stride * r) + (b / 8);
    441 				if (*rb & (0x80 >> (b % 8))) {
    442 					unsigned char *rrb;
    443 					int w = font->fontwidth;
    444 
    445 					rrb = newbits + (r / 8)
    446 					    + (n * newstride * w)
    447 					    + (newstride * (w - 1 - b));
    448 					*rrb |= (0x80 >> (r % 8));
    449 				}
    450 			}
    451 		}
    452 	}
    453 
    454 	newfont->data = newbits;
    455 
    456 	/* Update font sizes. */
    457 	newfont->stride = newstride;
    458 	newfont->fontwidth = font->fontheight;
    459 	newfont->fontheight = font->fontwidth;
    460 
    461 	if (wsfont_add(newfont, 0) != 0) {
    462 		/*
    463 		 * If we seem to have rotated this font already, drop the
    464 		 * new one...
    465 		 */
    466 		free(newbits, M_DEVBUF);
    467 		free(newfont, M_DEVBUF);
    468 		newfont = NULL;
    469 	}
    470 
    471 	return (newfont);
    472 }
    473 
    474 int
    475 wsfont_rotate(int cookie, int rotate)
    476 {
    477 	int s, ncookie;
    478 	struct wsdisplay_font *font;
    479 	struct font *origfont;
    480 
    481 	s = splhigh();
    482 	origfont = wsfont_find0(cookie, 0xffffffff);
    483 	splx(s);
    484 
    485 	switch (rotate) {
    486 	case WSFONT_ROTATE_CW:
    487 		font = wsfont_rotate_cw_internal(origfont->font);
    488 		if (font == NULL)
    489 			return (-1);
    490 		break;
    491 
    492 	case WSFONT_ROTATE_CCW:
    493 		font = wsfont_rotate_ccw_internal(origfont->font);
    494 		if (font == NULL)
    495 			return (-1);
    496 		break;
    497 
    498 	case WSFONT_ROTATE_UD:
    499 	default:
    500 		return (-1);
    501 	}
    502 	/* rotation works only with bitmap fonts so far */
    503 	ncookie = wsfont_find(font->name, font->fontwidth, font->fontheight,
    504 	    font->stride, 0, 0, WSFONT_FIND_BITMAP);
    505 
    506 	return (ncookie);
    507 }
    508 
    509 #endif	/* NRASOPS_ROTATION */
    510 
    511 void
    512 wsfont_init(void)
    513 {
    514 	struct font *ent;
    515 	static int again;
    516 	int i;
    517 
    518 	if (again != 0)
    519 		return;
    520 	again = 1;
    521 
    522 	TAILQ_INIT(&list);
    523 	ent = builtin_fonts;
    524 
    525 	for (i = 0; builtin_fonts[i].font != NULL; i++, ent++) {
    526 		ident += (1 << WSFONT_IDENT_SHIFT);
    527 		ent->cookie = wsfont_make_cookie(ident,
    528 		    ent->font->bitorder, ent->font->byteorder);
    529 		TAILQ_INSERT_TAIL(&list, ent, chain);
    530 	}
    531 }
    532 
    533 static struct font *
    534 wsfont_find0(int cookie, int mask)
    535 {
    536 	struct font *ent;
    537 
    538 	TAILQ_FOREACH(ent, &list, chain) {
    539 		if ((ent->cookie & mask) == (cookie & mask))
    540 			return (ent);
    541 	}
    542 
    543 	return (NULL);
    544 }
    545 
    546 int
    547 wsfont_matches(struct wsdisplay_font *font, const char *name,
    548 	       int width, int height, int stride, int flags)
    549 {
    550 
    551 	/* first weed out fonts the caller doesn't claim support for */
    552 	if (FONT_IS_ALPHA(font)) {
    553 		if ((flags & WSFONT_FIND_ALPHA) == 0)
    554 			return 0;
    555 	} else {
    556 		if ((flags & WSFONT_FIND_BITMAP) == 0)
    557 			return 0;
    558 	}
    559 
    560 	if (height != 0 && font->fontheight != height)
    561 		return (0);
    562 
    563 	if (width != 0 && font->fontwidth != width)
    564 		return (0);
    565 
    566 	if (stride != 0 && font->stride != stride)
    567 		return (0);
    568 
    569 	if (name != NULL && strcmp(font->name, name) != 0)
    570 		return (0);
    571 
    572 	return (1);
    573 }
    574 
    575 int
    576 wsfont_find(const char *name, int width, int height, int stride, int bito, int byteo, int flags)
    577 {
    578 	struct font *ent;
    579 
    580 	TAILQ_FOREACH(ent, &list, chain) {
    581 		if (wsfont_matches(ent->font, name, width, height, stride, flags))
    582 			return (wsfont_make_cookie(ent->cookie, bito, byteo));
    583 	}
    584 
    585 	return (-1);
    586 }
    587 
    588 void
    589 wsfont_walk(void (*matchfunc)(struct wsdisplay_font *, void *, int), void *cookie)
    590 {
    591 	struct font *ent;
    592 
    593 	TAILQ_FOREACH(ent, &list, chain) {
    594 		matchfunc(ent->font, cookie, ent->cookie);
    595 	}
    596 }
    597 
    598 static struct font *
    599 wsfont_add0(struct wsdisplay_font *font, int copy)
    600 {
    601 	struct font *ent;
    602 	size_t size;
    603 
    604 	ent = malloc(sizeof(struct font), M_DEVBUF, M_WAITOK | M_ZERO);
    605 
    606 	/* Is this font statically allocated? */
    607 	if (!copy) {
    608 		ent->font = font;
    609 		ent->flags = WSFONT_STATIC;
    610 	} else {
    611 		void *data;
    612 		char *name;
    613 
    614 		ent->font = malloc(sizeof(struct wsdisplay_font), M_DEVBUF,
    615 		    M_WAITOK);
    616 		memcpy(ent->font, font, sizeof(*ent->font));
    617 
    618 		size = font->fontheight * font->numchars * font->stride;
    619 		data = malloc(size, M_DEVBUF, M_WAITOK);
    620 		memcpy(data, font->data, size);
    621 		ent->font->data = data;
    622 
    623 		name = malloc(strlen(font->name) + 1, M_DEVBUF, M_WAITOK);
    624 		strlcpy(name, font->name, strlen(font->name) + 1);
    625 		ent->font->name = name;
    626 	}
    627 
    628 	TAILQ_INSERT_TAIL(&list, ent, chain);
    629 	return (ent);
    630 }
    631 
    632 int
    633 wsfont_add(struct wsdisplay_font *font, int copy)
    634 {
    635 	struct font *ent;
    636 
    637 	/* Don't allow exact duplicates */
    638 	if (wsfont_find(font->name, font->fontwidth, font->fontheight,
    639 	    font->stride, 0, 0, WSFONT_FIND_ALL) >= 0)
    640 		return (EEXIST);
    641 
    642 	ent = wsfont_add0(font, copy);
    643 
    644 	ident += (1 << WSFONT_IDENT_SHIFT);
    645 	ent->cookie = wsfont_make_cookie(ident, font->bitorder,
    646 	    font->byteorder);
    647 
    648 	return (0);
    649 }
    650 
    651 int
    652 wsfont_remove(int cookie)
    653 {
    654 	struct font *ent;
    655 
    656 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
    657 		return (ENOENT);
    658 
    659 	if ((ent->flags & WSFONT_BUILTIN) != 0 || ent->lockcount != 0)
    660 		return (EBUSY);
    661 
    662 	if ((ent->flags & WSFONT_STATIC) == 0) {
    663 		free(ent->font->data, M_DEVBUF);
    664 		free(__UNCONST(ent->font->name), M_DEVBUF); /*XXXUNCONST*/
    665 		free(ent->font, M_DEVBUF);
    666 	}
    667 
    668 	TAILQ_REMOVE(&list, ent, chain);
    669 	free(ent, M_DEVBUF);
    670 
    671 	return (0);
    672 }
    673 
    674 int
    675 wsfont_lock(int cookie, struct wsdisplay_font **ptr)
    676 {
    677 	struct font *ent, *neu;
    678 	int bito, byteo;
    679 
    680 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL) {
    681 		if ((ent = wsfont_find0(cookie, WSFONT_IDENT_MASK)) == NULL)
    682 			return (ENOENT);
    683 
    684 		bito = (cookie & WSFONT_BITO_MASK) >> WSFONT_BITO_SHIFT;
    685 		byteo = (cookie & WSFONT_BYTEO_MASK) >> WSFONT_BYTEO_SHIFT;
    686 
    687 		if (ent->lockcount != 0) {
    688 			neu = wsfont_add0(ent->font, 1);
    689 			neu->flags |= WSFONT_COPY;
    690 
    691 			aprint_debug("wsfont: font '%s' bito %d byteo %d "
    692 			    "copied to bito %d byteo %d\n",
    693 			    ent->font->name,
    694 			    ent->font->bitorder, ent->font->byteorder,
    695 			    bito, byteo);
    696 
    697 			ent = neu;
    698 		}
    699 
    700 		if (bito && bito != ent->font->bitorder) {
    701 			wsfont_revbit(ent->font);
    702 			ent->font->bitorder = bito;
    703 		}
    704 
    705 		if (byteo && byteo != ent->font->byteorder) {
    706 			wsfont_revbyte(ent->font);
    707 			ent->font->byteorder = byteo;
    708 		}
    709 
    710 		ent->cookie = cookie;
    711 	}
    712 
    713 	ent->lockcount++;
    714 	*ptr = ent->font;
    715 	return (0);
    716 }
    717 
    718 int
    719 wsfont_unlock(int cookie)
    720 {
    721 	struct font *ent;
    722 
    723 	if ((ent = wsfont_find0(cookie, 0xffffffff)) == NULL)
    724 		return (ENOENT);
    725 
    726 	if (ent->lockcount == 0)
    727 		panic("wsfont_unlock: font not locked");
    728 
    729 	if (--ent->lockcount == 0 && (ent->flags & WSFONT_COPY) != 0)
    730 		wsfont_remove(cookie);
    731 
    732 	return (0);
    733 }
    734 
    735 /*
    736  * Unicode to font encoding mappings
    737  */
    738 
    739 /*
    740  * To save memory, font encoding tables use a two level lookup.  First the
    741  * high byte of the Unicode is used to lookup the level 2 table, then the
    742  * low byte indexes that table.  Level 2 tables that are not needed are
    743  * omitted (NULL), and both level 1 and level 2 tables have base and size
    744  * attributes to keep their size down.
    745  */
    746 
    747 struct wsfont_level1_glyphmap {
    748 	const struct	wsfont_level2_glyphmap **level2;
    749 	int	base;	/* High byte for first level2 entry	*/
    750 	int	size;	/* Number of level2 entries		*/
    751 };
    752 
    753 struct wsfont_level2_glyphmap {
    754 	int	base;	/* Low byte for first character		*/
    755 	int	size;	/* Number of characters			*/
    756 	const void	*chars;	/* Pointer to character number entries  */
    757 	int	width;	/* Size of each entry in bytes (1,2,4)  */
    758 };
    759 
    760 #define null16			\
    761 	NULL, NULL, NULL, NULL,	\
    762 	NULL, NULL, NULL, NULL,	\
    763 	NULL, NULL, NULL, NULL,	\
    764 	NULL, NULL, NULL, NULL
    765 
    766 /*
    767  * IBM 437 maps
    768  */
    769 
    770 static const u_int8_t ibm437_chars_0[] = {
    771 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
    772 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
    773 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
    774 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
    775 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
    776 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
    777 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
    778 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
    779 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    780 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    781 	255,173,155,156, 0, 157, 0,  0,  0,  0, 166,174,170, 0,  0,  0,
    782 	 0, 241,253, 0,  0,  0,  0, 249, 0,  0, 167,175,172,171, 0, 168,
    783 	 0,  0,  0,  0, 142,143,146,128, 0, 144, 0,  0,  0,  0,  0,  0,
    784 	 0, 165, 0,  0,  0,  0, 153, 0,  0,  0,  0,  0, 154, 0,  0,  0,
    785 	133,160,131, 0, 132,134,145,135,138,130,136,137,141,161,140,139,
    786 	 0, 164,149,162,147, 0, 148,246, 0, 151,163,150,129, 0,  0, 152
    787 };
    788 
    789 static const u_int8_t ibm437_chars_1[] = {
    790 	159
    791 };
    792 
    793 static const u_int8_t ibm437_chars_3[] = {
    794 	226, 0,  0,  0,  0, 233, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    795 	228, 0,  0, 232, 0,  0, 234, 0,  0,  0,  0,  0,  0,  0, 224,225,
    796 	 0, 235,238, 0,  0,  0,  0,  0,  0, 230, 0,  0,  0, 227, 0,  0,
    797 	229,231
    798 };
    799 
    800 static const u_int8_t ibm437_chars_32[] = {
    801 	252, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    802 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    803 	 0,  0,  0,  0,  0,  0,  0,  0, 158
    804 };
    805 
    806 static const u_int8_t ibm437_chars_34[] = {
    807 	237, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    808 	 0,  0,  0, 248,250,251, 0,  0,  0, 236, 0,  0,  0,  0,  0,  0,
    809 	 0,  0,  0,  0, 239, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    810 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    811 	 0,  0,  0, 247, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    812 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,240,  0,  0,243,
    813 	242
    814 };
    815 
    816 static const u_int8_t ibm437_chars_35[] = {
    817 	169, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    818 	244,245
    819 };
    820 
    821 static const u_int8_t ibm437_chars_37[] = {
    822 	196,205,179,186, 0,  0,  0,  0,  0,  0,  0,  0, 218,213,214,201,
    823 	191,184,183,187,192,212,211,200,217,190,189,188,195,198, 0,  0,
    824 	199, 0,  0, 204,180,181, 0,  0, 182, 0,  0, 185,194, 0,  0, 209,
    825 	210, 0,  0, 203,193, 0,  0, 207,208, 0,  0, 202,197, 0,  0, 216,
    826 	 0,  0, 215, 0,  0,  0,  0,  0,  0,  0,  0, 206, 0,  0,  0,  0,
    827 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    828 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    829 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    830 	223, 0,  0,  0, 220, 0,  0,  0, 219, 0,  0,  0, 221, 0,  0,  0,
    831 	222,176,177,178, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    832 	254
    833 };
    834 
    835 static const struct wsfont_level2_glyphmap ibm437_level2_0 =
    836     { 0, 256, ibm437_chars_0, 1 };
    837 
    838 static const struct wsfont_level2_glyphmap ibm437_level2_1 =
    839     { 146, 1, ibm437_chars_1, 1 };
    840 
    841 static const struct wsfont_level2_glyphmap ibm437_level2_3 =
    842     { 147, 50, ibm437_chars_3, 1 };
    843 
    844 static const struct wsfont_level2_glyphmap ibm437_level2_32 =
    845     { 127, 41, ibm437_chars_32, 1 };
    846 
    847 static const struct wsfont_level2_glyphmap ibm437_level2_34 =
    848     { 5, 97, ibm437_chars_34, 1 };
    849 
    850 static const struct wsfont_level2_glyphmap ibm437_level2_35 =
    851     { 16, 18, ibm437_chars_35, 1 };
    852 
    853 static const struct wsfont_level2_glyphmap ibm437_level2_37 =
    854     { 0, 161, ibm437_chars_37, 1 };
    855 
    856 static const struct wsfont_level2_glyphmap *ibm437_level1[] = {
    857 	&ibm437_level2_0, &ibm437_level2_1, NULL, &ibm437_level2_3,
    858 	NULL, NULL, NULL, NULL,
    859 	NULL, NULL, NULL, NULL,
    860 	NULL, NULL, NULL, NULL,
    861 	NULL, NULL, NULL, NULL,
    862 	NULL, NULL, NULL, NULL,
    863 	NULL, NULL, NULL, NULL,
    864 	NULL, NULL, NULL, NULL,
    865 	&ibm437_level2_32, NULL, &ibm437_level2_34, &ibm437_level2_35,
    866 	NULL, &ibm437_level2_37
    867 };
    868 
    869 /*
    870  * ISO-8859-7 maps
    871  */
    872 static const u_int8_t iso7_chars_0[] = {
    873 	 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
    874 	16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
    875 	32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
    876 	48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
    877 	64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
    878 	80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
    879 	96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111,
    880 	112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,
    881 	128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
    882 	144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
    883 	160, 0,  0, 163, 0,  0, 166,167,168,169, 0, 171,172,173, 0,  0,
    884 	176,177,178,179,180, 0,  0, 183, 0,  0,  0, 187, 0, 189
    885 };
    886 
    887 static const u_int8_t iso7_chars_3[] = {
    888 	182, 0, 184,185,186, 0, 188, 0, 190,191,192,193,194,195,196,197,
    889 	198,199,200,201,202,203,204,205,206,207,208,209, 0, 211,212,213,
    890 	214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,229,
    891 	230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,
    892 	246,247,248,249,250,251,252,253,254, 0,  0,  0,  0,  0,  0,  0,
    893 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
    894 	 0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 181
    895 };
    896 
    897 /*
    898  * map all variants of the box drawing characters to the same basic shapes for
    899  * now, encoded like this:
    900  *
    901  *    1
    902  *    1
    903  * 888 222
    904  *    4
    905  *    4
    906  *
    907  * so an upright line would be 0x05
    908  */
    909 #define FL |WSFONT_FLAG_OPT
    910 static const u_int32_t netbsd_boxes[] = {
    911 /*00*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL,
    912 /*08*/ 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x06 FL,
    913 /*10*/ 0x0c FL, 0x0c FL, 0x0c FL, 0x0c FL, 0x03 FL, 0x03 FL, 0x03 FL, 0x03 FL,
    914 /*18*/ 0x09 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL,
    915 /*20*/ 0x07 FL, 0x07 FL, 0x07 FL, 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL,
    916 /*28*/ 0x0d FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL,
    917 /*30*/ 0x0e FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL,
    918 /*38*/ 0x0b FL, 0x0b FL, 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL,
    919 /*40*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL,
    920 /*48*/ 0x0f FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x0a FL, 0x0a FL, 0x05 FL, 0x05 FL,
    921 /*50*/ 0x0a FL, 0x05 FL, 0x06 FL, 0x06 FL, 0x06 FL, 0x0c FL, 0x0c FL, 0x0c FL,
    922 /*58*/ 0x03 FL, 0x03 FL, 0x03 FL, 0x09 FL, 0x09 FL, 0x09 FL, 0x07 FL, 0x07 FL,
    923 /*60*/ 0x07 FL, 0x0d FL, 0x0d FL, 0x0d FL, 0x0e FL, 0x0e FL, 0x0e FL, 0x0b FL,
    924 /*68*/ 0x0b FL, 0x0b FL, 0x0f FL, 0x0f FL, 0x0f FL, 0x06 FL, 0x0c FL, 0x09 FL,
    925 /*70*/ 0x03 FL,    0 FL,    0 FL,    0 FL, 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL,
    926 /*78*/ 0x08 FL, 0x01 FL, 0x02 FL, 0x04 FL, 0x0a FL, 0x05 FL, 0x0a FL, 0x05 FL
    927 };
    928 #undef FL
    929 
    930 static const u_int8_t iso7_chars_32[] = {
    931 	175, 0,  0,  0,  0, 162, 0, 161
    932 };
    933 
    934 static const struct wsfont_level2_glyphmap iso7_level2_0 =
    935     { 0, 190, iso7_chars_0, 1 };
    936 
    937 static const struct wsfont_level2_glyphmap iso7_level2_3 =
    938     { 134, 111, iso7_chars_3, 1 };
    939 
    940 static const struct wsfont_level2_glyphmap iso7_level2_32 =
    941     { 20, 8, iso7_chars_32, 1 };
    942 
    943 static const struct wsfont_level2_glyphmap netbsd_box_drawing =
    944     { 0, 128, netbsd_boxes, 4 };
    945 
    946 static const struct wsfont_level2_glyphmap *iso7_level1[] = {
    947 	&iso7_level2_0, NULL, NULL, &iso7_level2_3,
    948 	NULL, NULL, NULL, NULL,
    949 	NULL, NULL, NULL, NULL,
    950 	NULL, NULL, NULL, NULL,
    951 	NULL, NULL, NULL, NULL,
    952 	NULL, NULL, NULL, NULL,
    953 	NULL, NULL, NULL, NULL,
    954 	NULL, NULL, NULL, NULL,
    955 	&iso7_level2_32, NULL, NULL, NULL,
    956 	NULL, &netbsd_box_drawing
    957 };
    958 
    959 static const struct wsfont_level2_glyphmap *iso_level1[] = {
    960 	NULL, NULL, NULL, NULL,
    961 	NULL, NULL, NULL, NULL,
    962 	NULL, NULL, NULL, NULL,
    963 	NULL, NULL, NULL, NULL,
    964 	NULL, NULL, NULL, NULL,
    965 	NULL, NULL, NULL, NULL,
    966 	NULL, NULL, NULL, NULL,
    967 	NULL, NULL, NULL, NULL,
    968 	NULL, NULL, NULL, NULL,
    969 	NULL, &netbsd_box_drawing
    970 };
    971 
    972 static const struct wsfont_level1_glyphmap encodings[] = {
    973 	{ iso_level1, 0, 0x26 },	/* WSDISPLAY_FONTENC_ISO */
    974 	{ ibm437_level1, 0, 38 },	/* WSDISPLAY_FONTENC_IBM */
    975 	{ NULL, 0, 0 },			/* WSDISPLAY_FONTENC_PCVT */
    976 	{ iso7_level1, 0, 0x26 },	/* WSDISPLAY_FONTENC_ISO7 */
    977 };
    978 
    979 #define MAX_ENCODING (sizeof(encodings) / sizeof(encodings[0]))
    980 
    981 /*
    982  * Remap Unicode character to glyph
    983  */
    984 int
    985 wsfont_map_unichar(struct wsdisplay_font *font, int c)
    986 {
    987 	const struct wsfont_level1_glyphmap *map1;
    988 	const struct wsfont_level2_glyphmap *map2;
    989 	int hi, lo;
    990 
    991 	if (font->encoding < 0 || font->encoding >= MAX_ENCODING)
    992 		return (-1);
    993 
    994 	hi = (c >> 8);
    995 	lo = c & 255;
    996 	map1 = &encodings[font->encoding];
    997 
    998 	if (hi < map1->base || hi >= map1->base + map1->size)
    999 		return (-1);
   1000 
   1001 	map2 = map1->level2[hi - map1->base];
   1002 
   1003 	/* so we don't need an identical level 2 table for hi == 0 */
   1004 	if (hi == 0 && font->encoding == WSDISPLAY_FONTENC_ISO)
   1005 		return lo;
   1006 
   1007 	if (map2 == NULL || lo < map2->base || lo >= map2->base + map2->size)
   1008 		return (-1);
   1009 
   1010 	lo -= map2->base;
   1011 
   1012 	switch(map2->width) {
   1013 	case 1:
   1014 		c = (((const u_int8_t *)map2->chars)[lo]);
   1015 		break;
   1016 	case 2:
   1017 		c = (((const u_int16_t *)map2->chars)[lo]);
   1018 		break;
   1019 	case 4:
   1020 		c = (((const u_int32_t *)map2->chars)[lo]);
   1021 		break;
   1022 	}
   1023 
   1024 	if (c == 0 && lo != 0)
   1025 		return (-1);
   1026 
   1027 	return (c);
   1028 }
   1029