diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/api/extmark.c | 2 | ||||
-rw-r--r-- | src/nvim/decoration.c | 22 | ||||
-rw-r--r-- | src/nvim/decoration.h | 2 | ||||
-rw-r--r-- | src/nvim/drawline.c | 8 | ||||
-rw-r--r-- | src/nvim/drawscreen.c | 2 | ||||
-rw-r--r-- | src/nvim/extmark.c | 20 | ||||
-rw-r--r-- | src/nvim/marktree.c | 14 | ||||
-rw-r--r-- | src/nvim/marktree.h | 17 | ||||
-rw-r--r-- | src/nvim/spell.c | 6 |
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; } |