From 9f4310c24ca39284ad768a82d368e749b18fd76c Mon Sep 17 00:00:00 2001 From: WormHeamer Date: Sun, 28 Dec 2025 02:45:38 -0500 Subject: put more emphasis on TxtLoc --- txt.c | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 79 insertions(+), 13 deletions(-) (limited to 'txt.c') diff --git a/txt.c b/txt.c index 9f29f84..8fcafe9 100644 --- a/txt.c +++ b/txt.c @@ -9,6 +9,7 @@ #include "wrmr.h" #include "dynarr.h" #include "txt.h" +#include "utf8.h" void txt_replace_piece(Txt *b, u32 pi, TxtBufIdx buf, u32 ofs, u32 n) { b->ptbl.v[pi] = (TxtPiece) { buf, ofs, n }; @@ -39,16 +40,6 @@ u32 txt_split_piece(Txt *b, u32 pi, u32 i) { return pi + 1; } -TxtLoc txt_at(Txt *b, u32 cur) { - for (u32 i = 0; i < b->ptbl.n; i++) { - if (cur < b->ptbl.v[i].n) { - return (TxtLoc) { i, cur }; - } - cur -= b->ptbl.v[i].n; - } - return (TxtLoc) { b->ptbl.n - 1, b->ptbl.v[b->ptbl.n - 1].n }; -} - static void txt_buf_fit(Txt *b, TxtBufIdx bi, u32 sz) { TxtBuf *buf = &b->buf[bi]; if (sz > buf->c) { @@ -98,9 +89,11 @@ u32 txt_insert(Txt *b, u32 cur, const char *s, u32 n) { return cur + n; } -u32 txt_insert_c(Txt *b, u32 cur, char ch) { - /* TODO: utf-8 char */ - return txt_insert(b, cur, &ch, 1); +u32 txt_insert_c(Txt *b, u32 cur, u32 ch) { + char buf[6]; + u32 n = utf8_encode_len(&ch, 1); + utf8_encode(buf, &ch, 1); + return txt_insert(b, cur, buf, n); } static int txt_are_pieces_adjacent(Txt *t, u32 a, u32 b) { @@ -144,6 +137,13 @@ u32 txt_delete(Txt *b, u32 cur, u32 n) { return cur; } +u32 txt_delete_c(Txt *b, u32 cur) { + while (cur > 0 && (txt_byte(b, txt_at(b, cur-1)) & 0xc0) == 0x80) + cur = txt_delete(b, cur, 1); + cur = txt_delete(b, cur, 1); + return cur; +} + int txt_load(Txt *b, const char *path) { struct stat sb; int fd = open(path, O_RDONLY); @@ -192,3 +192,69 @@ void txt_free(Txt *t) { } free(t->ptbl.v); } + +/* reading individual chars */ + +u8 txt_byte(Txt *t, TxtLoc l) { + TxtPiece *p = &t->ptbl.v[l.p]; + TxtBuf *b = &t->buf[p->buf]; + if (l.p < t->ptbl.n && l.i == p->n) p++, l.i = 0; + if (p->ofs + l.i >= b->n) return 0; + return b->s[p->ofs + l.i]; +} + +u32 txt_chr(Txt *t, TxtLoc l) { + TxtPiece *p = &t->ptbl.v[l.p]; + TxtBuf *b = &t->buf[p->buf]; + if (l.p < t->ptbl.n && l.i == p->n) p++, l.i = 0; + return utf8_decode_at(b->s, p->ofs + l.i, b->n); +} + +/* cursor manipulation */ + +TxtLoc txt_at(Txt *b, u32 cur) { + for (u32 i = 0; i < b->ptbl.n; i++) { + if (cur < b->ptbl.v[i].n) { + return (TxtLoc) { i, cur }; + } + cur -= b->ptbl.v[i].n; + } + return (TxtLoc) { b->ptbl.n - 1, b->ptbl.v[b->ptbl.n - 1].n }; +} + +u32 txt_ofs(Txt *b, TxtLoc l) { + u32 r = 0; + for (u32 i = 0; i < l.p; i++) { + r += b->ptbl.v[i].n; + } + return r + l.i; +} + +TxtLoc txt_next(Txt *b, TxtLoc l) { + TxtPiece *p = &b->ptbl.v[l.p]; + if (l.i+1 < p->n) return (TxtLoc) { l.p, l.i + 1 }; + if (l.p+1 < b->ptbl.n) { + return (TxtLoc) { l.p + 1, l.i }; + } else { + return (TxtLoc) { l.p, p->n }; + } +} + +TxtLoc txt_prev(Txt *b, TxtLoc l) { + if (l.i > 0) { + return (TxtLoc) { l.p, l.i - 1 }; + } else if (l.p > 0) { + return (TxtLoc) { l.p - 1, b->ptbl.v[l.p - 1].n - 1 }; + } else { + return (TxtLoc) { 0, 0 }; + } +} + +int txt_at_start(Txt *b, TxtLoc l) { + (void)b; + return l.p == 0 && l.i == 0; +} + +int txt_at_end(Txt *b, TxtLoc l) { + return l.p + 1 == b->ptbl.n && l.i == b->ptbl.v[l.p].n; +} -- cgit v1.2.3