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