073263
diff --git a/runtime/doc/tags b/runtime/doc/tags
073263
index b7e16df..f5201aa 100644
073263
--- a/runtime/doc/tags
073263
+++ b/runtime/doc/tags
073263
@@ -920,6 +920,7 @@ $VIMRUNTIME	starting.txt	/*$VIMRUNTIME*
073263
 't_KJ'	term.txt	/*'t_KJ'*
073263
 't_KK'	term.txt	/*'t_KK'*
073263
 't_KL'	term.txt	/*'t_KL'*
073263
+'t_RB'	term.txt	/*'t_RB'*
073263
 't_RI'	term.txt	/*'t_RI'*
073263
 't_RV'	term.txt	/*'t_RV'*
073263
 't_SI'	term.txt	/*'t_SI'*
073263
@@ -7987,6 +7988,7 @@ t_KI	term.txt	/*t_KI*
073263
 t_KJ	term.txt	/*t_KJ*
073263
 t_KK	term.txt	/*t_KK*
073263
 t_KL	term.txt	/*t_KL*
073263
+t_RB	term.txt	/*t_RB*
073263
 t_RI	term.txt	/*t_RI*
073263
 t_RV	term.txt	/*t_RV*
073263
 t_SI	term.txt	/*t_SI*
073263
diff --git a/runtime/doc/term.txt b/runtime/doc/term.txt
073263
index c11ddea..bdd6aba 100644
073263
--- a/runtime/doc/term.txt
073263
+++ b/runtime/doc/term.txt
073263
@@ -300,6 +300,8 @@ Added by Vim (there are no standard codes for these):
073263
 		|xterm-8bit| |v:termresponse| |'ttymouse'| |xterm-codes|
073263
 	t_u7	request cursor position (for xterm)		*t_u7* *'t_u7'*
073263
 		see |'ambiwidth'|
073263
+	t_RB	request terminal background color		*t_RB* *'t_RB'*
073263
+		see |'ambiwidth'|
073263
 
073263
 KEY CODES
073263
 Note: Use the <> form if possible
073263
diff --git a/src/ascii.h b/src/ascii.h
073263
index a3cfecf..7ed736a 100644
073263
--- a/src/ascii.h
073263
+++ b/src/ascii.h
073263
@@ -34,10 +34,6 @@
073263
 #define ESC_STR_nc	"\033"
073263
 #define DEL		0x7f
073263
 #define DEL_STR		(char_u *)"\177"
073263
-#define CSI		0x9b	/* Control Sequence Introducer */
073263
-#define CSI_STR		"\233"
073263
-#define DCS		0x90	/* Device Control String */
073263
-#define STERM		0x9c	/* String Terminator */
073263
 
073263
 #define POUND		0xA3
073263
 
073263
@@ -117,11 +113,6 @@
073263
 #define ESC_STR_nc	"\x27"
073263
 #define DEL		0x07
073263
 #define DEL_STR		(char_u *)"\007"
073263
-/* TODO: EBCDIC Code page dependent (here 1047) */
073263
-#define CSI		0x9b	/* Control Sequence Introducer */
073263
-#define CSI_STR		"\233"
073263
-#define DCS		0x90	/* Device Control String */
073263
-#define STERM		0x9c	/* String Terminator */
073263
 
073263
 #define POUND		0xB1
073263
 
073263
@@ -173,6 +164,13 @@ extern char MetaCharTable[];
073263
 
073263
 #endif /* defined EBCDIC */
073263
 
073263
+/* TODO: EBCDIC Code page dependent (here 1047) */
073263
+#define CSI		0x9b	/* Control Sequence Introducer */
073263
+#define CSI_STR		"\233"
073263
+#define DCS		0x90	/* Device Control String */
073263
+#define OSC		0x9d	/* Operating System Command */
073263
+#define STERM		0x9c	/* String Terminator */
073263
+
073263
 /*
073263
  * Character that separates dir names in a path.
073263
  * For MS-DOS, WIN32 and OS/2 we use a backslash.  A slash mostly works
073263
diff --git a/src/main.c b/src/main.c
073263
index 885192b..41c2c41 100644
073263
--- a/src/main.c
073263
+++ b/src/main.c
073263
@@ -825,8 +825,11 @@ vim_main2(int argc UNUSED, char **argv UNUSED)
073263
 
073263
     starttermcap();	    /* start termcap if not done by wait_return() */
