summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorWormHeamer2025-12-28 15:59:30 -0500
committerWormHeamer2025-12-28 15:59:30 -0500
commit6249b0c56d8ae29ae9c533d9fe0d5ae30ef72819 (patch)
treeef3901c510ab19ea6419e4fffc2e81c0faeec775 /main.c
parent044a0ad2b153781fdab9984b7d1615869765f539 (diff)
many changes
Diffstat (limited to 'main.c')
-rw-r--r--main.c303
1 files changed, 211 insertions, 92 deletions
diff --git a/main.c b/main.c
index 18550ac..bc00618 100644
--- a/main.c
+++ b/main.c
@@ -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;
}
}