diff options
| author | WormHeamer | 2025-12-28 15:59:30 -0500 |
|---|---|---|
| committer | WormHeamer | 2025-12-28 15:59:30 -0500 |
| commit | 6249b0c56d8ae29ae9c533d9fe0d5ae30ef72819 (patch) | |
| tree | ef3901c510ab19ea6419e4fffc2e81c0faeec775 /main.c | |
| parent | 044a0ad2b153781fdab9984b7d1615869765f539 (diff) | |
many changes
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 303 |
1 files changed, 211 insertions, 92 deletions
@@ -18,6 +18,7 @@ Arena scratch = { 0 }; Txt txt = { 0 }; u32 cur = 0; +int mode = 0; int is_space(u32 c) { return c <= 0x20 && c != 0; @@ -85,32 +86,36 @@ TxtLoc start_of_line(Txt *t, TxtLoc l) { return l; } -TxtLoc prev_line(Txt *t, TxtLoc l) { - TxtLoc start = start_of_line(t, l); +TxtLoc end_of_line(Txt *t, TxtLoc l) { + return next_newline(t, start_of_line(t, l)); +} + +u32 get_col(Txt *t, TxtLoc 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); + for (TxtLoc tmp = start_of_line(t, l); txt_before(tmp, l); txt_chr_next(t, &tmp)) n++; + return n; +} + +TxtLoc at_col(Txt *t, TxtLoc l, u32 col) { + l = start_of_line(t, l); + while (col--) { + if (txt_chr_next(t, &l) == '\n') { + l = txt_prev(t, l); break; } } - return start_up; + return l; } -TxtLoc next_line(Txt *t, TxtLoc 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_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; + return at_col(t, txt_prev(t, start), get_col(t, l)); +} + +TxtLoc next_line(Txt *t, TxtLoc l) { + TxtLoc end = end_of_line(t, l); + if (txt_at_end(t, end)) return end; + return at_col(t, txt_next(t, end), get_col(t, l)); } u32 move_line_up(Txt *t, u32 cur) { @@ -122,7 +127,8 @@ u32 move_line_down(Txt *t, u32 cur) { } int empty_line(Txt *t, TxtLoc l) { - return txt_byte(t, start_of_line(t, l)) == '\n'; + u8 b = txt_byte(t, start_of_line(t, l)); + return b == '\n' || b == 0 /* last line of buffer */; } TxtLoc next_par(Txt *t, TxtLoc l) { @@ -180,7 +186,6 @@ void draw(void *ctx) { 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; @@ -198,14 +203,103 @@ void draw(void *ctx) { } } 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); + vui_aprintf(-1, -3, mode ? FG_BCYAN : FG_CYAN, "%s", mode ? "INSERT" : "NORMAL"); + vui_printf(-1, -1, "%u - %u.%u - %02x (%c)", cur, 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 motion(u32 c) { + switch (c) { + case KEY_LEFT: + case 'h': + cur = move_char_back(&txt, cur); + break; + case KEY_LEFT | KEY_CTRL_BIT: + case 'b': + cur = move_word_back(&txt, cur); + break; + case KEY_RIGHT: + case 'l': + cur = move_char_fwd(&txt, cur); + break; + case KEY_RIGHT | KEY_CTRL_BIT: + case 'w': + cur = move_word_fwd(&txt, cur); + break; + case KEY_UP: + case 'k': + cur = move_line_up(&txt, cur); + break; + case KEY_DOWN: + case 'j': + cur = move_line_down(&txt, cur); + break; + case KEY_UP | KEY_CTRL_BIT: + case '{': + cur = move_par_up(&txt, cur); + break; + case KEY_DOWN | KEY_CTRL_BIT: + case '}': + 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: + case '^': + case '0': + cur = txt_ofs(&txt, start_of_line(&txt, txt_at(&txt, cur))); + break; + case KEY_END: + case '$': + cur = txt_ofs(&txt, next_newline(&txt, txt_at(&txt, cur))); + break; + case KEY_HOME | KEY_CTRL_BIT: + case 'g': + cur = 0; + break; + case KEY_END | KEY_CTRL_BIT: + case 'G': + cur = txt.len; + break; + case 'f': { + u32 n = vui_key(); + TxtLoc l = txt_next(&txt, txt_at(&txt, cur)); + for (TxtLoc t = l;;) { + u32 c = txt_chr_next(&txt, &t); + if (c == '\n') break; + if (c == n) { + cur = txt_ofs(&txt, l); + break; + } + l = t; + } + } break; + case 'F': { + u32 n = vui_key(); + TxtLoc l = txt_prev(&txt, txt_at(&txt, cur)); + for (;;) { + u32 c = txt_chr(&txt, l); + if (c == '\n') break; + if (c == n) { + cur = txt_ofs(&txt, l); + break; + } + l = txt_prev(&txt, l); + } + } break; + default: + return 0; + } + return 1; +} + int main(int argc, const char **argv) { scratch = arena_init(1L << 20); vui_init(); @@ -220,77 +314,102 @@ int main(int argc, const char **argv) { draw(NULL); vui_blit(); u32 c = vui_key(); - switch (c) { - case KEY_ESC: - goto brk; - case KEY_BKSP: - cur = txt_delete_c(&txt, cur); - break; - case KEY_LEFT: - cur = move_char_back(&txt, cur); - break; - case KEY_LEFT | KEY_CTRL_BIT: - cur = move_word_back(&txt, cur); - break; - case KEY_RIGHT: - cur = move_char_fwd(&txt, cur); - break; - 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 KEY_HOME | KEY_CTRL_BIT: - cur = 0; - break; - case KEY_END | KEY_CTRL_BIT: - cur = txt.len; - break; - case 0x17 /* ^W */: - cur = del_between(&txt, move_word_back(&txt, cur), cur); - break; - case 0x05 /* ^E */: - cur = del_between(&txt, cur, move_word_fwd(&txt, cur)); - break; - case 0x13 /* ^S */: - txt_save(&txt, path); - //txt_load(&txt, "test.txt"); + switch (mode) { + case 0: + switch (c) { + case 'q': + goto brk; + case 0x13 /* ^S */: + txt_save(&txt, path); + //txt_load(&txt, "test.txt"); + break; + case 'i': + mode = 1; + break; + case 'a': { + mode = 1; + TxtLoc l = txt_at(&txt, cur); + TxtLoc e = end_of_line(&txt, l); + l = txt_before(l, e) ? txt_next(&txt, l) : e; + cur = txt_ofs(&txt, l); + } break; + case 'I': + mode = 1; + cur = txt_ofs(&txt, start_of_line(&txt, txt_at(&txt, cur))); + break; + case 'A': + mode = 1; + cur = txt_ofs(&txt, end_of_line(&txt, txt_at(&txt, cur))); + break; + case 'o': + mode = 1; + cur = txt_ofs(&txt, end_of_line(&txt, txt_at(&txt, cur))); + goto ins_newline; + case 'O': + mode = 1; + cur = txt_ofs(&txt, txt_prev(&txt, start_of_line(&txt, txt_at(&txt, cur)))); + goto ins_newline; + case 'd': { + u32 before = cur; + if (motion(vui_key())) { + del_between(&txt, before, cur); + if (before < cur) cur = before; + } + break; + } + case 'c': { + u32 before = cur; + if (motion(vui_key())) { + del_between(&txt, before, cur); + if (before < cur) cur = before; + } + mode = 1; + break; + } + case 'x': + txt_delete_c(&txt, txt_ofs(&txt, txt_next(&txt, txt_at(&txt, cur)))); + break; + case 's': + txt_delete_c(&txt, txt_ofs(&txt, txt_next(&txt, txt_at(&txt, cur)))); + mode = 1; + break; + default: + if (!motion(c)) {} /* TODO: bell/flash? */ + break; + } break; - case '\r': { - u32 tabs = 0; - TxtLoc start = start_of_line(&txt, txt_at(&txt, cur)); - for (TxtLoc l = start; txt_byte(&txt, l) == '\t'; l = txt_next(&txt, l)) - tabs++; - while (txt_byte(&txt, txt_at(&txt, cur - 1)) == '\t') { - cur = txt_delete(&txt, cur, 1); + case 1: + switch (c) { + case KEY_ESC: + if (txt_after(txt_at(&txt, cur), start_of_line(&txt, txt_at(&txt, cur)))) cur--; + mode = 0; + break; + case KEY_BKSP: + cur = txt_delete_c(&txt, cur); + break; + case 0x17 /* ^W */: + cur = del_between(&txt, move_word_back(&txt, cur), cur); + break; + case 0x05 /* ^E */: + cur = del_between(&txt, cur, move_word_fwd(&txt, cur)); + break; + case '\r': { +ins_newline:; + u32 tabs = 0; + TxtLoc start = start_of_line(&txt, txt_at(&txt, cur)); + for (TxtLoc l = start; txt_byte(&txt, l) == '\t'; l = txt_next(&txt, l)) + tabs++; + while (txt_byte(&txt, txt_at(&txt, cur - 1)) == '\t') { + cur = txt_delete(&txt, cur, 1); + } + cur = txt_insert_c(&txt, cur, '\n'); + while (tabs--) cur = txt_insert_c(&txt, cur, '\t'); + } break; + + default: + if ((c == '\t' || c >= ' ') && c <= KEY_UTF8_MAX) cur = txt_insert_c(&txt, cur, c); + break; } - cur = txt_insert_c(&txt, cur, '\n'); - while (tabs--) cur = txt_insert_c(&txt, cur, '\t'); - } break; - default: - if ((c == '\t' || c >= ' ') && c <= KEY_UTF8_MAX) cur = txt_insert_c(&txt, cur, c); break; } } |
