Skip to content

Commit 16168c4

Browse files
brammooldouglaskayama
authored andcommitted
patch 7.4.757 Problem: Cannot detect the background color of a terminal. Solution: Add T_RBG to request the background color if possible. (Lubomir Rintel)
1 parent dfc5fc3 commit 16168c4

5 files changed

Lines changed: 86 additions & 7 deletions

File tree

src/main.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -853,8 +853,11 @@ vim_main2(int argc UNUSED, char **argv UNUSED)
853853

854854
starttermcap(); /* start termcap if not done by wait_return() */
855855
TIME_MSG("start termcap");
856-
#if defined(FEAT_TERMRESPONSE) && defined(FEAT_MBYTE)
856+
#if defined(FEAT_TERMRESPONSE)
857+
# if defined(FEAT_MBYTE)
857858
may_req_ambiguous_char_width();
859+
# endif
860+
may_req_bg_color();
858861
#endif
859862

860863
#ifdef FEAT_MOUSE

src/proto/term.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ void starttermcap __ARGS((void));
3636
void stoptermcap __ARGS((void));
3737
void may_req_termresponse __ARGS((void));
3838
void may_req_ambiguous_char_width __ARGS((void));
39+
void may_req_bg_color __ARGS((void));
3940
int swapping_screen __ARGS((void));
4041
void setmouse __ARGS((void));
4142
int mouse_has __ARGS((int c));

src/term.c

Lines changed: 77 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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 */
126126
static 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
34033447
log_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

src/term.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ enum SpecialKey
7979
KS_CWP, /* set window position in pixels */
8080
KS_CWS, /* set window size in characters */
8181
KS_CRV, /* request version string */
82+
KS_RBG, /* request background color */
8283
KS_CSI, /* start insert mode (bar cursor) */
8384
KS_CEI, /* end insert mode (block cursor) */
8485
KS_CSR, /* start replace mode (underline cursor) */
@@ -162,6 +163,7 @@ extern char_u *(term_strings[]); /* current terminal strings */
162163
#define T_CEI (term_str(KS_CEI)) /* end insert mode */
163164
#define T_CSR (term_str(KS_CSR)) /* start replace mode */
164165
#define T_CRV (term_str(KS_CRV)) /* request version string */
166+
#define T_RBG (term_str(KS_RBG)) /* request background RGB */
165167
#define T_OP (term_str(KS_OP)) /* original color pair */
166168
#define T_U7 (term_str(KS_U7)) /* request cursor position */
167169

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,6 +756,8 @@ static char *(features[]) =
756756

757757
static int included_patches[] =
758758
{ /* Add new patch number below this line */
759+
/**/
760+
757,
759761
/**/
760762
756,
761763
/**/

0 commit comments

Comments
 (0)