@@ -124,6 +124,11 @@ static int crv_status = CRV_GET;
124124# define U7_SENT 2 /* did send T_U7, waiting for answer */
125125# define U7_GOT 3 /* received T_U7 response */
126126static int u7_status = U7_GET ;
127+ /* Request background color report: */
128+ # define RBG_GET 1 /* send T_RBG when switched to RAW mode */
129+ # define RBG_SENT 2 /* did send T_RBG, waiting for answer */
130+ # define RBG_GOT 3 /* received T_RBG response */
131+ static int rbg_status = RBG_GET ;
127132# endif
128133
129134/*
@@ -949,6 +954,7 @@ static struct builtin_term builtin_termcaps[] =
949954 {(int )KS_CWP , IF_EB ("\033[3;%d;%dt" , ESC_STR "[3;%d;%dt" )},
950955# endif
951956 {(int )KS_CRV , IF_EB ("\033[>c" , ESC_STR "[>c" )},
957+ {(int )KS_RBG , IF_EB ("\033]11;?\007" , ESC_STR "]11;?\007" )},
952958 {(int )KS_U7 , IF_EB ("\033[6n" , ESC_STR "[6n" )},
953959
954960 {K_UP , IF_EB ("\033O*A" , ESC_STR "O*A" )},
@@ -1240,6 +1246,7 @@ static struct builtin_term builtin_termcaps[] =
12401246# endif
12411247 {(int )KS_CRV , "[CRV]" },
12421248 {(int )KS_U7 , "[U7]" },
1249+ {(int )KS_RBG , "[RBG]" },
12431250 {K_UP , "[KU]" },
12441251 {K_DOWN , "[KD]" },
12451252 {K_LEFT , "[KL]" },
@@ -3224,7 +3231,8 @@ settmode(tmode)
32243231 * doesn't work in Cooked mode, an external program may get
32253232 * them. */
32263233 if (tmode != TMODE_RAW && (crv_status == CRV_SENT
3227- || u7_status == U7_SENT ))
3234+ || u7_status == U7_SENT
3235+ || rbg_status == RBG_SENT ))
32283236 (void )vpeekc_nomap ();
32293237 check_for_codes_from_term ();
32303238 }
@@ -3285,8 +3293,9 @@ stoptermcap()
32853293 if (!gui .in_use && !gui .starting )
32863294# endif
32873295 {
3288- /* May need to discard T_CRV or T_U7 response. */
3289- if (crv_status == CRV_SENT || u7_status == U7_SENT )
3296+ /* May need to discard T_CRV, T_U7 or T_RBG response. */
3297+ if (crv_status == CRV_SENT || u7_status == U7_SENT
3298+ || rbg_status == RBG_SENT )
32903299 {
32913300# ifdef UNIX
32923301 /* Give the terminal a chance to respond. */
@@ -3398,6 +3407,41 @@ may_req_ambiguous_char_width()
33983407}
33993408# endif
34003409
3410+ #if defined(FEAT_TERMRESPONSE ) || defined(PROTO )
3411+ /*
3412+ * Check how the terminal treats ambiguous character width (UAX #11).
3413+ * First, we move the cursor to (1, 0) and print a test ambiguous character
3414+ * \u25bd (WHITE DOWN-POINTING TRIANGLE) and query current cursor position.
3415+ * If the terminal treats \u25bd as single width, the position is (1, 1),
3416+ * or if it is treated as double width, that will be (1, 2).
3417+ * This function has the side effect that changes cursor position, so
3418+ * it must be called immediately after entering termcap mode.
3419+ */
3420+ void
3421+ may_req_bg_color ()
3422+ {
3423+ if (rbg_status == RBG_GET
3424+ && cur_tmode == TMODE_RAW
3425+ && termcap_active
3426+ && p_ek
3427+ # ifdef UNIX
3428+ && isatty (1 )
3429+ && isatty (read_cmd_fd )
3430+ # endif
3431+ && * T_RBG != NUL
3432+ && !option_was_set ((char_u * )"bg" ))
3433+ {
3434+ LOG_TR ("Sending BG request" );
3435+ out_str (T_RBG );
3436+ rbg_status = RBG_SENT ;
3437+ /* check for the characters now, otherwise they might be eaten by
3438+ * get_keystroke() */
3439+ out_flush ();
3440+ (void )vpeekc_nomap ();
3441+ }
3442+ }
3443+ # endif
3444+
34013445# ifdef DEBUG_TERMRESPONSE
34023446 static void
34033447log_tr (char * msg )
@@ -4222,12 +4266,18 @@ check_termcode(max_offset, buf, bufsize, buflen)
42224266 * - Cursor position report: <Esc>[{row};{col}R
42234267 * The final byte must be 'R'. It is used for checking the
42244268 * ambiguous-width character state.
4269+ *
4270+ * - Background color response:
4271+ * <Esc>]11;rgb:{rrrr}/{gggg}/{bbbb}\007
4272+ * The final byte must be '\007'.
42254273 */
4226- p = tp [0 ] == CSI ? tp + 1 : tp + 2 ;
4227- if ((* T_CRV != NUL || * T_U7 != NUL )
4274+ char_u * argp = tp [0 ] == CSI ? tp + 1 : tp + 2 ;
4275+
4276+ if ((* T_CRV != NUL || * T_U7 != NUL || * T_RBG != NUL )
42284277 && ((tp [0 ] == ESC && tp [1 ] == '[' && len >= 3 )
4278+ || (tp [0 ] == ESC && tp [1 ] == ']' && len >= 24 )
42294279 || (tp [0 ] == CSI && len >= 2 ))
4230- && (VIM_ISDIGIT (* p ) || * p == '>' || * p == '?' ))
4280+ && (VIM_ISDIGIT (* argp ) || * argp == '>' || * argp == '?' ))
42314281 {
42324282#ifdef FEAT_MBYTE
42334283 int col ;
@@ -4363,6 +4413,27 @@ check_termcode(max_offset, buf, bufsize, buflen)
43634413 key_name [1 ] = (int )KE_IGNORE ;
43644414 slen = i + 1 ;
43654415 }
4416+ else if (* T_RBG != NUL && len >= 24 - (tp [0 ] == CSI )
4417+ && argp [0 ] == '1' && argp [1 ] == '1'
4418+ && argp [2 ] == ';' && argp [3 ] == 'r' && argp [4 ] == 'g'
4419+ && argp [5 ] == 'b' && argp [6 ] == ':'
4420+ && argp [11 ] == '/' && argp [16 ] == '/'
4421+ && argp [21 ] == '\007' )
4422+ {
4423+ LOG_TR ("Received RBG" );
4424+ rbg_status = RBG_GOT ;
4425+ if (!option_was_set ((char_u * )"bg" ))
4426+ {
4427+ set_option_value ((char_u * )"bg" , 0L , (char_u * )(
4428+ (3 * '6' < argp [7 ] + argp [12 ] + argp [17 ])
4429+ ? "light" : "dark" ), 0 );
4430+ reset_option_was_set ((char_u * )"bg" );
4431+ redraw_asap (CLEAR );
4432+ }
4433+ key_name [0 ] = (int )KS_EXTRA ;
4434+ key_name [1 ] = (int )KE_IGNORE ;
4435+ slen = 24 ;
4436+ }
43664437 }
43674438
43684439 /* Check for '<Esc>P1+r<hex bytes><Esc>\'. A "0" instead of the
0 commit comments