From 3515f1c805cb3a61240d0187fd98530325be55f6 Mon Sep 17 00:00:00 2001 From: WormHeamer Date: Mon, 29 Dec 2025 19:48:19 -0500 Subject: simplify and clarify txt_split_piece(), txt_insert(), txt_delete() --- txt.c | 133 +++++++++++++++++++++++++----------------------------------------- 1 file changed, 50 insertions(+), 83 deletions(-) (limited to 'txt.c') diff --git a/txt.c b/txt.c index b4b4f54..62017c0 100644 --- a/txt.c +++ b/txt.c @@ -33,13 +33,35 @@ void txt_remove_piece(Txt *b, u32 pi) { b->ptbl.n--; } -u32 txt_split_piece(Txt *b, u32 pi, u32 i) { - TxtPiece *p = &b->ptbl.v[pi]; - if (i == 0) return pi; - if (i == p->n) return pi + 1; - txt_insert_piece(b, pi + 1, p->buf, p->ofs + i, p->n - i); - b->ptbl.v[pi].n = i; - return pi + 1; +TxtLoc txt_split_piece(TxtLoc l) { + TxtPiece *p = &l.t->ptbl.v[l.p]; + if (l.i < p->n) { + if (l.i == 0 && l.p > 0) { + l.p--; + l.i = l.t->ptbl.v[l.p].n; + } else { + txt_insert_piece(l.t, l.p + 1, p->buf, p->ofs + l.i, p->n - l.i); + l.t->ptbl.v[l.p].n = l.i; + } + } + ASSERT(l.p < l.t->ptbl.n); + ASSERT(l.i == l.t->ptbl.v[l.p].n); + return l; +} + +TxtLoc txt_add_piece(TxtLoc l) { + l = txt_split_piece(l); + TxtPiece *p = &l.t->ptbl.v[l.p]; + if (p->buf != TXT_ADD || p->ofs + p->n != l.t->buf[TXT_ADD].n) { + if (l.i > 0) { + txt_insert_piece(l.t, l.p + 1, TXT_ADD, l.t->buf[TXT_ADD].n, 0); + l.p++; + l.i = 0; + } else { + txt_replace_piece(l.t, l.p, TXT_ADD, l.t->buf[TXT_ADD].n, 0); + } + } + return l; } static void txt_buf_fit(Txt *b, TxtBufIdx bi, u32 sz) { @@ -67,59 +89,12 @@ static isize txt_buf_dedup(Txt *b, TxtBufIdx bi, const char *s, u32 n) { } } -TxtLoc 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); - goto insert; - } - } else { -insert: - if (l.p < b->ptbl.n && b->ptbl.v[l.p].n == 0) { - txt_replace_piece(b, l.p, TXT_ADD, b->buf[TXT_ADD].n, 0); - } else { - txt_insert_piece(b, l.p, TXT_ADD, b->buf[TXT_ADD].n, 0); - } - } - return l; -} - 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 int txt_trim_empty(TxtLoc *lp) { - TxtLoc l = *lp; - int deleted = 0; - while (l.p > 0 && l.t->ptbl.v[l.p-1].n == 0) { - txt_remove_piece(l.t, l.p - 1); - l.p--; - deleted = 1; - } - while (l.p + 1 < l.t->ptbl.n && l.t->ptbl.v[l.p+1].n == 0) { - txt_remove_piece(l.t, l.p + 1); - deleted = 1; - } - while (l.t->ptbl.n > 1 && l.t->ptbl.v[l.p].n == 0) { - txt_remove_piece(l.t, l.p); - if (l.p >= l.t->ptbl.n) { - l.p = l.t->ptbl.n - 1; - l.i = l.t->ptbl.v[l.p].n; - } - deleted = 1; - } - *lp = l; - return deleted; -} - static inline TxtLoc resolve_loc(TxtLoc l) { while (l.p + 1 < l.t->ptbl.n && l.i == l.t->ptbl.v[l.p].n) { l.p++; @@ -132,10 +107,6 @@ static inline TxtLoc resolve_loc(TxtLoc l) { static TxtLoc txt_post_edit(TxtLoc l) { l = resolve_loc(l); loop: - if (txt_trim_empty(&l)) { - ASSERT(txt_valid_loc(l)); - goto loop; - } if (l.p > 0 && txt_are_pieces_adjacent(l.t, l.p - 1, l.p)) { l.i = l.t->ptbl.v[l.p - 1].n; l.t->ptbl.v[l.p - 1].n += l.t->ptbl.v[l.p].n; @@ -155,7 +126,7 @@ loop: } TxtLoc txt_insert(TxtLoc l, const char *s, u32 n) { - l = txt_add_piece(l.t, l); + l = txt_add_piece(l); TxtPiece *p = &l.t->ptbl.v[l.p]; isize ext = txt_buf_dedup(l.t, p->buf, s, n); if (p->n > 0 || ext == -1) { @@ -169,37 +140,31 @@ TxtLoc txt_insert(TxtLoc l, const char *s, u32 n) { return txt_post_edit(l); } -TxtLoc txt_insert_c(TxtLoc l, u32 ch) { - char buf[6]; - u32 n = utf8_encode_len(&ch, 1); - utf8_encode(buf, &ch, 1); - return txt_insert(l, buf, n); -} - TxtLoc txt_delete(TxtLoc l, u32 n) { - u32 pi = txt_split_piece(l.t, l.p, l.i); - if (pi > 0) pi--; - l.p = pi; - l.i = l.t->ptbl.v[l.p].n; - for (;;) { - if (l.i != l.t->ptbl.v[l.p].n) break; - if (l.i >= n) { - l.i -= n; - l.t->ptbl.v[l.p].n -= n; - break; - } else { - l.t->ptbl.v[l.p].n -= l.i; - n -= l.i; - l.i = 0; - if (l.p == 0) break; - l.p = l.p - 1; + l = txt_split_piece(l); + while (n > 0) { + TxtPiece *p = &l.t->ptbl.v[l.p]; + u32 sz = p->n > n ? n : p->n; + p->n -= sz; + l.i -= sz; + n -= sz; + if (!p->n && l.t->ptbl.n > 1) txt_remove_piece(l.t, l.p); + if (l.p == 0) break; + if (l.i == 0) { + l.p--; l.i = l.t->ptbl.v[l.p].n; } - while (txt_trim_empty(&l)); } return txt_post_edit(l); } +TxtLoc txt_insert_c(TxtLoc l, u32 ch) { + char buf[6]; + u32 n = utf8_encode_len(&ch, 1); + utf8_encode(buf, &ch, 1); + return txt_insert(l, buf, n); +} + u32 txt_range_len(TxtLoc lo, TxtLoc hi) { u32 n = 0; while (lo.p < hi.p) { @@ -438,6 +403,8 @@ int at_end(TxtLoc l) { return l.p + 1 == l.t->ptbl.n && l.i == l.t->ptbl.v[l.p].n; } +/* TODO: make these use memchr() or equivalent */ + TxtLoc next_newline(TxtLoc l) { do l = cnext(l); while (!at_end(l) && txt_byte(l) != '\n'); -- cgit v1.2.3