changeset 12259:48eac9bc2f82 v8.0.1009

patch 8.0.1009: Xterm cursor blinking status may be inverted commit https://github.com/vim/vim/commit/4db2554954056f21f2ba4cf4988c652745d7042a Author: Bram Moolenaar <Bram@vim.org> Date: Mon Aug 28 22:43:05 2017 +0200 patch 8.0.1009: Xterm cursor blinking status may be inverted Problem: Xterm cursor blinking status may be inverted. Solution: Use another request to get the blink status and compare with the cursor style report
author Christian Brabandt <cb@256bit.org>
date Mon, 28 Aug 2017 22:45:04 +0200
parents 8b386ef3a93d
children 02a1228712da
files src/option.c src/proto/term.pro src/term.c src/term.h src/terminal.c src/version.c
diffstat 6 files changed, 98 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/option.c
+++ b/src/option.c
@@ -3194,6 +3194,7 @@ static struct vimoption options[] =
     p_term("t_nd", T_ND)
     p_term("t_op", T_OP)
     p_term("t_RB", T_RBG)
+    p_term("t_RC", T_CRC)
     p_term("t_RI", T_CRI)
     p_term("t_RS", T_CRS)
     p_term("t_RV", T_CRV)
--- a/src/proto/term.pro
+++ b/src/proto/term.pro
@@ -53,6 +53,7 @@ void cursor_on(void);
 void cursor_off(void);
 void term_cursor_mode(int forced);
 void term_cursor_color(char_u *color);
+int blink_state_is_inverted(void);
 void term_cursor_shape(int shape, int blink);
 void scroll_region_set(win_T *wp, int off);
 void scroll_region_reset(void);
--- a/src/term.c
+++ b/src/term.c
@@ -128,8 +128,11 @@ static int u7_status = STATUS_GET;
 /* Request background color report: */
 static int rbg_status = STATUS_GET;
 
-/* Request cursor mode report: */
-static int rcm_status = STATUS_GET;
+/* Request cursor blinking mode report: */
+static int rbm_status = STATUS_GET;
+
+/* Request cursor style report: */
+static int rcs_status = STATUS_GET;
 # endif
 
 /*
@@ -163,9 +166,14 @@ static int  detected_8bit = FALSE;	/* de
 
 #ifdef FEAT_TERMRESPONSE
 /* When the cursor shape was detected these values are used:
- * 1: block, 2: underline, 3: vertical bar
- * initial_cursor_blink is only valid when initial_cursor_shape is not zero. */
+ * 1: block, 2: underline, 3: vertical bar */
 static int initial_cursor_shape = 0;
+
+/* The blink flag from the style response may be inverted from the actual
+ * blinking state, xterm XORs the flags. */
+static int initial_cursor_shape_blink = FALSE;
+
+/* The blink flag from the blinking-cursor mode response */
 static int initial_cursor_blink = FALSE;
 #endif
 
@@ -835,6 +843,7 @@ static struct builtin_term builtin_termc
 #  else
     {(int)KS_CSH,	IF_EB("\033[%d q", ESC_STR "[%d q")},
 #  endif
+    {(int)KS_CRC,	IF_EB("\033[?12$p", ESC_STR "[?12$p")},
     {(int)KS_CRS,	IF_EB("\033P$q q\033\\", ESC_STR "P$q q" ESC_STR "\\")},
 #  ifdef TERMINFO
     {(int)KS_CM,	IF_EB("\033[%i%p1%d;%p2%dH",
@@ -3316,7 +3325,8 @@ settmode(int tmode)
 		if (tmode != TMODE_RAW && (crv_status == STATUS_SENT
 					 || u7_status == STATUS_SENT
 					 || rbg_status == STATUS_SENT
-					 || rcm_status == STATUS_SENT))
+					 || rbm_status == STATUS_SENT
+					 || rcs_status == STATUS_SENT))
 		    (void)vpeekc_nomap();
 		check_for_codes_from_term();
 	    }
