Mercurial > vim
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); |