stew

a monorepo of some sort
Log | Files | Refs

commit 72d7d4897d2f50c80daa55551156b483b69661d7
parent bb5fd5b9fcff1364b2bea20ebaaa8ae3436a32f7
Author: Renev Pavel <an2qzavok@gmail.com>
Date:   Sun, 27 Nov 2022 22:24:44 +0000

tabul: more code

Diffstat:
Msrc/tabul/tabul.c | 233+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 193 insertions(+), 40 deletions(-)

diff --git a/src/tabul/tabul.c b/src/tabul/tabul.c @@ -1,14 +1,14 @@ /* - Simple graphical editor for tsv files + Primitive editor for tsv files */ #include <u.h> #include <libc.h> #include <bio.h> -// #include <String.h> +#include <String.h> #include <thread.h> #include <draw.h> -// #include <keyboard.h> +#include <keyboard.h> #include <mouse.h> typedef struct Ed Ed; @@ -21,13 +21,24 @@ struct Ed { }; Ed *head; - Image *bord, *text, *bg, *curbg; -Rectangle cell, cells, edit; +Rectangle cell, cells; Point cur; Mousectl *mctl; +Keyboardctl *kctl; Mouse mv; int rv[2]; +Rune kv; +char *file; + +struct { + Rectangle r; + struct { + int s; + int e; + } sel; + String *str; +} edit; Ed * ed(Ed *parent, int x, int y, char *s) @@ -37,30 +48,41 @@ ed(Ed *parent, int x, int y, char *s) return e; } -/* + void freeed(Ed *e) { - if (e != nil) { - free(e->s); - free(e); - } + if (e != nil) free(e->s), free(e); +} + + +Ed * +getcell(Point p) +{ + Ed *ep = head; + while ((ep != nil) && ((ep->x != p.x) || (ep->y != p.y))) + ep = ep->prev; + return ep; } -*/ void -loadfile(char *file) +loadfile(char *newfile) { char *s, *args[64]; int n, x, y = 0; - Biobuf *b = Bopen(file, OREAD); - if (b == nil) sysfatal("loadfile: %r"); - + Biobuf *b = Bopen(newfile, OREAD); + if (b == nil) { + fprint(2, "loadfile: %r\n"); + return; + } + free(file); + file = newfile; while( (s = Brdstr(b, '\n', 1)) != nil ) { n = getfields(s, args, 64, 0, "\t"); for (x = 0; x < n; x++) { - head = ed(head, x, y, args[x]); + head = ed(head, x, y, strdup(args[x])); }; + free(s); y++; } Bterm(b); @@ -76,6 +98,22 @@ savefile(char *) } void +flushedit(void) +{ + Ed *ep = getcell(cur); + if (strcmp(s_to_c(edit.str), ep->s) != 0) + head = ed(head, cur.x, cur.y, strdup(s_to_c(edit.str))); +} + +void +setedit(void) +{ + Ed *ep = getcell(cur); + s_reset(edit.str); + if (ep != nil) s_append(edit.str, ep->s); +} + +void drawcell(int x, int y) { Ed *ep; @@ -84,28 +122,48 @@ drawcell(int x, int y) Rectangle r = rectaddpt(cell, addpt(Pt(x * cell.max.x, y * cell.max.y), cells.min)); draw(screen, r, bord, nil, ZP); draw(screen, insetrect(r, 1), cellbg, nil, ZP); - for (ep = head; ep != nil; ep = ep->prev) { - if ((ep->x == x) && (ep->y == y)) { - stringn(screen, addpt(r.min, Pt(3, 3)), text, ZP, font, ep->s, 8); - break; - } + ep = getcell(Pt(x, y)); + if (ep != nil) stringn(screen, addpt(r.min, Pt(3, 3)), text, ZP, font, ep->s, 8); +} + +void +drawedit(void) +{ + char buf[256]; + snprint(buf, 16, "[%d %d] ", cur.x, cur.y); + draw(screen, edit.r, curbg, nil, ZP); + Point p = edit.r.min; + if (edit.str != nil) { + strncat(buf, s_to_c(edit.str), 256 - strlen(buf)); } + string(screen, p, text, ZP, font, buf); } void resize(void) { - edit = Rpt( + edit.r = Rpt( screen->r.min, - Pt(screen->r.max.x, screen->r.min.y + font->height + 2) + Pt(screen->r.max.x, screen->r.min.y + font->height) ); cells = Rpt( - addpt(screen->r.min, Pt(0, Dy(edit))), + addpt(screen->r.min, Pt(0, Dy(edit.r))), screen->r.max ); } void +redraw(void) +{ + int x, y, maxx, maxy; + maxx = Dx(cells) / cell.max.x; + maxy = Dy(cells) / cell.max.y; + drawedit(); + for (x = 0; x <= maxx; x++) for (y = 0; y <= maxy; y++) + drawcell(x, y); +} + +void colors(void) { bord = display->black; @@ -115,44 +173,139 @@ colors(void) } void +mouse(Mouse m) +{ + if (m.buttons == 1) { + if (ptinrect(m.xy, cells) != 0) { + Point mr = subpt(m.xy, cells.min); + Point newcur = Pt(mr.x / cell.max.x, mr.y / cell.max.y); + if ((cur.x != newcur.x) || (cur.y != newcur.y)) { + Point oldcur = cur; + cur = newcur; + drawcell(oldcur.x, oldcur.y); + drawcell(newcur.x, newcur.y); + setedit(); + drawedit(); + flushimage(display, 1); + } + } + } else if (m.buttons == 4) { + static char *items[] = {"load", "save", nil}; + static Menu menu = { + items, + nil, + 0, + }; + char buf[1024]; + buf[0] = '\0'; + if (file != nil) strncat(buf, file, 1024); + switch (menuhit(3, mctl, &menu, nil)) { + case 0: + if (enter("load", buf, 1024, mctl, kctl, nil) > 0) { + while (head != nil) { + Ed *prev = head->prev; + freeed(head); + head = prev; + } + loadfile(strdup(buf)); + redraw(); + flushimage(display, 1); + } + break; + case 1: + if (enter("save", buf, 1024, mctl, kctl, nil) > 0) { + savefile(strdup(buf)); + } + break; + } + } +} + +void +kbd(Rune r) +{ + switch (r) { + case 0x7f: /* del */ + threadexitsall(nil); + case 0x0a: /* newline */ + flushedit(); + drawcell(cur.x, cur.y); + flushimage(display, 1); + break; + case 0x09: /* tab */ + flushedit(); + cur.x++; + setedit(); + drawedit(); + drawcell(cur.x, cur.y); + drawcell(cur.x-1, cur.y); + flushimage(display, 1); + break; + case 0x08: /* backspace */ + // TODO: make utf8-complaint, make thread safe? + if (edit.str->ptr > edit.str->base) edit.str->ptr--; + s_terminate(edit.str); + drawedit(); + flushimage(display, 1); + break; + default: + s_putc(edit.str, r); + s_terminate(edit.str); + drawedit(); + flushimage(display, 1); + } +} + +void +init(void) +{ + if (initdraw(nil, nil, "tabul") == 0) sysfatal("%r"); + colors(); + mctl = initmouse(nil, screen); + kctl = initkeyboard(nil); + cell = Rect(0, 0, stringwidth(font, "0") * 8 + 4, font->height + 4); + edit.str = s_new(); + cur = ZP; + setedit(); + resize(); + redraw(); + flushimage(display, 1); +} + +void usage(void) { - fprint(2, "usage: %s [tsv file]\n", argv0); + fprint(2, "usage: %s [tsv_file]\n", argv0); + threadexitsall("usage"); } void threadmain(int argc, char **argv) { - int x, y; ARGBEGIN { default: usage(); } ARGEND; - if (argc == 1) loadfile(argv[0]); - if (initdraw(nil, nil, "tabul") == 0) sysfatal("%r"); - colors(); - mctl = initmouse(0, screen); - cell = Rect(0, 0, stringwidth(font, "0") * 8 + 6, font->height + 6); - resize(); - draw(screen, edit, curbg, nil, ZP); - for (x = 0; x < 10; x++) for (y = 0; y < 24; y++) - drawcell(x, y); - flushimage(display, 1); + if (argc == 1) loadfile(strdup(argv[0])); + init(); Alt alts[] = { {mctl->c, &mv, CHANRCV}, {mctl->resizec, rv, CHANRCV}, + {kctl->c, &kv, CHANRCV}, {0, 0, CHANEND}, }; for(;;){ switch(alt(alts)) { case 0: /* mouse */ + mouse(mv); break; case 1: /* resize */ if (getwindow(display, Refnone) < 0) sysfatal("%r"); resize(); - draw(screen, edit, curbg, nil, ZP); - for (x = 0; x < 10; x++) for (y = 0; y < 24; y++) - drawcell(x, y); - flushimage(display, 1); + redraw(); + flushimage(display, 1); + break; + case 2: /* keyboard */ + kbd(kv); break; } }