# HG changeset patch # User Christian Brabandt # Date 1513617305 -3600 # Node ID 1bdc12630fc0639f5b4f92ff691881321adcc4f0 # Parent 5c8106a75f257cd656901c941108a70c79fa771f patch 8.0.1405: duplicated code for getting a typed character commit https://github.com/vim/vim/commit/c9e649ae816cdff0d1da8a97d40e695c6d3991bd Author: Bram Moolenaar Date: Mon Dec 18 18:14:47 2017 +0100 patch 8.0.1405: duplicated code for getting a typed character 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) diff --git a/src/gui.c b/src/gui.c --- a/src/gui.c +++ b/src/gui.c @@ -2886,6 +2886,18 @@ gui_insert_lines(int row, int count) } /* + * Passed to ui_wait_for_chars_or_timer(), ignoring extra arguments. + */ + static int +gui_wait_for_chars_3( + long wtime, + int *interrupted UNUSED, + int ignore_input UNUSED) +{ + return gui_mch_wait_for_chars(wtime); +} + +/* * Returns OK if a character was found to be available within the given time, * or FAIL otherwise. */ @@ -2893,32 +2905,7 @@ gui_insert_lines(int row, int count) gui_wait_for_chars_or_timer(long wtime) { #ifdef FEAT_TIMERS - 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 gui_mch_wait_for_chars(wtime); - - 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 (gui_mch_wait_for_chars(due_time)) - return OK; - if (wtime > 0) - remaining -= due_time; - } - return FAIL; + return ui_wait_for_chars_or_timer(wtime, gui_wait_for_chars_3, NULL, 0); #else return gui_mch_wait_for_chars(wtime); #endif @@ -2933,10 +2920,9 @@ gui_wait_for_chars_or_timer(long wtime) * or FAIL otherwise. */ int -gui_wait_for_chars(long wtime) +gui_wait_for_chars(long wtime, int tb_change_cnt) { int retval; - int tb_change_cnt = typebuf.tb_change_cnt; #ifdef FEAT_MENU /* @@ -2974,13 +2960,13 @@ gui_wait_for_chars(long wtime) retval = FAIL; /* * We may want to trigger the CursorHold event. First wait for - * 'updatetime' and if nothing is typed within that time put the - * K_CURSORHOLD key in the input buffer. + * '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; #ifdef FEAT_AUTOCMD - else if (trigger_cursorhold()) + else if (trigger_cursorhold() && typebuf.tb_change_cnt == tb_change_cnt) { char_u buf[3]; @@ -3006,6 +2992,22 @@ gui_wait_for_chars(long wtime) } /* + * Equivalent of mch_inchar() for the GUI. + */ + int +gui_inchar( + char_u *buf, + int maxlen, + 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; +} + +/* * Fill p[4] with mouse coordinates encoded for check_termcode(). */ static void diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c @@ -619,7 +619,7 @@ vim_main2(void) # ifdef FEAT_SUN_WORKSHOP if (!usingSunWorkShop) # endif - gui_wait_for_chars(50L); + gui_wait_for_chars(50L, typebuf.tb_change_cnt); TIME_MSG("GUI delay"); } #endif diff --git a/src/os_unix.c b/src/os_unix.c --- a/src/os_unix.c +++ b/src/os_unix.c @@ -5790,36 +5790,8 @@ mch_breakcheck(int force) WaitForChar(long msec, int *interrupted, int ignore_input) { #ifdef FEAT_TIMERS - long due_time; - long remaining = msec; - int tb_change_cnt = typebuf.tb_change_cnt; - - /* When waiting very briefly don't trigger timers. */ - if (msec >= 0 && msec < 10L) - return WaitForCharOrMouse(msec, NULL, ignore_input); - - while (msec < 0 || remaining > 0) - { - /* Trigger timers and then get the time in msec 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 FALSE; - } - if (due_time <= 0 || (msec > 0 && due_time > remaining)) - due_time = remaining; - if (WaitForCharOrMouse(due_time, interrupted, ignore_input)) - return TRUE; - 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 (msec > 0) - remaining -= due_time; - } - return FALSE; + return ui_wait_for_chars_or_timer( + msec, WaitForCharOrMouse, interrupted, ignore_input) == OK; #else return WaitForCharOrMouse(msec, interrupted, ignore_input); #endif diff --git a/src/proto/gui.pro b/src/proto/gui.pro --- a/src/proto/gui.pro +++ b/src/proto/gui.pro @@ -29,7 +29,8 @@ int gui_outstr_nowrap(char_u *s, int len void gui_undraw_cursor(void); void gui_redraw(int x, int y, int w, int h); int gui_redraw_block(int row1, int col1, int row2, int col2, int flags); -int gui_wait_for_chars(long wtime); +int gui_wait_for_chars(long wtime, int tb_change_cnt); +int gui_inchar(char_u *buf, int maxlen, long wtime, int tb_change_cnt); void gui_send_mouse_event(int button, int x, int y, int repeated_click, int_u modifiers); int gui_xy2colrow(int x, int y, int *colp); void gui_menu_cb(vimmenu_T *menu); diff --git a/src/proto/ui.pro b/src/proto/ui.pro --- a/src/proto/ui.pro +++ b/src/proto/ui.pro @@ -2,6 +2,7 @@ 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 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); void ui_suspend(void); diff --git a/src/ui.c b/src/ui.c --- 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); diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -772,6 +772,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1405, +/**/ 1404, /**/ 1403,