mirror of
https://github.com/vim/vim
synced 2025-07-15 16:51:57 +00:00
patch 8.1.1315: there is always a delay if a termrequest is never answered
Problem: There is always a delay if a termrequest is never answered. Solution: When the response is not received within two seconds consider the request to have failed.
This commit is contained in:
214
src/term.c
214
src/term.c
@ -110,19 +110,29 @@ static void log_tr(const char *fmt, ...);
|
||||
# define LOG_TR(msg) do { /**/ } while (0)
|
||||
# endif
|
||||
|
||||
# define STATUS_GET 1 /* send request when switching to RAW mode */
|
||||
# define STATUS_SENT 2 /* did send request, waiting for response */
|
||||
# define STATUS_GOT 3 /* received response */
|
||||
typedef enum {
|
||||
STATUS_GET, // send request when switching to RAW mode
|
||||
STATUS_SENT, // did send request, checking for response
|
||||
STATUS_GOT, // received response
|
||||
STATUS_FAIL // timed out
|
||||
} request_progress_T;
|
||||
|
||||
/* Request Terminal Version status: */
|
||||
static int crv_status = STATUS_GET;
|
||||
typedef struct {
|
||||
request_progress_T tr_progress;
|
||||
time_t tr_start; // when request was sent, -1 for never
|
||||
} termrequest_T;
|
||||
|
||||
/* Request Cursor position report: */
|
||||
static int u7_status = STATUS_GET;
|
||||
# define TERMREQUEST_INIT {STATUS_GET, -1}
|
||||
|
||||
// Request Terminal Version status:
|
||||
static termrequest_T crv_status = TERMREQUEST_INIT;
|
||||
|
||||
// Request Cursor position report:
|
||||
static termrequest_T u7_status = TERMREQUEST_INIT;
|
||||
|
||||
# ifdef FEAT_TERMINAL
|
||||
/* Request foreground color report: */
|
||||
static int rfg_status = STATUS_GET;
|
||||
// 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;
|
||||
@ -132,16 +142,29 @@ static int bg_b = 255;
|
||||
# endif
|
||||
|
||||
/* Request background color report: */
|
||||
static int rbg_status = STATUS_GET;
|
||||
static termrequest_T rbg_status = TERMREQUEST_INIT;
|
||||
|
||||
/* Request cursor blinking mode report: */
|
||||
static int rbm_status = STATUS_GET;
|
||||
static termrequest_T rbm_status = TERMREQUEST_INIT;
|
||||
|
||||
/* Request cursor style report: */
|
||||
static int rcs_status = STATUS_GET;
|
||||
static termrequest_T rcs_status = TERMREQUEST_INIT;
|
||||
|
||||
/* Request windos position report: */
|
||||
static int winpos_status = STATUS_GET;
|
||||
static termrequest_T winpos_status = TERMREQUEST_INIT;
|
||||
|
||||
static termrequest_T *all_termrequests[] = {
|
||||
&crv_status,
|
||||
&u7_status,
|
||||
# ifdef FEAT_TERMINAL
|
||||
&rfg_status,
|
||||
# endif
|
||||
&rbg_status,
|
||||
&rbm_status,
|
||||
&rcs_status,
|
||||
&winpos_status,
|
||||
NULL
|
||||
};
|
||||
# endif
|
||||
|
||||
/*
|
||||
@ -2011,7 +2034,7 @@ set_termname(char_u *term)
|
||||
set_term_defaults(); /* use current values as defaults */
|
||||
#ifdef FEAT_TERMRESPONSE
|
||||
LOG_TR(("setting crv_status to STATUS_GET"));
|
||||
crv_status = STATUS_GET; /* Get terminal version later */
|
||||
crv_status.tr_progress = STATUS_GET; // Get terminal version later
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -2833,12 +2856,47 @@ can_get_termresponse()
|
||||
{
|
||||
return cur_tmode == TMODE_RAW
|
||||
&& termcap_active
|
||||
# ifdef UNIX
|
||||
# ifdef UNIX
|
||||
&& (is_not_a_term() || (isatty(1) && isatty(read_cmd_fd)))
|
||||
# endif
|
||||
# endif
|
||||
&& p_ek;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set "status" to STATUS_SENT.
|
||||
*/
|
||||
static void
|
||||
termrequest_sent(termrequest_T *status)
|
||||
{
|
||||
status->tr_progress = STATUS_SENT;
|
||||
status->tr_start = time(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return TRUE if any of the requests are in STATUS_SENT.
|
||||
*/
|
||||
static int
|
||||
termrequest_any_pending()
|
||||
{
|
||||
int i;
|
||||
time_t now = time(NULL);
|
||||
|
||||
for (i = 0; all_termrequests[i] != NULL; ++i)
|
||||
{
|
||||
if (all_termrequests[i]->tr_progress == STATUS_SENT)
|
||||
{
|
||||
if (all_termrequests[i]->tr_start > 0 && now > 0
|
||||
&& all_termrequests[i]->tr_start + 2 < now)
|
||||
// Sent the request more than 2 seconds ago and didn't get a
|
||||
// response, assume it failed.
|
||||
all_termrequests[i]->tr_progress = STATUS_FAIL;
|
||||
else
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static int winpos_x = -1;
|
||||
static int winpos_y = -1;
|
||||
static int did_request_winpos = 0;
|
||||
@ -2860,7 +2918,7 @@ term_get_winpos(int *x, int *y, varnumber_T timeout)
|
||||
winpos_x = -1;
|
||||
winpos_y = -1;
|
||||
++did_request_winpos;
|
||||
winpos_status = STATUS_SENT;
|
||||
termrequest_sent(&winpos_status);
|
||||
OUT_STR(T_CGP);
|
||||
out_flush();
|
||||
|
||||
@ -3478,18 +3536,10 @@ settmode(int tmode)
|
||||
if (!gui.in_use && !gui.starting)
|
||||
# endif
|
||||
{
|
||||
/* May need to check for T_CRV response and termcodes, it
|
||||
* doesn't work in Cooked mode, an external program may get
|
||||
* them. */
|
||||
if (tmode != TMODE_RAW && (crv_status == STATUS_SENT
|
||||
|| u7_status == STATUS_SENT
|
||||
#ifdef FEAT_TERMINAL
|
||||
|| rfg_status == STATUS_SENT
|
||||
#endif
|
||||
|| rbg_status == STATUS_SENT
|
||||
|| rbm_status == STATUS_SENT
|
||||
|| rcs_status == STATUS_SENT
|
||||
|| winpos_status == STATUS_SENT))
|
||||
// May need to check for T_CRV response and termcodes, it
|
||||
// doesn't work in Cooked mode, an external program may get
|
||||
// them.
|
||||
if (tmode != TMODE_RAW && termrequest_any_pending())
|
||||
(void)vpeekc_nomap();
|
||||
check_for_codes_from_term();
|
||||
}
|
||||
@ -3540,7 +3590,7 @@ starttermcap(void)
|
||||
may_req_termresponse();
|
||||
/* Immediately check for a response. If t_Co changes, we don't
|
||||
* want to redraw with wrong colors first. */
|
||||
if (crv_status == STATUS_SENT)
|
||||
if (crv_status.tr_progress == STATUS_SENT)
|
||||
check_for_codes_from_term();
|
||||
}
|
||||
#endif
|
||||
@ -3559,23 +3609,15 @@ stoptermcap(void)
|
||||
if (!gui.in_use && !gui.starting)
|
||||
# endif
|
||||
{
|
||||
/* May need to discard T_CRV, T_U7 or T_RBG response. */
|
||||
if (crv_status == STATUS_SENT
|
||||
|| u7_status == STATUS_SENT
|
||||
# ifdef FEAT_TERMINAL
|
||||
|| rfg_status == STATUS_SENT
|
||||
# endif
|
||||
|| rbg_status == STATUS_SENT
|
||||
|| rbm_status == STATUS_SENT
|
||||
|| rcs_status == STATUS_SENT
|
||||
|| winpos_status == STATUS_SENT)
|
||||
// May need to discard T_CRV, T_U7 or T_RBG response.
|
||||
if (termrequest_any_pending())
|
||||
{
|
||||
# ifdef UNIX
|
||||
/* Give the terminal a chance to respond. */
|
||||
// Give the terminal a chance to respond.
|
||||
mch_delay(100L, FALSE);
|
||||
# endif
|
||||
# ifdef TCIFLUSH
|
||||
/* Discard data received but not read. */
|
||||
// Discard data received but not read.
|
||||
if (exiting)
|
||||
tcflush(fileno(stdin), TCIFLUSH);
|
||||
# endif
|
||||
@ -3614,14 +3656,14 @@ stoptermcap(void)
|
||||
void
|
||||
may_req_termresponse(void)
|
||||
{
|
||||
if (crv_status == STATUS_GET
|
||||
if (crv_status.tr_progress == STATUS_GET
|
||||
&& can_get_termresponse()
|
||||
&& starting == 0
|
||||
&& *T_CRV != NUL)
|
||||
{
|
||||
LOG_TR(("Sending CRV request"));
|
||||
out_str(T_CRV);
|
||||
crv_status = STATUS_SENT;
|
||||
termrequest_sent(&crv_status);
|
||||
/* check for the characters now, otherwise they might be eaten by
|
||||
* get_keystroke() */
|
||||
out_flush();
|
||||
@ -3641,37 +3683,37 @@ may_req_termresponse(void)
|
||||
void
|
||||
may_req_ambiguous_char_width(void)
|
||||
{
|
||||
if (u7_status == STATUS_GET
|
||||
if (u7_status.tr_progress == STATUS_GET
|
||||
&& can_get_termresponse()
|
||||
&& starting == 0
|
||||
&& *T_U7 != NUL
|
||||
&& !option_was_set((char_u *)"ambiwidth"))
|
||||
{
|
||||
char_u buf[16];
|
||||
char_u buf[16];
|
||||
|
||||
LOG_TR(("Sending U7 request"));
|
||||
/* Do this in the second row. In the first row the returned sequence
|
||||
* may be CSI 1;2R, which is the same as <S-F3>. */
|
||||
term_windgoto(1, 0);
|
||||
buf[mb_char2bytes(0x25bd, buf)] = 0;
|
||||
out_str(buf);
|
||||
out_str(T_U7);
|
||||
u7_status = STATUS_SENT;
|
||||
out_flush();
|
||||
LOG_TR(("Sending U7 request"));
|
||||
/* Do this in the second row. In the first row the returned sequence
|
||||
* may be CSI 1;2R, which is the same as <S-F3>. */
|
||||
term_windgoto(1, 0);
|
||||
buf[mb_char2bytes(0x25bd, buf)] = 0;
|
||||
out_str(buf);
|
||||
out_str(T_U7);
|
||||
termrequest_sent(&u7_status);
|
||||
out_flush();
|
||||
|
||||
/* This overwrites a few characters on the screen, a redraw is needed
|
||||
* after this. Clear them out for now. */
|
||||
term_windgoto(1, 0);
|
||||
out_str((char_u *)" ");
|
||||
term_windgoto(0, 0);
|
||||
/* This overwrites a few characters on the screen, a redraw is needed
|
||||
* after this. Clear them out for now. */
|
||||
term_windgoto(1, 0);
|
||||
out_str((char_u *)" ");
|
||||
term_windgoto(0, 0);
|
||||
|
||||
/* Need to reset the known cursor position. */
|
||||
screen_start();
|
||||
/* Need to reset the known cursor position. */
|
||||
screen_start();
|
||||
|
||||
/* check for the characters now, otherwise they might be eaten by
|
||||
* get_keystroke() */
|
||||
out_flush();
|
||||
(void)vpeekc_nomap();
|
||||
/* check for the characters now, otherwise they might be eaten by
|
||||
* get_keystroke() */
|
||||
out_flush();
|
||||
(void)vpeekc_nomap();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3688,21 +3730,21 @@ may_req_bg_color(void)
|
||||
|
||||
# ifdef FEAT_TERMINAL
|
||||
/* Only request foreground if t_RF is set. */
|
||||
if (rfg_status == STATUS_GET && *T_RFG != NUL)
|
||||
if (rfg_status.tr_progress == STATUS_GET && *T_RFG != NUL)
|
||||
{
|
||||
LOG_TR(("Sending FG request"));
|
||||
out_str(T_RFG);
|
||||
rfg_status = STATUS_SENT;
|
||||
termrequest_sent(&rfg_status);
|
||||
didit = TRUE;
|
||||
}
|
||||
# endif
|
||||
|
||||
/* Only request background if t_RB is set. */
|
||||
if (rbg_status == STATUS_GET && *T_RBG != NUL)
|
||||
if (rbg_status.tr_progress == STATUS_GET && *T_RBG != NUL)
|
||||
{
|
||||
LOG_TR(("Sending BG request"));
|
||||
out_str(T_RBG);
|
||||
rbg_status = STATUS_SENT;
|
||||
termrequest_sent(&rbg_status);
|
||||
didit = TRUE;
|
||||
}
|
||||
|
||||
@ -3962,7 +4004,7 @@ term_cursor_color(char_u *color)
|
||||
blink_state_is_inverted()
|
||||
{
|
||||
#ifdef FEAT_TERMRESPONSE
|
||||
return rbm_status == STATUS_GOT && rcs_status == STATUS_GOT
|
||||
return rbm_status.tr_progress == STATUS_GOT && rcs_status.tr_progress == STATUS_GOT
|
||||
&& initial_cursor_blink != initial_cursor_shape_blink;
|
||||
#else
|
||||
return FALSE;
|
||||
@ -4651,7 +4693,7 @@ check_termcode(
|
||||
char *aw = NULL;
|
||||
|
||||
LOG_TR(("Received U7 status: %s", tp));
|
||||
u7_status = STATUS_GOT;
|
||||
u7_status.tr_progress = STATUS_GOT;
|
||||
did_cursorhold = TRUE;
|
||||
if (col == 2)
|
||||
aw = "single";
|
||||
@ -4689,7 +4731,7 @@ check_termcode(
|
||||
int version = col;
|
||||
|
||||
LOG_TR(("Received CRV response: %s", tp));
|
||||
crv_status = STATUS_GOT;
|
||||
crv_status.tr_progress = STATUS_GOT;
|
||||
did_cursorhold = TRUE;
|
||||
|
||||
/* If this code starts with CSI, you can bet that the
|
||||
@ -4804,7 +4846,7 @@ check_termcode(
|
||||
* 279 (otherwise it returns 0x18).
|
||||
* Not for Terminal.app, it can't handle t_RS, it
|
||||
* echoes the characters to the screen. */
|
||||
if (rcs_status == STATUS_GET
|
||||
if (rcs_status.tr_progress == STATUS_GET
|
||||
&& version >= 279
|
||||
&& !is_not_xterm
|
||||
&& *T_CSH != NUL
|
||||
@ -4812,20 +4854,20 @@ check_termcode(
|
||||
{
|
||||
LOG_TR(("Sending cursor style request"));
|
||||
out_str(T_CRS);
|
||||
rcs_status = STATUS_SENT;
|
||||
termrequest_sent(&rcs_status);
|
||||
need_flush = TRUE;
|
||||
}
|
||||
|
||||
/* Only request the cursor blink mode if t_RC set. Not
|
||||
* for Gnome terminal, it can't handle t_RC, it
|
||||
* echoes the characters to the screen. */
|
||||
if (rbm_status == STATUS_GET
|
||||
if (rbm_status.tr_progress == STATUS_GET
|
||||
&& !is_not_xterm
|
||||
&& *T_CRC != NUL)
|
||||
{
|
||||
LOG_TR(("Sending cursor blink mode request"));
|
||||
out_str(T_CRC);
|
||||
rbm_status = STATUS_SENT;
|
||||
termrequest_sent(&rbm_status);
|
||||
need_flush = TRUE;
|
||||
}
|
||||
|
||||
@ -4848,7 +4890,7 @@ check_termcode(
|
||||
*
|
||||
* {lead} can be <Esc>[ or CSI
|
||||
*/
|
||||
else if (rbm_status == STATUS_SENT
|
||||
else if (rbm_status.tr_progress == STATUS_SENT
|
||||
&& tp[(j = 1 + (tp[0] == ESC))] == '?'
|
||||
&& i == j + 6
|
||||
&& tp[j + 1] == '1'
|
||||
@ -4858,7 +4900,7 @@ check_termcode(
|
||||
&& tp[i] == 'y')
|
||||
{
|
||||
initial_cursor_blink = (tp[j + 4] == '1');
|
||||
rbm_status = STATUS_GOT;
|
||||
rbm_status.tr_progress = STATUS_GOT;
|
||||
LOG_TR(("Received cursor blinking mode response: %s", tp));
|
||||
key_name[0] = (int)KS_EXTRA;
|
||||
key_name[1] = (int)KE_IGNORE;
|
||||
@ -4896,7 +4938,7 @@ check_termcode(
|
||||
slen = i + 1;
|
||||
|
||||
if (--did_request_winpos <= 0)
|
||||
winpos_status = STATUS_GOT;
|
||||
winpos_status.tr_progress = STATUS_GOT;
|
||||
}
|
||||
}
|
||||
if (i == len)
|
||||
@ -4948,7 +4990,7 @@ check_termcode(
|
||||
+ tp[j+17]) ? "light" : "dark";
|
||||
|
||||
LOG_TR(("Received RBG response: %s", tp));
|
||||
rbg_status = STATUS_GOT;
|
||||
rbg_status.tr_progress = STATUS_GOT;
|
||||
# ifdef FEAT_TERMINAL
|
||||
bg_r = rval;
|
||||
bg_g = gval;
|
||||
@ -4968,7 +5010,7 @@ check_termcode(
|
||||
else
|
||||
{
|
||||
LOG_TR(("Received RFG response: %s", tp));
|
||||
rfg_status = STATUS_GOT;
|
||||
rfg_status.tr_progress = STATUS_GOT;
|
||||
fg_r = rval;
|
||||
fg_g = gval;
|
||||
fg_b = bval;
|
||||
@ -5008,7 +5050,7 @@ check_termcode(
|
||||
*
|
||||
* Consume any code that starts with "{lead}.+r" or "{lead}.$r".
|
||||
*/
|
||||
else if ((check_for_codes || rcs_status == STATUS_SENT)
|
||||
else if ((check_for_codes || rcs_status.tr_progress == STATUS_SENT)
|
||||
&& ((tp[0] == ESC && len >= 2 && tp[1] == 'P')
|
||||
|| tp[0] == DCS))
|
||||
{
|
||||
@ -5061,7 +5103,7 @@ check_termcode(
|
||||
* the value set with T_SH. */
|
||||
initial_cursor_shape_blink =
|
||||
(number & 1) ? FALSE : TRUE;
|
||||
rcs_status = STATUS_GOT;
|
||||
rcs_status.tr_progress = STATUS_GOT;
|
||||
LOG_TR(("Received cursor shape response: %s", tp));
|
||||
|
||||
key_name[0] = (int)KS_EXTRA;
|
||||
@ -6045,7 +6087,7 @@ check_termcode(
|
||||
void
|
||||
term_get_fg_color(char_u *r, char_u *g, char_u *b)
|
||||
{
|
||||
if (rfg_status == STATUS_GOT)
|
||||
if (rfg_status.tr_progress == STATUS_GOT)
|
||||
{
|
||||
*r = fg_r;
|
||||
*g = fg_g;
|
||||
@ -6059,7 +6101,7 @@ 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)
|
||||
{
|
||||
if (rbg_status == STATUS_GOT)
|
||||
if (rbg_status.tr_progress == STATUS_GOT)
|
||||
{
|
||||
*r = bg_r;
|
||||
*g = bg_g;
|
||||
|
@ -767,6 +767,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1315,
|
||||
/**/
|
||||
1314,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user