073263
     TIME_MSG("start termcap");
073263
-#if defined(FEAT_TERMRESPONSE) && defined(FEAT_MBYTE)
073263
+#if defined(FEAT_TERMRESPONSE)
073263
+# if defined(FEAT_MBYTE)
073263
     may_req_ambiguous_char_width();
073263
+# endif
073263
+    may_req_bg_color();
073263
 #endif
073263
 
073263
 #ifdef FEAT_MOUSE
073263
diff --git a/src/proto/term.pro b/src/proto/term.pro
073263
index b3d0df3..f0c2a01 100644
073263
--- a/src/proto/term.pro
073263
+++ b/src/proto/term.pro
073263
@@ -36,6 +36,7 @@ void starttermcap __ARGS((void));
073263
 void stoptermcap __ARGS((void));
073263
 void may_req_termresponse __ARGS((void));
073263
 void may_req_ambiguous_char_width __ARGS((void));
073263
+void may_req_bg_color __ARGS((void));
073263
 int swapping_screen __ARGS((void));
073263
 void setmouse __ARGS((void));
073263
 int mouse_has __ARGS((int c));
073263
diff --git a/src/term.c b/src/term.c
073263
index 46274d8..660df07 100644
073263
--- a/src/term.c
073263
+++ b/src/term.c
073263
@@ -124,6 +124,11 @@ static int crv_status = CRV_GET;
073263
 #  define U7_SENT	2	/* did send T_U7, waiting for answer */
073263
 #  define U7_GOT	3	/* received T_U7 response */
073263
 static int u7_status = U7_GET;
073263
+/* Request background color report: */
073263
+#  define RBG_GET	1	/* send T_RBG when switched to RAW mode */
073263
+#  define RBG_SENT	2	/* did send T_RBG, waiting for answer */
073263
+#  define RBG_GOT	3	/* received T_RBG response */
073263
+static int rbg_status = RBG_GET;
073263
 # endif
073263
 
073263
 /*
073263
@@ -949,6 +954,7 @@ static struct builtin_term builtin_termcaps[] =
073263
     {(int)KS_CWP,	IF_EB("\033[3;%d;%dt", ESC_STR "[3;%d;%dt")},
073263
 #  endif
073263
     {(int)KS_CRV,	IF_EB("\033[>c", ESC_STR "[>c")},
073263
+    {(int)KS_RBG,	IF_EB("\033]11;?\007", ESC_STR "]11;?\007")},
073263
     {(int)KS_U7,	IF_EB("\033[6n", ESC_STR "[6n")},
073263
 
073263
     {K_UP,		IF_EB("\033O*A", ESC_STR "O*A")},
073263
@@ -1240,6 +1246,7 @@ static struct builtin_term builtin_termcaps[] =
073263
 #  endif
073263
     {(int)KS_CRV,	"[CRV]"},
073263
     {(int)KS_U7,	"[U7]"},
073263
+    {(int)KS_RBG,	"[RBG]"},
073263
     {K_UP,		"[KU]"},
073263
     {K_DOWN,		"[KD]"},
073263
     {K_LEFT,		"[KL]"},
073263
@@ -2357,7 +2364,7 @@ term_7to8bit(p)
073263
 	if (p[1] == '[')
073263
 	    return CSI;
073263
 	if (p[1] == ']')
073263
-	    return 0x9d;
073263
+	    return OSC;
073263
 	if (p[1] == 'O')
073263
 	    return 0x8f;
073263
     }
073263
@@ -3224,7 +3231,8 @@ settmode(tmode)
073263
 		 * doesn't work in Cooked mode, an external program may get
073263
 		 * them. */
073263
 		if (tmode != TMODE_RAW && (crv_status == CRV_SENT
073263
-					 || u7_status == U7_SENT))
073263
+					 || u7_status == U7_SENT
073263
+					 || rbg_status == RBG_SENT))
073263
 		    (void)vpeekc_nomap();
073263
 		check_for_codes_from_term();
