changeset 6901:2ce6b77a49de v7.4.770

patch 7.4.770 Problem: Background color response with transparency is not ignored. Solution: Change the way escape sequences are recognized. (partly by Hirohito Higashi)
author Bram Moolenaar <bram@vim.org>
date Fri, 10 Jul 2015 14:05:10 +0200
parents bfc3682510d6
children f3baff59f22a
files src/ascii.h src/term.c src/version.c
diffstat 3 files changed, 82 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/src/ascii.h
+++ b/src/ascii.h
@@ -34,10 +34,6 @@
 #define ESC_STR_nc	"\033"
 #define DEL		0x7f
 #define DEL_STR		(char_u *)"\177"
-#define CSI		0x9b	/* Control Sequence Introducer */
-#define CSI_STR		"\233"
-#define DCS		0x90	/* Device Control String */
-#define STERM		0x9c	/* String Terminator */
 
 #define POUND		0xA3
 
@@ -117,11 +113,6 @@
 #define ESC_STR_nc	"\x27"
 #define DEL		0x07
 #define DEL_STR		(char_u *)"\007"
-/* TODO: EBCDIC Code page dependent (here 1047) */
-#define CSI		0x9b	/* Control Sequence Introducer */
-#define CSI_STR		"\233"
-#define DCS		0x90	/* Device Control String */
-#define STERM		0x9c	/* String Terminator */
 
 #define POUND		0xB1
 
@@ -173,6 +164,13 @@ extern char MetaCharTable[];
 
 #endif /* defined EBCDIC */
 
+/* TODO: EBCDIC Code page dependent (here 1047) */
+#define CSI		0x9b	/* Control Sequence Introducer */
+#define CSI_STR		"\233"
+#define DCS		0x90	/* Device Control String */
+#define OSC		0x9d	/* Operating System Command */
+#define STERM		0x9c	/* String Terminator */
+
 /*
  * Character that separates dir names in a path.
  * For MS-DOS, WIN32 and OS/2 we use a backslash.  A slash mostly works
--- a/src/term.c
+++ b/src/term.c
@@ -2364,7 +2364,7 @@ term_7to8bit(p)
 	if (p[1] == '[')
 	    return CSI;
 	if (p[1] == ']')
-	    return 0x9d;
+	    return OSC;
 	if (p[1] == 'O')
 	    return 0x8f;
     }
@@ -4261,18 +4261,11 @@ check_termcode(max_offset, buf, bufsize,
 	     * - Cursor position report: <Esc>[{row};{col}R
 	     *   The final byte must be 'R'. It is used for checking the
 	     *   ambiguous-width character state.
-	     *
-	     * - Background color response:
-	     *       <Esc>]11;rgb:{rrrr}/{gggg}/{bbbb}\007
-	     *   Or
-	     *       <Esc>]11;rgb:{rrrr}/{gggg}/{bbbb}ST
-	     *   The final byte must be '\007' or ST(0x9c or ESC\).
 	     */
