]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 7.4.1759 v7.4.1759
authorBram Moolenaar <Bram@vim.org>
Wed, 20 Apr 2016 18:18:23 +0000 (20:18 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 20 Apr 2016 18:18:23 +0000 (20:18 +0200)
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.

src/gui.c
src/os_unix.c
src/os_win32.c
src/testdir/test_autocmd.vim
src/version.c

index 8999f793ff1fa6734b711a9d4da0fe9f6c73753e..d747d8117933332e83b71d168c725716a77813e2 100644 (file)
--- 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))
index 58a27da050c2398b547984e770b038a3bb13347b..f8cf691d1fd36e15aa030b7ba937ed4225f3ed94 100644 (file)
@@ -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))
index 627d515dda5465ce5a5d719c6a16492b8d6e72a7..159905d0b0d0564f4fc2d9fc9f3f5503d100b098 100644 (file)
@@ -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;
                }
index 12c984888e3d5debeffeaf0b1a7625832661f089..d3e09810250d31e8b6a1b50852cf87f593694c82 100644 (file)
@@ -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
index 0993f66fc6c90ab324e87ee15772a7fd1e4d91fc..f550196cb38ef4720767b34668010b24a460c18f 100644 (file)
@@ -748,6 +748,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1759,
 /**/
     1758,
 /**/