comparison src/term.c @ 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 2b333727279d
children 875d7cc9b127
comparison
equal deleted inserted replaced
12258:8b386ef3a93d 12259:48eac9bc2f82
126 static int u7_status = STATUS_GET; 126 static int u7_status = STATUS_GET;
127 127
128 /* Request background color report: */ 128 /* Request background color report: */
129 static int rbg_status = STATUS_GET; 129 static int rbg_status = STATUS_GET;
130 130
131 /* Request cursor mode report: */ 131 /* Request cursor blinking mode report: */
132 static int rcm_status = STATUS_GET; 132 static int rbm_status = STATUS_GET;
133
134 /* Request cursor style report: */
135 static int rcs_status = STATUS_GET;
133 # endif 136 # endif
134 137
135 /* 138 /*
136 * Don't declare these variables if termcap.h contains them. 139 * Don't declare these variables if termcap.h contains them.
137 * Autoconf checks if these variables should be declared extern (not all 140 * Autoconf checks if these variables should be declared extern (not all
161 164
162 static int detected_8bit = FALSE; /* detected 8-bit terminal */ 165 static int detected_8bit = FALSE; /* detected 8-bit terminal */
163 166
164 #ifdef FEAT_TERMRESPONSE 167 #ifdef FEAT_TERMRESPONSE
165 /* When the cursor shape was detected these values are used: 168 /* When the cursor shape was detected these values are used:
166 * 1: block, 2: underline, 3: vertical bar 169 * 1: block, 2: underline, 3: vertical bar */
167 * initial_cursor_blink is only valid when initial_cursor_shape is not zero. */
168 static int initial_cursor_shape = 0; 170 static 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 */
169 static int initial_cursor_blink = FALSE; 177 static int initial_cursor_blink = FALSE;
170 #endif 178 #endif
171 179
172 static struct builtin_term builtin_termcaps[] = 180 static struct builtin_term builtin_termcaps[] =
173 { 181 {
833 # ifdef TERMINFO 841 # ifdef TERMINFO
834 {(int)KS_CSH, IF_EB("\033[%p1%d q", ESC_STR "[%p1%d q")}, 842 {(int)KS_CSH, IF_EB("\033[%p1%d q", ESC_STR "[%p1%d q")},
835 # else 843 # else
836 {(int)KS_CSH, IF_EB("\033[%d q", ESC_STR "[%d q")}, 844 {(int)KS_CSH, IF_EB("\033[%d q", ESC_STR "[%d q")},
837 # endif 845 # endif
846 {(int)KS_CRC, IF_EB("\033[?12$p", ESC_STR "[?12$p")},
838 {(int)KS_CRS, IF_EB("\033P$q q\033\\", ESC_STR "P$q q" ESC_STR "\\")}, 847 {(int)KS_CRS, IF_EB("\033P$q q\033\\", ESC_STR "P$q q" ESC_STR "\\")},
839 # ifdef TERMINFO 848 # ifdef TERMINFO
840 {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH", 849 {(int)KS_CM, IF_EB("\033[%i%p1%d;%p2%dH",
841 ESC_STR "[%i%p1%d;%p2%dH")}, 850 ESC_STR "[%i%p1%d;%p2%dH")},
842 # else 851 # else
3314 * doesn't work in Cooked mode, an external program may get 3323 * doesn't work in Cooked mode, an external program may get
3315 * them. */ 3324 * them. */
3316 if (tmode != TMODE_RAW && (crv_status == STATUS_SENT 3325 if (tmode != TMODE_RAW && (crv_status == STATUS_SENT
3317 || u7_status == STATUS_SENT 3326 || u7_status == STATUS_SENT
3318 || rbg_status == STATUS_SENT 3327 || rbg_status == STATUS_SENT
3319 || rcm_status == STATUS_SENT)) 3328 || rbm_status == STATUS_SENT
3329 || rcs_status == STATUS_SENT))
3320 (void)vpeekc_nomap(); 3330 (void)vpeekc_nomap();
3321 check_for_codes_from_term(); 3331 check_for_codes_from_term();
3322 } 3332 }
3323 #endif 3333 #endif
3324 #ifdef FEAT_MOUSE_TTY 3334 #ifdef FEAT_MOUSE_TTY
3384 { 3394 {
3385 /* May need to discard T_CRV, T_U7 or T_RBG response. */ 3395 /* May need to discard T_CRV, T_U7 or T_RBG response. */
3386 if (crv_status == STATUS_SENT 3396 if (crv_status == STATUS_SENT
3387 || u7_status == STATUS_SENT 3397 || u7_status == STATUS_SENT
3388 || rbg_status == STATUS_SENT 3398 || rbg_status == STATUS_SENT
3389 || rcm_status == STATUS_SENT) 3399 || rbm_status == STATUS_SENT
3400 || rcs_status == STATUS_SENT)
3390 { 3401 {
3391 # ifdef UNIX 3402 # ifdef UNIX
3392 /* Give the terminal a chance to respond. */ 3403 /* Give the terminal a chance to respond. */
3393 mch_delay(100L, FALSE); 3404 mch_delay(100L, FALSE);
3394 # endif 3405 # endif
3498 * Also request the cursor shape, if possible. 3509 * Also request the cursor shape, if possible.
3499 */ 3510 */
3500 void 3511 void
3501 may_req_bg_color(void) 3512 may_req_bg_color(void)
3502 { 3513 {
3514 int did_one = FALSE;
3515
3503 if (can_get_termresponse() && starting == 0) 3516 if (can_get_termresponse() && starting == 0)
3504 { 3517 {
3505 /* Only request background if t_RB is set and 'background' wasn't 3518 /* Only request background if t_RB is set and 'background' wasn't
3506 * changed. */ 3519 * changed. */
3507 if (rbg_status == STATUS_GET 3520 if (rbg_status == STATUS_GET
3509 && !option_was_set((char_u *)"bg")) 3522 && !option_was_set((char_u *)"bg"))
3510 { 3523 {
3511 LOG_TR("Sending BG request"); 3524 LOG_TR("Sending BG request");
3512 out_str(T_RBG); 3525 out_str(T_RBG);
3513 rbg_status = STATUS_SENT; 3526 rbg_status = STATUS_SENT;
3514 3527 did_one = TRUE;
3528 }
3529
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 {
3515 /* check for the characters now, otherwise they might be eaten by 3541 /* check for the characters now, otherwise they might be eaten by
3516 * get_keystroke() */ 3542 * get_keystroke() */
3517 out_flush(); 3543 out_flush();
3518 (void)vpeekc_nomap(); 3544 (void)vpeekc_nomap();
3519 } 3545 }
3749 out_flush(); 3775 out_flush();
3750 } 3776 }
3751 } 3777 }
3752 # endif 3778 # endif
3753 3779
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
3754 /* 3787 /*
3755 * "shape": 1 = block, 2 = underline, 3 = vertical bar 3788 * "shape": 1 = block, 2 = underline, 3 = vertical bar
3756 */ 3789 */
3757 void 3790 void
3758 term_cursor_shape(int shape, int blink) 3791 term_cursor_shape(int shape, int blink)
3760 if (*T_CSH != NUL) 3793 if (*T_CSH != NUL)
3761 { 3794 {
3762 OUT_STR(tgoto((char *)T_CSH, 0, shape * 2 - blink)); 3795 OUT_STR(tgoto((char *)T_CSH, 0, shape * 2 - blink));
3763 out_flush(); 3796 out_flush();
3764 } 3797 }
3765 /* When t_SH is not set try setting just the blink state. */ 3798 else
3766 else if (blink && *T_VS != NUL) 3799 {
3767 { 3800 int do_blink = blink;
3768 out_str(T_VS); 3801
3769 out_flush(); 3802 /* t_SH is empty: try setting just the blink state.
3770 } 3803 * The blink flags are XORed together, if the initial blinking from
3771 else if (!blink && *T_CVS != NUL) 3804 * style and shape differs, we need to invert the flag here. */
3772 { 3805 if (blink_state_is_inverted())
3773 out_str(T_CVS); 3806 do_blink = !blink;
3774 out_flush(); 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 }
3775 } 3818 }
3776 } 3819 }
3777 #endif 3820 #endif
3778 3821
3779 /* 3822 /*
4531 # endif 4574 # endif
4532 4575
4533 /* Only request the cursor style if t_SH and t_RS are 4576 /* Only request the cursor style if t_SH and t_RS are
4534 * set. Not for Terminal.app, it can't handle t_RS, it 4577 * set. Not for Terminal.app, it can't handle t_RS, it
4535 * echoes the characters to the screen. */ 4578 * echoes the characters to the screen. */
4536 if (rcm_status == STATUS_GET 4579 if (rcs_status == STATUS_GET
4537 # ifdef MACOS 4580 # ifdef MACOS
4538 && !is_terminal_app 4581 && !is_terminal_app
4539 # endif 4582 # endif
4540 && *T_CSH != NUL 4583 && *T_CSH != NUL
4541 && *T_CRS != NUL) 4584 && *T_CRS != NUL)
4542 { 4585 {
4543 LOG_TR("Sending cursor style request"); 4586 LOG_TR("Sending cursor style request");
4544 out_str(T_CRS); 4587 out_str(T_CRS);
4545 rcm_status = STATUS_SENT; 4588 rcs_status = STATUS_SENT;
4546 out_flush(); 4589 out_flush();
4547 } 4590 }
4548 } 4591 }
4549 # ifdef FEAT_EVAL 4592 # ifdef FEAT_EVAL
4550 set_vim_var_string(VV_TERMRESPONSE, tp, i + 1); 4593 set_vim_var_string(VV_TERMRESPONSE, tp, i + 1);
4551 # endif 4594 # endif
4552 # ifdef FEAT_AUTOCMD 4595 # ifdef FEAT_AUTOCMD
4553 apply_autocmds(EVENT_TERMRESPONSE, 4596 apply_autocmds(EVENT_TERMRESPONSE,
4554 NULL, NULL, FALSE, curbuf); 4597 NULL, NULL, FALSE, curbuf);
4555 # endif 4598 # endif
4599 key_name[0] = (int)KS_EXTRA;
4600 key_name[1] = (int)KE_IGNORE;
4601 slen = i + 1;
4602 }
4603
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");
4556 key_name[0] = (int)KS_EXTRA; 4622 key_name[0] = (int)KS_EXTRA;
4557 key_name[1] = (int)KE_IGNORE; 4623 key_name[1] = (int)KE_IGNORE;
4558 slen = i + 1; 4624 slen = i + 1;
4559 } 4625 }
4560 4626
4666 * {lead} can be <Esc>P or DCS 4732 * {lead} can be <Esc>P or DCS
4667 * {tail} can be Esc>\ or STERM 4733 * {tail} can be Esc>\ or STERM
4668 * 4734 *
4669 * Consume any code that starts with "{lead}.+r" or "{lead}.$r". 4735 * Consume any code that starts with "{lead}.+r" or "{lead}.$r".
4670 */ 4736 */
4671 else if ((check_for_codes || rcm_status == STATUS_SENT) 4737 else if ((check_for_codes || rcs_status == STATUS_SENT)
4672 && ((tp[0] == ESC && len >= 2 && tp[1] == 'P') 4738 && ((tp[0] == ESC && len >= 2 && tp[1] == 'P')
4673 || tp[0] == DCS)) 4739 || tp[0] == DCS))
4674 { 4740 {
4675 j = 1 + (tp[0] == ESC); 4741 j = 1 + (tp[0] == ESC);
4676 if (len < j + 3) 4742 if (len < j + 3)
4708 * 5 = vertical bar blink, 6 = vertical bar */ 4774 * 5 = vertical bar blink, 6 = vertical bar */
4709 number = number == 0 ? 1 : number; 4775 number = number == 0 ? 1 : number;
4710 initial_cursor_shape = (number + 1) / 2; 4776 initial_cursor_shape = (number + 1) / 2;
4711 /* The blink flag is actually inverted, compared to 4777 /* The blink flag is actually inverted, compared to
4712 * the value set with T_SH. */ 4778 * the value set with T_SH. */
4713 initial_cursor_blink = (number & 1) ? FALSE : TRUE; 4779 initial_cursor_shape_blink =
4714 rcm_status = STATUS_GOT; 4780 (number & 1) ? FALSE : TRUE;
4781 rcs_status = STATUS_GOT;
4715 LOG_TR("Received cursor shape response"); 4782 LOG_TR("Received cursor shape response");
4716 4783
4717 key_name[0] = (int)KS_EXTRA; 4784 key_name[0] = (int)KS_EXTRA;
4718 key_name[1] = (int)KE_IGNORE; 4785 key_name[1] = (int)KE_IGNORE;
4719 slen = i + 1 + (tp[i] == ESC); 4786 slen = i + 1 + (tp[i] == ESC);