patch 9.2.0227: MS-Windows: CSI sequences may be written to screen

Problem:  MS-Windows: CSI sequences may be written to screen
          (after v9.2.0200).
Solution: Move the CSI parsing and skipping logic outside of the USE_VTP
          guard in mch_write() so that sequences are always consumed
          even if VTP is inactive (Yasuhiro Matsumoto).

After v9.2.0200 added send_decrqm_modes(), running vim -u NONE -U NONE
-N on Windows displays raw ESC[?2026$p on screen. This is because
USE_VTP is false when termguicolors is off and t_colors < 256, and the
CSI skip logic in mch_write() was inside the if (USE_VTP) block, so
s/len were never advanced and the escape sequence leaked out as plain
text.

Move the CSI parsing/skipping outside the USE_VTP guard so sequences are
always consumed. Only the vtp_printf() pass-through for DECSCUSR (q)
remains conditional on USE_VTP.

related: #19755
closes:  #19762

Signed-off-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Yasuhiro Matsumoto
2026-03-22 17:05:14 +00:00
committed by Christian Brabandt
parent 48137e4e48
commit aeb716ea77
2 changed files with 19 additions and 22 deletions
+17 -22
View File
@@ -7440,30 +7440,25 @@ notsgr:
}
else if (s[0] == ESC && len >= 3-1 && s[1] == '[')
{
// When USE_VTP is active, CSI sequences written through
// write_chars() are interpreted by the console's VTP parser,
// generating responses (e.g. DECRQM) that end up in the
// input buffer as unwanted keystrokes. Parse the sequence
// and only pass through known safe ones (e.g. DECSCUSR for
// cursor shape), discard the rest.
if (USE_VTP)
{
int l = 2;
// CSI sequences should not be written as plain text to the
// console. Parse the sequence and skip over it. When
// USE_VTP is active, pass through known safe ones (e.g.
// DECSCUSR for cursor shape) via vtp_printf().
int l = 2;
// skip parameter and intermediate bytes (0x20-0x3F)
while (s + l < end && s[l] >= 0x20 && s[l] <= 0x3F)
l++;
// skip the final byte (0x40-0x7E)
if (s + l < end && s[l] >= 0x40 && s[l] <= 0x7E)
{
// DECSCUSR (cursor style): pass through to terminal
if (s[l] == 'q')
vtp_printf("%.*s", l + 1, s);
l++;
}
len -= l - 1;
s += l;
// skip parameter and intermediate bytes (0x20-0x3F)
while (s + l < end && s[l] >= 0x20 && s[l] <= 0x3F)
l++;
// skip the final byte (0x40-0x7E)
if (s + l < end && s[l] >= 0x40 && s[l] <= 0x7E)
{
// DECSCUSR (cursor style): pass through to terminal
if (USE_VTP && s[l] == 'q')
vtp_printf("%.*s", l + 1, s);
l++;
}
len -= l - 1;
s += l;
}
else
{
+2
View File
@@ -734,6 +734,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
227,
/**/
226,
/**/