bufhl: use extmark column adjustment for bufhl

NB: this is not the final implementation. Bufhl should be made a
part of the extmark tree, so that "start" adjustment just works
automatically. But "stop" will still need some ad-hoc trickery,
until extended marks natively support ranges (hopefully sooner than
forever).
This commit is contained in:
Björn Linse
2018-06-29 13:35:42 +02:00
parent d5f14b8372
commit bdebe8516c
4 changed files with 241 additions and 1 deletions

View File

@@ -5626,6 +5626,86 @@ void bufhl_mark_adjust(buf_T* buf,
}
}
/// Adjust a placed highlight for column changes and joined/broken lines
bool bufhl_mark_col_adjust(buf_T *buf,
linenr_T lnum,
colnr_T mincol,
long lnum_amount,
long col_amount)
{
bool moved = false;
BufhlLine *lineinfo = bufhl_tree_ref(&buf->b_bufhl_info, lnum, false);
if (!lineinfo) {
// Old line empty, nothing to do
return false;
}
// Create the new line below only if needed
BufhlLine *lineinfo2 = NULL;
colnr_T delcol = MAXCOL;
if (lnum_amount == 0 && col_amount < 0) {
delcol = mincol+(int)col_amount;
}
size_t newidx = 0;
for (size_t i = 0; i < kv_size(lineinfo->items); i++) {
BufhlItem *item = &kv_A(lineinfo->items, i);
bool delete = false;
if (item->start >= mincol) {
moved = true;
item->start += (int)col_amount;
if (item->stop < MAXCOL) {
item->stop += (int)col_amount;
}
if (lnum_amount != 0) {
if (lineinfo2 == NULL) {
lineinfo2 = bufhl_tree_ref(&buf->b_bufhl_info,
lnum+lnum_amount, true);
}
kv_push(lineinfo2->items, *item);
delete = true;
}
} else {
if (item->start >= delcol) {
moved = true;
item->start = delcol;
}
if (item->stop == MAXCOL || item->stop+1 >= mincol) {
if (item->stop == MAXCOL) {
if (delcol < MAXCOL
&& delcol > (colnr_T)STRLEN(ml_get_buf(buf, lnum, false))) {
delete = true;
}
} else {
moved = true;
item->stop += (int)col_amount;
}
assert(lnum_amount >= 0);
if (lnum_amount > 0) {
item->stop = MAXCOL;
}
} else if (item->stop+1 >= delcol) {
moved = true;
item->stop = delcol-1;
}
// we covered the entire range with a visual delete or something
if (item->stop < item->start) {
delete = true;
}
}
if (!delete) {
if (i != newidx) {
kv_A(lineinfo->items, newidx) = kv_A(lineinfo->items, i);
}
newidx++;
}
}
kv_size(lineinfo->items) = newidx;
return moved;
}
/// Get highlights to display at a specific line
///