summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c57
-rw-r--r--txt.c86
2 files changed, 92 insertions, 51 deletions
diff --git a/main.c b/main.c
index df92cb3..26c305e 100644
--- a/main.c
+++ b/main.c
@@ -143,16 +143,6 @@ int shell_replace(TxtLoc start, TxtLoc end, const char *cmd) {
int p = popen2(cmd, &in, &out);
if (p < 0) return -1;
- TxtLoc l = start;
- while (txt_before(l, end)) {
- char c = txt_byte(l);
- if (write(in, &c, 1) != 1) {
- close(in);
- close(out);
- return -1;
- }
- l = bnext(l);
- }
txt_write_range(in, start, end);
close(in);
@@ -336,15 +326,48 @@ loop:
return 1;
}
+#include <time.h>
+
+void test_edits(void) {
+ for (u32 iter = 0; iter < 8192; iter++) {
+ ASSERT(iter != 385);
+ u32 n = rand() % 100;
+ cur = txt_at(&txt, rand() % txt.len);
+ if (rand() & 1) {
+ cur = txt_delete(cur, n);
+ } else {
+ for (u32 j = 0; j < n; j++) {
+ const char ch[] = {
+ 'a','b','c','d','e','f','g','h','j','k','l','i',
+ 'm','o','p','q','r','s','t','u','v','w','x','y','z','\n',
+ 'A','B','C','D','E','F','G','H','J','K','L','I',
+ 'M','O','P','Q','R','S','T','U','V','W','X','Y','Z',
+ };
+ cur = txt_insert_c(cur, ch[rand() % COUNTOF(ch)]);
+ }
+ }
+ if (txt.ptbl.n > 1) {
+ for (u32 i = 0; i < txt.ptbl.n; i++) {
+ ASSERT(txt.ptbl.v[i].n > 0);
+ }
+ }
+ }
+}
+
int main(int argc, const char **argv) {
scratch = arena_init(1L << 20);
vui_init();
vui_curs_vis(1);
vui_redraw_fn(draw);
const char *path = "test.txt";
+ //const char *path = "/usr/share/dict/words";
if (argc > 1) path = argv[1];
if (txt_load(&txt, path)) err(1, "couldn't open file");
cur = txt_end(&txt);
+
+ //srand(clock());
+ srand(123);
+
for (;;) {
scratch.beg = scratch.start;
draw(NULL);
@@ -464,17 +487,14 @@ int main(int argc, const char **argv) {
break;
case '\r': {
ins_newline:;
- /*
u32 tabs = 0;
TxtLoc start = start_of_line(cur);
for (TxtLoc l = start; txt_byte(l) == '\t'; l = bnext(l))
tabs++;
- while (txt_byte(txt_at(&txt, cur - 1)) == '\t') {
- cur = txt_ofs(txt_delete(cur, 1));
- }
- */
+ while (txt_byte(cprev(cur)) == '\t')
+ cur = txt_delete(cur, 1);
cur = txt_insert_c(cur, '\n');
- //while (tabs--) cur = txt_ofs(txt_insert_c(cur, '\t'));
+ while (tabs--) cur = txt_insert_c(cur, '\t');
} break;
default:
@@ -485,6 +505,11 @@ ins_newline:;
}
if (mode == 1) count = 0;
ASSERT(txt_valid_loc(cur));
+ if (txt.ptbl.n > 1) {
+ for (u32 i = 0; i < txt.ptbl.n; i++) {
+ ASSERT(txt.ptbl.v[i].n > 0);
+ }
+ }
}
brk:
vui_fini();
diff --git a/txt.c b/txt.c
index 36af521..3bd9eb4 100644
--- a/txt.c
+++ b/txt.c
@@ -94,48 +94,65 @@ static int txt_are_pieces_adjacent(Txt *t, u32 a, u32 b) {
return pa->buf == pb->buf && pa->ofs + pa->n == pb->ofs;
}
-static TxtLoc txt_join_or_kill(TxtLoc l) {
- Txt *b = l.t;
- while (l.t->ptbl.v[l.p].n == 0 && b->ptbl.n > 1) {
- txt_remove_piece(b, l.p);
- if (l.p >= b->ptbl.n) {
- l.p = b->ptbl.n - 1;
- l.i = b->ptbl.v[l.p].n;
- }
+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 < b->ptbl.n && l.t->ptbl.v[l.p + 1].n == 0) {
- txt_remove_piece(b, l.p + 1);
- if (l.p >= b->ptbl.n) {
- l.p = b->ptbl.n - 1;
- l.i = b->ptbl.v[l.p].n;
- }
+ 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;
}
- if (l.p + 1 < b->ptbl.n && txt_are_pieces_adjacent(b, l.p, l.p + 1)) {
- b->ptbl.v[l.p].n += b->ptbl.v[l.p+1].n;
- txt_remove_piece(b, l.p + 1);
- if (l.p >= b->ptbl.n) {
- l.p = b->ptbl.n - 1;
- l.i = b->ptbl.v[l.p].n;
+ 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;
}
- if (l.p > 0 && txt_are_pieces_adjacent(b, l.p - 1, l.p)) {
- l.i = b->ptbl.v[l.p - 1].n;
- b->ptbl.v[l.p - 1].n += b->ptbl.v[l.p].n;
- txt_remove_piece(b, l.p);
- l.p--;
- ASSERT(l.p < b->ptbl.n);
- }
- return l;
+ *lp = l;
+ return deleted;
}
static inline TxtLoc resolve_loc(TxtLoc l) {
- if (l.p + 1 < l.t->ptbl.n && l.i == l.t->ptbl.v[l.p].n) {
+ while (l.p + 1 < l.t->ptbl.n && l.i == l.t->ptbl.v[l.p].n) {
l.p++;
l.i = 0;
}
+ ASSERT(txt_valid_loc(l));
return l;
}
+static TxtLoc txt_post_edit(TxtLoc l) {
+ l = resolve_loc(l);
+ ASSERT(txt_valid_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;
+ txt_remove_piece(l.t, l.p);
+ l.p--;
+ ASSERT(txt_valid_loc(l));
+ goto loop;
+ }
+ if (l.p + 1 < l.t->ptbl.n && txt_are_pieces_adjacent(l.t, l.p, l.p + 1)) {
+ l.t->ptbl.v[l.p].n += l.t->ptbl.v[l.p + 1].n;
+ txt_remove_piece(l.t, l.p + 1);
+ ASSERT(txt_valid_loc(l));
+ goto loop;
+ }
+ ASSERT(txt_valid_loc(l));
+ return resolve_loc(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];
@@ -148,9 +165,7 @@ TxtLoc txt_insert(TxtLoc l, const char *s, u32 n) {
p->n += n;
l.t->len += n;
l.i = p->n;
- l = txt_join_or_kill(l);
- l.i = l.t->ptbl.v[l.p].n;
- return resolve_loc(l);
+ return txt_post_edit(l);
}
TxtLoc txt_insert_c(TxtLoc l, u32 ch) {
@@ -166,7 +181,7 @@ TxtLoc txt_delete(TxtLoc l, u32 n) {
l.p = pi;
l.i = l.t->ptbl.v[l.p].n;
for (;;) {
- ASSERT(l.i == l.t->ptbl.v[l.p].n);
+ 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;
@@ -179,9 +194,9 @@ TxtLoc txt_delete(TxtLoc l, u32 n) {
l.p = l.p - 1;
l.i = l.t->ptbl.v[l.p].n;
}
- l = txt_join_or_kill(l);
+ while (txt_trim_empty(&l));
}
- return resolve_loc(txt_join_or_kill(l));
+ return txt_post_edit(l);
}
u32 txt_range_len(TxtLoc lo, TxtLoc hi) {
@@ -270,6 +285,7 @@ void txt_write_range(int fd, TxtLoc lo, TxtLoc hi) {
lo.p++;
lo.i = 0;
}
+ ASSERT(lo.p == hi.p);
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);