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