aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/extmark.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/extmark.c')
-rw-r--r--src/nvim/extmark.c162
1 files changed, 70 insertions, 92 deletions
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index 2906a2196b..cf01c305d7 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -19,7 +19,7 @@
// Marks live in namespaces that allow plugins/users to segregate marks
// from other users.
//
-// Deleting marks only happens when explicitly calling extmark_del, deleteing
+// Deleting marks only happens when explicitly calling extmark_del, deleting
// over a range of marks will only move the marks. Deleting on a mark will
// leave it in same position unless it is on the EOL of a line.
//
@@ -29,55 +29,43 @@
// code for redrawing the line with the deleted decoration.
#include <assert.h>
+
#include "nvim/api/vim.h"
-#include "nvim/vim.h"
+#include "nvim/buffer.h"
+#include "nvim/buffer_updates.h"
#include "nvim/charset.h"
-#include "nvim/extmark.h"
#include "nvim/decoration.h"
-#include "nvim/buffer_updates.h"
-#include "nvim/memline.h"
-#include "nvim/pos.h"
+#include "nvim/extmark.h"
#include "nvim/globals.h"
-#include "nvim/map.h"
#include "nvim/lib/kbtree.h"
+#include "nvim/map.h"
+#include "nvim/memline.h"
+#include "nvim/pos.h"
#include "nvim/undo.h"
-#include "nvim/buffer.h"
+#include "nvim/vim.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "extmark.c.generated.h"
#endif
static ExtmarkNs *buf_ns_ref(buf_T *buf, uint64_t ns_id, bool put) {
- if (!buf->b_extmark_ns) {
- if (!put) {
- return NULL;
- }
- buf->b_extmark_ns = map_new(uint64_t, ExtmarkNs)();
- buf->b_extmark_index = map_new(uint64_t, ExtmarkItem)();
- }
-
- ExtmarkNs *ns = map_ref(uint64_t, ExtmarkNs)(buf->b_extmark_ns, ns_id, put);
- if (put && ns->map == NULL) {
- ns->map = map_new(uint64_t, uint64_t)();
- ns->free_id = 1;
- }
- return ns;
+ return map_ref(uint64_t, ExtmarkNs)(buf->b_extmark_ns, ns_id, put);
}
/// Create or update an extmark
///
/// must not be used during iteration!
-/// @returns the mark id
-uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t id,
- int row, colnr_T col, int end_row, colnr_T end_col,
- Decoration *decor, bool right_gravity,
- bool end_right_gravity, ExtmarkOp op)
+/// @returns the internal mark id
+uint64_t extmark_set(buf_T *buf, uint64_t ns_id, uint64_t *idp, int row, colnr_T col, int end_row,
+ colnr_T end_col, Decoration *decor, bool right_gravity, bool end_right_gravity,
+ ExtmarkOp op)
{
ExtmarkNs *ns = buf_ns_ref(buf, ns_id, true);
assert(ns != NULL);
mtpos_t old_pos;
uint64_t mark = 0;
+ uint64_t id = idp ? *idp : 0;
if (id == 0) {
id = ns->free_id++;
@@ -131,7 +119,11 @@ revised:
if (decor) {
decor_redraw(buf, row, end_row > -1 ? end_row : row, decor);
}
- return id;
+
+ if (idp) {
+ *idp = id;
+ }
+ return mark;
}
static bool extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col)
@@ -182,6 +174,10 @@ bool extmark_del(buf_T *buf, uint64_t ns_id, uint64_t id)
decor_free(item.decor);
}
+ if (mark == buf->b_virt_line_mark) {
+ clear_virt_lines(buf, pos.row);
+ }
+
map_del(uint64_t, uint64_t)(ns->map, id);
map_del(uint64_t, ExtmarkItem)(buf->b_extmark_index, mark);
@@ -191,11 +187,9 @@ bool extmark_del(buf_T *buf, uint64_t ns_id, uint64_t id)
// Free extmarks in a ns between lines
// if ns = 0, it means clear all namespaces
-bool extmark_clear(buf_T *buf, uint64_t ns_id,
- int l_row, colnr_T l_col,
- int u_row, colnr_T u_col)
+bool extmark_clear(buf_T *buf, uint64_t ns_id, int l_row, colnr_T l_col, int u_row, colnr_T u_col)
{
- if (!buf->b_extmark_ns) {
+ if (!map_size(buf->b_extmark_ns)) {
return false;
}
@@ -215,12 +209,9 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
}
// the value is either zero or the lnum (row+1) if highlight was present.
- static Map(uint64_t, ssize_t) *delete_set = NULL;
+ static Map(uint64_t, ssize_t) delete_set = MAP_INIT;
typedef struct { Decoration *decor; int row1; } DecorItem;
static kvec_t(DecorItem) decors;
- if (delete_set == NULL) {
- delete_set = map_new(uint64_t, ssize_t)();
- }
MarkTreeIter itr[1] = { 0 };
marktree_itr_get(buf->b_marktree, l_row, l_col, itr);
@@ -231,7 +222,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
|| (mark.row == u_row && mark.col > u_col)) {
break;
}
- ssize_t *del_status = map_ref(uint64_t, ssize_t)(delete_set, mark.id,
+ ssize_t *del_status = map_ref(uint64_t, ssize_t)(&delete_set, mark.id,
false);
if (del_status) {
marktree_del_itr(buf->b_marktree, itr, false);
@@ -240,11 +231,14 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
decor_redraw(buf, it.row1, mark.row, it.decor);
decor_free(it.decor);
}
- map_del(uint64_t, ssize_t)(delete_set, mark.id);
+ map_del(uint64_t, ssize_t)(&delete_set, mark.id);
continue;
}
uint64_t start_id = mark.id & ~MARKTREE_END_FLAG;
+ if (start_id == buf->b_virt_line_mark) {
+ clear_virt_lines(buf, mark.row);
+ }
ExtmarkItem item = map_get(uint64_t, ExtmarkItem)(buf->b_extmark_index,
start_id);
@@ -261,14 +255,14 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
kv_push(decors,
((DecorItem) { .decor = item.decor, .row1 = mark.row }));
}
- map_put(uint64_t, ssize_t)(delete_set, other, decor_id);
+ map_put(uint64_t, ssize_t)(&delete_set, other, decor_id);
} else if (item.decor) {
decor_redraw(buf, mark.row, mark.row, item.decor);
decor_free(item.decor);
}
ExtmarkNs *my_ns = all_ns ? buf_ns_ref(buf, item.ns_id, false) : ns;
map_del(uint64_t, uint64_t)(my_ns->map, item.mark_id);
- map_del(uint64_t, ExtmarkItem)(buf->b_extmark_index, mark.id);
+ map_del(uint64_t, ExtmarkItem)(buf->b_extmark_index, start_id);
marktree_del_itr(buf->b_marktree, itr, false);
} else {
marktree_itr_next(buf->b_marktree, itr);
@@ -276,7 +270,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
}
uint64_t id;
ssize_t decor_id;
- map_foreach(delete_set, id, decor_id, {
+ map_foreach(&delete_set, id, decor_id, {
mtpos_t pos = marktree_lookup(buf->b_marktree, id, itr);
assert(itr->node);
marktree_del_itr(buf->b_marktree, itr, false);
@@ -286,7 +280,7 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
decor_free(it.decor);
}
});
- map_clear(uint64_t, ssize_t)(delete_set);
+ map_clear(uint64_t, ssize_t)(&delete_set);
kv_size(decors) = 0;
return marks_cleared;
}
@@ -297,10 +291,8 @@ bool extmark_clear(buf_T *buf, uint64_t ns_id,
// will be searched to the start, or end
// dir can be set to control the order of the array
// amount = amount of marks to find or -1 for all
-ExtmarkInfoArray extmark_get(buf_T *buf, uint64_t ns_id,
- int l_row, colnr_T l_col,
- int u_row, colnr_T u_col,
- int64_t amount, bool reverse)
+ExtmarkInfoArray extmark_get(buf_T *buf, uint64_t ns_id, int l_row, colnr_T l_col, int u_row,
+ colnr_T u_col, int64_t amount, bool reverse)
{
ExtmarkInfoArray array = KV_INITIAL_VALUE;
MarkTreeIter itr[1];
@@ -383,7 +375,7 @@ ExtmarkInfo extmark_from_id(buf_T *buf, uint64_t ns_id, uint64_t id)
// free extmarks from the buffer
void extmark_free_all(buf_T *buf)
{
- if (!buf->b_extmark_ns) {
+ if (!map_size(buf->b_extmark_ns)) {
return;
}
@@ -395,25 +387,24 @@ void extmark_free_all(buf_T *buf)
map_foreach(buf->b_extmark_ns, id, ns, {
(void)id;
- map_free(uint64_t, uint64_t)(ns.map);
+ map_destroy(uint64_t, uint64_t)(ns.map);
});
- map_free(uint64_t, ExtmarkNs)(buf->b_extmark_ns);
- buf->b_extmark_ns = NULL;
+ map_destroy(uint64_t, ExtmarkNs)(buf->b_extmark_ns);
+ map_init(uint64_t, ExtmarkNs, buf->b_extmark_ns);
map_foreach(buf->b_extmark_index, id, item, {
(void)id;
decor_free(item.decor);
});
- map_free(uint64_t, ExtmarkItem)(buf->b_extmark_index);
- buf->b_extmark_index = NULL;
+ map_destroy(uint64_t, ExtmarkItem)(buf->b_extmark_index);
+ map_init(uint64_t, ExtmarkItem, buf->b_extmark_index);
}
// Save info for undo/redo of set marks
-static void u_extmark_set(buf_T *buf, uint64_t mark,
- int row, colnr_T col)
+static void u_extmark_set(buf_T *buf, uint64_t mark, int row, colnr_T col)
{
- u_header_T *uhp = u_force_get_undo_header(buf);
+ u_header_T *uhp = u_force_get_undo_header(buf);
if (!uhp) {
return;
}
@@ -435,11 +426,9 @@ static void u_extmark_set(buf_T *buf, uint64_t mark,
///
/// useful when we cannot simply reverse the operation. This will do nothing on
/// redo, enforces correct position when undo.
-void u_extmark_copy(buf_T *buf,
- int l_row, colnr_T l_col,
- int u_row, colnr_T u_col)
+void u_extmark_copy(buf_T *buf, int l_row, colnr_T l_col, int u_row, colnr_T u_col)
{
- u_header_T *uhp = u_force_get_undo_header(buf);
+ u_header_T *uhp = u_force_get_undo_header(buf);
if (!uhp) {
return;
}
@@ -483,7 +472,6 @@ void extmark_apply_undo(ExtmarkUndoObject undo_info, bool undo)
splice.new_row, splice.new_col, splice.new_byte,
splice.old_row, splice.old_col, splice.old_byte,
kExtmarkNoUndo);
-
} else {
extmark_splice_impl(curbuf,
splice.start_row, splice.start_col, splice.start_byte,
@@ -491,14 +479,14 @@ void extmark_apply_undo(ExtmarkUndoObject undo_info, bool undo)
splice.new_row, splice.new_col, splice.new_byte,
kExtmarkNoUndo);
}
- // kExtmarkSavePos
+ // kExtmarkSavePos
} else if (undo_info.type == kExtmarkSavePos) {
ExtmarkSavePos pos = undo_info.data.savepos;
if (undo) {
if (pos.old_row >= 0) {
extmark_setraw(curbuf, pos.mark, pos.old_row, pos.old_col);
}
- // Redo
+ // Redo
} else {
if (pos.row >= 0) {
extmark_setraw(curbuf, pos.mark, pos.row, pos.col);
@@ -520,15 +508,12 @@ void extmark_apply_undo(ExtmarkUndoObject undo_info, bool undo)
kExtmarkNoUndo);
}
}
+ curbuf->b_virt_line_pos = -1;
}
// Adjust extmark row for inserted/deleted rows (columns stay fixed).
-void extmark_adjust(buf_T *buf,
- linenr_T line1,
- linenr_T line2,
- long amount,
- long amount_after,
+void extmark_adjust(buf_T *buf, linenr_T line1, linenr_T line2, long amount, long amount_after,
ExtmarkOp undo)
{
if (curbuf_splice_pending) {
@@ -553,7 +538,7 @@ void extmark_adjust(buf_T *buf,
}
if (new_row > 0) {
new_byte = ml_find_line_or_offset(buf, line1+new_row, NULL, true)
- - start_byte;
+ - start_byte;
}
extmark_splice_impl(buf,
(int)line1-1, 0, start_byte,
@@ -578,10 +563,8 @@ void extmark_adjust(buf_T *buf,
// the end column of the new region.
// @param new_byte Byte extent of the new region.
// @param undo
-void extmark_splice(buf_T *buf,
- int start_row, colnr_T start_col,
- int old_row, colnr_T old_col, bcount_t old_byte,
- int new_row, colnr_T new_col, bcount_t new_byte,
+void extmark_splice(buf_T *buf, int start_row, colnr_T start_col, int old_row, colnr_T old_col,
+ bcount_t old_byte, int new_row, colnr_T new_col, bcount_t new_byte,
ExtmarkOp undo)
{
long offset = ml_find_line_or_offset(buf, start_row + 1, NULL, true);
@@ -600,13 +583,12 @@ void extmark_splice(buf_T *buf,
undo);
}
-void extmark_splice_impl(buf_T *buf,
- int start_row, colnr_T start_col, bcount_t start_byte,
- int old_row, colnr_T old_col, bcount_t old_byte,
- int new_row, colnr_T new_col, bcount_t new_byte,
- ExtmarkOp undo)
+void extmark_splice_impl(buf_T *buf, int start_row, colnr_T start_col, bcount_t start_byte,
+ int old_row, colnr_T old_col, bcount_t old_byte, int new_row,
+ colnr_T new_col, bcount_t new_byte, ExtmarkOp undo)
{
- curbuf->deleted_bytes2 = 0;
+ buf->deleted_bytes2 = 0;
+ buf->b_virt_line_pos = -1;
buf_updates_send_splice(buf, start_row, start_col, start_byte,
old_row, old_col, old_byte,
new_row, new_col, new_byte);
@@ -628,7 +610,7 @@ void extmark_splice_impl(buf_T *buf,
new_row, new_col);
if (undo == kExtmarkUndo) {
- u_header_T *uhp = u_force_get_undo_header(buf);
+ u_header_T *uhp = u_force_get_undo_header(buf);
if (!uhp) {
return;
}
@@ -637,7 +619,7 @@ void extmark_splice_impl(buf_T *buf,
// TODO(bfredl): this is quite rudimentary. We merge small (within line)
// inserts with each other and small deletes with each other. Add full
// merge algorithm later.
- if (old_row == 0 && new_row == 0 && kv_size(uhp->uh_extmark)) {
+ if (old_row == 0 && new_row == 0 && kv_size(uhp->uh_extmark)) {
ExtmarkUndoObject *item = &kv_A(uhp->uh_extmark,
kv_size(uhp->uh_extmark)-1);
if (item->type == kExtmarkSplice) {
@@ -685,24 +667,20 @@ void extmark_splice_impl(buf_T *buf,
}
}
-void extmark_splice_cols(buf_T *buf,
- int start_row, colnr_T start_col,
- colnr_T old_col, colnr_T new_col,
- ExtmarkOp undo)
+void extmark_splice_cols(buf_T *buf, int start_row, colnr_T start_col, colnr_T old_col,
+ colnr_T new_col, ExtmarkOp undo)
{
extmark_splice(buf, start_row, start_col,
0, old_col, old_col,
0, new_col, new_col, undo);
}
-void extmark_move_region(
- buf_T *buf,
- int start_row, colnr_T start_col, bcount_t start_byte,
- int extent_row, colnr_T extent_col, bcount_t extent_byte,
- int new_row, colnr_T new_col, bcount_t new_byte,
- ExtmarkOp undo)
+void extmark_move_region(buf_T *buf, int start_row, colnr_T start_col, bcount_t start_byte,
+ int extent_row, colnr_T extent_col, bcount_t extent_byte, int new_row,
+ colnr_T new_col, bcount_t new_byte, ExtmarkOp undo)
{
- curbuf->deleted_bytes2 = 0;
+ buf->deleted_bytes2 = 0;
+ buf->b_virt_line_pos = -1;
// TODO(bfredl): this is not synced to the buffer state inside the callback.
// But unless we make the undo implementation smarter, this is not ensured
// anyway.
@@ -720,7 +698,7 @@ void extmark_move_region(
if (undo == kExtmarkUndo) {
- u_header_T *uhp = u_force_get_undo_header(buf);
+ u_header_T *uhp = u_force_get_undo_header(buf);
if (!uhp) {
return;
}