summaryrefslogtreecommitdiff
path: root/src/ui.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-12-18 18:14:47 +0100
committerBram Moolenaar <Bram@vim.org>2017-12-18 18:14:47 +0100
commitc9e649ae816cdff0d1da8a97d40e695c6d3991bd (patch)
treeb9e52b1126c83609c9b5dae5305e535bc4002a10 /src/ui.c
parent606d45ccd8a2ad2956e2729f6135fd79fd2f6d72 (diff)
downloadvim-git-c9e649ae816cdff0d1da8a97d40e695c6d3991bd.tar.gz
patch 8.0.1405: duplicated code for getting a typed characterv8.0.1405
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)
Diffstat (limited to 'src/ui.c')
-rw-r--r--src/ui.c57
1 files changed, 49 insertions, 8 deletions
diff --git a/src/ui.c b/src/ui.c
index 7d969fec8..e410f6829 100644
--- 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);