summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c185
1 files changed, 93 insertions, 92 deletions
diff --git a/main.c b/main.c
index b0ba567..df92cb3 100644
--- a/main.c
+++ b/main.c
@@ -21,7 +21,7 @@
Arena scratch = { 0 };
Txt txt = { 0 };
-u32 cur = 0;
+TxtLoc cur = { 0 };
int mode = 0;
u32 count = 0;
@@ -137,6 +137,8 @@ int shell_replace(TxtLoc start, TxtLoc end, const char *cmd) {
end = t;
}
+ u32 cur_ofs = txt_range_len(cur, end);
+
int in, out;
int p = popen2(cmd, &in, &out);
if (p < 0) return -1;
@@ -151,24 +153,27 @@ int shell_replace(TxtLoc start, TxtLoc end, const char *cmd) {
}
l = bnext(l);
}
+ txt_write_range(in, start, end);
close(in);
- txt_delete_range(start, end);
+ start = txt_delete_range(start, end);
DYNARR(char) buf = { 0 };
- DA_AFIT(&buf, &scratch, 1024);
+ DA_AFIT(&buf, &scratch, 8192);
for (;;) {
- isize sz = read(out, &buf.v[buf.n], 1024);
+ isize sz = read(out, &buf.v[buf.n], 8192);
if (sz < 0) {
close(out);
return -1;
}
if (!sz) break;
buf.n += sz;
- DA_AFIT(&buf, &scratch, buf.n + 1024);
+ DA_AFIT(&buf, &scratch, buf.n + (-buf.n & 8191) + 8192);
}
-
- start = txt_insert(start, buf.v, buf.n);
close(out);
+
+ end = txt_insert(start, buf.v, buf.n);
+ cur = end;
+ while (cur_ofs--) cur = cprev(cur);
return 0;
}
@@ -177,8 +182,7 @@ int shell_replace(TxtLoc start, TxtLoc end, const char *cmd) {
#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);
+void find_view_window(TxtLoc l, TxtLoc *start, TxtLoc *end) {
u32 u = LINES / 2;
TxtLoc a = l;
for (u32 i = 0; i < u; i++) a = prev_newline(a);
@@ -197,7 +201,7 @@ void draw(void *ctx) {
int lmarg = 0;
int x = lmarg, y = 0;
TxtLoc start, end;
- find_view_window(&txt, cur, &start, &end);
+ find_view_window(cur, &start, &end);
vui_aprintf(-1, 0, ODD_ATTR, "%u piece(s)", txt.ptbl.n);
for (u32 i = 0; i < txt.ptbl.n; i++) {
@@ -206,7 +210,7 @@ void draw(void *ctx) {
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);
+ TxtLoc l = cur;
int cur_found = 0;
while (txt_before(start, end)) {
if (l.p == start.p && l.i == start.i) {
@@ -229,104 +233,106 @@ void draw(void *ctx) {
u32 c = txt_chr(l);
vui_printf(-1, -4, "%u", count);
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);
+ vui_printf(-1, -1, "%u - %u.%u - %02x (%c)", txt_ofs(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) {
- u32 last_cur = cur;
+int motion(TxtLoc *lp, u32 c) {
+ TxtLoc l = *lp;
+ TxtLoc last_loc = l;
loop:
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);
+ l = cprev(l);
break;
case KEY_RIGHT:
case 'l':
- cur = move_char_fwd(&txt, cur);
+ l = cnext(l);
+ break;
+ case KEY_LEFT | KEY_CTRL_BIT:
+ case 'b':
+ l = prev_word(l);
break;
case KEY_RIGHT | KEY_CTRL_BIT:
case 'w':
- cur = move_word_fwd(&txt, cur);
+ l = next_word(l);
break;
case KEY_UP:
case 'k':
- cur = move_line_up(&txt, cur);
+ l = prev_line(l);
break;
case KEY_DOWN:
case 'j':
- cur = move_line_down(&txt, cur);
+ l = next_line(l);
break;
case KEY_UP | KEY_CTRL_BIT:
case '{':
- cur = move_par_up(&txt, cur);
+ l = prev_par(l);
break;
case KEY_DOWN | KEY_CTRL_BIT:
case '}':
- cur = move_par_down(&txt, cur);
+ l = next_par(l);
break;
case KEY_PGUP:
- for (u32 i = 0; i < LINES; i += 3) cur = move_line_up(&txt, cur);
+ for (u32 i = 0; i < LINES; i += 3) l = prev_line(l);
break;
case KEY_PGDN:
- for (u32 i = 0; i < LINES; i += 3) cur = move_line_down(&txt, cur);
+ for (u32 i = 0; i < LINES; i += 3) l = next_line(l);
break;
case KEY_HOME:
case '^':
case '0':
- cur = txt_ofs(start_of_line(txt_at(&txt, cur)));
+ l = start_of_line(l);
break;
case KEY_END:
case '$':
- cur = txt_ofs(next_newline(txt_at(&txt, cur)));
+ l = end_of_line(l);
break;
case KEY_HOME | KEY_CTRL_BIT:
case 'g':
- cur = 0;
+ l = txt_start(&txt);
break;
case KEY_END | KEY_CTRL_BIT:
case 'G':
- cur = txt.len;
+ l = txt_end(&txt);
break;
case 'f': {
- u32 n = vui_key();
- TxtLoc l = cnext(txt_at(&txt, cur));
- for (TxtLoc t = l;;) {
- u32 c = txt_chr_next(&t);
- if (c == '\n' || c == 0) break;
- if (c == n) {
- cur = txt_ofs(l);
+ u32 k = vui_key();
+ TxtLoc t = cnext(l);
+ for (TxtLoc n = l;;) {
+ u32 x = txt_chr_next(&n);
+ if (x == '\n' || x == 0) break;
+ if (x == k) {
+ l = t;
break;
}
- l = t;
+ t = n;
}
} break;
case 'F': {
- u32 n = vui_key();
- TxtLoc l = bprev(txt_at(&txt, cur));
+ u32 k = vui_key();
+ TxtLoc t = cprev(l);
for (;;) {
- u32 c = txt_chr(l);
- if (c == '\n') break;
- if (c == n) {
- cur = txt_ofs(l);
+ u32 x = txt_chr(l);
+ if (x == '\n') break;
+ if (x == k) {
+ l = t;
break;
}
- l = bprev(l);
+ t = bprev(t);
}
} break;
default:
return 0;
}
- if (count > 1 && last_cur != cur) {
+ if (count > 1 && (txt_before(l, last_loc) || txt_after(l, last_loc))) {
count--;
goto loop;
}
count = 0;
+ *lp = l;
return 1;
}
@@ -338,7 +344,7 @@ int main(int argc, const char **argv) {
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;
+ cur = txt_end(&txt);
for (;;) {
scratch.beg = scratch.start;
draw(NULL);
@@ -362,69 +368,64 @@ int main(int argc, const char **argv) {
break;
case 'a': {
mode = 1;
- TxtLoc l = txt_at(&txt, cur);
+ TxtLoc l = cur;
TxtLoc e = end_of_line(l);
l = txt_before(l, e) ? cnext(l) : e;
- cur = txt_ofs(l);
+ cur = l;
} break;
case 'I':
mode = 1;
- cur = txt_ofs(start_of_line(txt_at(&txt, cur)));
+ cur = start_of_line(cur);
break;
case 'A':
mode = 1;
- cur = txt_ofs(end_of_line(txt_at(&txt, cur)));
+ cur = end_of_line(cur);
break;
case 'o':
mode = 1;
- cur = txt_ofs(end_of_line(txt_at(&txt, cur)));
+ cur = end_of_line(cur);
goto ins_newline;
case 'O':
mode = 1;
- cur = txt_ofs(bprev(start_of_line(txt_at(&txt, cur))));
+ cur = bprev(start_of_line(cur));
goto ins_newline;
case 'd': {
- u32 before = cur;
- if (motion(vui_key())) {
- del_between(&txt, before, cur);
- if (before < cur) cur = before;
+ TxtLoc before = cur;
+ if (motion(&cur, vui_key())) {
+ cur = txt_delete_range(before, cur);
}
} break;
- case 'D': {
- u32 end = txt_ofs(end_of_line(txt_at(&txt, cur)));
- del_between(&txt, cur, end);
- } break;
- case 'C': {
- u32 end = txt_ofs(end_of_line(txt_at(&txt, cur)));
- del_between(&txt, cur, end);
+ case 'D':
+ cur = txt_delete_range(cur, end_of_line(cur));
+ break;
+ case 'C':
+ cur = txt_delete_range(cur, end_of_line(cur));
mode = 1;
- } break;
+ break;
case 'S': {
- TxtLoc l = start_of_line(txt_at(&txt, cur));
- u32 end = txt_ofs(end_of_line(l));
- del_between(&txt, txt_ofs(l), end);
- cur = txt_ofs(l);
+ TxtLoc start = start_of_line(cur);
+ TxtLoc end = end_of_line(cur);
+ cur = txt_delete_range(start, end);
mode = 1;
} break;
case 'c': {
- u32 before = cur;
- if (motion(vui_key())) {
- del_between(&txt, before, cur);
- if (before < cur) cur = before;
+ TxtLoc before = cur;
+ if (motion(&cur, vui_key())) {
+ cur = txt_delete_range(before, cur);
+ mode = 1;
}
- mode = 1;
break;
}
case 'x':
- cur = txt_ofs(txt_delete_c(cnext(txt_at(&txt, cur))));
+ cur = txt_delete_c(cnext(cur));
break;
case 's':
- cur = txt_ofs(txt_delete_c(cnext(txt_at(&txt, cur))));
+ cur = txt_delete_c(cnext(cur));
mode = 1;
break;
case '0':
if (!count) {
- motion(c);
+ motion(&cur, c);
break;
}
/* fallthrough */
@@ -433,57 +434,57 @@ int main(int argc, const char **argv) {
count = (count % 100000000) * 10 + c - '0';
break;
case 'M': {
- TxtLoc start = prev_par(txt_at(&txt, cur));
- TxtLoc end = next_par(txt_at(&txt, cur));
+ TxtLoc start = prev_par(cur);
+ TxtLoc end = next_par(cur);
if (shell_replace(start, end, "fmt -w80 -u")) {
err(1, "shell_replace");
}
- if (cur > txt.len) cur = txt.len;
};
default:
- motion(c);
+ motion(&cur, c);
break;
}
break;
case 1:
switch (c) {
case KEY_ESC:
- if (txt_after(txt_at(&txt, cur), start_of_line(txt_at(&txt, cur)))) {
- cur = txt_ofs(cprev(txt_at(&txt, cur)));
+ if (txt_after(cur, start_of_line(cur))) {
+ cur = cprev(cur);
}
mode = 0;
break;
case KEY_BKSP:
- cur = txt_ofs(txt_delete_c(txt_at(&txt, cur)));
+ cur = txt_delete_c(cur);
break;
case 0x17 /* ^W */:
- cur = del_between(&txt, move_word_back(&txt, cur), cur);
+ cur = txt_delete_range(prev_word(cur), cur);
break;
case 0x05 /* ^E */:
- cur = del_between(&txt, cur, move_word_fwd(&txt, cur));
+ cur = txt_delete_range(cur, next_word(cur));
break;
case '\r': {
ins_newline:;
/*
u32 tabs = 0;
- TxtLoc start = start_of_line(txt_at(&txt, cur));
+ 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(txt_at(&txt, cur), 1));
+ cur = txt_ofs(txt_delete(cur, 1));
}
*/
- cur = txt_ofs(txt_insert_c(txt_at(&txt, cur), '\n'));
- //while (tabs--) cur = txt_ofs(txt_insert_c(txt_at(&txt, cur), '\t'));
+ cur = txt_insert_c(cur, '\n');
+ //while (tabs--) cur = txt_ofs(txt_insert_c(cur, '\t'));
} break;
default:
- if ((c == '\t' || c >= ' ') && c <= KEY_UTF8_MAX) cur = txt_ofs(txt_insert_c(txt_at(&txt, cur), c));
+ if ((c == '\t' || c >= ' ') && c <= KEY_UTF8_MAX) cur = txt_insert_c(cur, c);
break;
}
break;
}
if (mode == 1) count = 0;
+ ASSERT(txt_valid_loc(cur));
}
brk:
vui_fini();