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