patch 9.1.1757: The colorresp plugin causes additional redraws

Problem:  The colorresp plugin causes additional redraws
          (Linwei, after v9.1.1703)
Solution: Move the code back into the C core and get rid of the vim
          plugin (Foxe Chen)

fixes: #18251
closes: #18279

Signed-off-by: Foxe Chen <chen.foxe@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Foxe Chen
2025-09-14 04:38:33 -04:00
committed by Christian Brabandt
parent c975d62473
commit c077f5e9d8
13 changed files with 251 additions and 170 deletions

View File

@ -131,6 +131,19 @@ static termrequest_T u7_status = TERMREQUEST_INIT;
static termrequest_T xcc_status = TERMREQUEST_INIT;
#ifdef FEAT_TERMRESPONSE
# ifdef FEAT_TERMINAL
// Request foreground color report:
static termrequest_T rfg_status = TERMREQUEST_INIT;
static int fg_r = 0;
static int fg_g = 0;
static int fg_b = 0;
static int bg_r = 255;
static int bg_g = 255;
static int bg_b = 255;
# endif
// Request background color report:
static termrequest_T rbg_status = TERMREQUEST_INIT;
// Request cursor blinking mode report:
static termrequest_T rbm_status = TERMREQUEST_INIT;
@ -145,6 +158,10 @@ static termrequest_T *all_termrequests[] = {
&crv_status,
&u7_status,
&xcc_status,
# ifdef FEAT_TERMINAL
&rfg_status,
# endif
&rbg_status,
&rbm_status,
&rcs_status,
&winpos_status,
@ -4190,6 +4207,49 @@ check_terminal_behavior(void)
}
}
/*
* Similar to requesting the version string: Request the terminal background
* color when it is the right moment.
*/
void
may_req_bg_color(void)
{
if (can_get_termresponse() && starting == 0)
{
int didit = FALSE;
# ifdef FEAT_TERMINAL
// Only request foreground if t_RF is set.
if (rfg_status.tr_progress == STATUS_GET && *T_RFG != NUL)
{
MAY_WANT_TO_LOG_THIS;
LOG_TR1("Sending FG request");
out_str(T_RFG);
termrequest_sent(&rfg_status);
didit = TRUE;
}
# endif
// Only request background if t_RB is set.
if (rbg_status.tr_progress == STATUS_GET && *T_RBG != NUL)
{
MAY_WANT_TO_LOG_THIS;
LOG_TR1("Sending BG request");
out_str(T_RBG);
termrequest_sent(&rbg_status);
didit = TRUE;
}
if (didit)
{
// check for the characters now, otherwise they might be eaten by
// get_keystroke()
out_flush();
(void)vpeekc_nomap();
}
}
}
#endif
/*
@ -4983,6 +5043,8 @@ handle_u7_response(int *arg, char_u *tp UNUSED, int csi_len UNUSED)
}
}
/*
* Handle a response to T_CRV: {lead}{first}{x};{vers};{y}c
* Xterm and alike use '>' for {first}.
@ -5743,6 +5805,93 @@ handle_csi(
return 0;
}
static void
check_for_color_response(char_u *resp, int len)
{
int i, j;
char_u *argp;
j = 1 + (resp[0] == ESC);
argp = resp + j;
if (len >= j + 3 && (argp[0] != '1'
|| (argp[1] != '1' && argp[1] != '0')
|| argp[2] != ';'))
i = 0; // no match
else
{
for (i = j; i < len; ++i)
if (resp[i] == '\007' || (resp[0] == OSC ? resp[i] == STERM
: (resp[i] == ESC && i + 1 < len && resp[i + 1] == '\\')))
{
int is_bg = argp[1] == '1';
int is_4digit = i - j >= 21 && resp[j + 11] == '/'
&& resp[j + 16] == '/';
if (i - j >= 15 && STRNCMP(resp + j + 3, "rgb:", 4) == 0
&& (is_4digit
|| (resp[j + 9] == '/' && resp[j + 12] == '/')))
{
char_u *tp_r = resp + j + 7;
char_u *tp_g = resp + j + (is_4digit ? 12 : 10);
char_u *tp_b = resp + j + (is_4digit ? 17 : 13);
#if defined(FEAT_TERMRESPONSE) && defined(FEAT_TERMINAL)
int rval, gval, bval;
rval = hexhex2nr(tp_r);
gval = hexhex2nr(tp_g);
bval = hexhex2nr(tp_b);
#endif
if (is_bg)
{
char *new_bg_val = (3 * '6' < *tp_r + *tp_g +
*tp_b) ? "light" : "dark";
LOG_TRN("Received RBG response: %s", tp);
#ifdef FEAT_TERMRESPONSE
rbg_status.tr_progress = STATUS_GOT;
# ifdef FEAT_TERMINAL
bg_r = rval;
bg_g = gval;
bg_b = bval;
# endif
#endif
if (!option_was_set((char_u *)"bg")
&& STRCMP(p_bg, new_bg_val) != 0)
{
// value differs, apply it
set_option_value_give_err((char_u *)"bg",
0L, (char_u *)new_bg_val, 0);
reset_option_was_set((char_u *)"bg");
redraw_asap(UPD_CLEAR);
}
}
#if defined(FEAT_TERMRESPONSE) && defined(FEAT_TERMINAL)
else
{
LOG_TRN("Received RFG response: %s", tp);
rfg_status.tr_progress = STATUS_GOT;
fg_r = rval;
fg_g = gval;
fg_b = bval;
}
#endif
}
#ifdef FEAT_EVAL
set_vim_var_string(is_bg ? VV_TERMRBGRESP
: VV_TERMRFGRESP, resp, len);
#endif
apply_autocmds(EVENT_TERMRESPONSEALL,
is_bg ? (char_u *)"background" : (char_u *)"foreground",
NULL, FALSE, curbuf);
break;
}
}
if (i == len)
LOG_TR1("not enough characters for RB");
}
static oscstate_T osc_state;
/*
@ -5803,6 +5952,9 @@ handle_osc(char_u *tp, int len, char_u *key_name, int *slen)
#ifdef FEAT_EVAL
set_vim_var_string_direct(VV_TERMOSC, osc_state.buf.ga_data);
#endif
// Check for background/foreground colour response
check_for_color_response(osc_state.buf.ga_data, osc_state.buf.ga_len - 1);
char_u savebg = *p_bg;
apply_autocmds(EVENT_TERMRESPONSEALL, (char_u *)"osc",
NULL, FALSE, curbuf);
@ -6584,28 +6736,18 @@ handle_osc:
}
#if (defined(FEAT_TERMINAL) && defined(FEAT_TERMRESPONSE)) || defined(PROTO)
static void
term_get_color(char_u *str, char_u *r, char_u *g, char_u *b)
{
char_u rn[3], gn[3], bn[3];
if (sscanf((char *)str, "%*[^:]:%2s%*[^/]/%2s%*[^/]/%2s",
(char *)&rn, (char *)&gn, (char *)&bn) != 3)
return;
*r = hexhex2nr(rn);
*g = hexhex2nr(gn);
*b = hexhex2nr(bn);
}
/*
* Get the text foreground color, if known.
*/
void
term_get_fg_color(char_u *r, char_u *g, char_u *b)
{
term_get_color(get_vim_var_str(VV_TERMRFGRESP), r, g, b);
if (rfg_status.tr_progress != STATUS_GOT)
return;
*r = fg_r;
*g = fg_g;
*b = fg_b;
}
/*
@ -6614,7 +6756,12 @@ term_get_fg_color(char_u *r, char_u *g, char_u *b)
void
term_get_bg_color(char_u *r, char_u *g, char_u *b)
{
term_get_color(get_vim_var_str(VV_TERMRBGRESP), r, g, b);
if (rbg_status.tr_progress != STATUS_GOT)
return;
*r = bg_r;
*g = bg_g;
*b = bg_b;
}
#endif