Permalink
Browse files

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)
  • Loading branch information...
brammool committed Dec 18, 2017
1 parent 606d45c commit c9e649ae816cdff0d1da8a97d40e695c6d3991bd
Showing with 90 additions and 71 deletions.
  1. +33 −31 src/gui.c
  2. +1 −1 src/main.c
  3. +2 −30 src/os_unix.c
  4. +2 −1 src/proto/gui.pro
  5. +1 −0 src/proto/ui.pro
  6. +49 −8 src/ui.c
  7. +2 −0 src/version.c
View
@@ -2885,6 +2885,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];
@@ -3005,6 +2991,22 @@ gui_wait_for_chars(long wtime)
return retval;
}
/*
* 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().
*/
View
@@ -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
View
@@ -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
View
@@ -29,7 +29,8 @@ int gui_outstr_nowrap(char_u *s, int len, int flags, guicolor_T fg, guicolor_T b
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);
View
@@ -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);
View
@@ -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 @@ ui_inchar(
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);
View
@@ -771,6 +771,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1405,
/**/
1404,
/**/

0 comments on commit c9e649a

Please sign in to comment.