# HG changeset patch # User Christian Brabandt # Date 1461177007 -7200 # Node ID c07caeb90a3520b3b37618186a8c61a4b6827034 # Parent 0f9988d6fa4980b41400ceb7d2cd1b3a88e0a7c6 commit https://github.com/vim/vim/commit/40b1b5443c88fab77f1f7c6f9e801f7ffdb7e0a8 Author: Bram Moolenaar Date: Wed Apr 20 20:18:23 2016 +0200 patch 7.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. diff --git a/src/gui.c b/src/gui.c --- 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 --- 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, j /* 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 --- 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 --- 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("\") +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\", 'x!') + call assert_equal(0, g:triggered) +endfunc diff --git a/src/version.c b/src/version.c --- 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,