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