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