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