aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/parser.c
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2023-04-18 16:35:42 +0300
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2023-04-18 16:35:42 +0300
commit2f7266510a814ded6a53d9dfae6b61d4fb25f29e (patch)
treed799dbcdffed23e72ba75a2325c2531b2b299859 /src/parser.c
parent941f48da6dde691a7800290cc729aaaacd051392 (diff)
downloadsciteco-2f7266510a814ded6a53d9dfae6b61d4fb25f29e.tar.gz
fixup a6b5394086260c262e393dd113057916fd14134b: emit undo tokens for insert_len
* Turns out it is impossible - or at least very tricky - to avoid undo token emission for insert_len. I therefore opt for stability rather than saving memory. * The old workaround introduced in a6b5394086260c262e393dd113057916fd14134b would actually fail if you do not rub out the string argument completely after interruption. I.e. You type <Ihello^J$>, interrupt - insert_len may be != 0 at this point - and _partially_ rubout the insert-command and continue typing. This could still crash the editor.
Diffstat (limited to 'src/parser.c')
-rw-r--r--src/parser.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/src/parser.c b/src/parser.c
index cf887d4..9841c93 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -803,10 +803,6 @@ teco_state_expectstring_input(teco_machine_main_t *ctx, gchar chr, GError **erro
}
}
- /* insert_len might end up > 0 after interruptions */
- if (!ctx->expectstring.string.len)
- ctx->expectstring.insert_len = 0;
-
if (!ctx->expectstring.nesting) {
/*
* Call process_cb() even if interactive feedback
@@ -838,6 +834,8 @@ teco_state_expectstring_input(teco_machine_main_t *ctx, gchar chr, GError **erro
if (current->expectstring.string_building)
teco_machine_stringbuilding_reset(&ctx->expectstring.machine);
+ if (ctx->parent.must_undo)
+ teco_undo_gsize(ctx->expectstring.insert_len);
ctx->expectstring.insert_len = 0;
return next;
}
@@ -863,10 +861,16 @@ teco_state_expectstring_input(teco_machine_main_t *ctx, gchar chr, GError **erro
}
/*
- * NOTE: As an optimization insert_len is not restored on undo since
- * it is 0 after every key press anyway.
- * The only exception is when interrupting a command in a loop.
+ * NOTE: insert_len is always 0 after key presses in interactive mode,
+ * so we wouldn't have to undo it.
+ * But there is one exception: When interrupting a loop including a string
+ * argument (e.g. <I...$>), insert_len could end up != 0 which would consequently
+ * crash once you change the string argument.
+ * The only way to avoid repeated undo tokens might be adding an initial() callback
+ * that sets it to 0 on undo. But that is very tricky.
*/
+ if (ctx->parent.must_undo)
+ teco_undo_gsize(ctx->expectstring.insert_len);
ctx->expectstring.insert_len += ctx->expectstring.string.len - old_len;
return current;
@@ -877,17 +881,16 @@ teco_state_expectstring_refresh(teco_machine_main_t *ctx, GError **error)
{
teco_state_t *current = ctx->parent.current;
- /* insert_len might end up > 0 after interruptions */
- if (!ctx->expectstring.string.len)
- ctx->expectstring.insert_len = 0;
-
/* never calls process_cb() in parse-only mode */
if (ctx->expectstring.insert_len && current->expectstring.process_cb &&
!current->expectstring.process_cb(ctx, &ctx->expectstring.string,
ctx->expectstring.insert_len, error))
return FALSE;
+ if (ctx->parent.must_undo)
+ teco_undo_gsize(ctx->expectstring.insert_len);
ctx->expectstring.insert_len = 0;
+
return TRUE;
}