diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2023-04-18 16:35:42 +0300 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2023-04-18 16:35:42 +0300 |
commit | 2f7266510a814ded6a53d9dfae6b61d4fb25f29e (patch) | |
tree | d799dbcdffed23e72ba75a2325c2531b2b299859 | |
parent | 941f48da6dde691a7800290cc729aaaacd051392 (diff) | |
download | sciteco-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.
-rw-r--r-- | src/parser.c | 25 |
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; } |