kbtree: allow iterators to start at arbitrary position

This commit is contained in:
Björn Linse
2016-07-29 20:27:50 +02:00
parent 1eff241ec6
commit 6712e08bba
3 changed files with 83 additions and 23 deletions

View File

@@ -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;
}