# HG changeset patch # User Christian Brabandt # Date 1498576503 -7200 # Node ID 0a5d405e2520747a9e839de9c1dc329a7e18dfa9 # Parent 8ea05b723b257dad52f490b2fdb0c07a7f265fc8 patch 8.0.0683: visual bell flashes too quickly commit https://github.com/vim/vim/commit/2e147caa14f622dfd1c1def8e07c113b9b85d4b2 Author: Bram Moolenaar Date: Tue Jun 27 17:09:37 2017 +0200 patch 8.0.0683: visual bell flashes too quickly Problem: When using a visual bell there is no delay, causing the flash to be very short, possibly unnoticeable. Also, the flash and the beep can lockup the UI when repeated often. Solution: Do the delay in Vim or flush the output before the delay. Limit the bell to once per half a second. (Ozaki Kiichi, closes #1789) diff --git a/src/misc1.c b/src/misc1.c --- a/src/misc1.c +++ b/src/misc1.c @@ -3685,16 +3685,30 @@ vim_beep( { if (!((bo_flags & val) || (bo_flags & BO_ALL))) { - if (p_vb +#ifdef ELAPSED_FUNC + static int did_init = FALSE; + static ELAPSED_TYPE start_tv; + + /* Only beep once per half a second, otherwise a sequence of beeps + * would freeze Vim. */ + if (!did_init || ELAPSED_FUNC(start_tv) > 500) + { + did_init = TRUE; + ELAPSED_INIT(start_tv); +#endif + if (p_vb #ifdef FEAT_GUI - /* While the GUI is starting up the termcap is set for the - * GUI but the output still goes to a terminal. */ - && !(gui.in_use && gui.starting) -#endif - ) - out_str(T_VB); - else - out_char(BELL); + /* While the GUI is starting up the termcap is set for + * the GUI but the output still goes to a terminal. */ + && !(gui.in_use && gui.starting) +#endif + ) + out_str_cf(T_VB); + else + out_char(BELL); +#ifdef ELAPSED_FUNC + } +#endif } /* When 'verbose' is set and we are sourcing a script or executing a diff --git a/src/proto/term.pro b/src/proto/term.pro --- a/src/proto/term.pro +++ b/src/proto/term.pro @@ -16,6 +16,7 @@ void out_flush_check(void); void out_trash(void); void out_char(unsigned c); void out_str_nf(char_u *s); +void out_str_cf(char_u *s); void out_str(char_u *s); void term_windgoto(int row, int col); void term_cursor_right(int i); diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -2514,6 +2514,75 @@ out_str_nf(char_u *s) #endif /* + * A conditional-flushing out_str, mainly for visualbell. + * Handles a delay internally, because termlib may not respect the delay or do + * it at the wrong time. + * Note: Only for terminal strings. + */ + void +out_str_cf(char_u *s) +{ + if (s != NULL && *s) + { + char_u *p; + +#ifdef FEAT_GUI + /* Don't use tputs() when GUI is used, ncurses crashes. */ + if (gui.in_use) + { + out_str_nf(s); + return; + } +#endif + if (out_pos > OUT_SIZE - 20) + out_flush(); +#ifdef HAVE_TGETENT + for (p = s; *s; ++s) + { + /* flush just before delay command */ + if (*s == '$' && *(s + 1) == '<') + { + char_u save_c = *s; + int duration = atoi((char *)s + 2); + + *s = NUL; + tputs((char *)p, 1, TPUTSFUNCAST out_char_nf); + *s = save_c; + out_flush(); +#ifdef ELAPSED_FUNC + /* Only sleep here if we can limit this happening in + * vim_beep(). */ + p = vim_strchr(s, '>'); + if (p == NULL || duration <= 0) + { + /* can't parse the time, don't sleep here */ + p = s; + } + else + { + ++p; + do_sleep(duration); + } +#else + /* Rely on the terminal library to sleep. */ + p = s; +#endif + break; + } + } + tputs((char *)p, 1, TPUTSFUNCAST out_char_nf); +#else + while (*s) + out_char_nf(*s++); +#endif + + /* For testing we write one string at a time. */ + if (p_wd) + out_flush(); + } +} + +/* * out_str(s): Put a character string a byte at a time into the output buffer. * If HAVE_TGETENT is defined use the termcap parser. (jw) * This should only be used for writing terminal codes, not for outputting diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -765,6 +765,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 683, +/**/ 682, /**/ 681,