1 /* $NetBSD: wsemul_vt100_subr.c,v 1.20 2010/02/10 19:39:39 drochner Exp $ */ 2 3 /* 4 * Copyright (c) 1998 5 * Matthias Drochner. 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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 29 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: wsemul_vt100_subr.c,v 1.20 2010/02/10 19:39:39 drochner Exp $"); 31 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 35 #include <dev/wscons/wsconsio.h> 36 #include <dev/wscons/wsksymvar.h> 37 #include <dev/wscons/wsdisplayvar.h> 38 #include <dev/wscons/wsemulvar.h> 39 #include <dev/wscons/vt100_base.h> 40 41 #include "opt_wsemul.h" 42 43 static int vt100_selectattribute(struct vt100base_data *, 44 int, int, int, long *, long *); 45 static int vt100_ansimode(struct vt100base_data *, int, int); 46 static int vt100_decmode(struct vt100base_data *, int, int); 47 #define VTMODE_SET 33 48 #define VTMODE_RESET 44 49 #define VTMODE_REPORT 55 50 51 /* 52 * scroll up within scrolling region 53 */ 54 void 55 wsemul_vt100_scrollup(struct vt100base_data *edp, int n) 56 { 57 int help; 58 59 if (n > edp->scrreg_nrows) 60 n = edp->scrreg_nrows; 61 62 help = edp->scrreg_nrows - n; 63 if (help > 0) { 64 (*edp->emulops->copyrows)(edp->emulcookie, 65 edp->scrreg_startrow + n, 66 edp->scrreg_startrow, 67 help); 68 if (edp->dblwid) 69 memmove(&edp->dblwid[edp->scrreg_startrow], 70 &edp->dblwid[edp->scrreg_startrow + n], 71 help); 72 } 73 (*edp->emulops->eraserows)(edp->emulcookie, 74 edp->scrreg_startrow + help, n, 75 edp->bkgdattr); 76 if (edp->dblwid) 77 memset(&edp->dblwid[edp->scrreg_startrow + help], 0, n); 78 CHECK_DW(edp); 79 } 80 81 /* 82 * scroll down within scrolling region 83 */ 84 void 85 wsemul_vt100_scrolldown(struct vt100base_data *edp, int n) 86 { 87 int help; 88 89 if (n > edp->scrreg_nrows) 90 n = edp->scrreg_nrows; 91 92 help = edp->scrreg_nrows - n; 93 if (help > 0) { 94 (*edp->emulops->copyrows)(edp->emulcookie, 95 edp->scrreg_startrow, 96 edp->scrreg_startrow + n, 97 help); 98 if (edp->dblwid) 99 memmove(&edp->dblwid[edp->scrreg_startrow + n], 100 &edp->dblwid[edp->scrreg_startrow], 101 help); 102 } 103 (*edp->emulops->eraserows)(edp->emulcookie, 104 edp->scrreg_startrow, n, 105 edp->bkgdattr); 106 if (edp->dblwid) 107 memset(&edp->dblwid[edp->scrreg_startrow], 0, n); 108 CHECK_DW(edp); 109 } 110 111 /* 112 * erase in display 113 */ 114 void 115 wsemul_vt100_ed(struct vt100base_data *edp, int arg) 116 { 117 int n; 118 119 switch (arg) { 120 case 0: /* cursor to end */ 121 ERASECOLS(edp, edp->ccol, COLS_LEFT(edp) + 1, edp->bkgdattr); 122 n = edp->nrows - edp->crow - 1; 123 if (n > 0) { 124 (*edp->emulops->eraserows)(edp->emulcookie, 125 edp->crow + 1, n, 126 edp->bkgdattr); 127 if (edp->dblwid) 128 memset(&edp->dblwid[edp->crow + 1], 0, n); 129 } 130 break; 131 case 1: /* beginning to cursor */ 132 if (edp->crow > 0) { 133 (*edp->emulops->eraserows)(edp->emulcookie, 134 0, edp->crow, 135 edp->bkgdattr); 136 if (edp->dblwid) 137 memset(&edp->dblwid[0], 0, edp->crow); 138 } 139 ERASECOLS(edp, 0, edp->ccol + 1, edp->bkgdattr); 140 break; 141 case 2: /* complete display */ 142 (*edp->emulops->eraserows)(edp->emulcookie, 143 0, edp->nrows, 144 edp->bkgdattr); 145 if (edp->dblwid) 146 memset(&edp->dblwid[0], 0, edp->nrows); 147 break; 148 default: 149 #ifdef VT100_PRINTUNKNOWN 150 printf("ed(%d) unknown\n", arg); 151 #endif 152 break; 153 } 154 CHECK_DW(edp); 155 } 156 157 /* 158 * erase in line 159 */ 160 void 161 wsemul_vt100_el(struct vt100base_data *edp, int arg) 162 { 163 switch (arg) { 164 case 0: /* cursor to end */ 165 ERASECOLS(edp, edp->ccol, COLS_LEFT(edp) + 1, edp->bkgdattr); 166 break; 167 case 1: /* beginning to cursor */ 168 ERASECOLS(edp, 0, edp->ccol + 1, edp->bkgdattr); 169 break; 170 case 2: /* complete line */ 171 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 172 0, edp->ncols, 173 edp->bkgdattr); 174 break; 175 default: 176 #ifdef VT100_PRINTUNKNOWN 177 printf("el(%d) unknown\n", arg); 178 #endif 179 break; 180 } 181 } 182 183 /* 184 * handle commands after CSI (ESC[) 185 */ 186 void 187 wsemul_vt100_handle_csi(struct vt100base_data *edp, u_char c) 188 { 189 int n, help, flags, fgcol, bgcol; 190 long attr, bkgdattr; 191 192 #define A3(a, b, c) (((a) << 16) | ((b) << 8) | (c)) 193 switch (A3(edp->modif1, edp->modif2, c)) { 194 case A3('>', '\0', 'c'): /* DA secondary */ 195 wsdisplay_emulinput(edp->cbcookie, WSEMUL_VT_ID2, 196 sizeof(WSEMUL_VT_ID2)); 197 break; 198 199 case A3('\0', '\0', 'J'): /* ED selective erase in display */ 200 case A3('?', '\0', 'J'): /* DECSED selective erase in display */ 201 wsemul_vt100_ed(edp, ARG(edp, 0)); 202 break; 203 case A3('\0', '\0', 'K'): /* EL selective erase in line */ 204 case A3('?', '\0', 'K'): /* DECSEL selective erase in line */ 205 wsemul_vt100_el(edp, ARG(edp, 0)); 206 break; 207 case A3('\0', '\0', 'h'): /* SM */ 208 for (n = 0; n < edp->nargs; n++) 209 vt100_ansimode(edp, ARG(edp, n), VTMODE_SET); 210 break; 211 case A3('?', '\0', 'h'): /* DECSM */ 212 for (n = 0; n < edp->nargs; n++) 213 vt100_decmode(edp, ARG(edp, n), VTMODE_SET); 214 break; 215 case A3('\0', '\0', 'l'): /* RM */ 216 for (n = 0; n < edp->nargs; n++) 217 vt100_ansimode(edp, ARG(edp, n), VTMODE_RESET); 218 break; 219 case A3('?', '\0', 'l'): /* DECRM */ 220 for (n = 0; n < edp->nargs; n++) 221 vt100_decmode(edp, ARG(edp, n), VTMODE_RESET); 222 break; 223 case A3('\0', '$', 'p'): /* DECRQM request mode ANSI */ 224 vt100_ansimode(edp, ARG(edp, 0), VTMODE_REPORT); 225 break; 226 case A3('?', '$', 'p'): /* DECRQM request mode DEC */ 227 vt100_decmode(edp, ARG(edp, 0), VTMODE_REPORT); 228 break; 229 case A3('\0', '\0', 'i'): /* MC printer controller mode */ 230 case A3('?', '\0', 'i'): /* MC printer controller mode */ 231 switch (ARG(edp, 0)) { 232 case 0: /* print screen */ 233 case 1: /* print cursor line */ 234 case 4: /* off */ 235 case 5: /* on */ 236 #ifdef VT100_PRINTNOTIMPL 237 printf("CSI%di ignored\n", ARG(edp, 0)); 238 #endif 239 break; 240 default: 241 #ifdef VT100_PRINTUNKNOWN 242 printf("CSI%di unknown\n", ARG(edp, 0)); 243 #endif 244 break; 245 } 246 break; 247 248 #define A2(a, b) (((a) << 8) | (b)) 249 #if 0 /* XXX */ 250 case A2('!', 'p'): /* DECSTR soft reset VT300 only */ 251 wsemul_vt100_reset(edp); 252 break; 253 #endif 254 255 case A2('"', 'p'): /* DECSCL */ 256 switch (ARG(edp, 0)) { 257 case 61: /* VT100 mode (no further arguments!) */ 258 break; 259 case 62: 260 case 63: /* VT300 mode */ 261 break; 262 default: 263 #ifdef VT100_PRINTUNKNOWN 264 printf("CSI%d\"p unknown\n", ARG(edp, 0)); 265 #endif 266 break; 267 } 268 switch (ARG(edp, 1)) { 269 case 0: 270 case 2: /* 8-bit controls */ 271 #ifdef VT100_PRINTNOTIMPL 272 printf("CSI%d;%d\"p ignored\n", ARG(edp, 0), ARG(edp, 1)); 273 #endif 274 break; 275 case 1: /* 7-bit controls */ 276 break; 277 default: 278 #ifdef VT100_PRINTUNKNOWN 279 printf("CSI%d;%d\"p unknown\n", ARG(edp, 0), ARG(edp, 1)); 280 #endif 281 break; 282 } 283 break; 284 case A2('"', 'q'): /* DECSCA select character attribute VT300 */ 285 switch (ARG(edp, 0)) { 286 case 0: 287 case 1: /* erasable */ 288 break; 289 case 2: /* not erasable */ 290 #ifdef VT100_PRINTNOTIMPL 291 printf("CSI2\"q ignored\n"); 292 #endif 293 break; 294 default: 295 #ifdef VT100_PRINTUNKNOWN 296 printf("CSI%d\"q unknown\n", ARG(edp, 0)); 297 #endif 298 break; 299 } 300 break; 301 302 case A2('$', 'u'): /* DECRQTSR request terminal status report */ 303 switch (ARG(edp, 0)) { 304 case 0: /* ignored */ 305 break; 306 case 1: /* terminal state report */ 307 #ifdef VT100_PRINTNOTIMPL 308 printf("CSI1$u ignored\n"); 309 #endif 310 break; 311 default: 312 #ifdef VT100_PRINTUNKNOWN 313 printf("CSI%d$u unknown\n", ARG(edp, 0)); 314 #endif 315 break; 316 } 317 break; 318 case A2('$', 'w'): /* DECRQPSR request presentation status report 319 (VT300 only) */ 320 switch (ARG(edp, 0)) { 321 case 0: /* error */ 322 break; 323 case 1: /* cursor information report */ 324 #ifdef VT100_PRINTNOTIMPL 325 printf("CSI1$w ignored\n"); 326 #endif 327 break; 328 case 2: /* tab stop report */ 329 { 330 int i, j, ps = 0; 331 char buf[20]; 332 KASSERT(edp->tabs != 0); 333 wsdisplay_emulinput(edp->cbcookie, "\033P2$u", 5); 334 for (i = 0; i < edp->ncols; i++) 335 if (edp->tabs[i]) { 336 j = snprintf(buf, sizeof(buf), "%s%d", 337 (ps ? "/" : ""), i + 1); 338 wsdisplay_emulinput(edp->cbcookie, 339 buf, j); 340 ps = 1; 341 } 342 } 343 wsdisplay_emulinput(edp->cbcookie, "\033\\", 2); 344 break; 345 default: 346 #ifdef VT100_PRINTUNKNOWN 347 printf("CSI%d$w unknown\n", ARG(edp, 0)); 348 #endif 349 break; 350 } 351 break; 352 case A2('$', '}'): /* DECSASD select active status display */ 353 switch (ARG(edp, 0)) { 354 case 0: /* main display */ 355 case 1: /* status line */ 356 #ifdef VT100_PRINTNOTIMPL 357 printf("CSI%d$} ignored\n", ARG(edp, 0)); 358 #endif 359 break; 360 default: 361 #ifdef VT100_PRINTUNKNOWN 362 printf("CSI%d$} unknown\n", ARG(edp, 0)); 363 #endif 364 break; 365 } 366 break; 367 case A2('$', '~'): /* DECSSDD select status line type */ 368 switch (ARG(edp, 0)) { 369 case 0: /* none */ 370 case 1: /* indicator */ 371 case 2: /* host-writable */ 372 #ifdef VT100_PRINTNOTIMPL 373 printf("CSI%d$~ ignored\n", ARG(edp, 0)); 374 #endif 375 break; 376 default: 377 #ifdef VT100_PRINTUNKNOWN 378 printf("CSI%d$~ unknown\n", ARG(edp, 0)); 379 #endif 380 break; 381 } 382 break; 383 384 case A2('&', 'u'): /* DECRQUPSS request user preferred 385 supplemental set */ 386 wsdisplay_emulinput(edp->cbcookie, "\033P0!u%5\033\\", 9); 387 break; 388 389 case '@': /* ICH insert character VT300 only */ 390 n = min(DEF1_ARG(edp, 0), COLS_LEFT(edp) + 1); 391 help = NCOLS(edp) - (edp->ccol + n); 392 if (help > 0) 393 COPYCOLS(edp, edp->ccol, edp->ccol + n, help); 394 ERASECOLS(edp, edp->ccol, n, edp->bkgdattr); 395 break; 396 case 'A': /* CUU */ 397 edp->crow -= min(DEF1_ARG(edp, 0), ROWS_ABOVE(edp)); 398 CHECK_DW(edp); 399 break; 400 case 'B': /* CUD */ 401 edp->crow += min(DEF1_ARG(edp, 0), ROWS_BELOW(edp)); 402 CHECK_DW(edp); 403 break; 404 case 'C': /* CUF */ 405 edp->ccol += min(DEF1_ARG(edp, 0), COLS_LEFT(edp)); 406 break; 407 case 'D': /* CUB */ 408 edp->ccol -= min(DEF1_ARG(edp, 0), edp->ccol); 409 edp->flags &= ~VTFL_LASTCHAR; 410 break; 411 case 'H': /* CUP */ 412 case 'f': /* HVP */ 413 if (edp->flags & VTFL_DECOM) 414 edp->crow = edp->scrreg_startrow + 415 min(DEF1_ARG(edp, 0), edp->scrreg_nrows) - 1; 416 else 417 edp->crow = min(DEF1_ARG(edp, 0), edp->nrows) - 1; 418 CHECK_DW(edp); 419 edp->ccol = min(DEF1_ARG(edp, 1), NCOLS(edp)) - 1; 420 edp->flags &= ~VTFL_LASTCHAR; 421 break; 422 case 'L': /* IL insert line */ 423 case 'M': /* DL delete line */ 424 n = min(DEF1_ARG(edp, 0), ROWS_BELOW(edp) + 1); 425 { 426 int savscrstartrow, savscrnrows; 427 savscrstartrow = edp->scrreg_startrow; 428 savscrnrows = edp->scrreg_nrows; 429 edp->scrreg_nrows -= ROWS_ABOVE(edp); 430 edp->scrreg_startrow = edp->crow; 431 if (c == 'L') 432 wsemul_vt100_scrolldown(edp, n); 433 else 434 wsemul_vt100_scrollup(edp, n); 435 edp->scrreg_startrow = savscrstartrow; 436 edp->scrreg_nrows = savscrnrows; 437 } 438 break; 439 case 'P': /* DCH delete character */ 440 n = min(DEF1_ARG(edp, 0), COLS_LEFT(edp) + 1); 441 help = NCOLS(edp) - (edp->ccol + n); 442 if (help > 0) 443 COPYCOLS(edp, edp->ccol + n, edp->ccol, help); 444 ERASECOLS(edp, NCOLS(edp) - n, n, edp->bkgdattr); 445 break; 446 case 'X': /* ECH erase character */ 447 n = min(DEF1_ARG(edp, 0), COLS_LEFT(edp) + 1); 448 ERASECOLS(edp, edp->ccol, n, edp->bkgdattr); 449 break; 450 case 'c': /* DA primary */ 451 if (ARG(edp, 0) == 0) 452 wsdisplay_emulinput(edp->cbcookie, WSEMUL_VT_ID1, 453 sizeof(WSEMUL_VT_ID1)); 454 break; 455 case 'g': /* TBC */ 456 KASSERT(edp->tabs != 0); 457 switch (ARG(edp, 0)) { 458 case 0: 459 edp->tabs[edp->ccol] = 0; 460 break; 461 case 3: 462 memset(edp->tabs, 0, edp->ncols); 463 break; 464 default: 465 #ifdef VT100_PRINTUNKNOWN 466 printf("CSI%dg unknown\n", ARG(edp, 0)); 467 #endif 468 break; 469 } 470 break; 471 case 'm': /* SGR select graphic rendition */ 472 flags = edp->attrflags; 473 fgcol = edp->fgcol; 474 bgcol = edp->bgcol; 475 for (n = 0; n < edp->nargs; n++) { 476 switch (ARG(edp, n)) { 477 case 0: /* reset */ 478 if (n == edp->nargs - 1) { 479 edp->bkgdattr = edp->curattr = edp->defattr; 480 edp->attrflags = edp->msgattrs.default_attrs; 481 edp->fgcol = edp->msgattrs.default_fg; 482 edp->bgcol = edp->msgattrs.default_bg; 483 return; 484 } 485 flags = edp->msgattrs.default_attrs; 486 fgcol = edp->msgattrs.default_fg; 487 bgcol = edp->msgattrs.default_bg; 488 break; 489 case 1: /* bold */ 490 flags |= WSATTR_HILIT; 491 break; 492 case 4: /* underline */ 493 flags |= WSATTR_UNDERLINE; 494 break; 495 case 5: /* blink */ 496 flags |= WSATTR_BLINK; 497 break; 498 case 7: /* reverse */ 499 flags |= WSATTR_REVERSE; 500 break; 501 case 22: /* ~bold VT300 only */ 502 flags &= ~WSATTR_HILIT; 503 break; 504 case 24: /* ~underline VT300 only */ 505 flags &= ~WSATTR_UNDERLINE; 506 break; 507 case 25: /* ~blink VT300 only */ 508 flags &= ~WSATTR_BLINK; 509 break; 510 case 27: /* ~reverse VT300 only */ 511 flags &= ~WSATTR_REVERSE; 512 break; 513 case 30: case 31: case 32: case 33: 514 case 34: case 35: case 36: case 37: 515 /* fg color */ 516 flags |= WSATTR_WSCOLORS; 517 fgcol = ARG(edp, n) - 30; 518 break; 519 case 40: case 41: case 42: case 43: 520 case 44: case 45: case 46: case 47: 521 /* bg color */ 522 flags |= WSATTR_WSCOLORS; 523 bgcol = ARG(edp, n) - 40; 524 break; 525 default: 526 #ifdef VT100_PRINTUNKNOWN 527 printf("CSI%dm unknown\n", ARG(edp, n)); 528 #endif 529 break; 530 } 531 } 532 if (vt100_selectattribute(edp, flags, fgcol, bgcol, &attr, 533 &bkgdattr)) { 534 #ifdef VT100_DEBUG 535 printf("error allocating attr %d/%d/%x\n", 536 fgcol, bgcol, flags); 537 #endif 538 } else { 539 edp->curattr = attr; 540 edp->bkgdattr = bkgdattr; 541 edp->attrflags = flags; 542 edp->fgcol = fgcol; 543 edp->bgcol = bgcol; 544 } 545 break; 546 case 'n': /* reports */ 547 switch (ARG(edp, 0)) { 548 case 5: /* DSR operating status */ 549 /* 0 = OK, 3 = malfunction */ 550 wsdisplay_emulinput(edp->cbcookie, "\033[0n", 4); 551 break; 552 case 6: { /* DSR cursor position report */ 553 char buf[20]; 554 int row; 555 if (edp->flags & VTFL_DECOM) 556 row = ROWS_ABOVE(edp); 557 else 558 row = edp->crow; 559 n = snprintf(buf, sizeof(buf), "\033[%d;%dR", 560 row + 1, edp->ccol + 1); 561 wsdisplay_emulinput(edp->cbcookie, buf, n); 562 } 563 break; 564 case 15: /* DSR printer status */ 565 /* 13 = no printer, 10 = ready, 11 = not ready */ 566 wsdisplay_emulinput(edp->cbcookie, "\033[?13n", 6); 567 break; 568 case 25: /* UDK status - VT300 only */ 569 /* 20 = locked, 21 = unlocked */ 570 wsdisplay_emulinput(edp->cbcookie, "\033[?21n", 6); 571 break; 572 case 26: /* keyboard dialect */ 573 /* 1 = north american , 7 = german */ 574 wsdisplay_emulinput(edp->cbcookie, "\033[?27;1n", 8); 575 break; 576 default: 577 #ifdef VT100_PRINTUNKNOWN 578 printf("CSI%dn unknown\n", ARG(edp, 0)); 579 #endif 580 break; 581 } 582 break; 583 case 'r': /* DECSTBM set top/bottom margins */ 584 help = min(DEF1_ARG(edp, 0), edp->nrows) - 1; 585 n = min(DEFx_ARG(edp, 1, edp->nrows), edp->nrows) - help; 586 if (n < 2) { 587 /* minimal scrolling region has 2 lines */ 588 return; 589 } else { 590 edp->scrreg_startrow = help; 591 edp->scrreg_nrows = n; 592 } 593 edp->crow = ((edp->flags & VTFL_DECOM) ? 594 edp->scrreg_startrow : 0); 595 edp->ccol = 0; 596 break; 597 case 'y': 598 switch (ARG(edp, 0)) { 599 case 4: /* DECTST invoke confidence test */ 600 /* ignore */ 601 break; 602 default: 603 #ifdef VT100_PRINTUNKNOWN 604 printf("CSI%dy unknown\n", ARG(edp, 0)); 605 #endif 606 break; 607 } 608 break; 609 default: 610 #ifdef VT100_PRINTUNKNOWN 611 printf("CSI%c (%d, %d) unknown\n", c, ARG(edp, 0), ARG(edp, 1)); 612 #endif 613 break; 614 } 615 } 616 617 /* 618 * get an attribute from the graphics driver, 619 * try to find replacements if the desired appearance 620 * is not supported 621 */ 622 static int 623 vt100_selectattribute(struct vt100base_data *edp, 624 int flags, int fgcol, int bgcol, long *attr, long *bkgdattr) 625 { 626 int error; 627 628 if (!(edp->scrcapabilities & WSSCREEN_WSCOLORS)) { 629 flags &= ~WSATTR_WSCOLORS; 630 #ifdef VT100_DEBUG 631 printf("colors ignored (impossible)\n"); 632 #endif 633 } else 634 flags |= WSATTR_WSCOLORS; 635 error = (*edp->emulops->allocattr)(edp->emulcookie, fgcol, bgcol, 636 flags & WSATTR_WSCOLORS, bkgdattr); 637 if (error) 638 return (error); 639 640 if ((flags & WSATTR_HILIT) && 641 !(edp->scrcapabilities & WSSCREEN_HILIT)) { 642 flags &= ~WSATTR_HILIT; 643 if (edp->scrcapabilities & WSSCREEN_WSCOLORS) { 644 #if defined(WSEMUL_VT100_HILIT_FG) && WSEMUL_VT100_HILIT_FG != -1 645 fgcol = WSEMUL_VT100_HILIT_FG; 646 #elif !defined(WSEMUL_VT100_HILIT_FG) 647 fgcol = WSCOL_RED; 648 #endif 649 #if defined(WSEMUL_VT100_HILIT_BG) && WSEMUL_VT100_HILIT_BG != -1 650 bgcol = WSEMUL_VT100_HILIT_BG; 651 #endif 652 flags |= WSATTR_WSCOLORS; 653 } else { 654 #ifdef VT100_DEBUG 655 printf("bold ignored (impossible)\n"); 656 #endif 657 } 658 } 659 if ((flags & WSATTR_UNDERLINE) && 660 !(edp->scrcapabilities & WSSCREEN_UNDERLINE)) { 661 flags &= ~WSATTR_UNDERLINE; 662 if (edp->scrcapabilities & WSSCREEN_WSCOLORS) { 663 #if defined(WSEMUL_VT100_UNDERLINE_FG) && WSEMUL_VT100_UNDERLINE_FG != -1 664 fgcol = WSEMUL_VT100_UNDERLINE_FG; 665 #endif 666 #if defined(WSEMUL_VT100_UNDERLINE_BG) && WSEMUL_VT100_UNDERLINE_BG != -1 667 bgcol = WSEMUL_VT100_UNDERLINE_BG; 668 #elif !defined(WSEMUL_VT100_UNDERLINE_BG) 669 bgcol = WSCOL_BROWN; 670 #endif 671 flags |= WSATTR_WSCOLORS; 672 } else { 673 #ifdef VT100_DEBUG 674 printf("underline ignored (impossible)\n"); 675 #endif 676 } 677 } 678 if ((flags & WSATTR_BLINK) && 679 !(edp->scrcapabilities & WSSCREEN_BLINK)) { 680 flags &= ~WSATTR_BLINK; 681 #ifdef VT100_DEBUG 682 printf("blink ignored (impossible)\n"); 683 #endif 684 } 685 if ((flags & WSATTR_REVERSE) && 686 !(edp->scrcapabilities & WSSCREEN_REVERSE)) { 687 flags &= ~WSATTR_REVERSE; 688 if (edp->scrcapabilities & WSSCREEN_WSCOLORS) { 689 int help; 690 help = bgcol; 691 bgcol = fgcol; 692 fgcol = help; 693 flags |= WSATTR_WSCOLORS; 694 } else { 695 #ifdef VT100_DEBUG 696 printf("reverse ignored (impossible)\n"); 697 #endif 698 } 699 } 700 error = (*edp->emulops->allocattr)(edp->emulcookie, fgcol, bgcol, 701 flags, attr); 702 if (error) 703 return (error); 704 705 return (0); 706 } 707 708 /* 709 * handle device control sequences if the main state machine 710 * told so by setting edp->dcstype to a nonzero value 711 */ 712 void 713 wsemul_vt100_handle_dcs(struct vt100base_data *edp) 714 { 715 int i, pos; 716 717 switch (edp->dcstype) { 718 case 0: /* not handled */ 719 return; 720 case DCSTYPE_TABRESTORE: 721 KASSERT(edp->tabs != 0); 722 memset(edp->tabs, 0, edp->ncols); 723 pos = 0; 724 for (i = 0; i < edp->dcspos; i++) { 725 char c = edp->dcsarg[i]; 726 switch (c) { 727 case '0': case '1': case '2': case '3': case '4': 728 case '5': case '6': case '7': case '8': case '9': 729 pos = pos * 10 + (edp->dcsarg[i] - '0'); 730 break; 731 case '/': 732 if (pos > 0) 733 edp->tabs[pos - 1] = 1; 734 pos = 0; 735 break; 736 default: 737 #ifdef VT100_PRINTUNKNOWN 738 printf("unknown char %c in DCS\n", c); 739 #endif 740 break; 741 } 742 } 743 if (pos > 0) 744 edp->tabs[pos - 1] = 1; 745 break; 746 default: 747 panic("wsemul_vt100_handle_dcs: bad type %d", edp->dcstype); 748 } 749 edp->dcstype = 0; 750 } 751 752 static int 753 vt100_ansimode(struct vt100base_data *edp, int nr, int op) 754 { 755 int res = 0; /* default: unknown */ 756 757 switch (nr) { 758 case 2: /* KAM keyboard locked/unlocked */ 759 break; 760 case 3: /* CRM control representation */ 761 break; 762 case 4: /* IRM insert/replace characters */ 763 if (op == VTMODE_SET) 764 edp->flags |= VTFL_INSERTMODE; 765 else if (op == VTMODE_RESET) 766 edp->flags &= ~VTFL_INSERTMODE; 767 res = ((edp->flags & VTFL_INSERTMODE) ? 1 : 2); 768 break; 769 case 10: /* HEM horizontal editing (permanently reset) */ 770 res = 4; 771 break; 772 case 12: /* SRM local echo off/on */ 773 res = 4; /* permanently reset ??? */ 774 break; 775 case 20: /* LNM newline = newline/linefeed */ 776 break; 777 default: 778 #ifdef VT100_PRINTUNKNOWN 779 printf("ANSI mode %d unknown\n", nr); 780 #endif 781 break; 782 } 783 return (res); 784 } 785 786 static int 787 vt100_decmode(struct vt100base_data *edp, int nr, int op) 788 { 789 int res = 0; /* default: unknown */ 790 int flags; 791 792 flags = edp->flags; 793 switch (nr) { 794 case 1: /* DECCKM application/nomal cursor keys */ 795 if (op == VTMODE_SET) 796 flags |= VTFL_APPLCURSOR; 797 else if (op == VTMODE_RESET) 798 flags &= ~VTFL_APPLCURSOR; 799 res = ((flags & VTFL_APPLCURSOR) ? 1 : 2); 800 break; 801 case 2: /* DECANM ANSI vt100/vt52 */ 802 res = 3; /* permanently set ??? */ 803 break; 804 case 3: /* DECCOLM 132/80 cols */ 805 case 4: /* DECSCLM smooth/jump scroll */ 806 case 5: /* DECSCNM light/dark background */ 807 res = 4; /* all permanently reset ??? */ 808 break; 809 case 6: /* DECOM move within/outside margins */ 810 if (op == VTMODE_SET) 811 flags |= VTFL_DECOM; 812 else if (op == VTMODE_RESET) 813 flags &= ~VTFL_DECOM; 814 res = ((flags & VTFL_DECOM) ? 1 : 2); 815 break; 816 case 7: /* DECAWM autowrap */ 817 if (op == VTMODE_SET) 818 flags |= VTFL_DECAWM; 819 else if (op == VTMODE_RESET) 820 flags &= ~VTFL_DECAWM; 821 res = ((flags & VTFL_DECAWM) ? 1 : 2); 822 break; 823 case 8: /* DECARM keyboard autorepeat */ 824 break; 825 case 18: /* DECPFF print form feed */ 826 break; 827 case 19: /* DECPEX printer extent: screen/scrolling region */ 828 break; 829 case 25: /* DECTCEM text cursor on/off */ 830 if (op == VTMODE_SET) 831 flags |= VTFL_CURSORON; 832 else if (op == VTMODE_RESET) 833 flags &= ~VTFL_CURSORON; 834 if (flags != edp->flags) 835 (*edp->emulops->cursor)(edp->emulcookie, 836 flags & VTFL_CURSORON, 837 edp->crow, edp->ccol); 838 res = ((flags & VTFL_CURSORON) ? 1 : 2); 839 break; 840 case 42: /* DECNRCM use 7-bit NRC / 841 7/8 bit from DEC multilingual or ISO-latin-1*/ 842 if (op == VTMODE_SET) 843 flags |= VTFL_NATCHARSET; 844 else if (op == VTMODE_RESET) 845 flags &= ~VTFL_NATCHARSET; 846 res = ((flags & VTFL_NATCHARSET) ? 1 : 2); 847 break; 848 case 66: /* DECNKM numeric keypad */ 849 break; 850 case 68: /* DECKBUM keyboard usage data processing/typewriter */ 851 break; 852 default: 853 #ifdef VT100_PRINTUNKNOWN 854 printf("DEC mode %d unknown\n", nr); 855 #endif 856 break; 857 } 858 edp->flags = flags; 859 860 return (res); 861 } 862