summaryrefslogtreecommitdiff
path: root/sys/dev/wscons/wscons_emul.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1996-06-18 09:45:47 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1996-06-18 09:45:47 +0000
commit41ae123ec2d77615cd0b0476ff62564bd7a4865f (patch)
treeba6a57d3a8d7d725a5e0ae64e8401ed3bea0efb9 /sys/dev/wscons/wscons_emul.c
parent7a0b7f798c45842a34a4c6413f45e1b3824154a5 (diff)
sync to 0616, retaining local diffs
Diffstat (limited to 'sys/dev/wscons/wscons_emul.c')
-rw-r--r--sys/dev/wscons/wscons_emul.c416
1 files changed, 416 insertions, 0 deletions
diff --git a/sys/dev/wscons/wscons_emul.c b/sys/dev/wscons/wscons_emul.c
new file mode 100644
index 00000000000..cb218fd5cd0
--- /dev/null
+++ b/sys/dev/wscons/wscons_emul.c
@@ -0,0 +1,416 @@
+/* $NetBSD: wscons_emul.c,v 1.2 1996/04/12 06:10:29 cgd Exp $ */
+
+/*
+ * Copyright (c) 1995, 1996 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+/*
+ * Console emulator for a 'generic' ANSI X3.64 console.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <alpha/wscons/wsconsvar.h>
+#include <alpha/wscons/wscons_emul.h>
+#include <alpha/wscons/ascii.h>
+
+void
+wscons_emul_attach(we, wo)
+ struct wscons_emul_data *we;
+ const struct wscons_odev_spec *wo;
+{
+ int i;
+
+#ifdef DIAGNOSTIC
+ if (we == NULL || wo == NULL)
+ panic("wscons_emul_attach: bogus args");
+ if (wo->wo_ef == NULL)
+ panic("wscons_emul_attach: bogus emul functions");
+#endif
+ if (wo->wo_nrows < 0 || wo->wo_ncols < 0)
+ panic("wscons_emul_attach: bogus size");
+ if (wo->wo_crow < 0 || wo->wo_ccol < 0 ||
+ wo->wo_crow >= wo->wo_nrows || wo->wo_ccol >= wo->wo_ncols)
+ panic("wscons_emul_attach: bogus location (n: %d/%d, c: %d/%d",
+ wo->wo_nrows, wo->wo_ncols, wo->wo_crow, wo->wo_ccol);
+
+ we->ac_state = ANSICONS_STATE_NORMAL;
+ we->ac_ef = wo->wo_ef;
+ we->ac_efa = wo->wo_efa;
+
+ we->ac_nrow = wo->wo_nrows;
+ we->ac_ncol = wo->wo_ncols;
+
+ we->ac_crow = wo->wo_crow;
+ we->ac_ccol = wo->wo_ccol;
+
+ for (i = 0; i < ANSICONS_NARGS; i++)
+ we->ac_args[i] = 0;
+
+ (*we->ac_ef->wef_cursor)(we->ac_efa, 1, we->ac_crow, we->ac_ccol);
+}
+
+static inline int
+wscons_emul_input_normal(we, c)
+ struct wscons_emul_data *we;
+ char c;
+{
+ int newstate = ANSICONS_STATE_NORMAL;
+ int n;
+
+ switch (c) {
+ case ASCII_BEL:
+ wscons_kbd_bell();
+ break;
+
+ case ASCII_BS:
+ if (we->ac_ccol > 0)
+ we->ac_ccol--;
+ break;
+
+ case ASCII_HT:
+ n = 8 - (we->ac_ccol & 7);
+ if (we->ac_ccol + n >= we->ac_ncol)
+ n = we->ac_ncol - we->ac_ccol - 1;
+
+ (*we->ac_ef->wef_erasecols)(we->ac_efa, we->ac_crow,
+ we->ac_ccol, we->ac_ccol + n);
+
+ we->ac_ccol += n;
+ break;
+
+ case ASCII_LF:
+ if (we->ac_crow < we->ac_nrow - 1) {
+ we->ac_crow++;
+ break;
+ }
+
+#ifdef DIAGNOSTIC
+ if (we->ac_crow >= we->ac_nrow)
+ panic("wscons_emul: didn't scroll (1)");
+#endif
+
+#if 0
+ (*we->ac_ef->wef_copyrows)(we->ac_efa, 1, 0,
+ we->ac_nrow - 1);
+ (*we->ac_ef->wef_eraserows)(we->ac_efa,
+ we->ac_nrow - 1, 1);
+#else
+ (*we->ac_ef->wef_copyrows)(we->ac_efa, 10, 0,
+ we->ac_nrow - 10);
+ (*we->ac_ef->wef_eraserows)(we->ac_efa,
+ we->ac_nrow - 10, 10);
+ we->ac_crow -= 10 - 1;
+#endif
+ break;
+
+ case ASCII_VT:
+ if (we->ac_crow > 0)
+ we->ac_crow--;
+ break;
+
+ case ASCII_NP:
+ (*we->ac_ef->wef_eraserows)(we->ac_efa,
+ 0, we->ac_nrow - 1);
+
+ we->ac_ccol = 0;
+ we->ac_crow = 0;
+ break;
+
+ case ASCII_CR:
+ we->ac_ccol = 0;
+ break;
+
+ case ASCII_ESC:
+ if (we->ac_state == ANSICONS_STATE_NORMAL) {
+ newstate = ANSICONS_STATE_HAVEESC;
+ break;
+ }
+ /* else fall through; we're printing one out */
+
+ default:
+ (*we->ac_ef->wef_putstr)(we->ac_efa,
+ we->ac_crow, we->ac_ccol, &c, 1);
+ we->ac_ccol++;
+
+ /* if the current column is still on the current line, done. */
+ if (we->ac_ccol < we->ac_ncol)
+ break;
+
+ /* wrap the column around. */
+ we->ac_ccol = 0;
+
+ /* if the current row isn't the last, increment and leave. */
+ if (we->ac_crow < we->ac_nrow - 1) {
+ we->ac_crow++;
+ break;
+ }
+
+#ifdef DIAGNOSTIC
+ /* check against row overflow */
+ if (we->ac_crow >= we->ac_nrow)
+ panic("wscons_emul: didn't scroll (2)");
+#endif
+
+#if 0
+ /* scroll all of the rows up one; leave current row # alone */
+ (*we->ac_ef->wef_copyrows)(we->ac_efa, 1, 0,
+ we->ac_nrow - 1);
+ (*we->ac_ef->wef_eraserows)(we->ac_efa,
+ we->ac_nrow - 1, 1);
+#else
+ (*we->ac_ef->wef_copyrows)(we->ac_efa, 10, 0,
+ we->ac_nrow - 10);
+ (*we->ac_ef->wef_eraserows)(we->ac_efa,
+ we->ac_nrow - 10, 10);
+ we->ac_crow -= 10 - 1;
+#endif
+ break;
+ }
+
+ return newstate;
+}
+
+static inline int
+wscons_emul_input_haveesc(we, c)
+ struct wscons_emul_data *we;
+ char c;
+{
+ int newstate = ANSICONS_STATE_NORMAL;
+ int i;
+
+ switch (c) {
+ case '[':
+ for (i = 0; i < ANSICONS_NARGS; i++)
+ we->ac_args[i] = 0;
+ newstate = ANSICONS_STATE_CONTROL;
+ break;
+
+ default:
+ wscons_emul_input_normal(we, ASCII_ESC); /* special cased */
+ newstate = wscons_emul_input_normal(we, c);
+ break;
+ }
+
+ return newstate;
+}
+
+static inline void
+wscons_emul_docontrol(we, c)
+ struct wscons_emul_data *we;
+ char c;
+{
+ int n, m;
+
+#if 0
+ printf("control: %c: %d, %d\n", c, we->ac_args[0], we->ac_args[1]);
+#endif
+ switch (c) {
+ case 'A': /* Cursor Up */
+ n = we->ac_args[0] ? we->ac_args[0] : 1;
+ n = min(n, we->ac_crow);
+ we->ac_crow -= n;
+ break;
+
+ case 'B': /* Cursor Down */
+ n = we->ac_args[0] ? we->ac_args[0] : 1;
+ n = min(n, we->ac_nrow - we->ac_crow - 1);
+ we->ac_crow += n;
+ break;
+
+ case 'C': /* Cursor Forward */
+ n = we->ac_args[0] ? we->ac_args[0] : 1;
+ n = min(n, we->ac_ncol - we->ac_ccol - 1);
+ we->ac_ccol += n;
+ break;
+
+ case 'D': /* Cursor Backward */
+ n = we->ac_args[0] ? we->ac_args[0] : 1;
+ n = min(n, we->ac_ccol);
+ we->ac_ccol -= n;
+ break;
+
+ case 'E': /* Cursor Next Line */
+ n = we->ac_args[0] ? we->ac_args[0] : 1;
+ n = min(n, we->ac_nrow - we->ac_crow - 1);
+ we->ac_crow += n;
+ we->ac_ccol = 0;
+ break;
+
+ case 'f': /* Horizontal and Vertical Position */
+ case 'H': /* Cursor Position */
+ m = we->ac_args[1] ? we->ac_args[1] : 1; /* arg 1 */
+ m = min(m, we->ac_nrow);
+
+ n = we->ac_args[0] ? we->ac_args[0] : 1; /* arg 2 */
+ n = min(n, we->ac_ncol);
+
+ we->ac_crow = m - 1;
+ we->ac_ccol = n - 1;
+ break;
+
+ case 'J': /* Erase in Display */
+ (*we->ac_ef->wef_erasecols)(we->ac_efa, we->ac_crow,
+ we->ac_ccol, we->ac_ncol - we->ac_ccol);
+ if (we->ac_crow + 1 < we->ac_nrow)
+ (*we->ac_ef->wef_eraserows)(we->ac_efa,
+ we->ac_crow + 1, we->ac_nrow - we->ac_crow - 1);
+ break;
+
+ case 'K': /* Erase in Line */
+ (*we->ac_ef->wef_erasecols)(we->ac_efa, we->ac_crow,
+ we->ac_ccol, we->ac_ncol - we->ac_ccol);
+ break;
+
+ case 'L': /* Insert Line */
+ {
+ int copy_src, copy_dst, copy_nlines;
+
+ n = we->ac_args[0] ? we->ac_args[0] : 1;
+ n = min(n, we->ac_nrow - we->ac_crow);
+
+ copy_src = we->ac_crow;
+ copy_dst = we->ac_crow + n;
+ copy_nlines = we->ac_nrow - copy_dst;
+ if (copy_nlines > 0)
+ (*we->ac_ef->wef_copyrows)(we->ac_efa,
+ copy_src, copy_dst, copy_nlines);
+
+ (*we->ac_ef->wef_eraserows)(we->ac_efa,
+ we->ac_crow, n);
+ }
+ break;
+
+ case 'M': /* Delete Line */
+ {
+ int copy_src, copy_dst, copy_nlines;
+
+ n = we->ac_args[0] ? we->ac_args[0] : 1;
+ n = min(n, we->ac_nrow - we->ac_crow);
+
+ copy_src = we->ac_crow + n;
+ copy_dst = we->ac_crow;
+ copy_nlines = we->ac_nrow - copy_src;
+ if (copy_nlines > 0)
+ (*we->ac_ef->wef_copyrows)(we->ac_efa,
+ copy_src, copy_dst, copy_nlines);
+
+ (*we->ac_ef->wef_eraserows)(we->ac_efa,
+ we->ac_crow + copy_nlines,
+ we->ac_nrow - (we->ac_crow + copy_nlines));
+ }
+ break;
+
+ case 'P': /* Delete Character */
+ {
+ int copy_src, copy_dst, copy_ncols;
+
+ n = we->ac_args[0] ? we->ac_args[0] : 1;
+ n = min(n, we->ac_ncol - we->ac_ccol);
+
+ copy_src = we->ac_ccol + n;
+ copy_dst = we->ac_ccol;
+ copy_ncols = we->ac_ncol - copy_src;
+ if (copy_ncols > 0)
+ (*we->ac_ef->wef_copycols)(we->ac_efa,
+ we->ac_crow, copy_src, copy_dst,
+ copy_ncols);
+
+ (*we->ac_ef->wef_erasecols)(we->ac_efa,
+ we->ac_crow, we->ac_ccol + copy_ncols,
+ we->ac_ncol - (we->ac_ccol + copy_ncols));
+ break;
+ }
+ break;
+ }
+}
+
+static inline int
+wscons_emul_input_control(we, c)
+ struct wscons_emul_data *we;
+ char c;
+{
+ int newstate = ANSICONS_STATE_CONTROL;
+ int i;
+
+ switch (c) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ we->ac_args[0] *= 10;
+ we->ac_args[0] += c - '0';
+ break;
+
+ case ';':
+ for (i = 0; i < ANSICONS_NARGS - 1; i++)
+ we->ac_args[i + 1] = we->ac_args[i];
+ we->ac_args[0] = 0;
+ break;
+
+ default:
+ wscons_emul_docontrol(we, c);
+ newstate = ANSICONS_STATE_NORMAL;
+ break;
+ }
+
+ return newstate;
+}
+
+void
+wscons_emul_input(we, cp, n)
+ struct wscons_emul_data *we;
+ char *cp;
+ int n;
+{
+ int newstate;
+
+ (*we->ac_ef->wef_cursor)(we->ac_efa, 0, we->ac_crow, we->ac_ccol);
+ for (; n; n--, cp++) {
+ switch (we->ac_state) {
+ case ANSICONS_STATE_NORMAL:
+ newstate = wscons_emul_input_normal(we, *cp);
+ break;
+
+ case ANSICONS_STATE_HAVEESC:
+ newstate = wscons_emul_input_haveesc(we, *cp);
+ break;
+
+ case ANSICONS_STATE_CONTROL:
+ newstate = wscons_emul_input_control(we, *cp);
+ break;
+
+ default:
+#ifdef DIAGNOSTIC
+ panic("wscons_emul: invalid state %d\n", we->ac_state);
+#endif
+ /* try to recover, if things get screwed up... */
+ newstate = ANSICONS_STATE_NORMAL;
+ break;
+ }
+
+ we->ac_state = newstate;
+ }
+ (*we->ac_ef->wef_cursor)(we->ac_efa, 1, we->ac_crow, we->ac_ccol);
+}