From 90f40ce7037a6fcb29c280d76d69e9831f21f110 Mon Sep 17 00:00:00 2001 From: a Date: Mon, 7 Sep 2026 00:46:10 -0500 Subject: [PATCH] tmux compatibility - New allowclipboard config flag (default on) so OSC 52 works without enabling all window ops. tmux set-clipboard was silently dropped before. - DA2 (CSI >c) and DA3 (CSI =c) answered; tmux fingerprints with these. - DSR 996 reports the colour scheme (dark/light) from the background. - DECRQM 2031 reported as permanently reset. - Unknown DCS sequences (DCS tmux; passthrough, XTGETTCAP) are discarded until ST instead of having their body interpreted as text/CSI. - Private mode 7727 (extended keys) silently ignored. - st.info: add RGB, Smulx, Setulc, kxIN, kxOUT and Hls so tmux and ncurses apps use truecolor, styled underlines, focus events and links. --- .st.h.swn | Bin 0 -> 16384 bytes .st.h.swo | Bin 0 -> 16384 bytes .st.h.swp | Bin 0 -> 16384 bytes config.def.h | 4 ++++ config.h | 4 ++++ st.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++---- st.h | 1 + st.info | 9 ++++++++ 8 files changed, 75 insertions(+), 4 deletions(-) create mode 100644 .st.h.swn create mode 100644 .st.h.swo create mode 100644 .st.h.swp diff --git a/.st.h.swn b/.st.h.swn new file mode 100644 index 0000000000000000000000000000000000000000..7f009ac05c10f9c1cc1dc4c4ed7d2761929ef64b GIT binary patch literal 16384 zcmeI1ZHOF68OPg8G_L2ps6jZQP)TH&SvNa7n-~*!bLZ?#?{2fbGfU4*c2-ZDo}QkW zHa*>w?w;(fS>p@h+npGY!}E*gKm|nz>YB8spOg%0yNgfD z>)b^xNxEj_e5>!}!ohCen6urSkqbin&2{gpxu_%*5DL6r1qNaJ)VcfWrx)_`)WyjY z$H_b1UVpvbL_48?P(Uak6c7ps1%v`Z0il3U;Qvs8uzy(kB=Ww8=l*5>{|#gRU*n%o z-=W^WdHGj)`Tg8M?B@`-Kg9n(HCE2e;-64JC?FIN3J3*+0zv_yfKWgvAQTV^2nB=! z{{sb#R`l#&rY``n{~tg9KmULv{RaFRJOjQDo&eWC7pUM2I0g=ZzuhlMe+7R4KLB3> z9|beu<@+S*S@1dF0}1@`t&;RB@N@84;DQ=B241;WlAZ>)fDhKeG`JVM@D{`Xx4}(t z9b5()I1P@1e@sczbKr;INw5dD!Flj*@amh95BM?oI`|a01lGYkI0pW81aZJG!AIQ1?T`WeKA;d02n};Uk=ZqTGN9iG`iVtps#-2= z>Z($f$px~&Pq!*s38(p4$#Mrh5?GF9hPLPGfot^1Ro+lmbxkhT3gy+hTF`iNW{eG! z4yd@J4hp61w5hzYS)-?DI8}u!rKHll<|h*Ad9BosUQlba5g{ZuLkuUheAfsq5}3Ya zxnw2>XQ-nxPpnSU3%jK6+daeIBZk|ejYg|)Y6_~K%Fj}lan00Wq)X)gs)Q=_0Am(< z#KdgzJ%{XcZL`Z=W`ZoaWbHL=w`IGXfCcP%g8&)QK{f{=Z2i8o2M2RBUFoESs%?_X zku9Yp>#OSa=2}(XEYyl?Y|u(tVM||GMTcp(mzJ1d%(y&cgltpHSgx?)jb&_MLLw2J zi+B=|Cc_NnP*oZj3m%;)J)>i(c7WM6MJHP58*b1ye2dOEW-+_*0p@*V@tgpMX}2_a zMXhXcpR9^+wHE?2o-8IO<%64 zC4Hr!lHBwZi6_QjEuYiZx_Kn`;d{|Y=9~TsB&F#{(ch7%95ZvW{Cr$ot!ee*dQyR>MyDuit&}e+ zRb?5!=j+O zi7Fd%Nm*Gz&H>v=xrBGkGXQ-b)@Gl6>OVgT^$nbIlGpPIIG2X&^c?iW{35 z1D&D5(VFav%ImV@eaHZNJMn-c*l1KIu%cc~L|}bAxD~%+ors+T$FN;vb9M`BHA_b^ zI;DMsvNSi^5tdw1cyQe)Ph4Eab&02rs%%6f8cTpdgnxW5(O%PW#Ww~MmWQc+)Piqj zNhU@~UMbYoTB0MGz{zm)W-59~xmc7HHRH~b785<=W-*GHOe;%Hkvw{sBREbQEX%bm zSuWFg7iCGui7Z8F;xfjv#TlKeNxx9vfcL3PV1L~5+O$QEB*!0~|43SQqtHk)XP!s< zX$-mDP~bM5EL5aO61ayXGy~j7_6*bag6J;Lc1>r18{HFqBQ(2KFxNeS#m$XNjeI`W zSYLMR=3MvTaeF(=;Q?l{0QaH6UT@NF4*bCL+qiq3ENdJb!U(-FN5Ni@qj&g7bU2~V z?pdRjAjF+8izMM$LoLycS1k)Ottgjq4QS(W%CSugOP#c=(6F6=-5As7|M%c|{04n4 z$Mb)@KmQ`0>3;!kg6rTi(7+-%4h{qQ-2Znx-~R~Q0N24jcoaMW9s-BJJ>Vtye*xSE zw*ZazO&~r(0il3UKqw#-5DEwdgaSeVp@2|8C=e-tSLWDzAvMeI5ghdvr6J1}_CLHG zf~|+d+^EJ|OJozGYzN?h5yG=LX5X2yKa% zOvbEil#1ATNV(0O{6u0kC92!mR7MWJ++@xEQGjzJRMh}^Cr!*78!JZH%4Cam3 HM~nXe=HCan literal 0 HcmV?d00001 diff --git a/.st.h.swo b/.st.h.swo new file mode 100644 index 0000000000000000000000000000000000000000..e8acfc85b1222008d629884a41109fe4d4736c7a GIT binary patch literal 16384 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') { + /* + * DA2 -- Secondary Device Attributes: CSI > Pp ; Pv ; Pc c + * Pp = 0 (VT100 class), Pv = firmware version, Pc = 0. + * tmux and others use this to fingerprint the terminal. + */ + if (csiescseq.arg[0] == 0) + ttywrite("\033[>0;95;0c", 10, 0); + break; + } + if (csiescseq.prefix == '=') { + /* DA3 -- Tertiary Device Attributes: unit id, all zeroes */ + if (csiescseq.arg[0] == 0) + ttywrite("\033P!|00000000\033\\", 14, 0); + break; + } if (csiescseq.arg[0] == 0) ttywrite(vtiden, strlen(vtiden), 0); break; @@ -2634,6 +2654,18 @@ csihandle(void) term.c.y+1, term.c.x+1); ttywrite(buffer, len, 0); break; + case 996: /* colour scheme (dark/light) report: CSI ? 997 ; Ps n */ + if (csiescseq.priv) { + unsigned char r, g, b; + int dark = 1; + if (!xgetcolor(defaultbg, &r, &g, &b)) + dark = (299*r + 587*g + 114*b) / 1000 < 128; + len = snprintf(buffer, sizeof(buffer), "\033[?997;%dn", + dark ? 1 : 2); + ttywrite(buffer, len, 0); + break; + } + goto unknown; default: goto unknown; } @@ -2871,7 +2903,7 @@ strhandle(void) #endif // CSI_22_23_PATCH return; case 52: - if (narg > 2 && allowwindowops) { + if (narg > 2 && (allowwindowops || allowclipboard)) { dec = base64dec(strescseq.args[2]); if (dec) { xsetsel(dec); @@ -3369,9 +3401,13 @@ dcshandle(void) switch (csiescseq.mode[0]) { default: unknown: - fprintf(stderr, "erresc: unknown csi "); - csidump(); - /* die(""); */ + /* + * An unknown DCS, e.g. the "DCS tmux;" passthrough wrapper or + * XTGETTCAP. Its body must not be interpreted, so discard every + * byte until the terminating ST. Note the body may contain ESC ESC + * (tmux doubles them), which must not end the string. + */ + term.esc |= ESC_DCS_IGNORE; break; #if SYNC_PATCH case '=': @@ -3541,6 +3577,23 @@ tputc(Rune u) * receives a ESC, a SUB, a ST or any other C1 control * character. */ + if (term.esc & ESC_DCS_IGNORE) { + static int sawesc; + if (sawesc) { + sawesc = 0; + if (u == '\\') { + term.esc = 0; + return; + } + /* ESC ESC or ESC : still inside the payload */ + if (u != 033) + return; + } + if (u == 033) + sawesc = 1; + return; + } + if (term.esc & ESC_STR) { if (u == '\a' || u == 030 || u == 032 || u == 033 || ISCONTROLC1(u)) { diff --git a/st.h b/st.h index 437498b..0408f4d 100644 --- a/st.h +++ b/st.h @@ -415,6 +415,7 @@ extern wchar_t *kbds_ldelim; #endif // KEYBOARDSELECT_PATCH extern int allowaltscreen; extern int allowwindowops; +extern int allowclipboard; extern char *termname; extern unsigned int tabspaces; extern unsigned int defaultfg; diff --git a/st.info b/st.info index b286fb5..5935bba 100644 --- a/st.info +++ b/st.info @@ -199,11 +199,20 @@ st-mono| simpleterm monocolor, # rep=%p1%c\E[%p2%{1}%-%db, # tmux extensions, see TERMINFO EXTENSIONS in tmux(1) Tc, + RGB, Ms=\E]52;%p1%s;%p2%s\007, Se=\E[2 q, Ss=\E[%p1%d q, # sync patch / SYNC_PATCH Sync=\EP=%p1%ds\E\\, +# undercurl patch / UNDERCURL_PATCH: styled and coloured underlines + Smulx=\E[4:%p1%dm, + Setulc=\E[58:2::%p1%{65536}%/%d:%p1%{256}%/%{255}%&%d:%p1%{255}%&%dm, +# focus events (mode 1004), used by tmux focus-events + kxIN=\E[I, + kxOUT=\E[O, +# hyperlinks / OSC7_OSC8_PATCH + Hls=\E]8;id=%p1%s;%p2%s\E\\, st| simpleterm, use=st-mono,