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