summaryrefslogtreecommitdiff
path: root/txt.c
diff options
context:
space:
mode:
Diffstat (limited to 'txt.c')
-rw-r--r--txt.c65
1 files changed, 59 insertions, 6 deletions
diff --git a/txt.c b/txt.c
index 7092964..36af521 100644
--- a/txt.c
+++ b/txt.c
@@ -58,7 +58,7 @@ static void txt_buf_append(Txt *b, TxtBufIdx bi, const char *s, u32 n) {
static isize txt_buf_dedup(Txt *b, TxtBufIdx bi, const char *s, u32 n) {
TxtBuf *buf = &b->buf[bi];
- if (buf->n >= n && !memcmp(buf->s + (buf->n - n), s, n)) {
+ if (buf->n >= n && buf->s && !memcmp(buf->s + (buf->n - n), s, n)) {
return buf->n - n;
} else {
return -1;
@@ -128,6 +128,14 @@ static TxtLoc txt_join_or_kill(TxtLoc l) {
return l;
}
+static inline TxtLoc resolve_loc(TxtLoc l) {
+ if (l.p + 1 < l.t->ptbl.n && l.i == l.t->ptbl.v[l.p].n) {
+ l.p++;
+ l.i = 0;
+ }
+ return l;
+}
+
TxtLoc txt_insert(TxtLoc l, const char *s, u32 n) {
l = txt_add_piece(l.t, l);
TxtPiece *p = &l.t->ptbl.v[l.p];
@@ -142,7 +150,7 @@ TxtLoc txt_insert(TxtLoc l, const char *s, u32 n) {
l.i = p->n;
l = txt_join_or_kill(l);
l.i = l.t->ptbl.v[l.p].n;
- return l;
+ return resolve_loc(l);
}
TxtLoc txt_insert_c(TxtLoc l, u32 ch) {
@@ -173,15 +181,28 @@ TxtLoc txt_delete(TxtLoc l, u32 n) {
}
l = txt_join_or_kill(l);
}
- return txt_join_or_kill(l);
+ return resolve_loc(txt_join_or_kill(l));
+}
+
+u32 txt_range_len(TxtLoc lo, TxtLoc hi) {
+ u32 n = 0;
+ while (lo.p < hi.p) {
+ n += lo.t->ptbl.v[lo.p].n - lo.i;
+ lo.p++;
+ lo.i = 0;
+ }
+ n += hi.i - lo.i;
+ return n;
}
TxtLoc txt_delete_range(TxtLoc lo, TxtLoc hi) {
/* TODO: figure out nr. of chars, then delete all at once */
- while (txt_before(lo, hi)) {
- hi = txt_delete(hi, 1);
+ if (txt_before(hi, lo)) {
+ TxtLoc t = lo;
+ lo = hi;
+ hi = t;
}
- return lo;
+ return txt_delete(hi, txt_range_len(lo, hi));
}
TxtLoc txt_delete_c(TxtLoc l) {
@@ -242,8 +263,28 @@ void txt_free(Txt *t) {
free(t->ptbl.v);
}
+void txt_write_range(int fd, TxtLoc lo, TxtLoc hi) {
+ while (lo.p < hi.p) {
+ TxtPiece *p = &lo.t->ptbl.v[lo.p];
+ write(fd, lo.t->buf[p->buf].s + p->ofs + lo.i, p->n - lo.i);
+ lo.p++;
+ lo.i = 0;
+ }
+ if (hi.i > lo.i) {
+ TxtPiece *p = &lo.t->ptbl.v[lo.p];
+ write(fd, lo.t->buf[p->buf].s + p->ofs + lo.i, hi.i - lo.i);
+ }
+}
+
/* navigation */
+int txt_valid_loc(TxtLoc l) {
+ return l.p < l.t->ptbl.n
+ && (l.i < l.t->ptbl.v[l.p].n
+ || (l.p + 1 == l.t->ptbl.n
+ && l.i <= l.t->ptbl.v[l.p].n));
+}
+
TxtLoc txt_at(Txt *b, u32 ofs) {
for (u32 i = 0; i < b->ptbl.n; i++) {
if (ofs < b->ptbl.v[i].n) {
@@ -263,13 +304,25 @@ u32 txt_ofs(TxtLoc l) {
}
int txt_before(TxtLoc a, TxtLoc b) {
+ ASSERT(txt_valid_loc(a));
+ ASSERT(txt_valid_loc(b));
return a.p < b.p || (a.p == b.p && a.i < b.i);
}
int txt_after(TxtLoc a, TxtLoc b) {
+ ASSERT(txt_valid_loc(a));
+ ASSERT(txt_valid_loc(b));
return a.p > b.p || (a.p == b.p && a.i > b.i);
}
+TxtLoc txt_start(Txt *t) {
+ return (TxtLoc) { t, 0, 0 };
+}
+
+TxtLoc txt_end(Txt *t) {
+ return (TxtLoc) { t, t->ptbl.n-1, t->ptbl.v[t->ptbl.n-1].n };
+}
+
TxtLoc bnext(TxtLoc l) {
TxtPiece *p = &l.t->ptbl.v[l.p];
if (l.p + 1 < l.t->ptbl.n) {