diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-06-18 09:45:47 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 1996-06-18 09:45:47 +0000 |
commit | 41ae123ec2d77615cd0b0476ff62564bd7a4865f (patch) | |
tree | ba6a57d3a8d7d725a5e0ae64e8401ed3bea0efb9 /sys/dev/wscons/wscons_emul.c | |
parent | 7a0b7f798c45842a34a4c6413f45e1b3824154a5 (diff) |
sync to 0616, retaining local diffs
Diffstat (limited to 'sys/dev/wscons/wscons_emul.c')
-rw-r--r-- | sys/dev/wscons/wscons_emul.c | 416 |
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); +} |