summaryrefslogtreecommitdiff
path: root/data/vim/patches/8.1.0834
diff options
context:
space:
mode:
Diffstat (limited to 'data/vim/patches/8.1.0834')
-rw-r--r--data/vim/patches/8.1.0834688
1 files changed, 688 insertions, 0 deletions
diff --git a/data/vim/patches/8.1.0834 b/data/vim/patches/8.1.0834
new file mode 100644
index 000000000..f5de64ec5
--- /dev/null
+++ b/data/vim/patches/8.1.0834
@@ -0,0 +1,688 @@
+To: vim_dev@googlegroups.com
+Subject: Patch 8.1.0834
+Fcc: outbox
+From: Bram Moolenaar <Bram@moolenaar.net>
+Mime-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+------------
+
+Patch 8.1.0834
+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)
+Files: src/ui.c, src/proto/ui.pro, src/os_unix.c, src/gui.c,
+ src/testdir/screendump.vim
+
+
+*** ../vim-8.1.0833/src/ui.c 2019-01-26 17:28:22.236599060 +0100
+--- src/ui.c 2019-01-27 16:50:31.054860125 +0100
+***************
+*** 178,183 ****
+--- 178,225 ----
+ ctrl_c_interrupts = FALSE;
+ }
+
++ /*
++ * Here we call gui_inchar() or mch_inchar(), the GUI or machine-dependent
++ * input function. The functionality they implement is like this:
++ *
++ * while (not timed out)
++ * {
++ * handle-resize;
++ * parse-queued-messages;
++ * if (waited for 'updatetime')
++ * trigger-cursorhold;
++ * ui_wait_for_chars_or_timer()
++ * if (character available)
++ * break;
++ * }
++ *
++ * ui_wait_for_chars_or_timer() does:
++ *
++ * while (not timed out)
++ * {
++ * if (any-timer-triggered)
++ * invoke-timer-callback;
++ * wait-for-character();
++ * if (character available)
++ * break;
++ * }
++ *
++ * wait-for-character() does:
++ * while (not timed out)
++ * {
++ * Wait for event;
++ * if (something on channel)
++ * read/write channel;
++ * else if (resized)
++ * handle_resize();
++ * else if (system event)
++ * deal-with-system-event;
++ * else if (character available)
++ * break;
++ * }
++ *
++ */
++
+ #ifdef FEAT_GUI
+ if (gui.in_use)
+ retval = gui_inchar(buf, maxlen, wtime, tb_change_cnt);
+***************
+*** 205,210 ****
+--- 247,422 ----
+ return retval;
+ }
+
++ #if defined(UNIX) || defined(FEAT_GUI) || defined(PROTO)
++ /*
++ * Common code for mch_inchar() and gui_inchar(): Wait for a while or
++ * indefinitely until characters are available, dealing with timers and
++ * messages on channels.
++ *
++ * "buf" may be NULL if the available characters are not to be returned, only
++ * check if they are available.
++ *
++ * Return the number of characters that are available.
++ * If "wtime" == 0 do not wait for characters.
++ * If "wtime" == n wait a short time for characters.
++ * If "wtime" == -1 wait forever for characters.
++ */
++ int
++ inchar_loop(
++ char_u *buf,
++ int maxlen,
++ long wtime, // don't use "time", MIPS cannot handle it
++ int tb_change_cnt,
++ int (*wait_func)(long wtime, int *interrupted, int ignore_input),
++ int (*resize_func)(int check_only))
++ {
++ int len;
++ int interrupted = FALSE;
++ int did_start_blocking = FALSE;
++ long wait_time;
++ long elapsed_time = 0;
++ #ifdef ELAPSED_FUNC
++ elapsed_T start_tv;
++
++ ELAPSED_INIT(start_tv);
++ #endif
++
++ /* repeat until we got a character or waited long enough */
++ for (;;)
++ {
++ /* Check if window changed size while we were busy, perhaps the ":set
++ * columns=99" command was used. */
++ if (resize_func != NULL)
++ resize_func(FALSE);
++
++ #ifdef MESSAGE_QUEUE
++ // Only process messages when waiting.
++ if (wtime != 0)
++ {
++ parse_queued_messages();
++ // If input was put directly in typeahead buffer bail out here.
++ if (typebuf_changed(tb_change_cnt))
++ return 0;
++ }
++ #endif
++ if (wtime < 0 && did_start_blocking)
++ // blocking and already waited for p_ut
++ wait_time = -1;
++ else
++ {
++ if (wtime >= 0)
++ wait_time = wtime;
++ else
++ // going to block after p_ut
++ wait_time = p_ut;
++ #ifdef ELAPSED_FUNC
++ elapsed_time = ELAPSED_FUNC(start_tv);
++ #endif
++ wait_time -= elapsed_time;
++ if (wait_time <= 0)
++ {
++ if (wtime >= 0)
++ // no character available within "wtime"
++ return 0;
++
++ // No character available within 'updatetime'.
++ did_start_blocking = TRUE;
++ if (trigger_cursorhold() && maxlen >= 3
++ && !typebuf_changed(tb_change_cnt))
++ {
++ // Put K_CURSORHOLD in the input buffer or return it.
++ if (buf == NULL)
++ {
++ char_u ibuf[3];
++
++ ibuf[0] = CSI;
++ ibuf[1] = KS_EXTRA;
++ ibuf[2] = (int)KE_CURSORHOLD;
++ add_to_input_buf(ibuf, 3);
++ }
++ else
++ {
++ buf[0] = K_SPECIAL;
++ buf[1] = KS_EXTRA;
++ buf[2] = (int)KE_CURSORHOLD;
++ }
++ return 3;
++ }
++
++ // There is no character available within 'updatetime' seconds:
++ // flush all the swap files to disk. Also done when
++ // interrupted by SIGWINCH.
++ before_blocking();
++ continue;
++ }
++ }
++
++ #ifdef FEAT_JOB_CHANNEL
++ if (wait_time < 0 || wait_time > 100L)
++ {
++ // Checking if a job ended requires polling. Do this at least
++ // every 100 msec.
++ if (has_pending_job())
++ wait_time = 100L;
++
++ // If there is readahead then parse_queued_messages() timed out and
++ // we should call it again soon.
++ if (channel_any_readahead())
++ wait_time = 10L;
++ }
++ #endif
++ #ifdef FEAT_BEVAL_GUI
++ if (p_beval && wait_time > 100L)
++ // The 'balloonexpr' may indirectly invoke a callback while waiting
++ // for a character, need to check often.
++ wait_time = 100L;
++ #endif
++
++ // Wait for a character to be typed or another event, such as the winch
++ // signal or an event on the monitored file descriptors.
++ if (wait_func(wait_time, &interrupted, FALSE))
++ {
++ // If input was put directly in typeahead buffer bail out here.
++ if (typebuf_changed(tb_change_cnt))
++ return 0;
++
++ // We might have something to return now.
++ if (buf == NULL)
++ // "buf" is NULL, we were just waiting, not actually getting
++ // input.
++ return input_available();
++
++ len = read_from_input_buf(buf, (long)maxlen);
++ if (len > 0)
++ return len;
++ continue;
++ }
++ // Timed out or interrupted with no character available.
++
++ #ifndef ELAPSED_FUNC
++ // estimate the elapsed time
++ elapsed_time += wait_time;
++ #endif
++
++ if ((resize_func != NULL && resize_func(TRUE))
++ #ifdef FEAT_CLIENTSERVER
++ || server_waiting()
++ #endif
++ #ifdef MESSAGE_QUEUE
++ || interrupted
++ #endif
++ || wait_time > 0
++ || (wtime < 0 && !did_start_blocking))
++ // no character available, but something to be done, keep going
++ continue;
++
++ // no character available or interrupted, return zero
++ break;
++ }
++ return 0;
++ }
++ #endif
++
+ #if defined(FEAT_TIMERS) || defined(PROTO)
+ /*
+ * Wait for a timer to fire or "wait_func" to return non-zero.
+*** ../vim-8.1.0833/src/proto/ui.pro 2018-05-17 13:52:54.000000000 +0200
+--- src/proto/ui.pro 2019-01-26 22:35:56.703647735 +0100
+***************
+*** 2,7 ****
+--- 2,8 ----
+ void ui_write(char_u *s, int len);
+ void ui_inchar_undo(char_u *s, int len);
+ int ui_inchar(char_u *buf, int maxlen, long wtime, int tb_change_cnt);
++ int inchar_loop(char_u *buf, int maxlen, long wtime, int tb_change_cnt, int (*wait_func)(long wtime, int *interrupted, int ignore_input), int (*resize_func)(int check_only));
+ 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 ui_char_avail(void);
+ void ui_delay(long msec, int ignoreinput);
+*** ../vim-8.1.0833/src/os_unix.c 2019-01-26 15:12:52.558260916 +0100
+--- src/os_unix.c 2019-01-26 22:36:20.799486197 +0100
+***************
+*** 356,361 ****
+--- 356,376 ----
+ }
+
+ /*
++ * Function passed to inchar_loop() to handle window resizing.
++ * If "check_only" is TRUE: Return whether there was a resize.
++ * If "check_only" is FALSE: Deal with the window resized.
++ */
++ static int
++ resize_func(int check_only)
++ {
++ if (check_only)
++ return do_resize;
++ while (do_resize)
++ handle_resize();
++ return FALSE;
++ }
++
++ /*
+ * mch_inchar(): low level input function.
+ * Get a characters from the keyboard.
+ * Return the number of characters that are available.
+***************
+*** 370,507 ****
+ long wtime, /* don't use "time", MIPS cannot handle it */
+ int tb_change_cnt)
+ {
+! int len;
+! int interrupted = FALSE;
+! int did_start_blocking = FALSE;
+! long wait_time;
+! long elapsed_time = 0;
+! #ifdef ELAPSED_FUNC
+! elapsed_T start_tv;
+!
+! ELAPSED_INIT(start_tv);
+! #endif
+!
+! /* repeat until we got a character or waited long enough */
+! for (;;)
+! {
+! /* Check if window changed size while we were busy, perhaps the ":set
+! * columns=99" command was used. */
+! while (do_resize)
+! handle_resize();
+!
+! #ifdef MESSAGE_QUEUE
+! // Only process messages when waiting.
+! if (wtime != 0)
+! {
+! parse_queued_messages();
+! // If input was put directly in typeahead buffer bail out here.
+! if (typebuf_changed(tb_change_cnt))
+! return 0;
+! }
+! #endif
+! if (wtime < 0 && did_start_blocking)
+! /* blocking and already waited for p_ut */
+! wait_time = -1;
+! else
+! {
+! if (wtime >= 0)
+! wait_time = wtime;
+! else
+! /* going to block after p_ut */
+! wait_time = p_ut;
+! #ifdef ELAPSED_FUNC
+! elapsed_time = ELAPSED_FUNC(start_tv);
+! #endif
+! wait_time -= elapsed_time;
+! if (wait_time < 0)
+! {
+! if (wtime >= 0)
+! /* no character available within "wtime" */
+! return 0;
+!
+! else
+! {
+! /* no character available within 'updatetime' */
+! did_start_blocking = TRUE;
+! if (trigger_cursorhold() && maxlen >= 3
+! && !typebuf_changed(tb_change_cnt))
+! {
+! buf[0] = K_SPECIAL;
+! buf[1] = KS_EXTRA;
+! buf[2] = (int)KE_CURSORHOLD;
+! return 3;
+! }
+! /*
+! * If there is no character available within 'updatetime'
+! * seconds flush all the swap files to disk.
+! * Also done when interrupted by SIGWINCH.
+! */
+! before_blocking();
+! continue;
+! }
+! }
+! }
+!
+! #ifdef FEAT_JOB_CHANNEL
+! /* Checking if a job ended requires polling. Do this every 100 msec. */
+! if (has_pending_job() && (wait_time < 0 || wait_time > 100L))
+! wait_time = 100L;
+! /* If there is readahead then parse_queued_messages() timed out and we
+! * should call it again soon. */
+! if ((wait_time < 0 || wait_time > 100L) && channel_any_readahead())
+! wait_time = 10L;
+! #endif
+! #ifdef FEAT_BEVAL_GUI
+! if (p_beval && wait_time > 100L)
+! /* The 'balloonexpr' may indirectly invoke a callback while waiting
+! * for a character, need to check often. */
+! wait_time = 100L;
+! #endif
+!
+! /*
+! * We want to be interrupted by the winch signal
+! * or by an event on the monitored file descriptors.
+! */
+! if (WaitForChar(wait_time, &interrupted, FALSE))
+! {
+! /* If input was put directly in typeahead buffer bail out here. */
+! if (typebuf_changed(tb_change_cnt))
+! return 0;
+!
+! /*
+! * For some terminals we only get one character at a time.
+! * We want the get all available characters, so we could keep on
+! * trying until none is available
+! * For some other terminals this is quite slow, that's why we don't
+! * do it.
+! */
+! len = read_from_input_buf(buf, (long)maxlen);
+! if (len > 0)
+! return len;
+! continue;
+! }
+!
+! /* no character available */
+! #ifndef ELAPSED_FUNC
+! /* estimate the elapsed time */
+! elapsed_time += wait_time;
+! #endif
+!
+! if (do_resize /* interrupted by SIGWINCH signal */
+! #ifdef FEAT_CLIENTSERVER
+! || server_waiting()
+! #endif
+! #ifdef MESSAGE_QUEUE
+! || interrupted
+! #endif
+! || wait_time > 0
+! || (wtime < 0 && !did_start_blocking))
+! continue;
+!
+! /* no character available or interrupted */
+! break;
+! }
+! return 0;
+ }
+
+ static void
+--- 385,392 ----
+ long wtime, /* don't use "time", MIPS cannot handle it */
+ int tb_change_cnt)
+ {
+! return inchar_loop(buf, maxlen, wtime, tb_change_cnt,
+! WaitForChar, resize_func);
+ }
+
+ static void
+*** ../vim-8.1.0833/src/gui.c 2019-01-26 17:28:22.224599141 +0100
+--- src/gui.c 2019-01-26 23:17:38.097634554 +0100
+***************
+*** 2896,2905 ****
+ * or FAIL otherwise.
+ */
+ static int
+! gui_wait_for_chars_or_timer(long wtime)
+ {
+ #ifdef FEAT_TIMERS
+! return ui_wait_for_chars_or_timer(wtime, gui_wait_for_chars_3, NULL, 0);
+ #else
+ return gui_mch_wait_for_chars(wtime);
+ #endif
+--- 2896,2909 ----
+ * or FAIL otherwise.
+ */
+ static int
+! 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,
+! interrupted, ignore_input);
+ #else
+ return gui_mch_wait_for_chars(wtime);
+ #endif
+***************
+*** 2907,3000 ****
+
+ /*
+ * 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 OK if a character was found to be available within the given time,
+! * or FAIL otherwise.
+ */
+! 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;
+ }
+
+ /*
+ * Equivalent of mch_inchar() for the GUI.
+ */
+ int
+--- 2911,2982 ----
+
+ /*
+ * 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.
++ * Returns OK if a character was found to be available within the given time,
++ * or FAIL otherwise.
++ */
++ int
++ gui_wait_for_chars(long wtime, int tb_change_cnt)
++ {
++ return gui_wait_for_chars_buf(NULL, 0, wtime, tb_change_cnt);
++ }
++
++ /*
+ * Equivalent of mch_inchar() for the GUI.
+ */
+ int
+***************
+*** 3004,3013 ****
+ 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;
+ }
+
+ /*
+--- 2986,2992 ----
+ long wtime, /* milli seconds */
+ int tb_change_cnt)
+ {
+! return gui_wait_for_chars_buf(buf, maxlen, wtime, tb_change_cnt);
+ }
+
+ /*
+*** ../vim-8.1.0833/src/testdir/screendump.vim 2018-12-04 22:24:12.193693584 +0100
+--- src/testdir/screendump.vim 2019-01-27 16:20:34.371242071 +0100
+***************
+*** 58,63 ****
+--- 58,67 ----
+ let cmd .= ' -v ' . a:arguments
+ let buf = term_start(cmd, {'curwin': 1, 'term_rows': rows, 'term_cols': cols})
+ if &termwinsize == ''
++ " in the GUI we may end up with a different size, try to set it.
++ if term_getsize(buf) != [rows, cols]
++ call term_setsize(buf, rows, cols)
++ endif
+ call assert_equal([rows, cols], term_getsize(buf))
+ else
+ let rows = term_getsize(buf)[0]
+*** ../vim-8.1.0833/src/version.c 2019-01-27 15:07:35.161741346 +0100
+--- src/version.c 2019-01-27 16:36:02.924759049 +0100
+***************
+*** 785,786 ****
+--- 785,788 ----
+ { /* Add new patch number below this line */
++ /**/
++ 834,
+ /**/
+
+--
+We do not stumble over mountains, but over molehills.
+ Confucius
+
+ /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
+/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
+\\\ an exciting new programming language -- http://www.Zimbu.org ///
+ \\\ help me help AIDS victims -- http://ICCF-Holland.org ///