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