richterm

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

commit a4b59540530dc03ec5cc0cdf141b3e40c9a7c954
parent 0c9db2fb0aa728c6bb12f0ffd3ca32a141fb3a88
Author: Pavel Renev <an2qzavok@gmail.com>
Date:   Sat, 14 Aug 2021 23:33:40 +0000

fix mouse selection, rewrite drawview, we now do not regenerate the page on selection events

Diffstat:
Mmkfile | 3+++
Mrichterm.c | 154+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------
Mrichterm.h | 6++++--
3 files changed, 126 insertions(+), 37 deletions(-)

diff --git a/mkfile b/mkfile @@ -5,3 +5,6 @@ OFILES=richterm.$O devfs.$O fs.$O array.$O HFILES=richterm.h array.h </sys/src/cmd/mkone + +acid:V: + $CC -a *.c > acid.lib diff --git a/richterm.c b/richterm.c @@ -18,6 +18,9 @@ Devfsctl *dctl; Fsctl *fsctl; Array *fonts; Image *Iscrollbar, *Ilink, *Inormbg, *Iselbg; + +Image *It1, *It2, *It3; + Object *olast; enum { @@ -81,6 +84,16 @@ 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; @@ -261,9 +274,11 @@ mouse(Mouse mv, int *mmode) break; case MM_TEXT: if (mv.buttons == 1) { - rich.page.selstart = getsel(mv.xy); - rich.page.selend = rich.page.selstart; - redraw(1); + rich.sel.n[0] = getsel(mv.xy); + rich.sel.v[0] = getview(mv.xy); + rich.sel.n[1] = rich.sel.n[0]; + rich.sel.v[1] = rich.sel.v[0]; + redraw(0); *mmode = MM_SELECT; } if (mv.buttons == 4) { @@ -292,31 +307,29 @@ mouse(Mouse mv, int *mmode) /* paste */ break; } - rich.page.selend = getsel(mv.xy); - redraw(1); + rich.sel.n[1] = getsel(mv.xy); + rich.sel.v[1] = getview(mv.xy); + redraw(0); } } usize getsel(Point p) { - View *v, *vp; + View *v; long i; - usize cc; - cc = 0; + v = getview(p); + + p = addpt(subpt(p, rich.page.r.min), rich.page.scroll); + if (v == nil) return 0; - for (i = 0; i < rich.page.views->count ; i++) { - vp = arrayget(rich.page.views, i); - if (v == vp) break; - cc += vp->length; - } for (i = 0; i < v->length; i++) { if (stringnwidth(v->obj->font, v->dp, i) >= p.x - v->r.min.x) break; } - return cc + i - 1; + return i - 1; } View * @@ -325,11 +338,16 @@ getview(Point p) int i; View *vp; + if (p.x < rich.page.r.min.x) p.x = rich.page.r.min.x; if (p.x > rich.page.r.max.x) p.x = rich.page.r.max.x; + p = addpt(subpt(p, rich.page.r.min), rich.page.scroll); + for (i = 0; i < rich.page.views->count; i++) { + vp = arrayget(rich.page.views, i); + if (ptinrect(p, vp->r) != 0) return vp; } @@ -353,35 +371,102 @@ drawpage(Image *dst, Page *p) void drawview(Image *dst, View *v) { - Image *bg; - Rectangle r; + Image *bg1, *bg2, *bg3; + Rectangle r, r1, r2, r3; + View *vmin, *vmax; + long nmin, nmax; + + if (rich.sel.v[0] < rich.sel.v[1]) { + vmin = rich.sel.v[0]; + vmax = rich.sel.v[1]; + nmin = rich.sel.n[0]; + nmax = rich.sel.n[1]; + } else { + vmin = rich.sel.v[1]; + vmax = rich.sel.v[0]; + nmin = rich.sel.n[1]; + nmax = rich.sel.n[0]; + } + + if (vmin == vmax) { + if (rich.sel.n[0] < rich.sel.n[1]) { + nmin = rich.sel.n[0]; + nmax = rich.sel.n[1]; + } else { + nmin = rich.sel.n[1]; + nmax = rich.sel.n[0]; + } + } r = rectaddpt(rectsubpt(v->r, rich.page.scroll), rich.page.r.min); + r1 = r; + r1.max.x = r.min.x; + r2 = r; + r3 = r; + r3.min.x = r.max.x; + + bg1 = Inormbg; + bg2 = Inormbg; + bg3 = Inormbg; + + if ((v > vmin) && (v < vmax)) { + bg1 = Iselbg; + bg2 = Iselbg; + bg3 = Iselbg; + } + + + if (v == vmin) { + r1.max.x = r.min.x + stringnwidth(v->obj->font, v->dp, nmin); + r2.min.x = r1.max.x; + bg1 = Inormbg;//Iselbg; + bg2 = Iselbg;//Iselbg; + bg3 = Iselbg;//Iselbg; + } + if (v == vmax) { + r2.max.x = r.min.x + stringnwidth(v->obj->font, v->dp, nmax); + r3.min.x = r2.max.x; + bg1 = Iselbg;//Iselbg; + bg2 = Iselbg;//Iselbg; + bg3 = Inormbg;//Iselbg; + } + if (vmin == vmax) { + bg1 = Inormbg; + bg3 = Inormbg;//Iselbg; + } + + draw(dst, r1, bg1, nil, ZP); + 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); - } else { - bg = (v->selected != 0) ? Iselbg : Inormbg; - draw(dst, r, bg, nil, ZP); - stringn(dst, r.min, v->color, ZP, - v->obj->font, v->dp, v->length); + return; } + + stringn(dst, r.min, v->color, ZP, + v->obj->font, v->dp, v->length); } View * viewadd(Array *views, Object *obj, - char *dp, long len, int sel, Rectangle rprev) + char *dp, long len, Rectangle rprev) { View *vp; Rectangle r; + Point p; + + p = Pt(rprev.max.x, rprev.min.y); - r = Rect( - rprev.max.x, - rprev.min.y, - rprev.max.x + stringnwidth(obj->font, dp, len), - r.min.y + (Dy(rprev) > obj->font->height ? - Dy(rprev) : obj->font->height)); + r = Rpt(p, + addpt(p, Pt( + stringnwidth(obj->font, dp, len), + (Dy(rprev) > obj->font->height) ? + Dy(rprev) : obj->font->height))); vp = arrayadd(views); @@ -391,7 +476,6 @@ viewadd(Array *views, Object *obj, len, display->black, r, - sel, }; return vp; @@ -426,26 +510,25 @@ generateviews(Rich *rich, Object *obj, View *v) Dx(rich->page.r)) { fl = FL_NEW | FL_NL; } - + /* TODO: - * if border of selection ... * if object has an image ... */ if (fl & FL_NEW) { - v = viewadd(views, obj, sp, n, 0, rprev); + v = viewadd(views, obj, sp, n, rprev); rprev = v->r; sp = p + 1; n = -1; } if (fl & FL_TAB) { int tl; - v = viewadd(views, obj, sp, 0, 0, rprev); + v = viewadd(views, obj, sp, 0, rprev); tl = stringwidth(font, "0") * 4; v->r.max.x = ((v->r.max.x / tl) + 1) * tl; rprev = v->r; } if (fl & FL_EL) { - v = viewadd(views, obj, sp, 0, 0, rprev); + v = viewadd(views, obj, sp, 0, rprev); v->r.max.x = rich->page.r.max.x; rprev = v->r; } @@ -454,7 +537,7 @@ generateviews(Rich *rich, Object *obj, View *v) rprev = Rect(0, rprev.max.y, 0, rprev.max.y); } } - v = viewadd(views, obj, sp, n, 0, rprev); + v = viewadd(views, obj, sp, n, rprev); return v; } @@ -604,6 +687,7 @@ redraw(int regen) } drawpage(screen, &rich.page); drawscrollbar(); + flushimage(display, 1); } diff --git a/richterm.h b/richterm.h @@ -45,7 +45,6 @@ struct View { long length; Image *color; Rectangle r; - int selected; }; struct Page { @@ -69,7 +68,10 @@ struct Rich { Array *objects; u64int idcount; Page page; - + struct { + View *v[2]; + long n[2]; + } sel; }; extern Rich rich;