diff options
author | zeertzjq <zeertzjq@outlook.com> | 2024-02-13 06:30:35 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-02-13 06:30:35 +0800 |
commit | 984f7a9fd3d4ad4c6b51fa5c54c3550756056723 (patch) | |
tree | 222b8b0d6a5bd074394abe2b0d108aa46d61a9e6 | |
parent | 84b6ade41510ffad7d712abe2b010e4027b7033c (diff) | |
download | rneovim-984f7a9fd3d4ad4c6b51fa5c54c3550756056723.tar.gz rneovim-984f7a9fd3d4ad4c6b51fa5c54c3550756056723.tar.bz2 rneovim-984f7a9fd3d4ad4c6b51fa5c54c3550756056723.zip |
vim-patch:9.0.0245: mechanism to prevent recursive screen updating is incomplete (#27448)
Problem: Mechanism to prevent recursive screen updating is incomplete.
Solution: Add "redraw_not_allowed" and set it in build_stl_str_hl().
(issue vim/vim#10952)
https://github.com/vim/vim/commit/471c0fa3eed4f6207d1cb7636970547bfd2eee26
Co-authored-by: Bram Moolenaar <Bram@vim.org>
-rw-r--r-- | src/nvim/change.c | 6 | ||||
-rw-r--r-- | src/nvim/drawscreen.c | 15 | ||||
-rw-r--r-- | src/nvim/drawscreen.h | 4 | ||||
-rw-r--r-- | src/nvim/ex_getln.c | 4 | ||||
-rw-r--r-- | src/nvim/message.c | 8 | ||||
-rw-r--r-- | src/nvim/statusline.c | 25 | ||||
-rw-r--r-- | src/nvim/winfloat.c | 2 |
7 files changed, 33 insertions, 31 deletions
diff --git a/src/nvim/change.c b/src/nvim/change.c index 2db3d007d7..a7c885bf4d 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -322,7 +322,7 @@ static void changed_common(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnum FOR_ALL_TAB_WINDOWS(tp, wp) { if (wp->w_buffer == buf) { // Mark this window to be redrawn later. - if (wp->w_redr_type < UPD_VALID) { + if (!redraw_not_allowed && wp->w_redr_type < UPD_VALID) { wp->w_redr_type = UPD_VALID; } @@ -390,9 +390,7 @@ static void changed_common(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnum // Call update_screen() later, which checks out what needs to be redrawn, // since it notices b_mod_set and then uses b_mod_*. - if (must_redraw < UPD_VALID) { - must_redraw = UPD_VALID; - } + set_must_redraw(UPD_VALID); // when the cursor line is changed always trigger CursorMoved if (last_cursormoved_win == curwin && curwin->w_buffer == buf diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c index 4df01d9476..7e1a453497 100644 --- a/src/nvim/drawscreen.c +++ b/src/nvim/drawscreen.c @@ -2647,7 +2647,7 @@ void redraw_later(win_T *wp, int type) { // curwin may have been set to NULL when exiting assert(wp != NULL || exiting); - if (!exiting && wp->w_redr_type < type) { + if (!exiting && !redraw_not_allowed && wp->w_redr_type < type) { wp->w_redr_type = type; if (type >= UPD_NOT_VALID) { wp->w_lines_valid = 0; @@ -2665,7 +2665,14 @@ void redraw_all_later(int type) redraw_later(wp, type); } // This may be needed when switching tabs. - if (must_redraw < type) { + set_must_redraw(type); +} + +/// Set "must_redraw" to "type" unless it already has a higher value +/// or it is currently not allowed. +void set_must_redraw(int type) +{ + if (!redraw_not_allowed && must_redraw < type) { must_redraw = type; } } @@ -2730,9 +2737,7 @@ void redraw_buf_status_later(buf_T *buf) || (wp == curwin && global_stl_height()) || wp->w_winbar_height)) { wp->w_redr_status = true; - if (must_redraw < UPD_VALID) { - must_redraw = UPD_VALID; - } + set_must_redraw(UPD_VALID); } } } diff --git a/src/nvim/drawscreen.h b/src/nvim/drawscreen.h index 1f6f41fae2..f804345bca 100644 --- a/src/nvim/drawscreen.h +++ b/src/nvim/drawscreen.h @@ -21,6 +21,10 @@ enum { /// ('lines' and 'rows') must not be changed. EXTERN bool updating_screen INIT( = false); +/// While computing a statusline and the like we do not want any w_redr_type or +/// must_redraw to be set. +EXTERN bool redraw_not_allowed INIT( = false); + EXTERN match_T screen_search_hl INIT( = { 0 }); ///< used for 'hlsearch' highlight matching #define W_ENDCOL(wp) ((wp)->w_wincol + (wp)->w_width) diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 307fd480cc..8af5730ffe 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -902,9 +902,7 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear // not get printed in the middle of it. msg_check(); if (p_ch == 0 && !ui_has(kUIMessages)) { - if (must_redraw < UPD_VALID) { - must_redraw = UPD_VALID; - } + set_must_redraw(UPD_VALID); } msg_scroll = s->save_msg_scroll; redir_off = false; diff --git a/src/nvim/message.c b/src/nvim/message.c index d879fa1423..b4e1d61cc7 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -2419,9 +2419,7 @@ static void inc_msg_scrolled(void) xfree(tofree); } msg_scrolled++; - if (must_redraw < UPD_VALID) { - must_redraw = UPD_VALID; - } + set_must_redraw(UPD_VALID); } static msgchunk_T *last_msgchunk = NULL; // last displayed text @@ -3067,9 +3065,7 @@ void msg_ext_clear_later(void) { if (msg_ext_is_visible()) { msg_ext_need_clear = true; - if (must_redraw < UPD_VALID) { - must_redraw = UPD_VALID; - } + set_must_redraw(UPD_VALID); } } diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c index 0a716067c6..b403f840ca 100644 --- a/src/nvim/statusline.c +++ b/src/nvim/statusline.c @@ -935,14 +935,20 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op char buf_tmp[TMPLEN]; char win_tmp[TMPLEN]; char *usefmt = fmt; - const int save_must_redraw = must_redraw; - const int save_redr_type = curwin->w_redr_type; + const bool save_redraw_not_allowed = redraw_not_allowed; const bool save_KeyTyped = KeyTyped; // TODO(Bram): find out why using called_emsg_before makes tests fail, does it // matter? // const int called_emsg_before = called_emsg; const int did_emsg_before = did_emsg; + // When inside update_screen() we do not want redrawing a statusline, + // ruler, title, etc. to trigger another redraw, it may cause an endless + // loop. + if (updating_screen) { + redraw_not_allowed = true; + } + if (stl_items == NULL) { stl_items = xmalloc(sizeof(stl_item_t) * stl_items_len); stl_groupitems = xmalloc(sizeof(int) * stl_items_len); @@ -1938,16 +1944,16 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op stl_items[curitem].type = Empty; } + if (num >= 0 || (!itemisflag && str && *str)) { + prevchar_isflag = false; // Item not NULL, but not a flag + } + // Only free the string buffer if we allocated it. // Note: This is not needed if `str` is pointing at `tmp` if (opt == STL_VIM_EXPR) { XFREE_CLEAR(str); } - if (num >= 0 || (!itemisflag && str && *str)) { - prevchar_isflag = false; // Item not NULL, but not a flag - } - // Item processed, move to the next curitem++; } @@ -2172,12 +2178,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op cur_tab_rec->def.func = NULL; } - // When inside update_screen we do not want redrawing a statusline, ruler, - // title, etc. to trigger another redraw, it may cause an endless loop. - if (updating_screen) { - must_redraw = save_must_redraw; - curwin->w_redr_type = save_redr_type; - } + redraw_not_allowed = save_redraw_not_allowed; // Check for an error. If there is one the display will be messed up and // might loop redrawing. Avoid that by making the corresponding option diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c index 83a04a1bcf..8fe0315230 100644 --- a/src/nvim/winfloat.c +++ b/src/nvim/winfloat.c @@ -184,7 +184,7 @@ void win_config_float(win_T *wp, WinConfig fconfig) } win_set_inner_size(wp, true); - must_redraw = MAX(must_redraw, UPD_VALID); + set_must_redraw(UPD_VALID); wp->w_pos_changed = true; if (change_external || change_border) { |