073263
 	    }
073263
@@ -3285,8 +3293,9 @@ stoptermcap()
073263
 	if (!gui.in_use && !gui.starting)
073263
 # endif
073263
 	{
073263
-	    /* May need to discard T_CRV or T_U7 response. */
073263
-	    if (crv_status == CRV_SENT || u7_status == U7_SENT)
073263
+	    /* May need to discard T_CRV, T_U7 or T_RBG response. */
073263
+	    if (crv_status == CRV_SENT || u7_status == U7_SENT
073263
+						     || rbg_status == RBG_SENT)
073263
 	    {
073263
 # ifdef UNIX
073263
 		/* Give the terminal a chance to respond. */
073263
@@ -3398,6 +3407,36 @@ may_req_ambiguous_char_width()
073263
 }
073263
 # endif
073263
 
073263
+#if defined(FEAT_TERMRESPONSE) || defined(PROTO)
073263
+/*
073263
+ * Similar to requesting the version string: Request the terminal background
073263
+ * color when it is the right moment.
073263
+ */
073263
+    void
073263
+may_req_bg_color()
073263
+{
073263
+    if (rbg_status == RBG_GET
073263
+	    && cur_tmode == TMODE_RAW
073263
+	    && termcap_active
073263
+	    && p_ek
073263
+#  ifdef UNIX
073263
+	    && isatty(1)
073263
+	    && isatty(read_cmd_fd)
073263
+#  endif
073263
+	    && *T_RBG != NUL
073263
+	    && !option_was_set((char_u *)"bg"))
073263
+    {
073263
+	LOG_TR("Sending BG request");
073263
+	out_str(T_RBG);
073263
+	rbg_status = RBG_SENT;
073263
+	/* check for the characters now, otherwise they might be eaten by
073263
+	 * get_keystroke() */
073263
+	out_flush();
073263
+	(void)vpeekc_nomap();
073263
+    }
073263
+}
073263
+# endif
073263
+
073263
 # ifdef DEBUG_TERMRESPONSE
073263
     static void
073263
 log_tr(char *msg)
073263
@@ -4204,11 +4243,12 @@ check_termcode(max_offset, buf, bufsize, buflen)
073263
 	     *   The final byte must be 'R'. It is used for checking the
073263
 	     *   ambiguous-width character state.
073263
 	     */
073263
-	    p = tp[0] == CSI ? tp + 1 : tp + 2;
073263
+	    char_u *argp = tp[0] == ESC ? tp + 2 : tp + 1;
073263
+
073263
 	    if ((*T_CRV != NUL || *T_U7 != NUL)
073263
-			&& ((tp[0] == ESC && tp[1] == '[' && len >= 3)
073263
+			&& ((tp[0] == ESC && len >= 3 && tp[1] == '[')
073263
 			    || (tp[0] == CSI && len >= 2))
073263
-			&& (VIM_ISDIGIT(*p) || *p == '>' || *p == '?'))
073263
+			&& (VIM_ISDIGIT(*argp) || *argp == '>' || *argp == '?'))
073263
 	    {
073263
 #ifdef FEAT_MBYTE
073263
 		int col;
073263
@@ -4346,18 +4386,78 @@ check_termcode(max_offset, buf, bufsize, buflen)
073263
 		}
073263
 	    }
073263
 
