diff src/ui.c @ 13060:1bdc12630fc0 v8.0.1405

patch 8.0.1405: duplicated code for getting a typed character commit https://github.com/vim/vim/commit/c9e649ae816cdff0d1da8a97d40e695c6d3991bd Author: Bram Moolenaar <Bram@vim.org> Date: Mon Dec 18 18:14:47 2017 +0100 patch 8.0.1405: duplicated code for getting a typed character Problem: Duplicated code for getting a typed character. CursorHold is called too often in the GUI. (lilydjwg) Solution: Refactor code to move code up from mch_inchar(). Don't fire CursorHold if feedkeys() was used. (closes #2451)
author Christian Brabandt <cb@256bit.org>
date Mon, 18 Dec 2017 18:15:05 +0100
parents 85a601f985ab
children 808625d4b71b
line wrap: on
line diff
--- a/src/ui.c
+++ b/src/ui.c
@@ -32,7 +32,7 @@ ui_write(char_u *s, int len)
     {
 	gui_write(s, len);
 	if (p_wd)
-	    gui_wait_for_chars(p_wd);
+	    gui_wait_for_chars(p_wd, typebuf.tb_change_cnt);
 	return;
     }
 #endif
@@ -182,18 +182,13 @@ ui_inchar(
 
 #ifdef FEAT_GUI
     if (gui.in_use)
-    {
-	if (gui_wait_for_chars(wtime) && !typebuf_changed(tb_change_cnt))
-	    retval = read_from_input_buf(buf, (long)maxlen);
-    }
+	retval = gui_inchar(buf, maxlen, wtime, tb_change_cnt);
 #endif
 #ifndef NO_CONSOLE
 # ifdef FEAT_GUI
     else
 # endif
-    {
 	retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt);
-    }
 #endif
 
     if (wtime == -1 || wtime > 100L)
@@ -212,6 +207,52 @@ theend:
     return retval;
 }
 
+#if defined(FEAT_TIMERS) || defined(PROT)
+/*
+ * Wait for a timer to fire or "wait_func" to return non-zero.
+ * Returns OK when something was read.
+ * Returns FAIL when it timed out or was interrupted.
+ */
+    int
+ui_wait_for_chars_or_timer(
+    long    wtime,
+    int	    (*wait_func)(long wtime, int *interrupted, int ignore_input),
+    int	    *interrupted,
+    int	    ignore_input)
+{
+    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)
+	return wait_func(wtime, NULL, ignore_input);
+
+    while (wtime < 0 || remaining > 0)
+    {
+	/* 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 FAIL;
+	}
+	if (due_time <= 0 || (wtime > 0 && due_time > remaining))
+	    due_time = remaining;
+	if (wait_func(due_time, interrupted, ignore_input))
+	    return OK;
+	if (interrupted != NULL && *interrupted)
+	    /* Nothing available, but need to return so that side effects get
+	     * handled, such as handling a message on a channel. */
+	    return FALSE;
+	if (wtime > 0)
+	    remaining -= due_time;
+    }
+    return FAIL;
+}
+#endif
+
 /*
  * return non-zero if a character is available
  */
@@ -245,7 +286,7 @@ ui_delay(long msec, int ignoreinput)
 {
 #ifdef FEAT_GUI
     if (gui.in_use && !ignoreinput)
-	gui_wait_for_chars(msec);
+	gui_wait_for_chars(msec, typebuf.tb_change_cnt);
     else
 #endif
 	mch_delay(msec, ignoreinput);