diff options
Diffstat (limited to 'data/vim/patches/8.1.0834')
-rw-r--r-- | data/vim/patches/8.1.0834 | 688 |
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 /// |