patch 9.2.0311: redrawing logic with text properties can be improved
Commit:
https://github.com/vim/vim/commit/c4921023b1234e6c31cc748c6ff13e1cdd7912b1
Author: Yasuhiro Matsumoto <[email protected]>
Date: Mon Apr 6 13:19:04 2026 +0000
patch 9.2.0311: redrawing logic with text properties can be improved
Problem: redrawing logic with text properties can be improved in
win_line()
Solution: Avoid repeated sorts, use stack storage for small
properties, pre-compute whether trailing virtual text follows
(Yasuhiro Matsumoto)
closes: #19880
Signed-off-by: Yasuhiro Matsumoto <[email protected]>
Signed-off-by: Christian Brabandt <[email protected]>
diff --git a/src/drawline.c b/src/drawline.c
index e42044256..f3a3b1671 100644
--- a/src/drawline.c
+++ b/src/drawline.c
@@ -1213,13 +1213,19 @@ win_line(
int save_did_emsg;
#endif
#ifdef FEAT_PROP_POPUP
+# define WIN_LINE_TEXT_PROP_STACK_LEN 32
int did_line = FALSE; // set to TRUE when line text
done
int text_prop_count;
int last_textprop_text_idx = -1;
int text_prop_next = 0; // next text property to use
+ textprop_T text_props_buf[WIN_LINE_TEXT_PROP_STACK_LEN];
+ int text_prop_idxs_buf[WIN_LINE_TEXT_PROP_STACK_LEN];
+ char_u text_prop_suffix_flags_buf[WIN_LINE_TEXT_PROP_STACK_LEN + 1];
textprop_T *text_props = NULL;
int *text_prop_idxs = NULL;
+ char_u *text_prop_suffix_flags = NULL;
int text_props_active = 0;
+ int text_props_need_sort = FALSE;
proptype_T *text_prop_type = NULL;
int text_prop_attr = 0;
int text_prop_attr_comb = 0; // text_prop_attr combined
with
@@ -1694,15 +1700,40 @@ win_line(
{
// Make a copy of the properties, so that they are properly
// aligned.
- text_props = ALLOC_MULT(textprop_T, text_prop_count);
+ if (text_prop_count <= WIN_LINE_TEXT_PROP_STACK_LEN)
+ text_props = text_props_buf;
+ else
+ text_props = ALLOC_MULT(textprop_T, text_prop_count);
if (text_props != NULL)
mch_memmove(text_props, prop_start,
text_prop_count * sizeof(textprop_T));
// Allocate an array for the indexes.
- text_prop_idxs = ALLOC_MULT(int, text_prop_count);
+ if (text_prop_count <= WIN_LINE_TEXT_PROP_STACK_LEN)
+ text_prop_idxs = text_prop_idxs_buf;
+ else
+ text_prop_idxs = ALLOC_MULT(int, text_prop_count);
if (text_prop_idxs == NULL)
- VIM_CLEAR(text_props);
+ {
+ if (text_props != text_props_buf)
+ VIM_CLEAR(text_props);
+ else
+ text_props = NULL;
+ }
+ if (text_prop_count <= WIN_LINE_TEXT_PROP_STACK_LEN)
+ text_prop_suffix_flags = text_prop_suffix_flags_buf;
+ else
+ text_prop_suffix_flags = ALLOC_MULT(char_u, text_prop_count + 1);
+ if (text_prop_suffix_flags == NULL)
+ {
+ if (text_prop_idxs != text_prop_idxs_buf)
+ vim_free(text_prop_idxs);
+ text_prop_idxs = NULL;
+ if (text_props != text_props_buf)
+ VIM_CLEAR(text_props);
+ else
+ text_props = NULL;
+ }
if (text_props != NULL)
{
@@ -1736,6 +1767,20 @@ win_line(
else
++wlv.text_prop_above_count;
}
+
+ text_prop_suffix_flags[text_prop_count] = 0;
+ for (int i = text_prop_count - 1; i >= 0; --i)
+ {
+ int flags = text_prop_suffix_flags[i + 1];
+
+ if (text_props[i].tp_col == MAXCOL)
+ {
+ flags |= 1;
+ if (text_props[i].tp_flags & TP_FLAG_ALIGN_BELOW)
+ flags |= 2;
+ }
+ text_prop_suffix_flags[i] = flags;
+ }
}
}
@@ -1745,8 +1790,12 @@ win_line(
wlv.row += wlv.text_prop_above_count;
if (wlv.row >= endrow)
{
- vim_free(text_props);
- vim_free(text_prop_idxs);
+ if (text_props != text_props_buf)
+ vim_free(text_props);
+ if (text_prop_idxs != text_prop_idxs_buf)
+ vim_free(text_prop_idxs);
+ if (text_prop_suffix_flags != text_prop_suffix_flags_buf)
+ vim_free(text_prop_suffix_flags);
return wlv.row;
}
wlv.screen_row += wlv.text_prop_above_count;
@@ -2122,6 +2171,7 @@ win_line(
sizeof(int)
* (text_props_active - (pi + 1)));
--text_props_active;
+ text_props_need_sort = TRUE;
--pi;
# ifdef FEAT_LINEBREAK
// not exactly right but should work in most cases
@@ -2164,7 +2214,10 @@ win_line(
}
if (active)
+ {
text_prop_idxs[text_props_active++] = text_prop_next;
+ text_props_need_sort = TRUE;
+ }
++text_prop_next;
}
@@ -2190,10 +2243,14 @@ win_line(
text_prop_above = FALSE;
text_prop_follows = FALSE;
- // Sort the properties on priority and/or starting last.
- // Then combine the attributes, highest priority last.
- sort_text_props(wp->w_buffer, text_props,
- text_prop_idxs, text_props_active);
+ if (text_props_need_sort)
+ {
+ // The active set only changes when a property starts
+ // or ends, so avoid sorting again for every column.
+ sort_text_props(wp->w_buffer, text_props,
+ text_prop_idxs, text_props_active);
+ text_props_need_sort = FALSE;
+ }
for (pi = 0; pi < text_props_active; ++pi)
{
@@ -2402,19 +2459,10 @@ win_line(
// Or when not wrapping and at the rightmost column.
int only_below_follows = !wp->w_p_wrap && wlv.col ==
wp->w_width - 1;
- // TODO: Store "after"/"right"/"below" text properties in
order
- // in the buffer so only `text_props[text_prop_count
- 1]`
- // needs to be checked for following "below" virtual
text
- for (int i = text_prop_next; i < text_prop_count; ++i)
- {
- if (text_props[i].tp_col == MAXCOL
- && (!only_below_follows
- || (text_props[i].tp_flags &
TP_FLAG_ALIGN_BELOW)))
- {
- text_prop_follows = TRUE;
- break;
- }
- }
+ int suffix_flags = text_prop_suffix_flags[text_prop_next];
+
+ text_prop_follows = (suffix_flags
+ & (only_below_follows ? 2 : 1)) != 0;
}
}
@@ -4500,8 +4548,12 @@ win_line(
} // for every character in the line
#ifdef FEAT_PROP_POPUP
- vim_free(text_props);
- vim_free(text_prop_idxs);
+ if (text_props != text_props_buf)
+ vim_free(text_props);
+ if (text_prop_idxs != text_prop_idxs_buf)
+ vim_free(text_prop_idxs);
+ if (text_prop_suffix_flags != text_prop_suffix_flags_buf)
+ vim_free(text_prop_suffix_flags);
vim_free(p_extra_free2);
#endif
diff --git a/src/version.c b/src/version.c
index ed4cf0ecf..57f688cfe 100644
--- a/src/version.c
+++ b/src/version.c
@@ -734,6 +734,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 311,
/**/
310,
/**/
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/vim_dev/E1w9k1j-006syV-7W%40256bit.org.