1 /*- 2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 3 * Copyright (c) 1992-1998 S�ren Schmidt 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer as 11 * the first lines of this file unmodified. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 */ 29 30 #include "opt_syscons.h" 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/kernel.h> 35 #include <sys/consio.h> 36 37 #include <machine/pc/display.h> 38 39 #include <dev/syscons/syscons.h> 40 #include <dev/syscons/sctermvar.h> 41 42 #ifndef SC_DUMB_TERMINAL 43 44 #define MAX_ESC_PAR 5 45 46 /* attribute flags */ 47 typedef struct { 48 u_short fg; /* foreground color */ 49 u_short bg; /* background color */ 50 } color_t; 51 52 typedef struct { 53 int flags; 54 #define SCTERM_BUSY (1 << 0) 55 int esc; 56 int num_param; 57 int last_param; 58 int param[MAX_ESC_PAR]; 59 int saved_xpos; 60 int saved_ypos; 61 int attr_mask; /* current logical attr mask */ 62 #define NORMAL_ATTR 0x00 63 #define BLINK_ATTR 0x01 64 #define BOLD_ATTR 0x02 65 #define UNDERLINE_ATTR 0x04 66 #define REVERSE_ATTR 0x08 67 #define FG_CHANGED 0x10 68 #define BG_CHANGED 0x20 69 int cur_attr; /* current hardware attr word */ 70 color_t cur_color; /* current hardware color */ 71 color_t std_color; /* normal hardware color */ 72 color_t rev_color; /* reverse hardware color */ 73 color_t dflt_std_color; /* default normal color */ 74 color_t dflt_rev_color; /* default reverse color */ 75 } term_stat; 76 77 static sc_term_init_t scterm_init; 78 static sc_term_term_t scterm_term; 79 static sc_term_puts_t scterm_puts; 80 static sc_term_ioctl_t scterm_ioctl; 81 static sc_term_reset_t scterm_reset; 82 static sc_term_default_attr_t scterm_default_attr; 83 static sc_term_clear_t scterm_clear; 84 static sc_term_notify_t scterm_notify; 85 static sc_term_input_t scterm_input; 86 87 static sc_term_sw_t sc_term_sc = { 88 { NULL, NULL }, 89 "sc", /* emulator name */ 90 "syscons terminal", /* description */ 91 "*", /* matching renderer, any :-) */ 92 sizeof(term_stat), /* softc size */ 93 0, 94 scterm_init, 95 scterm_term, 96 scterm_puts, 97 scterm_ioctl, 98 scterm_reset, 99 scterm_default_attr, 100 scterm_clear, 101 scterm_notify, 102 scterm_input, 103 }; 104 105 SCTERM_MODULE(sc, sc_term_sc); 106 107 static term_stat reserved_term_stat; 108 static void scterm_scan_esc(scr_stat *scp, term_stat *tcp, 109 u_char c); 110 static int mask2attr(term_stat *tcp); 111 112 static int 113 scterm_init(scr_stat *scp, void **softc, int code) 114 { 115 term_stat *tcp; 116 117 if (*softc == NULL) { 118 if (reserved_term_stat.flags & SCTERM_BUSY) 119 return EINVAL; 120 *softc = &reserved_term_stat; 121 } 122 tcp = *softc; 123 124 switch (code) { 125 case SC_TE_COLD_INIT: 126 bzero(tcp, sizeof(*tcp)); 127 tcp->flags = SCTERM_BUSY; 128 tcp->esc = 0; 129 tcp->saved_xpos = -1; 130 tcp->saved_ypos = -1; 131 tcp->attr_mask = NORMAL_ATTR; 132 /* XXX */ 133 tcp->dflt_std_color.fg = SC_NORM_ATTR & 0x0f; 134 tcp->dflt_std_color.bg = (SC_NORM_ATTR >> 4) & 0x0f; 135 tcp->dflt_rev_color.fg = SC_NORM_REV_ATTR & 0x0f; 136 tcp->dflt_rev_color.bg = (SC_NORM_REV_ATTR >> 4) & 0x0f; 137 tcp->std_color = tcp->dflt_std_color; 138 tcp->rev_color = tcp->dflt_rev_color; 139 tcp->cur_color = tcp->std_color; 140 tcp->cur_attr = mask2attr(tcp); 141 ++sc_term_sc.te_refcount; 142 break; 143 144 case SC_TE_WARM_INIT: 145 tcp->esc = 0; 146 tcp->saved_xpos = -1; 147 tcp->saved_ypos = -1; 148 #if 0 149 tcp->std_color = tcp->dflt_std_color; 150 tcp->rev_color = tcp->dflt_rev_color; 151 #endif 152 tcp->cur_color = tcp->std_color; 153 tcp->cur_attr = mask2attr(tcp); 154 break; 155 } 156 157 return 0; 158 } 159 160 static int 161 scterm_term(scr_stat *scp, void **softc) 162 { 163 if (*softc == &reserved_term_stat) { 164 *softc = NULL; 165 bzero(&reserved_term_stat, sizeof(reserved_term_stat)); 166 } 167 --sc_term_sc.te_refcount; 168 return 0; 169 } 170 171 static void 172 scterm_scan_esc(scr_stat *scp, term_stat *tcp, u_char c) 173 { 174 static u_char ansi_col[16] = { 175 #ifdef __alpha__ 176 /* 177 * DEC is evil. They switch the red and blue attributes in 178 * the palette in the system console. As a simple work-around, 179 * re-map the ANSI colors appropriately. 180 */ 181 FG_BLACK, FG_BLUE, FG_GREEN, FG_CYAN, 182 FG_RED, FG_MAGENTA, FG_BROWN, FG_LIGHTGREY, 183 FG_DARKGREY, FG_LIGHTBLUE, FG_LIGHTGREEN, FG_LIGHTCYAN, 184 FG_LIGHTRED, FG_LIGHTMAGENTA, FG_YELLOW, FG_WHITE 185 #else 186 FG_BLACK, FG_RED, FG_GREEN, FG_BROWN, 187 FG_BLUE, FG_MAGENTA, FG_CYAN, FG_LIGHTGREY, 188 FG_DARKGREY, FG_LIGHTRED, FG_LIGHTGREEN, FG_YELLOW, 189 FG_LIGHTBLUE, FG_LIGHTMAGENTA, FG_LIGHTCYAN, FG_WHITE 190 #endif 191 }; 192 static int cattrs[] = { 193 0, /* block */ 194 CONS_BLINK_CURSOR, /* blinking block */ 195 CONS_CHAR_CURSOR, /* underline */ 196 CONS_CHAR_CURSOR | CONS_BLINK_CURSOR, /* blinking underline */ 197 CONS_RESET_CURSOR, /* reset to default */ 198 CONS_HIDDEN_CURSOR, /* hide cursor */ 199 }; 200 static int tcattrs[] = { 201 CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, /* normal */ 202 CONS_HIDDEN_CURSOR | CONS_LOCAL_CURSOR, /* invisible */ 203 CONS_BLINK_CURSOR | CONS_LOCAL_CURSOR, /* very visible */ 204 }; 205 sc_softc_t *sc; 206 int v0, v1, v2; 207 int i, n; 208 209 i = n = 0; 210 sc = scp->sc; 211 if (tcp->esc == 1) { /* seen ESC */ 212 switch (c) { 213 214 case '7': /* Save cursor position */ 215 tcp->saved_xpos = scp->xpos; 216 tcp->saved_ypos = scp->ypos; 217 break; 218 219 case '8': /* Restore saved cursor position */ 220 if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0) 221 sc_move_cursor(scp, tcp->saved_xpos, 222 tcp->saved_ypos); 223 break; 224 225 case '[': /* Start ESC [ sequence */ 226 tcp->esc = 2; 227 tcp->last_param = -1; 228 for (i = tcp->num_param; i < MAX_ESC_PAR; i++) 229 tcp->param[i] = 1; 230 tcp->num_param = 0; 231 return; 232 233 case 'M': /* Move cursor up 1 line, scroll if at top */ 234 sc_term_up_scroll(scp, 1, sc->scr_map[0x20], 235 tcp->cur_attr, 0, 0); 236 break; 237 #if notyet 238 case 'Q': 239 tcp->esc = 4; 240 return; 241 #endif 242 case 'c': /* reset */ 243 tcp->attr_mask = NORMAL_ATTR; 244 tcp->cur_color = tcp->std_color 245 = tcp->dflt_std_color; 246 tcp->rev_color = tcp->dflt_rev_color; 247 tcp->cur_attr = mask2attr(tcp); 248 sc_change_cursor_shape(scp, 249 CONS_RESET_CURSOR | CONS_LOCAL_CURSOR, -1, -1); 250 sc_clear_screen(scp); 251 break; 252 253 case '(': /* iso-2022: designate 94 character set to G0 */ 254 tcp->esc = 5; 255 return; 256 } 257 } else if (tcp->esc == 2) { /* seen ESC [ */ 258 if (c >= '0' && c <= '9') { 259 if (tcp->num_param < MAX_ESC_PAR) { 260 if (tcp->last_param != tcp->num_param) { 261 tcp->last_param = tcp->num_param; 262 tcp->param[tcp->num_param] = 0; 263 } else { 264 tcp->param[tcp->num_param] *= 10; 265 } 266 tcp->param[tcp->num_param] += c - '0'; 267 return; 268 } 269 } 270 tcp->num_param = tcp->last_param + 1; 271 switch (c) { 272 273 case ';': 274 if (tcp->num_param < MAX_ESC_PAR) 275 return; 276 break; 277 278 case '=': 279 tcp->esc = 3; 280 tcp->last_param = -1; 281 for (i = tcp->num_param; i < MAX_ESC_PAR; i++) 282 tcp->param[i] = 1; 283 tcp->num_param = 0; 284 return; 285 286 case 'A': /* up n rows */ 287 sc_term_up(scp, tcp->param[0], 0); 288 break; 289 290 case 'B': /* down n rows */ 291 sc_term_down(scp, tcp->param[0], 0); 292 break; 293 294 case 'C': /* right n columns */ 295 sc_term_right(scp, tcp->param[0]); 296 break; 297 298 case 'D': /* left n columns */ 299 sc_term_left(scp, tcp->param[0]); 300 break; 301 302 case 'E': /* cursor to start of line n lines down */ 303 n = tcp->param[0]; 304 if (n < 1) 305 n = 1; 306 sc_move_cursor(scp, 0, scp->ypos + n); 307 break; 308 309 case 'F': /* cursor to start of line n lines up */ 310 n = tcp->param[0]; 311 if (n < 1) 312 n = 1; 313 sc_move_cursor(scp, 0, scp->ypos - n); 314 break; 315 316 case 'f': /* Cursor move */ 317 case 'H': 318 if (tcp->num_param == 0) 319 sc_move_cursor(scp, 0, 0); 320 else if (tcp->num_param == 2) 321 sc_move_cursor(scp, tcp->param[1] - 1, 322 tcp->param[0] - 1); 323 break; 324 325 case 'J': /* Clear all or part of display */ 326 if (tcp->num_param == 0) 327 n = 0; 328 else 329 n = tcp->param[0]; 330 sc_term_clr_eos(scp, n, sc->scr_map[0x20], 331 tcp->cur_attr); 332 break; 333 334 case 'K': /* Clear all or part of line */ 335 if (tcp->num_param == 0) 336 n = 0; 337 else 338 n = tcp->param[0]; 339 sc_term_clr_eol(scp, n, sc->scr_map[0x20], 340 tcp->cur_attr); 341 break; 342 343 case 'L': /* Insert n lines */ 344 sc_term_ins_line(scp, scp->ypos, tcp->param[0], 345 sc->scr_map[0x20], tcp->cur_attr, 0); 346 break; 347 348 case 'M': /* Delete n lines */ 349 sc_term_del_line(scp, scp->ypos, tcp->param[0], 350 sc->scr_map[0x20], tcp->cur_attr, 0); 351 break; 352 353 case 'P': /* Delete n chars */ 354 sc_term_del_char(scp, tcp->param[0], 355 sc->scr_map[0x20], tcp->cur_attr); 356 break; 357 358 case '@': /* Insert n chars */ 359 sc_term_ins_char(scp, tcp->param[0], 360 sc->scr_map[0x20], tcp->cur_attr); 361 break; 362 363 case 'S': /* scroll up n lines */ 364 sc_term_del_line(scp, 0, tcp->param[0], 365 sc->scr_map[0x20], tcp->cur_attr, 0); 366 break; 367 368 case 'T': /* scroll down n lines */ 369 sc_term_ins_line(scp, 0, tcp->param[0], 370 sc->scr_map[0x20], tcp->cur_attr, 0); 371 break; 372 373 case 'X': /* erase n characters in line */ 374 n = tcp->param[0]; 375 if (n < 1) 376 n = 1; 377 if (n > scp->xsize - scp->xpos) 378 n = scp->xsize - scp->xpos; 379 sc_vtb_erase(&scp->vtb, scp->cursor_pos, n, 380 sc->scr_map[0x20], tcp->cur_attr); 381 mark_for_update(scp, scp->cursor_pos); 382 mark_for_update(scp, scp->cursor_pos + n - 1); 383 break; 384 385 case 'Z': /* move n tabs backwards */ 386 sc_term_backtab(scp, tcp->param[0]); 387 break; 388 389 case '`': /* move cursor to column n */ 390 sc_term_col(scp, tcp->param[0]); 391 break; 392 393 case 'a': /* move cursor n columns to the right */ 394 sc_term_right(scp, tcp->param[0]); 395 break; 396 397 case 'd': /* move cursor to row n */ 398 sc_term_row(scp, tcp->param[0]); 399 break; 400 401 case 'e': /* move cursor n rows down */ 402 sc_term_down(scp, tcp->param[0], 0); 403 break; 404 405 case 'm': /* change attribute */ 406 if (tcp->num_param == 0) { 407 tcp->attr_mask = NORMAL_ATTR; 408 tcp->cur_color = tcp->std_color; 409 tcp->cur_attr = mask2attr(tcp); 410 break; 411 } 412 for (i = 0; i < tcp->num_param; i++) { 413 switch (n = tcp->param[i]) { 414 case 0: /* back to normal */ 415 tcp->attr_mask = NORMAL_ATTR; 416 tcp->cur_color = tcp->std_color; 417 tcp->cur_attr = mask2attr(tcp); 418 break; 419 case 1: /* bold */ 420 tcp->attr_mask |= BOLD_ATTR; 421 tcp->cur_attr = mask2attr(tcp); 422 break; 423 case 4: /* underline */ 424 tcp->attr_mask |= UNDERLINE_ATTR; 425 tcp->cur_attr = mask2attr(tcp); 426 break; 427 case 5: /* blink */ 428 tcp->attr_mask |= BLINK_ATTR; 429 tcp->cur_attr = mask2attr(tcp); 430 break; 431 case 7: /* reverse */ 432 tcp->attr_mask |= REVERSE_ATTR; 433 tcp->cur_attr = mask2attr(tcp); 434 break; 435 case 22: /* remove bold (or dim) */ 436 tcp->attr_mask &= ~BOLD_ATTR; 437 tcp->cur_attr = mask2attr(tcp); 438 break; 439 case 24: /* remove underline */ 440 tcp->attr_mask &= ~UNDERLINE_ATTR; 441 tcp->cur_attr = mask2attr(tcp); 442 break; 443 case 25: /* remove blink */ 444 tcp->attr_mask &= ~BLINK_ATTR; 445 tcp->cur_attr = mask2attr(tcp); 446 break; 447 case 27: /* remove reverse */ 448 tcp->attr_mask &= ~REVERSE_ATTR; 449 tcp->cur_attr = mask2attr(tcp); 450 break; 451 case 30: case 31: /* set ansi fg color */ 452 case 32: case 33: case 34: 453 case 35: case 36: case 37: 454 tcp->attr_mask |= FG_CHANGED; 455 tcp->cur_color.fg = ansi_col[n - 30]; 456 tcp->cur_attr = mask2attr(tcp); 457 break; 458 case 39: /* restore fg color back to normal */ 459 tcp->attr_mask &= ~(FG_CHANGED|BOLD_ATTR); 460 tcp->cur_color.fg = tcp->std_color.fg; 461 tcp->cur_attr = mask2attr(tcp); 462 break; 463 case 40: case 41: /* set ansi bg color */ 464 case 42: case 43: case 44: 465 case 45: case 46: case 47: 466 tcp->attr_mask |= BG_CHANGED; 467 tcp->cur_color.bg = ansi_col[n - 40]; 468 tcp->cur_attr = mask2attr(tcp); 469 break; 470 case 49: /* restore bg color back to normal */ 471 tcp->attr_mask &= ~BG_CHANGED; 472 tcp->cur_color.bg = tcp->std_color.bg; 473 tcp->cur_attr = mask2attr(tcp); 474 break; 475 } 476 } 477 break; 478 479 case 's': /* Save cursor position */ 480 tcp->saved_xpos = scp->xpos; 481 tcp->saved_ypos = scp->ypos; 482 break; 483 484 case 'u': /* Restore saved cursor position */ 485 if (tcp->saved_xpos >= 0 && tcp->saved_ypos >= 0) 486 sc_move_cursor(scp, tcp->saved_xpos, 487 tcp->saved_ypos); 488 break; 489 490 case 'x': 491 if (tcp->num_param == 0) 492 n = 0; 493 else 494 n = tcp->param[0]; 495 switch (n) { 496 case 0: /* reset colors and attributes back to normal */ 497 tcp->attr_mask = NORMAL_ATTR; 498 tcp->cur_color = tcp->std_color 499 = tcp->dflt_std_color; 500 tcp->rev_color = tcp->dflt_rev_color; 501 tcp->cur_attr = mask2attr(tcp); 502 break; 503 case 1: /* set ansi background */ 504 tcp->attr_mask &= ~BG_CHANGED; 505 tcp->cur_color.bg = tcp->std_color.bg 506 = ansi_col[tcp->param[1] & 0x0f]; 507 tcp->cur_attr = mask2attr(tcp); 508 break; 509 case 2: /* set ansi foreground */ 510 tcp->attr_mask &= ~FG_CHANGED; 511 tcp->cur_color.fg = tcp->std_color.fg 512 = ansi_col[tcp->param[1] & 0x0f]; 513 tcp->cur_attr = mask2attr(tcp); 514 break; 515 case 3: /* set adapter attribute directly */ 516 tcp->attr_mask &= ~(FG_CHANGED | BG_CHANGED); 517 tcp->cur_color.fg = tcp->std_color.fg 518 = tcp->param[1] & 0x0f; 519 tcp->cur_color.bg = tcp->std_color.bg 520 = (tcp->param[1] >> 4) & 0x0f; 521 tcp->cur_attr = mask2attr(tcp); 522 break; 523 case 5: /* set ansi reverse background */ 524 tcp->rev_color.bg = ansi_col[tcp->param[1] & 0x0f]; 525 tcp->cur_attr = mask2attr(tcp); 526 break; 527 case 6: /* set ansi reverse foreground */ 528 tcp->rev_color.fg = ansi_col[tcp->param[1] & 0x0f]; 529 tcp->cur_attr = mask2attr(tcp); 530 break; 531 case 7: /* set adapter reverse attribute directly */ 532 tcp->rev_color.fg = tcp->param[1] & 0x0f; 533 tcp->rev_color.bg = (tcp->param[1] >> 4) & 0x0f; 534 tcp->cur_attr = mask2attr(tcp); 535 break; 536 } 537 break; 538 539 case 'z': /* switch to (virtual) console n */ 540 if (tcp->num_param == 1) 541 sc_switch_scr(sc, tcp->param[0]); 542 break; 543 } 544 } else if (tcp->esc == 3) { /* seen ESC [0-9]+ = */ 545 if (c >= '0' && c <= '9') { 546 if (tcp->num_param < MAX_ESC_PAR) { 547 if (tcp->last_param != tcp->num_param) { 548 tcp->last_param = tcp->num_param; 549 tcp->param[tcp->num_param] = 0; 550 } else { 551 tcp->param[tcp->num_param] *= 10; 552 } 553 tcp->param[tcp->num_param] += c - '0'; 554 return; 555 } 556 } 557 tcp->num_param = tcp->last_param + 1; 558 switch (c) { 559 560 case ';': 561 if (tcp->num_param < MAX_ESC_PAR) 562 return; 563 break; 564 565 case 'A': /* set display border color */ 566 if (tcp->num_param == 1) { 567 scp->border=tcp->param[0] & 0xff; 568 if (scp == sc->cur_scp) 569 sc_set_border(scp, scp->border); 570 } 571 break; 572 573 case 'B': /* set bell pitch and duration */ 574 if (tcp->num_param == 2) { 575 scp->bell_pitch = tcp->param[0]; 576 scp->bell_duration = 577 (tcp->param[1] * hz + 99) / 100; 578 } 579 break; 580 581 case 'C': /* set global/parmanent cursor type & shape */ 582 i = spltty(); 583 n = tcp->num_param; 584 v0 = tcp->param[0]; 585 v1 = tcp->param[1]; 586 v2 = tcp->param[2]; 587 switch (n) { 588 case 1: /* flags only */ 589 if (v0 < sizeof(cattrs)/sizeof(cattrs[0])) 590 v0 = cattrs[v0]; 591 else /* backward compatibility */ 592 v0 = cattrs[v0 & 0x3]; 593 sc_change_cursor_shape(scp, v0, -1, -1); 594 break; 595 case 2: 596 v2 = 0; 597 v0 &= 0x1f; /* backward compatibility */ 598 v1 &= 0x1f; 599 /* FALL THROUGH */ 600 case 3: /* base and height */ 601 if (v2 == 0) /* count from top */ 602 sc_change_cursor_shape(scp, -1, 603 scp->font_size - v1 - 1, 604 v1 - v0 + 1); 605 else if (v2 == 1) /* count from bottom */ 606 sc_change_cursor_shape(scp, -1, 607 v0, v1 - v0 + 1); 608 break; 609 } 610 splx(i); 611 break; 612 613 case 'F': /* set adapter foreground */ 614 if (tcp->num_param == 1) { 615 tcp->attr_mask &= ~FG_CHANGED; 616 tcp->cur_color.fg = tcp->std_color.fg 617 = tcp->param[0] & 0x0f; 618 tcp->cur_attr = mask2attr(tcp); 619 } 620 break; 621 622 case 'G': /* set adapter background */ 623 if (tcp->num_param == 1) { 624 tcp->attr_mask &= ~BG_CHANGED; 625 tcp->cur_color.bg = tcp->std_color.bg 626 = tcp->param[0] & 0x0f; 627 tcp->cur_attr = mask2attr(tcp); 628 } 629 break; 630 631 case 'H': /* set adapter reverse foreground */ 632 if (tcp->num_param == 1) { 633 tcp->rev_color.fg = tcp->param[0] & 0x0f; 634 tcp->cur_attr = mask2attr(tcp); 635 } 636 break; 637 638 case 'I': /* set adapter reverse background */ 639 if (tcp->num_param == 1) { 640 tcp->rev_color.bg = tcp->param[0] & 0x0f; 641 tcp->cur_attr = mask2attr(tcp); 642 } 643 break; 644 645 case 'S': /* set local/temporary cursor type & shape */ 646 i = spltty(); 647 n = tcp->num_param; 648 v0 = tcp->param[0]; 649 switch (n) { 650 case 0: 651 v0 = 0; 652 /* FALL THROUGH */ 653 case 1: 654 if (v0 < sizeof(tcattrs)/sizeof(tcattrs[0])) 655 sc_change_cursor_shape(scp, 656 tcattrs[v0], -1, -1); 657 break; 658 } 659 splx(i); 660 break; 661 } 662 #if notyet 663 } else if (tcp->esc == 4) { /* seen ESC Q */ 664 /* to be filled */ 665 #endif 666 } else if (tcp->esc == 5) { /* seen ESC ( */ 667 switch (c) { 668 case 'B': /* iso-2022: desginate ASCII into G0 */ 669 break; 670 /* other items to be filled */ 671 default: 672 break; 673 } 674 } 675 tcp->esc = 0; 676 } 677 678 static void 679 scterm_puts(scr_stat *scp, u_char *buf, int len) 680 { 681 term_stat *tcp; 682 683 tcp = scp->ts; 684 outloop: 685 scp->sc->write_in_progress++; 686 687 if (tcp->esc) { 688 scterm_scan_esc(scp, tcp, *buf); 689 buf++; 690 len--; 691 } else { 692 switch (*buf) { 693 case 0x1b: 694 tcp->esc = 1; 695 tcp->num_param = 0; 696 buf++; 697 len--; 698 break; 699 default: 700 sc_term_gen_print(scp, &buf, &len, tcp->cur_attr); 701 break; 702 } 703 } 704 705 sc_term_gen_scroll(scp, scp->sc->scr_map[0x20], tcp->cur_attr); 706 707 scp->sc->write_in_progress--; 708 if (len) 709 goto outloop; 710 } 711 712 static int 713 scterm_ioctl(scr_stat *scp, struct tty *tp, u_long cmd, caddr_t data, 714 int flag, struct thread *td) 715 { 716 term_stat *tcp = scp->ts; 717 vid_info_t *vi; 718 719 switch (cmd) { 720 case GIO_ATTR: /* get current attributes */ 721 /* FIXME: */ 722 *(int*)data = (tcp->cur_attr >> 8) & 0xff; 723 return 0; 724 case CONS_GETINFO: /* get current (virtual) console info */ 725 vi = (vid_info_t *)data; 726 if (vi->size != sizeof(struct vid_info)) 727 return EINVAL; 728 vi->mv_norm.fore = tcp->std_color.fg; 729 vi->mv_norm.back = tcp->std_color.bg; 730 vi->mv_rev.fore = tcp->rev_color.fg; 731 vi->mv_rev.back = tcp->rev_color.bg; 732 /* 733 * The other fields are filled by the upper routine. XXX 734 */ 735 return ENOIOCTL; 736 } 737 return ENOIOCTL; 738 } 739 740 static int 741 scterm_reset(scr_stat *scp, int code) 742 { 743 /* FIXME */ 744 return 0; 745 } 746 747 static void 748 scterm_default_attr(scr_stat *scp, int color, int rev_color) 749 { 750 term_stat *tcp = scp->ts; 751 752 tcp->dflt_std_color.fg = color & 0x0f; 753 tcp->dflt_std_color.bg = (color >> 4) & 0x0f; 754 tcp->dflt_rev_color.fg = rev_color & 0x0f; 755 tcp->dflt_rev_color.bg = (rev_color >> 4) & 0x0f; 756 tcp->std_color = tcp->dflt_std_color; 757 tcp->rev_color = tcp->dflt_rev_color; 758 tcp->cur_color = tcp->std_color; 759 tcp->cur_attr = mask2attr(tcp); 760 } 761 762 static void 763 scterm_clear(scr_stat *scp) 764 { 765 term_stat *tcp = scp->ts; 766 767 sc_move_cursor(scp, 0, 0); 768 sc_vtb_clear(&scp->vtb, scp->sc->scr_map[0x20], tcp->cur_attr); 769 mark_all(scp); 770 } 771 772 static void 773 scterm_notify(scr_stat *scp, int event) 774 { 775 switch (event) { 776 case SC_TE_NOTIFY_VTSWITCH_IN: 777 break; 778 case SC_TE_NOTIFY_VTSWITCH_OUT: 779 break; 780 } 781 } 782 783 static int 784 scterm_input(scr_stat *scp, int c, struct tty *tp) 785 { 786 return FALSE; 787 } 788 789 /* 790 * Calculate hardware attributes word using logical attributes mask and 791 * hardware colors 792 */ 793 794 /* FIXME */ 795 static int 796 mask2attr(term_stat *tcp) 797 { 798 int attr, mask = tcp->attr_mask; 799 800 if (mask & REVERSE_ATTR) { 801 attr = ((mask & FG_CHANGED) ? 802 tcp->cur_color.bg : tcp->rev_color.fg) | 803 (((mask & BG_CHANGED) ? 804 tcp->cur_color.fg : tcp->rev_color.bg) << 4); 805 } else 806 attr = tcp->cur_color.fg | (tcp->cur_color.bg << 4); 807 808 /* XXX: underline mapping for Hercules adapter can be better */ 809 if (mask & (BOLD_ATTR | UNDERLINE_ATTR)) 810 attr ^= 0x08; 811 if (mask & BLINK_ATTR) 812 attr ^= 0x80; 813 814 return (attr << 8); 815 } 816 817 #endif /* SC_DUMB_TERMINAL */ 818