diff options
| author | WormHeamer | 2025-12-28 00:46:52 -0500 |
|---|---|---|
| committer | WormHeamer | 2025-12-28 00:46:52 -0500 |
| commit | 17eddfde53dd988d7d3ac0748eaab4da52bd16d7 (patch) | |
| tree | 55818e36eed5d7ce3d50cfc092eaa973b8b3f0a2 /txt.c | |
| parent | bf4535008a78ed84fe3e76a9ae262646b9a5f150 (diff) | |
some bugfixes
Diffstat (limited to 'txt.c')
| -rw-r--r-- | txt.c | 64 |
1 files changed, 48 insertions, 16 deletions
@@ -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; } |
