Re: [hackers] [st][patch] Handle DECRQM (Request Mode) escape sequences

From: Hiltjo Posthuma <hiltjo_AT_codemadness.org>
Date: Sun, 29 Nov 2020 17:37:30 +0100

On Fri, Nov 27, 2020 at 01:54:36AM +0100, François-Xavier Carton wrote:
> Handle DECRQM (Request Mode) escape sequences
>
> The DECRQM [1] escape sequence is a request to the terminal to query the state
> of a mode. The terminal replies to this request with a DECRPM [2] escape
> sequence, containing the status of the mode flag.
>
> [1] https://vt100.net/docs/vt510-rm/DECRQM.html
> [2] https://vt100.net/docs/vt510-rm/DECRPM.html
>
> diff -rup st-0.8.4.orig/st.c st-0.8.4/st.c
> --- st-0.8.4.orig/st.c 2020-06-19 11:29:45.000000000 +0200
> +++ st-0.8.4/st.c 2020-11-27 01:33:28.572861355 +0100
> _AT_@ -1476,17 +1476,17 @@ tsetmode(int priv, int set, int *args, i
> if (priv) {
> switch (*args) {
> case 1: /* DECCKM -- Cursor key */
> - xsetmode(set, MODE_APPCURSOR);
> + xdomode(priv, *args, set, MODE_APPCURSOR);
> break;
> case 5: /* DECSCNM -- Reverse video */
> - xsetmode(set, MODE_REVERSE);
> + xdomode(priv, *args, set, MODE_REVERSE);
> break;
> case 6: /* DECOM -- Origin */
> - MODBIT(term.c.state, set, CURSOR_ORIGIN);
> + DOBIT(priv, *args, term.c.state, set, CURSOR_ORIGIN);
> tmoveato(0, 0);
> break;
> case 7: /* DECAWM -- Auto wrap */
> - MODBIT(term.mode, set, MODE_WRAP);
> + DOBIT(priv, *args, term.mode, set, MODE_WRAP);
> break;
> case 0: /* Error (IGNORED) */
> case 2: /* DECANM -- ANSI/VT52 (IGNORED) */
> _AT_@ -1497,46 +1497,71 @@ tsetmode(int priv, int set, int *args, i
> case 19: /* DECPEX -- Printer extent (IGNORED) */
> case 42: /* DECNRCM -- National characters (IGNORED) */
> case 12: /* att610 -- Start blinking cursor (IGNORED) */
> + if (set & 2) decrpm(priv, *args, 0);
> break;
> case 25: /* DECTCEM -- Text Cursor Enable Mode */
> - xsetmode(!set, MODE_HIDE);
> + xdomode(priv, *args, set ^ 1, MODE_HIDE);
> break;
> case 9: /* X10 mouse compatibility mode */
> + if (set & 2) {
> + decrpm(priv, *args, 0);
> + break;
> + }
> xsetpointermotion(0);
> xsetmode(0, MODE_MOUSE);
> xsetmode(set, MODE_MOUSEX10);
> break;
> case 1000: /* 1000: report button press */
> + if (set & 2) {
> + decrpm(priv, *args, 0);
> + break;
> + }
> xsetpointermotion(0);
> xsetmode(0, MODE_MOUSE);
> xsetmode(set, MODE_MOUSEBTN);
> break;
> case 1002: /* 1002: report motion on button press */
> + if (set & 2) {
> + decrpm(priv, *args, 0);
> + break;
> + }
> xsetpointermotion(0);
> xsetmode(0, MODE_MOUSE);
> xsetmode(set, MODE_MOUSEMOTION);
> break;
> case 1003: /* 1003: enable all mouse motions */
> + if (set & 2) {
> + decrpm(priv, *args, 0);
> + break;
> + }
> xsetpointermotion(set);
> xsetmode(0, MODE_MOUSE);
> xsetmode(set, MODE_MOUSEMANY);
> break;
> case 1004: /* 1004: send focus events to tty */
> - xsetmode(set, MODE_FOCUS);
> + xdomode(priv, *args, set, MODE_FOCUS);
> break;
> case 1006: /* 1006: extended reporting mode */
> - xsetmode(set, MODE_MOUSESGR);
> + xdomode(priv, *args, set, MODE_MOUSESGR);
> break;
> case 1034:
> - xsetmode(set, MODE_8BIT);
> + xdomode(priv, *args, set, MODE_8BIT);
> break;
> case 1049: /* swap screen & set/restore cursor as xterm */
> + if (set & 2) {
> + decrpm(priv, *args, !IS_SET(MODE_ALTSCREEN) + 1);
> + break;
> + }
> if (!allowaltscreen)
> break;
> tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD);
> /* FALLTHROUGH */
> case 47: /* swap screen */
> case 1047:
> + if (set & 2) {
> + decrpm(priv, *args, !IS_SET(MODE_ALTSCREEN) + 1);
> + break;
> + }
> if (!allowaltscreen)
> break;
> alt = IS_SET(MODE_ALTSCREEN);
> _AT_@ -1550,10 +1575,14 @@ tsetmode(int priv, int set, int *args, i
> break;
> /* FALLTHROUGH */
> case 1048:
> + if (set & 2) {
> + decrpm(priv, *args, 0);
> + break;
> + }
> tcursor((set) ? CURSOR_SAVE : CURSOR_LOAD);
> break;
> case 2004: /* 2004: bracketed paste mode */
> - xsetmode(set, MODE_BRCKTPASTE);
> + xdomode(priv, *args, set, MODE_BRCKTPASTE);
> break;
> /* Not implemented mouse modes. See comments there. */
> case 1001: /* mouse highlight mode; can hang the
> _AT_@ -1564,33 +1593,37 @@ tsetmode(int priv, int set, int *args, i
> case 1015: /* urxvt mangled mouse mode; incompatible
> and can be mistaken for other control
> codes. */
> + if (set & 2) decrpm(priv, *args, 0);
> break;
> default:
> fprintf(stderr,
> "erresc: unknown private set/reset mode %d\n",
> *args);
> + if (set & 2) decrpm(priv, *args, 0);
> break;
> }
> } else {
> switch (*args) {
> case 0: /* Error (IGNORED) */
> + if (set & 2) decrpm(priv, *args, 0);
> break;
> case 2:
> - xsetmode(set, MODE_KBDLOCK);
> + xdomode(priv, *args, set, MODE_KBDLOCK);
> break;
> case 4: /* IRM -- Insertion-replacement */
> - MODBIT(term.mode, set, MODE_INSERT);
> + DOBIT(priv, *args, term.mode, set, MODE_INSERT);
> break;
> case 12: /* SRM -- Send/Receive */
> - MODBIT(term.mode, !set, MODE_ECHO);
> + DOBIT(priv, *args, term.mode, set ^ 1, MODE_ECHO);
> break;
> case 20: /* LNM -- Linefeed/new line */
> - MODBIT(term.mode, set, MODE_CRLF);
> + DOBIT(priv, *args, term.mode, set, MODE_CRLF);
> break;
> default:
> fprintf(stderr,
> "erresc: unknown set/reset mode %d\n",
> *args);
> + if (set & 2) decrpm(priv, *args, 0);
> break;
> }
> }
> _AT_@ -1806,6 +1839,15 @@ csihandle(void)
> goto unknown;
> }
> break;
> + case '$':
> + switch (csiescseq.mode[1]) {
> + case 'p': /* DECRQM -- Request Mode - Host To Terminal */
> + tsetmode(csiescseq.priv, 2, csiescseq.arg, csiescseq.narg);
> + break;
> + default:
> + goto unknown;
> + }
> + break;
> }
> }
>
> _AT_@ -2595,3 +2637,17 @@ redraw(void)
> tfulldirt();
> draw();
> }
> +
> +void
> +decrpm(int priv, int mode, unsigned value)
> +{
> + char buf[40], *ptr = buf;
> + int len;
> +
> + *ptr++ = 033;
> + *ptr++ = '[';
> + if (priv) *ptr++ = '?';
> + len = snprintf(ptr, sizeof(buf) - (ptr - buf), "%d;%u$y", mode, value);
> + if (len < 0) return;
> + ttywrite(buf, len + 2 + (priv != 0), 0);
> +}
> diff -rup st-0.8.4.orig/st.h st-0.8.4/st.h
> --- st-0.8.4.orig/st.h 2020-06-19 11:29:45.000000000 +0200
> +++ st-0.8.4/st.h 2020-11-27 00:58:15.278976407 +0100
> _AT_@ -16,6 +16,10 @@
> #define TIMEDIFF(t1, t2) ((t1.tv_sec-t2.tv_sec)*1000 + \
> (t1.tv_nsec-t2.tv_nsec)/1E6)
> #define MODBIT(x, set, bit) ((set) ? ((x) |= (bit)) : ((x) &= ~(bit)))
> +#define DOBIT(priv, mode, x, set, bit) (((set) & 2) ? \
> + decrpm((priv), (mode), ((!((x) & (bit))) ^ ((set) & 1)) + 1) : \
> + ((void)MODBIT((x), (set), (bit))) \
> + )
>
> #define TRUECOLOR(r,g,b) (1 << 24 | (r) << 16 | (g) << 8 | (b))
> #define IS_TRUECOL(x) (1 << 24 & (x))
> _AT_@ -111,6 +115,8 @@ void *xmalloc(size_t);
> void *xrealloc(void *, size_t);
> char *xstrdup(char *);
>
> +void decrpm(int, int, unsigned int);
> +
> /* config.h globals */
> extern char *utmp;
> extern char *scroll;
> diff -rup st-0.8.4.orig/win.h st-0.8.4/win.h
> --- st-0.8.4.orig/win.h 2020-06-19 11:29:45.000000000 +0200
> +++ st-0.8.4/win.h 2020-11-27 00:02:20.482159051 +0100
> _AT_@ -33,6 +33,7 @@ int xsetcolorname(int, const char *);
> void xsettitle(char *);
> int xsetcursor(int);
> void xsetmode(int, unsigned int);
> +void xdomode(int, int, int, unsigned int);
> void xsetpointermotion(int);
> void xsetsel(char *);
> int xstartdraw(void);
> diff -rup st-0.8.4.orig/x.c st-0.8.4/x.c
> --- st-0.8.4.orig/x.c 2020-06-19 11:29:45.000000000 +0200
> +++ st-0.8.4/x.c 2020-11-27 00:34:55.913052592 +0100
> _AT_@ -1687,6 +1687,21 @@ xsetmode(int set, unsigned int flags)
> redraw();
> }
>
> +void
> +xdomode(int priv, int mode, int set, unsigned int flags)
> +{
> + switch (set) {
> + case 0:
> + case 1:
> + xsetmode(set, flags);
> + break;
> + case 2:
> + case 3:
> + DOBIT(priv, mode, win.mode, set, flags);
> + break;
> + }
> +}
> +
> int
> xsetcursor(int cursor)
> {
>

Hi Francois,

First: thanks for the patch.

Do you have maybe a practical use-case example why you'd like to request
supporting this?

In all st years it has not been requested before. I'd like to prevent
obscure/non-tested features. Although maybe it's not so obscure and useful, in
that case please say so :)

-- 
Kind regards,
Hiltjo
Received on Sun Nov 29 2020 - 17:37:30 CET

This archive was generated by hypermail 2.3.0 : Sun Nov 29 2020 - 17:48:32 CET