summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2024-11-05 08:12:09 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2024-11-05 08:12:09 +0000
commit1e35ff888dc3ab8c50fbf9ecdb9c6f5a469c91b5 (patch)
treed4323dee2a353326c05523c6892127b4185e9187
parent2a99f0caf858ed862bffc8dce3ea0303ce808bc4 (diff)
Add support for CSI b control sequence (repeat last printed character) to
the wscons vt100 emulation. Based on a diff from Crystal Kolipe, modified to properly handle partial updates, verified to work with udl(4).
-rw-r--r--sys/dev/wscons/wsemul_vt100.c102
-rw-r--r--sys/dev/wscons/wsemul_vt100_subr.c14
-rw-r--r--sys/dev/wscons/wsemul_vt100var.h7
-rw-r--r--sys/dev/wscons/wsemulvar.h5
4 files changed, 74 insertions, 54 deletions
diff --git a/sys/dev/wscons/wsemul_vt100.c b/sys/dev/wscons/wsemul_vt100.c
index 1c122fe68f8..e2184d512e2 100644
--- a/sys/dev/wscons/wsemul_vt100.c
+++ b/sys/dev/wscons/wsemul_vt100.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsemul_vt100.c,v 1.47 2023/08/02 19:20:19 miod Exp $ */
+/* $OpenBSD: wsemul_vt100.c,v 1.48 2024/11/05 08:12:08 miod Exp $ */
/* $NetBSD: wsemul_vt100.c,v 1.13 2000/04/28 21:56:16 mycroft Exp $ */
/*
@@ -80,14 +80,12 @@ void wsemul_vt100_init(struct wsemul_vt100_emuldata *,
const struct wsscreen_descr *, void *, int, int, uint32_t);
int wsemul_vt100_jump_scroll(struct wsemul_vt100_emuldata *,
const u_char *, u_int, int);
-int wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *,
- struct wsemul_inputstate *, int);
int wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *,
struct wsemul_inputstate *, int);
int wsemul_vt100_nextline(struct wsemul_vt100_emuldata *);
typedef int vt100_handler(struct wsemul_vt100_emuldata *, struct
- wsemul_inputstate *);
+ wsemul_inputstate *, int);
vt100_handler
wsemul_vt100_output_esc,
wsemul_vt100_output_csi,
@@ -312,9 +310,11 @@ wsemul_vt100_reset(struct wsemul_vt100_emuldata *edp)
edp->instate.inchar = 0;
edp->instate.lbound = 0;
edp->instate.mbleft = 0;
+ edp->instate.last_output = 0;
edp->kstate.inchar = 0;
edp->kstate.lbound = 0;
edp->kstate.mbleft = 0;
+ edp->kstate.last_output = 0;
}
/*
@@ -347,22 +347,14 @@ wsemul_vt100_nextline(struct wsemul_vt100_emuldata *edp)
int
wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate, int kernel)
+ struct wsemul_inputstate *instate, int kernel, int count)
{
u_int *ct, dc;
u_char c;
int oldsschartab = edp->sschartab;
+ int m;
int rc = 0;
- if ((edp->flags & (VTFL_LASTCHAR | VTFL_DECAWM)) ==
- (VTFL_LASTCHAR | VTFL_DECAWM)) {
- rc = wsemul_vt100_nextline(edp);
- if (rc != 0)
- return rc;
- edp->ccol = 0;
- edp->flags &= ~VTFL_LASTCHAR;
- }
-
#ifdef HAVE_UTF8_SUPPORT
if (edp->flags & VTFL_UTF8) {
(*edp->emulops->mapchar)(edp->emulcookie, instate->inchar, &dc);
@@ -383,26 +375,41 @@ wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp,
dc = ct ? ct[c] : c;
}
- if ((edp->flags & VTFL_INSERTMODE) && COLS_LEFT) {
- WSEMULOP(rc, edp, &edp->abortstate, copycols,
- COPYCOLS(edp->ccol, edp->ccol + 1, COLS_LEFT));
- if (rc != 0) {
- /* undo potential sschartab update */
- edp->sschartab = oldsschartab;
+ for (m = 0; m < count; m++) {
+ if ((edp->flags & (VTFL_LASTCHAR | VTFL_DECAWM)) ==
+ (VTFL_LASTCHAR | VTFL_DECAWM)) {
+ rc = wsemul_vt100_nextline(edp);
+ if (rc != 0)
+ return rc;
+ edp->ccol = 0;
+ edp->flags &= ~VTFL_LASTCHAR;
+ }
- return rc;
+ if ((edp->flags & VTFL_INSERTMODE) && COLS_LEFT) {
+ WSEMULOP(rc, edp, &edp->abortstate, copycols,
+ COPYCOLS(edp->ccol, edp->ccol + 1, COLS_LEFT));
+ if (rc != 0)
+ break;
}
- }
#ifdef HAVE_DOUBLE_WIDTH_HEIGHT
- WSEMULOP(rc, edp, &edp->abortstate, putchar,
- (edp->emulcookie, edp->crow, edp->ccol << edp->dw, dc,
- kernel ? edp->kernattr : edp->curattr));
+ WSEMULOP(rc, edp, &edp->abortstate, putchar,
+ (edp->emulcookie, edp->crow, edp->ccol << edp->dw, dc,
+ kernel ? edp->kernattr : edp->curattr));
#else
- WSEMULOP(rc, edp, &edp->abortstate, putchar,
- (edp->emulcookie, edp->crow, edp->ccol, dc,
- kernel ? edp->kernattr : edp->curattr));
+ WSEMULOP(rc, edp, &edp->abortstate, putchar,
+ (edp->emulcookie, edp->crow, edp->ccol, dc,
+ kernel ? edp->kernattr : edp->curattr));
#endif
+ if (rc != 0)
+ break;
+
+ if (COLS_LEFT)
+ edp->ccol++;
+ else
+ edp->flags |= VTFL_LASTCHAR;
+ }
+
if (rc != 0) {
/* undo potential sschartab update */
edp->sschartab = oldsschartab;
@@ -410,11 +417,6 @@ wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *edp,
return rc;
}
- if (COLS_LEFT)
- edp->ccol++;
- else
- edp->flags |= VTFL_LASTCHAR;
-
return 0;
}
@@ -503,7 +505,7 @@ wsemul_vt100_output_c0c1(struct wsemul_vt100_emuldata *edp,
int
wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
u_int newstate = VT100_EMUL_STATE_NORMAL;
int rc = 0;
@@ -656,7 +658,7 @@ wsemul_vt100_output_esc(struct wsemul_vt100_emuldata *edp,
int
wsemul_vt100_output_scs94(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
u_int newstate = VT100_EMUL_STATE_NORMAL;
@@ -699,7 +701,7 @@ wsemul_vt100_output_scs94(struct wsemul_vt100_emuldata *edp,
int
wsemul_vt100_output_scs94_percent(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
switch (instate->inchar) {
case '5': /* DEC supplemental graphic */
@@ -721,7 +723,7 @@ wsemul_vt100_output_scs94_percent(struct wsemul_vt100_emuldata *edp,
int
wsemul_vt100_output_scs96(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
u_int newstate = VT100_EMUL_STATE_NORMAL;
int nrc;
@@ -781,7 +783,7 @@ setnrc:
int
wsemul_vt100_output_scs96_percent(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
switch (instate->inchar) {
case '6': /* portuguese */
@@ -802,7 +804,7 @@ wsemul_vt100_output_scs96_percent(struct wsemul_vt100_emuldata *edp,
int
wsemul_vt100_output_esc_spc(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
switch (instate->inchar) {
case 'F': /* 7-bit controls */
@@ -824,7 +826,7 @@ wsemul_vt100_output_esc_spc(struct wsemul_vt100_emuldata *edp,
int
wsemul_vt100_output_string(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
if (edp->dcsarg && edp->dcstype && edp->dcspos < DCS_MAXLEN) {
if (instate->inchar & ~0xff) {
@@ -841,7 +843,7 @@ wsemul_vt100_output_string(struct wsemul_vt100_emuldata *edp,
int
wsemul_vt100_output_string_esc(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
if (instate->inchar == '\\') { /* ST complete */
wsemul_vt100_handle_dcs(edp);
@@ -854,7 +856,7 @@ wsemul_vt100_output_string_esc(struct wsemul_vt100_emuldata *edp,
int
wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
u_int newstate = VT100_EMUL_STATE_DCS;
@@ -902,7 +904,7 @@ wsemul_vt100_output_dcs(struct wsemul_vt100_emuldata *edp,
int
wsemul_vt100_output_dcs_dollar(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
switch (instate->inchar) {
case 'p': /* DECRSTS terminal state restore */
@@ -945,7 +947,7 @@ wsemul_vt100_output_dcs_dollar(struct wsemul_vt100_emuldata *edp,
int
wsemul_vt100_output_esc_percent(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
switch (instate->inchar) {
#ifdef HAVE_UTF8_SUPPORT
@@ -969,7 +971,7 @@ wsemul_vt100_output_esc_percent(struct wsemul_vt100_emuldata *edp,
int
wsemul_vt100_output_esc_hash(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
int rc = 0;
@@ -1049,7 +1051,7 @@ wsemul_vt100_output_esc_hash(struct wsemul_vt100_emuldata *edp,
int
wsemul_vt100_output_csi(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
u_int newstate = VT100_EMUL_STATE_CSI;
int oargs;
@@ -1082,7 +1084,7 @@ wsemul_vt100_output_csi(struct wsemul_vt100_emuldata *edp,
oargs = edp->nargs;
if (edp->nargs < VT100_EMUL_NARGS)
edp->nargs++;
- rc = wsemul_vt100_handle_csi(edp, instate);
+ rc = wsemul_vt100_handle_csi(edp, instate, kernel);
if (rc != 0) {
/* undo nargs progress */
edp->nargs = oargs;
@@ -1215,9 +1217,11 @@ wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
}
if (edp->state == VT100_EMUL_STATE_NORMAL || kernel) {
- rc = wsemul_vt100_output_normal(edp, instate, kernel);
+ rc =
+ wsemul_vt100_output_normal(edp, instate, kernel, 1);
if (rc != 0)
break;
+ instate->last_output = instate->inchar;
processed += prev_count - count;
continue;
}
@@ -1225,7 +1229,7 @@ wsemul_vt100_output(void *cookie, const u_char *data, u_int count, int kernel)
if (edp->state > nitems(vt100_output))
panic("wsemul_vt100: invalid state %d", edp->state);
#endif
- rc = vt100_output[edp->state - 1](edp, instate);
+ rc = vt100_output[edp->state - 1](edp, instate, kernel);
if (rc != 0)
break;
processed += prev_count - count;
diff --git a/sys/dev/wscons/wsemul_vt100_subr.c b/sys/dev/wscons/wsemul_vt100_subr.c
index 9c04ce36912..32dfebfa553 100644
--- a/sys/dev/wscons/wsemul_vt100_subr.c
+++ b/sys/dev/wscons/wsemul_vt100_subr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsemul_vt100_subr.c,v 1.30 2023/02/26 15:09:53 miod Exp $ */
+/* $OpenBSD: wsemul_vt100_subr.c,v 1.31 2024/11/05 08:12:08 miod Exp $ */
/* $NetBSD: wsemul_vt100_subr.c,v 1.7 2000/04/28 21:56:16 mycroft Exp $ */
/*
@@ -225,7 +225,7 @@ wsemul_vt100_el(struct wsemul_vt100_emuldata *edp, int arg)
*/
int
wsemul_vt100_handle_csi(struct wsemul_vt100_emuldata *edp,
- struct wsemul_inputstate *instate)
+ struct wsemul_inputstate *instate, int kernel)
{
int n, m, help, flags, fgcol, bgcol;
uint32_t attr, bkgdattr;
@@ -548,6 +548,16 @@ wsemul_vt100_handle_csi(struct wsemul_vt100_emuldata *edp,
break;
}
break;
+ case 'b': /* REP */
+ /*
+ * We arbitrarily limit the repeat count to 65535 to avoid
+ * uninterruptible flooding of the console. This matches
+ * current xterm behaviour.
+ */
+ n = min(DEF1_ARG(0), 65535);
+ instate->inchar = instate->last_output;
+ rc = wsemul_vt100_output_normal(edp, instate, kernel, n);
+ break;
case 'c': /* DA primary */
if (ARG(0) == 0)
wsdisplay_emulinput(edp->cbcookie, WSEMUL_VT_ID1,
diff --git a/sys/dev/wscons/wsemul_vt100var.h b/sys/dev/wscons/wsemul_vt100var.h
index 4b7c7a6c716..a3875d7bb9a 100644
--- a/sys/dev/wscons/wsemul_vt100var.h
+++ b/sys/dev/wscons/wsemul_vt100var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsemul_vt100var.h,v 1.13 2023/03/06 17:14:44 miod Exp $ */
+/* $OpenBSD: wsemul_vt100var.h,v 1.14 2024/11/05 08:12:08 miod Exp $ */
/* $NetBSD: wsemul_vt100var.h,v 1.5 2000/04/28 21:56:17 mycroft Exp $ */
/*
@@ -153,10 +153,13 @@ int wsemul_vt100_scrolldown(struct wsemul_vt100_emuldata *, int);
int wsemul_vt100_ed(struct wsemul_vt100_emuldata *, int);
int wsemul_vt100_el(struct wsemul_vt100_emuldata *, int);
int wsemul_vt100_handle_csi(struct wsemul_vt100_emuldata *,
- struct wsemul_inputstate *);
+ struct wsemul_inputstate *, int);
void wsemul_vt100_handle_dcs(struct wsemul_vt100_emuldata *);
int wsemul_vt100_translate(void *cookie, kbd_t, keysym_t, const u_char **);
void vt100_initchartables(struct wsemul_vt100_emuldata *);
int vt100_setnrc(struct wsemul_vt100_emuldata *, int);
+
+int wsemul_vt100_output_normal(struct wsemul_vt100_emuldata *,
+ struct wsemul_inputstate *, int, int);
diff --git a/sys/dev/wscons/wsemulvar.h b/sys/dev/wscons/wsemulvar.h
index a0a88e727be..a0200db44b5 100644
--- a/sys/dev/wscons/wsemulvar.h
+++ b/sys/dev/wscons/wsemulvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: wsemulvar.h,v 1.19 2023/03/06 17:14:44 miod Exp $ */
+/* $OpenBSD: wsemulvar.h,v 1.20 2024/11/05 08:12:08 miod Exp $ */
/* $NetBSD: wsemulvar.h,v 1.6 1999/01/17 15:46:15 drochner Exp $ */
/*
@@ -81,6 +81,9 @@ struct wsemul_inputstate {
uint32_t inchar; /* character being reconstructed */
uint32_t lbound; /* lower bound of above */
u_int mbleft; /* multibyte bytes left until char complete */
+
+ uint32_t last_output; /* last printable character */
+ /* (used by vt100 emul only) */
};
extern const struct wsemul_ops wsemul_dumb_ops;