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