073263
-	    /* Check for '<Esc>P1+r<hex bytes><Esc>\'.  A "0" instead of the
073263
-	     * "1" means an invalid request. */
073263
+	    /* Check for background color response from the terminal:
073263
+	     *
073263
+	     *       {lead}11;rgb:{rrrr}/{gggg}/{bbbb}{tail}
073263
+	     *
073263
+	     * {lead} can be <Esc>] or OSC
073263
+	     * {tail} can be '\007', <Esc>\ or STERM.
073263
+	     *
073263
+	     * Consume any code that starts with "{lead}11;", it's also
073263
+	     * possible that "rgba" is following.
073263
+	     */
073263
+	    else if (*T_RBG != NUL
073263
+			&& ((tp[0] == ESC && len >= 2 && tp[1] == ']')
073263
+			    || tp[0] == OSC))
073263
+	    {
073263
+		j = 1 + (tp[0] == ESC);
073263
+		if (len >= j + 3 && (argp[0] != '1'
073263
+					 || argp[1] != '1' || argp[2] != ';'))
073263
+		  i = 0; /* no match */
073263
+		else
073263
+		  for (i = j; i < len; ++i)
073263
+		    if (tp[i] == '\007' || (tp[0] == OSC ? tp[i] == STERM
073263
+			: (tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\')))
073263
+		    {
073263
+			if (i - j >= 21 && STRNCMP(tp + j + 3, "rgb:", 4) == 0
073263
+			    && tp[j + 11] == '/' && tp[j + 16] == '/'
073263
+			    && !option_was_set((char_u *)"bg"))
073263
+			{/* TODO: don't set option when already the right value */
073263
+			    LOG_TR("Received RBG");
073263
+			    rbg_status = RBG_GOT;
073263
+			    set_option_value((char_u *)"bg", 0L, (char_u *)(
073263
+				    (3 * '6' < tp[j+7] + tp[j+12] + tp[j+17])
073263
+				    ? "light" : "dark"), 0);
073263
+			    reset_option_was_set((char_u *)"bg");
073263
+			    redraw_asap(CLEAR);
073263
+			}
073263
+
073263
+			/* got finished code: consume it */
073263
+			key_name[0] = (int)KS_EXTRA;
073263
+			key_name[1] = (int)KE_IGNORE;
073263
+			slen = i + 1 + (tp[i] == ESC);
073263
+			break;
073263
+		    }
073263
+		if (i == len)
073263
+		{
073263
+		    LOG_TR("not enough characters for RB");
073263
+		    return -1;
073263
+		}
073263
+	    }
073263
+
073263
+	    /* Check for key code response from xterm:
073263
+	     *
073263
+	     * {lead}{flag}+r<hex bytes><{tail}
073263
+	     *
073263
+	     * {lead} can be <Esc>P or DCS
073263
+	     * {flag} can be '0' or '1'
073263
+	     * {tail} can be Esc>\ or STERM
073263
+	     *
073263
+	     * Consume any code that starts with "{lead}.+r".
073263
+	     */
073263
 	    else if (check_for_codes
073263
-		    && ((tp[0] == ESC && tp[1] == 'P' && len >= 2)
073263
+		    && ((tp[0] == ESC && len >= 2 && tp[1] == 'P')
073263
 			|| tp[0] == DCS))
073263
 	    {
073263
-		j = 1 + (tp[0] != DCS);
073263
-		for (i = j; i < len; ++i)
073263
-		    if ((tp[i] == ESC && tp[i + 1] == '\\' && i + 1 < len)
073263
+		j = 1 + (tp[0] == ESC);
073263
+		if (len >= j + 3 && (argp[1] != '+' || argp[2] != 'r'))
073263
+		  i = 0; /* no match */
073263
+		else
073263
+		  for (i = j; i < len; ++i)
073263
+		    if ((tp[i] == ESC && i + 1 < len && tp[i + 1] == '\\')
073263
 			    || tp[i] == STERM)
073263
 		    {
073263
-			if (i - j >= 3 && tp[j + 1] == '+' && tp[j + 2] == 'r')
073263
+			if (i - j >= 3)
073263
 			    got_code_from_term(tp + j, i);
073263
 			key_name[0] = (int)KS_EXTRA;
073263
 			key_name[1] = (int)KE_IGNORE;
073263
@@ -4367,8 +4467,10 @@ check_termcode(max_offset, buf, bufsize, buflen)
073263
 
073263
 		if (i == len)
073263
 		{
073263
+		    /* These codes arrive many together, each code can be
073263
+		     * truncated at any point. */
073263
 		    LOG_TR("not enough characters for XT");
073263
-		    return -1;		/* not enough characters */
073263
+		    return -1;
073263
 		}
073263
 	    }
073263
 	}
073263
diff --git a/src/term.h b/src/term.h
073263
index 28390a2..4925599 100644
073263
--- a/src/term.h
073263
+++ b/src/term.h
073263
@@ -79,6 +79,7 @@ enum SpecialKey
073263
     KS_CWP,	/* set window position in pixels */
073263
     KS_CWS,	/* set window size in characters */
073263
     KS_CRV,	/* request version string */
073263
+    KS_RBG,	/* request background color */
073263
     KS_CSI,	/* start insert mode (bar cursor) */
073263
     KS_CEI,	/* end insert mode (block cursor) */
073263
 #ifdef FEAT_VERTSPLIT
073263
@@ -160,6 +161,7 @@ extern char_u *(term_strings[]);    /* current terminal strings */
073263
 #define T_CSI	(term_str(KS_CSI))	/* start insert mode */
073263
 #define T_CEI	(term_str(KS_CEI))	/* end insert mode */
073263
 #define T_CRV	(term_str(KS_CRV))	/* request version string */
073263
+#define T_RBG	(term_str(KS_RBG))	/* request background RGB */
073263
 #define T_OP	(term_str(KS_OP))	/* original color pair */
073263
 #define T_U7	(term_str(KS_U7))	/* request cursor position */
073263
 
073263
diff --git a/src/option.c b/src/option.c
073263
index e20efc1..7da18a5 100644
073263
--- a/src/option.c
073263
+++ b/src/option.c
073263
@@ -2939,11 +2939,11 @@ static struct vimoption
073263
 #ifdef FEAT_VERTSPLIT
073263
     p_term("t_CV", T_CSV)
073263
 #endif
073263
-    p_term("t_ut", T_UT)
073263
     p_term("t_da", T_DA)
073263
     p_term("t_db", T_DB)
073263
     p_term("t_DL", T_CDL)
073263
     p_term("t_dl", T_DL)
073263
+    p_term("t_EI", T_CEI)
073263
     p_term("t_fs", T_FS)
073263
     p_term("t_IE", T_CIE)
073263
     p_term("t_IS", T_CIS)
073263
@@ -2957,27 +2957,28 @@ static struct vimoption
073263
     p_term("t_ms", T_MS)
073263
     p_term("t_nd", T_ND)
073263
     p_term("t_op", T_OP)
073263
+    p_term("t_RB", T_RBG)
073263
     p_term("t_RI", T_CRI)
073263
     p_term("t_RV", T_CRV)
073263
-    p_term("t_u7", T_U7)
073263
     p_term("t_Sb", T_CSB)
073263
-    p_term("t_Sf", T_CSF)
073263
     p_term("t_se", T_SE)
073263
+    p_term("t_Sf", T_CSF)
073263
+    p_term("t_SI", T_CSI)
073263
     p_term("t_so", T_SO)
073263
     p_term("t_sr", T_SR)
073263
-    p_term("t_ts", T_TS)
073263
     p_term("t_te", T_TE)
073263
     p_term("t_ti", T_TI)
073263
+    p_term("t_ts", T_TS)
073263
+    p_term("t_u7", T_U7)
073263
     p_term("t_ue", T_UE)
073263
     p_term("t_us", T_US)
073263
+    p_term("t_ut", T_UT)
073263
     p_term("t_vb", T_VB)
073263
     p_term("t_ve", T_VE)
073263
     p_term("t_vi", T_VI)
073263
     p_term("t_vs", T_VS)
073263
     p_term("t_WP", T_CWP)
073263
     p_term("t_WS", T_CWS)
073263
-    p_term("t_SI", T_CSI)
073263
-    p_term("t_EI", T_CEI)
073263
     p_term("t_xn", T_XN)
073263
     p_term("t_xs", T_XS)
073263
     p_term("t_ZH", T_CZH)
073263
diff --git a/src/term.c b/src/term.c
073263
index 660df07..b4b0c4b 100644
073263
--- a/src/term.c
073263
+++ b/src/term.c
073263
@@ -1622,7 +1622,7 @@ set_termname(term)
073263
 				{KS_TS, "ts"}, {KS_FS, "fs"},
073263
 				{KS_CWP, "WP"}, {KS_CWS, "WS"},
073263
 				{KS_CSI, "SI"}, {KS_CEI, "EI"},
073263
-				{KS_U7, "u7"},
073263
+				{KS_U7, "u7"}, {KS_RBG, "RB"},
073263
 				{(enum SpecialKey)0, NULL}
073263
 			    };
073263