@@ -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" ,
@@ -3322,7 +3331,8 @@ settmode(int tmode)
33223331 if (tmode != TMODE_RAW && (crv_status == STATUS_SENT
33233332 || u7_status == STATUS_SENT
33243333 || rbg_status == STATUS_SENT
3325- || rcm_status == STATUS_SENT ))
3334+ || rbm_status == STATUS_SENT
3335+ || rcs_status == STATUS_SENT ))
33263336 (void )vpeekc_nomap ();
33273337 check_for_codes_from_term ();
33283338 }
@@ -3392,7 +3402,8 @@ stoptermcap(void)
33923402 if (crv_status == STATUS_SENT
33933403 || u7_status == STATUS_SENT
33943404 || rbg_status == STATUS_SENT
3395- || rcm_status == STATUS_SENT )
3405+ || rbm_status == STATUS_SENT
3406+ || rcs_status == STATUS_SENT )
33963407 {
33973408# ifdef UNIX
33983409 /* Give the terminal a chance to respond. */
@@ -3506,6 +3517,8 @@ may_req_ambiguous_char_width(void)
35063517 void
35073518may_req_bg_color (void )
35083519{
3520+ int did_one = FALSE;
3521+
35093522 if (can_get_termresponse () && starting == 0 )
35103523 {
35113524 /* Only request background if t_RB is set and 'background' wasn't
@@ -3517,7 +3530,20 @@ may_req_bg_color(void)
35173530 LOG_TR ("Sending BG request" );
35183531 out_str (T_RBG );
35193532 rbg_status = STATUS_SENT ;
3533+ did_one = TRUE;
3534+ }
35203535
3536+ /* Only request cursor blinking mode if t_RC is set. */
3537+ if (rbm_status == STATUS_GET && * T_CRC != NUL )
3538+ {
3539+ LOG_TR ("Sending BC request" );
3540+ out_str (T_CRC );
3541+ rbm_status = STATUS_SENT ;
3542+ did_one = TRUE;
3543+ }
3544+
3545+ if (did_one )
3546+ {
35213547 /* check for the characters now, otherwise they might be eaten by
35223548 * get_keystroke() */
35233549 out_flush ();
@@ -3757,6 +3783,17 @@ term_cursor_color(char_u *color)
37573783}
37583784# endif
37593785
3786+ int
3787+ blink_state_is_inverted ()
3788+ {
3789+ #ifdef FEAT_TERMRESPONSE
3790+ return rbm_status == STATUS_GOT && rcs_status == STATUS_GOT
3791+ && initial_cursor_blink != initial_cursor_shape_blink ;
3792+ #else
3793+ return FALSE;
3794+ #endif
3795+ }
3796+
37603797/*
37613798 * "shape": 1 = block, 2 = underline, 3 = vertical bar
37623799 */
@@ -3768,16 +3805,26 @@ term_cursor_shape(int shape, int blink)
37683805 OUT_STR (tgoto ((char * )T_CSH , 0 , shape * 2 - blink ));
37693806 out_flush ();
37703807 }
3771- /* When t_SH is not set try setting just the blink state. */
3772- else if (blink && * T_VS != NUL )
3773- {
3774- out_str (T_VS );
3775- out_flush ();
3776- }
3777- else if (!blink && * T_CVS != NUL )
3808+ else
37783809 {
3779- out_str (T_CVS );
3780- out_flush ();
3810+ int do_blink = blink ;
3811+
3812+ /* t_SH is empty: try setting just the blink state.
3813+ * The blink flags are XORed together, if the initial blinking from
3814+ * style and shape differs, we need to invert the flag here. */
3815+ if (blink_state_is_inverted ())
3816+ do_blink = !blink ;
3817+
3818+ if (do_blink && * T_VS != NUL )
3819+ {
3820+ out_str (T_VS );
3821+ out_flush ();
3822+ }
3823+ else if (!do_blink && * T_CVS != NUL )
3824+ {
3825+ out_str (T_CVS );
3826+ out_flush ();
3827+ }
37813828 }
37823829}
37833830#endif
@@ -4539,7 +4586,7 @@ check_termcode(
45394586 /* Only request the cursor style if t_SH and t_RS are
45404587 * set. Not for Terminal.app, it can't handle t_RS, it
45414588 * echoes the characters to the screen. */
4542- if (rcm_status == STATUS_GET
4589+ if (rcs_status == STATUS_GET
45434590# ifdef MACOS
45444591 && !is_terminal_app
45454592# endif
@@ -4548,7 +4595,7 @@ check_termcode(
45484595 {
45494596 LOG_TR ("Sending cursor style request" );
45504597 out_str (T_CRS );
4551- rcm_status = STATUS_SENT ;
4598+ rcs_status = STATUS_SENT ;
45524599 out_flush ();
45534600 }
45544601 }
@@ -4564,6 +4611,29 @@ check_termcode(
45644611 slen = i + 1 ;
45654612 }
45664613
4614+ /* Check blinking cursor from xterm:
4615+ * {lead}?12;1$y set
4616+ * {lead}?12;2$y not set
4617+ *
4618+ * {lead} can be <Esc>[ or CSI
4619+ */
4620+ else if (rbm_status == STATUS_SENT
4621+ && tp [(j = 1 + (tp [0 ] == ESC ))] == '?'
4622+ && i == j + 6
4623+ && tp [j + 1 ] == '1'
4624+ && tp [j + 2 ] == '2'
4625+ && tp [j + 3 ] == ';'
4626+ && tp [i - 1 ] == '$'
4627+ && tp [i ] == 'y' )
4628+ {
4629+ initial_cursor_blink = (tp [j + 4 ] == '1' );
4630+ rbm_status = STATUS_GOT ;
4631+ LOG_TR ("Received cursor blinking mode response" );
4632+ key_name [0 ] = (int )KS_EXTRA ;
4633+ key_name [1 ] = (int )KE_IGNORE ;
4634+ slen = i + 1 ;
4635+ }
4636+
45674637 /*
45684638 * Check for a window position response from the terminal:
45694639 * {lead}3;{x}:{y}t
@@ -4674,7 +4744,7 @@ check_termcode(
46744744 *
46754745 * Consume any code that starts with "{lead}.+r" or "{lead}.$r".
46764746 */
4677- else if ((check_for_codes || rcm_status == STATUS_SENT )
4747+ else if ((check_for_codes || rcs_status == STATUS_SENT )
46784748 && ((tp [0 ] == ESC && len >= 2 && tp [1 ] == 'P' )
46794749 || tp [0 ] == DCS ))
46804750 {
@@ -4716,8 +4786,9 @@ check_termcode(
47164786 initial_cursor_shape = (number + 1 ) / 2 ;
47174787 /* The blink flag is actually inverted, compared to
47184788 * the value set with T_SH. */
4719- initial_cursor_blink = (number & 1 ) ? FALSE : TRUE;
4720- rcm_status = STATUS_GOT ;
4789+ initial_cursor_shape_blink =
4790+ (number & 1 ) ? FALSE : TRUE;
4791+ rcs_status = STATUS_GOT ;
47214792 LOG_TR ("Received cursor shape response" );
47224793
47234794 key_name [0 ] = (int )KS_EXTRA ;
0 commit comments