diff src/gui.c @ 15653:59a1ff689b4d v8.1.0834

patch 8.1.0834: GUI may wait too long before dealing with messages commit https://github.com/vim/vim/commit/e40b9d47bf8f8f716d3ef5a95c8ecbbdc0a501f9 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Jan 27 16:55:47 2019 +0100 patch 8.1.0834: GUI may wait too long before dealing with messages Problem: GUI may wait too long before dealing with messages. Returning early may cause a mapping to time out. Solution: Use the waiting loop from Unix also for the GUI. (closes #3817, closes #3824)
author Bram Moolenaar <Bram@vim.org>
date Sun, 27 Jan 2019 17:00:07 +0100
parents 6f1c7e9a6393
children ad8b2c109b22
line wrap: on
line diff
--- a/src/gui.c
+++ b/src/gui.c
@@ -2896,10 +2896,14 @@ gui_wait_for_chars_3(
  * or FAIL otherwise.
  */
     static int
-gui_wait_for_chars_or_timer(long wtime)
+gui_wait_for_chars_or_timer(
+	long wtime,
+	int *interrupted UNUSED,
+	int ignore_input UNUSED)
 {
 #ifdef FEAT_TIMERS
-    return ui_wait_for_chars_or_timer(wtime, gui_wait_for_chars_3, NULL, 0);
+    return ui_wait_for_chars_or_timer(wtime, gui_wait_for_chars_3,
+						    interrupted, ignore_input);
 #else
     return gui_mch_wait_for_chars(wtime);
 #endif
@@ -2907,6 +2911,59 @@ gui_wait_for_chars_or_timer(long wtime)
 
 /*
  * The main GUI input routine.	Waits for a character from the keyboard.
+ * "wtime" == -1    Wait forever.
+ * "wtime" == 0	    Don't wait.
+ * "wtime" > 0	    Wait wtime milliseconds for a character.
+ *
+ * Returns the number of characters read or zero when timed out or interrupted.
+ * "buf" may be NULL, in which case a non-zero number is returned if characters
+ * are available.
+ */
+    static int
+gui_wait_for_chars_buf(
+    char_u	*buf,
+    int		maxlen,
+    long	wtime,	    // don't use "time", MIPS cannot handle it
+    int		tb_change_cnt)
+{
+    int	    retval;
+
+#ifdef FEAT_MENU
+    // If we're going to wait a bit, update the menus and mouse shape for the
+    // current State.
+    if (wtime != 0)
+	gui_update_menus(0);
+#endif
+
+    gui_mch_update();
+    if (input_available())	// Got char, return immediately
+    {
+	if (buf != NULL && !typebuf_changed(tb_change_cnt))
+	    return read_from_input_buf(buf, (long)maxlen);
+	return 0;
+    }
+    if (wtime == 0)		// Don't wait for char
+	return FAIL;
+
+    // Before waiting, flush any output to the screen.
+    gui_mch_flush();
+
+    // Blink while waiting for a character.
+    gui_mch_start_blink();
+
+    // Common function to loop until "wtime" is met, while handling timers and
+    // other callbacks.
+    retval = inchar_loop(buf, maxlen, wtime, tb_change_cnt,
+			 gui_wait_for_chars_or_timer, NULL);
+
+    gui_mch_stop_blink(TRUE);
+
+    return retval;
+}
+
+/*
+ * Wait for a character from the keyboard without actually reading it.
+ * Also deals with timers.
  * wtime == -1	    Wait forever.
  * wtime == 0	    Don't wait.
  * wtime > 0	    Wait wtime milliseconds for a character.
@@ -2916,82 +2973,7 @@ gui_wait_for_chars_or_timer(long wtime)
     int
 gui_wait_for_chars(long wtime, int tb_change_cnt)
 {
-    int		retval;
-#if defined(ELAPSED_FUNC)
-    elapsed_T	start_tv;
-#endif
-
-#ifdef FEAT_MENU
-    /*
-     * If we're going to wait a bit, update the menus and mouse shape for the
-     * current State.
-     */
-    if (wtime != 0)
-	gui_update_menus(0);
-#endif
-
-    gui_mch_update();
-    if (input_available())	/* Got char, return immediately */
-	return OK;
-    if (wtime == 0)	/* Don't wait for char */
-	return FAIL;
-
-    /* Before waiting, flush any output to the screen. */
-    gui_mch_flush();
-
-    if (wtime > 0)
-    {
-	/* Blink when waiting for a character.	Probably only does something
-	 * for showmatch() */
-	gui_mch_start_blink();
-	retval = gui_wait_for_chars_or_timer(wtime);
-	gui_mch_stop_blink(TRUE);
-	return retval;
-    }
-
-#if defined(ELAPSED_FUNC)
-    ELAPSED_INIT(start_tv);
-#endif
-
-    /*
-     * While we are waiting indefinitely for a character, blink the cursor.
-     */
-    gui_mch_start_blink();
-
-    retval = FAIL;
-    /*
-     * We may want to trigger the CursorHold event.  First wait for
-     * 'updatetime' and if nothing is typed within that time, and feedkeys()
-     * wasn't used, put the K_CURSORHOLD key in the input buffer.
-     */
-    if (gui_wait_for_chars_or_timer(p_ut) == OK)
-	retval = OK;
-    else if (trigger_cursorhold()
-#if defined(ELAPSED_FUNC)
-	    && ELAPSED_FUNC(start_tv) >= p_ut
-#endif
-	    && typebuf.tb_change_cnt == tb_change_cnt)
-    {
-	char_u	buf[3];
-
-	/* Put K_CURSORHOLD in the input buffer. */
-	buf[0] = CSI;
-	buf[1] = KS_EXTRA;
-	buf[2] = (int)KE_CURSORHOLD;
-	add_to_input_buf(buf, 3);
-
-	retval = OK;
-    }
-
-    if (retval == FAIL && typebuf.tb_change_cnt == tb_change_cnt)
-    {
-	/* Blocking wait. */
-	before_blocking();
-	retval = gui_wait_for_chars_or_timer(-1L);
-    }
-
-    gui_mch_stop_blink(TRUE);
-    return retval;
+    return gui_wait_for_chars_buf(NULL, 0, wtime, tb_change_cnt);
 }
 
 /*
@@ -3004,10 +2986,7 @@ gui_inchar(
     long    wtime,		/* milli seconds */
     int	    tb_change_cnt)
 {
-    if (gui_wait_for_chars(wtime, tb_change_cnt)
-	    && !typebuf_changed(tb_change_cnt))
-	return read_from_input_buf(buf, (long)maxlen);
-    return 0;
+    return gui_wait_for_chars_buf(buf, maxlen, wtime, tb_change_cnt);
 }
 
 /*