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