1 /* $NetBSD: wsemul_vt100.c,v 1.14 2001/02/21 23:12:58 jdolecek 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 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed for the NetBSD Project 18 * by Matthias Drochner. 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/time.h> 38 #include <sys/malloc.h> 39 #include <sys/fcntl.h> 40 41 #include <dev/wscons/wsconsio.h> 42 #include <dev/wscons/wsdisplayvar.h> 43 #include <dev/wscons/wsemulvar.h> 44 #include <dev/wscons/wsemul_vt100var.h> 45 #include <dev/wscons/ascii.h> 46 47 #include "opt_wskernattr.h" 48 49 void *wsemul_vt100_cnattach __P((const struct wsscreen_descr *, void *, 50 int, int, long)); 51 void *wsemul_vt100_attach __P((int console, const struct wsscreen_descr *, 52 void *, int, int, void *, long)); 53 void wsemul_vt100_output __P((void *cookie, const u_char *data, u_int count, 54 int)); 55 void wsemul_vt100_detach __P((void *cookie, u_int *crowp, u_int *ccolp)); 56 void wsemul_vt100_resetop __P((void *, enum wsemul_resetops)); 57 58 const struct wsemul_ops wsemul_vt100_ops = { 59 "vt100", 60 wsemul_vt100_cnattach, 61 wsemul_vt100_attach, 62 wsemul_vt100_output, 63 wsemul_vt100_translate, 64 wsemul_vt100_detach, 65 wsemul_vt100_resetop 66 }; 67 68 struct wsemul_vt100_emuldata wsemul_vt100_console_emuldata; 69 70 static void wsemul_vt100_init __P((struct wsemul_vt100_emuldata *, 71 const struct wsscreen_descr *, 72 void *, int, int, long)); 73 74 static void wsemul_vt100_output_normal __P((struct wsemul_vt100_emuldata *, 75 u_char, int)); 76 static void wsemul_vt100_output_c0c1 __P((struct wsemul_vt100_emuldata *, 77 u_char, int)); 78 typedef u_int vt100_handler __P((struct wsemul_vt100_emuldata *, u_char)); 79 static vt100_handler 80 wsemul_vt100_output_esc, 81 wsemul_vt100_output_csi, 82 wsemul_vt100_output_scs94, 83 wsemul_vt100_output_scs94_percent, 84 wsemul_vt100_output_scs96, 85 wsemul_vt100_output_scs96_percent, 86 wsemul_vt100_output_esc_hash, 87 wsemul_vt100_output_esc_spc, 88 wsemul_vt100_output_string, 89 wsemul_vt100_output_string_esc, 90 wsemul_vt100_output_dcs, 91 wsemul_vt100_output_dcs_dollar; 92 93 #define VT100_EMUL_STATE_NORMAL 0 /* normal processing */ 94 #define VT100_EMUL_STATE_ESC 1 /* got ESC */ 95 #define VT100_EMUL_STATE_CSI 2 /* got CSI (ESC[) */ 96 #define VT100_EMUL_STATE_SCS94 3 /* got ESC{()*+} */ 97 #define VT100_EMUL_STATE_SCS94_PERCENT 4 /* got ESC{()*+}% */ 98 #define VT100_EMUL_STATE_SCS96 5 /* got ESC{-./} */ 99 #define VT100_EMUL_STATE_SCS96_PERCENT 6 /* got ESC{-./}% */ 100 #define VT100_EMUL_STATE_ESC_HASH 7 /* got ESC# */ 101 #define VT100_EMUL_STATE_ESC_SPC 8 /* got ESC<SPC> */ 102 #define VT100_EMUL_STATE_STRING 9 /* waiting for ST (ESC\) */ 103 #define VT100_EMUL_STATE_STRING_ESC 10 /* waiting for ST, got ESC */ 104 #define VT100_EMUL_STATE_DCS 11 /* got DCS (ESC P) */ 105 #define VT100_EMUL_STATE_DCS_DOLLAR 12 /* got DCS<p>$ */ 106 107 vt100_handler *vt100_output[] = { 108 wsemul_vt100_output_esc, 109 wsemul_vt100_output_csi, 110 wsemul_vt100_output_scs94, 111 wsemul_vt100_output_scs94_percent, 112 wsemul_vt100_output_scs96, 113 wsemul_vt100_output_scs96_percent, 114 wsemul_vt100_output_esc_hash, 115 wsemul_vt100_output_esc_spc, 116 wsemul_vt100_output_string, 117 wsemul_vt100_output_string_esc, 118 wsemul_vt100_output_dcs, 119 wsemul_vt100_output_dcs_dollar, 120 }; 121 122 static void 123 wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr) 124 struct wsemul_vt100_emuldata *edp; 125 const struct wsscreen_descr *type; 126 void *cookie; 127 int ccol, crow; 128 long defattr; 129 { 130 edp->emulops = type->textops; 131 edp->emulcookie = cookie; 132 edp->scrcapabilities = type->capabilities; 133 edp->nrows = type->nrows; 134 edp->ncols = type->ncols; 135 edp->crow = crow; 136 edp->ccol = ccol; 137 edp->defattr = defattr; 138 } 139 140 void * 141 wsemul_vt100_cnattach(type, cookie, ccol, crow, defattr) 142 const struct wsscreen_descr *type; 143 void *cookie; 144 int ccol, crow; 145 long defattr; 146 { 147 struct wsemul_vt100_emuldata *edp; 148 #if defined(WS_KERNEL_FG) || defined(WS_KERNEL_BG) || \ 149 defined(WS_KERNEL_COLATTR) || defined(WS_KERNEL_MONOATTR) 150 int res; 151 #endif 152 153 edp = &wsemul_vt100_console_emuldata; 154 wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr); 155 #ifdef DIAGNOSTIC 156 edp->console = 1; 157 #endif 158 edp->cbcookie = NULL; 159 160 #if defined(WS_KERNEL_FG) || defined(WS_KERNEL_BG) || \ 161 defined(WS_KERNEL_COLATTR) || defined(WS_KERNEL_MONOATTR) 162 #ifndef WS_KERNEL_FG 163 #define WS_KERNEL_FG WSCOL_WHITE 164 #endif 165 #ifndef WS_KERNEL_BG 166 #define WS_KERNEL_BG WSCOL_BLACK 167 #endif 168 #ifndef WS_KERNEL_COLATTR 169 #define WS_KERNEL_COLATTR 0 170 #endif 171 #ifndef WS_KERNEL_MONOATTR 172 #define WS_KERNEL_MONOATTR 0 173 #endif 174 if (type->capabilities & WSSCREEN_WSCOLORS) 175 res = (*edp->emulops->alloc_attr)(cookie, 176 WS_KERNEL_FG, WS_KERNEL_BG, 177 WS_KERNEL_COLATTR | WSATTR_WSCOLORS, 178 &edp->kernattr); 179 else 180 res = (*edp->emulops->alloc_attr)(cookie, 0, 0, 181 WS_KERNEL_MONOATTR, 182 &edp->kernattr); 183 if (res) 184 #endif 185 edp->kernattr = defattr; 186 187 edp->tabs = 0; 188 edp->dblwid = 0; 189 edp->dw = 0; 190 edp->dcsarg = 0; 191 edp->isolatin1tab = edp->decgraphtab = edp->dectechtab = 0; 192 edp->nrctab = 0; 193 wsemul_vt100_reset(edp); 194 return (edp); 195 } 196 197 void * 198 wsemul_vt100_attach(console, type, cookie, ccol, crow, cbcookie, defattr) 199 int console; 200 const struct wsscreen_descr *type; 201 void *cookie; 202 int ccol, crow; 203 void *cbcookie; 204 long defattr; 205 { 206 struct wsemul_vt100_emuldata *edp; 207 208 if (console) { 209 edp = &wsemul_vt100_console_emuldata; 210 #ifdef DIAGNOSTIC 211 KASSERT(edp->console == 1); 212 #endif 213 } else { 214 edp = malloc(sizeof *edp, M_DEVBUF, M_WAITOK); 215 wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr); 216 #ifdef DIAGNOSTIC 217 edp->console = 0; 218 #endif 219 } 220 edp->cbcookie = cbcookie; 221 222 edp->tabs = malloc(edp->ncols, M_DEVBUF, M_NOWAIT); 223 edp->dblwid = malloc(edp->nrows, M_DEVBUF, M_NOWAIT); 224 memset(edp->dblwid, 0, edp->nrows); 225 edp->dw = 0; 226 edp->dcsarg = malloc(DCS_MAXLEN, M_DEVBUF, M_NOWAIT); 227 edp->isolatin1tab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT); 228 edp->decgraphtab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT); 229 edp->dectechtab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT); 230 edp->nrctab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT); 231 vt100_initchartables(edp); 232 wsemul_vt100_reset(edp); 233 return (edp); 234 } 235 236 void 237 wsemul_vt100_detach(cookie, crowp, ccolp) 238 void *cookie; 239 u_int *crowp, *ccolp; 240 { 241 struct wsemul_vt100_emuldata *edp = cookie; 242 243 *crowp = edp->crow; 244 *ccolp = edp->ccol; 245 #define f(ptr) if (ptr) {free(ptr, M_DEVBUF); ptr = 0;} 246 f(edp->tabs) 247 f(edp->dblwid) 248 f(edp->dcsarg) 249 f(edp->isolatin1tab) 250 f(edp->decgraphtab) 251 f(edp->dectechtab) 252 f(edp->nrctab) 253 #undef f 254 if (edp != &wsemul_vt100_console_emuldata) 255 free(edp, M_DEVBUF); 256 } 257 258 void 259 wsemul_vt100_resetop(cookie, op) 260 void *cookie; 261 enum wsemul_resetops op; 262 { 263 struct wsemul_vt100_emuldata *edp = cookie; 264 265 switch (op) { 266 case WSEMUL_RESET: 267 wsemul_vt100_reset(edp); 268 break; 269 case WSEMUL_SYNCFONT: 270 vt100_initchartables(edp); 271 break; 272 case WSEMUL_CLEARSCREEN: 273 wsemul_vt100_ed(edp, 2); 274 edp->ccol = edp->crow = 0; 275 (*edp->emulops->cursor)(edp->emulcookie, 276 edp->flags & VTFL_CURSORON, 0, 0); 277 break; 278 default: 279 break; 280 } 281 } 282 283 void 284 wsemul_vt100_reset(edp) 285 struct wsemul_vt100_emuldata *edp; 286 { 287 int i; 288 289 edp->state = VT100_EMUL_STATE_NORMAL; 290 edp->flags = VTFL_DECAWM | VTFL_CURSORON; 291 edp->bkgdattr = edp->curattr = edp->defattr; 292 edp->attrflags = 0; 293 edp->fgcol = WSCOL_WHITE; 294 edp->bgcol = WSCOL_BLACK; 295 edp->scrreg_startrow = 0; 296 edp->scrreg_nrows = edp->nrows; 297 if (edp->tabs) { 298 memset(edp->tabs, 0, edp->ncols); 299 for (i = 8; i < edp->ncols; i += 8) 300 edp->tabs[i] = 1; 301 } 302 edp->dcspos = 0; 303 edp->dcstype = 0; 304 edp->chartab_G[0] = 0; 305 edp->chartab_G[1] = edp->nrctab; /* ??? */ 306 edp->chartab_G[2] = edp->isolatin1tab; 307 edp->chartab_G[3] = edp->isolatin1tab; 308 edp->chartab0 = 0; 309 edp->chartab1 = 2; 310 edp->sschartab = 0; 311 } 312 313 /* 314 * now all the state machine bits 315 */ 316 317 static void 318 wsemul_vt100_output_normal(edp, c, kernel) 319 struct wsemul_vt100_emuldata *edp; 320 u_char c; 321 int kernel; 322 { 323 u_int *ct, dc; 324 325 if ((edp->flags & (VTFL_LASTCHAR | VTFL_DECAWM)) == 326 (VTFL_LASTCHAR | VTFL_DECAWM)) { 327 if (ROWS_BELOW > 0) { 328 edp->crow++; 329 CHECK_DW; 330 } else 331 wsemul_vt100_scrollup(edp, 1); 332 edp->ccol = 0; 333 edp->flags &= ~VTFL_LASTCHAR; 334 } 335 336 if (c & 0x80) { 337 c &= 0x7f; 338 ct = edp->chartab_G[edp->chartab1]; 339 } else { 340 if (edp->sschartab) { 341 ct = edp->chartab_G[edp->sschartab]; 342 edp->sschartab = 0; 343 } else 344 ct = edp->chartab_G[edp->chartab0]; 345 } 346 dc = (ct ? ct[c] : c); 347 348 if ((edp->flags & VTFL_INSERTMODE) && COLS_LEFT) 349 COPYCOLS(edp->ccol, edp->ccol + 1, COLS_LEFT); 350 351 (*edp->emulops->putchar)(edp->emulcookie, edp->crow, 352 edp->ccol << edp->dw, dc, 353 kernel ? edp->kernattr : edp->curattr); 354 355 if (COLS_LEFT) 356 edp->ccol++; 357 else 358 edp->flags |= VTFL_LASTCHAR; 359 } 360 361 static void 362 wsemul_vt100_output_c0c1(edp, c, kernel) 363 struct wsemul_vt100_emuldata *edp; 364 u_char c; 365 int kernel; 366 { 367 u_int n; 368 369 switch (c) { 370 case ASCII_NUL: 371 default: 372 /* ignore */ 373 break; 374 case ASCII_BEL: 375 wsdisplay_emulbell(edp->cbcookie); 376 break; 377 case ASCII_BS: 378 if (edp->ccol > 0) { 379 edp->ccol--; 380 edp->flags &= ~VTFL_LASTCHAR; 381 } 382 break; 383 case ASCII_CR: 384 edp->ccol = 0; 385 edp->flags &= ~VTFL_LASTCHAR; 386 break; 387 case ASCII_HT: 388 if (edp->tabs) { 389 if (!COLS_LEFT) 390 break; 391 for (n = edp->ccol + 1; n < NCOLS - 1; n++) 392 if (edp->tabs[n]) 393 break; 394 } else { 395 n = edp->ccol + min(8 - (edp->ccol & 7), COLS_LEFT); 396 } 397 edp->ccol = n; 398 break; 399 case ASCII_SO: /* LS1 */ 400 edp->chartab0 = 1; 401 break; 402 case ASCII_SI: /* LS0 */ 403 edp->chartab0 = 0; 404 break; 405 case ASCII_ESC: 406 if (kernel) { 407 printf("wsemul_vt100_output_c0c1: ESC in kernel output ignored\n"); 408 break; /* ignore the ESC */ 409 } 410 411 if (edp->state == VT100_EMUL_STATE_STRING) { 412 /* might be a string end */ 413 edp->state = VT100_EMUL_STATE_STRING_ESC; 414 } else { 415 /* XXX cancel current escape sequence */ 416 edp->state = VT100_EMUL_STATE_ESC; 417 } 418 break; 419 #if 0 420 case CSI: /* 8-bit */ 421 /* XXX cancel current escape sequence */ 422 edp->nargs = 0; 423 memset(edp->args, 0, sizeof (edp->args)); 424 edp->modif1 = edp->modif2 = '\0'; 425 edp->state = VT100_EMUL_STATE_CSI; 426 break; 427 case DCS: /* 8-bit */ 428 /* XXX cancel current escape sequence */ 429 edp->nargs = 0; 430 memset(edp->args, 0, sizeof (edp->args)); 431 edp->state = VT100_EMUL_STATE_DCS; 432 break; 433 case ST: /* string end 8-bit */ 434 /* XXX only in VT100_EMUL_STATE_STRING */ 435 wsemul_vt100_handle_dcs(edp); 436 return (VT100_EMUL_STATE_NORMAL); 437 #endif 438 case ASCII_LF: 439 case ASCII_VT: 440 case ASCII_FF: 441 if (ROWS_BELOW > 0) { 442 edp->crow++; 443 CHECK_DW; 444 } else 445 wsemul_vt100_scrollup(edp, 1); 446 break; 447 } 448 } 449 450 static u_int 451 wsemul_vt100_output_esc(edp, c) 452 struct wsemul_vt100_emuldata *edp; 453 u_char c; 454 { 455 u_int newstate = VT100_EMUL_STATE_NORMAL; 456 int i; 457 458 switch (c) { 459 case '[': /* CSI */ 460 edp->nargs = 0; 461 memset(edp->args, 0, sizeof (edp->args)); 462 edp->modif1 = edp->modif2 = '\0'; 463 newstate = VT100_EMUL_STATE_CSI; 464 break; 465 case '7': /* DECSC */ 466 edp->savedcursor_row = edp->crow; 467 edp->savedcursor_col = edp->ccol; 468 edp->savedattr = edp->curattr; 469 edp->savedbkgdattr = edp->bkgdattr; 470 edp->savedattrflags = edp->attrflags; 471 edp->savedfgcol = edp->fgcol; 472 edp->savedbgcol = edp->bgcol; 473 for (i = 0; i < 4; i++) 474 edp->savedchartab_G[i] = edp->chartab_G[i]; 475 edp->savedchartab0 = edp->chartab0; 476 edp->savedchartab1 = edp->chartab1; 477 break; 478 case '8': /* DECRC */ 479 edp->crow = edp->savedcursor_row; 480 edp->ccol = edp->savedcursor_col; 481 edp->curattr = edp->savedattr; 482 edp->bkgdattr = edp->savedbkgdattr; 483 edp->attrflags = edp->savedattrflags; 484 edp->fgcol = edp->savedfgcol; 485 edp->bgcol = edp->savedbgcol; 486 for (i = 0; i < 4; i++) 487 edp->chartab_G[i] = edp->savedchartab_G[i]; 488 edp->chartab0 = edp->savedchartab0; 489 edp->chartab1 = edp->savedchartab1; 490 break; 491 case '=': /* DECKPAM application mode */ 492 edp->flags |= VTFL_APPLKEYPAD; 493 break; 494 case '>': /* DECKPNM numeric mode */ 495 edp->flags &= ~VTFL_APPLKEYPAD; 496 break; 497 case 'E': /* NEL */ 498 edp->ccol = 0; 499 /* FALLTHRU */ 500 case 'D': /* IND */ 501 if (ROWS_BELOW > 0) { 502 edp->crow++; 503 CHECK_DW; 504 break; 505 } 506 wsemul_vt100_scrollup(edp, 1); 507 break; 508 case 'H': /* HTS */ 509 KASSERT(edp->tabs != 0); 510 edp->tabs[edp->ccol] = 1; 511 break; 512 case '~': /* LS1R */ 513 edp->chartab1 = 1; 514 break; 515 case 'n': /* LS2 */ 516 edp->chartab0 = 2; 517 break; 518 case '}': /* LS2R */ 519 edp->chartab1 = 2; 520 break; 521 case 'o': /* LS3 */ 522 edp->chartab0 = 3; 523 break; 524 case '|': /* LS3R */ 525 edp->chartab1 = 3; 526 break; 527 case 'N': /* SS2 */ 528 edp->sschartab = 2; 529 break; 530 case 'O': /* SS3 */ 531 edp->sschartab = 3; 532 break; 533 case 'M': /* RI */ 534 if (ROWS_ABOVE > 0) { 535 edp->crow--; 536 CHECK_DW; 537 break; 538 } 539 wsemul_vt100_scrolldown(edp, 1); 540 break; 541 case 'P': /* DCS */ 542 edp->nargs = 0; 543 memset(edp->args, 0, sizeof (edp->args)); 544 newstate = VT100_EMUL_STATE_DCS; 545 break; 546 case 'c': /* RIS */ 547 wsemul_vt100_reset(edp); 548 wsemul_vt100_ed(edp, 2); 549 edp->ccol = edp->crow = 0; 550 break; 551 case '(': case ')': case '*': case '+': /* SCS */ 552 edp->designating = c - '('; 553 newstate = VT100_EMUL_STATE_SCS94; 554 break; 555 case '-': case '.': case '/': /* SCS */ 556 edp->designating = c - '-' + 1; 557 newstate = VT100_EMUL_STATE_SCS96; 558 break; 559 case '#': 560 newstate = VT100_EMUL_STATE_ESC_HASH; 561 break; 562 case ' ': /* 7/8 bit */ 563 newstate = VT100_EMUL_STATE_ESC_SPC; 564 break; 565 case ']': /* OSC operating system command */ 566 case '^': /* PM privacy message */ 567 case '_': /* APC application program command */ 568 /* ignored */ 569 newstate = VT100_EMUL_STATE_STRING; 570 break; 571 case '<': /* exit VT52 mode - ignored */ 572 break; 573 default: 574 #ifdef VT100_PRINTUNKNOWN 575 printf("ESC%c unknown\n", c); 576 #endif 577 break; 578 } 579 580 return (newstate); 581 } 582 583 static u_int 584 wsemul_vt100_output_scs94(edp, c) 585 struct wsemul_vt100_emuldata *edp; 586 u_char c; 587 { 588 u_int newstate = VT100_EMUL_STATE_NORMAL; 589 590 switch (c) { 591 case '%': /* probably DEC supplemental graphic */ 592 newstate = VT100_EMUL_STATE_SCS94_PERCENT; 593 break; 594 case 'A': /* british / national */ 595 edp->chartab_G[edp->designating] = edp->nrctab; 596 break; 597 case 'B': /* ASCII */ 598 edp->chartab_G[edp->designating] = 0; 599 break; 600 case '<': /* user preferred supplemental */ 601 /* XXX not really "user" preferred */ 602 edp->chartab_G[edp->designating] = edp->isolatin1tab; 603 break; 604 case '0': /* DEC special graphic */ 605 edp->chartab_G[edp->designating] = edp->decgraphtab; 606 break; 607 case '>': /* DEC tech */ 608 edp->chartab_G[edp->designating] = edp->dectechtab; 609 break; 610 default: 611 #ifdef VT100_PRINTUNKNOWN 612 printf("ESC%c%c unknown\n", edp->designating + '(', c); 613 #endif 614 break; 615 } 616 return (newstate); 617 } 618 619 static u_int 620 wsemul_vt100_output_scs94_percent(edp, c) 621 struct wsemul_vt100_emuldata *edp; 622 u_char c; 623 { 624 switch (c) { 625 case '5': /* DEC supplemental graphic */ 626 /* XXX there are differences */ 627 edp->chartab_G[edp->designating] = edp->isolatin1tab; 628 break; 629 default: 630 #ifdef VT100_PRINTUNKNOWN 631 printf("ESC%c%%%c unknown\n", edp->designating + '(', c); 632 #endif 633 break; 634 } 635 return (VT100_EMUL_STATE_NORMAL); 636 } 637 638 static u_int 639 wsemul_vt100_output_scs96(edp, c) 640 struct wsemul_vt100_emuldata *edp; 641 u_char c; 642 { 643 u_int newstate = VT100_EMUL_STATE_NORMAL; 644 int nrc; 645 646 switch (c) { 647 case '%': /* probably portugese */ 648 newstate = VT100_EMUL_STATE_SCS96_PERCENT; 649 break; 650 case 'A': /* ISO-latin-1 supplemental */ 651 edp->chartab_G[edp->designating] = edp->isolatin1tab; 652 break; 653 case '4': /* dutch */ 654 nrc = 1; 655 goto setnrc; 656 case '5': case 'C': /* finnish */ 657 nrc = 2; 658 goto setnrc; 659 case 'R': /* french */ 660 nrc = 3; 661 goto setnrc; 662 case 'Q': /* french canadian */ 663 nrc = 4; 664 goto setnrc; 665 case 'K': /* german */ 666 nrc = 5; 667 goto setnrc; 668 case 'Y': /* italian */ 669 nrc = 6; 670 goto setnrc; 671 case 'E': case '6': /* norwegian / danish */ 672 nrc = 7; 673 goto setnrc; 674 case 'Z': /* spanish */ 675 nrc = 9; 676 goto setnrc; 677 case '7': case 'H': /* swedish */ 678 nrc = 10; 679 goto setnrc; 680 case '=': /* swiss */ 681 nrc = 11; 682 setnrc: 683 vt100_setnrc(edp, nrc); /* what table ??? */ 684 break; 685 default: 686 #ifdef VT100_PRINTUNKNOWN 687 printf("ESC%c%c unknown\n", edp->designating + '-' - 1, c); 688 #endif 689 break; 690 } 691 return (newstate); 692 } 693 694 static u_int 695 wsemul_vt100_output_scs96_percent(edp, c) 696 struct wsemul_vt100_emuldata *edp; 697 u_char c; 698 { 699 switch (c) { 700 case '6': /* portugese */ 701 vt100_setnrc(edp, 8); 702 break; 703 default: 704 #ifdef VT100_PRINTUNKNOWN 705 printf("ESC%c%%%c unknown\n", edp->designating + '-', c); 706 #endif 707 break; 708 } 709 return (VT100_EMUL_STATE_NORMAL); 710 } 711 712 static u_int 713 wsemul_vt100_output_esc_spc(edp, c) 714 struct wsemul_vt100_emuldata *edp; 715 u_char c; 716 { 717 switch (c) { 718 case 'F': /* 7-bit controls */ 719 case 'G': /* 8-bit controls */ 720 #ifdef VT100_PRINTNOTIMPL 721 printf("ESC<SPC>%c ignored\n", c); 722 #endif 723 break; 724 default: 725 #ifdef VT100_PRINTUNKNOWN 726 printf("ESC<SPC>%c unknown\n", c); 727 #endif 728 break; 729 } 730 return (VT100_EMUL_STATE_NORMAL); 731 } 732 733 static u_int 734 wsemul_vt100_output_string(edp, c) 735 struct wsemul_vt100_emuldata *edp; 736 u_char c; 737 { 738 if (edp->dcstype && edp->dcspos < DCS_MAXLEN) 739 edp->dcsarg[edp->dcspos++] = c; 740 return (VT100_EMUL_STATE_STRING); 741 } 742 743 static u_int 744 wsemul_vt100_output_string_esc(edp, c) 745 struct wsemul_vt100_emuldata *edp; 746 u_char c; 747 { 748 if (c == '\\') { /* ST complete */ 749 wsemul_vt100_handle_dcs(edp); 750 return (VT100_EMUL_STATE_NORMAL); 751 } else 752 return (VT100_EMUL_STATE_STRING); 753 } 754 755 static u_int 756 wsemul_vt100_output_dcs(edp, c) 757 struct wsemul_vt100_emuldata *edp; 758 u_char c; 759 { 760 u_int newstate = VT100_EMUL_STATE_DCS; 761 762 switch (c) { 763 case '0': case '1': case '2': case '3': case '4': 764 case '5': case '6': case '7': case '8': case '9': 765 /* argument digit */ 766 if (edp->nargs > VT100_EMUL_NARGS - 1) 767 break; 768 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) + 769 (c - '0'); 770 break; 771 case ';': /* argument terminator */ 772 edp->nargs++; 773 break; 774 default: 775 edp->nargs++; 776 if (edp->nargs > VT100_EMUL_NARGS) { 777 #ifdef VT100_DEBUG 778 printf("vt100: too many arguments\n"); 779 #endif 780 edp->nargs = VT100_EMUL_NARGS; 781 } 782 newstate = VT100_EMUL_STATE_STRING; 783 switch (c) { 784 case '$': 785 newstate = VT100_EMUL_STATE_DCS_DOLLAR; 786 break; 787 case '{': /* DECDLD soft charset */ 788 case '!': /* DECRQUPSS user preferred supplemental set */ 789 /* 'u' must follow - need another state */ 790 case '|': /* DECUDK program F6..F20 */ 791 #ifdef VT100_PRINTNOTIMPL 792 printf("DCS%c ignored\n", c); 793 #endif 794 break; 795 default: 796 #ifdef VT100_PRINTUNKNOWN 797 printf("DCS%c (%d, %d) unknown\n", c, ARG(0), ARG(1)); 798 #endif 799 break; 800 } 801 } 802 803 return (newstate); 804 } 805 806 static u_int 807 wsemul_vt100_output_dcs_dollar(edp, c) 808 struct wsemul_vt100_emuldata *edp; 809 u_char c; 810 { 811 switch (c) { 812 case 'p': /* DECRSTS terminal state restore */ 813 case 'q': /* DECRQSS control function request */ 814 #ifdef VT100_PRINTNOTIMPL 815 printf("DCS$%c ignored\n", c); 816 #endif 817 break; 818 case 't': /* DECRSPS restore presentation state */ 819 switch (ARG(0)) { 820 case 0: /* error */ 821 break; 822 case 1: /* cursor information restore */ 823 #ifdef VT100_PRINTNOTIMPL 824 printf("DCS1$t ignored\n"); 825 #endif 826 break; 827 case 2: /* tab stop restore */ 828 edp->dcspos = 0; 829 edp->dcstype = DCSTYPE_TABRESTORE; 830 break; 831 default: 832 #ifdef VT100_PRINTUNKNOWN 833 printf("DCS%d$t unknown\n", ARG(0)); 834 #endif 835 break; 836 } 837 break; 838 default: 839 #ifdef VT100_PRINTUNKNOWN 840 printf("DCS$%c (%d, %d) unknown\n", c, ARG(0), ARG(1)); 841 #endif 842 break; 843 } 844 return (VT100_EMUL_STATE_STRING); 845 } 846 847 static u_int 848 wsemul_vt100_output_esc_hash(edp, c) 849 struct wsemul_vt100_emuldata *edp; 850 u_char c; 851 { 852 int i; 853 854 switch (c) { 855 case '5': /* DECSWL single width, single height */ 856 if (edp->dw) { 857 for (i = 0; i < edp->ncols / 2; i++) 858 (*edp->emulops->copycols)(edp->emulcookie, 859 edp->crow, 860 2 * i, i, 1); 861 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 862 i, edp->ncols - i, 863 edp->bkgdattr); 864 edp->dblwid[edp->crow] = 0; 865 edp->dw = 0; 866 } 867 break; 868 case '6': /* DECDWL double width, single height */ 869 case '3': /* DECDHL double width, double height, top half */ 870 case '4': /* DECDHL double width, double height, bottom half */ 871 if (!edp->dw) { 872 for (i = edp->ncols / 2 - 1; i >= 0; i--) 873 (*edp->emulops->copycols)(edp->emulcookie, 874 edp->crow, 875 i, 2 * i, 1); 876 for (i = 0; i < edp->ncols / 2; i++) 877 (*edp->emulops->erasecols)(edp->emulcookie, 878 edp->crow, 879 2 * i + 1, 1, 880 edp->bkgdattr); 881 edp->dblwid[edp->crow] = 1; 882 edp->dw = 1; 883 if (edp->ccol > (edp->ncols >> 1) - 1) 884 edp->ccol = (edp->ncols >> 1) - 1; 885 } 886 break; 887 case '8': { /* DECALN */ 888 int i, j; 889 for (i = 0; i < edp->nrows; i++) 890 for (j = 0; j < edp->ncols; j++) 891 (*edp->emulops->putchar)(edp->emulcookie, i, j, 892 'E', edp->curattr); 893 } 894 edp->ccol = 0; 895 edp->crow = 0; 896 break; 897 default: 898 #ifdef VT100_PRINTUNKNOWN 899 printf("ESC#%c unknown\n", c); 900 #endif 901 break; 902 } 903 return (VT100_EMUL_STATE_NORMAL); 904 } 905 906 static u_int 907 wsemul_vt100_output_csi(edp, c) 908 struct wsemul_vt100_emuldata *edp; 909 u_char c; 910 { 911 u_int newstate = VT100_EMUL_STATE_CSI; 912 913 switch (c) { 914 case '0': case '1': case '2': case '3': case '4': 915 case '5': case '6': case '7': case '8': case '9': 916 /* argument digit */ 917 if (edp->nargs > VT100_EMUL_NARGS - 1) 918 break; 919 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) + 920 (c - '0'); 921 break; 922 case ';': /* argument terminator */ 923 edp->nargs++; 924 break; 925 case '?': /* DEC specific */ 926 case '>': /* DA query */ 927 edp->modif1 = c; 928 break; 929 case '!': 930 case '"': 931 case '$': 932 case '&': 933 edp->modif2 = c; 934 break; 935 default: /* end of escape sequence */ 936 edp->nargs++; 937 if (edp->nargs > VT100_EMUL_NARGS) { 938 #ifdef VT100_DEBUG 939 printf("vt100: too many arguments\n"); 940 #endif 941 edp->nargs = VT100_EMUL_NARGS; 942 } 943 wsemul_vt100_handle_csi(edp, c); 944 newstate = VT100_EMUL_STATE_NORMAL; 945 break; 946 } 947 return (newstate); 948 } 949 950 void 951 wsemul_vt100_output(cookie, data, count, kernel) 952 void *cookie; 953 const u_char *data; 954 u_int count; 955 int kernel; 956 { 957 struct wsemul_vt100_emuldata *edp = cookie; 958 959 #ifdef DIAGNOSTIC 960 if (kernel && !edp->console) 961 panic("wsemul_vt100_output: kernel output, not console"); 962 #endif 963 964 if (edp->flags & VTFL_CURSORON) 965 (*edp->emulops->cursor)(edp->emulcookie, 0, 966 edp->crow, edp->ccol << edp->dw); 967 for (; count > 0; data++, count--) { 968 if ((*data & 0x7f) < 0x20) { 969 wsemul_vt100_output_c0c1(edp, *data, kernel); 970 continue; 971 } 972 if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) { 973 wsemul_vt100_output_normal(edp, *data, kernel); 974 continue; 975 } 976 #ifdef DIAGNOSTIC 977 if (edp->state > sizeof(vt100_output) / sizeof(vt100_output[0])) 978 panic("wsemul_vt100: invalid state %d\n", edp->state); 979 #endif 980 edp->state = vt100_output[edp->state - 1](edp, *data); 981 } 982 if (edp->flags & VTFL_CURSORON) 983 (*edp->emulops->cursor)(edp->emulcookie, 1, 984 edp->crow, edp->ccol << edp->dw); 985 } 986