aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/extmark.c2
-rw-r--r--src/nvim/decoration.c22
-rw-r--r--src/nvim/decoration.h2
-rw-r--r--src/nvim/drawline.c8
-rw-r--r--src/nvim/drawscreen.c2
-rw-r--r--src/nvim/extmark.c20
-rw-r--r--src/nvim/marktree.c14
-rw-r--r--src/nvim/marktree.h17
-rw-r--r--src/nvim/spell.c6
9 files changed, 53 insertions, 40 deletions
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index 9e03cc8676..adc2925b7e 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -793,7 +793,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
// TODO(bfredl): synergize these two branches even more
- if (ephemeral && decor_state.buf == buf) {
+ if (ephemeral && decor_state.win && decor_state.win->w_buffer == buf) {
decor_add_ephemeral((int)line, (int)col, line2, col2, &decor, (uint64_t)ns_id, id);
} else {
if (ephemeral) {
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 7e47565247..217544175d 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -166,10 +166,10 @@ next_mark:
return NULL;
}
-bool decor_redraw_reset(buf_T *buf, DecorState *state)
+bool decor_redraw_reset(win_T *wp, DecorState *state)
{
state->row = -1;
- state->buf = buf;
+ state->win = wp;
for (size_t i = 0; i < kv_size(state->active); i++) {
DecorRange item = kv_A(state->active, i);
if (item.virt_text_owned) {
@@ -177,7 +177,7 @@ bool decor_redraw_reset(buf_T *buf, DecorState *state)
}
}
kv_size(state->active) = 0;
- return buf->b_marktree->n_keys;
+ return wp->w_buffer->b_marktree->n_keys;
}
Decoration get_decor(mtkey_t mark)
@@ -198,8 +198,9 @@ static bool decor_virt_pos(Decoration decor)
return kv_size(decor.virt_text) || decor.ui_watched;
}
-bool decor_redraw_start(buf_T *buf, int top_row, DecorState *state)
+bool decor_redraw_start(win_T *wp, int top_row, DecorState *state)
{
+ buf_T *buf = wp->w_buffer;
state->top_row = top_row;
marktree_itr_get(buf->b_marktree, top_row, 0, state->itr);
if (!state->itr->node) {
@@ -250,10 +251,10 @@ next_mark:
return true; // TODO(bfredl): check if available in the region
}
-bool decor_redraw_line(buf_T *buf, int row, DecorState *state)
+bool decor_redraw_line(win_T *wp, int row, DecorState *state)
{
if (state->row == -1) {
- decor_redraw_start(buf, row, state);
+ decor_redraw_start(wp, row, state);
}
state->row = row;
state->col_until = -1;
@@ -282,8 +283,9 @@ static void decor_add(DecorState *state, int start_row, int start_col, int end_r
kv_A(state->active, index) = range;
}
-int decor_redraw_col(buf_T *buf, int col, int win_col, bool hidden, DecorState *state)
+int decor_redraw_col(win_T *wp, int col, int win_col, bool hidden, DecorState *state)
{
+ buf_T *buf = wp->w_buffer;
if (col <= state->col_until) {
return state->current;
}
@@ -529,12 +531,12 @@ next_mark:
void decor_redraw_end(DecorState *state)
{
- state->buf = NULL;
+ state->win = NULL;
}
-bool decor_redraw_eol(buf_T *buf, DecorState *state, int *eol_attr, int eol_col)
+bool decor_redraw_eol(win_T *wp, DecorState *state, int *eol_attr, int eol_col)
{
- decor_redraw_col(buf, MAXCOL, MAXCOL, false, state);
+ decor_redraw_col(wp, MAXCOL, MAXCOL, false, state);
state->eol_col = eol_col;
bool has_virttext = false;
for (size_t i = 0; i < kv_size(state->active); i++) {
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h
index c9ec8ede7f..f43002521c 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -88,7 +88,7 @@ typedef struct {
typedef struct {
MarkTreeIter itr[1];
kvec_t(DecorRange) active;
- buf_T *buf;
+ win_T *win;
int top_row;
int row;
int col_until;
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index d9a8c6a6d9..6d8cf1c7e1 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -1096,7 +1096,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
}
}
- has_decor = decor_redraw_line(buf, lnum - 1, &decor_state);
+ has_decor = decor_redraw_line(wp, lnum - 1, &decor_state);
decor_providers_invoke_line(wp, providers, lnum - 1, &has_decor, provider_err);
@@ -1619,7 +1619,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
wlv.draw_state = WL_LINE;
if (has_decor && wlv.row == startrow + wlv.filler_lines) {
// hide virt_text on text hidden by 'nowrap'
- decor_redraw_col(wp->w_buffer, wlv.vcol, wlv.off, true, &decor_state);
+ decor_redraw_col(wp, wlv.vcol, wlv.off, true, &decor_state);
}
win_line_continue(&wlv); // use wlv.saved_ values
}
@@ -2011,7 +2011,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
if (has_decor && v > 0) {
bool selected = (area_active || (area_highlighting && noinvcur
&& wlv.vcol == wp->w_virtcol));
- int extmark_attr = decor_redraw_col(wp->w_buffer, (colnr_T)v - 1, wlv.off,
+ int extmark_attr = decor_redraw_col(wp, (colnr_T)v - 1, wlv.off,
selected, &decor_state);
if (extmark_attr != 0) {
if (!attr_pri) {
@@ -2615,7 +2615,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange,
? 1 : 0);
if (has_decor) {
- has_virttext = decor_redraw_eol(wp->w_buffer, &decor_state, &wlv.line_attr,
+ has_virttext = decor_redraw_eol(wp, &decor_state, &wlv.line_attr,
wlv.col + eol_skip);
}
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index f456947f5a..499f4a39e3 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -1427,7 +1427,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
win_extmark_arr.size = 0;
- decor_redraw_reset(buf, &decor_state);
+ decor_redraw_reset(wp, &decor_state);
DecorProviders line_providers;
decor_providers_invoke_win(wp, providers, &line_providers, &provider_err);
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index 1132a5e752..d385a2018f 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -92,7 +92,7 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
extmark_del(buf, ns_id, id);
} else {
// TODO(bfredl): we need to do more if "revising" a decoration mark.
- assert(itr->node);
+ assert(marktree_itr_valid(itr));
if (old_mark.pos.row == row && old_mark.pos.col == col) {
if (marktree_decor_level(old_mark) > kDecorLevelNone) {
decor_remove(buf, row, row, old_mark.decor_full);
@@ -191,12 +191,12 @@ bool extmark_del(buf_T *buf, uint32_t ns_id, uint32_t id)
return false;
}
assert(key.pos.row >= 0);
- marktree_del_itr(buf->b_marktree, itr, false);
+ uint64_t other = marktree_del_itr(buf->b_marktree, itr, false);
mtkey_t key2 = key;
- if (mt_paired(key)) {
- key2 = marktree_lookup_ns(buf->b_marktree, ns_id, id, true, itr);
+ if (other) {
+ key2 = marktree_lookup(buf->b_marktree, other, itr);
assert(key2.pos.row >= 0);
marktree_del_itr(buf->b_marktree, itr, false);
}
@@ -258,8 +258,11 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
assert(mark.ns > 0 && mark.id > 0);
if (mark.ns == ns_id || all_ns) {
marks_cleared = true;
+ if (mark.decor_full && !mt_paired(mark)) { // if paired: deal with it later
+ decor_remove(buf, mark.pos.row, mark.pos.row, mark.decor_full);
+ }
+ uint64_t other = marktree_del_itr(buf->b_marktree, itr, false);
if (mt_paired(mark)) {
- uint64_t other = mt_lookup_id(mark.ns, mark.id, !mt_end(mark));
ssize_t decor_id = -1;
if (marktree_decor_level(mark) > kDecorLevelNone) {
// Save the decoration and the first pos. Clear the decoration
@@ -269,10 +272,7 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
((DecorItem) { .row1 = mark.pos.row }));
}
map_put(uint64_t, ssize_t)(&delete_set, other, decor_id);
- } else if (mark.decor_full) {
- decor_remove(buf, mark.pos.row, mark.pos.row, mark.decor_full);
}
- marktree_del_itr(buf->b_marktree, itr, false);
} else {
marktree_itr_next(buf->b_marktree, itr);
}
@@ -281,7 +281,7 @@ bool extmark_clear(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_col, int u_r
ssize_t decor_id;
map_foreach(&delete_set, id, decor_id, {
mtkey_t mark = marktree_lookup(buf->b_marktree, id, itr);
- assert(itr->node);
+ assert(marktree_itr_valid(itr));
marktree_del_itr(buf->b_marktree, itr, false);
if (decor_id >= 0) {
DecorItem it = kv_A(decors, decor_id);
@@ -306,7 +306,7 @@ ExtmarkInfoArray extmark_get(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_co
ExtmarkInfoArray array = KV_INITIAL_VALUE;
MarkTreeIter itr[1];
// Find all the marks
- marktree_itr_get_ext(buf->b_marktree, (mtpos_t){ l_row, l_col },
+ marktree_itr_get_ext(buf->b_marktree, mtpos_t(l_row, l_col),
itr, reverse, false, NULL);
int order = reverse ? -1 : 1;
while ((int64_t)kv_size(array) < amount) {
diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c
index cb981bb00c..7e900bafa2 100644
--- a/src/nvim/marktree.c
+++ b/src/nvim/marktree.c
@@ -279,13 +279,13 @@ void marktree_put_key(MarkTree *b, mtkey_t k)
/// 6. If 4 went all the way to the root node. The root node
/// might have ended up with size 0. Delete it then.
///
-/// NB: ideally keeps the iterator valid. Like point to the key after this
-/// if present.
+/// The iterator remains valid, and now points at the key _after_ the deleted
+/// one.
///
/// @param rev should be true if we plan to iterate _backwards_ and delete
/// stuff before this key. Most of the time this is false (the
/// recommended strategy is to always iterate forward)
-void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
+uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
{
int adjustment = 0;
@@ -294,6 +294,12 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
uint64_t id = mt_lookup_key(cur->key[curi]);
// fprintf(stderr, "\nDELET %lu\n", id);
+ mtkey_t raw = rawkey(itr);
+ uint64_t other = 0;
+ if (mt_paired(raw)) {
+ other = mt_lookup_id(raw.ns, raw.id, !mt_end(raw));
+ }
+
if (itr->node->level) {
if (rev) {
abort();
@@ -442,6 +448,8 @@ void marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
marktree_itr_next(b, itr);
}
}
+
+ return other;
}
static mtnode_t *merge_node(MarkTree *b, mtnode_t *p, int i)
diff --git a/src/nvim/marktree.h b/src/nvim/marktree.h
index 5ce4b2cd24..046946bc95 100644
--- a/src/nvim/marktree.h
+++ b/src/nvim/marktree.h
@@ -22,21 +22,26 @@ typedef struct {
int32_t row;
int32_t col;
} mtpos_t;
+#define mtpos_t(r, c) ((mtpos_t){ .row = (r), .col = (c) })
typedef struct mtnode_s mtnode_t;
-typedef struct {
- int oldcol;
- int i;
-} iterstate_t;
typedef struct {
mtpos_t pos;
int lvl;
mtnode_t *node;
int i;
- iterstate_t s[MT_MAX_DEPTH];
+ struct {
+ int oldcol;
+ int i;
+ } s[MT_MAX_DEPTH];
+
+ size_t intersect_idx;
+ mtpos_t intersect_pos;
} MarkTreeIter;
+#define marktree_itr_valid(itr) ((itr)->node != NULL)
+
// Internal storage
//
// NB: actual marks have flags > 0, so we can use (row,col,0) pseudo-key for
@@ -123,8 +128,6 @@ struct mtnode_s {
mtnode_t *ptr[];
};
-// TODO(bfredl): the iterator is pretty much everpresent, make it part of the
-// tree struct itself?
typedef struct {
mtnode_t *root;
size_t n_keys, n_nodes;
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index b514ed694d..c65f822080 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -1203,7 +1203,7 @@ bool no_spell_checking(win_T *wp)
static void decor_spell_nav_start(win_T *wp)
{
decor_state = (DecorState){ 0 };
- decor_redraw_reset(wp->w_buffer, &decor_state);
+ decor_redraw_reset(wp, &decor_state);
}
static bool decor_spell_nav_col(win_T *wp, linenr_T lnum, linenr_T *decor_lnum, int col,
@@ -1211,10 +1211,10 @@ static bool decor_spell_nav_col(win_T *wp, linenr_T lnum, linenr_T *decor_lnum,
{
if (*decor_lnum != lnum) {
decor_providers_invoke_spell(wp, lnum - 1, col, lnum - 1, -1, decor_error);
- decor_redraw_line(wp->w_buffer, lnum - 1, &decor_state);
+ decor_redraw_line(wp, lnum - 1, &decor_state);
*decor_lnum = lnum;
}
- decor_redraw_col(wp->w_buffer, col, col, false, &decor_state);
+ decor_redraw_col(wp, col, col, false, &decor_state);
return decor_state.spell == kTrue;
}