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