summaryrefslogtreecommitdiff
path: root/txt.c
diff options
context:
space:
mode:
Diffstat (limited to 'txt.c')
-rw-r--r--txt.c92
1 files changed, 79 insertions, 13 deletions
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;
+}