@@ -3386,7 +3396,8 @@ stoptermcap(void)
 	    if (crv_status == STATUS_SENT
 		    || u7_status == STATUS_SENT
 		    || rbg_status == STATUS_SENT
-		    || rcm_status == STATUS_SENT)
+		    || rbm_status == STATUS_SENT
+		    || rcs_status == STATUS_SENT)
 	    {
 # ifdef UNIX
 		/* Give the terminal a chance to respond. */
@@ -3500,6 +3511,8 @@ may_req_ambiguous_char_width(void)
     void
 may_req_bg_color(void)
 {
+    int	    did_one = FALSE;
+
     if (can_get_termresponse() && starting == 0)
     {
 	/* Only request background if t_RB is set and 'background' wasn't
@@ -3511,7 +3524,20 @@ may_req_bg_color(void)
 	    LOG_TR("Sending BG request");
 	    out_str(T_RBG);
 	    rbg_status = STATUS_SENT;
-
+	    did_one = TRUE;
+	}
+
+	/* Only request cursor blinking mode if t_RC is set. */
+	if (rbm_status == STATUS_GET && *T_CRC != NUL)
+	{
+	    LOG_TR("Sending BC request");
+	    out_str(T_CRC);
+	    rbm_status = STATUS_SENT;
+	    did_one = TRUE;
+	}
+
+	if (did_one)
+	{
 	    /* check for the characters now, otherwise they might be eaten by
 	     * get_keystroke() */
 	    out_flush();
@@ -3751,6 +3777,13 @@ term_cursor_color(char_u *color)
 }
 # endif
 
+    int
+blink_state_is_inverted()
+{
+    return rbm_status == STATUS_GOT && rcs_status == STATUS_GOT
+		&& initial_cursor_blink != initial_cursor_shape_blink;
+}
+
 /*
  * "shape": 1 = block, 2 = underline, 3 = vertical bar
  */
@@ -3762,16 +3795,26 @@ term_cursor_shape(int shape, int blink)
 	OUT_STR(tgoto((char *)T_CSH, 0, shape * 2 - blink));
 	out_flush();
     }
-    /* When t_SH is not set try setting just the blink state. */
-    else if (blink && *T_VS != NUL)
+    else
     {
-	out_str(T_VS);
-	out_flush();
-    }
-    else if (!blink && *T_CVS != NUL)
-    {
-	out_str(T_CVS);
-	out_flush();
+	int do_blink = blink;
+
+	/* t_SH is empty: try setting just the blink state.
+	 * The blink flags are XORed together, if the initial blinking from
+	 * style and shape differs, we need to invert the flag here. */
+	if (blink_state_is_inverted())
+	    do_blink = !blink;
+
+	if (do_blink && *T_VS != NUL)
+	{
+	    out_str(T_VS);
+	    out_flush();
+	}
+	else if (!do_blink && *T_CVS != NUL)
+	{
+	    out_str(T_CVS);
+	    out_flush();
+	}
     }
 }
 #endif
@@ -4533,7 +4576,7 @@ check_termcode(
 			/* Only request the cursor style if t_SH and t_RS are
 			 * set. Not for Terminal.app, it can't handle t_RS, it
 			 * echoes the characters to the screen. */
-			if (rcm_status == STATUS_GET
+			if (rcs_status == STATUS_GET
 #  ifdef MACOS
 				&& !is_terminal_app
 #  endif
@@ -4542,7 +4585,7 @@ check_termcode(
 			{
 			    LOG_TR("Sending cursor style request");
 			    out_str(T_CRS);
-			    rcm_status = STATUS_SENT;
+			    rcs_status = STATUS_SENT;
 			    out_flush();
 			}
 		    }
@@ -4558,6 +4601,29 @@ check_termcode(
 		    slen = i + 1;
 		}
 
+		/* Check blinking cursor from xterm:
+		 * {lead}?12;1$y       set
+		 * {lead}?12;2$y       not set
+		 *
+		 * {lead} can be <Esc>[ or CSI
+		 */
+		else if (rbm_status == STATUS_SENT
+			&& tp[(j = 1 + (tp[0] == ESC))] == '?'
+			&& i == j + 6
+			&& tp[j + 1] == '1'
+			&& tp[j + 2] == '2'
+			&& tp[j + 3] == ';'
+			&& tp[i - 1] == '$'
+			&& tp[i] == 'y')
+		{
+		    initial_cursor_blink = (tp[j + 4] == '1');
+		    rbm_status = STATUS_GOT;
+		    LOG_TR("Received cursor blinking mode response");
+		    key_name[0] = (int)KS_EXTRA;
+		    key_name[1] = (int)KE_IGNORE;
+		    slen = i + 1;
+		}
+
 		/*
 		 * Check for a window position response from the terminal:
 		 *       {lead}3;{x}:{y}t
@@ -4668,7 +4734,7 @@ check_termcode(
 	     *
 	     * Consume any code that starts with "{lead}.+r" or "{lead}.$r".
 	     */
-	    else if ((check_for_codes || rcm_status == STATUS_SENT)
+	    else if ((check_for_codes || rcs_status == STATUS_SENT)
 		    && ((tp[0] == ESC && len >= 2 && tp[1] == 'P')
 			|| tp[0] == DCS))
 	    {
@@ -4710,8 +4776,9 @@ check_termcode(
 			initial_cursor_shape = (number + 1) / 2;
 			/* The blink flag is actually inverted, compared to
 			 * the value set with T_SH. */
-			initial_cursor_blink = (number & 1) ? FALSE : TRUE;
-			rcm_status = STATUS_GOT;
+			initial_cursor_shape_blink =
+						   (number & 1) ? FALSE : TRUE;
+			rcs_status = STATUS_GOT;
 			LOG_TR("Received cursor shape response");
 
 			key_name[0] = (int)KS_EXTRA;
--- a/src/term.h
+++ b/src/term.h
@@ -42,7 +42,8 @@ enum SpecialKey
     KS_VS,	/* cursor very visible (blink) */
     KS_CVS,	/* cursor normally visible (no blink) */
     KS_CSH,	/* cursor shape */
-    KS_CRS,	/* request cursor shape */
+    KS_CRC,	/* request cursor blinking */
+    KS_CRS,	/* request cursor style */
     KS_ME,	/* normal mode */
     KS_MR,	/* reverse mode */
     KS_MD,	/* bold mode */
@@ -135,7 +136,8 @@ extern char_u *(term_strings[]);    /* c
 #define T_VS	(TERM_STR(KS_VS))	/* cursor very visible (blink) */
 #define T_CVS	(TERM_STR(KS_CVS))	/* cursor normally visible (no blink) */
 #define T_CSH	(TERM_STR(KS_CSH))	/* cursor shape */
-#define T_CRS	(TERM_STR(KS_CRS))	/* request cursor shape */
+#define T_CRC	(TERM_STR(KS_CRC))	/* request cursor blinking */
+#define T_CRS	(TERM_STR(KS_CRS))	/* request cursor style */
 #define T_ME	(TERM_STR(KS_ME))	/* normal mode */
 #define T_MR	(TERM_STR(KS_MR))	/* reverse mode */
 #define T_MD	(TERM_STR(KS_MD))	/* bold mode */
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -39,7 +39,6 @@
  *
  * TODO:
  * - ":term NONE" does not work in MS-Windows.
- * - better check for blinking - reply from Thomas Dickey Aug 22
  * - test for writing lines to terminal job does not work on MS-Windows
  * - implement term_setsize()
  * - add test for giving error for invalid 'termsize' value.
@@ -2482,7 +2481,8 @@ f_term_getcursor(typval_T *argvars, typv
     if (d != NULL)
     {
 	dict_add_nr_str(d, "visible", term->tl_cursor_visible, NULL);
-	dict_add_nr_str(d, "blink", term->tl_cursor_blink, NULL);
+	dict_add_nr_str(d, "blink", blink_state_is_inverted()
+		       ? !term->tl_cursor_blink : term->tl_cursor_blink, NULL);
 	dict_add_nr_str(d, "shape", term->tl_cursor_shape, NULL);
 	dict_add_nr_str(d, "color", 0L, term->tl_cursor_color == NULL
 				       ? (char_u *)"" : term->tl_cursor_color);
--- a/src/version.c
+++ b/src/version.c
@@ -770,6 +770,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1009,
+/**/
     1008,
 /**/
     1007,