diff options
| -rw-r--r-- | main.c | 57 | ||||
| -rw-r--r-- | txt.c | 86 |
2 files changed, 92 insertions, 51 deletions
@@ -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(); @@ -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); |
