summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2025-12-28 00:46:52 -0500
committerWormHeamer2025-12-28 00:46:52 -0500
commit17eddfde53dd988d7d3ac0748eaab4da52bd16d7 (patch)
tree55818e36eed5d7ce3d50cfc092eaa973b8b3f0a2
parentbf4535008a78ed84fe3e76a9ae262646b9a5f150 (diff)
some bugfixes
-rw-r--r--txt.c64
1 files changed, 48 insertions, 16 deletions
diff --git a/txt.c b/txt.c
index b71bba3..daa02e5 100644
--- a/txt.c
+++ b/txt.c
@@ -35,12 +35,12 @@ u32 txt_split_piece(Txt *b, u32 pi, u32 i) {
TxtLoc txt_at(Txt *b, u32 cur) {
for (u32 i = 0; i < b->ptbl.n; i++) {
- if (cur <= b->ptbl.v[i].n) {
+ if (cur < b->ptbl.v[i].n) {
return (TxtLoc) { i, cur };
}
cur -= b->ptbl.v[i].n;
}
- return (TxtLoc) { 0, 0 };
+ return (TxtLoc) { b->ptbl.n - 1, b->ptbl.v[b->ptbl.n - 1].n };
}
void txt_buf_append(Txt *b, TxtBufIdx bi, const char *s, u32 n) {
@@ -54,18 +54,29 @@ void txt_buf_append(Txt *b, TxtBufIdx bi, const char *s, u32 n) {
buf->n += n;
}
-u32 txt_insert(Txt *b, u32 cur, const char *s, u32 n) {
- TxtLoc l = txt_at(b, cur);
+u32 txt_add_piece(Txt *b, TxtLoc l) {
+ if (l.p > 0 && !l.i) {
+ l.p--;
+ l.i = b->ptbl.v[l.p].n;
+ }
if (l.p < b->ptbl.n) {
TxtPiece *p = &b->ptbl.v[l.p];
int mid = p->ofs + l.i < b->buf[p->buf].n;
if (p->buf == TXT_SRC || mid) {
l.p = txt_split_piece(b, l.p, l.i);
- txt_insert_piece(b, l.p, TXT_ADD, b->buf[TXT_ADD].n, 0);
+ goto insert;
}
} else {
+insert:
+ if (b->ptbl.v[l.p].n == 0) txt_remove_piece(b, l.p);
txt_insert_piece(b, l.p, TXT_ADD, b->buf[TXT_ADD].n, 0);
}
+ return l.p;
+}
+
+u32 txt_insert(Txt *b, u32 cur, const char *s, u32 n) {
+ TxtLoc l = txt_at(b, cur);
+ l.p = txt_add_piece(b, l);
TxtPiece *p = &b->ptbl.v[l.p];
txt_buf_append(b, p->buf, s, n);
p->n += n;
@@ -78,23 +89,44 @@ u32 txt_insert_c(Txt *b, u32 cur, char ch) {
return txt_insert(b, cur, &ch, 1);
}
+static int txt_are_pieces_adjacent(Txt *t, u32 a, u32 b) {
+ TxtPiece *pa = &t->ptbl.v[a];
+ TxtPiece *pb = &t->ptbl.v[b];
+ return pa->buf == pb->buf && pa->ofs + pa->n == pb->ofs;
+}
+
+static void txt_join_or_kill(Txt *b, u32 pi) {
+ if (b->ptbl.v[pi].n == 0 && !(pi == 0 && b->ptbl.n == 1)) {
+ txt_remove_piece(b, pi);
+ }
+ if (pi + 1 < b->ptbl.n && txt_are_pieces_adjacent(b, pi, pi + 1)) {
+ b->ptbl.v[pi].n += b->ptbl.v[pi+1].n;
+ txt_remove_piece(b, pi + 1);
+ }
+}
+
u32 txt_delete(Txt *b, u32 cur, u32 n) {
TxtLoc l = txt_at(b, cur);
- txt_split_piece(b, l.p, l.i);
- TxtPiece *p = &b->ptbl.v[l.p];
+ u32 pi = txt_split_piece(b, l.p, l.i);
+ if (pi > 0) pi--;
if (n > cur) n = cur;
cur -= n;
b->len -= n;
- while (n > p->n) {
- n -= p->n;
- if (l.p + 1 < b->ptbl.n) txt_remove_piece(b, l.p);
- b->ptbl.n--;
- if (!l.p) return cur;
- l.p--;
- p = &b->ptbl.v[l.p];
+ for (;;) {
+ TxtPiece *p = &b->ptbl.v[pi];
+ if (n >= p->n) {
+ n -= p->n;
+ p->n = 0;
+ if (pi > 0 || b->ptbl.n > 1) txt_remove_piece(b, pi);
+ } else {
+ p->n -= n;
+ n = 0;
+ break;
+ }
+ if (pi == 0) break;
+ pi--;
}
- p->n -= n;
- if (p->n == 0) txt_remove_piece(b, l.p);
+ txt_join_or_kill(b, pi);
return cur;
}