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