244static void 245scteken_nop(void) 246{ 247 248} 249 250/* 251 * libteken routines. 252 */ 253 254static const unsigned char fgcolors_normal[TC_NCOLORS] = { 255 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, 256 FG_BLUE, FG_MAGENTA, FG_CYAN, FG_LIGHTGREY, 257}; 258 259static const unsigned char fgcolors_bold[TC_NCOLORS] = { 260 FG_DARKGREY, FG_LIGHTRED, FG_LIGHTGREEN, FG_YELLOW, 261 FG_LIGHTBLUE, FG_LIGHTMAGENTA, FG_LIGHTCYAN, FG_WHITE, 262}; 263 264static const unsigned char bgcolors[TC_NCOLORS] = { 265 BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, 266 BG_BLUE, BG_MAGENTA, BG_CYAN, BG_LIGHTGREY, 267}; 268 269static void 270scteken_revattr(unsigned char color, teken_attr_t *a) 271{ 272 teken_color_t fg, bg; 273 274 /* 275 * XXX: Reverse conversion of syscons to teken attributes. Not 276 * realiable. Maybe we should turn it into a 1:1 mapping one of 277 * these days? 278 */ 279 280 a->ta_format = 0; 281 a->ta_fgcolor = TC_WHITE; 282 a->ta_bgcolor = TC_BLACK; 283 284#ifdef FG_BLINK 285 if (color & FG_BLINK) { 286 a->ta_format |= TF_BLINK; 287 color &= ~FG_BLINK; 288 } 289#endif /* FG_BLINK */ 290 291 for (fg = 0; fg < TC_NCOLORS; fg++) { 292 for (bg = 0; bg < TC_NCOLORS; bg++) { 293 if ((fgcolors_normal[fg] | bgcolors[bg]) == color) { 294 a->ta_fgcolor = fg; 295 a->ta_bgcolor = bg; 296 return; 297 } 298 299 if ((fgcolors_bold[fg] | bgcolors[bg]) == color) { 300 a->ta_fgcolor = fg; 301 a->ta_bgcolor = bg; 302 a->ta_format |= TF_BOLD; 303 return; 304 } 305 } 306 } 307} 308 309static unsigned int 310scteken_attr(const teken_attr_t *a) 311{ 312 unsigned int attr = 0; 313 teken_color_t fg, bg; 314 315 if (a->ta_format & TF_REVERSE) { 316 fg = teken_256to8(a->ta_bgcolor); 317 bg = teken_256to8(a->ta_fgcolor); 318 } else { 319 fg = teken_256to8(a->ta_fgcolor); 320 bg = teken_256to8(a->ta_bgcolor); 321 } 322 if (a->ta_format & TF_BOLD) 323 attr |= fgcolors_bold[fg]; 324 else 325 attr |= fgcolors_normal[fg]; 326 attr |= bgcolors[bg]; 327 328#ifdef FG_UNDERLINE 329 if (a->ta_format & TF_UNDERLINE) 330 attr |= FG_UNDERLINE; 331#endif /* FG_UNDERLINE */ 332#ifdef FG_BLINK 333 if (a->ta_format & TF_BLINK) 334 attr |= FG_BLINK; 335#endif /* FG_BLINK */ 336 337 return (attr); 338} 339 340static void 341scteken_bell(void *arg) 342{ 343 scr_stat *scp = arg; 344 345 sc_bell(scp, scp->bell_pitch, scp->bell_duration); 346} 347 348static void 349scteken_cursor(void *arg, const teken_pos_t *p) 350{ 351 scr_stat *scp = arg; 352 353 sc_move_cursor(scp, p->tp_col, p->tp_row); 354} 355 356#ifdef TEKEN_UTF8 357struct unicp437 { 358 uint16_t unicode_base; 359 uint8_t cp437_base; 360 uint8_t length; 361}; 362 363static const struct unicp437 cp437table[] = { 364 { 0x0020, 0x20, 0x5e }, { 0x00a0, 0x20, 0x00 }, 365 { 0x00a1, 0xad, 0x00 }, { 0x00a2, 0x9b, 0x00 }, 366 { 0x00a3, 0x9c, 0x00 }, { 0x00a5, 0x9d, 0x00 }, 367 { 0x00a7, 0x15, 0x00 }, { 0x00aa, 0xa6, 0x00 }, 368 { 0x00ab, 0xae, 0x00 }, { 0x00ac, 0xaa, 0x00 }, 369 { 0x00b0, 0xf8, 0x00 }, { 0x00b1, 0xf1, 0x00 }, 370 { 0x00b2, 0xfd, 0x00 }, { 0x00b5, 0xe6, 0x00 }, 371 { 0x00b6, 0x14, 0x00 }, { 0x00b7, 0xfa, 0x00 }, 372 { 0x00ba, 0xa7, 0x00 }, { 0x00bb, 0xaf, 0x00 }, 373 { 0x00bc, 0xac, 0x00 }, { 0x00bd, 0xab, 0x00 }, 374 { 0x00bf, 0xa8, 0x00 }, { 0x00c4, 0x8e, 0x01 }, 375 { 0x00c6, 0x92, 0x00 }, { 0x00c7, 0x80, 0x00 }, 376 { 0x00c9, 0x90, 0x00 }, { 0x00d1, 0xa5, 0x00 }, 377 { 0x00d6, 0x99, 0x00 }, { 0x00dc, 0x9a, 0x00 }, 378 { 0x00df, 0xe1, 0x00 }, { 0x00e0, 0x85, 0x00 }, 379 { 0x00e1, 0xa0, 0x00 }, { 0x00e2, 0x83, 0x00 }, 380 { 0x00e4, 0x84, 0x00 }, { 0x00e5, 0x86, 0x00 }, 381 { 0x00e6, 0x91, 0x00 }, { 0x00e7, 0x87, 0x00 }, 382 { 0x00e8, 0x8a, 0x00 }, { 0x00e9, 0x82, 0x00 }, 383 { 0x00ea, 0x88, 0x01 }, { 0x00ec, 0x8d, 0x00 }, 384 { 0x00ed, 0xa1, 0x00 }, { 0x00ee, 0x8c, 0x00 }, 385 { 0x00ef, 0x8b, 0x00 }, { 0x00f0, 0xeb, 0x00 }, 386 { 0x00f1, 0xa4, 0x00 }, { 0x00f2, 0x95, 0x00 }, 387 { 0x00f3, 0xa2, 0x00 }, { 0x00f4, 0x93, 0x00 }, 388 { 0x00f6, 0x94, 0x00 }, { 0x00f7, 0xf6, 0x00 }, 389 { 0x00f8, 0xed, 0x00 }, { 0x00f9, 0x97, 0x00 }, 390 { 0x00fa, 0xa3, 0x00 }, { 0x00fb, 0x96, 0x00 }, 391 { 0x00fc, 0x81, 0x00 }, { 0x00ff, 0x98, 0x00 }, 392 { 0x0192, 0x9f, 0x00 }, { 0x0393, 0xe2, 0x00 }, 393 { 0x0398, 0xe9, 0x00 }, { 0x03a3, 0xe4, 0x00 }, 394 { 0x03a6, 0xe8, 0x00 }, { 0x03a9, 0xea, 0x00 }, 395 { 0x03b1, 0xe0, 0x01 }, { 0x03b4, 0xeb, 0x00 }, 396 { 0x03b5, 0xee, 0x00 }, { 0x03bc, 0xe6, 0x00 }, 397 { 0x03c0, 0xe3, 0x00 }, { 0x03c3, 0xe5, 0x00 }, 398 { 0x03c4, 0xe7, 0x00 }, { 0x03c6, 0xed, 0x00 }, 399 { 0x03d5, 0xed, 0x00 }, { 0x2010, 0x2d, 0x00 }, 400 { 0x2014, 0x2d, 0x00 }, { 0x2018, 0x60, 0x00 }, 401 { 0x2019, 0x27, 0x00 }, { 0x201c, 0x22, 0x00 }, 402 { 0x201d, 0x22, 0x00 }, { 0x2022, 0x07, 0x00 }, 403 { 0x203c, 0x13, 0x00 }, { 0x207f, 0xfc, 0x00 }, 404 { 0x20a7, 0x9e, 0x00 }, { 0x20ac, 0xee, 0x00 }, 405 { 0x2126, 0xea, 0x00 }, { 0x2190, 0x1b, 0x00 }, 406 { 0x2191, 0x18, 0x00 }, { 0x2192, 0x1a, 0x00 }, 407 { 0x2193, 0x19, 0x00 }, { 0x2194, 0x1d, 0x00 }, 408 { 0x2195, 0x12, 0x00 }, { 0x21a8, 0x17, 0x00 }, 409 { 0x2202, 0xeb, 0x00 }, { 0x2208, 0xee, 0x00 }, 410 { 0x2211, 0xe4, 0x00 }, { 0x2212, 0x2d, 0x00 }, 411 { 0x2219, 0xf9, 0x00 }, { 0x221a, 0xfb, 0x00 }, 412 { 0x221e, 0xec, 0x00 }, { 0x221f, 0x1c, 0x00 }, 413 { 0x2229, 0xef, 0x00 }, { 0x2248, 0xf7, 0x00 }, 414 { 0x2261, 0xf0, 0x00 }, { 0x2264, 0xf3, 0x00 }, 415 { 0x2265, 0xf2, 0x00 }, { 0x2302, 0x7f, 0x00 }, 416 { 0x2310, 0xa9, 0x00 }, { 0x2320, 0xf4, 0x00 }, 417 { 0x2321, 0xf5, 0x00 }, { 0x2500, 0xc4, 0x00 }, 418 { 0x2502, 0xb3, 0x00 }, { 0x250c, 0xda, 0x00 }, 419 { 0x2510, 0xbf, 0x00 }, { 0x2514, 0xc0, 0x00 }, 420 { 0x2518, 0xd9, 0x00 }, { 0x251c, 0xc3, 0x00 }, 421 { 0x2524, 0xb4, 0x00 }, { 0x252c, 0xc2, 0x00 }, 422 { 0x2534, 0xc1, 0x00 }, { 0x253c, 0xc5, 0x00 }, 423 { 0x2550, 0xcd, 0x00 }, { 0x2551, 0xba, 0x00 }, 424 { 0x2552, 0xd5, 0x00 }, { 0x2553, 0xd6, 0x00 }, 425 { 0x2554, 0xc9, 0x00 }, { 0x2555, 0xb8, 0x00 }, 426 { 0x2556, 0xb7, 0x00 }, { 0x2557, 0xbb, 0x00 }, 427 { 0x2558, 0xd4, 0x00 }, { 0x2559, 0xd3, 0x00 }, 428 { 0x255a, 0xc8, 0x00 }, { 0x255b, 0xbe, 0x00 }, 429 { 0x255c, 0xbd, 0x00 }, { 0x255d, 0xbc, 0x00 }, 430 { 0x255e, 0xc6, 0x01 }, { 0x2560, 0xcc, 0x00 }, 431 { 0x2561, 0xb5, 0x00 }, { 0x2562, 0xb6, 0x00 }, 432 { 0x2563, 0xb9, 0x00 }, { 0x2564, 0xd1, 0x01 }, 433 { 0x2566, 0xcb, 0x00 }, { 0x2567, 0xcf, 0x00 }, 434 { 0x2568, 0xd0, 0x00 }, { 0x2569, 0xca, 0x00 }, 435 { 0x256a, 0xd8, 0x00 }, { 0x256b, 0xd7, 0x00 }, 436 { 0x256c, 0xce, 0x00 }, { 0x2580, 0xdf, 0x00 }, 437 { 0x2584, 0xdc, 0x00 }, { 0x2588, 0xdb, 0x00 }, 438 { 0x258c, 0xdd, 0x00 }, { 0x2590, 0xde, 0x00 }, 439 { 0x2591, 0xb0, 0x02 }, { 0x25a0, 0xfe, 0x00 }, 440 { 0x25ac, 0x16, 0x00 }, { 0x25b2, 0x1e, 0x00 }, 441 { 0x25ba, 0x10, 0x00 }, { 0x25bc, 0x1f, 0x00 }, 442 { 0x25c4, 0x11, 0x00 }, { 0x25cb, 0x09, 0x00 }, 443 { 0x25d8, 0x08, 0x00 }, { 0x25d9, 0x0a, 0x00 }, 444 { 0x263a, 0x01, 0x01 }, { 0x263c, 0x0f, 0x00 }, 445 { 0x2640, 0x0c, 0x00 }, { 0x2642, 0x0b, 0x00 }, 446 { 0x2660, 0x06, 0x00 }, { 0x2663, 0x05, 0x00 }, 447 { 0x2665, 0x03, 0x01 }, { 0x266a, 0x0d, 0x01 }, 448}; 449 450static void 451scteken_get_cp437(teken_char_t *c, int *attr) 452{ 453 int min, mid, max; 454 455 min = 0; 456 max = (sizeof(cp437table) / sizeof(struct unicp437)) - 1; 457 458 if (*c < cp437table[0].unicode_base || 459 *c > cp437table[max].unicode_base + cp437table[max].length) 460 goto bad; 461 462 while (max >= min) { 463 mid = (min + max) / 2; 464 if (*c < cp437table[mid].unicode_base) { 465 max = mid - 1; 466 } else if (*c > cp437table[mid].unicode_base + 467 cp437table[mid].length) { 468 min = mid + 1; 469 } else { 470 *c -= cp437table[mid].unicode_base; 471 *c += cp437table[mid].cp437_base; 472 return; 473 } 474 } 475bad: 476 /* Character not present in CP437. */ 477 *attr = (FG_RED|BG_BLACK) << 8; 478 *c = '?'; 479} 480#endif /* TEKEN_UTF8 */ 481 482static void 483scteken_putchar(void *arg, const teken_pos_t *tp, teken_char_t c, 484 const teken_attr_t *a) 485{ 486 scr_stat *scp = arg; 487 u_char *map; 488 u_char ch; 489 vm_offset_t p; 490 int cursor, attr; 491 492 attr = scteken_attr(a) << 8; 493#ifdef TEKEN_UTF8 494 scteken_get_cp437(&c, &attr); 495#endif /* TEKEN_UTF8 */ 496 ch = c; 497 498 map = scp->sc->scr_map; 499 500 cursor = tp->tp_row * scp->xsize + tp->tp_col; 501 p = sc_vtb_pointer(&scp->vtb, cursor); 502 sc_vtb_putchar(&scp->vtb, p, map[ch], attr); 503 504 mark_for_update(scp, cursor); 505 /* 506 * XXX: Why do we need this? Only marking `cursor' should be 507 * enough. Without this line, we get artifacts. 508 */ 509 mark_for_update(scp, imin(cursor + 1, scp->xsize * scp->ysize - 1)); 510} 511 512static void 513scteken_fill(void *arg, const teken_rect_t *r, teken_char_t c, 514 const teken_attr_t *a) 515{ 516 scr_stat *scp = arg; 517 u_char *map; 518 u_char ch; 519 unsigned int width; 520 int attr, row; 521 522 attr = scteken_attr(a) << 8; 523#ifdef TEKEN_UTF8 524 scteken_get_cp437(&c, &attr); 525#endif /* TEKEN_UTF8 */ 526 ch = c; 527 528 map = scp->sc->scr_map; 529 530 if (r->tr_begin.tp_col == 0 && r->tr_end.tp_col == scp->xsize) { 531 /* Single contiguous region to fill. */ 532 sc_vtb_erase(&scp->vtb, r->tr_begin.tp_row * scp->xsize, 533 (r->tr_end.tp_row - r->tr_begin.tp_row) * scp->xsize, 534 map[ch], attr); 535 } else { 536 /* Fill display line by line. */ 537 width = r->tr_end.tp_col - r->tr_begin.tp_col; 538 539 for (row = r->tr_begin.tp_row; row < r->tr_end.tp_row; row++) { 540 sc_vtb_erase(&scp->vtb, r->tr_begin.tp_row * 541 scp->xsize + r->tr_begin.tp_col, 542 width, map[ch], attr); 543 } 544 } 545 546 /* Mark begin and end positions to be refreshed. */ 547 mark_for_update(scp, 548 r->tr_begin.tp_row * scp->xsize + r->tr_begin.tp_col); 549 mark_for_update(scp, 550 (r->tr_end.tp_row - 1) * scp->xsize + (r->tr_end.tp_col - 1)); 551 sc_remove_cutmarking(scp); 552} 553 554static void 555scteken_copy(void *arg, const teken_rect_t *r, const teken_pos_t *p) 556{ 557 scr_stat *scp = arg; 558 unsigned int width; 559 int src, dst, end; 560 561#ifndef SC_NO_HISTORY 562 /* 563 * We count a line of input as history if we perform a copy of 564 * one whole line upward. In other words: if a line of text gets 565 * overwritten by a rectangle that's right below it. 566 */ 567 if (scp->history != NULL && 568 r->tr_begin.tp_col == 0 && r->tr_end.tp_col == scp->xsize && 569 r->tr_begin.tp_row == p->tp_row + 1) { 570 sc_hist_save_one_line(scp, p->tp_row); 571 } 572#endif 573 574 if (r->tr_begin.tp_col == 0 && r->tr_end.tp_col == scp->xsize) { 575 /* Single contiguous region to copy. */ 576 sc_vtb_move(&scp->vtb, r->tr_begin.tp_row * scp->xsize, 577 p->tp_row * scp->xsize, 578 (r->tr_end.tp_row - r->tr_begin.tp_row) * scp->xsize); 579 } else { 580 /* Copy line by line. */ 581 width = r->tr_end.tp_col - r->tr_begin.tp_col; 582 583 if (p->tp_row < r->tr_begin.tp_row) { 584 /* Copy from top to bottom. */ 585 src = r->tr_begin.tp_row * scp->xsize + 586 r->tr_begin.tp_col; 587 end = r->tr_end.tp_row * scp->xsize + 588 r->tr_end.tp_col; 589 dst = p->tp_row * scp->xsize + p->tp_col; 590 591 while (src < end) { 592 sc_vtb_move(&scp->vtb, src, dst, width); 593 594 src += scp->xsize; 595 dst += scp->xsize; 596 } 597 } else { 598 /* Copy from bottom to top. */ 599 src = (r->tr_end.tp_row - 1) * scp->xsize + 600 r->tr_begin.tp_col; 601 end = r->tr_begin.tp_row * scp->xsize + 602 r->tr_begin.tp_col; 603 dst = (p->tp_row + r->tr_end.tp_row - 604 r->tr_begin.tp_row - 1) * scp->xsize + p->tp_col; 605 606 while (src >= end) { 607 sc_vtb_move(&scp->vtb, src, dst, width); 608 609 src -= scp->xsize; 610 dst -= scp->xsize; 611 } 612 } 613 } 614 615 /* Mark begin and end positions to be refreshed. */ 616 mark_for_update(scp, 617 p->tp_row * scp->xsize + p->tp_col); 618 mark_for_update(scp, 619 (p->tp_row + r->tr_end.tp_row - r->tr_begin.tp_row - 1) * 620 scp->xsize + 621 (p->tp_col + r->tr_end.tp_col - r->tr_begin.tp_col - 1)); 622 sc_remove_cutmarking(scp); 623} 624 625static void 626scteken_param(void *arg, int cmd, unsigned int value) 627{ 628 scr_stat *scp = arg; 629 630 switch (cmd) { 631 case TP_SHOWCURSOR: 632 if (value) { 633 sc_change_cursor_shape(scp, 634 CONS_RESET_CURSOR|CONS_LOCAL_CURSOR, -1, -1); 635 } else { 636 sc_change_cursor_shape(scp, 637 CONS_HIDDEN_CURSOR|CONS_LOCAL_CURSOR, -1, -1); 638 } 639 break; 640 case TP_SWITCHVT: 641 sc_switch_scr(scp->sc, value); 642 break; 643 case TP_SETBELLPD: 644 scp->bell_pitch = TP_SETBELLPD_PITCH(value); 645 scp->bell_duration = TP_SETBELLPD_DURATION(value); 646 break; 647 case TP_MOUSE: 648 scp->mouse_level = value; 649 break; 650 } 651} 652 653static void 654scteken_respond(void *arg, const void *buf, size_t len) 655{ 656 scr_stat *scp = arg; 657 658 sc_respond(scp, buf, len, 0); 659}
| 297static void 298scteken_nop(void) 299{ 300 301} 302 303/* 304 * libteken routines. 305 */ 306 307static const unsigned char fgcolors_normal[TC_NCOLORS] = { 308 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, 309 FG_BLUE, FG_MAGENTA, FG_CYAN, FG_LIGHTGREY, 310}; 311 312static const unsigned char fgcolors_bold[TC_NCOLORS] = { 313 FG_DARKGREY, FG_LIGHTRED, FG_LIGHTGREEN, FG_YELLOW, 314 FG_LIGHTBLUE, FG_LIGHTMAGENTA, FG_LIGHTCYAN, FG_WHITE, 315}; 316 317static const unsigned char bgcolors[TC_NCOLORS] = { 318 BG_BLACK, BG_RED, BG_GREEN, BG_BROWN, 319 BG_BLUE, BG_MAGENTA, BG_CYAN, BG_LIGHTGREY, 320}; 321 322static void 323scteken_revattr(unsigned char color, teken_attr_t *a) 324{ 325 teken_color_t fg, bg; 326 327 /* 328 * XXX: Reverse conversion of syscons to teken attributes. Not 329 * realiable. Maybe we should turn it into a 1:1 mapping one of 330 * these days? 331 */ 332 333 a->ta_format = 0; 334 a->ta_fgcolor = TC_WHITE; 335 a->ta_bgcolor = TC_BLACK; 336 337#ifdef FG_BLINK 338 if (color & FG_BLINK) { 339 a->ta_format |= TF_BLINK; 340 color &= ~FG_BLINK; 341 } 342#endif /* FG_BLINK */ 343 344 for (fg = 0; fg < TC_NCOLORS; fg++) { 345 for (bg = 0; bg < TC_NCOLORS; bg++) { 346 if ((fgcolors_normal[fg] | bgcolors[bg]) == color) { 347 a->ta_fgcolor = fg; 348 a->ta_bgcolor = bg; 349 return; 350 } 351 352 if ((fgcolors_bold[fg] | bgcolors[bg]) == color) { 353 a->ta_fgcolor = fg; 354 a->ta_bgcolor = bg; 355 a->ta_format |= TF_BOLD; 356 return; 357 } 358 } 359 } 360} 361 362static unsigned int 363scteken_attr(const teken_attr_t *a) 364{ 365 unsigned int attr = 0; 366 teken_color_t fg, bg; 367 368 if (a->ta_format & TF_REVERSE) { 369 fg = teken_256to8(a->ta_bgcolor); 370 bg = teken_256to8(a->ta_fgcolor); 371 } else { 372 fg = teken_256to8(a->ta_fgcolor); 373 bg = teken_256to8(a->ta_bgcolor); 374 } 375 if (a->ta_format & TF_BOLD) 376 attr |= fgcolors_bold[fg]; 377 else 378 attr |= fgcolors_normal[fg]; 379 attr |= bgcolors[bg]; 380 381#ifdef FG_UNDERLINE 382 if (a->ta_format & TF_UNDERLINE) 383 attr |= FG_UNDERLINE; 384#endif /* FG_UNDERLINE */ 385#ifdef FG_BLINK 386 if (a->ta_format & TF_BLINK) 387 attr |= FG_BLINK; 388#endif /* FG_BLINK */ 389 390 return (attr); 391} 392 393static void 394scteken_bell(void *arg) 395{ 396 scr_stat *scp = arg; 397 398 sc_bell(scp, scp->bell_pitch, scp->bell_duration); 399} 400 401static void 402scteken_cursor(void *arg, const teken_pos_t *p) 403{ 404 scr_stat *scp = arg; 405 406 sc_move_cursor(scp, p->tp_col, p->tp_row); 407} 408 409#ifdef TEKEN_UTF8 410struct unicp437 { 411 uint16_t unicode_base; 412 uint8_t cp437_base; 413 uint8_t length; 414}; 415 416static const struct unicp437 cp437table[] = { 417 { 0x0020, 0x20, 0x5e }, { 0x00a0, 0x20, 0x00 }, 418 { 0x00a1, 0xad, 0x00 }, { 0x00a2, 0x9b, 0x00 }, 419 { 0x00a3, 0x9c, 0x00 }, { 0x00a5, 0x9d, 0x00 }, 420 { 0x00a7, 0x15, 0x00 }, { 0x00aa, 0xa6, 0x00 }, 421 { 0x00ab, 0xae, 0x00 }, { 0x00ac, 0xaa, 0x00 }, 422 { 0x00b0, 0xf8, 0x00 }, { 0x00b1, 0xf1, 0x00 }, 423 { 0x00b2, 0xfd, 0x00 }, { 0x00b5, 0xe6, 0x00 }, 424 { 0x00b6, 0x14, 0x00 }, { 0x00b7, 0xfa, 0x00 }, 425 { 0x00ba, 0xa7, 0x00 }, { 0x00bb, 0xaf, 0x00 }, 426 { 0x00bc, 0xac, 0x00 }, { 0x00bd, 0xab, 0x00 }, 427 { 0x00bf, 0xa8, 0x00 }, { 0x00c4, 0x8e, 0x01 }, 428 { 0x00c6, 0x92, 0x00 }, { 0x00c7, 0x80, 0x00 }, 429 { 0x00c9, 0x90, 0x00 }, { 0x00d1, 0xa5, 0x00 }, 430 { 0x00d6, 0x99, 0x00 }, { 0x00dc, 0x9a, 0x00 }, 431 { 0x00df, 0xe1, 0x00 }, { 0x00e0, 0x85, 0x00 }, 432 { 0x00e1, 0xa0, 0x00 }, { 0x00e2, 0x83, 0x00 }, 433 { 0x00e4, 0x84, 0x00 }, { 0x00e5, 0x86, 0x00 }, 434 { 0x00e6, 0x91, 0x00 }, { 0x00e7, 0x87, 0x00 }, 435 { 0x00e8, 0x8a, 0x00 }, { 0x00e9, 0x82, 0x00 }, 436 { 0x00ea, 0x88, 0x01 }, { 0x00ec, 0x8d, 0x00 }, 437 { 0x00ed, 0xa1, 0x00 }, { 0x00ee, 0x8c, 0x00 }, 438 { 0x00ef, 0x8b, 0x00 }, { 0x00f0, 0xeb, 0x00 }, 439 { 0x00f1, 0xa4, 0x00 }, { 0x00f2, 0x95, 0x00 }, 440 { 0x00f3, 0xa2, 0x00 }, { 0x00f4, 0x93, 0x00 }, 441 { 0x00f6, 0x94, 0x00 }, { 0x00f7, 0xf6, 0x00 }, 442 { 0x00f8, 0xed, 0x00 }, { 0x00f9, 0x97, 0x00 }, 443 { 0x00fa, 0xa3, 0x00 }, { 0x00fb, 0x96, 0x00 }, 444 { 0x00fc, 0x81, 0x00 }, { 0x00ff, 0x98, 0x00 }, 445 { 0x0192, 0x9f, 0x00 }, { 0x0393, 0xe2, 0x00 }, 446 { 0x0398, 0xe9, 0x00 }, { 0x03a3, 0xe4, 0x00 }, 447 { 0x03a6, 0xe8, 0x00 }, { 0x03a9, 0xea, 0x00 }, 448 { 0x03b1, 0xe0, 0x01 }, { 0x03b4, 0xeb, 0x00 }, 449 { 0x03b5, 0xee, 0x00 }, { 0x03bc, 0xe6, 0x00 }, 450 { 0x03c0, 0xe3, 0x00 }, { 0x03c3, 0xe5, 0x00 }, 451 { 0x03c4, 0xe7, 0x00 }, { 0x03c6, 0xed, 0x00 }, 452 { 0x03d5, 0xed, 0x00 }, { 0x2010, 0x2d, 0x00 }, 453 { 0x2014, 0x2d, 0x00 }, { 0x2018, 0x60, 0x00 }, 454 { 0x2019, 0x27, 0x00 }, { 0x201c, 0x22, 0x00 }, 455 { 0x201d, 0x22, 0x00 }, { 0x2022, 0x07, 0x00 }, 456 { 0x203c, 0x13, 0x00 }, { 0x207f, 0xfc, 0x00 }, 457 { 0x20a7, 0x9e, 0x00 }, { 0x20ac, 0xee, 0x00 }, 458 { 0x2126, 0xea, 0x00 }, { 0x2190, 0x1b, 0x00 }, 459 { 0x2191, 0x18, 0x00 }, { 0x2192, 0x1a, 0x00 }, 460 { 0x2193, 0x19, 0x00 }, { 0x2194, 0x1d, 0x00 }, 461 { 0x2195, 0x12, 0x00 }, { 0x21a8, 0x17, 0x00 }, 462 { 0x2202, 0xeb, 0x00 }, { 0x2208, 0xee, 0x00 }, 463 { 0x2211, 0xe4, 0x00 }, { 0x2212, 0x2d, 0x00 }, 464 { 0x2219, 0xf9, 0x00 }, { 0x221a, 0xfb, 0x00 }, 465 { 0x221e, 0xec, 0x00 }, { 0x221f, 0x1c, 0x00 }, 466 { 0x2229, 0xef, 0x00 }, { 0x2248, 0xf7, 0x00 }, 467 { 0x2261, 0xf0, 0x00 }, { 0x2264, 0xf3, 0x00 }, 468 { 0x2265, 0xf2, 0x00 }, { 0x2302, 0x7f, 0x00 }, 469 { 0x2310, 0xa9, 0x00 }, { 0x2320, 0xf4, 0x00 }, 470 { 0x2321, 0xf5, 0x00 }, { 0x2500, 0xc4, 0x00 }, 471 { 0x2502, 0xb3, 0x00 }, { 0x250c, 0xda, 0x00 }, 472 { 0x2510, 0xbf, 0x00 }, { 0x2514, 0xc0, 0x00 }, 473 { 0x2518, 0xd9, 0x00 }, { 0x251c, 0xc3, 0x00 }, 474 { 0x2524, 0xb4, 0x00 }, { 0x252c, 0xc2, 0x00 }, 475 { 0x2534, 0xc1, 0x00 }, { 0x253c, 0xc5, 0x00 }, 476 { 0x2550, 0xcd, 0x00 }, { 0x2551, 0xba, 0x00 }, 477 { 0x2552, 0xd5, 0x00 }, { 0x2553, 0xd6, 0x00 }, 478 { 0x2554, 0xc9, 0x00 }, { 0x2555, 0xb8, 0x00 }, 479 { 0x2556, 0xb7, 0x00 }, { 0x2557, 0xbb, 0x00 }, 480 { 0x2558, 0xd4, 0x00 }, { 0x2559, 0xd3, 0x00 }, 481 { 0x255a, 0xc8, 0x00 }, { 0x255b, 0xbe, 0x00 }, 482 { 0x255c, 0xbd, 0x00 }, { 0x255d, 0xbc, 0x00 }, 483 { 0x255e, 0xc6, 0x01 }, { 0x2560, 0xcc, 0x00 }, 484 { 0x2561, 0xb5, 0x00 }, { 0x2562, 0xb6, 0x00 }, 485 { 0x2563, 0xb9, 0x00 }, { 0x2564, 0xd1, 0x01 }, 486 { 0x2566, 0xcb, 0x00 }, { 0x2567, 0xcf, 0x00 }, 487 { 0x2568, 0xd0, 0x00 }, { 0x2569, 0xca, 0x00 }, 488 { 0x256a, 0xd8, 0x00 }, { 0x256b, 0xd7, 0x00 }, 489 { 0x256c, 0xce, 0x00 }, { 0x2580, 0xdf, 0x00 }, 490 { 0x2584, 0xdc, 0x00 }, { 0x2588, 0xdb, 0x00 }, 491 { 0x258c, 0xdd, 0x00 }, { 0x2590, 0xde, 0x00 }, 492 { 0x2591, 0xb0, 0x02 }, { 0x25a0, 0xfe, 0x00 }, 493 { 0x25ac, 0x16, 0x00 }, { 0x25b2, 0x1e, 0x00 }, 494 { 0x25ba, 0x10, 0x00 }, { 0x25bc, 0x1f, 0x00 }, 495 { 0x25c4, 0x11, 0x00 }, { 0x25cb, 0x09, 0x00 }, 496 { 0x25d8, 0x08, 0x00 }, { 0x25d9, 0x0a, 0x00 }, 497 { 0x263a, 0x01, 0x01 }, { 0x263c, 0x0f, 0x00 }, 498 { 0x2640, 0x0c, 0x00 }, { 0x2642, 0x0b, 0x00 }, 499 { 0x2660, 0x06, 0x00 }, { 0x2663, 0x05, 0x00 }, 500 { 0x2665, 0x03, 0x01 }, { 0x266a, 0x0d, 0x01 }, 501}; 502 503static void 504scteken_get_cp437(teken_char_t *c, int *attr) 505{ 506 int min, mid, max; 507 508 min = 0; 509 max = (sizeof(cp437table) / sizeof(struct unicp437)) - 1; 510 511 if (*c < cp437table[0].unicode_base || 512 *c > cp437table[max].unicode_base + cp437table[max].length) 513 goto bad; 514 515 while (max >= min) { 516 mid = (min + max) / 2; 517 if (*c < cp437table[mid].unicode_base) { 518 max = mid - 1; 519 } else if (*c > cp437table[mid].unicode_base + 520 cp437table[mid].length) { 521 min = mid + 1; 522 } else { 523 *c -= cp437table[mid].unicode_base; 524 *c += cp437table[mid].cp437_base; 525 return; 526 } 527 } 528bad: 529 /* Character not present in CP437. */ 530 *attr = (FG_RED|BG_BLACK) << 8; 531 *c = '?'; 532} 533#endif /* TEKEN_UTF8 */ 534 535static void 536scteken_putchar(void *arg, const teken_pos_t *tp, teken_char_t c, 537 const teken_attr_t *a) 538{ 539 scr_stat *scp = arg; 540 u_char *map; 541 u_char ch; 542 vm_offset_t p; 543 int cursor, attr; 544 545 attr = scteken_attr(a) << 8; 546#ifdef TEKEN_UTF8 547 scteken_get_cp437(&c, &attr); 548#endif /* TEKEN_UTF8 */ 549 ch = c; 550 551 map = scp->sc->scr_map; 552 553 cursor = tp->tp_row * scp->xsize + tp->tp_col; 554 p = sc_vtb_pointer(&scp->vtb, cursor); 555 sc_vtb_putchar(&scp->vtb, p, map[ch], attr); 556 557 mark_for_update(scp, cursor); 558 /* 559 * XXX: Why do we need this? Only marking `cursor' should be 560 * enough. Without this line, we get artifacts. 561 */ 562 mark_for_update(scp, imin(cursor + 1, scp->xsize * scp->ysize - 1)); 563} 564 565static void 566scteken_fill(void *arg, const teken_rect_t *r, teken_char_t c, 567 const teken_attr_t *a) 568{ 569 scr_stat *scp = arg; 570 u_char *map; 571 u_char ch; 572 unsigned int width; 573 int attr, row; 574 575 attr = scteken_attr(a) << 8; 576#ifdef TEKEN_UTF8 577 scteken_get_cp437(&c, &attr); 578#endif /* TEKEN_UTF8 */ 579 ch = c; 580 581 map = scp->sc->scr_map; 582 583 if (r->tr_begin.tp_col == 0 && r->tr_end.tp_col == scp->xsize) { 584 /* Single contiguous region to fill. */ 585 sc_vtb_erase(&scp->vtb, r->tr_begin.tp_row * scp->xsize, 586 (r->tr_end.tp_row - r->tr_begin.tp_row) * scp->xsize, 587 map[ch], attr); 588 } else { 589 /* Fill display line by line. */ 590 width = r->tr_end.tp_col - r->tr_begin.tp_col; 591 592 for (row = r->tr_begin.tp_row; row < r->tr_end.tp_row; row++) { 593 sc_vtb_erase(&scp->vtb, r->tr_begin.tp_row * 594 scp->xsize + r->tr_begin.tp_col, 595 width, map[ch], attr); 596 } 597 } 598 599 /* Mark begin and end positions to be refreshed. */ 600 mark_for_update(scp, 601 r->tr_begin.tp_row * scp->xsize + r->tr_begin.tp_col); 602 mark_for_update(scp, 603 (r->tr_end.tp_row - 1) * scp->xsize + (r->tr_end.tp_col - 1)); 604 sc_remove_cutmarking(scp); 605} 606 607static void 608scteken_copy(void *arg, const teken_rect_t *r, const teken_pos_t *p) 609{ 610 scr_stat *scp = arg; 611 unsigned int width; 612 int src, dst, end; 613 614#ifndef SC_NO_HISTORY 615 /* 616 * We count a line of input as history if we perform a copy of 617 * one whole line upward. In other words: if a line of text gets 618 * overwritten by a rectangle that's right below it. 619 */ 620 if (scp->history != NULL && 621 r->tr_begin.tp_col == 0 && r->tr_end.tp_col == scp->xsize && 622 r->tr_begin.tp_row == p->tp_row + 1) { 623 sc_hist_save_one_line(scp, p->tp_row); 624 } 625#endif 626 627 if (r->tr_begin.tp_col == 0 && r->tr_end.tp_col == scp->xsize) { 628 /* Single contiguous region to copy. */ 629 sc_vtb_move(&scp->vtb, r->tr_begin.tp_row * scp->xsize, 630 p->tp_row * scp->xsize, 631 (r->tr_end.tp_row - r->tr_begin.tp_row) * scp->xsize); 632 } else { 633 /* Copy line by line. */ 634 width = r->tr_end.tp_col - r->tr_begin.tp_col; 635 636 if (p->tp_row < r->tr_begin.tp_row) { 637 /* Copy from top to bottom. */ 638 src = r->tr_begin.tp_row * scp->xsize + 639 r->tr_begin.tp_col; 640 end = r->tr_end.tp_row * scp->xsize + 641 r->tr_end.tp_col; 642 dst = p->tp_row * scp->xsize + p->tp_col; 643 644 while (src < end) { 645 sc_vtb_move(&scp->vtb, src, dst, width); 646 647 src += scp->xsize; 648 dst += scp->xsize; 649 } 650 } else { 651 /* Copy from bottom to top. */ 652 src = (r->tr_end.tp_row - 1) * scp->xsize + 653 r->tr_begin.tp_col; 654 end = r->tr_begin.tp_row * scp->xsize + 655 r->tr_begin.tp_col; 656 dst = (p->tp_row + r->tr_end.tp_row - 657 r->tr_begin.tp_row - 1) * scp->xsize + p->tp_col; 658 659 while (src >= end) { 660 sc_vtb_move(&scp->vtb, src, dst, width); 661 662 src -= scp->xsize; 663 dst -= scp->xsize; 664 } 665 } 666 } 667 668 /* Mark begin and end positions to be refreshed. */ 669 mark_for_update(scp, 670 p->tp_row * scp->xsize + p->tp_col); 671 mark_for_update(scp, 672 (p->tp_row + r->tr_end.tp_row - r->tr_begin.tp_row - 1) * 673 scp->xsize + 674 (p->tp_col + r->tr_end.tp_col - r->tr_begin.tp_col - 1)); 675 sc_remove_cutmarking(scp); 676} 677 678static void 679scteken_param(void *arg, int cmd, unsigned int value) 680{ 681 scr_stat *scp = arg; 682 683 switch (cmd) { 684 case TP_SHOWCURSOR: 685 if (value) { 686 sc_change_cursor_shape(scp, 687 CONS_RESET_CURSOR|CONS_LOCAL_CURSOR, -1, -1); 688 } else { 689 sc_change_cursor_shape(scp, 690 CONS_HIDDEN_CURSOR|CONS_LOCAL_CURSOR, -1, -1); 691 } 692 break; 693 case TP_SWITCHVT: 694 sc_switch_scr(scp->sc, value); 695 break; 696 case TP_SETBELLPD: 697 scp->bell_pitch = TP_SETBELLPD_PITCH(value); 698 scp->bell_duration = TP_SETBELLPD_DURATION(value); 699 break; 700 case TP_MOUSE: 701 scp->mouse_level = value; 702 break; 703 } 704} 705 706static void 707scteken_respond(void *arg, const void *buf, size_t len) 708{ 709 scr_stat *scp = arg; 710 711 sc_respond(scp, buf, len, 0); 712}
|