commit 81ddea61d765938b662b3456b3fe80369cfbc138
parent 626c8692fa7f3dadb3c83a7c5b68b129e9e04ad5
Author: lumidify <nobody@lumidify.org>
Date: Fri, 6 Oct 2023 11:05:17 +0200
Fix bug with undo
Sometimes, the text would get scrambled when using undo. This was
actually due to a bug in the deletion function that only became
apparent when using undo.
Diffstat:
2 files changed, 28 insertions(+), 12 deletions(-)
diff --git a/buffer.c b/buffer.c
@@ -909,8 +909,12 @@ buffer_prev_char_pos(
*byte_ret = cur_byte;
}
+/* The check for length == 0 in buffer_delete_line_section_base and the check for
+ empty range in delete_range_base shouldn't be needed, but I added them just in case. */
static void
buffer_delete_line_section_base(ledit_buffer *buffer, size_t line, size_t start, size_t length) {
+ if (length == 0)
+ return;
ledit_line *l = buffer_get_line(buffer, line);
/* FIXME: somehow make sure this doesn't get optimized out? */
(void)add_sz(start, length); /* just check that no overflow */
@@ -928,7 +932,7 @@ buffer_delete_line_section_base(ledit_buffer *buffer, size_t line, size_t start,
memmove(
l->text + l->gap,
l->text + l->gap + l->cap - l->len,
- start - l->gap
+ start - l->gap - l->cap + l->len
);
}
l->len -= length;
@@ -947,6 +951,8 @@ delete_range_base(
size_t line_index1, size_t byte_index1,
size_t line_index2, size_t byte_index2,
txtbuf *text_ret) {
+ if (line_index1 == line_index2 && byte_index1 == byte_index2)
+ return;
sort_range(&line_index1, &byte_index1, &line_index2, &byte_index2);
if (line_index1 == line_index2) {
if (text_ret) {
diff --git a/undo.c b/undo.c
@@ -101,6 +101,23 @@ undo_change_mode_group(undo_stack *undo) {
undo->change_mode_group = 1;
}
+/*
+static void
+dump_undo(undo_stack *undo) {
+ printf("START UNDO STACK\n");
+ printf("cur: %zu\n", undo->cur);
+ for (size_t i = 0; i < undo->len; i++) {
+ undo_elem *e = &undo->stack[i];
+ printf(
+ "type %d, mode %d, group %d, mode_group %d, text '%.*s', range (%zu, %zu)\n",
+ e->type, e->mode, e->group, e->mode_group, (int)e->text->len, e->text->text,
+ e->op_range.byte1, e->op_range.byte2
+ );
+ }
+ printf("END UNDO STACK\n");
+}
+*/
+
static void
push_undo(
undo_stack *undo, txtbuf *text,
@@ -123,17 +140,7 @@ push_undo(
txtbuf_copy(e->text, text);
else
e->text = txtbuf_dup(text);
- /*
- printf("START UNDO STACK\n");
- for (size_t i = 0; i < undo->len; i++) {
- undo_elem *e = &undo->stack[i];
- printf(
- "type %d, mode %d, group %d, mode_group %d, text '%.*s'\n",
- e->type, e->mode, e->group, e->mode_group, (int)e->text->len, e->text->text
- );
- }
- printf("END UNDO STACK\n");
- */
+ /* dump_undo(undo); */
}
void
@@ -195,6 +202,7 @@ ledit_undo(undo_stack *undo, ledit_mode mode, void *callback_data,
switch (e->type) {
case UNDO_INSERT:
/* FIXME: should the paste buffer also be modified? */
+ /* printf("delete %zu,%zu; %zu,%zu\n", e->op_range.line1, e->op_range.byte1, e->op_range.line2, e->op_range.byte2); */
delete_cb(
callback_data,
e->op_range.line1, e->op_range.byte1,
@@ -202,6 +210,7 @@ ledit_undo(undo_stack *undo, ledit_mode mode, void *callback_data,
);
break;
case UNDO_DELETE:
+ /* printf("delete %zu,%zu; %zu,%zu\n", e->op_range.line1, e->op_range.byte1, e->op_range.line2, e->op_range.byte2); */
insert_cb(
callback_data,
e->op_range.line1, e->op_range.byte1,
@@ -234,6 +243,7 @@ ledit_undo(undo_stack *undo, ledit_mode mode, void *callback_data,
*min_line_ret = min_line;
if (mode == NORMAL || mode == VISUAL)
undo_change_mode_group(undo);
+ /* dump_undo(undo); */
return UNDO_NORMAL;
}