richterm

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

commit e97714b722758348b8594462370bd5c69a5dbaf4
parent c7293470b622b891a59b84a10584c21817de44dc
Author: Pavel Renev <an2qzavok@gmail.com>
Date:   Sat, 26 Mar 2022 15:56:22 +0000

selection and middle menu is back

Diffstat:
Mrichterm.c | 224++++++++++++++++++++++++++++---------------------------------------------------
Mrichterm.h | 42++++++++++++++++++++++++------------------
2 files changed, 104 insertions(+), 162 deletions(-)

diff --git a/richterm.c b/richterm.c @@ -12,32 +12,30 @@ #include "array.h" #include "richterm.h" +int getelem(Point); +void insertfromcons(Array *); +void mouse(Mousectl *, Mouse, int *); void resize(void); -void shutdown(void); -void send_interrupt(void); void runcmd(void *); void scroll(Point, Rich *); -void mouse(Mousectl *, Mouse, int *); -void insertfromcons(Array *); -Elem *getelem(Point); - -Rich rich; -int hostpid = -1; -Channel *pidchan, *redrawc, *insertc; -Mousectl *mctl; -Keyboardctl *kctl; -Array *fonts; -Image *Iscrollbar, *Ilink, *Inormbg, *Iselbg, *Itext; - -char *srvname; +void send_interrupt(void); +void shutdown(void); Array *elems; +Array *fonts; Array *richdata; +Channel *pidchan, *redrawc, *insertc; Elem *euser; +Image *Iscrollbar, *Ilink, *Inormbg, *Iselbg, *Itext; +Keyboardctl *kctl; +Mousectl *mctl; +Rich rich; +char *srvname; +int hostpid = -1; void mpaste(Rich *); -void msnarf(Rich *); void mplumb(Rich *); +void msnarf(Rich *); char *mitems[] = {"paste", "snarf", "plumb", nil}; void (*mfunc[])(Rich *) = {mpaste, msnarf, mplumb, nil}; @@ -145,6 +143,8 @@ threadmain(int argc, char **argv) insertc = chancreate(sizeof(Array *), 8); generatesampleelems(); + rich.selmin = 10; + rich.selmax = 100; resize(); draw(screen, screen->r, Inormbg, nil, ZP); @@ -336,25 +336,23 @@ mouse(Mousectl *mc, Mouse mv, int *mmode) break; case MM_TEXT: if (mv.buttons == 1) { - /* - selstart = getsel(mv.xy); + selstart = getelem(mv.xy); selend = selstart; rich.selmin = selstart; rich.selmax = selstart; nbsend(redrawc, nil); *mmode = MM_SELECT; - /* } else if (mv.buttons == 2) { - /* int f; f = menuhit(2, mc, &mmenu, nil); if (f >= 0) mfunc[f](&rich); - */ *mmode = MM_NONE; } else if (mv.buttons == 4) { int f; - Elem *e; - e = getelem(mv.xy); + int n; + Elem *e = nil; + n = getelem(mv.xy); + if (n >= 0) arrayget(elems, n, &e); if ((e != nil) && (e->link != nil)) { f = menuhit(3, mc, &rmenu, nil); if (f >= 0) { @@ -370,16 +368,14 @@ mouse(Mousectl *mc, Mouse mv, int *mmode) break; case MM_SELECT: - break; - -/* if (mv.buttons == (1|2)) { break; } if (mv.buttons == (1|4)) { break; } - selend = getsel(mv.xy); + selend = getelem(mv.xy); + if (selend == -1 ) selend = selstart; if (selstart < selend) { rich.selmin = selstart; rich.selmax = selend; @@ -388,7 +384,6 @@ mouse(Mousectl *mc, Mouse mv, int *mmode) rich.selmax = selstart; } nbsend(redrawc, nil); -*/ } } @@ -419,9 +414,9 @@ scroll(Point p, Rich *r) r->scroll = p.y; - qlock(rich.l); - // update elements y positions ??? - qunlock(rich.l); + // qlock(rich.l); + // TODO: update elements y positions ??? + // qunlock(rich.l); nbsend(redrawc, nil); } @@ -638,8 +633,6 @@ ruseract(int f) nbsend(ctlc, &a); } - - char * rusergen(int f) { @@ -681,16 +674,21 @@ elemparse(Elem *e, char *str, long n) e->type = type; e->count = ep - sp; -/* + switch(e->type) { case E_NL: + e->type = E_TEXT; + e->count = 1; + e->r = L'\n'; case E_TAB: + e->type = E_TEXT; + e->count = 1; + e->r = L'\t'; case E_SPACE: e->type = E_TEXT; e->count = 1; - sp = str; + e->r = L' '; } -*/ if (e->count > 0) { e->str = malloc(e->count + 1); @@ -702,12 +700,12 @@ elemparse(Elem *e, char *str, long n) } void -text2runes(Elem *E, Array *elems) +text2runes(char *str, Array *elems) { - if (E->str == nil) return; - Rune *r = runesmprint("%s", E->str); + if (str == nil) return; + Rune *r = runesmprint("%s", str); Rune *rp; - for (rp =r; *rp != L'\0'; rp++) { + for (rp = r; *rp != L'\0'; rp++) { Elem *e = mallocz(sizeof(Elem), 1); e->type = E_TEXT; e->str = smprint("%C", *rp); @@ -733,7 +731,7 @@ parsedata(Array *data, Array *elems) dp = elemparse(e, dp, data->p + data->count - dp); if (dp == nil) break; if (e->type == E_TEXT) { - text2runes(e, elems); + text2runes(e->str, elems); freeelem(e); } else arraygrow(elems, 1, &e); } @@ -812,35 +810,36 @@ void drawelems(void) { long i; - Point pos; + DrawState ds; Elem *e; e = nil; - pos = rich.r.min; - pos.y -= rich.scroll; + ds.pos = rich.r.min; + ds.pos.y -= rich.scroll; for (i = 0; i < elems->count; i++) { + ds.n = i; if (arrayget(elems, i, &e) == nil) sysfatal("drawelems: failed to get elem"); - e->pos = pos; - pos = drawelem(e); + e->pos = ds.pos; + drawelem(&ds, e); } if (e != nil) rich.max = e->nlpos.y + rich.scroll - rich.r.min.y; else rich.max = 0; } Point -drawelem(Elem *e) +drawelem(DrawState *ds, Elem *e) { - Point (*drawp)(Elem *); + Point (*drawp)(DrawState *, Elem *); - static const Point (*dtable[256])(Elem *) = { + static const Point (*dtable[256])(DrawState *, Elem *) = { [E_NOOP] drawnoop, [E_TEXT] drawrune, [E_FONT] drawnoop, [E_LINK] drawnoop, [E_IMAGE] drawnoop, - [E_NL] drawnl, - [E_TAB] drawtab, - [E_SPACE] drawspace, + [E_NL] drawnoop, + [E_TAB] drawnoop, + [E_SPACE] drawnoop, }; if (e == nil) sysfatal("drawelem: e is nil"); @@ -849,6 +848,8 @@ drawelem(Elem *e) e->prev->nlpos : Pt(rich.r.min.x, rich.r.min.y + e->font->height - rich.scroll); + ds->nlpos = e->nlpos; + drawp = dtable[e->type]; if (drawp == nil) { @@ -857,22 +858,25 @@ drawelem(Elem *e) drawp = drawnoop; } - return drawp(e); + ds->pos = drawp(ds, e); + return ds->pos; } Point -drawrune(Elem *e) +drawrune(DrawState *ds, Elem *e) { - if (e->r == L'\t') return drawtab(e); - if (e->r == L'\n') return drawnl(e); + if (e->r == L'\t') return drawtab(ds, e); + if (e->r == L'\n') return drawnl(ds, e); Point pos; - Image *fg; + Image *fg, *bg; int w; - if (e->font == nil) sysfatal("drawtext: e->font is nil!"); + if (e->font == nil) sysfatal("drawrune: e->font is nil!"); fg = (e->link != nil) ? Ilink : Itext; + bg = ((ds->n >= rich.selmin) && + (ds->n < rich.selmax)) ? Iselbg : Inormbg; if (e->nlpos.y < e->pos.y + e->font->height) e->nlpos.y = e->pos.y + e->font->height; @@ -885,104 +889,30 @@ drawrune(Elem *e) } if ((pos.y >= rich.r.min.y) && (pos.y <= rich.r.max.y)) { - runestringn(screen, pos, fg, ZP, e->font, &e->r, 1); + runestringnbg(screen, pos, fg, ZP, e->font, &e->r, 1, bg, ZP); } pos.x += w; return pos; } Point -drawtext(Elem *e) +drawnl(DrawState *ds, Elem *e) { - Point pos; - int i, n, s, nl; - Image *fg; - Rune *R; - char *sp; - - if (e->count == 0) return e->pos; - - if (e->font == nil) sysfatal("drawtext: e->font is nil!"); - if (e->str == nil) sysfatal("drawtext: e->str is nil!"); - - if (e->nlpos.y < e->pos.y + e->font->height) + if (e->nlpos.y <= e->pos.y) { e->nlpos.y = e->pos.y + e->font->height; - - fg = (e->link != nil) ? Ilink : Itext; - - sp = e->str; - n = utfnlen(sp, e->count); - R = malloc(sizeof(Rune) * (n + 1)); - R[n] = 0; - for (i = 0; i < n; i++) { - sp += chartorune(&R[i], sp); + ds->nlpos = e->nlpos; } - pos = e->pos; - s = 0; - nl = 0; - while (s < n) { - for (i = 0; i < n - s; i++) { - /* if (selection start) break; */ - /* if (selection end) break; */ - if (pos.x + runestringnwidth(e->font, &R[s], i) > rich.r.max.x) { - i --; - nl = 1; - break; - } - } - /* - * if (selected) Ibg = Isel; - * else Ibg = Inormbg; - */ - pos = runestringn(screen, pos, fg, ZP, e->font, &R[s], i); - if (nl != 0) { - nl = 0; - pos = e->nlpos; - e->nlpos.y = pos.y + e->font->height; - } - s += i; - } - - free(R); - - return pos; -} - -Point -drawnl(Elem *e) -{ - if (e->nlpos.y <= e->pos.y) { - e->nlpos.y = e->pos.y + e->font->height; + if ((ds->n >= rich.selmin) && + (ds->n < rich.selmax)) { + draw(screen, Rpt(ds->pos, Pt(rich.r.max.x, ds->nlpos.y)), Iselbg, nil, ZP); } - /* - * if (selected) Ibg = Isel; - * else Ibg = Inormbg; - * draw(Ibg); - */ return e->nlpos; } Point -drawspace(Elem *e) -{ - Point pos; - - /* - * if (selected) Ibg = Isel; - * else Ibg = Inormbg; - * draw(Ibg); - */ - - pos = e->pos; - pos.x += stringwidth(e->font, " "); - /* TODO: add linewrap handling */ - return pos; -} - -Point -drawtab(Elem *e) +drawtab(DrawState *ds, Elem *e) { int x, tabw; tabw = stringwidth(font, "0") * 4; @@ -990,11 +920,17 @@ drawtab(Elem *e) Point pos; pos = e->pos; pos.x = rich.r.min.x + (x + 1) * tabw; + + if ((ds->n >= rich.selmin) && + (ds->n < rich.selmax)) { + draw(screen, Rpt(ds->pos, Pt(pos.x, ds->nlpos.y)), Iselbg, nil, ZP); + } + return pos; } Point -drawnoop(Elem *e) +drawnoop(DrawState *, Elem *e) { return e->pos; } @@ -1058,7 +994,7 @@ freeelem(Elem *e) e->nlpos = ZP; } -Elem * +int getelem(Point xy) { int i; @@ -1074,7 +1010,7 @@ getelem(Point xy) (xy.y < np.y) && (xy.x >= sp.x) && (xy.x < ep.x) - ) return e; + ) return i; } - return nil; + return -1; } diff --git a/richterm.h b/richterm.h @@ -1,7 +1,16 @@ -typedef struct Rich Rich; +typedef struct DrawState DrawState; +typedef struct Elem Elem; typedef struct Faux Faux; +typedef struct Rich Rich; typedef struct Token Token; -typedef struct Elem Elem; + +struct DrawState { + int n; + Point pos; + Point nlpos; + char *link; + Font *font; +}; struct Rich { QLock *l; @@ -35,7 +44,7 @@ enum { E_SPACE = 's', }; -enum {TRune, TFont, TLink, TImage}; +enum {TRune = '.', TFont = 'f', TLink = 'l', TImage = 'i'}; struct Elem { char type; @@ -57,28 +66,25 @@ struct Elem { Point nlpos; }; -extern Channel *redrawc; -extern Channel *insertc; +extern Array *elems; +extern Array *fonts; +extern Array *menubuf; +extern Array *richdata; extern Channel *consc; extern Channel *ctlc; +extern Channel *insertc; +extern Channel *redrawc; +extern Elem *euser; extern File *fsroot; -extern Array *menubuf; -extern Array *fonts; extern Rich rich; -extern Array *elems; -extern Array *richdata; -extern Elem *euser; - Faux * fauxalloc(Array *, void (*)(Req *), void (*)(Req *), void (*)(Req *), void (*)(Req *), void (*)(Fid *)); Font* getfont(Array *, char *); -Point drawelem(Elem *); -Point drawnl(Elem *); -Point drawnoop(Elem *); -Point drawspace(Elem *); -Point drawtab(Elem *); -// Point drawtext(Elem *); -Point drawrune(Elem *); +Point drawelem(DrawState *, Elem *); +Point drawnl(DrawState *, Elem *); +Point drawnoop(DrawState *, Elem *); +Point drawtab(DrawState *, Elem *); +Point drawrune(DrawState *, Elem *); char * elemparse(Elem *, char *, long); int initfs(char *); void drawelems(void);