scterm-sck.c revision 90465
1/*- 2 * Copyright (c) 1999 FreeBSD(98) Porting Team. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer as 10 * the first lines of this file unmodified. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $FreeBSD: head/sys/pc98/cbus/scterm-sck.c 90465 2002-02-10 10:15:41Z nyan $ 27 */ 28 29#include "opt_syscons.h" 30 31#include <sys/param.h> 32#include <sys/systm.h> 33#include <sys/kernel.h> 34#include <sys/consio.h> 35 36#include <machine/pc/display.h> 37 38#include <dev/syscons/syscons.h> 39#include <dev/syscons/sctermvar.h> 40 41#ifndef SC_DUMB_TERMINAL 42 43#define MAX_ESC_PAR 5 44 45#ifdef KANJI 46#define IS_KTYPE_ASCII_or_HANKAKU(A) (!((A) & 0xee)) 47#define IS_KTYPE_KANA(A) ((A) & 0x11) 48#define KTYPE_MASK_CTRL(A) ((A) &= 0xF0) 49#endif /* KANJI */ 50 51/* attribute flags */ 52typedef struct { 53 u_short fg; /* foreground color */ 54 u_short bg; /* background color */ 55} color_t; 56 57typedef struct { 58 int flags; 59#define SCTERM_BUSY (1 << 0) 60 int esc; 61 int num_param; 62 int last_param; 63 int param[MAX_ESC_PAR]; 64 int saved_xpos; 65 int saved_ypos; 66 67#ifdef KANJI 68 u_char kanji_1st_char; 69 u_char kanji_type; 70#define KTYPE_ASCII 0 /* ASCII */ 71#define KTYPE_KANA 1 /* HANKAKU */ 72#define KTYPE_JKANA 0x10 /* JIS HANKAKU */ 73#define KTYPE_7JIS 0x20 /* JIS */ 74#define KTYPE_SJIS 2 /* Shift JIS */ 75#define KTYPE_UJIS 4 /* UJIS */ 76#define KTYPE_SUKANA 3 /* Shift JIS or UJIS HANKAKU */ 77#define KTYPE_SUJIS 6 /* SHift JIS or UJIS */ 78#define KTYPE_KANIN 0x80 /* Kanji Invoke sequence */ 79#define KTYPE_ASCIN 0x40 /* ASCII Invoke sequence */ 80#endif /* KANJI */ 81 82 int attr_mask; /* current logical attr mask */ 83#define NORMAL_ATTR 0x00 84#define BLINK_ATTR 0x01 85#define BOLD_ATTR 0x02 86#define UNDERLINE_ATTR 0x04 87#define REVERSE_ATTR 0x08 88#define FG_CHANGED 0x10 89#define BG_CHANGED 0x20 90 int cur_attr; /* current hardware attr word */ 91 color_t cur_color; /* current hardware color */ 92 color_t std_color; /* normal hardware color */ 93 color_t rev_color; /* reverse hardware color */ 94 color_t dflt_std_color; /* default normal color */ 95 color_t dflt_rev_color; /* default reverse color */ 96} term_stat; 97 98static sc_term_init_t scterm_init; 99static sc_term_term_t scterm_term; 100static sc_term_puts_t scterm_puts; 101static sc_term_ioctl_t scterm_ioctl; 102static sc_term_reset_t scterm_reset; 103static sc_term_default_attr_t scterm_default_attr; 104static sc_term_clear_t scterm_clear; 105static sc_term_notify_t scterm_notify; 106static sc_term_input_t scterm_input; 107 108static sc_term_sw_t sc_term_sc = { 109 { NULL, NULL }, 110 "sck", /* emulator name */ 111 "syscons kanji terminal", /* description */ 112 "*", /* matching renderer, any :-) */ 113 sizeof(term_stat), /* softc size */ 114 0, 115 scterm_init, 116 scterm_term, 117 scterm_puts, 118 scterm_ioctl, 119 scterm_reset, 120 scterm_default_attr, 121 scterm_clear, 122 scterm_notify, 123 scterm_input, 124}; 125 126SCTERM_MODULE(sc, sc_term_sc); 127 128static term_stat reserved_term_stat; 129static int default_kanji = UJIS; 130static void scterm_scan_esc(scr_stat *scp, term_stat *tcp, 131 u_char c); 132static int mask2attr(term_stat *tcp); 133 134#ifdef KANJI 135__inline static u_char 136iskanji1(u_char mode, u_char c) 137{ 138 if (c > 0x80) { 139 if ((c >= 0xa1) && (c <= 0xdf)) { 140 if (default_kanji == UJIS) { 141 /* UJIS */ 142 return KTYPE_UJIS; 143 } 144 if (default_kanji == SJIS) { 145 /* SJIS HANKAKU */ 146 return KTYPE_KANA; 147 } 148 } 149 150 if (c <= 0x9f) { 151 if (c == 0x8e) { 152 /* SJIS or UJIS HANKAKU */ 153 return KTYPE_SUKANA; 154 } 155 156 /* SJIS */ 157 default_kanji = SJIS; 158 return KTYPE_SJIS; 159 } 160 161 if ((c >= 0xe0) && (c <= 0xef)) { 162 /* SJIS or UJIS */ 163 return KTYPE_SUJIS; 164 } 165 166 if ((c >= 0xf0) && (c <= 0xfe)) { 167 /* UJIS */ 168 default_kanji = UJIS; 169 return KTYPE_UJIS; 170 } 171 } else { 172 if ((mode == KTYPE_7JIS) && (c >= 0x21) && (c <= 0x7e)) { 173 /* JIS */ 174 default_kanji = UJIS; 175 return KTYPE_7JIS; 176 } 177 178 if ((mode == KTYPE_JKANA) && (c >= 0x21) && (c <= 0x5f)) { 179 /* JIS HANKAKU */ 180 default_kanji = UJIS; 181 return KTYPE_JKANA; 182 } 183 } 184 185 return KTYPE_ASCII; 186} 187 188__inline static u_char 189iskanji2(u_char mode, u_char c) 190{ 191 switch (mode) { 192 case KTYPE_7JIS: 193 if ((c >= 0x21) && (c <= 0x7e)) { 194 /* JIS */ 195 return KTYPE_7JIS; 196 } 197 break; 198 case KTYPE_SJIS: 199 if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) { 200 /* SJIS */ 201 return KTYPE_SJIS; 202 } 203 break; 204 case KTYPE_UJIS: 205 if ((c >= 0xa1) && (c <= 0xfe)) { 206 /* UJIS */ 207 return KTYPE_UJIS; 208 } 209 break; 210 case KTYPE_SUKANA: 211 if ((c >= 0xa1) && (c <= 0xdf) && (default_kanji == UJIS)) { 212 /* UJIS HANKAKU */ 213 return KTYPE_KANA; 214 } 215 if ((c >= 0x40) && (c <= 0xfc) && (c != 0x7f)) { 216 /* SJIS */ 217 default_kanji = SJIS; 218 return KTYPE_SJIS; 219 } 220 break; 221 case KTYPE_SUJIS: 222 if ((c >= 0x40) && (c <= 0xa0) && (c != 0x7f)) { 223 /* SJIS */ 224 default_kanji = SJIS; 225 return KTYPE_SJIS; 226 } 227 if ((c == 0xfd) || (c == 0xfe)) { 228 /* UJIS */ 229 default_kanji = UJIS; 230 return KTYPE_UJIS; 231 } 232 if ((c >= 0xa1) && (c <= 0xfc)) { 233 if (default_kanji == SJIS) 234 return KTYPE_SJIS; 235 if (default_kanji == UJIS) 236 return KTYPE_UJIS; 237 } 238 break; 239 } 240 return KTYPE_ASCII; 241} 242 243/* 244 * JIS X0208-83 keisen conversion table 245 */ 246static u_short keiConv[32] = { 247 0x240c, 0x260c, 0x300c, 0x340c, 0x3c0c, 0x380c, 0x400c, 0x500c, 248 0x480c, 0x580c, 0x600c, 0x250c, 0x270c, 0x330c, 0x370c, 0x3f0c, 249 0x3b0c, 0x470c, 0x570c, 0x4f0c, 0x5f0c, 0x6f0c, 0x440c, 0x530c, 250 0x4c0c, 0x5b0c, 0x630c, 0x410c, 0x540c, 0x490c, 0x5c0c, 0x660c 251}; 252 253static u_short 254kanji_convert(u_char mode, u_char h, u_char l) 255{ 256 u_short tmp, high, low, c; 257 high = (u_short) h; 258 low = (u_short) l; 259 260 switch (mode) { 261 case KTYPE_SJIS: /* SHIFT JIS */ 262 if (low >= 0xe0) { 263 low -= 0x40; 264 } 265 low = (low - 0x81) * 2 + 0x21; 266 if (high > 0x7f) { 267 high--; 268 } 269 if (high > 0x9d) { 270 low++; 271 high -= 0x9e - 0x21; 272 } else { 273 high -= 0x40 - 0x21; 274 } 275 high &= 0x7F; 276 low &= 0x7F; 277 tmp = ((high << 8) | low) - 0x20; 278 break; 279 case KTYPE_7JIS: /* JIS */ 280 case KTYPE_UJIS: /* UJIS */ 281 high &= 0x7F; 282 low &= 0x7F; 283 tmp = ((high << 8) | low) - 0x20; 284 break; 285 default: 286 tmp = 0; 287 break; 288 } 289 290 /* keisen */ 291 c = ((tmp & 0xff) << 8) | (tmp >> 8); 292 /* 0x2821 .. 0x2840 */ 293 if (0x0821 <= c && c <= 0x0840) 294 tmp = keiConv[c - 0x0821]; 295 296 return (tmp); 297} 298#endif /* KANJI */ 299 300static int 301scterm_init(scr_stat *scp, void **softc, int code) 302{ 303 term_stat *tcp; 304 305 if (*softc == NULL) { 306 if (reserved_term_stat.flags & SCTERM_BUSY) 307 return EINVAL; 308 *softc = &reserved_term_stat; 309 } 310 tcp = *softc; 311 312 switch (code) { 313 case SC_TE_COLD_INIT: 314 bzero(tcp, sizeof(*tcp)); 315 tcp->flags = SCTERM_BUSY; 316 tcp->esc = 0; 317 tcp->saved_xpos = -1; 318 tcp->saved_ypos = -1; 319#ifdef KANJI 320 tcp->kanji_1st_char = 0; 321 tcp->kanji_type = KTYPE_ASCII; 322#endif 323 tcp->attr_mask = NORMAL_ATTR; 324 /* XXX */ 325 tcp->dflt_std_color.fg = SC_NORM_ATTR & 0x0f; 326 tcp->dflt_std_color.bg = (SC_NORM_ATTR >> 4) & 0x0f; 327 tcp->dflt_rev_color.fg = SC_NORM_REV_ATTR & 0x0f; 328 tcp->dflt_rev_color.bg = (SC_NORM_REV_ATTR >> 4) & 0x0f; 329 tcp->std_color = tcp->dflt_std_color; 330 tcp->rev_color = tcp->dflt_rev_color; 331 tcp->cur_color = tcp->std_color; 332 tcp->cur_attr = mask2attr(tcp); 333 ++sc_term_sc.te_refcount; 334 break; 335 336 case SC_TE_WARM_INIT: 337 tcp->esc = 0; 338 tcp->saved_xpos = -1; 339 tcp->saved_ypos = -1; 340#if 0 341 tcp->std_color = tcp->dflt_std_color; 342 tcp->rev_color = tcp->dflt_rev_color; 343#endif 344 tcp->cur_color = tcp->std_color; 345 tcp->cur_attr = mask2attr(tcp); 346 break; 347 } 348 349 return 0; 350} 351 352static int 353scterm_term(scr_stat *scp, void **softc) 354{ 355 if (*softc == &reserved_term_stat) { 356 *softc = NULL; 357 bzero(&reserved_term_stat, sizeof(reserved_term_stat)); 358 } 359 --sc_term_sc.te_refcount; 360 return 0; 361} 362 363static void 364scterm_scan_esc(scr_stat *scp, term_stat *tcp, u_char c) 365{ 366 static u_char ansi_col[16] = { 367 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, 368 FG_BLUE, FG_MAGENTA, FG_CYAN, FG_LIGHTGREY, 369 FG_DARKGREY, FG_LIGHTRED, FG_LIGHTGREEN, FG_YELLOW, 370 FG_LIGHTBLUE, FG_LIGHTMAGENTA, FG_LIGHTCYAN, FG_WHITE 371 }; 372 static int cattrs[] = { 373 0, /* block */ 374 CONS_BLINK_CURSOR, /* blinking block */ 375 CONS_CHAR_CURSOR, /* underline */ 376 CONS_CHAR_CURSOR | CONS_BLINK_CURSOR, /* blinking underline */ 377 CONS_RESET_CURSOR, /* reset to default */ 378 CONS_HIDDEN_CURSOR, /* hide cursor */ 379 }; 380 static int tcattrs[] = { 381 CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, /* normal */ 382 CONS_HIDDEN_CURSOR | CONS_LOCAL_CURSOR, /* invisible */ 383 CONS_BLINK_CURSOR | CONS_LOCAL_CURSOR, /* very visible */ 384 }; 385 sc_softc_t *sc; 386 int v0, v1, v2; 387 int i, n; 388 389 i = n = 0; 390 sc = scp->sc; 391 if (tcp->esc == 1) { /* seen ESC */ 392#ifdef KANJI 393 switch (tcp->kanji_type) { 394 case KTYPE_KANIN: /* Kanji Invoke sequence */ 395 switch (c) { 396 case 'B': 397 case '@': 398 tcp->kanji_type = KTYPE_7JIS; 399 tcp->esc = 0; 400 tcp->kanji_1st_char = 0; 401 return; 402 default: 403 tcp->kanji_type = KTYPE_ASCII; 404 tcp->esc = 0; 405 break; 406 } 407 break; 408 case KTYPE_ASCIN: /* Ascii Invoke sequence */ 409 switch (c) { 410 case 'J': 411 case 'B': 412 case 'H': 413 tcp->kanji_type = KTYPE_ASCII; 414 tcp->esc = 0; 415 tcp->kanji_1st_char = 0; 416 return; 417 case 'I': 418 tcp->kanji_type = KTYPE_JKANA; 419 tcp->esc = 0; 420 tcp->kanji_1st_char = 0; 421 return; 422 default: 423 tcp->kanji_type = KTYPE_ASCII; 424 tcp->esc = 0; 425 break; 426 } 427 break; 428 default: 429 break; 430 } 431#endif 432 switch (c) { 433 434 case '7': /* Save cursor position */ 435 tcp->saved_xpos = scp->xpos; 436 tcp->saved_ypos = scp->ypos; 437 break; 438 439 case '8': /* Restore saved cursor position */ 440 if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0) 441 sc_move_cursor(scp, tcp->saved_xpos, 442 tcp->saved_ypos); 443 break; 444 445 case '[': /* Start ESC [ sequence */ 446 tcp->esc = 2; 447 tcp->last_param = -1; 448 for (i = tcp->num_param; i < MAX_ESC_PAR; i++) 449 tcp->param[i] = 1; 450 tcp->num_param = 0; 451 return; 452 453#ifdef KANJI 454 case '$': /* Kanji Invoke sequence */ 455 tcp->kanji_type = KTYPE_KANIN; 456 return; 457#endif 458 459 case 'M': /* Move cursor up 1 line, scroll if at top */ 460 sc_term_up_scroll(scp, 1, sc->scr_map[0x20], 461 tcp->cur_attr, 0, 0); 462 break; 463#if notyet 464 case 'Q': 465 tcp->esc = 4; 466 return; 467#endif 468 case 'c': /* reset */ 469 tcp->attr_mask = NORMAL_ATTR; 470 tcp->cur_color = tcp->std_color 471 = tcp->dflt_std_color; 472 tcp->rev_color = tcp->dflt_rev_color; 473 tcp->cur_attr = mask2attr(tcp); 474 sc_change_cursor_shape(scp, 475 CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, -1, -1); 476 sc_clear_screen(scp); 477 break; 478 479 case '(': /* iso-2022: designate 94 character set to G0 */ 480#ifdef KANJI 481 tcp->kanji_type = KTYPE_ASCIN; 482#else 483 tcp->esc = 5; 484#endif 485 return; 486 } 487 } else if (tcp->esc == 2) { /* seen ESC [ */ 488 if (c >= '0' && c <= '9') { 489 if (tcp->num_param < MAX_ESC_PAR) { 490 if (tcp->last_param != tcp->num_param) { 491 tcp->last_param = tcp->num_param; 492 tcp->param[tcp->num_param] = 0; 493 } else { 494 tcp->param[tcp->num_param] *= 10; 495 } 496 tcp->param[tcp->num_param] += c - '0'; 497 return; 498 } 499 } 500 tcp->num_param = tcp->last_param + 1; 501 switch (c) { 502 503 case ';': 504 if (tcp->num_param < MAX_ESC_PAR) 505 return; 506 break; 507 508 case '=': 509 tcp->esc = 3; 510 tcp->last_param = -1; 511 for (i = tcp->num_param; i < MAX_ESC_PAR; i++) 512 tcp->param[i] = 1; 513 tcp->num_param = 0; 514 return; 515 516 case 'A': /* up n rows */ 517 sc_term_up(scp, tcp->param[0], 0); 518 break; 519 520 case 'B': /* down n rows */ 521 sc_term_down(scp, tcp->param[0], 0); 522 break; 523 524 case 'C': /* right n columns */ 525 sc_term_right(scp, tcp->param[0]); 526 break; 527 528 case 'D': /* left n columns */ 529 sc_term_left(scp, tcp->param[0]); 530 break; 531 532 case 'E': /* cursor to start of line n lines down */ 533 n = tcp->param[0]; 534 if (n < 1) 535 n = 1; 536 sc_move_cursor(scp, 0, scp->ypos + n); 537 break; 538 539 case 'F': /* cursor to start of line n lines up */ 540 n = tcp->param[0]; 541 if (n < 1) 542 n = 1; 543 sc_move_cursor(scp, 0, scp->ypos - n); 544 break; 545 546 case 'f': /* Cursor move */ 547 case 'H': 548 if (tcp->num_param == 0) 549 sc_move_cursor(scp, 0, 0); 550 else if (tcp->num_param == 2) 551 sc_move_cursor(scp, tcp->param[1] - 1, 552 tcp->param[0] - 1); 553 break; 554 555 case 'J': /* Clear all or part of display */ 556 if (tcp->num_param == 0) 557 n = 0; 558 else 559 n = tcp->param[0]; 560 sc_term_clr_eos(scp, n, sc->scr_map[0x20], 561 tcp->cur_attr); 562 break; 563 564 case 'K': /* Clear all or part of line */ 565 if (tcp->num_param == 0) 566 n = 0; 567 else 568 n = tcp->param[0]; 569 sc_term_clr_eol(scp, n, sc->scr_map[0x20], 570 tcp->cur_attr); 571 break; 572 573 case 'L': /* Insert n lines */ 574 sc_term_ins_line(scp, scp->ypos, tcp->param[0], 575 sc->scr_map[0x20], tcp->cur_attr, 0); 576 break; 577 578 case 'M': /* Delete n lines */ 579 sc_term_del_line(scp, scp->ypos, tcp->param[0], 580 sc->scr_map[0x20], tcp->cur_attr, 0); 581 break; 582 583 case 'P': /* Delete n chars */ 584 sc_term_del_char(scp, tcp->param[0], 585 sc->scr_map[0x20], tcp->cur_attr); 586 break; 587 588 case '@': /* Insert n chars */ 589 sc_term_ins_char(scp, tcp->param[0], 590 sc->scr_map[0x20], tcp->cur_attr); 591 break; 592 593 case 'S': /* scroll up n lines */ 594 sc_term_del_line(scp, 0, tcp->param[0], 595 sc->scr_map[0x20], tcp->cur_attr, 0); 596 break; 597 598 case 'T': /* scroll down n lines */ 599 sc_term_ins_line(scp, 0, tcp->param[0], 600 sc->scr_map[0x20], tcp->cur_attr, 0); 601 break; 602 603 case 'X': /* erase n characters in line */ 604 n = tcp->param[0]; 605 if (n < 1) 606 n = 1; 607 if (n > scp->xsize - scp->xpos) 608 n = scp->xsize - scp->xpos; 609 sc_vtb_erase(&scp->vtb, scp->cursor_pos, n, 610 sc->scr_map[0x20], tcp->cur_attr); 611 mark_for_update(scp, scp->cursor_pos); 612 mark_for_update(scp, scp->cursor_pos + n - 1); 613 break; 614 615 case 'Z': /* move n tabs backwards */ 616 sc_term_backtab(scp, tcp->param[0]); 617 break; 618 619 case '`': /* move cursor to column n */ 620 sc_term_col(scp, tcp->param[0]); 621 break; 622 623 case 'a': /* move cursor n columns to the right */ 624 sc_term_right(scp, tcp->param[0]); 625 break; 626 627 case 'd': /* move cursor to row n */ 628 sc_term_row(scp, tcp->param[0]); 629 break; 630 631 case 'e': /* move cursor n rows down */ 632 sc_term_down(scp, tcp->param[0], 0); 633 break; 634 635 case 'm': /* change attribute */ 636 if (tcp->num_param == 0) { 637 tcp->attr_mask = NORMAL_ATTR; 638 tcp->cur_color = tcp->std_color; 639 tcp->cur_attr = mask2attr(tcp); 640 break; 641 } 642 for (i = 0; i < tcp->num_param; i++) { 643 switch (n = tcp->param[i]) { 644 case 0: /* back to normal */ 645 tcp->attr_mask = NORMAL_ATTR; 646 tcp->cur_color = tcp->std_color; 647 tcp->cur_attr = mask2attr(tcp); 648 break; 649 case 1: /* bold */ 650 tcp->attr_mask |= BOLD_ATTR; 651 tcp->cur_attr = mask2attr(tcp); 652 break; 653 case 4: /* underline */ 654 tcp->attr_mask |= UNDERLINE_ATTR; 655 tcp->cur_attr = mask2attr(tcp); 656 break; 657 case 5: /* blink */ 658 tcp->attr_mask |= BLINK_ATTR; 659 tcp->cur_attr = mask2attr(tcp); 660 break; 661 case 7: /* reverse */ 662 tcp->attr_mask |= REVERSE_ATTR; 663 tcp->cur_attr = mask2attr(tcp); 664 break; 665 case 22: /* remove bold (or dim) */ 666 tcp->attr_mask &= ~BOLD_ATTR; 667 tcp->cur_attr = mask2attr(tcp); 668 break; 669 case 24: /* remove underline */ 670 tcp->attr_mask &= ~UNDERLINE_ATTR; 671 tcp->cur_attr = mask2attr(tcp); 672 break; 673 case 25: /* remove blink */ 674 tcp->attr_mask &= ~BLINK_ATTR; 675 tcp->cur_attr = mask2attr(tcp); 676 break; 677 case 27: /* remove reverse */ 678 tcp->attr_mask &= ~REVERSE_ATTR; 679 tcp->cur_attr = mask2attr(tcp); 680 break; 681 case 30: case 31: /* set ansi fg color */ 682 case 32: case 33: case 34: 683 case 35: case 36: case 37: 684 tcp->attr_mask |= FG_CHANGED; 685 tcp->cur_color.fg = ansi_col[n - 30]; 686 tcp->cur_attr = mask2attr(tcp); 687 break; 688 case 39: /* restore fg color back to normal */ 689 tcp->attr_mask &= ~(FG_CHANGED|BOLD_ATTR); 690 tcp->cur_color.fg = tcp->std_color.fg; 691 tcp->cur_attr = mask2attr(tcp); 692 break; 693 case 40: case 41: /* set ansi bg color */ 694 case 42: case 43: case 44: 695 case 45: case 46: case 47: 696 tcp->attr_mask |= BG_CHANGED; 697 tcp->cur_color.bg = ansi_col[n - 40]; 698 tcp->cur_attr = mask2attr(tcp); 699 break; 700 case 49: /* restore bg color back to normal */ 701 tcp->attr_mask &= ~BG_CHANGED; 702 tcp->cur_color.bg = tcp->std_color.bg; 703 tcp->cur_attr = mask2attr(tcp); 704 break; 705 } 706 } 707 break; 708 709 case 's': /* Save cursor position */ 710 tcp->saved_xpos = scp->xpos; 711 tcp->saved_ypos = scp->ypos; 712 break; 713 714 case 'u': /* Restore saved cursor position */ 715 if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0) 716 sc_move_cursor(scp, tcp->saved_xpos, 717 tcp->saved_ypos); 718 break; 719 720 case 'x': 721 if (tcp->num_param == 0) 722 n = 0; 723 else 724 n = tcp->param[0]; 725 switch (n) { 726 case 0: /* reset colors and attributes back to normal */ 727 tcp->attr_mask = NORMAL_ATTR; 728 tcp->cur_color = tcp->std_color 729 = tcp->dflt_std_color; 730 tcp->rev_color = tcp->dflt_rev_color; 731 tcp->cur_attr = mask2attr(tcp); 732 break; 733 case 1: /* set ansi background */ 734 tcp->attr_mask &= ~BG_CHANGED; 735 tcp->cur_color.bg = tcp->std_color.bg 736 = ansi_col[tcp->param[1] & 0x0f]; 737 tcp->cur_attr = mask2attr(tcp); 738 break; 739 case 2: /* set ansi foreground */ 740 tcp->attr_mask &= ~FG_CHANGED; 741 tcp->cur_color.fg = tcp->std_color.fg 742 = ansi_col[tcp->param[1] & 0x0f]; 743 tcp->cur_attr = mask2attr(tcp); 744 break; 745 case 3: /* set adapter attribute directly */ 746 tcp->attr_mask &= ~(FG_CHANGED | BG_CHANGED); 747 tcp->cur_color.fg = tcp->std_color.fg 748 = tcp->param[1] & 0x0f; 749 tcp->cur_color.bg = tcp->std_color.bg 750 = (tcp->param[1] >> 4) & 0x0f; 751 tcp->cur_attr = mask2attr(tcp); 752 break; 753 case 5: /* set ansi reverse background */ 754 tcp->rev_color.bg = ansi_col[tcp->param[1] & 0x0f]; 755 tcp->cur_attr = mask2attr(tcp); 756 break; 757 case 6: /* set ansi reverse foreground */ 758 tcp->rev_color.fg = ansi_col[tcp->param[1] & 0x0f]; 759 tcp->cur_attr = mask2attr(tcp); 760 break; 761 case 7: /* set adapter reverse attribute directly */ 762 tcp->rev_color.fg = tcp->param[1] & 0x0f; 763 tcp->rev_color.bg = (tcp->param[1] >> 4) & 0x0f; 764 tcp->cur_attr = mask2attr(tcp); 765 break; 766 } 767 break; 768 769 case 'z': /* switch to (virtual) console n */ 770 if (tcp->num_param == 1) 771 sc_switch_scr(sc, tcp->param[0]); 772 break; 773 } 774 } else if (tcp->esc == 3) { /* seen ESC [0-9]+ = */ 775 if (c >= '0' && c <= '9') { 776 if (tcp->num_param < MAX_ESC_PAR) { 777 if (tcp->last_param != tcp->num_param) { 778 tcp->last_param = tcp->num_param; 779 tcp->param[tcp->num_param] = 0; 780 } else { 781 tcp->param[tcp->num_param] *= 10; 782 } 783 tcp->param[tcp->num_param] += c - '0'; 784 return; 785 } 786 } 787 tcp->num_param = tcp->last_param + 1; 788 switch (c) { 789 790 case ';': 791 if (tcp->num_param < MAX_ESC_PAR) 792 return; 793 break; 794 795 case 'A': /* set display border color */ 796 if (tcp->num_param == 1) { 797 scp->border=tcp->param[0] & 0xff; 798 if (scp == sc->cur_scp) 799 sc_set_border(scp, scp->border); 800 } 801 break; 802 803 case 'B': /* set bell pitch and duration */ 804 if (tcp->num_param == 2) { 805 scp->bell_pitch = tcp->param[0]; 806 scp->bell_duration = 807 (tcp->param[1] * hz + 99) / 100; 808 } 809 break; 810 811 case 'C': /* set global/parmanent cursor type & shape */ 812 i = spltty(); 813 n = tcp->num_param; 814 v0 = tcp->param[0]; 815 v1 = tcp->param[1]; 816 v2 = tcp->param[2]; 817 switch (n) { 818 case 1: /* flags only */ 819 if (v0 < sizeof(cattrs)/sizeof(cattrs[0])) 820 v0 = cattrs[v0]; 821 else /* backward compatibility */ 822 v0 = cattrs[v0 & 0x3]; 823 sc_change_cursor_shape(scp, v0, -1, -1); 824 break; 825 case 2: 826 v2 = 0; 827 v0 &= 0x1f; /* backward compatibility */ 828 v1 &= 0x1f; 829 /* FALL THROUGH */ 830 case 3: /* base and height */ 831 if (v2 == 0) /* count from top */ 832 sc_change_cursor_shape(scp, -1, 833 scp->font_size - v1 - 1, 834 v1 - v0 + 1); 835 else if (v2 == 1) /* count from bottom */ 836 sc_change_cursor_shape(scp, -1, 837 v0, v1 - v0 + 1); 838 break; 839 } 840 splx(i); 841 break; 842 843 case 'F': /* set adapter foreground */ 844 if (tcp->num_param == 1) { 845 tcp->attr_mask &= ~FG_CHANGED; 846 tcp->cur_color.fg = tcp->std_color.fg 847 = tcp->param[0] & 0x0f; 848 tcp->cur_attr = mask2attr(tcp); 849 } 850 break; 851 852 case 'G': /* set adapter background */ 853 if (tcp->num_param == 1) { 854 tcp->attr_mask &= ~BG_CHANGED; 855 tcp->cur_color.bg = tcp->std_color.bg 856 = tcp->param[0] & 0x0f; 857 tcp->cur_attr = mask2attr(tcp); 858 } 859 break; 860 861 case 'H': /* set adapter reverse foreground */ 862 if (tcp->num_param == 1) { 863 tcp->rev_color.fg = tcp->param[0] & 0x0f; 864 tcp->cur_attr = mask2attr(tcp); 865 } 866 break; 867 868 case 'I': /* set adapter reverse background */ 869 if (tcp->num_param == 1) { 870 tcp->rev_color.bg = tcp->param[0] & 0x0f; 871 tcp->cur_attr = mask2attr(tcp); 872 } 873 break; 874 875 case 'S': /* set local/temporary cursor type & shape */ 876 i = spltty(); 877 n = tcp->num_param; 878 v0 = tcp->param[0]; 879 switch (n) { 880 case 0: 881 v0 = 0; 882 /* FALL THROUGH */ 883 case 1: 884 if (v0 < sizeof(tcattrs)/sizeof(tcattrs[0])) 885 sc_change_cursor_shape(scp, 886 tcattrs[v0], -1, -1); 887 break; 888 } 889 splx(i); 890 break; 891 } 892#if notyet 893 } else if (tcp->esc == 4) { /* seen ESC Q */ 894 /* to be filled */ 895#endif 896 } else if (tcp->esc == 5) { /* seen ESC ( */ 897 switch (c) { 898 case 'B': /* iso-2022: desginate ASCII into G0 */ 899 break; 900 /* other items to be filled */ 901 default: 902 break; 903 } 904 } 905 tcp->esc = 0; 906} 907 908static void 909scterm_puts(scr_stat *scp, u_char *buf, int len) 910{ 911 term_stat *tcp; 912 u_char *ptr; 913#ifdef KANJI 914 u_short kanji_code; 915#endif 916 917 tcp = scp->ts; 918 ptr = buf; 919outloop: 920 scp->sc->write_in_progress++; 921 922 if (tcp->esc) { 923 scterm_scan_esc(scp, tcp, *ptr++); 924 len--; 925 } else if (PRINTABLE(*ptr)) { /* Print only printables */ 926 vm_offset_t p; 927 u_char *map; 928 int attr; 929 int i; 930 int cnt; 931#ifdef KANJI 932 u_char c; 933#endif 934 935 p = sc_vtb_pointer(&scp->vtb, scp->cursor_pos); 936 map = scp->sc->scr_map; 937 attr = tcp->cur_attr; 938 939#ifdef KANJI 940 c = *ptr; 941 if (tcp->kanji_1st_char == 0) { 942 tcp->kanji_type = iskanji1(tcp->kanji_type, c); 943 if (!IS_KTYPE_ASCII_or_HANKAKU(tcp->kanji_type)) { 944 /* not Ascii & not HANKAKU */ 945 tcp->kanji_1st_char = c; 946 goto kanji_end; 947 } else if (tcp->kanji_type == KTYPE_ASCII) { 948 cnt = imin(len, scp->xsize - scp->xpos); 949 i = cnt; 950 do { 951 p = sc_vtb_putchar(&scp->vtb, p, map[c], attr); 952 c = *++ptr; 953 --i; 954 } while (i > 0 && PRINTABLE(c) && 955 iskanji1(tcp->kanji_type, c) == KTYPE_ASCII); 956 957 len -= cnt - i; 958 mark_for_update(scp, scp->cursor_pos); 959 scp->cursor_pos += cnt - i; 960 mark_for_update(scp, scp->cursor_pos - 1); 961 scp->xpos += cnt - i; 962 KTYPE_MASK_CTRL(tcp->kanji_type); 963 goto ascii_end; 964 } 965 } else { 966 if ((tcp->kanji_type = 967 iskanji2(tcp->kanji_type, c)) & 0xee) { 968 /* print kanji on TEXT VRAM */ 969 kanji_code = kanji_convert(tcp->kanji_type, c, 970 tcp->kanji_1st_char); 971 mark_for_update(scp, scp->cursor_pos); 972 for (i = 0; i < 2; i++) { 973 /* *cursor_pos = (kanji_code | (i*0x80)); */ 974 p = sc_vtb_putchar(&scp->vtb, p, 975 kanji_code | ((i == 0) ? 0x00 : 0x80), attr); 976 ++scp->cursor_pos; 977 if (++scp->xpos >= scp->xsize) { 978 scp->xpos = 0; 979 scp->ypos++; 980 } 981 } 982 mark_for_update(scp, scp->cursor_pos - 1); 983 KTYPE_MASK_CTRL(tcp->kanji_type); 984 tcp->kanji_1st_char = 0; 985 goto kanji_end; 986 } else { 987 tcp->kanji_1st_char = 0; 988 } 989 } 990 if (IS_KTYPE_KANA(tcp->kanji_type)) 991 c |= 0x80; 992 KTYPE_MASK_CTRL(tcp->kanji_type); 993 sc_vtb_putchar(&scp->vtb, p, map[c], attr); 994 mark_for_update(scp, scp->cursor_pos); 995 mark_for_update(scp, scp->cursor_pos); 996 ++scp->cursor_pos; 997 ++scp->xpos; 998kanji_end: 999 ++ptr; 1000 --len; 1001ascii_end: 1002#else /* !KANJI */ 1003 cnt = imin(len, scp->xsize - scp->xpos); 1004 i = cnt; 1005 do { 1006 /* 1007 * gcc-2.6.3 generates poor (un)sign extension code. 1008 * Casting the pointers in the following to volatile should 1009 * have no effect, but in fact speeds up this inner loop 1010 * from 26 to 18 cycles (+ cache misses) on i486's. 1011 */ 1012#define UCVP(ucp) ((u_char volatile *)(ucp)) 1013 p = sc_vtb_putchar(&scp->vtb, p, UCVP(map)[*UCVP(ptr)], 1014 attr); 1015 ++ptr; 1016 --i; 1017 } while (i > 0 && PRINTABLE(*ptr)); 1018 1019 len -= cnt - i; 1020 mark_for_update(scp, scp->cursor_pos); 1021 scp->cursor_pos += cnt - i; 1022 mark_for_update(scp, scp->cursor_pos - 1); 1023 scp->xpos += cnt - i; 1024#endif /* !KANJI */ 1025 1026 if (scp->xpos >= scp->xsize) { 1027 scp->xpos = 0; 1028 scp->ypos++; 1029 } 1030 } else { 1031 switch (*ptr) { 1032 case 0x07: 1033 sc_bell(scp, scp->bell_pitch, scp->bell_duration); 1034 break; 1035 1036 case 0x08: /* non-destructive backspace */ 1037 if (scp->cursor_pos > 0) { 1038 mark_for_update(scp, scp->cursor_pos); 1039 scp->cursor_pos--; 1040 mark_for_update(scp, scp->cursor_pos); 1041 if (scp->xpos > 0) 1042 scp->xpos--; 1043 else { 1044 scp->xpos += scp->xsize - 1; 1045 scp->ypos--; 1046 } 1047 } 1048 break; 1049 1050 case 0x09: /* non-destructive tab */ 1051 mark_for_update(scp, scp->cursor_pos); 1052 scp->cursor_pos += (8 - scp->xpos % 8u); 1053 scp->xpos += (8 - scp->xpos % 8u); 1054 if (scp->xpos >= scp->xsize) { 1055 scp->xpos = 0; 1056 scp->ypos++; 1057 scp->cursor_pos = scp->xsize * scp->ypos; 1058 } 1059 mark_for_update(scp, scp->cursor_pos); 1060 break; 1061 1062 case 0x0a: /* newline, same pos */ 1063 mark_for_update(scp, scp->cursor_pos); 1064 scp->cursor_pos += scp->xsize; 1065 mark_for_update(scp, scp->cursor_pos); 1066 scp->ypos++; 1067 break; 1068 1069 case 0x0c: /* form feed, clears screen */ 1070 sc_clear_screen(scp); 1071 break; 1072 1073 case 0x0d: /* return, return to pos 0 */ 1074 mark_for_update(scp, scp->cursor_pos); 1075 scp->cursor_pos -= scp->xpos; 1076 mark_for_update(scp, scp->cursor_pos); 1077 scp->xpos = 0; 1078 break; 1079 1080#ifdef PC98 1081 case 0x0e: /* ^N */ 1082 tcp->kanji_type = KTYPE_JKANA; 1083 tcp->esc = 0; 1084 tcp->kanji_1st_char = 0; 1085 break; 1086 1087 case 0x0f: /* ^O */ 1088 tcp->kanji_type = KTYPE_ASCII; 1089 tcp->esc = 0; 1090 tcp->kanji_1st_char = 0; 1091 break; 1092#endif /* PC98 */ 1093 1094 case 0x1b: /* start escape sequence */ 1095 tcp->esc = 1; 1096 tcp->num_param = 0; 1097 break; 1098 } 1099 ptr++; 1100 len--; 1101 } 1102 1103 sc_term_gen_scroll(scp, scp->sc->scr_map[0x20], tcp->cur_attr); 1104 1105 scp->sc->write_in_progress--; 1106 if (len) 1107 goto outloop; 1108} 1109 1110static int 1111scterm_ioctl(scr_stat *scp, struct tty *tp, u_long cmd, caddr_t data, 1112 int flag, struct thread *td) 1113{ 1114 term_stat *tcp = scp->ts; 1115 vid_info_t *vi; 1116 1117 switch (cmd) { 1118 case GIO_ATTR: /* get current attributes */ 1119 /* FIXME: */ 1120 *(int*)data = (tcp->cur_attr >> 8) & 0xff; 1121 return 0; 1122 case CONS_GETINFO: /* get current (virtual) console info */ 1123 vi = (vid_info_t *)data; 1124 if (vi->size != sizeof(struct vid_info)) 1125 return EINVAL; 1126 vi->mv_norm.fore = tcp->std_color.fg; 1127 vi->mv_norm.back = tcp->std_color.bg; 1128 vi->mv_rev.fore = tcp->rev_color.fg; 1129 vi->mv_rev.back = tcp->rev_color.bg; 1130 /* 1131 * The other fields are filled by the upper routine. XXX 1132 */ 1133 return ENOIOCTL; 1134 } 1135 return ENOIOCTL; 1136} 1137 1138static int 1139scterm_reset(scr_stat *scp, int code) 1140{ 1141 /* FIXME */ 1142 return 0; 1143} 1144 1145static void 1146scterm_default_attr(scr_stat *scp, int color, int rev_color) 1147{ 1148 term_stat *tcp = scp->ts; 1149 1150 tcp->dflt_std_color.fg = color & 0x0f; 1151 tcp->dflt_std_color.bg = (color >> 4) & 0x0f; 1152 tcp->dflt_rev_color.fg = rev_color & 0x0f; 1153 tcp->dflt_rev_color.bg = (rev_color >> 4) & 0x0f; 1154 tcp->std_color = tcp->dflt_std_color; 1155 tcp->rev_color = tcp->dflt_rev_color; 1156 tcp->cur_color = tcp->std_color; 1157 tcp->cur_attr = mask2attr(tcp); 1158} 1159 1160static void 1161scterm_clear(scr_stat *scp) 1162{ 1163 term_stat *tcp = scp->ts; 1164 1165 sc_move_cursor(scp, 0, 0); 1166 sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], tcp->cur_attr); 1167 mark_all(scp); 1168} 1169 1170static void 1171scterm_notify(scr_stat *scp, int event) 1172{ 1173 switch (event) { 1174 case SC_TE_NOTIFY_VTSWITCH_IN: 1175 break; 1176 case SC_TE_NOTIFY_VTSWITCH_OUT: 1177 break; 1178 } 1179} 1180 1181static int 1182scterm_input(scr_stat *scp, int c, struct tty *tp) 1183{ 1184 return FALSE; 1185} 1186 1187/* 1188 * Calculate hardware attributes word using logical attributes mask and 1189 * hardware colors 1190 */ 1191 1192/* FIXME */ 1193static int 1194mask2attr(term_stat *tcp) 1195{ 1196 int attr, mask = tcp->attr_mask; 1197 1198 if (mask & REVERSE_ATTR) { 1199 attr = ((mask & FG_CHANGED) ? 1200 tcp->cur_color.bg : tcp->rev_color.fg) | 1201 (((mask & BG_CHANGED) ? 1202 tcp->cur_color.fg : tcp->rev_color.bg) << 4); 1203 } else 1204 attr = tcp->cur_color.fg | (tcp->cur_color.bg << 4); 1205 1206 /* XXX: underline mapping for Hercules adapter can be better */ 1207 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 1208 attr ^= 0x08; 1209 if (mask & BLINK_ATTR) 1210 attr ^= 0x80; 1211 1212 return (attr << 8); 1213} 1214 1215#endif /* SC_DUMB_TERMINAL */ 1216