wsemul_vt100.c revision 1.12
1219820Sjeff/* $NetBSD: wsemul_vt100.c,v 1.12 1999/11/03 15:55:29 mycroft Exp $ */ 2219820Sjeff 3219820Sjeff/* 4219820Sjeff * Copyright (c) 1998 5219820Sjeff * Matthias Drochner. All rights reserved. 6219820Sjeff * 7219820Sjeff * Redistribution and use in source and binary forms, with or without 8219820Sjeff * modification, are permitted provided that the following conditions 9219820Sjeff * are met: 10219820Sjeff * 1. Redistributions of source code must retain the above copyright 11219820Sjeff * notice, this list of conditions and the following disclaimer. 12219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright 13219820Sjeff * notice, this list of conditions and the following disclaimer in the 14219820Sjeff * documentation and/or other materials provided with the distribution. 15219820Sjeff * 3. All advertising materials mentioning features or use of this software 16219820Sjeff * must display the following acknowledgement: 17219820Sjeff * This product includes software developed for the NetBSD Project 18219820Sjeff * by Matthias Drochner. 19219820Sjeff * 4. The name of the author may not be used to endorse or promote products 20219820Sjeff * derived from this software without specific prior written permission. 21219820Sjeff * 22219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23219820Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24219820Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25219820Sjeff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26219820Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27219820Sjeff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28219820Sjeff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29219820Sjeff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30219820Sjeff * (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 49void *wsemul_vt100_cnattach __P((const struct wsscreen_descr *, void *, 50 int, int, long)); 51void *wsemul_vt100_attach __P((int console, const struct wsscreen_descr *, 52 void *, int, int, void *, long)); 53void wsemul_vt100_output __P((void *cookie, const u_char *data, u_int count, 54 int)); 55void wsemul_vt100_detach __P((void *cookie, u_int *crowp, u_int *ccolp)); 56void wsemul_vt100_resetop __P((void *, enum wsemul_resetops)); 57 58const 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 68struct wsemul_vt100_emuldata wsemul_vt100_console_emuldata; 69 70static void wsemul_vt100_init __P((struct wsemul_vt100_emuldata *, 71 const struct wsscreen_descr *, 72 void *, int, int, long)); 73 74static void wsemul_vt100_output_normal __P((struct wsemul_vt100_emuldata *, 75 u_char, int)); 76static void wsemul_vt100_output_c0c1 __P((struct wsemul_vt100_emuldata *, 77 u_char, int)); 78typedef u_int vt100_handler __P((struct wsemul_vt100_emuldata *, u_char)); 79static vt100_handler 80wsemul_vt100_output_esc, 81wsemul_vt100_output_csi, 82wsemul_vt100_output_scs94, 83wsemul_vt100_output_scs94_percent, 84wsemul_vt100_output_scs96, 85wsemul_vt100_output_scs96_percent, 86wsemul_vt100_output_esc_hash, 87wsemul_vt100_output_esc_spc, 88wsemul_vt100_output_string, 89wsemul_vt100_output_string_esc, 90wsemul_vt100_output_dcs, 91wsemul_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 107vt100_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 122static void 123wsemul_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 140void * 141wsemul_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 197void * 198wsemul_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 236void 237wsemul_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 258void 259wsemul_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 283void 284wsemul_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->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 317static void 318wsemul_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 361static void 362wsemul_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#ifdef DIAGNOSTIC 407 if (kernel) 408 panic("ESC in kernel output"); 409#endif 410 if (edp->state == VT100_EMUL_STATE_STRING) { 411 /* might be a string end */ 412 edp->state = VT100_EMUL_STATE_STRING_ESC; 413 } else { 414 /* XXX cancel current escape sequence */ 415 edp->state = VT100_EMUL_STATE_ESC; 416 } 417 break; 418#if 0 419 case CSI: /* 8-bit */ 420 /* XXX cancel current escape sequence */ 421 edp->nargs = 0; 422 memset(edp->args, 0, sizeof (edp->args)); 423 edp->modif1 = edp->modif2 = '\0'; 424 edp->state = VT100_EMUL_STATE_CSI; 425 break; 426 case DCS: /* 8-bit */ 427 /* XXX cancel current escape sequence */ 428 edp->nargs = 0; 429 memset(edp->args, 0, sizeof (edp->args)); 430 edp->state = VT100_EMUL_STATE_DCS; 431 break; 432 case ST: /* string end 8-bit */ 433 /* XXX only in VT100_EMUL_STATE_STRING */ 434 wsemul_vt100_handle_dcs(edp); 435 return (VT100_EMUL_STATE_NORMAL); 436#endif 437 case ASCII_LF: 438 case ASCII_VT: 439 case ASCII_FF: 440 if (ROWS_BELOW > 0) { 441 edp->crow++; 442 CHECK_DW; 443 } else 444 wsemul_vt100_scrollup(edp, 1); 445 break; 446 } 447} 448 449static u_int 450wsemul_vt100_output_esc(edp, c) 451 struct wsemul_vt100_emuldata *edp; 452 u_char c; 453{ 454 u_int newstate = VT100_EMUL_STATE_NORMAL; 455 int i; 456 457 switch (c) { 458 case '[': /* CSI */ 459 edp->nargs = 0; 460 memset(edp->args, 0, sizeof (edp->args)); 461 edp->modif1 = edp->modif2 = '\0'; 462 newstate = VT100_EMUL_STATE_CSI; 463 break; 464 case '7': /* DECSC */ 465 edp->savedcursor_row = edp->crow; 466 edp->savedcursor_col = edp->ccol; 467 edp->savedattr = edp->curattr; 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->attrflags = edp->savedattrflags; 481 edp->fgcol = edp->savedfgcol; 482 edp->bgcol = edp->savedbgcol; 483 for (i = 0; i < 4; i++) 484 edp->chartab_G[i] = edp->savedchartab_G[i]; 485 edp->chartab0 = edp->savedchartab0; 486 edp->chartab1 = edp->savedchartab1; 487 break; 488 case '=': /* DECKPAM application mode */ 489 edp->flags |= VTFL_APPLKEYPAD; 490 break; 491 case '>': /* DECKPNM numeric mode */ 492 edp->flags &= ~VTFL_APPLKEYPAD; 493 break; 494 case 'E': /* NEL */ 495 edp->ccol = 0; 496 /* FALLTHRU */ 497 case 'D': /* IND */ 498 if (ROWS_BELOW > 0) { 499 edp->crow++; 500 CHECK_DW; 501 break; 502 } 503 wsemul_vt100_scrollup(edp, 1); 504 break; 505 case 'H': /* HTS */ 506 KASSERT(edp->tabs != 0); 507 edp->tabs[edp->ccol] = 1; 508 break; 509 case '~': /* LS1R */ 510 edp->chartab1 = 1; 511 break; 512 case 'n': /* LS2 */ 513 edp->chartab0 = 2; 514 break; 515 case '}': /* LS2R */ 516 edp->chartab1 = 2; 517 break; 518 case 'o': /* LS3 */ 519 edp->chartab0 = 3; 520 break; 521 case '|': /* LS3R */ 522 edp->chartab1 = 3; 523 break; 524 case 'N': /* SS2 */ 525 edp->sschartab = 2; 526 break; 527 case 'O': /* SS3 */ 528 edp->sschartab = 3; 529 break; 530 case 'M': /* RI */ 531 if (ROWS_ABOVE > 0) { 532 edp->crow--; 533 CHECK_DW; 534 break; 535 } 536 wsemul_vt100_scrolldown(edp, 1); 537 break; 538 case 'P': /* DCS */ 539 edp->nargs = 0; 540 memset(edp->args, 0, sizeof (edp->args)); 541 newstate = VT100_EMUL_STATE_DCS; 542 break; 543 case 'c': /* RIS */ 544 wsemul_vt100_reset(edp); 545 wsemul_vt100_ed(edp, 2); 546 edp->ccol = edp->crow = 0; 547 break; 548 case '(': case ')': case '*': case '+': /* SCS */ 549 edp->designating = c - '('; 550 newstate = VT100_EMUL_STATE_SCS94; 551 break; 552 case '-': case '.': case '/': /* SCS */ 553 edp->designating = c - '-' + 1; 554 newstate = VT100_EMUL_STATE_SCS96; 555 break; 556 case '#': 557 newstate = VT100_EMUL_STATE_ESC_HASH; 558 break; 559 case ' ': /* 7/8 bit */ 560 newstate = VT100_EMUL_STATE_ESC_SPC; 561 break; 562 case ']': /* OSC operating system command */ 563 case '^': /* PM privacy message */ 564 case '_': /* APC application program command */ 565 /* ignored */ 566 newstate = VT100_EMUL_STATE_STRING; 567 break; 568 case '<': /* exit VT52 mode - ignored */ 569 break; 570 default: 571#ifdef VT100_PRINTUNKNOWN 572 printf("ESC%c unknown\n", c); 573#endif 574 break; 575 } 576 577 return (newstate); 578} 579 580static u_int 581wsemul_vt100_output_scs94(edp, c) 582 struct wsemul_vt100_emuldata *edp; 583 u_char c; 584{ 585 u_int newstate = VT100_EMUL_STATE_NORMAL; 586 587 switch (c) { 588 case '%': /* probably DEC supplemental graphic */ 589 newstate = VT100_EMUL_STATE_SCS94_PERCENT; 590 break; 591 case 'A': /* british / national */ 592 edp->chartab_G[edp->designating] = edp->nrctab; 593 break; 594 case 'B': /* ASCII */ 595 edp->chartab_G[edp->designating] = 0; 596 break; 597 case '<': /* user preferred supplemental */ 598 /* XXX not really "user" preferred */ 599 edp->chartab_G[edp->designating] = edp->isolatin1tab; 600 break; 601 case '0': /* DEC special graphic */ 602 edp->chartab_G[edp->designating] = edp->decgraphtab; 603 break; 604 case '>': /* DEC tech */ 605 edp->chartab_G[edp->designating] = edp->dectechtab; 606 break; 607 default: 608#ifdef VT100_PRINTUNKNOWN 609 printf("ESC%c%c unknown\n", edp->designating + '(', c); 610#endif 611 break; 612 } 613 return (newstate); 614} 615 616static u_int 617wsemul_vt100_output_scs94_percent(edp, c) 618 struct wsemul_vt100_emuldata *edp; 619 u_char c; 620{ 621 switch (c) { 622 case '5': /* DEC supplemental graphic */ 623 /* XXX there are differences */ 624 edp->chartab_G[edp->designating] = edp->isolatin1tab; 625 break; 626 default: 627#ifdef VT100_PRINTUNKNOWN 628 printf("ESC%c%%%c unknown\n", edp->designating + '(', c); 629#endif 630 break; 631 } 632 return (VT100_EMUL_STATE_NORMAL); 633} 634 635static u_int 636wsemul_vt100_output_scs96(edp, c) 637 struct wsemul_vt100_emuldata *edp; 638 u_char c; 639{ 640 u_int newstate = VT100_EMUL_STATE_NORMAL; 641 int nrc; 642 643 switch (c) { 644 case '%': /* probably portugese */ 645 newstate = VT100_EMUL_STATE_SCS96_PERCENT; 646 break; 647 case 'A': /* ISO-latin-1 supplemental */ 648 edp->chartab_G[edp->designating] = edp->isolatin1tab; 649 break; 650 case '4': /* dutch */ 651 nrc = 1; 652 goto setnrc; 653 case '5': case 'C': /* finnish */ 654 nrc = 2; 655 goto setnrc; 656 case 'R': /* french */ 657 nrc = 3; 658 goto setnrc; 659 case 'Q': /* french canadian */ 660 nrc = 4; 661 goto setnrc; 662 case 'K': /* german */ 663 nrc = 5; 664 goto setnrc; 665 case 'Y': /* italian */ 666 nrc = 6; 667 goto setnrc; 668 case 'E': case '6': /* norwegian / danish */ 669 nrc = 7; 670 goto setnrc; 671 case 'Z': /* spanish */ 672 nrc = 9; 673 goto setnrc; 674 case '7': case 'H': /* swedish */ 675 nrc = 10; 676 goto setnrc; 677 case '=': /* swiss */ 678 nrc = 11; 679setnrc: 680 vt100_setnrc(edp, nrc); /* what table ??? */ 681 break; 682 default: 683#ifdef VT100_PRINTUNKNOWN 684 printf("ESC%c%c unknown\n", edp->designating + '-' - 1, c); 685#endif 686 break; 687 } 688 return (newstate); 689} 690 691static u_int 692wsemul_vt100_output_scs96_percent(edp, c) 693 struct wsemul_vt100_emuldata *edp; 694 u_char c; 695{ 696 switch (c) { 697 case '6': /* portugese */ 698 vt100_setnrc(edp, 8); 699 break; 700 default: 701#ifdef VT100_PRINTUNKNOWN 702 printf("ESC%c%%%c unknown\n", edp->designating + '-', c); 703#endif 704 break; 705 } 706 return (VT100_EMUL_STATE_NORMAL); 707} 708 709static u_int 710wsemul_vt100_output_esc_spc(edp, c) 711 struct wsemul_vt100_emuldata *edp; 712 u_char c; 713{ 714 switch (c) { 715 case 'F': /* 7-bit controls */ 716 case 'G': /* 8-bit controls */ 717#ifdef VT100_PRINTNOTIMPL 718 printf("ESC<SPC>%c ignored\n", c); 719#endif 720 break; 721 default: 722#ifdef VT100_PRINTUNKNOWN 723 printf("ESC<SPC>%c unknown\n", c); 724#endif 725 break; 726 } 727 return (VT100_EMUL_STATE_NORMAL); 728} 729 730static u_int 731wsemul_vt100_output_string(edp, c) 732 struct wsemul_vt100_emuldata *edp; 733 u_char c; 734{ 735 if (edp->dcstype && edp->dcspos < DCS_MAXLEN) 736 edp->dcsarg[edp->dcspos++] = c; 737 return (VT100_EMUL_STATE_STRING); 738} 739 740static u_int 741wsemul_vt100_output_string_esc(edp, c) 742 struct wsemul_vt100_emuldata *edp; 743 u_char c; 744{ 745 if (c == '\\') { /* ST complete */ 746 wsemul_vt100_handle_dcs(edp); 747 return (VT100_EMUL_STATE_NORMAL); 748 } else 749 return (VT100_EMUL_STATE_STRING); 750} 751 752static u_int 753wsemul_vt100_output_dcs(edp, c) 754 struct wsemul_vt100_emuldata *edp; 755 u_char c; 756{ 757 u_int newstate = VT100_EMUL_STATE_DCS; 758 759 switch (c) { 760 case '0': case '1': case '2': case '3': case '4': 761 case '5': case '6': case '7': case '8': case '9': 762 /* argument digit */ 763 if (edp->nargs > VT100_EMUL_NARGS - 1) 764 break; 765 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) + 766 (c - '0'); 767 break; 768 case ';': /* argument terminator */ 769 edp->nargs++; 770 break; 771 default: 772 edp->nargs++; 773 if (edp->nargs > VT100_EMUL_NARGS) { 774#ifdef VT100_DEBUG 775 printf("vt100: too many arguments\n"); 776#endif 777 edp->nargs = VT100_EMUL_NARGS; 778 } 779 newstate = VT100_EMUL_STATE_STRING; 780 switch (c) { 781 case '$': 782 newstate = VT100_EMUL_STATE_DCS_DOLLAR; 783 break; 784 case '{': /* DECDLD soft charset */ 785 case '!': /* DECRQUPSS user preferred supplemental set */ 786 /* 'u' must follow - need another state */ 787 case '|': /* DECUDK program F6..F20 */ 788#ifdef VT100_PRINTNOTIMPL 789 printf("DCS%c ignored\n", c); 790#endif 791 break; 792 default: 793#ifdef VT100_PRINTUNKNOWN 794 printf("DCS%c (%d, %d) unknown\n", c, ARG(0), ARG(1)); 795#endif 796 break; 797 } 798 } 799 800 return (newstate); 801} 802 803static u_int 804wsemul_vt100_output_dcs_dollar(edp, c) 805 struct wsemul_vt100_emuldata *edp; 806 u_char c; 807{ 808 switch (c) { 809 case 'p': /* DECRSTS terminal state restore */ 810 case 'q': /* DECRQSS control function request */ 811#ifdef VT100_PRINTNOTIMPL 812 printf("DCS$%c ignored\n", c); 813#endif 814 break; 815 case 't': /* DECRSPS restore presentation state */ 816 switch (ARG(0)) { 817 case 0: /* error */ 818 break; 819 case 1: /* cursor information restore */ 820#ifdef VT100_PRINTNOTIMPL 821 printf("DCS1$t ignored\n"); 822#endif 823 break; 824 case 2: /* tab stop restore */ 825 edp->dcspos = 0; 826 edp->dcstype = DCSTYPE_TABRESTORE; 827 break; 828 default: 829#ifdef VT100_PRINTUNKNOWN 830 printf("DCS%d$t unknown\n", ARG(0)); 831#endif 832 break; 833 } 834 break; 835 default: 836#ifdef VT100_PRINTUNKNOWN 837 printf("DCS$%c (%d, %d) unknown\n", c, ARG(0), ARG(1)); 838#endif 839 break; 840 } 841 return (VT100_EMUL_STATE_STRING); 842} 843 844static u_int 845wsemul_vt100_output_esc_hash(edp, c) 846 struct wsemul_vt100_emuldata *edp; 847 u_char c; 848{ 849 int i; 850 851 switch (c) { 852 case '5': /* DECSWL single width, single height */ 853 if (edp->dw) { 854 for (i = 0; i < edp->ncols / 2; i++) 855 (*edp->emulops->copycols)(edp->emulcookie, 856 edp->crow, 857 2 * i, i, 1); 858 (*edp->emulops->erasecols)(edp->emulcookie, edp->crow, 859 i, edp->ncols - i, 860 edp->defattr); 861 edp->dblwid[edp->crow] = 0; 862 edp->dw = 0; 863 } 864 break; 865 case '6': /* DECDWL double width, single height */ 866 case '3': /* DECDHL double width, double height, top half */ 867 case '4': /* DECDHL double width, double height, bottom half */ 868 if (!edp->dw) { 869 for (i = edp->ncols / 2 - 1; i >= 0; i--) 870 (*edp->emulops->copycols)(edp->emulcookie, 871 edp->crow, 872 i, 2 * i, 1); 873 for (i = 0; i < edp->ncols / 2; i++) 874 (*edp->emulops->erasecols)(edp->emulcookie, 875 edp->crow, 876 2 * i + 1, 1, 877 edp->defattr); 878 edp->dblwid[edp->crow] = 1; 879 edp->dw = 1; 880 if (edp->ccol > (edp->ncols >> 1) - 1) 881 edp->ccol = (edp->ncols >> 1) - 1; 882 } 883 break; 884 case '8': { /* DECALN */ 885 int i, j; 886 for (i = 0; i < edp->nrows; i++) 887 for (j = 0; j < edp->ncols; j++) 888 (*edp->emulops->putchar)(edp->emulcookie, i, j, 889 'E', edp->curattr); 890 } 891 edp->ccol = 0; 892 edp->crow = 0; 893 break; 894 default: 895#ifdef VT100_PRINTUNKNOWN 896 printf("ESC#%c unknown\n", c); 897#endif 898 break; 899 } 900 return (VT100_EMUL_STATE_NORMAL); 901} 902 903static u_int 904wsemul_vt100_output_csi(edp, c) 905 struct wsemul_vt100_emuldata *edp; 906 u_char c; 907{ 908 u_int newstate = VT100_EMUL_STATE_CSI; 909 910 switch (c) { 911 case '0': case '1': case '2': case '3': case '4': 912 case '5': case '6': case '7': case '8': case '9': 913 /* argument digit */ 914 if (edp->nargs > VT100_EMUL_NARGS - 1) 915 break; 916 edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) + 917 (c - '0'); 918 break; 919 case ';': /* argument terminator */ 920 edp->nargs++; 921 break; 922 case '?': /* DEC specific */ 923 case '>': /* DA query */ 924 edp->modif1 = c; 925 break; 926 case '!': 927 case '"': 928 case '$': 929 case '&': 930 edp->modif2 = c; 931 break; 932 default: /* end of escape sequence */ 933 edp->nargs++; 934 if (edp->nargs > VT100_EMUL_NARGS) { 935#ifdef VT100_DEBUG 936 printf("vt100: too many arguments\n"); 937#endif 938 edp->nargs = VT100_EMUL_NARGS; 939 } 940 wsemul_vt100_handle_csi(edp, c); 941 newstate = VT100_EMUL_STATE_NORMAL; 942 break; 943 } 944 return (newstate); 945} 946 947void 948wsemul_vt100_output(cookie, data, count, kernel) 949 void *cookie; 950 const u_char *data; 951 u_int count; 952 int kernel; 953{ 954 struct wsemul_vt100_emuldata *edp = cookie; 955 956#ifdef DIAGNOSTIC 957 if (kernel && !edp->console) 958 panic("wsemul_vt100_output: kernel output, not console"); 959#endif 960 961 if (edp->flags & VTFL_CURSORON) 962 (*edp->emulops->cursor)(edp->emulcookie, 0, 963 edp->crow, edp->ccol << edp->dw); 964 for (; count > 0; data++, count--) { 965 if ((*data & 0x7f) < 0x20) { 966 wsemul_vt100_output_c0c1(edp, *data, kernel); 967 continue; 968 } 969 if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) { 970 wsemul_vt100_output_normal(edp, *data, kernel); 971 continue; 972 } 973#ifdef DIAGNOSTIC 974 if (edp->state > sizeof(vt100_output) / sizeof(vt100_output[0])) 975 panic("wsemul_vt100: invalid state %d\n", edp->state); 976#endif 977 edp->state = vt100_output[edp->state - 1](edp, *data); 978 } 979 if (edp->flags & VTFL_CURSORON) 980 (*edp->emulops->cursor)(edp->emulcookie, 1, 981 edp->crow, edp->ccol << edp->dw); 982} 983