summaryrefslogtreecommitdiff
path: root/sys/dev/wscons/wsemul_vt100.c
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2000-05-16 23:49:13 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2000-05-16 23:49:13 +0000
commita0654a2deddb43b17d7b134a1ee1b01fb7510fb7 (patch)
tree5e5855c85cbcdef6a8f655e834f9d94f2f82998b /sys/dev/wscons/wsemul_vt100.c
parent4003f5f7165c81c13d6491fc69628ef45a48b5c2 (diff)
import newer wscons source from netbsd.
art@ said it will make his life easier in alpha rhands@ said it is not used in powerpc for now bjc@ said that it would make vax port easier mickey@ said other platforms can use it, and it's faster
Diffstat (limited to 'sys/dev/wscons/wsemul_vt100.c')
-rw-r--r--sys/dev/wscons/wsemul_vt100.c983
1 files changed, 983 insertions, 0 deletions
diff --git a/sys/dev/wscons/wsemul_vt100.c b/sys/dev/wscons/wsemul_vt100.c
new file mode 100644
index 00000000000..3de01d30a0f
--- /dev/null
+++ b/sys/dev/wscons/wsemul_vt100.c
@@ -0,0 +1,983 @@
+/* $OpenBSD: wsemul_vt100.c,v 1.1 2000/05/16 23:49:11 mickey Exp $ */
+/* $NetBSD: wsemul_vt100.c,v 1.12 1999/11/03 15:55:29 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1998
+ * Matthias Drochner. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project
+ * by Matthias Drochner.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/time.h>
+#include <sys/malloc.h>
+#include <sys/fcntl.h>
+
+#include <dev/wscons/wsconsio.h>
+#include <dev/wscons/wsdisplayvar.h>
+#include <dev/wscons/wsemulvar.h>
+#include <dev/wscons/wsemul_vt100var.h>
+#include <dev/wscons/ascii.h>
+
+void *wsemul_vt100_cnattach __P((const struct wsscreen_descr *, void *,
+ int, int, long));
+void *wsemul_vt100_attach __P((int console, const struct wsscreen_descr *,
+ void *, int, int, void *, long));
+void wsemul_vt100_output __P((void *cookie, const u_char *data, u_int count,
+ int));
+void wsemul_vt100_detach __P((void *cookie, u_int *crowp, u_int *ccolp));
+void wsemul_vt100_resetop __P((void *, enum wsemul_resetops));
+
+const struct wsemul_ops wsemul_vt100_ops = {
+ "vt100",
+ wsemul_vt100_cnattach,
+ wsemul_vt100_attach,
+ wsemul_vt100_output,
+ wsemul_vt100_translate,
+ wsemul_vt100_detach,
+ wsemul_vt100_resetop
+};
+
+struct wsemul_vt100_emuldata wsemul_vt100_console_emuldata;
+
+static void wsemul_vt100_init __P((struct wsemul_vt100_emuldata *,
+ const struct wsscreen_descr *,
+ void *, int, int, long));
+
+static void wsemul_vt100_output_normal __P((struct wsemul_vt100_emuldata *,
+ u_char, int));
+static void wsemul_vt100_output_c0c1 __P((struct wsemul_vt100_emuldata *,
+ u_char, int));
+typedef u_int vt100_handler __P((struct wsemul_vt100_emuldata *, u_char));
+static vt100_handler
+wsemul_vt100_output_esc,
+wsemul_vt100_output_csi,
+wsemul_vt100_output_scs94,
+wsemul_vt100_output_scs94_percent,
+wsemul_vt100_output_scs96,
+wsemul_vt100_output_scs96_percent,
+wsemul_vt100_output_esc_hash,
+wsemul_vt100_output_esc_spc,
+wsemul_vt100_output_string,
+wsemul_vt100_output_string_esc,
+wsemul_vt100_output_dcs,
+wsemul_vt100_output_dcs_dollar;
+
+#define VT100_EMUL_STATE_NORMAL 0 /* normal processing */
+#define VT100_EMUL_STATE_ESC 1 /* got ESC */
+#define VT100_EMUL_STATE_CSI 2 /* got CSI (ESC[) */
+#define VT100_EMUL_STATE_SCS94 3 /* got ESC{()*+} */
+#define VT100_EMUL_STATE_SCS94_PERCENT 4 /* got ESC{()*+}% */
+#define VT100_EMUL_STATE_SCS96 5 /* got ESC{-./} */
+#define VT100_EMUL_STATE_SCS96_PERCENT 6 /* got ESC{-./}% */
+#define VT100_EMUL_STATE_ESC_HASH 7 /* got ESC# */
+#define VT100_EMUL_STATE_ESC_SPC 8 /* got ESC<SPC> */
+#define VT100_EMUL_STATE_STRING 9 /* waiting for ST (ESC\) */
+#define VT100_EMUL_STATE_STRING_ESC 10 /* waiting for ST, got ESC */
+#define VT100_EMUL_STATE_DCS 11 /* got DCS (ESC P) */
+#define VT100_EMUL_STATE_DCS_DOLLAR 12 /* got DCS<p>$ */
+
+vt100_handler *vt100_output[] = {
+ wsemul_vt100_output_esc,
+ wsemul_vt100_output_csi,
+ wsemul_vt100_output_scs94,
+ wsemul_vt100_output_scs94_percent,
+ wsemul_vt100_output_scs96,
+ wsemul_vt100_output_scs96_percent,
+ wsemul_vt100_output_esc_hash,
+ wsemul_vt100_output_esc_spc,
+ wsemul_vt100_output_string,
+ wsemul_vt100_output_string_esc,
+ wsemul_vt100_output_dcs,
+ wsemul_vt100_output_dcs_dollar,
+};
+
+static void
+wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr)
+ struct wsemul_vt100_emuldata *edp;
+ const struct wsscreen_descr *type;
+ void *cookie;
+ int ccol, crow;
+ long defattr;
+{
+ edp->emulops = type->textops;
+ edp->emulcookie = cookie;
+ edp->scrcapabilities = type->capabilities;
+ edp->nrows = type->nrows;
+ edp->ncols = type->ncols;
+ edp->crow = crow;
+ edp->ccol = ccol;
+ edp->defattr = defattr;
+}
+
+void *
+wsemul_vt100_cnattach(type, cookie, ccol, crow, defattr)
+ const struct wsscreen_descr *type;
+ void *cookie;
+ int ccol, crow;
+ long defattr;
+{
+ struct wsemul_vt100_emuldata *edp;
+#if defined(WS_KERNEL_FG) || defined(WS_KERNEL_BG) || \
+ defined(WS_KERNEL_COLATTR) || defined(WS_KERNEL_MONOATTR)
+ int res;
+#endif
+
+ edp = &wsemul_vt100_console_emuldata;
+ wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
+#ifdef DIAGNOSTIC
+ edp->console = 1;
+#endif
+ edp->cbcookie = NULL;
+
+#if defined(WS_KERNEL_FG) || defined(WS_KERNEL_BG) || \
+ defined(WS_KERNEL_COLATTR) || defined(WS_KERNEL_MONOATTR)
+#ifndef WS_KERNEL_FG
+#define WS_KERNEL_FG WSCOL_WHITE
+#endif
+#ifndef WS_KERNEL_BG
+#define WS_KERNEL_BG WSCOL_BLACK
+#endif
+#ifndef WS_KERNEL_COLATTR
+#define WS_KERNEL_COLATTR 0
+#endif
+#ifndef WS_KERNEL_MONOATTR
+#define WS_KERNEL_MONOATTR 0
+#endif
+ if (type->capabilities & WSSCREEN_WSCOLORS)
+ res = (*edp->emulops->alloc_attr)(cookie,
+ WS_KERNEL_FG, WS_KERNEL_BG,
+ WS_KERNEL_COLATTR | WSATTR_WSCOLORS,
+ &edp->kernattr);
+ else
+ res = (*edp->emulops->alloc_attr)(cookie, 0, 0,
+ WS_KERNEL_MONOATTR,
+ &edp->kernattr);
+ if (res)
+#endif
+ edp->kernattr = defattr;
+
+ edp->tabs = 0;
+ edp->dblwid = 0;
+ edp->dw = 0;
+ edp->dcsarg = 0;
+ edp->isolatin1tab = edp->decgraphtab = edp->dectechtab = 0;
+ edp->nrctab = 0;
+ wsemul_vt100_reset(edp);
+ return (edp);
+}
+
+void *
+wsemul_vt100_attach(console, type, cookie, ccol, crow, cbcookie, defattr)
+ int console;
+ const struct wsscreen_descr *type;
+ void *cookie;
+ int ccol, crow;
+ void *cbcookie;
+ long defattr;
+{
+ struct wsemul_vt100_emuldata *edp;
+
+ if (console) {
+ edp = &wsemul_vt100_console_emuldata;
+#ifdef DIAGNOSTIC
+ KASSERT(edp->console == 1);
+#endif
+ } else {
+ edp = malloc(sizeof *edp, M_DEVBUF, M_WAITOK);
+ wsemul_vt100_init(edp, type, cookie, ccol, crow, defattr);
+#ifdef DIAGNOSTIC
+ edp->console = 0;
+#endif
+ }
+ edp->cbcookie = cbcookie;
+
+ edp->tabs = malloc(edp->ncols, M_DEVBUF, M_NOWAIT);
+ edp->dblwid = malloc(edp->nrows, M_DEVBUF, M_NOWAIT);
+ bzero(edp->dblwid, edp->nrows);
+ edp->dw = 0;
+ edp->dcsarg = malloc(DCS_MAXLEN, M_DEVBUF, M_NOWAIT);
+ edp->isolatin1tab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
+ edp->decgraphtab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
+ edp->dectechtab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
+ edp->nrctab = malloc(128 * sizeof(int), M_DEVBUF, M_NOWAIT);
+ vt100_initchartables(edp);
+ wsemul_vt100_reset(edp);
+ return (edp);
+}
+
+void
+wsemul_vt100_detach(cookie, crowp, ccolp)
+ void *cookie;
+ u_int *crowp, *ccolp;
+{
+ struct wsemul_vt100_emuldata *edp = cookie;
+
+ *crowp = edp->crow;
+ *ccolp = edp->ccol;
+#define f(ptr) if (ptr) {free(ptr, M_DEVBUF); ptr = 0;}
+ f(edp->tabs)
+ f(edp->dblwid)
+ f(edp->dcsarg)
+ f(edp->isolatin1tab)
+ f(edp->decgraphtab)
+ f(edp->dectechtab)
+ f(edp->nrctab)
+#undef f
+ if (edp != &wsemul_vt100_console_emuldata)
+ free(edp, M_DEVBUF);
+}
+
+void
+wsemul_vt100_resetop(cookie, op)
+ void *cookie;
+ enum wsemul_resetops op;
+{
+ struct wsemul_vt100_emuldata *edp = cookie;
+
+ switch (op) {
+ case WSEMUL_RESET:
+ wsemul_vt100_reset(edp);
+ break;
+ case WSEMUL_SYNCFONT:
+ vt100_initchartables(edp);
+ break;
+ case WSEMUL_CLEARSCREEN:
+ wsemul_vt100_ed(edp, 2);
+ edp->ccol = edp->crow = 0;
+ (*edp->emulops->cursor)(edp->emulcookie,
+ edp->flags & VTFL_CURSORON, 0, 0);
+ break;
+ default:
+ break;
+ }
+}
+
+void
+wsemul_vt100_reset(edp)
+ struct wsemul_vt100_emuldata *edp;
+{
+ int i;
+
+ edp->state = VT100_EMUL_STATE_NORMAL;
+ edp->flags = VTFL_DECAWM | VTFL_CURSORON;
+ edp->bkgdattr = edp->curattr = edp->defattr;
+ edp->attrflags = 0;
+ edp->fgcol = WSCOL_WHITE;
+ edp->bgcol = WSCOL_BLACK;
+ edp->scrreg_startrow = 0;
+ edp->scrreg_nrows = edp->nrows;
+ if (edp->tabs) {
+ bzero(edp->tabs, edp->ncols);
+ for (i = 8; i < edp->ncols; i += 8)
+ edp->tabs[i] = 1;
+ }
+ edp->dcspos = 0;
+ edp->dcstype = 0;
+ edp->chartab_G[0] = 0;
+ edp->chartab_G[1] = edp->nrctab; /* ??? */
+ edp->chartab_G[2] = edp->isolatin1tab;
+ edp->chartab_G[3] = edp->isolatin1tab;
+ edp->chartab0 = 0;
+ edp->chartab1 = 2;
+ edp->sschartab = 0;
+}
+
+/*
+ * now all the state machine bits
+ */
+
+static void
+wsemul_vt100_output_normal(edp, c, kernel)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+ int kernel;
+{
+ u_int *ct, dc;
+
+ if ((edp->flags & (VTFL_LASTCHAR | VTFL_DECAWM)) ==
+ (VTFL_LASTCHAR | VTFL_DECAWM)) {
+ if (ROWS_BELOW > 0) {
+ edp->crow++;
+ CHECK_DW;
+ } else
+ wsemul_vt100_scrollup(edp, 1);
+ edp->ccol = 0;
+ edp->flags &= ~VTFL_LASTCHAR;
+ }
+
+ if (c & 0x80) {
+ c &= 0x7f;
+ ct = edp->chartab_G[edp->chartab1];
+ } else {
+ if (edp->sschartab) {
+ ct = edp->chartab_G[edp->sschartab];
+ edp->sschartab = 0;
+ } else
+ ct = edp->chartab_G[edp->chartab0];
+ }
+ dc = (ct ? ct[c] : c);
+
+ if ((edp->flags & VTFL_INSERTMODE) && COLS_LEFT)
+ COPYCOLS(edp->ccol, edp->ccol + 1, COLS_LEFT);
+
+ (*edp->emulops->putchar)(edp->emulcookie, edp->crow,
+ edp->ccol << edp->dw, dc,
+ kernel ? edp->kernattr : edp->curattr);
+
+ if (COLS_LEFT)
+ edp->ccol++;
+ else
+ edp->flags |= VTFL_LASTCHAR;
+}
+
+static void
+wsemul_vt100_output_c0c1(edp, c, kernel)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+ int kernel;
+{
+ u_int n;
+
+ switch (c) {
+ case ASCII_NUL:
+ default:
+ /* ignore */
+ break;
+ case ASCII_BEL:
+ wsdisplay_emulbell(edp->cbcookie);
+ break;
+ case ASCII_BS:
+ if (edp->ccol > 0) {
+ edp->ccol--;
+ edp->flags &= ~VTFL_LASTCHAR;
+ }
+ break;
+ case ASCII_CR:
+ edp->ccol = 0;
+ edp->flags &= ~VTFL_LASTCHAR;
+ break;
+ case ASCII_HT:
+ if (edp->tabs) {
+ if (!COLS_LEFT)
+ break;
+ for (n = edp->ccol + 1; n < NCOLS - 1; n++)
+ if (edp->tabs[n])
+ break;
+ } else {
+ n = edp->ccol + min(8 - (edp->ccol & 7), COLS_LEFT);
+ }
+ edp->ccol = n;
+ break;
+ case ASCII_SO: /* LS1 */
+ edp->chartab0 = 1;
+ break;
+ case ASCII_SI: /* LS0 */
+ edp->chartab0 = 0;
+ break;
+ case ASCII_ESC:
+#ifdef DIAGNOSTIC
+ if (kernel)
+ panic("ESC in kernel output");
+#endif
+ if (edp->state == VT100_EMUL_STATE_STRING) {
+ /* might be a string end */
+ edp->state = VT100_EMUL_STATE_STRING_ESC;
+ } else {
+ /* XXX cancel current escape sequence */
+ edp->state = VT100_EMUL_STATE_ESC;
+ }
+ break;
+#if 0
+ case CSI: /* 8-bit */
+ /* XXX cancel current escape sequence */
+ edp->nargs = 0;
+ bzero(edp->args, sizeof (edp->args));
+ edp->modif1 = edp->modif2 = '\0';
+ edp->state = VT100_EMUL_STATE_CSI;
+ break;
+ case DCS: /* 8-bit */
+ /* XXX cancel current escape sequence */
+ edp->nargs = 0;
+ bzero(edp->args, sizeof (edp->args));
+ edp->state = VT100_EMUL_STATE_DCS;
+ break;
+ case ST: /* string end 8-bit */
+ /* XXX only in VT100_EMUL_STATE_STRING */
+ wsemul_vt100_handle_dcs(edp);
+ return (VT100_EMUL_STATE_NORMAL);
+#endif
+ case ASCII_LF:
+ case ASCII_VT:
+ case ASCII_FF:
+ if (ROWS_BELOW > 0) {
+ edp->crow++;
+ CHECK_DW;
+ } else
+ wsemul_vt100_scrollup(edp, 1);
+ break;
+ }
+}
+
+static u_int
+wsemul_vt100_output_esc(edp, c)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+{
+ u_int newstate = VT100_EMUL_STATE_NORMAL;
+ int i;
+
+ switch (c) {
+ case '[': /* CSI */
+ edp->nargs = 0;
+ bzero(edp->args, sizeof (edp->args));
+ edp->modif1 = edp->modif2 = '\0';
+ newstate = VT100_EMUL_STATE_CSI;
+ break;
+ case '7': /* DECSC */
+ edp->savedcursor_row = edp->crow;
+ edp->savedcursor_col = edp->ccol;
+ edp->savedattr = edp->curattr;
+ edp->savedbkgdattr = edp->bkgdattr;
+ edp->savedattrflags = edp->attrflags;
+ edp->savedfgcol = edp->fgcol;
+ edp->savedbgcol = edp->bgcol;
+ for (i = 0; i < 4; i++)
+ edp->savedchartab_G[i] = edp->chartab_G[i];
+ edp->savedchartab0 = edp->chartab0;
+ edp->savedchartab1 = edp->chartab1;
+ break;
+ case '8': /* DECRC */
+ edp->crow = edp->savedcursor_row;
+ edp->ccol = edp->savedcursor_col;
+ edp->curattr = edp->savedattr;
+ edp->bkgdattr = edp->savedbkgdattr;
+ edp->attrflags = edp->savedattrflags;
+ edp->fgcol = edp->savedfgcol;
+ edp->bgcol = edp->savedbgcol;
+ for (i = 0; i < 4; i++)
+ edp->chartab_G[i] = edp->savedchartab_G[i];
+ edp->chartab0 = edp->savedchartab0;
+ edp->chartab1 = edp->savedchartab1;
+ break;
+ case '=': /* DECKPAM application mode */
+ edp->flags |= VTFL_APPLKEYPAD;
+ break;
+ case '>': /* DECKPNM numeric mode */
+ edp->flags &= ~VTFL_APPLKEYPAD;
+ break;
+ case 'E': /* NEL */
+ edp->ccol = 0;
+ /* FALLTHRU */
+ case 'D': /* IND */
+ if (ROWS_BELOW > 0) {
+ edp->crow++;
+ CHECK_DW;
+ break;
+ }
+ wsemul_vt100_scrollup(edp, 1);
+ break;
+ case 'H': /* HTS */
+ KASSERT(edp->tabs != 0);
+ edp->tabs[edp->ccol] = 1;
+ break;
+ case '~': /* LS1R */
+ edp->chartab1 = 1;
+ break;
+ case 'n': /* LS2 */
+ edp->chartab0 = 2;
+ break;
+ case '}': /* LS2R */
+ edp->chartab1 = 2;
+ break;
+ case 'o': /* LS3 */
+ edp->chartab0 = 3;
+ break;
+ case '|': /* LS3R */
+ edp->chartab1 = 3;
+ break;
+ case 'N': /* SS2 */
+ edp->sschartab = 2;
+ break;
+ case 'O': /* SS3 */
+ edp->sschartab = 3;
+ break;
+ case 'M': /* RI */
+ if (ROWS_ABOVE > 0) {
+ edp->crow--;
+ CHECK_DW;
+ break;
+ }
+ wsemul_vt100_scrolldown(edp, 1);
+ break;
+ case 'P': /* DCS */
+ edp->nargs = 0;
+ bzero(edp->args, sizeof (edp->args));
+ newstate = VT100_EMUL_STATE_DCS;
+ break;
+ case 'c': /* RIS */
+ wsemul_vt100_reset(edp);
+ wsemul_vt100_ed(edp, 2);
+ edp->ccol = edp->crow = 0;
+ break;
+ case '(': case ')': case '*': case '+': /* SCS */
+ edp->designating = c - '(';
+ newstate = VT100_EMUL_STATE_SCS94;
+ break;
+ case '-': case '.': case '/': /* SCS */
+ edp->designating = c - '-' + 1;
+ newstate = VT100_EMUL_STATE_SCS96;
+ break;
+ case '#':
+ newstate = VT100_EMUL_STATE_ESC_HASH;
+ break;
+ case ' ': /* 7/8 bit */
+ newstate = VT100_EMUL_STATE_ESC_SPC;
+ break;
+ case ']': /* OSC operating system command */
+ case '^': /* PM privacy message */
+ case '_': /* APC application program command */
+ /* ignored */
+ newstate = VT100_EMUL_STATE_STRING;
+ break;
+ case '<': /* exit VT52 mode - ignored */
+ break;
+ default:
+#ifdef VT100_PRINTUNKNOWN
+ printf("ESC%c unknown\n", c);
+#endif
+ break;
+ }
+
+ return (newstate);
+}
+
+static u_int
+wsemul_vt100_output_scs94(edp, c)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+{
+ u_int newstate = VT100_EMUL_STATE_NORMAL;
+
+ switch (c) {
+ case '%': /* probably DEC supplemental graphic */
+ newstate = VT100_EMUL_STATE_SCS94_PERCENT;
+ break;
+ case 'A': /* british / national */
+ edp->chartab_G[edp->designating] = edp->nrctab;
+ break;
+ case 'B': /* ASCII */
+ edp->chartab_G[edp->designating] = 0;
+ break;
+ case '<': /* user preferred supplemental */
+ /* XXX not really "user" preferred */
+ edp->chartab_G[edp->designating] = edp->isolatin1tab;
+ break;
+ case '0': /* DEC special graphic */
+ edp->chartab_G[edp->designating] = edp->decgraphtab;
+ break;
+ case '>': /* DEC tech */
+ edp->chartab_G[edp->designating] = edp->dectechtab;
+ break;
+ default:
+#ifdef VT100_PRINTUNKNOWN
+ printf("ESC%c%c unknown\n", edp->designating + '(', c);
+#endif
+ break;
+ }
+ return (newstate);
+}
+
+static u_int
+wsemul_vt100_output_scs94_percent(edp, c)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+{
+ switch (c) {
+ case '5': /* DEC supplemental graphic */
+ /* XXX there are differences */
+ edp->chartab_G[edp->designating] = edp->isolatin1tab;
+ break;
+ default:
+#ifdef VT100_PRINTUNKNOWN
+ printf("ESC%c%%%c unknown\n", edp->designating + '(', c);
+#endif
+ break;
+ }
+ return (VT100_EMUL_STATE_NORMAL);
+}
+
+static u_int
+wsemul_vt100_output_scs96(edp, c)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+{
+ u_int newstate = VT100_EMUL_STATE_NORMAL;
+ int nrc;
+
+ switch (c) {
+ case '%': /* probably portugese */
+ newstate = VT100_EMUL_STATE_SCS96_PERCENT;
+ break;
+ case 'A': /* ISO-latin-1 supplemental */
+ edp->chartab_G[edp->designating] = edp->isolatin1tab;
+ break;
+ case '4': /* dutch */
+ nrc = 1;
+ goto setnrc;
+ case '5': case 'C': /* finnish */
+ nrc = 2;
+ goto setnrc;
+ case 'R': /* french */
+ nrc = 3;
+ goto setnrc;
+ case 'Q': /* french canadian */
+ nrc = 4;
+ goto setnrc;
+ case 'K': /* german */
+ nrc = 5;
+ goto setnrc;
+ case 'Y': /* italian */
+ nrc = 6;
+ goto setnrc;
+ case 'E': case '6': /* norwegian / danish */
+ nrc = 7;
+ goto setnrc;
+ case 'Z': /* spanish */
+ nrc = 9;
+ goto setnrc;
+ case '7': case 'H': /* swedish */
+ nrc = 10;
+ goto setnrc;
+ case '=': /* swiss */
+ nrc = 11;
+setnrc:
+ vt100_setnrc(edp, nrc); /* what table ??? */
+ break;
+ default:
+#ifdef VT100_PRINTUNKNOWN
+ printf("ESC%c%c unknown\n", edp->designating + '-' - 1, c);
+#endif
+ break;
+ }
+ return (newstate);
+}
+
+static u_int
+wsemul_vt100_output_scs96_percent(edp, c)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+{
+ switch (c) {
+ case '6': /* portugese */
+ vt100_setnrc(edp, 8);
+ break;
+ default:
+#ifdef VT100_PRINTUNKNOWN
+ printf("ESC%c%%%c unknown\n", edp->designating + '-', c);
+#endif
+ break;
+ }
+ return (VT100_EMUL_STATE_NORMAL);
+}
+
+static u_int
+wsemul_vt100_output_esc_spc(edp, c)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+{
+ switch (c) {
+ case 'F': /* 7-bit controls */
+ case 'G': /* 8-bit controls */
+#ifdef VT100_PRINTNOTIMPL
+ printf("ESC<SPC>%c ignored\n", c);
+#endif
+ break;
+ default:
+#ifdef VT100_PRINTUNKNOWN
+ printf("ESC<SPC>%c unknown\n", c);
+#endif
+ break;
+ }
+ return (VT100_EMUL_STATE_NORMAL);
+}
+
+static u_int
+wsemul_vt100_output_string(edp, c)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+{
+ if (edp->dcstype && edp->dcspos < DCS_MAXLEN)
+ edp->dcsarg[edp->dcspos++] = c;
+ return (VT100_EMUL_STATE_STRING);
+}
+
+static u_int
+wsemul_vt100_output_string_esc(edp, c)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+{
+ if (c == '\\') { /* ST complete */
+ wsemul_vt100_handle_dcs(edp);
+ return (VT100_EMUL_STATE_NORMAL);
+ } else
+ return (VT100_EMUL_STATE_STRING);
+}
+
+static u_int
+wsemul_vt100_output_dcs(edp, c)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+{
+ u_int newstate = VT100_EMUL_STATE_DCS;
+
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /* argument digit */
+ if (edp->nargs > VT100_EMUL_NARGS - 1)
+ break;
+ edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
+ (c - '0');
+ break;
+ case ';': /* argument terminator */
+ edp->nargs++;
+ break;
+ default:
+ edp->nargs++;
+ if (edp->nargs > VT100_EMUL_NARGS) {
+#ifdef VT100_DEBUG
+ printf("vt100: too many arguments\n");
+#endif
+ edp->nargs = VT100_EMUL_NARGS;
+ }
+ newstate = VT100_EMUL_STATE_STRING;
+ switch (c) {
+ case '$':
+ newstate = VT100_EMUL_STATE_DCS_DOLLAR;
+ break;
+ case '{': /* DECDLD soft charset */
+ case '!': /* DECRQUPSS user preferred supplemental set */
+ /* 'u' must follow - need another state */
+ case '|': /* DECUDK program F6..F20 */
+#ifdef VT100_PRINTNOTIMPL
+ printf("DCS%c ignored\n", c);
+#endif
+ break;
+ default:
+#ifdef VT100_PRINTUNKNOWN
+ printf("DCS%c (%d, %d) unknown\n", c, ARG(0), ARG(1));
+#endif
+ break;
+ }
+ }
+
+ return (newstate);
+}
+
+static u_int
+wsemul_vt100_output_dcs_dollar(edp, c)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+{
+ switch (c) {
+ case 'p': /* DECRSTS terminal state restore */
+ case 'q': /* DECRQSS control function request */
+#ifdef VT100_PRINTNOTIMPL
+ printf("DCS$%c ignored\n", c);
+#endif
+ break;
+ case 't': /* DECRSPS restore presentation state */
+ switch (ARG(0)) {
+ case 0: /* error */
+ break;
+ case 1: /* cursor information restore */
+#ifdef VT100_PRINTNOTIMPL
+ printf("DCS1$t ignored\n");
+#endif
+ break;
+ case 2: /* tab stop restore */
+ edp->dcspos = 0;
+ edp->dcstype = DCSTYPE_TABRESTORE;
+ break;
+ default:
+#ifdef VT100_PRINTUNKNOWN
+ printf("DCS%d$t unknown\n", ARG(0));
+#endif
+ break;
+ }
+ break;
+ default:
+#ifdef VT100_PRINTUNKNOWN
+ printf("DCS$%c (%d, %d) unknown\n", c, ARG(0), ARG(1));
+#endif
+ break;
+ }
+ return (VT100_EMUL_STATE_STRING);
+}
+
+static u_int
+wsemul_vt100_output_esc_hash(edp, c)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+{
+ int i;
+
+ switch (c) {
+ case '5': /* DECSWL single width, single height */
+ if (edp->dw) {
+ for (i = 0; i < edp->ncols / 2; i++)
+ (*edp->emulops->copycols)(edp->emulcookie,
+ edp->crow,
+ 2 * i, i, 1);
+ (*edp->emulops->erasecols)(edp->emulcookie, edp->crow,
+ i, edp->ncols - i,
+ edp->bkgdattr);
+ edp->dblwid[edp->crow] = 0;
+ edp->dw = 0;
+ }
+ break;
+ case '6': /* DECDWL double width, single height */
+ case '3': /* DECDHL double width, double height, top half */
+ case '4': /* DECDHL double width, double height, bottom half */
+ if (!edp->dw) {
+ for (i = edp->ncols / 2 - 1; i >= 0; i--)
+ (*edp->emulops->copycols)(edp->emulcookie,
+ edp->crow,
+ i, 2 * i, 1);
+ for (i = 0; i < edp->ncols / 2; i++)
+ (*edp->emulops->erasecols)(edp->emulcookie,
+ edp->crow,
+ 2 * i + 1, 1,
+ edp->bkgdattr);
+ edp->dblwid[edp->crow] = 1;
+ edp->dw = 1;
+ if (edp->ccol > (edp->ncols >> 1) - 1)
+ edp->ccol = (edp->ncols >> 1) - 1;
+ }
+ break;
+ case '8': { /* DECALN */
+ int i, j;
+ for (i = 0; i < edp->nrows; i++)
+ for (j = 0; j < edp->ncols; j++)
+ (*edp->emulops->putchar)(edp->emulcookie, i, j,
+ 'E', edp->curattr);
+ }
+ edp->ccol = 0;
+ edp->crow = 0;
+ break;
+ default:
+#ifdef VT100_PRINTUNKNOWN
+ printf("ESC#%c unknown\n", c);
+#endif
+ break;
+ }
+ return (VT100_EMUL_STATE_NORMAL);
+}
+
+static u_int
+wsemul_vt100_output_csi(edp, c)
+ struct wsemul_vt100_emuldata *edp;
+ u_char c;
+{
+ u_int newstate = VT100_EMUL_STATE_CSI;
+
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ /* argument digit */
+ if (edp->nargs > VT100_EMUL_NARGS - 1)
+ break;
+ edp->args[edp->nargs] = (edp->args[edp->nargs] * 10) +
+ (c - '0');
+ break;
+ case ';': /* argument terminator */
+ edp->nargs++;
+ break;
+ case '?': /* DEC specific */
+ case '>': /* DA query */
+ edp->modif1 = c;
+ break;
+ case '!':
+ case '"':
+ case '$':
+ case '&':
+ edp->modif2 = c;
+ break;
+ default: /* end of escape sequence */
+ edp->nargs++;
+ if (edp->nargs > VT100_EMUL_NARGS) {
+#ifdef VT100_DEBUG
+ printf("vt100: too many arguments\n");
+#endif
+ edp->nargs = VT100_EMUL_NARGS;
+ }
+ wsemul_vt100_handle_csi(edp, c);
+ newstate = VT100_EMUL_STATE_NORMAL;
+ break;
+ }
+ return (newstate);
+}
+
+void
+wsemul_vt100_output(cookie, data, count, kernel)
+ void *cookie;
+ const u_char *data;
+ u_int count;
+ int kernel;
+{
+ struct wsemul_vt100_emuldata *edp = cookie;
+
+#ifdef DIAGNOSTIC
+ if (kernel && !edp->console)
+ panic("wsemul_vt100_output: kernel output, not console");
+#endif
+
+ if (edp->flags & VTFL_CURSORON)
+ (*edp->emulops->cursor)(edp->emulcookie, 0,
+ edp->crow, edp->ccol << edp->dw);
+ for (; count > 0; data++, count--) {
+ if ((*data & 0x7f) < 0x20) {
+ wsemul_vt100_output_c0c1(edp, *data, kernel);
+ continue;
+ }
+ if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) {
+ wsemul_vt100_output_normal(edp, *data, kernel);
+ continue;
+ }
+#ifdef DIAGNOSTIC
+ if (edp->state > sizeof(vt100_output) / sizeof(vt100_output[0]))
+ panic("wsemul_vt100: invalid state %d\n", edp->state);
+#endif
+ edp->state = vt100_output[edp->state - 1](edp, *data);
+ }
+ if (edp->flags & VTFL_CURSORON)
+ (*edp->emulops->cursor)(edp->emulcookie, 1,
+ edp->crow, edp->ccol << edp->dw);
+}