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