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:
Bram Moolenaar
2019-05-10 23:10:31 +02:00
parent c049b52b90
commit afd78266c5
2 changed files with 130 additions and 86 deletions

View File

@ -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;

View File

@ -767,6 +767,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1315,
/**/
1314,
/**/