changeset 16625:d4e74f9f7ae9 v8.1.1315

patch 8.1.1315: there is always a delay if a termrequest is never answered commit https://github.com/vim/vim/commit/afd78266c5096574ec057c36fb4a0e56912e9a71 Author: Bram Moolenaar <Bram@vim.org> Date: Fri May 10 23:10:31 2019 +0200 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.
author Bram Moolenaar <Bram@vim.org>
date Fri, 10 May 2019 23:15:05 +0200
parents 5c53e2a20f0d
children 44290e98c950
files src/term.c src/version.c
diffstat 2 files changed, 136 insertions(+), 92 deletions(-) [+]
line wrap: on
line diff
--- a/src/term.c
+++ b/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 */
-
-/* Request Terminal Version status: */
-static int crv_status = STATUS_GET;
-
-/* Request Cursor position report: */
-static int u7_status = STATUS_GET;
+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;
+
+typedef struct {
+    request_progress_T	    tr_progress;
+    time_t		    tr_start;	// when request was sent, -1 for never
+} termrequest_T;
+
+#  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, varnumbe
     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];
-
-	 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();
-
-	 /* 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();
-
-	 /* check for the characters now, otherwise they might be eaten by
-	  * get_keystroke() */
-	 out_flush();
-	 (void)vpeekc_nomap();
+	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);
+	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);
+
+	/* 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();
     }
 }
 
@@ -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, 
     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;
--- a/src/version.c
+++ b/src/version.c
@@ -768,6 +768,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1315,
+/**/
     1314,
 /**/
     1313,