To: vim_dev@googlegroups.com Subject: Patch 8.0.1405 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.0.1405 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) Files: src/gui.c, src/proto/gui.pro, src/main.c, src/ui.c, src/proto/ui.pro, src/os_unix.c *** ../vim-8.0.1404/src/gui.c 2017-12-17 21:54:51.240060608 +0100 --- src/gui.c 2017-12-18 18:09:53.489250690 +0100 *************** *** 2886,2891 **** --- 2886,2903 ---- } /* + * 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,2924 **** 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; #else return gui_mch_wait_for_chars(wtime); #endif --- 2905,2911 ---- 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 *************** *** 2933,2942 **** * or FAIL otherwise. */ int ! gui_wait_for_chars(long wtime) { int retval; - int tb_change_cnt = typebuf.tb_change_cnt; #ifdef FEAT_MENU /* --- 2920,2928 ---- * or FAIL otherwise. */ int ! gui_wait_for_chars(long wtime, int tb_change_cnt) { int retval; #ifdef FEAT_MENU /* *************** *** 2974,2986 **** 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. */ if (gui_wait_for_chars_or_timer(p_ut) == OK) retval = OK; #ifdef FEAT_AUTOCMD ! else if (trigger_cursorhold()) { char_u buf[3]; --- 2960,2972 ---- 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; #ifdef FEAT_AUTOCMD ! else if (trigger_cursorhold() && typebuf.tb_change_cnt == tb_change_cnt) { char_u buf[3]; *************** *** 3006,3011 **** --- 2992,3013 ---- } /* + * 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 *** ../vim-8.0.1404/src/proto/gui.pro 2016-09-12 13:04:25.000000000 +0200 --- src/proto/gui.pro 2017-12-18 18:00:51.755846325 +0100 *************** *** 29,35 **** 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); 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); --- 29,36 ---- 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 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); *** ../vim-8.0.1404/src/main.c 2017-12-18 16:21:40.660711890 +0100 --- src/main.c 2017-12-18 16:46:22.563494123 +0100 *************** *** 619,625 **** # ifdef FEAT_SUN_WORKSHOP if (!usingSunWorkShop) # endif ! gui_wait_for_chars(50L); TIME_MSG("GUI delay"); } #endif --- 619,625 ---- # ifdef FEAT_SUN_WORKSHOP if (!usingSunWorkShop) # endif ! gui_wait_for_chars(50L, typebuf.tb_change_cnt); TIME_MSG("GUI delay"); } #endif *** ../vim-8.0.1404/src/ui.c 2017-11-25 17:14:29.608189513 +0100 --- src/ui.c 2017-12-18 18:01:43.399614597 +0100 *************** *** 32,38 **** { gui_write(s, len); if (p_wd) ! gui_wait_for_chars(p_wd); return; } #endif --- 32,38 ---- { gui_write(s, len); if (p_wd) ! gui_wait_for_chars(p_wd, typebuf.tb_change_cnt); return; } #endif *************** *** 182,199 **** #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); ! } #endif #ifndef NO_CONSOLE # ifdef FEAT_GUI else # endif - { retval = mch_inchar(buf, maxlen, wtime, tb_change_cnt); - } #endif if (wtime == -1 || wtime > 100L) --- 182,194 ---- #ifdef FEAT_GUI if (gui.in_use) ! 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,217 **** --- 207,258 ---- 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,251 **** { #ifdef FEAT_GUI if (gui.in_use && !ignoreinput) ! gui_wait_for_chars(msec); else #endif mch_delay(msec, ignoreinput); --- 286,292 ---- { #ifdef FEAT_GUI if (gui.in_use && !ignoreinput) ! gui_wait_for_chars(msec, typebuf.tb_change_cnt); else #endif mch_delay(msec, ignoreinput); *** ../vim-8.0.1404/src/proto/ui.pro 2017-08-12 19:51:37.815214191 +0200 --- src/proto/ui.pro 2017-12-18 18:00:26.931956053 +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 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); *** ../vim-8.0.1404/src/os_unix.c 2017-11-18 22:13:04.749908702 +0100 --- src/os_unix.c 2017-12-18 17:56:15.404992051 +0100 *************** *** 5790,5825 **** 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; #else return WaitForCharOrMouse(msec, interrupted, ignore_input); #endif --- 5790,5797 ---- WaitForChar(long msec, int *interrupted, int ignore_input) { #ifdef FEAT_TIMERS ! return ui_wait_for_chars_or_timer( ! msec, WaitForCharOrMouse, interrupted, ignore_input) == OK; #else return WaitForCharOrMouse(msec, interrupted, ignore_input); #endif *** ../vim-8.0.1404/src/version.c 2017-12-18 16:21:40.660711890 +0100 --- src/version.c 2017-12-18 18:13:20.268197562 +0100 *************** *** 773,774 **** --- 773,776 ---- { /* Add new patch number below this line */ + /**/ + 1405, /**/ -- Would you care for a drink? I mean, if it were, like, disabled and you had to look after it? /// 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 ///