1 /* $OpenBSD: wsemul_sun.c,v 1.23 2007/11/27 16:37:27 miod Exp $ */ 2 /* $NetBSD: wsemul_sun.c,v 1.11 2000/01/05 11:19:36 drochner Exp $ */ 3 4 /* 5 * Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by Christopher G. Demetriou 18 * for the NetBSD Project. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * This file implements a sun terminal personality for wscons. 36 * 37 * Derived from old rcons code. 38 * Color support from NetBSD's rcons color code, and wsemul_vt100. 39 */ 40 41 #ifndef SMALL_KERNEL 42 #define JUMP_SCROLL 43 #endif 44 45 #include <sys/param.h> 46 #include <sys/systm.h> 47 #include <sys/time.h> 48 #include <sys/malloc.h> 49 #include <sys/fcntl.h> 50 51 #include <dev/wscons/wsconsio.h> 52 #include <dev/wscons/wsdisplayvar.h> 53 #include <dev/wscons/wsemulvar.h> 54 #include <dev/wscons/wsksymdef.h> 55 #include <dev/wscons/ascii.h> 56 57 void *wsemul_sun_cnattach(const struct wsscreen_descr *, void *, 58 int, int, long); 59 void *wsemul_sun_attach(int, const struct wsscreen_descr *, 60 void *, int, int, void *, long); 61 void wsemul_sun_output(void *, const u_char *, u_int, int); 62 int wsemul_sun_translate(void *, keysym_t, const char **); 63 void wsemul_sun_detach(void *, u_int *, u_int *); 64 void wsemul_sun_resetop(void *, enum wsemul_resetops); 65 66 const struct wsemul_ops wsemul_sun_ops = { 67 "sun", 68 wsemul_sun_cnattach, 69 wsemul_sun_attach, 70 wsemul_sun_output, 71 wsemul_sun_translate, 72 wsemul_sun_detach, 73 wsemul_sun_resetop 74 }; 75 76 #define SUN_EMUL_STATE_NORMAL 0 /* normal processing */ 77 #define SUN_EMUL_STATE_HAVEESC 1 /* seen start of ctl seq */ 78 #define SUN_EMUL_STATE_CONTROL 2 /* processing ctl seq */ 79 80 #define SUN_EMUL_NARGS 2 /* max # of args to a command */ 81 82 struct wsemul_sun_emuldata { 83 const struct wsdisplay_emulops *emulops; 84 void *emulcookie; 85 void *cbcookie; 86 int scrcapabilities; 87 u_int nrows, ncols, crow, ccol; 88 long defattr; /* default attribute (rendition) */ 89 90 u_int state; /* processing state */ 91 u_int args[SUN_EMUL_NARGS]; /* command args, if CONTROL */ 92 int nargs; /* number of args */ 93 94 u_int scrolldist; /* distance to scroll */ 95 long curattr, bkgdattr; /* currently used attribute */ 96 long kernattr; /* attribute for kernel output */ 97 int attrflags, fgcol, bgcol; /* properties of curattr */ 98 99 #ifdef DIAGNOSTIC 100 int console; 101 #endif 102 }; 103 104 void wsemul_sun_init(struct wsemul_sun_emuldata *, 105 const struct wsscreen_descr *, void *, int, int, long); 106 void wsemul_sun_jump_scroll(struct wsemul_sun_emuldata *, const u_char *, 107 u_int, int); 108 void wsemul_sun_reset(struct wsemul_sun_emuldata *); 109 void wsemul_sun_output_lowchars(struct wsemul_sun_emuldata *, u_char, int); 110 void wsemul_sun_output_normal(struct wsemul_sun_emuldata *, u_char, int); 111 u_int wsemul_sun_output_haveesc(struct wsemul_sun_emuldata *, u_char); 112 u_int wsemul_sun_output_control(struct wsemul_sun_emuldata *, u_char); 113 void wsemul_sun_control(struct wsemul_sun_emuldata *, u_char); 114 int wsemul_sun_selectattribute(struct wsemul_sun_emuldata *, int, int, int, 115 long *, long *); 116 void wsemul_sun_scrollup(struct wsemul_sun_emuldata *, u_int); 117 118 struct wsemul_sun_emuldata wsemul_sun_console_emuldata; 119 120 /* some useful utility macros */ 121 #define ARG(n,c) \ 122 ((n) >= edp->nargs ? 0 : edp->args[(n) + MAX(0, edp->nargs - (c))]) 123 #define NORMALIZE(arg) ((arg) != 0 ? (arg) : 1) 124 #define COLS_LEFT (edp->ncols - 1 - edp->ccol) 125 #define ROWS_LEFT (edp->nrows - 1 - edp->crow) 126 127 void 128 wsemul_sun_init(struct wsemul_sun_emuldata *edp, 129 const struct wsscreen_descr *type, void *cookie, int ccol, int crow, 130 long defattr) 131 { 132 edp->emulops = type->textops; 133 edp->emulcookie = cookie; 134 edp->scrcapabilities = type->capabilities; 135 edp->nrows = type->nrows; 136 edp->ncols = type->ncols; 137 edp->crow = crow; 138 edp->ccol = ccol; 139 edp->defattr = defattr; 140 } 141 142 void 143 wsemul_sun_reset(struct wsemul_sun_emuldata *edp) 144 { 145 edp->state = SUN_EMUL_STATE_NORMAL; 146 edp->bkgdattr = edp->curattr = edp->defattr; 147 edp->attrflags = 0; 148 edp->fgcol = WSCOL_BLACK; 149 edp->bgcol = WSCOL_WHITE; 150 edp->scrolldist = 1; 151 } 152 153 void * 154 wsemul_sun_cnattach(const struct wsscreen_descr *type, void *cookie, int ccol, 155 int crow, long defattr) 156 { 157 struct wsemul_sun_emuldata *edp; 158 int res; 159 160 edp = &wsemul_sun_console_emuldata; 161 wsemul_sun_init(edp, type, cookie, ccol, crow, defattr); 162 163 #ifndef WS_KERNEL_FG 164 #define WS_KERNEL_FG WSCOL_BLACK 165 #endif 166 #ifndef WS_KERNEL_BG 167 #define WS_KERNEL_BG WSCOL_WHITE 168 #endif 169 #ifndef WS_KERNEL_COLATTR 170 #define WS_KERNEL_COLATTR 0 171 #endif 172 #ifndef WS_KERNEL_MONOATTR 173 #define WS_KERNEL_MONOATTR 0 174 #endif 175 if (type->capabilities & WSSCREEN_WSCOLORS) 176 res = (*edp->emulops->alloc_attr)(cookie, 177 WS_KERNEL_FG, WS_KERNEL_BG, 178 WS_KERNEL_COLATTR | WSATTR_WSCOLORS, 179 &edp->kernattr); 180 else 181 res = (*edp->emulops->alloc_attr)(cookie, 0, 0, 182 WS_KERNEL_MONOATTR, 183 &edp->kernattr); 184 if (res) 185 edp->kernattr = defattr; 186 187 edp->cbcookie = NULL; 188 189 #ifdef DIAGNOSTIC 190 edp->console = 1; 191 #endif 192 193 wsemul_sun_reset(edp); 194 return (edp); 195 } 196 197 void * 198 wsemul_sun_attach(int console, const struct wsscreen_descr *type, void *cookie, 199 int ccol, int crow, void *cbcookie, long defattr) 200 { 201 struct wsemul_sun_emuldata *edp; 202 203 if (console) { 204 edp = &wsemul_sun_console_emuldata; 205 #ifdef DIAGNOSTIC 206 KASSERT(edp->console == 1); 207 #endif 208 } else { 209 edp = malloc(sizeof *edp, M_DEVBUF, M_NOWAIT); 210 if (edp == NULL) 211 return (NULL); 212 wsemul_sun_init(edp, type, cookie, ccol, crow, defattr); 213 214 #ifdef DIAGNOSTIC 215 edp->console = 0; 216 #endif 217 } 218 219 edp->cbcookie = cbcookie; 220 221 wsemul_sun_reset(edp); 222 return (edp); 223 } 224 225 void 226 wsemul_sun_output_lowchars(struct wsemul_sun_emuldata *edp, u_char c, 227 int kernel) 228 { 229 u_int n; 230 231 switch (c) { 232 case ASCII_NUL: 233 default: 234 /* ignore */ 235 break; 236 237 case ASCII_BEL: /* "Bell (BEL)" */ 238 wsdisplay_emulbell(edp->cbcookie); 239 break; 240 241 case ASCII_BS: /* "Backspace (BS)" */ 242 if (edp->ccol > 0) 243 edp->ccol--; 244 break; 245 246 case ASCII_CR: /* "Return (CR)" */ 247 edp->ccol = 0; 248 break; 249 250 case ASCII_HT: /* "Tab (TAB)" */ 251 n = min(8 - (edp->ccol & 7), COLS_LEFT); 252 if (n != 0) { 253 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 254 edp->ccol, n, 255 kernel ? edp->kernattr : edp->bkgdattr); 256 edp->ccol += n; 257 } 258 break; 259 260 case ASCII_FF: /* "Form Feed (FF)" */ 261 (*edp->emulops->eraserows)(edp->emulcookie, 0, edp->nrows, 262 edp->bkgdattr); 263 edp->ccol = edp->crow = 0; 264 break; 265 266 case ASCII_VT: /* "Reverse Line Feed" */ 267 if (edp->crow > 0) 268 edp->crow--; 269 break; 270 271 case ASCII_ESC: /* "Escape (ESC)" */ 272 if (kernel) { 273 printf("wsemul_sun_output_lowchars: ESC in kernel " 274 "output ignored\n"); 275 break; /* ignore the ESC */ 276 } 277 278 edp->state = SUN_EMUL_STATE_HAVEESC; 279 break; 280 281 case ASCII_LF: /* "Line Feed (LF)" */ 282 /* if the cur line isn't the last, incr and leave. */ 283 if (ROWS_LEFT > 0) 284 edp->crow++; 285 else 286 wsemul_sun_scrollup(edp, edp->scrolldist); 287 break; 288 } 289 } 290 291 void 292 wsemul_sun_output_normal(struct wsemul_sun_emuldata *edp, u_char c, int kernel) 293 { 294 295 (*edp->emulops->putchar)(edp->emulcookie, edp->crow, edp->ccol, 296 c, kernel ? edp->kernattr : edp->curattr); 297 298 if (++edp->ccol >= edp->ncols) { 299 /* if the cur line isn't the last, incr and leave. */ 300 if (ROWS_LEFT > 0) 301 edp->crow++; 302 else 303 wsemul_sun_scrollup(edp, edp->scrolldist); 304 edp->ccol = 0; 305 } 306 } 307 308 u_int 309 wsemul_sun_output_haveesc(struct wsemul_sun_emuldata *edp, u_char c) 310 { 311 u_int newstate; 312 313 switch (c) { 314 case '[': /* continuation of multi-char sequence */ 315 edp->nargs = 0; 316 bzero(edp->args, sizeof (edp->args)); 317 newstate = SUN_EMUL_STATE_CONTROL; 318 break; 319 320 default: 321 #ifdef DEBUG 322 printf("ESC%c unknown\n", c); 323 #endif 324 newstate = SUN_EMUL_STATE_NORMAL; /* XXX is this wise? */ 325 break; 326 } 327 328 return (newstate); 329 } 330 331 void 332 wsemul_sun_control(struct wsemul_sun_emuldata *edp, u_char c) 333 { 334 u_int n, src, dst; 335 int flags, fgcol, bgcol; 336 long attr, bkgdattr; 337 338 switch (c) { 339 case '@': /* "Insert Character (ICH)" */ 340 n = min(NORMALIZE(ARG(0,1)), COLS_LEFT + 1); 341 src = edp->ccol; 342 dst = edp->ccol + n; 343 if (dst < edp->ncols) { 344 (*edp->emulops->copycols)(edp->emulcookie, edp->crow, 345 src, dst, edp->ncols - dst); 346 } 347 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 348 src, n, edp->bkgdattr); 349 break; 350 351 case 'A': /* "Cursor Up (CUU)" */ 352 edp->crow -= min(NORMALIZE(ARG(0,1)), edp->crow); 353 break; 354 355 case 'E': /* "Cursor Next Line (CNL)" */ 356 edp->ccol = 0; 357 /* FALLTHROUGH */ 358 case 'B': /* "Cursor Down (CUD)" */ 359 edp->crow += min(NORMALIZE(ARG(0,1)), ROWS_LEFT); 360 break; 361 362 case 'C': /* "Cursor Forward (CUF)" */ 363 edp->ccol += min(NORMALIZE(ARG(0,1)), COLS_LEFT); 364 break; 365 366 case 'D': /* "Cursor Backward (CUB)" */ 367 edp->ccol -= min(NORMALIZE(ARG(0,1)), edp->ccol); 368 break; 369 370 case 'f': /* "Horizontal And Vertical Position (HVP)" */ 371 case 'H': /* "Cursor Position (CUP)" */ 372 edp->crow = min(NORMALIZE(ARG(0,2)), edp->nrows) - 1; 373 edp->ccol = min(NORMALIZE(ARG(1,2)), edp->ncols) - 1; 374 break; 375 376 case 'J': /* "Erase in Display (ED)" */ 377 if (ROWS_LEFT > 0) { 378 (*edp->emulops->eraserows)(edp->emulcookie, 379 edp->crow + 1, ROWS_LEFT, edp->bkgdattr); 380 } 381 /* FALLTHROUGH */ 382 case 'K': /* "Erase in Line (EL)" */ 383 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 384 edp->ccol, COLS_LEFT + 1, edp->bkgdattr); 385 break; 386 387 case 'L': /* "Insert Line (IL)" */ 388 n = min(NORMALIZE(ARG(0,1)), ROWS_LEFT + 1); 389 src = edp->crow; 390 dst = edp->crow + n; 391 if (dst < edp->nrows) { 392 (*edp->emulops->copyrows)(edp->emulcookie, 393 src, dst, edp->nrows - dst); 394 } 395 (*edp->emulops->eraserows)(edp->emulcookie, 396 src, n, edp->bkgdattr); 397 break; 398 399 case 'M': /* "Delete Line (DL)" */ 400 n = min(NORMALIZE(ARG(0,1)), ROWS_LEFT + 1); 401 src = edp->crow + n; 402 dst = edp->crow; 403 if (src < edp->nrows) { 404 (*edp->emulops->copyrows)(edp->emulcookie, 405 src, dst, edp->nrows - src); 406 } 407 (*edp->emulops->eraserows)(edp->emulcookie, 408 dst + edp->nrows - src, n, edp->bkgdattr); 409 break; 410 411 case 'P': /* "Delete Character (DCH)" */ 412 n = min(NORMALIZE(ARG(0,1)), COLS_LEFT + 1); 413 src = edp->ccol + n; 414 dst = edp->ccol; 415 if (src < edp->ncols) { 416 (*edp->emulops->copycols)(edp->emulcookie, edp->crow, 417 src, dst, edp->ncols - src); 418 } 419 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 420 edp->ncols - n, n, edp->bkgdattr); 421 break; 422 423 case 'm': /* "Select Graphic Rendition (SGR)" */ 424 flags = edp->attrflags; 425 fgcol = edp->fgcol; 426 bgcol = edp->bgcol; 427 428 for (n = 0; n < edp->nargs; n++) { 429 switch (ARG(n,edp->nargs)) { 430 /* Clear all attributes || End underline */ 431 case 0: 432 if (n == edp->nargs - 1) { 433 edp->bkgdattr = 434 edp->curattr = edp->defattr; 435 edp->attrflags = 0; 436 edp->fgcol = WSCOL_BLACK; 437 edp->bgcol = WSCOL_WHITE; 438 return; 439 } 440 flags = 0; 441 fgcol = WSCOL_BLACK; 442 bgcol = WSCOL_WHITE; 443 break; 444 /* Begin bold */ 445 case 1: 446 flags |= WSATTR_HILIT; 447 break; 448 /* Begin underline */ 449 case 4: 450 flags |= WSATTR_UNDERLINE; 451 break; 452 /* Begin reverse */ 453 case 7: 454 flags |= WSATTR_REVERSE; 455 break; 456 /* ANSI foreground color */ 457 case 30: case 31: case 32: case 33: 458 case 34: case 35: case 36: case 37: 459 fgcol = ARG(n,edp->nargs) - 30; 460 break; 461 /* ANSI background color */ 462 case 40: case 41: case 42: case 43: 463 case 44: case 45: case 46: case 47: 464 bgcol = ARG(n,edp->nargs) - 40; 465 break; 466 } 467 } 468 setattr: 469 if (wsemul_sun_selectattribute(edp, flags, fgcol, bgcol, &attr, 470 &bkgdattr)) { 471 #ifdef DEBUG 472 printf("error allocating attr %d/%d/%x\n", 473 fgcol, bgcol, flags); 474 #endif 475 } else { 476 edp->curattr = attr; 477 edp->bkgdattr = bkgdattr; 478 edp->attrflags = flags; 479 edp->fgcol = fgcol; 480 edp->bgcol = bgcol; 481 } 482 break; 483 484 case 'p': /* "Black On White (SUNBOW)" */ 485 flags = 0; 486 fgcol = WSCOL_BLACK; 487 bgcol = WSCOL_WHITE; 488 goto setattr; 489 490 case 'q': /* "White On Black (SUNWOB)" */ 491 flags = 0; 492 fgcol = WSCOL_WHITE; 493 bgcol = WSCOL_BLACK; 494 goto setattr; 495 496 case 'r': /* "Set Scrolling (SUNSCRL)" */ 497 edp->scrolldist = min(ARG(0,1), edp->nrows); 498 break; 499 500 case 's': /* "Reset Terminal Emulator (SUNRESET)" */ 501 wsemul_sun_reset(edp); 502 break; 503 } 504 } 505 506 u_int 507 wsemul_sun_output_control(struct wsemul_sun_emuldata *edp, u_char c) 508 { 509 u_int newstate = SUN_EMUL_STATE_CONTROL; 510 511 switch (c) { 512 case '0': case '1': case '2': case '3': case '4': /* argument digit */ 513 case '5': case '6': case '7': case '8': case '9': 514 /* 515 * If we receive more arguments than we are expecting, 516 * discard the earliest arguments. 517 */ 518 if (edp->nargs > SUN_EMUL_NARGS - 1) { 519 bcopy(edp->args + 1, edp->args, 520 (SUN_EMUL_NARGS - 1) * sizeof(edp->args[0])); 521 edp->args[edp->nargs = SUN_EMUL_NARGS - 1] = 0; 522 } 523 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) + 524 (c - '0'); 525 break; 526 527 case ';': /* argument terminator */ 528 edp->nargs++; 529 break; 530 531 default: /* end of escape sequence */ 532 edp->nargs++; 533 if (edp->nargs > SUN_EMUL_NARGS) 534 edp->nargs = SUN_EMUL_NARGS; 535 wsemul_sun_control(edp, c); 536 newstate = SUN_EMUL_STATE_NORMAL; 537 break; 538 } 539 return (newstate); 540 } 541 542 void 543 wsemul_sun_output(void *cookie, const u_char *data, u_int count, int kernel) 544 { 545 struct wsemul_sun_emuldata *edp = cookie; 546 u_int newstate; 547 548 #ifdef DIAGNOSTIC 549 if (kernel && !edp->console) 550 panic("wsemul_sun_output: kernel output, not console"); 551 #endif 552 553 /* XXX */ 554 (*edp->emulops->cursor)(edp->emulcookie, 0, edp->crow, edp->ccol); 555 556 for (; count > 0; data++, count--) { 557 #ifdef JUMP_SCROLL 558 /* 559 * If scrolling is not disabled and we are the bottom of 560 * the screen, count newlines until an escape sequence 561 * appears. 562 */ 563 if ((edp->state == SUN_EMUL_STATE_NORMAL || kernel) && 564 ROWS_LEFT == 0 && edp->scrolldist != 0) 565 wsemul_sun_jump_scroll(edp, data, count, kernel); 566 #endif 567 568 if (*data < ' ') { 569 wsemul_sun_output_lowchars(edp, *data, kernel); 570 continue; 571 } 572 573 if (kernel) { 574 wsemul_sun_output_normal(edp, *data, 1); 575 continue; 576 } 577 578 switch (newstate = edp->state) { 579 case SUN_EMUL_STATE_NORMAL: 580 wsemul_sun_output_normal(edp, *data, 0); 581 break; 582 case SUN_EMUL_STATE_HAVEESC: 583 newstate = wsemul_sun_output_haveesc(edp, *data); 584 break; 585 case SUN_EMUL_STATE_CONTROL: 586 newstate = wsemul_sun_output_control(edp, *data); 587 break; 588 default: 589 #ifdef DIAGNOSTIC 590 panic("wsemul_sun: invalid state %d", edp->state); 591 #else 592 /* try to recover, if things get screwed up... */ 593 newstate = SUN_EMUL_STATE_NORMAL; 594 wsemul_sun_output_normal(edp, *data, 0); 595 #endif 596 break; 597 } 598 edp->state = newstate; 599 } 600 /* XXX */ 601 (*edp->emulops->cursor)(edp->emulcookie, 1, edp->crow, edp->ccol); 602 } 603 604 #ifdef JUMP_SCROLL 605 void 606 wsemul_sun_jump_scroll(struct wsemul_sun_emuldata *edp, const u_char *data, 607 u_int count, int kernel) 608 { 609 u_char curchar; 610 u_int pos, lines; 611 612 lines = 0; 613 pos = edp->ccol; 614 for (; count != 0; data++, count--) { 615 curchar = *data; 616 if (curchar == ASCII_FF || 617 curchar == ASCII_VT || curchar == ASCII_ESC) 618 break; 619 620 switch (curchar) { 621 case ASCII_BS: 622 if (pos > 0) 623 pos--; 624 break; 625 case ASCII_CR: 626 pos = 0; 627 break; 628 case ASCII_HT: 629 pos = (pos + 7) & ~7; 630 if (pos >= edp->ncols) 631 pos = edp->ncols - 1; 632 break; 633 default: 634 if (++pos >= edp->ncols) { 635 pos = 0; 636 curchar = ASCII_LF; 637 } 638 break; 639 } 640 if (curchar == ASCII_LF) { 641 if (++lines >= edp->nrows - 1) 642 break; 643 } 644 } 645 646 if (lines > 1) { 647 wsemul_sun_scrollup(edp, lines); 648 edp->crow--; 649 } 650 } 651 #endif 652 653 /* 654 * Get an attribute from the graphics driver. 655 * Try to find replacements if the desired appearance is not supported. 656 */ 657 int 658 wsemul_sun_selectattribute(struct wsemul_sun_emuldata *edp, int flags, 659 int fgcol, int bgcol, long *attr, long *bkgdattr) 660 { 661 int error; 662 663 /* 664 * Rasops will force white on black as normal output colors, unless 665 * WSATTR_WSCOLORS is specified. Since Sun console is black on white, 666 * always use WSATTR_WSCOLORS and our colors, as we know better. 667 */ 668 if (!(edp->scrcapabilities & WSSCREEN_WSCOLORS)) { 669 flags &= ~WSATTR_WSCOLORS; 670 } else { 671 flags |= WSATTR_WSCOLORS; 672 } 673 674 error = (*edp->emulops->alloc_attr)(edp->emulcookie, fgcol, bgcol, 675 flags & WSATTR_WSCOLORS, bkgdattr); 676 if (error) 677 return (error); 678 679 if ((flags & WSATTR_HILIT) && 680 !(edp->scrcapabilities & WSSCREEN_HILIT)) { 681 flags &= ~WSATTR_HILIT; 682 if (edp->scrcapabilities & WSSCREEN_WSCOLORS) { 683 fgcol = WSCOL_RED; 684 flags |= WSATTR_WSCOLORS; 685 } 686 } 687 if ((flags & WSATTR_UNDERLINE) && 688 !(edp->scrcapabilities & WSSCREEN_UNDERLINE)) { 689 flags &= ~WSATTR_UNDERLINE; 690 if (edp->scrcapabilities & WSSCREEN_WSCOLORS) { 691 fgcol = WSCOL_CYAN; 692 flags &= ~WSATTR_UNDERLINE; 693 flags |= WSATTR_WSCOLORS; 694 } 695 } 696 if ((flags & WSATTR_BLINK) && 697 !(edp->scrcapabilities & WSSCREEN_BLINK)) { 698 flags &= ~WSATTR_BLINK; 699 } 700 if ((flags & WSATTR_REVERSE) && 701 !(edp->scrcapabilities & WSSCREEN_REVERSE)) { 702 flags &= ~WSATTR_REVERSE; 703 if (edp->scrcapabilities & WSSCREEN_WSCOLORS) { 704 int help; 705 help = bgcol; 706 bgcol = fgcol; 707 fgcol = help; 708 flags |= WSATTR_WSCOLORS; 709 } 710 } 711 error = (*edp->emulops->alloc_attr)(edp->emulcookie, fgcol, bgcol, 712 flags, attr); 713 if (error) 714 return (error); 715 716 return (0); 717 } 718 719 static const char *sun_fkeys[] = { 720 "\033[224z", /* F1 */ 721 "\033[225z", 722 "\033[226z", 723 "\033[227z", 724 "\033[228z", 725 "\033[229z", 726 "\033[230z", 727 "\033[231z", 728 "\033[232z", 729 "\033[233z", 730 "\033[234z", 731 "\033[235z", /* F12 */ 732 }; 733 734 static const char *sun_lkeys[] = { 735 "\033[207z", /* KS_Help */ 736 NULL, /* KS_Execute */ 737 "\033[200z", /* KS_Find */ 738 NULL, /* KS_Select */ 739 "\033[193z", /* KS_Again */ 740 "\033[194z", /* KS_Props */ 741 "\033[195z", /* KS_Undo */ 742 "\033[196z", /* KS_Front */ 743 "\033[197z", /* KS_Copy */ 744 "\033[198z", /* KS_Open */ 745 "\033[199z", /* KS_Paste */ 746 "\033[201z", /* KS_Cut */ 747 }; 748 749 int 750 wsemul_sun_translate(void *cookie, keysym_t in, const char **out) 751 { 752 static char c; 753 754 if (KS_GROUP(in) == KS_GROUP_Keypad && (in & 0x80) == 0) { 755 c = in & 0xff; /* turn into ASCII */ 756 *out = &c; 757 return (1); 758 } 759 760 if (in >= KS_f1 && in <= KS_f12) { 761 *out = sun_fkeys[in - KS_f1]; 762 return (6); 763 } 764 if (in >= KS_F1 && in <= KS_F12) { 765 *out = sun_fkeys[in - KS_F1]; 766 return (6); 767 } 768 if (in >= KS_KP_F1 && in <= KS_KP_F4) { 769 *out = sun_fkeys[in - KS_KP_F1]; 770 return (6); 771 } 772 if (in >= KS_Help && in <= KS_Cut && sun_lkeys[in - KS_Help] != NULL) { 773 *out = sun_lkeys[in - KS_Help]; 774 return (6); 775 } 776 777 switch (in) { 778 case KS_Home: 779 case KS_KP_Home: 780 case KS_KP_Begin: 781 *out = "\033[214z"; 782 return (6); 783 case KS_End: 784 case KS_KP_End: 785 *out = "\033[220z"; 786 return (6); 787 case KS_Insert: 788 case KS_KP_Insert: 789 *out = "\033[247z"; 790 return (6); 791 case KS_Prior: 792 case KS_KP_Prior: 793 *out = "\033[216z"; 794 return (6); 795 case KS_Next: 796 case KS_KP_Next: 797 *out = "\033[222z"; 798 return (6); 799 case KS_Up: 800 case KS_KP_Up: 801 *out = "\033[A"; 802 return (3); 803 case KS_Down: 804 case KS_KP_Down: 805 *out = "\033[B"; 806 return (3); 807 case KS_Left: 808 case KS_KP_Left: 809 *out = "\033[D"; 810 return (3); 811 case KS_Right: 812 case KS_KP_Right: 813 *out = "\033[C"; 814 return (3); 815 case KS_KP_Delete: 816 *out = "\177"; 817 return (1); 818 } 819 return (0); 820 } 821 822 void 823 wsemul_sun_detach(void *cookie, u_int *crowp, u_int *ccolp) 824 { 825 struct wsemul_sun_emuldata *edp = cookie; 826 827 *crowp = edp->crow; 828 *ccolp = edp->ccol; 829 if (edp != &wsemul_sun_console_emuldata) 830 free(edp, M_DEVBUF); 831 } 832 833 void 834 wsemul_sun_resetop(void *cookie, enum wsemul_resetops op) 835 { 836 struct wsemul_sun_emuldata *edp = cookie; 837 838 switch (op) { 839 case WSEMUL_RESET: 840 wsemul_sun_reset(edp); 841 break; 842 case WSEMUL_CLEARSCREEN: 843 (*edp->emulops->eraserows)(edp->emulcookie, 0, edp->nrows, 844 edp->bkgdattr); 845 edp->ccol = edp->crow = 0; 846 (*edp->emulops->cursor)(edp->emulcookie, 1, 0, 0); 847 break; 848 case WSEMUL_CLEARCURSOR: 849 (*edp->emulops->cursor)(edp->emulcookie, 0, 850 edp->crow, edp->ccol); 851 break; 852 default: 853 break; 854 } 855 } 856 857 void 858 wsemul_sun_scrollup(struct wsemul_sun_emuldata *edp, u_int lines) 859 { 860 /* 861 * if we're in wrap-around mode, go to the first 862 * line and clear it. 863 */ 864 if (lines == 0) { 865 edp->crow = 0; 866 (*edp->emulops->eraserows)(edp->emulcookie, 0, 1, 867 edp->bkgdattr); 868 return; 869 } 870 871 /* 872 * If the scrolling distance is equal to the screen height 873 * (usually 34), clear the screen; otherwise, scroll by the 874 * scrolling distance. 875 */ 876 if (lines < edp->nrows) 877 (*edp->emulops->copyrows)(edp->emulcookie, lines, 0, 878 edp->nrows - lines); 879 (*edp->emulops->eraserows)(edp->emulcookie, 880 edp->nrows - lines, lines, edp->bkgdattr); 881 edp->crow -= lines - 1; 882 } 883