diff options
Diffstat (limited to 'src/nvim/buffer.c')
-rw-r--r-- | src/nvim/buffer.c | 51 |
1 files changed, 32 insertions, 19 deletions
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 8491e77e73..580eb07d6b 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -74,6 +74,12 @@ #include "nvim/os/time.h" #include "nvim/os/input.h" +typedef enum { + kBLSUnchanged = 0, + kBLSChanged = 1, + kBLSDeleted = 2, +} BufhlLineStatus; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "buffer.c.generated.h" #endif @@ -5228,21 +5234,21 @@ void bufhl_clear_line_range(buf_T *buf, return; } linenr_T first_changed = MAXLNUM, last_changed = -1; - // TODO: implement kb_itr_interval and jump directly to the first line + kbitr_t itr; - BufhlLine *l; - for (kb_itr_first(bufhl, buf->b_bufhl_info, &itr); - kb_itr_valid(&itr); - kb_itr_next(bufhl, buf->b_bufhl_info, &itr)) { + BufhlLine *l, t = {line_start}; + if (!kb_itr_get(bufhl, buf->b_bufhl_info, &t, &itr)) { + kb_itr_next(bufhl, buf->b_bufhl_info, &itr); + } + for (; kb_itr_valid(&itr); kb_itr_next(bufhl, buf->b_bufhl_info, &itr)) { l = kb_itr_key(BufhlLine *, &itr); linenr_T line = l->line; - if (line < line_start) { - continue; - } else if (line > line_end) { + if (line > line_end) { break; } if (line_start <= line && line <= line_end) { - if (bufhl_clear_line(buf->b_bufhl_info, src_id, line)) { + BufhlLineStatus status = bufhl_clear_line(buf->b_bufhl_info, src_id, line); + if (status != kBLSUnchanged) { if (line > last_changed) { last_changed = line; } @@ -5250,6 +5256,9 @@ void bufhl_clear_line_range(buf_T *buf, first_changed = line; } } + if (status == kBLSDeleted) { + kb_del_itr(bufhl, buf->b_bufhl_info, &itr); + } } } @@ -5264,8 +5273,8 @@ void bufhl_clear_line_range(buf_T *buf, /// @param bufhl_info The highlight info for the buffer /// @param src_id Highlight source group to clear, or -1 to clear all groups. /// @param lnum Linenr where the highlight should be cleared -static bool bufhl_clear_line(bufhl_info_T *bufhl_info, int src_id, - linenr_T lnum) +static BufhlLineStatus bufhl_clear_line(bufhl_info_T *bufhl_info, int src_id, + linenr_T lnum) { BufhlLine *lineinfo = bufhl_tree_ref(bufhl_info, lnum, false); size_t oldsize = kv_size(lineinfo->items); @@ -5286,9 +5295,9 @@ static bool bufhl_clear_line(bufhl_info_T *bufhl_info, int src_id, if (kv_size(lineinfo->items) == 0) { kv_destroy(lineinfo->items); - kb_del(bufhl, bufhl_info, lineinfo); + return kBLSDeleted; } - return kv_size(lineinfo->items) != oldsize; + return kv_size(lineinfo->items) != oldsize ? kBLSChanged : kBLSUnchanged; } /// Remove all highlights and free the highlight data @@ -5315,15 +5324,19 @@ void bufhl_mark_adjust(buf_T* buf, // we need to detect this case and kbitr_t itr; - BufhlLine *l; - for (kb_itr_first(bufhl, buf->b_bufhl_info, &itr); - kb_itr_valid(&itr); - kb_itr_next(bufhl, buf->b_bufhl_info, &itr)) { + BufhlLine *l, t = {line1}; + if (!kb_itr_get(bufhl, buf->b_bufhl_info, &t, &itr)) { + kb_itr_next(bufhl, buf->b_bufhl_info, &itr); + } + for (; kb_itr_valid(&itr); kb_itr_next(bufhl, buf->b_bufhl_info, &itr)) { l = kb_itr_key(BufhlLine *, &itr); if (l->line >= line1 && l->line <= line2) { if (amount == MAXLNUM) { - bufhl_clear_line(buf->b_bufhl_info, -1, l->line); - continue; + if (bufhl_clear_line(buf->b_bufhl_info, -1, l->line) == kBLSDeleted) { + kb_del_itr(bufhl, buf->b_bufhl_info, &itr); + } else { + assert(false); + } } else { l->line += amount; } |