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 @@ -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) */ @@ -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); @@ -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 @@ -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; } } @@ -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; } } @@ -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 @@ -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)) @@ -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 @@ -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 @@ -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) {
