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

From: François-Xavier Carton <fx.carton91_AT_gmail.com>
Date: Fri, 27 Nov 2020 01:54:36 +0100

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)
 {
Received on Fri Nov 27 2020 - 01:54:36 CET

This archive was generated by hypermail 2.3.0 : Fri Nov 27 2020 - 02:00:33 CET