aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/buffer.c14
-rw-r--r--src/nvim/ops.c27
-rw-r--r--src/nvim/ops.h1
3 files changed, 34 insertions, 8 deletions
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 915b99486d..a396693a61 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -27,6 +27,7 @@
#include "nvim/map_defs.h"
#include "nvim/map.h"
#include "nvim/mark.h"
+#include "nvim/ops.h"
#include "nvim/extmark.h"
#include "nvim/decoration.h"
#include "nvim/fileio.h"
@@ -441,6 +442,8 @@ void nvim_buf_set_lines(uint64_t channel_id,
goto end;
}
+ bcount_t deleted_bytes = MAX(get_region_bytecount(start, end, 0, 0)-1, 0);
+
// If the size of the range is reducing (ie, new_len < old_len) we
// need to delete some old_len. We do this at the start, by
// repeatedly deleting line "start".
@@ -460,6 +463,7 @@ void nvim_buf_set_lines(uint64_t channel_id,
// new old_len. This is a more efficient operation, as it requires
// less memory allocation and freeing.
size_t to_replace = old_len < new_len ? old_len : new_len;
+ bcount_t inserted_bytes = 0;
for (size_t i = 0; i < to_replace; i++) {
int64_t lnum = start + (int64_t)i;
@@ -472,6 +476,8 @@ void nvim_buf_set_lines(uint64_t channel_id,
api_set_error(err, kErrorTypeException, "Failed to replace line");
goto end;
}
+
+ inserted_bytes += STRLEN(lines[i]) + 1;
// Mark lines that haven't been passed to the buffer as they need
// to be freed later
lines[i] = NULL;
@@ -491,6 +497,8 @@ void nvim_buf_set_lines(uint64_t channel_id,
goto end;
}
+ inserted_bytes += STRLEN(lines[i]) + 1;
+
// Same as with replacing, but we also need to free lines
xfree(lines[i]);
lines[i] = NULL;
@@ -505,7 +513,11 @@ void nvim_buf_set_lines(uint64_t channel_id,
(linenr_T)(end - 1),
MAXLNUM,
(long)extra,
- kExtmarkUndo);
+ kExtmarkNOOP);
+
+ extmark_splice(curbuf, (int)start-1, 0, (int)(end-start), 0,
+ deleted_bytes, (int)(end+extra-1), 0, inserted_bytes,
+ kExtmarkUndo);
changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra, true);
fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra);
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 10b8ebdc22..569ed167d2 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -1676,17 +1676,14 @@ int op_delete(oparg_T *oap)
curbuf_splice_pending++;
pos_T startpos = curwin->w_cursor; // start position for delete
- bcount_t deleted_bytes = (bcount_t)STRLEN(
- ml_get(startpos.lnum)) + 1 - startpos.col;
+ bcount_t deleted_bytes = get_region_bytecount(
+ startpos.lnum, oap->end.lnum, startpos.col,
+ oap->end.col) - !oap->inclusive;
truncate_line(true); // delete from cursor to end of line
curpos = curwin->w_cursor; // remember curwin->w_cursor
curwin->w_cursor.lnum++;
- for (linenr_T i = 1; i <= oap->line_count - 2; i++) {
- deleted_bytes += (bcount_t)STRLEN(
- ml_get(startpos.lnum + i)) + 1;
- }
del_lines(oap->line_count - 2, false);
// delete from start of line until op_end
@@ -1694,7 +1691,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);
- deleted_bytes += n;
curwin->w_cursor = curpos; // restore curwin->w_cursor
(void)do_join(2, false, false, false, false);
curbuf_splice_pending--;
@@ -6303,3 +6299,20 @@ bool op_reg_set_previous(const char name)
y_previous = &y_regs[i];
return true;
}
+
+bcount_t get_region_bytecount(linenr_T start_lnum, linenr_T end_lnum,
+ colnr_T start_col, colnr_T end_col)
+{
+ const char *first = (const char *)ml_get(start_lnum);
+ bcount_t deleted_bytes = (bcount_t)STRLEN(first) - start_col + 1;
+
+ if (start_lnum == end_lnum) {
+ return deleted_bytes - ((bcount_t)STRLEN(first) - end_col + 1);
+ }
+
+ for (linenr_T i = 1; i <= end_lnum-start_lnum-1; i++) {
+ deleted_bytes += (bcount_t)STRLEN(
+ ml_get(start_lnum + i)) + 1;
+ }
+ return deleted_bytes + end_col + 1;
+}
diff --git a/src/nvim/ops.h b/src/nvim/ops.h
index a8867e02ea..77d6b4435f 100644
--- a/src/nvim/ops.h
+++ b/src/nvim/ops.h
@@ -6,6 +6,7 @@
#include "nvim/macros.h"
#include "nvim/ascii.h"
#include "nvim/types.h"
+#include "nvim/extmark.h"
#include "nvim/eval/typval.h"
#include "nvim/os/time.h"
#include "nvim/normal.h" // for MotionType and oparg_T