summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--txt.c133
-rw-r--r--txt.h2
2 files changed, 51 insertions, 84 deletions
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');
diff --git a/txt.h b/txt.h
index d7c5685..6bc5dd1 100644
--- a/txt.h
+++ b/txt.h
@@ -33,7 +33,7 @@ typedef struct {
/* text buffer manipulation */
-u32 txt_split_piece(Txt *b, u32 pi, u32 i);
+TxtLoc txt_split_piece(TxtLoc l);
void txt_remove_piece(Txt *b, u32 pi);
void txt_insert_piece(Txt *b, u32 pi, TxtBufIdx buf, u32 ofs, u32 n);