comparison src/term.c @ 13398:aef75fbfc07d v8.0.1573

patch 8.0.1573: getwinpos(1) may cause response to be handled as command commit https://github.com/vim/vim/commit/89894aa671ed1db03d95d38cab300702c242239d Author: Bram Moolenaar <Bram@vim.org> Date: Mon Mar 5 22:43:10 2018 +0100 patch 8.0.1573: getwinpos(1) may cause response to be handled as command Problem: getwinpos(1) may cause response to be handled as command. Solution: Handle any cursor position report once one was request. (partly by Hirohito Higashi)
author Christian Brabandt <cb@256bit.org>
date Mon, 05 Mar 2018 22:45:06 +0100
parents 6740c499de13
children 4e30f3f4cb78
comparison
equal deleted inserted replaced
13397:2110b429f0a2 13398:aef75fbfc07d
141 /* Request cursor blinking mode report: */ 141 /* Request cursor blinking mode report: */
142 static int rbm_status = STATUS_GET; 142 static int rbm_status = STATUS_GET;
143 143
144 /* Request cursor style report: */ 144 /* Request cursor style report: */
145 static int rcs_status = STATUS_GET; 145 static int rcs_status = STATUS_GET;
146
147 /* Request windos position report: */
148 static int winpos_status = STATUS_GET;
146 # endif 149 # endif
147 150
148 /* 151 /*
149 * Don't declare these variables if termcap.h contains them. 152 * Don't declare these variables if termcap.h contains them.
150 * Autoconf checks if these variables should be declared extern (not all 153 * Autoconf checks if these variables should be declared extern (not all
2776 && (is_not_a_term() || (isatty(1) && isatty(read_cmd_fd))) 2779 && (is_not_a_term() || (isatty(1) && isatty(read_cmd_fd)))
2777 # endif 2780 # endif
2778 && p_ek; 2781 && p_ek;
2779 } 2782 }
2780 2783
2781 static int winpos_x; 2784 static int winpos_x = -1;
2782 static int winpos_y; 2785 static int winpos_y = -1;
2783 static int waiting_for_winpos = FALSE; 2786 static int did_request_winpos = 0;
2784 2787
2785 /* 2788 /*
2786 * Try getting the Vim window position from the terminal. 2789 * Try getting the Vim window position from the terminal.
2787 * Returns OK or FAIL. 2790 * Returns OK or FAIL.
2788 */ 2791 */
2789 int 2792 int
2790 term_get_winpos(int *x, int *y, varnumber_T timeout) 2793 term_get_winpos(int *x, int *y, varnumber_T timeout)
2791 { 2794 {
2792 int count = 0; 2795 int count = 0;
2796 int prev_winpos_x = winpos_x;
2797 int prev_winpos_y = winpos_y;
2793 2798
2794 if (*T_CGP == NUL || !can_get_termresponse()) 2799 if (*T_CGP == NUL || !can_get_termresponse())
2795 return FAIL; 2800 return FAIL;
2796 winpos_x = -1; 2801 winpos_x = -1;
2797 winpos_y = -1; 2802 winpos_y = -1;
2798 waiting_for_winpos = TRUE; 2803 ++did_request_winpos;
2804 winpos_status = STATUS_SENT;
2799 OUT_STR(T_CGP); 2805 OUT_STR(T_CGP);
2800 out_flush(); 2806 out_flush();
2801 2807
2802 /* Try reading the result for "timeout" msec. */ 2808 /* Try reading the result for "timeout" msec. */
2803 while (count++ < timeout / 10) 2809 while (count++ <= timeout / 10 && !got_int)
2804 { 2810 {
2805 (void)vpeekc_nomap(); 2811 (void)vpeekc_nomap();
2806 if (winpos_x >= 0 && winpos_y >= 0) 2812 if (winpos_x >= 0 && winpos_y >= 0)
2807 { 2813 {
2808 *x = winpos_x; 2814 *x = winpos_x;
2809 *y = winpos_y; 2815 *y = winpos_y;
2810 waiting_for_winpos = FALSE;
2811 return OK; 2816 return OK;
2812 } 2817 }
2813 ui_delay(10, FALSE); 2818 ui_delay(10, FALSE);
2814 } 2819 }
2815 waiting_for_winpos = FALSE; 2820 /* Do not reset "did_request_winpos", if we timed out the response might
2821 * still come later and we must consume it. */
2822
2823 winpos_x = prev_winpos_x;
2824 winpos_y = prev_winpos_y;
2825 if (timeout < 10 && prev_winpos_y >= 0 && prev_winpos_y >= 0)
2826 {
2827 /* Polling: return previous values if we have them. */
2828 *x = winpos_x;
2829 *y = winpos_y;
2830 return OK;
2831 }
2832
2816 return FALSE; 2833 return FALSE;
2817 } 2834 }
2818 # endif 2835 # endif
2819 2836
2820 void 2837 void
3363 #ifdef FEAT_TERMINAL 3380 #ifdef FEAT_TERMINAL
3364 || rfg_status == STATUS_SENT 3381 || rfg_status == STATUS_SENT
3365 #endif 3382 #endif
3366 || rbg_status == STATUS_SENT 3383 || rbg_status == STATUS_SENT
3367 || rbm_status == STATUS_SENT 3384 || rbm_status == STATUS_SENT
3368 || rcs_status == STATUS_SENT)) 3385 || rcs_status == STATUS_SENT
3386 || winpos_status == STATUS_SENT))
3369 (void)vpeekc_nomap(); 3387 (void)vpeekc_nomap();
3370 check_for_codes_from_term(); 3388 check_for_codes_from_term();
3371 } 3389 }
3372 #endif 3390 #endif
3373 #ifdef FEAT_MOUSE_TTY 3391 #ifdef FEAT_MOUSE_TTY
3437 # ifdef FEAT_TERMINAL 3455 # ifdef FEAT_TERMINAL
3438 || rfg_status == STATUS_SENT 3456 || rfg_status == STATUS_SENT
3439 # endif 3457 # endif
3440 || rbg_status == STATUS_SENT 3458 || rbg_status == STATUS_SENT
3441 || rbm_status == STATUS_SENT 3459 || rbm_status == STATUS_SENT
3442 || rcs_status == STATUS_SENT) 3460 || rcs_status == STATUS_SENT
3461 || winpos_status == STATUS_SENT)
3443 { 3462 {
3444 # ifdef UNIX 3463 # ifdef UNIX
3445 /* Give the terminal a chance to respond. */ 3464 /* Give the terminal a chance to respond. */
3446 mch_delay(100L, FALSE); 3465 mch_delay(100L, FALSE);
3447 # endif 3466 # endif
4466 * 4485 *
4467 * - window position reply: <Esc>[3;{x};{y}t 4486 * - window position reply: <Esc>[3;{x};{y}t
4468 */ 4487 */
4469 char_u *argp = tp[0] == ESC ? tp + 2 : tp + 1; 4488 char_u *argp = tp[0] == ESC ? tp + 2 : tp + 1;
4470 4489
4471 if ((*T_CRV != NUL || *T_U7 != NUL || waiting_for_winpos) 4490 if ((*T_CRV != NUL || *T_U7 != NUL || did_request_winpos)
4472 && ((tp[0] == ESC && len >= 3 && tp[1] == '[') 4491 && ((tp[0] == ESC && len >= 3 && tp[1] == '[')
4473 || (tp[0] == CSI && len >= 2)) 4492 || (tp[0] == CSI && len >= 2))
4474 && (VIM_ISDIGIT(*argp) || *argp == '>' || *argp == '?')) 4493 && (VIM_ISDIGIT(*argp) || *argp == '>' || *argp == '?'))
4475 { 4494 {
4476 int col = 0; 4495 int col = 0;
4728 4747
4729 /* 4748 /*
4730 * Check for a window position response from the terminal: 4749 * Check for a window position response from the terminal:
4731 * {lead}3;{x}:{y}t 4750 * {lead}3;{x}:{y}t
4732 */ 4751 */
4733 else if (waiting_for_winpos 4752 else if (did_request_winpos
4734 && ((len >= 4 && tp[0] == ESC && tp[1] == '[') 4753 && ((len >= 4 && tp[0] == ESC && tp[1] == '[')
4735 || (len >= 3 && tp[0] == CSI)) 4754 || (len >= 3 && tp[0] == CSI))
4736 && tp[(j = 1 + (tp[0] == ESC))] == '3' 4755 && tp[(j = 1 + (tp[0] == ESC))] == '3'
4737 && tp[j + 1] == ';') 4756 && tp[j + 1] == ';')
4738 { 4757 {
4750 winpos_y = atoi((char *)tp + j); 4769 winpos_y = atoi((char *)tp + j);
4751 /* got finished code: consume it */ 4770 /* got finished code: consume it */
4752 key_name[0] = (int)KS_EXTRA; 4771 key_name[0] = (int)KS_EXTRA;
4753 key_name[1] = (int)KE_IGNORE; 4772 key_name[1] = (int)KE_IGNORE;
4754 slen = i + 1; 4773 slen = i + 1;
4774
4775 if (--did_request_winpos <= 0)
4776 winpos_status = STATUS_GOT;
4755 } 4777 }
4756 } 4778 }
4757 if (i == len) 4779 if (i == len)
4758 { 4780 {
4759 LOG_TR("not enough characters for winpos"); 4781 LOG_TR("not enough characters for winpos");