]> granicus.if.org Git - vim/commitdiff
patch 8.0.1009: Xterm cursor blinking status may be inverted v8.0.1009
authorBram Moolenaar <Bram@vim.org>
Mon, 28 Aug 2017 20:43:05 +0000 (22:43 +0200)
committerBram Moolenaar <Bram@vim.org>
Mon, 28 Aug 2017 20:43:05 +0000 (22:43 +0200)
Problem:    Xterm cursor blinking status may be inverted.
Solution:   Use another request to get the blink status and compare with the
            cursor style report

src/option.c
src/proto/term.pro
src/term.c
src/term.h
src/terminal.c
src/version.c

index 90a11bce3a897a3aaadd1c9e79445caa20311176..5b50913e18f11eb014ba87bb5ab055ca55d32b2f 100644 (file)
@@ -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)
index 392b067334375ef0141517dae431becdde62e676..65e67402aacb7460c03a3f42362a49ffaac01f0b 100644 (file)
@@ -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);
index b9594d5fc19621652a277945981fdcd12fe6461c..fec50d583a2ca6cebad9797b9706de3365bde99a 100644 (file)
@@ -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; /* detected 8-bit terminal */
 
 #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_termcaps[] =
 #  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)
-    {
-       out_str(T_VS);
-       out_flush();
-    }
-    else if (!blink && *T_CVS != NUL)
+    else
     {
-       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;
index 18c1294afa0add74285825bf4033c858e8e6a4c5..0fedfeaa85d518dcffe07ed159acddcb4d6c4d98 100644 (file)
@@ -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[]);    /* current terminal strings */
 #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 */
index a8c7ae59de13334270ce48bacc8fa0e9eca8793f..288ad28eb6070efd3e809f74af3d3584c74de3ce 100644 (file)
@@ -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, typval_T *rettv)
     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);
index ae7e6ed5addc60329cf3312aea8188ebffccd590..6631bd02323a697f6ee665d3161d228e3b80a83f 100644 (file)
@@ -769,6 +769,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1009,
 /**/
     1008,
 /**/