richterm

"terminal emulator" with support for text fonts and images for plan9
git clone git://nsmpr.xyz/richterm.git
Log | Files | Refs | README

commit 191b0d598e6c8cd4d503794475e6d89dc89c7ede
parent a4b59540530dc03ec5cc0cdf141b3e40c9a7c954
Author: Pavel Renev <an2qzavok@gmail.com>
Date:   Mon, 16 Aug 2021 22:32:29 +0000

add middle-click menu (broken), add TODO

Diffstat:
ATODO | 5+++++
Mrichterm.c | 193+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Mrichterm.h | 6++----
3 files changed, 157 insertions(+), 47 deletions(-)

diff --git a/TODO b/TODO @@ -0,0 +1,5 @@ +Use single buffer array for text. +Only store pointer offset in objects, so that offset of next obj is treated as end of current obj. + +Remove Views and draw Objects directly, maybe even letter by letter. +Keep track of object's positional info, such as start point, end poit and next line offset. diff --git a/richterm.c b/richterm.c @@ -11,15 +11,39 @@ #include "array.h" #include "richterm.h" +void resize(void); +void shutdown(void); +void send_interrupt(void); +void runcmd(void *); +void scroll(Point, Rich *); +void mouse(Mousectl *, Mouse, int *); +usize getsel(Point p); +View * getview(Point p); + +void mpaste(Rich *); +void msnarf(Rich *); +void mplumb(Rich *); +void msend(Rich *); + Rich rich; int hostpid = -1; Channel *pidchan; +Mousectl *mctl; +Keyboardctl *kctl; Devfsctl *dctl; Fsctl *fsctl; Array *fonts; Image *Iscrollbar, *Ilink, *Inormbg, *Iselbg; +// Image *It1, *It2, *It3; +char *mitems[] = {"paste", "snarf", "plumb", nil}; +void (*mfunc[])(Rich *) = {mpaste, msnarf, mplumb, nil}; + +struct Menu mmenu = { + .item = mitems, + .gen = nil, + .lasthit = 0, +}; -Image *It1, *It2, *It3; Object *olast; @@ -30,15 +54,6 @@ enum { MM_SELECT, }; -void resize(void); -void shutdown(void); -void send_interrupt(void); -void runcmd(void *); -void scroll(Point, Rich *); -void mouse(Mouse, int *); -usize getsel(Point p); -View * getview(Point p); - void usage(void) { @@ -50,8 +65,6 @@ void threadmain(int argc, char **argv) { Font **fp; - Mousectl *mctl; - Keyboardctl *kctl; int rv[2], mmode; Mouse mv; Rune kv; @@ -84,16 +97,6 @@ threadmain(int argc, char **argv) Ilink = allocimage( display, Rect(0,0,1,1), screen->chan, 1, DBlue); - - It1 = allocimage( - display, Rect(0,0,1,1), screen->chan, 1, DRed); - It2 = allocimage( - display, Rect(0,0,1,1), screen->chan, 1, DGreen); - It3 = allocimage( - display, Rect(0,0,1,1), screen->chan, 1, DYellow); - - - fonts = arraycreate(sizeof(Font *), 2, nil); fp = arrayadd(fonts); *fp = font; @@ -103,13 +106,10 @@ threadmain(int argc, char **argv) qlock(rich.l); rich.objects = arraycreate(sizeof(Object *), 8, nil); - rich.page.views = arraycreate(sizeof(View), 8, nil); + rich.views = arraycreate(sizeof(View), 8, nil); rich.page.scroll = ZP; - rich.page.selstart = 0; - rich.page.selend = 0; - qunlock(rich.l); olast = newobject(&rich, nil); @@ -135,7 +135,7 @@ threadmain(int argc, char **argv) for (;;) { switch(alt(alts)) { case MOUSE: - mouse(mv, &mmode); + mouse(mctl, mv, &mmode); break; case RESIZE: if (getwindow(display, Refnone) < 0) @@ -222,7 +222,7 @@ threadmain(int argc, char **argv) } void -mouse(Mouse mv, int *mmode) +mouse(Mousectl *mc, Mouse mv, int *mmode) { View *v; @@ -281,6 +281,12 @@ mouse(Mouse mv, int *mmode) redraw(0); *mmode = MM_SELECT; } + if (mv.buttons == 2) { + int f; + f = menuhit(2, mc, &mmenu, nil); + if (f >= 0) mfunc[f](&rich); + *mmode = MM_NONE; + } if (mv.buttons == 4) { Object *obj; Data *dlink; @@ -324,6 +330,8 @@ getsel(Point p) p = addpt(subpt(p, rich.page.r.min), rich.page.scroll); if (v == nil) return 0; + if (v->length == 0) return 0; + for (i = 0; i < v->length; i++) { if (stringnwidth(v->obj->font, v->dp, i) >= p.x - v->r.min.x) @@ -344,9 +352,9 @@ getview(Point p) p = addpt(subpt(p, rich.page.r.min), rich.page.scroll); - for (i = 0; i < rich.page.views->count; i++) { + for (i = 0; i < rich.views->count; i++) { - vp = arrayget(rich.page.views, i); + vp = arrayget(rich.views, i); if (ptinrect(p, vp->r) != 0) return vp; @@ -355,17 +363,17 @@ getview(Point p) } void -drawpage(Image *dst, Page *p) +drawpage(Image *dst, Rich *rich) { View *vp; int i; - qlock(rich.l); - for (i = 0; i < p->views->count; i++) { - vp = arrayget(p->views, i); + qlock(rich->l); + for (i = 0; i < rich->views->count; i++) { + vp = arrayget(rich->views, i); drawview(dst, vp); } - qunlock(rich.l); + qunlock(rich->l); } void @@ -417,7 +425,6 @@ drawview(Image *dst, View *v) bg3 = Iselbg; } - if (v == vmin) { r1.max.x = r.min.x + stringnwidth(v->obj->font, v->dp, nmin); r2.min.x = r1.max.x; @@ -441,8 +448,6 @@ drawview(Image *dst, View *v) draw(dst, r2, bg2, nil, ZP); draw(dst, r3, bg3, nil, ZP); - - if (v->obj->image != nil) { draw(dst, r, v->obj->image, nil, ZP); return; @@ -496,7 +501,7 @@ generateviews(Rich *rich, Object *obj, View *v) FL_NL = 8, }; - views = rich->page.views; + views = rich->views; rprev = (v != nil) ? v->r : Rect(0, 0, 0, 0); end = obj->dtext->p + obj->dtext->n; sp = obj->dtext->p; @@ -552,7 +557,7 @@ generatepage(Rich *rich, long n) qlock(rich->l); - views = rich->page.views; + views = rich->views; if (n < views->count) views->count = n; v = (views->count > 0) ? @@ -685,7 +690,7 @@ redraw(int regen) if ((rich.objects->count != 0) && (regen != 0)) { generatepage(&rich, 0); } - drawpage(screen, &rich.page); + drawpage(screen, &rich); drawscrollbar(); flushimage(display, 1); @@ -789,4 +794,107 @@ objectfree(void *v) // free(op->dimage->p); free(op); -} -\ No newline at end of file +} + +Data * +getseltext(Rich *rich) +{ + long n, nmin, nmax; + View *vmin, *vmax; + Object **o, **om, *omin, *omax; + Data *d; + + d = malloc(sizeof(Data)); + + vmin = rich->sel.v[0]; + vmax = rich->sel.v[1]; + nmin = rich->sel.n[0]; + nmax = rich->sel.n[1]; + if (vmin > vmax) { + vmin = rich->sel.v[1]; + vmax = rich->sel.v[0]; + nmin = rich->sel.n[1]; + nmax = rich->sel.n[0]; + } + + if (vmin == nil) vmin = arrayget(rich->views, 0); + if (vmax == nil) vmax = arrayget(rich->views, 0); + + if (vmin == vmax) { + if (nmin > nmax) { + n = nmin; + nmin = nmax; + nmax = n; + } + d->n = nmax - nmin; + d->p = malloc(d->n + 1); + d->p[d->n] = '\0'; + memcpy(d->p, vmin->dp + nmin, d->n); + return d; + } + + omin = vmin->obj; + omax = vmax->obj; + + for (om = arrayget(rich->objects, 0); *om != omin; om++); + + for (o = om, n = nmax - nmin; o[1] != omax; o++) + n += (*o)->dtext->n; + + d->n = n; + d->p = malloc(n + 1); + d->p[n] = '\0'; + + if ((*om)->dtext->p != nil) + memcpy(d->p, (*om)->dtext->p + nmin, + (*om)->dtext->n - nmin); + + for (o = om + 1; o[1] != omax; o++) { + if ((*o)->dtext->p != nil) + memcpy(d->p + n, (*o)->dtext->p, (*o)->dtext->n); + n += (*o)->dtext->n; + } + + o++; + + if ((*o)->dtext->p != nil) + memcpy(d->p + n, (*o)->dtext->p, nmax); + + return d; +} + +void +mpaste(Rich *rich) +{ + print("plumbing\n"); +} + +void +msnarf(Rich *rich) +{ + Data *d; + int snarf; + long n; + n = 0; + d = getseltext(rich); + + if (d->n > 0) { + snarf = open("/dev/snarf", OTRUNC|OWRITE); + if (snarf >= 0) { + n = write(snarf, d->p, d->n); + close(snarf); + } + } + if (n != d->n) + fprint(2, "%s: msnarf: %r\n", argv0); + + free(d->p); + free(d); +} + +void +mplumb(Rich *rich) +{ + print("plumbing\n"); +} + diff --git a/richterm.h b/richterm.h @@ -48,17 +48,13 @@ struct View { }; struct Page { - Array *views; Point scroll; Point max; Rectangle r; Rectangle rs; - usize selstart; - usize selend; }; void drawview(Image *, View *); -void drawpage(Image *, Page *); Point viewsize(View *); typedef struct Rich Rich; @@ -66,6 +62,7 @@ typedef struct Rich Rich; struct Rich { QLock *l; Array *objects; + Array *views; u64int idcount; Page page; struct { @@ -76,6 +73,7 @@ struct Rich { extern Rich rich; +void drawpage(Image *, Rich *); void generatepage(Rich *, long); Object * newobject(Rich *, char *);