diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2024-11-05 08:12:09 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2024-11-05 08:12:09 +0000 |
commit | 1e35ff888dc3ab8c50fbf9ecdb9c6f5a469c91b5 (patch) | |
tree | d4323dee2a353326c05523c6892127b4185e9187 | |
parent | 2a99f0caf858ed862bffc8dce3ea0303ce808bc4 (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.c | 102 | ||||
-rw-r--r-- | sys/dev/wscons/wsemul_vt100_subr.c | 14 | ||||
-rw-r--r-- | sys/dev/wscons/wsemul_vt100var.h | 7 | ||||
-rw-r--r-- | sys/dev/wscons/wsemulvar.h | 5 |
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; |