summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorWormHeamer2025-12-28 02:45:38 -0500
committerWormHeamer2025-12-28 02:45:38 -0500
commit9f4310c24ca39284ad768a82d368e749b18fd76c (patch)
tree0563d7b351de59e395315381a113a936e1382669 /main.c
parent54e30f7e1a3269946bcffd0bb293c7f4f39eda7c (diff)
put more emphasis on TxtLoc
Diffstat (limited to 'main.c')
-rw-r--r--main.c163
1 files changed, 155 insertions, 8 deletions
diff --git a/main.c b/main.c
index e367825..3862625 100644
--- a/main.c
+++ b/main.c
@@ -1,27 +1,174 @@
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
+#include <ctype.h>
+#include <err.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#define ARENA_IMPL
+#define UTF8_IMPL
#include "wrmr.h"
#include "arena.h"
#include "txt.h"
+#include "vui.h"
+#include "utf8.h"
-int main(void) {
- Arena a = arena_init(1L << 20);
- Txt txt = { 0 };
- txt_open(&txt, "test.txt");
- txt_insert(&txt, txt.len, "wheeee", 6);
- txt_delete(&txt, txt.len, 6);
+Arena scratch = { 0 };
+Txt txt = { 0 };
+u32 cur = 0;
+
+int is_space(u32 c) {
+ return c <= 0x20 && c != 0;
+}
+
+u32 move_word_back(Txt *t, u32 cur) {
+ TxtLoc l = txt_at(t, cur);
+ while (!txt_at_start(t,l)) {
+ TxtLoc n = txt_prev(t, l);
+ if (!is_space(txt_chr(t, n))) break;
+ l = n;
+ }
+ while (!txt_at_start(t,l)) {
+ TxtLoc n = txt_prev(t, l);
+ if (is_space(txt_chr(t, n))) break;
+ l = n;
+ }
+ return txt_ofs(t, l);
+}
+
+u32 move_word_fwd(Txt *t, u32 cur) {
+ TxtLoc l = txt_at(t, cur);
+ while (!txt_at_end(t,l) && is_space(txt_chr(t, l))) l = txt_next(t, l);
+ while (!txt_at_end(t,l) && !is_space(txt_chr(t, l))) l = txt_next(t, l);
+ return txt_ofs(t, l);
+}
+
+u32 move_char_back(Txt *t, u32 cur) {
+ while (cur > 0) {
+ cur--;
+ u8 c = txt_byte(t, txt_at(t, cur));
+ if ((c & 0xc0) != 0x80) break;
+ }
+ return cur;
+}
+
+u32 move_char_fwd(Txt *t, u32 cur) {
+ u8 b = txt_byte(t, txt_at(t, cur));
+ u32 n = stdc_leading_ones(b);
+ if (cur + n >= t->len) return t->len;
+ return cur + n + !n;
+}
+
+u32 del_between(Txt *t, u32 a, u32 b) {
+ if (b < a) { u32 t = a; a = b; b = t; }
+ //if (b - a > 10) TRAP();
+ return txt_delete(t, b, b - a);
+}
+
+/* main */
+
+#define ODD_ATTR (FG_CYAN | BG_BLACK)
+#define EVEN_ATTR (FG_WHITE | BG_BLACK)
+
+void draw(void *ctx) {
+ (void)ctx;
+redraw:;
+ vui_clear();
+ static int max_y = 0;
+ int x = 0, y = 0;
+ u32 ofs = 0;
for (u32 i = 0; i < txt.ptbl.n; i++) {
+ Arena stk = scratch;
TxtPiece *p = &txt.ptbl.v[i];
- printf("%u. %.*s\n", i, (int)p->n, txt.buf[p->buf].s + p->ofs);
+ 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;
+ }
+ TxtLoc l = txt_at(&txt, cur);
+ 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) {
+ 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");
+ cur = txt.len;
+ for (;;) {
+ scratch.beg = scratch.start;
+ 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 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, "test.txt");
+ txt_load(&txt, "test.txt");
+ break;
+ case '\r':
+ cur = txt_insert_c(&txt, cur, '\n');
+ break;
+ default:
+ if (c >= ' ' && c <= KEY_UTF8_MAX) cur = txt_insert_c(&txt, cur, c);
+ break;
+ }
}
- arena_free(&a);
+brk:
+ vui_fini();
+ arena_free(&scratch);
return 0;
}