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