diff options
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 179 |
1 files changed, 145 insertions, 34 deletions
@@ -69,62 +69,149 @@ u32 del_between(Txt *t, u32 a, u32 b) { return txt_delete(t, b, b - a); } +TxtLoc next_newline(Txt *t, TxtLoc l) { + do l = txt_next(t, l); + while (!txt_at_end(t, l) && txt_byte(t, l) != '\n'); + return l; +} + +TxtLoc prev_newline(Txt *t, TxtLoc l) { + do l = txt_prev(t, l); + while (!txt_at_start(t, l) && txt_byte(t, l) != '\n'); + return l; +} + +TxtLoc start_of_line(Txt *t, TxtLoc l) { + l = prev_newline(t, l); + if (!txt_at_start(t,l) && txt_byte(t, l) == '\n') l = txt_next(t, l); + return l; +} + +TxtLoc prev_line(Txt *t, TxtLoc l) { + TxtLoc start = start_of_line(t, l); + u32 n = 0; + for (TxtLoc tmp = start; txt_before(tmp, l); txt_chr_next(t, &tmp)) n++; + TxtLoc start_up = start_of_line(t, txt_prev(t, start)); + while (n--) { + if (txt_chr_next(t, &start_up) == '\n') { + start_up = txt_prev(t, start_up); + break; + } + } + return start_up; +} + +TxtLoc next_line(Txt *t, TxtLoc l) { + TxtLoc start = start_of_line(t, l); + u32 n = 0; + for (TxtLoc tmp = start; txt_before(tmp, l); txt_chr_next(t, &tmp)) n++; + TxtLoc start_dn = txt_byte(t, l) == '\n' ? txt_next(t, l) : txt_next(t, next_newline(t, l)); + while (n--) { + if (txt_chr_next(t, &start_dn) == '\n') { + start_dn = txt_prev(t, start_dn); + break; + } + } + return start_dn; +} + +u32 move_line_up(Txt *t, u32 cur) { + return txt_ofs(t, prev_line(t, txt_at(t, cur))); +} + +u32 move_line_down(Txt *t, u32 cur) { + return txt_ofs(t, next_line(t, txt_at(t, cur))); +} + +int empty_line(Txt *t, TxtLoc l) { + return txt_byte(t, start_of_line(t, l)) == '\n'; +} + +TxtLoc next_par(Txt *t, TxtLoc l) { + while (!txt_at_end(t, l) && empty_line(t, l)) l = next_line(t, l); + while (!txt_at_end(t, l) && !empty_line(t, l)) l = next_line(t, l); + return l; +} + +TxtLoc prev_par(Txt *t, TxtLoc l) { + while (!txt_at_start(t, l) && empty_line(t, l)) l = prev_line(t, l); + while (!txt_at_start(t, l) && !empty_line(t, l)) l = prev_line(t, l); + return l; +} + +u32 move_par_up(Txt *t, u32 cur) { + return txt_ofs(t, prev_par(t, txt_at(t, cur))); +} + +u32 move_par_down(Txt *t, u32 cur) { + return txt_ofs(t, next_par(t, txt_at(t, cur))); +} + /* main */ #define ODD_ATTR (FG_CYAN | BG_BLACK) #define EVEN_ATTR (FG_WHITE | BG_BLACK) +void find_view_window(Txt *t, u32 curs, TxtLoc *start, TxtLoc *end) { + TxtLoc l = txt_at(t, curs); + u32 n = LINES; + u32 u = LINES / 2; + TxtLoc a = l; + for (u32 i = 0; i < u; i++) a = prev_newline(t, a); + TxtLoc b = a; + while (!txt_at_end(t, b) && n--) b = next_newline(t, b); + if (!txt_at_start(t,a) && txt_byte(t,a) == '\n') a = txt_next(t, a); + *start = a; + *end = b; +} + void draw(void *ctx) { (void)ctx; -redraw:; vui_clear(); - static int max_y = 0; int x = 0, y = 0; - u32 ofs = 0; + TxtLoc start, end; + find_view_window(&txt, cur, &start, &end); + + vui_aprintf(-1, 0, ODD_ATTR, "%u pieces", txt.ptbl.n); for (u32 i = 0; i < txt.ptbl.n; i++) { - Arena stk = scratch; TxtPiece *p = &txt.ptbl.v[i]; - const char *s = txt.buf[p->buf].s + p->ofs; - - u32 bufn = utf8_decode_len(s, p->n); - u32 *buf = new_arr(&scratch, u32, bufn); - utf8_decode(buf, s, bufn); - VuiAttr a = i&1 ? ODD_ATTR : EVEN_ATTR; - vui_aprintf(-1, i, a, "%u, %u (%s)", p->ofs, p->n, p->buf == TXT_ADD ? "add" : "src"); - - for (u32 j = 0; j < bufn; j++) { - u32 c = buf[j]; - if (ofs == cur) vui_curs_pos(x, y - (max_y - LINES + 1)); - if (c != '\r' && c != '\n') { - vui_chra(x++, y - (max_y - LINES + 1), c, a); - } - if (c == '\n') { - x = 0; - y++; - } - ofs += UTF8_CP_LEN(c); - } - scratch = stk; - } - if (ofs == cur) vui_curs_pos(x, y - (max_y - LINES + 1)); - if (y > max_y) { - max_y = y; - goto redraw; + vui_aprintf(-1, i+1, a, "%u, %u (%s)", p->ofs, p->n, p->buf == TXT_ADD ? "add" : "src"); } + TxtLoc l = txt_at(&txt, cur); + int cur_found = 0; + vui_printf(-1, -3, "(%u.%u)-(%u.%u)", start.p, start.i, end.p, end.i); + while (txt_before(start, end)) { + if (l.p == start.p && l.i == start.i) { + cur_found = 1; + vui_curs_pos(x, y); + } + u32 c = txt_chr_next(&txt, &start); + if (c == '\n') { + x = 0; + y++; + } else if (c) { + vui_chr(x++, y, c); + } + } + ASSERT(start.i <= txt.ptbl.v[start.p].n); + vui_printf(-1, -4, "end(%u.%u)", start.p, start.i); + if (!cur_found) vui_curs_pos(x, y); u32 c = txt_chr(&txt, l); vui_printf(-1, -1, "%u, %u - %02x (%c)", l.p, l.i, c, (c < 0x20 || c > 0x7e) ? ' ' : c); u32 used = scratch.beg - scratch.start, max = scratch.end - scratch.start; vui_printf(-1, -2, "scratch %.02f/%.02fk", used/1024.0, max/1024.0); } -int main(void) { +int main(int argc, const char **argv) { scratch = arena_init(1L << 20); vui_init(); vui_curs_vis(1); vui_redraw_fn(draw); - if (txt_load(&txt, "test.txt")) err(1, "couldn't open file"); + const char *path = "test.txt"; + if (argc > 1) path = argv[1]; + if (txt_load(&txt, path)) err(1, "couldn't open file"); cur = txt.len; for (;;) { scratch.beg = scratch.start; @@ -149,6 +236,30 @@ int main(void) { case KEY_RIGHT | KEY_CTRL_BIT: cur = move_word_fwd(&txt, cur); break; + case KEY_UP: + cur = move_line_up(&txt, cur); + break; + case KEY_DOWN: + cur = move_line_down(&txt, cur); + break; + case KEY_UP | KEY_CTRL_BIT: + cur = move_par_up(&txt, cur); + break; + case KEY_DOWN | KEY_CTRL_BIT: + cur = move_par_down(&txt, cur); + break; + case KEY_PGUP: + for (u32 i = 0; i < LINES; i += 3) cur = move_line_up(&txt, cur); + break; + case KEY_PGDN: + for (u32 i = 0; i < LINES; i += 3) cur = move_line_down(&txt, cur); + break; + case KEY_HOME: + cur = txt_ofs(&txt, start_of_line(&txt, txt_at(&txt, cur))); + break; + case KEY_END: + cur = txt_ofs(&txt, next_newline(&txt, txt_at(&txt, cur))); + break; case 0x17 /* ^W */: cur = del_between(&txt, move_word_back(&txt, cur), cur); break; @@ -156,8 +267,8 @@ int main(void) { cur = del_between(&txt, cur, move_word_fwd(&txt, cur)); break; case 0x13 /* ^S */: - txt_save(&txt, "test.txt"); - txt_load(&txt, "test.txt"); + txt_save(&txt, path); + //txt_load(&txt, "test.txt"); break; case '\r': cur = txt_insert_c(&txt, cur, '\n'); |
