aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/view.c
diff options
context:
space:
mode:
authorRobin Haberkorn <rhaberkorn@fmsbw.de>2026-09-25 01:43:56 +0200
committerRobin Haberkorn <rhaberkorn@fmsbw.de>2026-09-25 01:43:56 +0200
commite371b5fc710c597e175e6b7d7645b3a224a731a1 (patch)
tree3861fa4949adfd1c95a06ae0b7dd41c4167a3b7a /src/view.c
parent207af96f4eb3220534ea06c2e107517372246544 (diff)
instead of relying on Scintilla undo actions, use SciTECO undo tokens exclusivelyHEADmaster-fmsbw-cimaster
Previously we were using both Scintilla undo actions and our own undo tokens and both had to be coordinated via `undo__teco_interface_ssm(SCI_UNDO, 0, 0)`. This was error prone since we have to predict when an undo action is actually generated. Furthermore, you had to update SCI_SETUNDOCOLLECTION on all buffers and the Q-Reg view whenever switching to and from interactive mode. Also, this probably wasted memory for the doubled undo bookkeeping. Now, we always set SCI_SETUNDOCOLLECTION(FALSE), even in interactive mode. teco_undo_view_insert() was introduced to undo text deletions. While this saves almost no lines of code, it's just a clearer and simpler architecture.
Diffstat (limited to 'src/view.c')
-rw-r--r--src/view.c58
1 files changed, 52 insertions, 6 deletions
diff --git a/src/view.c b/src/view.c
index 43cdd3f..d866a5e 100644
--- a/src/view.c
+++ b/src/view.c
@@ -65,10 +65,9 @@ teco_view_setup(teco_view_t *ctx)
SC_MOD_INSERTTEXT | SC_MOD_BEFOREDELETE, 0);
/*
- * Start with or without undo collection,
- * depending on teco_undo_enabled.
+ * We are exclusively using SciTECO's undo tokens.
*/
- teco_view_ssm(ctx, SCI_SETUNDOCOLLECTION, teco_undo_enabled, 0);
+ teco_view_ssm(ctx, SCI_SETUNDOCOLLECTION, FALSE, 0);
teco_view_ssm(ctx, SCI_SETFOCUS, TRUE, 0);
@@ -248,7 +247,6 @@ teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel,
teco_view_ssm(ctx, SCI_RELEASELINECHARACTERINDEX,
SC_LINECHARACTERINDEX_UTF32, 0);
- teco_view_ssm(ctx, SCI_BEGINUNDOACTION, 0, 0);
if (clear) {
teco_view_ssm(ctx, SCI_CLEARALL, 0, 0);
@@ -322,8 +320,6 @@ teco_view_load_from_channel(teco_view_t *ctx, GIOChannel *channel,
"Inconsistent EOL styles normalized");
cleanup:
- teco_view_ssm(ctx, SCI_ENDUNDOACTION, 0, 0);
-
if (cp == SC_CP_UTF8)
teco_view_ssm(ctx, SCI_ALLOCATELINECHARACTERINDEX,
SC_LINECHARACTERINDEX_UTF32, 0);
@@ -835,6 +831,56 @@ teco_view_get_character(teco_view_t *ctx, gsize pos, gsize len)
return rc < 0 ? rc-1 : rc;
}
+typedef struct {
+ teco_view_t *view;
+ /** dot in bytes before the deletion */
+ gsize dot_bytes;
+ gsize position, length;
+ gchar text[];
+} teco_undo_view_insert_t;
+
+static void
+teco_undo_view_insert_action(teco_undo_view_insert_t *ctx, gboolean run)
+{
+ if (!run)
+ return;
+ teco_view_ssm(ctx->view, SCI_GOTOPOS, ctx->position, 0);
+ teco_view_ssm(ctx->view, SCI_ADDTEXT, ctx->length, (sptr_t)ctx->text);
+ teco_view_ssm(ctx->view, SCI_GOTOPOS, ctx->dot_bytes, 0);
+}
+
+/**
+ * During undo, insert a string from the given view.
+ * This can be used to undo text deletions.
+ *
+ * @param view The view that contains the string
+ * @param pos Beginning of string in bytes
+ * @param len Length of string in bytes
+ */
+void
+teco_undo_view_insert(teco_view_t *view, gsize pos, gsize len)
+{
+ if (!len)
+ return;
+
+ teco_undo_view_insert_t *ctx;
+ ctx = teco_undo_push_size((teco_undo_action_t)teco_undo_view_insert_action,
+ sizeof(*ctx) + len + 1);
+ if (!ctx)
+ return;
+
+ ctx->view = view;
+ ctx->dot_bytes = teco_view_ssm(view, SCI_GETCURRENTPOS, 0, 0);
+ ctx->position = pos;
+ ctx->length = len;
+
+ struct Sci_TextRangeFull range = {
+ .chrg = {pos, pos + len},
+ .lpstrText = ctx->text
+ };
+ teco_view_ssm(view, SCI_GETTEXTRANGEFULL, 0, (sptr_t)&range);
+}
+
void
teco_view_process_notify(teco_view_t *ctx, const SCNotification *notify)
{