From 07b3782804272abce9ada300e96fa141e359b359 Mon Sep 17 00:00:00 2001 From: WormHeamer Date: Fri, 2 Jan 2026 03:00:29 -0500 Subject: convert non-utf-8 files to a readonly hex dump --- main.c | 91 +++++++++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 57 insertions(+), 34 deletions(-) (limited to 'main.c') diff --git a/main.c b/main.c index 9325a11..f9cf22e 100644 --- a/main.c +++ b/main.c @@ -30,7 +30,8 @@ typedef enum { ED_BUF_SCRATCH, - ED_BUF_FILE + ED_BUF_FILE, + ED_BUF_BIN_FILE } EditBufType; typedef struct { @@ -56,7 +57,7 @@ static const char *mode_key_str[] = { }; typedef struct { - Arena scratch; + Arena perm, scratch; EditBuf buf[ED_BUF_MAX]; u32 bufn, bufi; Txt *txt_free; @@ -84,6 +85,8 @@ typedef struct { Editor e = { 0 }; +int ed_buf_shell_replace(Editor *e, u32 bufi, TxtLoc start, TxtLoc end, const char *cmd); + static Str normalize_path(Str s); int ed_buf_open(Editor *e, const char *path) { Str paths = { 0 }; @@ -95,26 +98,32 @@ int ed_buf_open(Editor *e, const char *path) { } if (e->bufn == ED_BUF_MAX) return -1; - EditBuf b = { 0 }; - b.arena = arena_init(1L << 30); - b.txt = FREELIST_NEW(&e->txt_free, &b.arena); + EditBuf *b = &e->buf[e->bufn]; + memset(b, 0, sizeof(EditBuf)); + b->arena = arena_init(1L << 30); + b->txt = FREELIST_NEW(&e->txt_free, &e->perm); if (path) { - b.path = str_dup(paths, &b.arena); - b.type = ED_BUF_FILE; - txt_load(b.txt, path); + b->path = str_dup(paths, &b->arena); + b->type = ED_BUF_FILE; + txt_load(b->txt, path); + if (!utf8_validate(b->txt->buf[TXT_SRC].s, b->txt->buf[TXT_SRC].n)) { + ed_buf_shell_replace(e, e->bufn, txt_start(b->txt), txt_end(b->txt), "xxd"); + b->txt->readonly = 1; + b->type = ED_BUF_BIN_FILE; + } } else { - b.path = S("*scratch*"); - b.type = ED_BUF_SCRATCH; - txt_load_empty(b.txt); + b->path = S("*scratch*"); + b->type = ED_BUF_SCRATCH; + txt_load_empty(b->txt); } - b.cur = txt_end(b.txt); - txt_hist_push(b.txt, b.cur); - e->buf[e->bufn] = b; + b->cur = txt_end(b->txt); + b->txt->ptbl.dirty = 0; + txt_hist_push(b->txt, b->cur); return e->bufn++; } -void ed_buf_free(EditBuf *b) { - txt_free(b->txt); +void ed_buf_free(Editor *e, EditBuf *b) { + FREELIST_FREE(&e->txt_free, b->txt); arena_free(&b->arena); } @@ -127,6 +136,7 @@ void ed_buf_change_path(Editor *e, u32 i, Str s) { void ed_init(Editor *e) { memset(e, 0, sizeof(Editor)); e->scratch = arena_init(1L << 30); + e->perm = arena_init(1L << 30); e->bufi = ed_buf_open(e, NULL); Str s = S("(Scratch buffer, type whatever)"); e->buf[e->bufi].cur = txt_insert(e->buf[e->bufi].cur, s.s, s.n); @@ -135,14 +145,14 @@ void ed_init(Editor *e) { void ed_fini(Editor *e) { for (u32 i = 0; i < e->bufn; i++) { - ed_buf_free(&e->buf[i]); + ed_buf_free(e, &e->buf[i]); } if (e->search.s) free(e->search.s); if (e->yank.s) free(e->yank.s); } u32 ed_buf_close(Editor *e, u32 i) { - ed_buf_free(&e->buf[i]); + ed_buf_free(e, &e->buf[i]); if (i + 1 < e->bufn) { MOVE(&e->buf[i], &e->buf[i+1], e->bufn - (i + 1)); } @@ -150,15 +160,6 @@ u32 ed_buf_close(Editor *e, u32 i) { return i > 0 ? i - 1 : 0; } -int ed_buf_save(Editor *e, u32 i) { - EditBuf *b = &e->buf[i]; - if (b->type == ED_BUF_FILE) { - return txt_save(b->txt, str_to_cstr(b->path, &e->scratch)); - } else { - return 0; - } -} - Str str_printf(Arena *a, const char *fmt, ...) { va_list ap; va_start(ap, fmt); @@ -171,6 +172,17 @@ Str str_printf(Arena *a, const char *fmt, ...) { return (Str) { buf, n }; } +int ed_buf_save(Editor *e, u32 i) { + EditBuf *b = &e->buf[i]; + if (b->type == ED_BUF_FILE || b->type == ED_BUF_BIN_FILE) { + e->msg = str_printf(&e->scratch, "%.02fk written", b->txt->len / 1024.0); + return txt_save(b->txt, str_to_cstr(b->path, &e->scratch)); + } else { + e->msg = S("unwriteable file type"); + return 0; + } +} + static inline int is_space(u32 c) { return c <= 0x20 && c != 0; } @@ -362,7 +374,7 @@ int popen2(const char *cmd, int *in, int *out) { return p; } -int shell_replace(TxtLoc start, TxtLoc end, const char *cmd) { +int ed_buf_shell_replace(Editor *e, u32 bufi, TxtLoc start, TxtLoc end, const char *cmd) { if (txt_before(end, start)) { TxtLoc t = start; start = end; @@ -377,7 +389,7 @@ int shell_replace(TxtLoc start, TxtLoc end, const char *cmd) { { .fd = in, .events = POLLOUT }, { .fd = out, .events = POLLIN } }; - Str wrs = txt_collect_range(start, end, &e.scratch); + Str wrs = txt_collect_range(start, end, &e->scratch); DYNARR(char) rds = { 0 }; u32 wr_i = 0; while ((pfds[0].fd >= 0 || pfds[1].fd >= 0) && poll(pfds, 2, 200) >= 0) { @@ -397,7 +409,7 @@ int shell_replace(TxtLoc start, TxtLoc end, const char *cmd) { pfds[0].fd = -1; } if (pfds[1].revents & POLLIN) { - DA_AFIT(&rds, &e.scratch, rds.n + (-rds.n & (chunksz-1)) + chunksz); + DA_AFIT(&rds, &e->scratch, rds.n + (-rds.n & (chunksz-1)) + chunksz); isize r = read(out, &rds.v[rds.n], chunksz); if (r > 0) { rds.n += r; @@ -419,7 +431,7 @@ int shell_replace(TxtLoc start, TxtLoc end, const char *cmd) { * final one until it matches or gets too small. */ if (!txt_range_equal(start, end, (Str){rds.v,rds.n})) { - EditBuf *eb = &e.buf[e.bufi]; + EditBuf *eb = &e->buf[bufi]; u32 b = txt_ofs(eb->cur); start = txt_delete_range(start, end); end = txt_insert(start, rds.v, rds.n); @@ -428,6 +440,10 @@ int shell_replace(TxtLoc start, TxtLoc end, const char *cmd) { return 0; } +int shell_replace(TxtLoc start, TxtLoc end, const char *cmd) { + return ed_buf_shell_replace(&e, e.bufi, start, end, cmd); +} + #define ANY_KEY_PROMPT "[Press any key to resume editing]" static void press_any_key(void) { @@ -524,7 +540,7 @@ void draw_buf(EditBuf *eb) { VuiAttr a = i == e.bufi ? sel : norm; Str p = basename(b->path); x += vui_aprintf(x, y, a, " %.*s", (int)p.n, p.s); - if (b->type == ED_BUF_FILE && b->txt->ptbl.dirty) { + if (b->type != ED_BUF_SCRATCH && b->txt->ptbl.dirty) { x += vui_putsa(x, y, "* ", a); } else { vui_chra(x++, y, ' ', a); @@ -554,7 +570,7 @@ void draw_buf(EditBuf *eb) { if (c == '\n') { x = lmarg; y++; - } else if (is_space(c)) { + } else if (c == '\n' || c == '\t' || c == ' ') { VuiAttr a = txt_chr(start) == '\n' ? trailsp : txt; if (c == '\t') { u32 n = 1 + (-(x+1) & 7); @@ -562,8 +578,14 @@ void draw_buf(EditBuf *eb) { } else { vui_chra(x++, y, ' ', a); } + } else if (c < 0x20) { + x += vui_aprintf(x, y, FG_CYAN, "<%02>", c); } else if (c) { vui_chra(x++, y, c, txt); + } else if (x >= COLS) { + start = next_line_start(start); + x = lmarg; + y++; } } @@ -1373,7 +1395,6 @@ void mode_key_normal(Editor *e, u32 c) { case 'Z': case 0x13 /* ^S */: ed_buf_save(e, e->bufi); - e->msg = str_printf(&e->scratch, "%.02fk written", eb->txt->len / 1024.0); if (c == 'Z') e->bufi = ed_buf_close(e, e->bufi); break; case 'i': @@ -1677,6 +1698,8 @@ int main(int argc, const char **argv) { vui_redraw_ctx(&e); while (e.bufn > 0) { + ASSERT(e.bufi < e.bufn); + ASSERT(e.buf[e.bufi].cur.t == e.buf[e.bufi].txt); draw(NULL); arena_reset(&e.scratch); /* must happen after draw, so e.msg can persist */ vui_blit(); -- cgit v1.2.3