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