aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2024-02-13 06:30:35 +0800
committerGitHub <noreply@github.com>2024-02-13 06:30:35 +0800
commit984f7a9fd3d4ad4c6b51fa5c54c3550756056723 (patch)
tree222b8b0d6a5bd074394abe2b0d108aa46d61a9e6
parent84b6ade41510ffad7d712abe2b010e4027b7033c (diff)
downloadrneovim-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.c6
-rw-r--r--src/nvim/drawscreen.c15
-rw-r--r--src/nvim/drawscreen.h4
-rw-r--r--src/nvim/ex_getln.c4
-rw-r--r--src/nvim/message.c8
-rw-r--r--src/nvim/statusline.c25
-rw-r--r--src/nvim/winfloat.c2
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) {