aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/vim.c7
-rw-r--r--src/nvim/buffer.c80
-rw-r--r--src/nvim/change.c24
-rw-r--r--src/nvim/edit.c14
-rw-r--r--src/nvim/mark_extended.c4
-rw-r--r--src/nvim/ops.c28
-rw-r--r--src/nvim/window.c6
7 files changed, 119 insertions, 44 deletions
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index 10f7dd1a7b..3535bc3186 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -1074,9 +1074,10 @@ fail:
/// float where the text should not be edited. Disables
/// 'number', 'relativenumber', 'cursorline', 'cursorcolumn',
/// 'foldcolumn', 'spell' and 'list' options. 'signcolumn'
-/// is changed to `auto`. The end-of-buffer region is hidden
-/// by setting `eob` flag of 'fillchars' to a space char,
-/// and clearing the |EndOfBuffer| region in 'winhighlight'.
+/// is changed to `auto` and 'colorcolumn' is cleared. The
+/// end-of-buffer region is hidden by setting `eob` flag of
+/// 'fillchars' to a space char, and clearing the
+/// |EndOfBuffer| region in 'winhighlight'.
/// @param[out] err Error details, if any
///
/// @return Window handle, or 0 on error
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 79f339b3aa..1244b8502c 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -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
///
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 7558055696..8a782c2b20 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -359,6 +359,24 @@ void changed_bytes(linenr_T lnum, colnr_T col)
}
}
+/// insert/delete bytes at column
+///
+/// Like changed_bytes() but also adjust extmark for "added" bytes.
+/// When "added" is negative text was deleted.
+static void inserted_bytes(linenr_T lnum, colnr_T col, int added)
+{
+ if (added > 0) {
+ extmark_col_adjust(curbuf, lnum, col+1, 0, added, kExtmarkUndo);
+ } else if (added < 0) {
+ // TODO(bfredl): next revision of extmarks should handle both these
+ // with the same entry point. Also with more sane params..
+ extmark_col_adjust_delete(curbuf, lnum, col+2,
+ col+(-added)+1, kExtmarkUndo, 0);
+ }
+
+ changed_bytes(lnum, col);
+}
+
/// Appended "count" lines below line "lnum" in the current buffer.
/// Must be called AFTER the change and after mark_adjust().
/// Takes care of marking the buffer to be redrawn and sets the changed flag.
@@ -630,7 +648,7 @@ void ins_char_bytes(char_u *buf, size_t charlen)
ml_replace(lnum, newp, false);
// mark the buffer as changed and prepare for displaying
- changed_bytes(lnum, (colnr_T)col);
+ inserted_bytes(lnum, (colnr_T)col, (int)(newlen - oldlen));
// If we're in Insert or Replace mode and 'showmatch' is set, then briefly
// show the match for right parens and braces.
@@ -676,7 +694,7 @@ void ins_str(char_u *s)
assert(bytes >= 0);
memmove(newp + col + newlen, oldp + col, (size_t)bytes);
ml_replace(lnum, newp, false);
- changed_bytes(lnum, col);
+ inserted_bytes(lnum, col, newlen);
curwin->w_cursor.col += newlen;
}
@@ -797,7 +815,7 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
}
// mark the buffer as changed and prepare for displaying
- changed_bytes(lnum, curwin->w_cursor.col);
+ inserted_bytes(lnum, col, -count);
return OK;
}
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index cd0f3f4b9d..eecea03a19 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -5600,9 +5600,6 @@ insertchar (
do_digraph(buf[i-1]); /* may be the start of a digraph */
buf[i] = NUL;
ins_str(buf);
- extmark_col_adjust(curbuf, curwin->w_cursor.lnum,
- (colnr_T)(curwin->w_cursor.col + 1), 0,
- (long)STRLEN(buf), kExtmarkUndo);
if (flags & INSCHAR_CTRLV) {
redo_literal(*buf);
i = 1;
@@ -5613,9 +5610,6 @@ insertchar (
} else {
int cc;
- extmark_col_adjust(curbuf, curwin->w_cursor.lnum,
- (colnr_T)(curwin->w_cursor.col + 1), 0,
- 1, kExtmarkUndo);
if ((cc = utf_char2len(c)) > 1) {
char_u buf[MB_MAXBYTES + 1];
@@ -8506,14 +8500,6 @@ static bool ins_tab(void)
temp -= get_nolist_virtcol() % temp;
- // Move extmarks
- extmark_col_adjust(curbuf,
- curwin->w_cursor.lnum,
- curwin->w_cursor.col,
- 0,
- temp,
- kExtmarkUndo);
-
/*
* Insert the first space with ins_char(). It will delete one char in
* replace mode. Insert the rest with ins_str(); it will not delete any
diff --git a/src/nvim/mark_extended.c b/src/nvim/mark_extended.c
index 01745f484d..91c2f919ce 100644
--- a/src/nvim/mark_extended.c
+++ b/src/nvim/mark_extended.c
@@ -910,6 +910,9 @@ void extmark_col_adjust(buf_T *buf, linenr_T lnum,
bool marks_moved = extmark_col_adjust_impl(buf, lnum, mincol, lnum_amount,
false, col_amount);
+ marks_moved |= bufhl_mark_col_adjust(buf, lnum, mincol,
+ lnum_amount, col_amount);
+
if (undo == kExtmarkUndo && marks_moved) {
u_extmark_col_adjust(buf, lnum, mincol, lnum_amount, col_amount);
}
@@ -938,6 +941,7 @@ void extmark_col_adjust_delete(buf_T *buf, linenr_T lnum,
marks_moved = extmark_col_adjust_impl(buf, lnum, mincol, 0,
true, (long)endcol);
+ marks_moved |= bufhl_mark_col_adjust(buf, lnum, endcol, 0, mincol-(endcol+1));
// Deletes at the end of the line have different behaviour than the normal
// case when deleted.
// Cleanup any marks that are floating beyond the end of line.
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 2301b2159f..f2d35d5e43 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -1644,8 +1644,6 @@ int op_delete(oparg_T *oap)
curwin->w_cursor.col = 0;
(void)del_bytes((colnr_T)n, !virtual_op,
oap->op_type == OP_DELETE && !oap->is_VIsual);
- extmark_col_adjust(curbuf, curwin->w_cursor.lnum,
- (colnr_T)0, 0L, (long)-n, kExtmarkUndo);
curwin->w_cursor = curpos; // restore curwin->w_cursor
(void)do_join(2, false, false, false, false);
}
@@ -1685,7 +1683,6 @@ setmarks:
if (oap->is_VIsual == false) {
endcol = MAX(endcol - 1, mincol);
}
- extmark_col_adjust_delete(curbuf, lnum, mincol, endcol, kExtmarkUndo, 0);
}
return OK;
}
@@ -2279,7 +2276,7 @@ void op_insert(oparg_T *oap, long count1)
colnr_T col = oap->start.col;
for (linenr_T lnum = oap->start.lnum; lnum <= oap->end.lnum; lnum++) {
extmark_col_adjust(curbuf, lnum, col, 0, 1, kExtmarkUndo);
- }
+ }
}
/*
@@ -4279,14 +4276,14 @@ format_lines(
if (next_leader_len > 0) {
(void)del_bytes(next_leader_len, false, false);
mark_col_adjust(curwin->w_cursor.lnum, (colnr_T)0, 0L,
- (long)-next_leader_len, 0, kExtmarkUndo);
+ (long)-next_leader_len, 0, kExtmarkNOOP);
} else if (second_indent > 0) { // the "leader" for FO_Q_SECOND
int indent = (int)getwhitecols_curline();
if (indent > 0) {
- (void)del_bytes(indent, FALSE, FALSE);
+ (void)del_bytes(indent, false, false);
mark_col_adjust(curwin->w_cursor.lnum,
- (colnr_T)0, 0L, (long)-indent, 0, kExtmarkUndo);
+ (colnr_T)0, 0L, (long)-indent, 0, kExtmarkNOOP);
}
}
curwin->w_cursor.lnum--;
@@ -4951,23 +4948,6 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
curbuf->b_op_end.col--;
}
- // if buf1 wasn't allocated, only a singe ASCII char was changed in-place.
- if (did_change && buf1 != NULL) {
- extmark_col_adjust_delete(curbuf,
- pos->lnum,
- startpos.col + 2,
- endpos.col + 1 + length,
- kExtmarkUndo,
- 0);
- long col_amount = (long)STRLEN(buf1);
- extmark_col_adjust(curbuf,
- pos->lnum,
- startpos.col + 1,
- 0,
- col_amount,
- kExtmarkUndo);
- }
-
theend:
xfree(buf1);
if (visual) {
diff --git a/src/nvim/window.c b/src/nvim/window.c
index 2a7578e33c..dee36df433 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -633,6 +633,12 @@ void win_set_minimal_style(win_T *wp)
xfree(wp->w_p_scl);
wp->w_p_scl = (char_u *)xstrdup("auto");
}
+
+ // colorcolumn: cleared
+ if (wp->w_p_cc != NULL && *wp->w_p_cc != NUL) {
+ xfree(wp->w_p_cc);
+ wp->w_p_cc = (char_u *)xstrdup("");
+ }
}
void win_config_float(win_T *wp, FloatConfig fconfig)