changeset 15665:31367ce5aac7 v8.1.0840

patch 8.1.0840: getchar(0) never returns a character in the terminal commit https://github.com/vim/vim/commit/12dfc9eef14fe74c46145aa9e6cba9666f1bcd40 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Jan 28 22:32:58 2019 +0100 patch 8.1.0840: getchar(0) never returns a character in the terminal Problem: getchar(0) never returns a character in the terminal. Solution: Call wait_func() at least once.
author Bram Moolenaar <Bram@vim.org>
date Mon, 28 Jan 2019 22:45:05 +0100
parents 128d7a4ccd54
children 0591140b84b2
files src/gui_gtk_x11.c src/gui_photon.c src/gui_w32.c src/gui_x11.c src/testdir/test_timers.vim src/ui.c src/version.c
diffstat 7 files changed, 37 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/src/gui_gtk_x11.c
+++ b/src/gui_gtk_x11.c
@@ -6317,10 +6317,11 @@ gui_mch_wait_for_chars(long wtime)
 
     timed_out = FALSE;
 
-    /* this timeout makes sure that we will return if no characters arrived in
-     * time */
-    if (wtime > 0)
-	timer = timeout_add(wtime, input_timer_cb, &timed_out);
+    // This timeout makes sure that we will return if no characters arrived in
+    // time. If "wtime" is zero just use one.
+    if (wtime >= 0)
+	timer = timeout_add(wtime <= 0 ? 1L : wtime,
+						   input_timer_cb, &timed_out);
     else
 	timer = 0;
 
--- a/src/gui_photon.c
+++ b/src/gui_photon.c
@@ -1344,8 +1344,9 @@ gui_mch_wait_for_chars(int wtime)
 {
     is_timeout = FALSE;
 
-    if (wtime > 0)
-	PtSetResource(gui_ph_timer_timeout, Pt_ARG_TIMER_INITIAL, wtime, 0);
+    if (wtime >= 0)
+	PtSetResource(gui_ph_timer_timeout, Pt_ARG_TIMER_INITIAL,
+						    wtime == 0 ? 1 : wtime, 0);
 
     while (1)
     {
--- a/src/gui_w32.c
+++ b/src/gui_w32.c
@@ -2097,12 +2097,14 @@ gui_mch_wait_for_chars(int wtime)
 
     s_timed_out = FALSE;
 
-    if (wtime > 0)
-    {
-	/* Don't do anything while processing a (scroll) message. */
+    if (wtime >= 0)
+    {
+	// Don't do anything while processing a (scroll) message.
 	if (s_busy_processing)
 	    return FAIL;
-	s_wait_timer = (UINT)SetTimer(NULL, 0, (UINT)wtime,
+
+	// When called with "wtime" zero, just want one msec.
+	s_wait_timer = (UINT)SetTimer(NULL, 0, (UINT)(wtime == 0 ? 1 : wtime),
 							 (TIMERPROC)_OnTimer);
     }
 
--- a/src/gui_x11.c
+++ b/src/gui_x11.c
@@ -2683,9 +2683,10 @@ gui_mch_wait_for_chars(long wtime)
 
     timed_out = FALSE;
 
-    if (wtime > 0)
-	timer = XtAppAddTimeOut(app_context, (long_u)wtime, gui_x11_timer_cb,
-								  &timed_out);
+    if (wtime >= 0)
+	timer = XtAppAddTimeOut(app_context,
+				(long_u)(wtime == 0 ? 1L : wtime),
+						 gui_x11_timer_cb, &timed_out);
 #ifdef FEAT_JOB_CHANNEL
     /* If there is a channel with the keep_open flag we need to poll for input
      * on them. */
--- a/src/testdir/test_timers.vim
+++ b/src/testdir/test_timers.vim
@@ -250,6 +250,16 @@ func Test_peek_and_get_char()
   call timer_stop(intr)
 endfunc
 
+func Test_getchar_zero()
+  call timer_start(20, {id -> feedkeys('x', 'L')})
+  let c = 0
+  while c == 0
+    let c = getchar(0)
+    sleep 10m
+  endwhile
+  call assert_equal('x', nr2char(c))
+endfunc
+
 func Test_ex_mode()
   " Function with an empty line.
   func Foo(...)
--- a/src/ui.c
+++ b/src/ui.c
@@ -272,6 +272,7 @@ inchar_loop(
 {
     int		len;
     int		interrupted = FALSE;
+    int		did_call_wait_func = FALSE;
     int		did_start_blocking = FALSE;
     long	wait_time;
     long	elapsed_time = 0;
@@ -313,7 +314,11 @@ inchar_loop(
 	    elapsed_time = ELAPSED_FUNC(start_tv);
 #endif
 	    wait_time -= elapsed_time;
-	    if (wait_time <= 0)
+
+	    // If the waiting time is now zero or less, we timed out.  However,
+	    // loop at least once to check for characters and events.  Matters
+	    // when "wtime" is zero.
+	    if (wait_time <= 0 && did_call_wait_func)
 	    {
 		if (wtime >= 0)
 		    // no character available within "wtime"
@@ -374,6 +379,7 @@ inchar_loop(
 
 	// Wait for a character to be typed or another event, such as the winch
 	// signal or an event on the monitored file descriptors.
+	did_call_wait_func = TRUE;
 	if (wait_func(wait_time, &interrupted, FALSE))
 	{
 	    // If input was put directly in typeahead buffer bail out here.
--- a/src/version.c
+++ b/src/version.c
@@ -784,6 +784,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    840,
+/**/
     839,
 /**/
     838,