@@ -128,8 +128,11 @@ static int u7_status = STATUS_GET;
128128/* Request background color report: */
129129static int rbg_status = STATUS_GET ;
130130
131- /* Request cursor mode report: */
132- static int rcm_status = STATUS_GET ;
131+ /* Request cursor blinking mode report: */
132+ static int rbm_status = STATUS_GET ;
133+
134+ /* Request cursor style report: */
135+ static int rcs_status = STATUS_GET ;
133136# endif
134137
135138/*
@@ -163,9 +166,14 @@ static int detected_8bit = FALSE; /* detected 8-bit terminal */
163166
164167#ifdef FEAT_TERMRESPONSE
165168/* When the cursor shape was detected these values are used:
166- * 1: block, 2: underline, 3: vertical bar
167- * initial_cursor_blink is only valid when initial_cursor_shape is not zero. */
169+ * 1: block, 2: underline, 3: vertical bar */
168170static int initial_cursor_shape = 0 ;
171+
172+ /* The blink flag from the style response may be inverted from the actual
173+ * blinking state, xterm XORs the flags. */
174+ static int initial_cursor_shape_blink = FALSE;
175+
176+ /* The blink flag from the blinking-cursor mode response */
169177static int initial_cursor_blink = FALSE;
170178#endif
171179
@@ -835,6 +843,7 @@ static struct builtin_term builtin_termcaps[] =
835843# else
836844 {(int )KS_CSH , IF_EB ("\033[%d q" , ESC_STR "[%d q" )},
837845# endif
846+ {(int )KS_CRC , IF_EB ("\033[?12$p" , ESC_STR "[?12$p" )},
838847 {(int )KS_CRS , IF_EB ("\033P$q q\033\\" , ESC_STR "P$q q" ESC_STR "\\" )},
839848# ifdef TERMINFO
840849 {(int )KS_CM , IF_EB ("\033[%i%p1%d;%p2%dH" ,
@@ -3316,7 +3325,8 @@ settmode(int tmode)
33163325 if (tmode != TMODE_RAW && (crv_status == STATUS_SENT
33173326 || u7_status == STATUS_SENT
33183327 || rbg_status == STATUS_SENT
3319- || rcm_status == STATUS_SENT ))
3328+ || rbm_status == STATUS_SENT
3329+ || rcs_status == STATUS_SENT ))
33203330 (void )vpeekc_nomap ();
33213331 check_for_codes_from_term ();
33223332 }
@@ -3386,7 +3396,8 @@ stoptermcap(void)
33863396 if (crv_status == STATUS_SENT
33873397 || u7_status == STATUS_SENT
33883398 || rbg_status == STATUS_SENT
3389- || rcm_status == STATUS_SENT )
3399+ || rbm_status == STATUS_SENT
3400+ || rcs_status == STATUS_SENT )
33903401 {
33913402# ifdef UNIX
33923403 /* Give the terminal a chance to respond. */
@@ -3500,6 +3511,8 @@ may_req_ambiguous_char_width(void)
35003511 void
35013512may_req_bg_color (void )
35023513{
3514+ int did_one = FALSE;
3515+
35033516 if (can_get_termresponse () && starting == 0 )
35043517 {
35053518 /* Only request background if t_RB is set and 'background' wasn't
@@ -3511,7 +3524,20 @@ may_req_bg_color(void)
35113524 LOG_TR ("Sending BG request" );
35123525 out_str (T_RBG );
35133526 rbg_status = STATUS_SENT ;
3527+ did_one = TRUE;
3528+ }
35143529
3530+ /* Only request cursor blinking mode if t_RC is set. */
3531+ if (rbm_status == STATUS_GET && * T_CRC != NUL )
3532+ {
3533+ LOG_TR ("Sending BC request" );
3534+ out_str (T_CRC );
3535+ rbm_status = STATUS_SENT ;
3536+ did_one = TRUE;
3537+ }
3538+
3539+ if (did_one )
3540+ {
35153541 /* check for the characters now, otherwise they might be eaten by
35163542 * get_keystroke() */
35173543 out_flush ();
@@ -3751,6 +3777,13 @@ term_cursor_color(char_u *color)
37513777}
37523778# endif
37533779
3780+ int
3781+ blink_state_is_inverted ()
3782+ {
3783+ return rbm_status == STATUS_GOT && rcs_status == STATUS_GOT
3784+ && initial_cursor_blink != initial_cursor_shape_blink ;
3785+ }
3786+
37543787/*
37553788 * "shape": 1 = block, 2 = underline, 3 = vertical bar
37563789 */
@@ -3762,16 +3795,26 @@ term_cursor_shape(int shape, int blink)
37623795 OUT_STR (tgoto ((char * )T_CSH , 0 , shape * 2 - blink ));
37633796 out_flush ();
37643797 }
3765- /* When t_SH is not set try setting just the blink state. */
3766- else if (blink && * T_VS != NUL )
3767- {
3768- out_str (T_VS );
3769- out_flush ();
3770- }
3771- else if (!blink && * T_CVS != NUL )
3798+ else
37723799 {
3773- out_str (T_CVS );
3774- out_flush ();
3800+ int do_blink = blink ;
3801+
3802+ /* t_SH is empty: try setting just the blink state.
3803+ * The blink flags are XORed together, if the initial blinking from
3804+ * style and shape differs, we need to invert the flag here. */
3805+ if (blink_state_is_inverted ())
3806+ do_blink = !blink ;
3807+
3808+ if (do_blink && * T_VS != NUL )
3809+ {
3810+ out_str (T_VS );
3811+ out_flush ();
3812+ }
3813+ else if (!do_blink && * T_CVS != NUL )
3814+ {
3815+ out_str (T_CVS );
3816+ out_flush ();
3817+ }
37753818 }
37763819}
37773820#endif
@@ -4533,7 +4576,7 @@ check_termcode(
45334576 /* Only request the cursor style if t_SH and t_RS are
45344577 * set. Not for Terminal.app, it can't handle t_RS, it
45354578 * echoes the characters to the screen. */
4536- if (rcm_status == STATUS_GET
4579+ if (rcs_status == STATUS_GET
45374580# ifdef MACOS
45384581 && !is_terminal_app
45394582# endif
@@ -4542,7 +4585,7 @@ check_termcode(
45424585 {
45434586 LOG_TR ("Sending cursor style request" );
45444587 out_str (T_CRS );
4545- rcm_status = STATUS_SENT ;
4588+ rcs_status = STATUS_SENT ;
45464589 out_flush ();
45474590 }
45484591 }
@@ -4558,6 +4601,29 @@ check_termcode(
45584601 slen = i + 1 ;
45594602 }
45604603
4604+ /* Check blinking cursor from xterm:
4605+ * {lead}?12;1$y set
4606+ * {lead}?12;2$y not set
4607+ *
4608+ * {lead} can be <Esc>[ or CSI
4609+ */
4610+ else if (rbm_status == STATUS_SENT
4611+ && tp [(j = 1 + (tp [0 ] == ESC ))] == '?'
4612+ && i == j + 6
4613+ && tp [j + 1 ] == '1'
4614+ && tp [j + 2 ] == '2'
4615+ && tp [j + 3 ] == ';'
4616+ && tp [i - 1 ] == '$'
4617+ && tp [i ] == 'y' )
4618+ {
4619+ initial_cursor_blink = (tp [j + 4 ] == '1' );
4620+ rbm_status = STATUS_GOT ;
4621+ LOG_TR ("Received cursor blinking mode response" );
4622+ key_name [0 ] = (int )KS_EXTRA ;
4623+ key_name [1 ] = (int )KE_IGNORE ;
4624+ slen = i + 1 ;
4625+ }
4626+
45614627 /*
45624628 * Check for a window position response from the terminal:
45634629 * {lead}3;{x}:{y}t
@@ -4668,7 +4734,7 @@ check_termcode(
46684734 *
46694735 * Consume any code that starts with "{lead}.+r" or "{lead}.$r".
46704736 */
4671- else if ((check_for_codes || rcm_status == STATUS_SENT )
4737+ else if ((check_for_codes || rcs_status == STATUS_SENT )
46724738 && ((tp [0 ] == ESC && len >= 2 && tp [1 ] == 'P' )
46734739 || tp [0 ] == DCS ))
46744740 {
@@ -4710,8 +4776,9 @@ check_termcode(
47104776 initial_cursor_shape = (number + 1 ) / 2 ;
47114777 /* The blink flag is actually inverted, compared to
47124778 * the value set with T_SH. */
4713- initial_cursor_blink = (number & 1 ) ? FALSE : TRUE;
4714- rcm_status = STATUS_GOT ;
4779+ initial_cursor_shape_blink =
4780+ (number & 1 ) ? FALSE : TRUE;
4781+ rcs_status = STATUS_GOT ;
47154782 LOG_TR ("Received cursor shape response" );
47164783
47174784 key_name [0 ] = (int )KS_EXTRA ;
0 commit comments