-	    char_u *argp = tp[0] == CSI ? tp + 1 : tp + 2;
-
-	    if ((*T_CRV != NUL || *T_U7 != NUL || *T_RBG != NUL)
-			&& ((tp[0] == ESC && tp[1] == '[' && len >= 3)
-			    || (tp[0] == ESC && tp[1] == ']' && len >= 24)
+	    char_u *argp = tp[0] == ESC ? tp + 2 : tp + 1;
+
+	    if ((*T_CRV != NUL || *T_U7 != NUL)
+			&& ((tp[0] == ESC && len >= 3 && tp[1] == '[')
 			    || (tp[0] == CSI && len >= 2))
 			&& (VIM_ISDIGIT(*argp) || *argp == '>' || *argp == '?'))
 	    {
@@ -4410,44 +4403,80 @@ check_termcode(max_offset, buf, bufsize,
 		    key_name[1] = (int)KE_IGNORE;
 		    slen = i + 1;
 		}
-		else if (*T_RBG != NUL
-			&& len >= 24 - (tp[0] == CSI)
-			&& len >= 24 - (tp[0] == CSI) + (argp[21] == ESC)
-			&& argp[0] == '1' && argp[1] == '1'
-			&& argp[2] == ';' && argp[3] == 'r' && argp[4] == 'g'
-			&& argp[5] == 'b' && argp[6] == ':'
-			&& argp[11] == '/' && argp[16] == '/'
-			&& (argp[21] == '\007' || argp[21] == STERM
-			    || (argp[21] == ESC && argp[22] == '\\')))
+	    }
+
+	    /* Check for background color response from the terminal:
+	     *
+	     *       {lead}11;rgb:{rrrr}/{gggg}/{bbbb}{tail}
+	     *
+	     * {lead} can be <Esc>] or OSC
+	     * {tail} can be '\007', <Esc>\ or STERM.
+	     *
+	     * Consume any code that starts with "{lead}11;", it's also
+	     * possible that "rgba" is following.
+	     */
+	    else if (*T_RBG != NUL
+			&& ((tp[0] == ESC && len >= 2 && tp[1] == ']')
+			    || tp[0] == OSC))
+	    {
+		j = 1 + (tp[0] == ESC);
+		if (len >= j + 3 && (argp[0] != '1'
+					 || argp[1] != '1' || argp[2] != ';'))
+		  i = 0; /* no match */
+		else
+		  for (i = j; i < len; ++i)
+		    if (tp[i] == '\007' || (tp[0] == OSC ? tp[i] == STERM
+			: (tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\')))
+		    {
+			if (i - j >= 21 && STRNCMP(tp + j + 3, "rgb:", 4) == 0
+			    && tp[j + 11] == '/' && tp[j + 16] == '/'
+			    && !option_was_set((char_u *)"bg"))
+			{/* TODO: don't set option when already the right value */
+			    LOG_TR("Received RBG");
+			    rbg_status = RBG_GOT;
+			    set_option_value((char_u *)"bg", 0L, (char_u *)(
+				    (3 * '6' < tp[j+7] + tp[j+12] + tp[j+17])
+				    ? "light" : "dark"), 0);
+			    reset_option_was_set((char_u *)"bg");
+			    redraw_asap(CLEAR);
+			}
+
+			/* got finished code: consume it */
+			key_name[0] = (int)KS_EXTRA;
+			key_name[1] = (int)KE_IGNORE;
+			slen = i + 1 + (tp[i] == ESC);
+			break;
+		    }
+		if (i == len)
 		{
-		    LOG_TR("Received RBG");
-		    rbg_status = RBG_GOT;
-		    if (!option_was_set((char_u *)"bg"))
-		    {
-			set_option_value((char_u *)"bg", 0L, (char_u *)(
-				    (3 * '6' < argp[7] + argp[12] + argp[17])
-						      ? "light" : "dark"), 0);
-			reset_option_was_set((char_u *)"bg");
-			redraw_asap(CLEAR);
-		    }
-		    key_name[0] = (int)KS_EXTRA;
-		    key_name[1] = (int)KE_IGNORE;
-		    slen = 24 - (tp[0] == CSI) + (argp[21] == ESC);
+		    LOG_TR("not enough characters for RB");
+		    return -1;
 		}
 	    }
 
-	    /* Check for '<Esc>P1+r<hex bytes><Esc>\'.  A "0" instead of the
-	     * "1" means an invalid request. */
+	    /* Check for key code response from xterm:
+	     *
+	     * {lead}{flag}+r<hex bytes><{tail}
+	     *
+	     * {lead} can be <Esc>P or DCS
+	     * {flag} can be '0' or '1'
+	     * {tail} can be Esc>\ or STERM
+	     *
+	     * Consume any code that starts with "{lead}.+r".
+	     */
 	    else if (check_for_codes
-		    && ((tp[0] == ESC && tp[1] == 'P' && len >= 2)
+		    && ((tp[0] == ESC && len >= 2 && tp[1] == 'P')
 			|| tp[0] == DCS))
 	    {
-		j = 1 + (tp[0] != DCS);
-		for (i = j; i < len; ++i)
-		    if ((tp[i] == ESC && tp[i + 1] == '\\' && i + 1 < len)
+		j = 1 + (tp[0] == ESC);
+		if (len >= j + 3 && (argp[1] != '+' || argp[2] != 'r'))
+		  i = 0; /* no match */
+		else
+		  for (i = j; i < len; ++i)
+		    if ((tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\')
 			    || tp[i] == STERM)
 		    {
-			if (i - j >= 3 && tp[j + 1] == '+' && tp[j + 2] == 'r')
+			if (i - j >= 3)
 			    got_code_from_term(tp + j, i);
 			key_name[0] = (int)KS_EXTRA;
 			key_name[1] = (int)KE_IGNORE;
@@ -4457,8 +4486,10 @@ check_termcode(max_offset, buf, bufsize,
 
 		if (i == len)
 		{
+		    /* These codes arrive many together, each code can be
+		     * truncated at any point. */
 		    LOG_TR("not enough characters for XT");
-		    return -1;		/* not enough characters */
+		    return -1;
 		}
 	    }
 	}
--- a/src/version.c
+++ b/src/version.c
@@ -742,6 +742,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    770,
+/**/
     769,
 /**/
     768,