summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2026-01-02 00:22:17 -0500
committerWormHeamer2026-01-02 00:22:17 -0500
commit8fa897bdfdfef633e669cd980d856ea05ef83022 (patch)
treed20162d8fe8cf8343a53cb63c5ead463c7f4033c
parentcff961a844962fcd61ee04bbe67777d442d0c76f (diff)
undo/redo
-rw-r--r--txt.c43
-rw-r--r--txt.h27
2 files changed, 64 insertions, 6 deletions
diff --git a/txt.c b/txt.c
index 0a24b22..3107b94 100644
--- a/txt.c
+++ b/txt.c
@@ -258,6 +258,49 @@ void txt_free(Txt *t) {
free(t->ptbl.v);
}
+void txt_hist_push(Txt *t, TxtLoc cur) {
+ if (t->hist.n > 0) {
+ TxtPieceTbl *pt = &t->hist.v[t->hist.i];
+ if (t->ptbl.n == pt->n && !memcmp(pt->v, t->ptbl.v, sizeof(TxtPiece) * pt->n)) {
+ t->hist.cur[t->hist.i] = cur;
+ return;
+ }
+ }
+ if (t->hist.i + 1 < t->hist.n) t->hist.n = t->hist.i + 1;
+ if (t->hist.n == TXT_HIST_MAX) {
+ free(t->hist.v[0].v);
+ MOVE(&t->hist.v[0], &t->hist.v[1], TXT_HIST_MAX - 1);
+ t->hist.i--;
+ t->hist.n--;
+ }
+ if (t->hist.i + 1 == t->hist.n) t->hist.i++;
+ DA_FIT(&t->hist.v[t->hist.i], t->ptbl.n);
+ memcpy(t->hist.v[t->hist.i].v, t->ptbl.v, sizeof(TxtPiece) * t->ptbl.n);
+ t->hist.v[t->hist.i].n = t->ptbl.n;
+ t->hist.cur[t->hist.i] = cur;
+ t->hist.n++;
+}
+
+int txt_hist_fwd(Txt *t, TxtLoc *cur) {
+ if (t->hist.i + 1 >= t->hist.n) return 0;
+ t->hist.i++;
+ t->ptbl.n = t->hist.v[t->hist.i].n;
+ DA_FIT(&t->ptbl, t->ptbl.n);
+ memcpy(t->ptbl.v, t->hist.v[t->hist.i].v, sizeof(TxtPiece) * t->ptbl.n);
+ *cur = t->hist.cur[t->hist.i];
+ return 1;
+}
+
+int txt_hist_back(Txt *t, TxtLoc *cur) {
+ if (t->hist.i == 0) return 0;
+ t->hist.i--;
+ t->ptbl.n = t->hist.v[t->hist.i].n;
+ DA_FIT(&t->ptbl, t->ptbl.n);
+ memcpy(t->ptbl.v, t->hist.v[t->hist.i].v, sizeof(TxtPiece) * t->ptbl.n);
+ *cur = t->hist.cur[t->hist.i];
+ return 1;
+}
+
Str txt_collect_range(TxtLoc lo, TxtLoc hi, Arena *a) {
DYNARR(char) buf = { 0 };
while (lo.p < hi.p) {
diff --git a/txt.h b/txt.h
index 5df33a7..148369e 100644
--- a/txt.h
+++ b/txt.h
@@ -5,6 +5,8 @@
#include "arena.h"
#include "str.h"
+#define TXT_HIST_MAX 32
+
typedef enum : u8 {
TXT_SRC,
TXT_ADD
@@ -20,18 +22,27 @@ typedef struct {
u32 n, c;
} TxtBuf;
+typedef DYNARR(TxtPiece) TxtPieceTbl;
+
+typedef struct {
+ struct Txt *t;
+ u32 p, i;
+} TxtLoc;
+
typedef struct {
- DYNARR(TxtPiece) ptbl;
+ TxtPieceTbl v[TXT_HIST_MAX];
+ TxtLoc cur[TXT_HIST_MAX];
+ u32 i, n;
+} TxtHist;
+
+typedef struct Txt {
+ TxtPieceTbl ptbl;
+ TxtHist hist;
TxtBuf buf[2];
u32 len;
int dirty;
} Txt;
-typedef struct {
- Txt *t;
- u32 p, i;
-} TxtLoc;
-
/* text buffer manipulation */
TxtLoc txt_split_piece(TxtLoc l);
@@ -43,6 +54,10 @@ int txt_load(Txt *b, const char *path);
int txt_save(Txt *b, const char *path);
void txt_free(Txt *b);
+void txt_hist_push(Txt *t, TxtLoc cur);
+int txt_hist_fwd(Txt *t, TxtLoc *cur);
+int txt_hist_back(Txt *t, TxtLoc *cur);
+
Str txt_collect_range(TxtLoc lo, TxtLoc hi, Arena *a);
u32 txt_read_chunk(TxtLoc *lo, TxtLoc hi, char *buf, u32 sz);
Str txt_next_chunk(TxtLoc *l);