1 /* $NetBSD: wsemul_vt100_subr.c,v 1.21 2017/05/19 19:22:33 macallan 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.21 2017/05/19 19:22:33 macallan 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 't': /* terminal size and such */ 547 switch (ARG(edp, 0)) { 548 case 18: { /* xterm size */ 549 char buf[20]; 550 551 n = snprintf(buf, sizeof(buf), "\033[8;%d;%dt", 552 edp->nrows, edp->ncols); 553 wsdisplay_emulinput(edp->cbcookie, buf, n); 554 } 555 break; 556 } 557 break; 558 case 'n': /* reports */ 559 switch (ARG(edp, 0)) { 560 case 5: /* DSR operating status */ 561 /* 0 = OK, 3 = malfunction */ 562 wsdisplay_emulinput(edp->cbcookie, "\033[0n", 4); 563 break; 564 case 6: { /* DSR cursor position report */ 565 char buf[20]; 566 int row; 567 if (edp->flags & VTFL_DECOM) 568 row = ROWS_ABOVE(edp); 569 else 570 row = edp->crow; 571 n = snprintf(buf, sizeof(buf), "\033[%d;%dR", 572 row + 1, edp->ccol + 1); 573 wsdisplay_emulinput(edp->cbcookie, buf, n); 574 } 575 break; 576 case 15: /* DSR printer status */ 577 /* 13 = no printer, 10 = ready, 11 = not ready */ 578 wsdisplay_emulinput(edp->cbcookie, "\033[?13n", 6); 579 break; 580 case 25: /* UDK status - VT300 only */ 581 /* 20 = locked, 21 = unlocked */ 582 wsdisplay_emulinput(edp->cbcookie, "\033[?21n", 6); 583 break; 584 case 26: /* keyboard dialect */ 585 /* 1 = north american , 7 = german */ 586 wsdisplay_emulinput(edp->cbcookie, "\033[?27;1n", 8); 587 break; 588 default: 589 #ifdef VT100_PRINTUNKNOWN 590 printf("CSI%dn unknown\n", ARG(edp, 0)); 591 #endif 592 break; 593 } 594 break; 595 case 'r': /* DECSTBM set top/bottom margins */ 596 help = min(DEF1_ARG(edp, 0), edp->nrows) - 1; 597 n = min(DEFx_ARG(edp, 1, edp->nrows), edp->nrows) - help; 598 if (n < 2) { 599 /* minimal scrolling region has 2 lines */ 600 return; 601 } else { 602 edp->scrreg_startrow = help; 603 edp->scrreg_nrows = n; 604 } 605 edp->crow = ((edp->flags & VTFL_DECOM) ? 606 edp->scrreg_startrow : 0); 607 edp->ccol = 0; 608 break; 609 case 'y': 610 switch (ARG(edp, 0)) { 611 case 4: /* DECTST invoke confidence test */ 612 /* ignore */ 613 break; 614 default: 615 #ifdef VT100_PRINTUNKNOWN 616 printf("CSI%dy unknown\n", ARG(edp, 0)); 617 #endif 618 break; 619 } 620 break; 621 default: 622 #ifdef VT100_PRINTUNKNOWN 623 printf("CSI%c (%d, %d) unknown\n", c, ARG(edp, 0), ARG(edp, 1)); 624 #endif 625 break; 626 } 627 } 628 629 /* 630 * get an attribute from the graphics driver, 631 * try to find replacements if the desired appearance 632 * is not supported 633 */ 634 static int 635 vt100_selectattribute(struct vt100base_data *edp, 636 int flags, int fgcol, int bgcol, long *attr, long *bkgdattr) 637 { 638 int error; 639 640 if (!(edp->scrcapabilities & WSSCREEN_WSCOLORS)) { 641 flags &= ~WSATTR_WSCOLORS; 642 #ifdef VT100_DEBUG 643 printf("colors ignored (impossible)\n"); 644 #endif 645 } else 646 flags |= WSATTR_WSCOLORS; 647 error = (*edp->emulops->allocattr)(edp->emulcookie, fgcol, bgcol, 648 flags & WSATTR_WSCOLORS, bkgdattr); 649 if (error) 650 return (error); 651 652 if ((flags & WSATTR_HILIT) && 653 !(edp->scrcapabilities & WSSCREEN_HILIT)) { 654 flags &= ~WSATTR_HILIT; 655 if (edp->scrcapabilities & WSSCREEN_WSCOLORS) { 656 #if defined(WSEMUL_VT100_HILIT_FG) && WSEMUL_VT100_HILIT_FG != -1 657 fgcol = WSEMUL_VT100_HILIT_FG; 658 #elif !defined(WSEMUL_VT100_HILIT_FG) 659 fgcol = WSCOL_RED; 660 #endif 661 #if defined(WSEMUL_VT100_HILIT_BG) && WSEMUL_VT100_HILIT_BG != -1 662 bgcol = WSEMUL_VT100_HILIT_BG; 663 #endif 664 flags |= WSATTR_WSCOLORS; 665 } else { 666 #ifdef VT100_DEBUG 667 printf("bold ignored (impossible)\n"); 668 #endif 669 } 670 } 671 if ((flags & WSATTR_UNDERLINE) && 672 !(edp->scrcapabilities & WSSCREEN_UNDERLINE)) { 673 flags &= ~WSATTR_UNDERLINE; 674 if (edp->scrcapabilities & WSSCREEN_WSCOLORS) { 675 #if defined(WSEMUL_VT100_UNDERLINE_FG) && WSEMUL_VT100_UNDERLINE_FG != -1 676 fgcol = WSEMUL_VT100_UNDERLINE_FG; 677 #endif 678 #if defined(WSEMUL_VT100_UNDERLINE_BG) && WSEMUL_VT100_UNDERLINE_BG != -1 679 bgcol = WSEMUL_VT100_UNDERLINE_BG; 680 #elif !defined(WSEMUL_VT100_UNDERLINE_BG) 681 bgcol = WSCOL_BROWN; 682 #endif 683 flags |= WSATTR_WSCOLORS; 684 } else { 685 #ifdef VT100_DEBUG 686 printf("underline ignored (impossible)\n"); 687 #endif 688 } 689 } 690 if ((flags & WSATTR_BLINK) && 691 !(edp->scrcapabilities & WSSCREEN_BLINK)) { 692 flags &= ~WSATTR_BLINK; 693 #ifdef VT100_DEBUG 694 printf("blink ignored (impossible)\n"); 695 #endif 696 } 697 if ((flags & WSATTR_REVERSE) && 698 !(edp->scrcapabilities & WSSCREEN_REVERSE)) { 699 flags &= ~WSATTR_REVERSE; 700 if (edp->scrcapabilities & WSSCREEN_WSCOLORS) { 701 int help; 702 help = bgcol; 703 bgcol = fgcol; 704 fgcol = help; 705 flags |= WSATTR_WSCOLORS; 706 } else { 707 #ifdef VT100_DEBUG 708 printf("reverse ignored (impossible)\n"); 709 #endif 710 } 711 } 712 error = (*edp->emulops->allocattr)(edp->emulcookie, fgcol, bgcol, 713 flags, attr); 714 if (error) 715 return (error); 716 717 return (0); 718 } 719 720 /* 721 * handle device control sequences if the main state machine 722 * told so by setting edp->dcstype to a nonzero value 723 */ 724 void 725 wsemul_vt100_handle_dcs(struct vt100base_data *edp) 726 { 727 int i, pos; 728 729 switch (edp->dcstype) { 730 case 0: /* not handled */ 731 return; 732 case DCSTYPE_TABRESTORE: 733 KASSERT(edp->tabs != 0); 734 memset(edp->tabs, 0, edp->ncols); 735 pos = 0; 736 for (i = 0; i < edp->dcspos; i++) { 737 char c = edp->dcsarg[i]; 738 switch (c) { 739 case '0': case '1': case '2': case '3': case '4': 740 case '5': case '6': case '7': case '8': case '9': 741 pos = pos * 10 + (edp->dcsarg[i] - '0'); 742 break; 743 case '/': 744 if (pos > 0) 745 edp->tabs[pos - 1] = 1; 746 pos = 0; 747 break; 748 default: 749 #ifdef VT100_PRINTUNKNOWN 750 printf("unknown char %c in DCS\n", c); 751 #endif 752 break; 753 } 754 } 755 if (pos > 0) 756 edp->tabs[pos - 1] = 1; 757 break; 758 default: 759 panic("wsemul_vt100_handle_dcs: bad type %d", edp->dcstype); 760 } 761 edp->dcstype = 0; 762 } 763 764 static int 765 vt100_ansimode(struct vt100base_data *edp, int nr, int op) 766 { 767 int res = 0; /* default: unknown */ 768 769 switch (nr) { 770 case 2: /* KAM keyboard locked/unlocked */ 771 break; 772 case 3: /* CRM control representation */ 773 break; 774 case 4: /* IRM insert/replace characters */ 775 if (op == VTMODE_SET) 776 edp->flags |= VTFL_INSERTMODE; 777 else if (op == VTMODE_RESET) 778 edp->flags &= ~VTFL_INSERTMODE; 779 res = ((edp->flags & VTFL_INSERTMODE) ? 1 : 2); 780 break; 781 case 10: /* HEM horizontal editing (permanently reset) */ 782 res = 4; 783 break; 784 case 12: /* SRM local echo off/on */ 785 res = 4; /* permanently reset ??? */ 786 break; 787 case 20: /* LNM newline = newline/linefeed */ 788 break; 789 default: 790 #ifdef VT100_PRINTUNKNOWN 791 printf("ANSI mode %d unknown\n", nr); 792 #endif 793 break; 794 } 795 return (res); 796 } 797 798 static int 799 vt100_decmode(struct vt100base_data *edp, int nr, int op) 800 { 801 int res = 0; /* default: unknown */ 802 int flags; 803 804 flags = edp->flags; 805 switch (nr) { 806 case 1: /* DECCKM application/nomal cursor keys */ 807 if (op == VTMODE_SET) 808 flags |= VTFL_APPLCURSOR; 809 else if (op == VTMODE_RESET) 810 flags &= ~VTFL_APPLCURSOR; 811 res = ((flags & VTFL_APPLCURSOR) ? 1 : 2); 812 break; 813 case 2: /* DECANM ANSI vt100/vt52 */ 814 res = 3; /* permanently set ??? */ 815 break; 816 case 3: /* DECCOLM 132/80 cols */ 817 case 4: /* DECSCLM smooth/jump scroll */ 818 case 5: /* DECSCNM light/dark background */ 819 res = 4; /* all permanently reset ??? */ 820 break; 821 case 6: /* DECOM move within/outside margins */ 822 if (op == VTMODE_SET) 823 flags |= VTFL_DECOM; 824 else if (op == VTMODE_RESET) 825 flags &= ~VTFL_DECOM; 826 res = ((flags & VTFL_DECOM) ? 1 : 2); 827 break; 828 case 7: /* DECAWM autowrap */ 829 if (op == VTMODE_SET) 830 flags |= VTFL_DECAWM; 831 else if (op == VTMODE_RESET) 832 flags &= ~VTFL_DECAWM; 833 res = ((flags & VTFL_DECAWM) ? 1 : 2); 834 break; 835 case 8: /* DECARM keyboard autorepeat */ 836 break; 837 case 18: /* DECPFF print form feed */ 838 break; 839 case 19: /* DECPEX printer extent: screen/scrolling region */ 840 break; 841 case 25: /* DECTCEM text cursor on/off */ 842 if (op == VTMODE_SET) 843 flags |= VTFL_CURSORON; 844 else if (op == VTMODE_RESET) 845 flags &= ~VTFL_CURSORON; 846 if (flags != edp->flags) 847 (*edp->emulops->cursor)(edp->emulcookie, 848 flags & VTFL_CURSORON, 849 edp->crow, edp->ccol); 850 res = ((flags & VTFL_CURSORON) ? 1 : 2); 851 break; 852 case 42: /* DECNRCM use 7-bit NRC / 853 7/8 bit from DEC multilingual or ISO-latin-1*/ 854 if (op == VTMODE_SET) 855 flags |= VTFL_NATCHARSET; 856 else if (op == VTMODE_RESET) 857 flags &= ~VTFL_NATCHARSET; 858 res = ((flags & VTFL_NATCHARSET) ? 1 : 2); 859 break; 860 case 66: /* DECNKM numeric keypad */ 861 break; 862 case 68: /* DECKBUM keyboard usage data processing/typewriter */ 863 break; 864 default: 865 #ifdef VT100_PRINTUNKNOWN 866 printf("DEC mode %d unknown\n", nr); 867 #endif 868 break; 869 } 870 edp->flags = flags; 871 872 return (res); 873 } 874