diff options
Diffstat (limited to 'src/nvim/change.c')
-rw-r--r-- | src/nvim/change.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/src/nvim/change.c b/src/nvim/change.c index ba80e71ae6..51afb40b40 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -17,6 +17,7 @@ #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/mark.h" +#include "nvim/extmark.h" #include "nvim/memline.h" #include "nvim/misc1.h" #include "nvim/move.h" @@ -358,6 +359,19 @@ void changed_bytes(linenr_T lnum, colnr_T col) } } +/// insert/delete bytes at column +/// +/// Like changed_bytes() but also adjust extmark for "new" bytes. +/// When "new" is negative text was deleted. +static void inserted_bytes(linenr_T lnum, colnr_T col, int old, int new) +{ + if (curbuf_splice_pending == 0) { + extmark_splice(curbuf, (int)lnum-1, col, 0, old, 0, new, kExtmarkUndo); + } + + 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. @@ -372,7 +386,10 @@ void appended_lines_mark(linenr_T lnum, long count) // Skip mark_adjust when adding a line after the last one, there can't // be marks there. But it's still needed in diff mode. if (lnum + count < curbuf->b_ml.ml_line_count || curwin->w_p_diff) { - mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L, false); + mark_adjust(lnum + 1, (linenr_T)MAXLNUM, count, 0L, kExtmarkUndo); + } else { + extmark_adjust(curbuf, lnum + 1, (linenr_T)MAXLNUM, count, 0L, + kExtmarkUndo); } changed_lines(lnum + 1, 0, lnum + 1, count, true); } @@ -390,7 +407,8 @@ void deleted_lines(linenr_T lnum, long count) /// be triggered to display the cursor. void deleted_lines_mark(linenr_T lnum, long count) { - mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM, -count, false); + mark_adjust(lnum, (linenr_T)(lnum + count - 1), (long)MAXLNUM, -count, + kExtmarkUndo); changed_lines(lnum, 0, lnum + count, -count, true); } @@ -628,7 +646,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)oldlen, (int)newlen); // If we're in Insert or Replace mode and 'showmatch' is set, then briefly // show the match for right parens and braces. @@ -674,7 +692,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, 0, newlen); curwin->w_cursor.col += newlen; } @@ -737,7 +755,7 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine) } // If "count" is negative the caller must be doing something wrong. if (count < 1) { - IEMSGN("E950: Invalid count for del_bytes(): %ld", count); + IEMSGN("E292: Invalid count for del_bytes(): %ld", count); return FAIL; } @@ -795,7 +813,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, 0); return OK; } @@ -951,6 +969,9 @@ int open_line( bool did_append; // appended a new line int saved_pi = curbuf->b_p_pi; // copy of preserveindent setting + linenr_T lnum = curwin->w_cursor.lnum; + colnr_T mincol = curwin->w_cursor.col + 1; + // make a copy of the current line so we can mess with it char_u *saved_line = vim_strsave(get_cursor_line_ptr()); @@ -1560,6 +1581,7 @@ int open_line( end_comment_pending = NUL; // turns out there was no leader } + curbuf_splice_pending++; old_cursor = curwin->w_cursor; if (dir == BACKWARD) { curwin->w_cursor.lnum--; @@ -1574,7 +1596,8 @@ int open_line( // be marks there. But still needed in diff mode. if (curwin->w_cursor.lnum + 1 < curbuf->b_ml.ml_line_count || curwin->w_p_diff) { - mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L, false); + mark_adjust(curwin->w_cursor.lnum + 1, (linenr_T)MAXLNUM, 1L, 0L, + kExtmarkUndo); } did_append = true; } else { @@ -1614,7 +1637,7 @@ int open_line( // it. It gets restored at the function end. curbuf->b_p_pi = true; } else { - (void)set_indent(newindent, SIN_INSERT); + (void)set_indent(newindent, SIN_INSERT|SIN_NOMARK); } less_cols -= curwin->w_cursor.col; @@ -1665,6 +1688,11 @@ int open_line( curwin->w_cursor.col + less_cols_off, 1L, (long)-less_cols, 0); } + // Always move extmarks - Here we move only the line where the + // cursor is, the previous mark_adjust takes care of the lines after + int cols_added = mincol-1+less_cols_off-less_cols; + extmark_splice(curbuf, (int)lnum-1, mincol-1, 0, less_cols_off, + 1, cols_added, kExtmarkUndo); } else { changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col); } @@ -1676,7 +1704,10 @@ int open_line( } if (did_append) { changed_lines(curwin->w_cursor.lnum, 0, curwin->w_cursor.lnum, 1L, true); + extmark_splice(curbuf, (int)curwin->w_cursor.lnum-1, + 0, 0, 0, 1, 0, kExtmarkUndo); } + curbuf_splice_pending--; curwin->w_cursor.col = newcol; curwin->w_cursor.coladd = 0; |