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