aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/drawscreen.c
diff options
context:
space:
mode:
authorLuuk van Baal <luukvbaal@gmail.com>2024-01-11 14:30:12 +0100
committerLewis Russell <me@lewisr.dev>2024-01-15 09:37:53 +0000
commit967c7abde3c6fa3210a4920a5848a54dc913d851 (patch)
treea44518ccfcfab9a0011f05f62aa0be543fd8a3e2 /src/nvim/drawscreen.c
parent4d91604c8868b7afaf429cc16b72192ce89ea698 (diff)
downloadrneovim-967c7abde3c6fa3210a4920a5848a54dc913d851.tar.gz
rneovim-967c7abde3c6fa3210a4920a5848a54dc913d851.tar.bz2
rneovim-967c7abde3c6fa3210a4920a5848a54dc913d851.zip
fix(column): keep track of number of lines with number of signs
Problem: Some edge cases to the old (pre-#26406) and current "b_signcols" structure result in an incorrectly sized "auto" 'signcolumn'. Solution: * Implement a simpler 'signcolumn' validation strategy by immediately counting the number of signs in a range upon sign insertion and deletion. Decrease in performance here but there is a clear path forward to decreasing this performance hit by moving signs to a dedicated marktree, or by adding meta-data to the existing marktree which may be queried more efficiently? * Also replace "max_count" and keep track of the number of lines with a certain number of signs. This makes it so that it is no longer necessary to scan the entire buffer when the maximum number of signs decreases. This likely makes the commit a net increase in performance. * To ensure correctness we also have re-initialize the count for an edited region that spans multiple lines. Such an edit may move the signs within it. Thus we count and decrement before splicing the marktree and count and increment after.
Diffstat (limited to 'src/nvim/drawscreen.c')
-rw-r--r--src/nvim/drawscreen.c35
1 files changed, 19 insertions, 16 deletions
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index 7f794a58d2..b49de19349 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -1201,27 +1201,30 @@ void comp_col(void)
/// Redraw entire window "wp" if configured 'signcolumn' width changes.
static bool win_redraw_signcols(win_T *wp)
{
- int width;
- bool rebuild_stc = false;
buf_T *buf = wp->w_buffer;
- if (wp->w_minscwidth <= SCL_NO) {
- if (*wp->w_p_stc) {
- buf_signcols_validate(wp, buf, true);
- if (buf->b_signcols.resized) {
- rebuild_stc = true;
- wp->w_nrwidth_line_count = 0;
- }
- }
- width = 0;
- } else if (wp->w_maxscwidth <= 1 && buf->b_signs_with_text >= (size_t)wp->w_maxscwidth) {
- width = wp->w_maxscwidth;
- } else {
- width = MIN(wp->w_maxscwidth, buf_signcols_validate(wp, buf, false));
+ if (!buf->b_signcols.autom
+ && (*wp->w_p_stc != NUL || (wp->w_maxscwidth > 1 && wp->w_minscwidth != wp->w_maxscwidth))) {
+ buf->b_signcols.autom = true;
+ buf_signcols_count_range(buf, 0, buf->b_ml.ml_line_count, MAXLNUM, kNone);
+ }
+
+ while (buf->b_signcols.max > 0 && buf->b_signcols.count[buf->b_signcols.max - 1] == 0) {
+ buf->b_signcols.resized = true;
+ buf->b_signcols.max--;
+ }
+
+ int width = MIN(wp->w_maxscwidth, buf->b_signcols.max);
+ bool rebuild_stc = buf->b_signcols.resized && *wp->w_p_stc != NUL;
+
+ if (rebuild_stc) {
+ wp->w_nrwidth_line_count = 0;
+ } else if (wp->w_minscwidth == 0 && wp->w_maxscwidth == 1) {
+ width = buf->b_signs_with_text > 0;
}
int scwidth = wp->w_scwidth;
- wp->w_scwidth = MAX(wp->w_minscwidth, width);
+ wp->w_scwidth = MAX(MAX(0, wp->w_minscwidth), width);
return (wp->w_scwidth != scwidth || rebuild_stc);
}