summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-04-20 20:18:23 +0200
committerBram Moolenaar <Bram@vim.org>2016-04-20 20:18:23 +0200
commit40b1b5443c88fab77f1f7c6f9e801f7ffdb7e0a8 (patch)
tree59056726cfbcd9afe1b71eab0db0f30ac61856f4
parent245c41070c7f37d52be43cce0cb140bd3ade6c7e (diff)
downloadvim-git-40b1b5443c88fab77f1f7c6f9e801f7ffdb7e0a8.tar.gz
patch 7.4.1759v7.4.1759
Problem: When using feedkeys() in a timer the inserted characters are not used right away. Solution: Break the wait loop when characters have been added to typebuf. use this for testing CursorHoldI.
-rw-r--r--src/gui.c6
-rw-r--r--src/os_unix.c17
-rw-r--r--src/os_win32.c6
-rw-r--r--src/testdir/test_autocmd.vim27
-rw-r--r--src/version.c2
5 files changed, 53 insertions, 5 deletions
diff --git a/src/gui.c b/src/gui.c
index 8999f793f..d747d8117 100644
--- a/src/gui.c
+++ b/src/gui.c
@@ -2855,6 +2855,7 @@ gui_wait_for_chars_or_timer(long wtime)
#ifdef FEAT_TIMERS
int due_time;
long remaining = wtime;
+ int tb_change_cnt = typebuf.tb_change_cnt;
/* When waiting very briefly don't trigger timers. */
if (wtime >= 0 && wtime < 10L)
@@ -2865,6 +2866,11 @@ gui_wait_for_chars_or_timer(long wtime)
/* Trigger timers and then get the time in wtime until the next one is
* due. Wait up to that time. */
due_time = check_due_timer();
+ if (typebuf.tb_change_cnt != tb_change_cnt)
+ {
+ /* timer may have used feedkeys() */
+ return FALSE;
+ }
if (due_time <= 0 || (wtime > 0 && due_time > remaining))
due_time = remaining;
if (gui_mch_wait_for_chars(due_time))
diff --git a/src/os_unix.c b/src/os_unix.c
index 58a27da05..f8cf691d1 100644
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -397,7 +397,7 @@ mch_inchar(
if (wtime >= 0)
{
- while (WaitForChar(wtime) == 0) /* no character available */
+ while (!WaitForChar(wtime)) /* no character available */
{
if (do_resize)
handle_resize();
@@ -420,7 +420,7 @@ mch_inchar(
* flush all the swap files to disk.
* Also done when interrupted by SIGWINCH.
*/
- if (WaitForChar(p_ut) == 0)
+ if (!WaitForChar(p_ut))
{
#ifdef FEAT_AUTOCMD
if (trigger_cursorhold() && maxlen >= 3
@@ -448,7 +448,7 @@ mch_inchar(
* We want to be interrupted by the winch signal
* or by an event on the monitored file descriptors.
*/
- if (WaitForChar(-1L) == 0)
+ if (!WaitForChar(-1L))
{
if (do_resize) /* interrupted by SIGWINCH signal */
handle_resize();
@@ -482,7 +482,7 @@ handle_resize(void)
}
/*
- * return non-zero if a character is available
+ * Return non-zero if a character is available.
*/
int
mch_char_avail(void)
@@ -5210,7 +5210,7 @@ mch_start_job(char **argv, job_T *job, jobopt_T *options UNUSED)
/* See above for type of argv. */
execvp(argv[0], argv);
- perror("executing job failed");
+ // perror("executing job failed");
_exit(EXEC_FAILED); /* exec failed, return failure code */
}
@@ -5359,6 +5359,7 @@ mch_breakcheck(void)
* "msec" == -1 will block forever.
* Invokes timer callbacks when needed.
* When a GUI is being used, this will never get called -- webb
+ * Returns TRUE when a character is available.
*/
static int
WaitForChar(long msec)
@@ -5367,6 +5368,7 @@ WaitForChar(long msec)
long due_time;
long remaining = msec;
int break_loop = FALSE;
+ int tb_change_cnt = typebuf.tb_change_cnt;
/* When waiting very briefly don't trigger timers. */
if (msec >= 0 && msec < 10L)
@@ -5377,6 +5379,11 @@ WaitForChar(long msec)
/* Trigger timers and then get the time in msec until the next one is
* due. Wait up to that time. */
due_time = check_due_timer();
+ if (typebuf.tb_change_cnt != tb_change_cnt)
+ {
+ /* timer may have used feedkeys() */
+ return FALSE;
+ }
if (due_time <= 0 || (msec > 0 && due_time > remaining))
due_time = remaining;
if (WaitForCharOrMouse(due_time, &break_loop))
diff --git a/src/os_win32.c b/src/os_win32.c
index 627d515dd..159905d0b 100644
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -1446,6 +1446,7 @@ WaitForChar(long msec)
INPUT_RECORD ir;
DWORD cRecords;
WCHAR ch, ch2;
+ int tb_change_cnt = typebuf.tb_change_cnt;
if (msec > 0)
/* Wait until the specified time has elapsed. */
@@ -1511,6 +1512,11 @@ WaitForChar(long msec)
/* Trigger timers and then get the time in msec until the
* next one is due. Wait up to that time. */
due_time = check_due_timer();
+ if (typebuf.tb_change_cnt != tb_change_cnt)
+ {
+ /* timer may have used feedkeys() */
+ return FALSE;
+ }
if (due_time > 0 && dwWaitTime > (DWORD)due_time)
dwWaitTime = due_time;
}
diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim
index 12c984888..d3e098102 100644
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -6,3 +6,30 @@ func Test_vim_did_enter()
" This script will never reach the main loop, can't check if v:vim_did_enter
" becomes one.
endfunc
+
+if !has('timers')
+ finish
+endif
+
+func ExitInsertMode(id)
+ call feedkeys("\<Esc>")
+endfunc
+
+func Test_cursorhold_insert()
+ let g:triggered = 0
+ au CursorHoldI * let g:triggered += 1
+ set updatetime=20
+ call timer_start(100, 'ExitInsertMode')
+ call feedkeys('a', 'x!')
+ call assert_equal(1, g:triggered)
+endfunc
+
+func Test_cursorhold_insert_ctrl_x()
+ let g:triggered = 0
+ au CursorHoldI * let g:triggered += 1
+ set updatetime=20
+ call timer_start(100, 'ExitInsertMode')
+ " CursorHoldI does not trigger after CTRL-X
+ call feedkeys("a\<C-X>", 'x!')
+ call assert_equal(0, g:triggered)
+endfunc
diff --git a/src/version.c b/src/version.c
index 0993f66fc..f550196cb 100644
--- a/src/version.c
+++ b/src/version.c
@@ -749,6 +749,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1759,
+/**/
1758,
/**/
1757,