richterm

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

commit 61ec78051d6f8ef2171219ee1033708d0fc5cf0c
parent 569c4f884d4b3e5af1a6a33ccba698f1c14cfa4f
Author: Pavel Renev <an2qzavok@gmail.com>
Date:   Wed, 18 Aug 2021 19:15:10 +0000

working on switching to single text buffer, still not done yet

Diffstat:
Marray.c | 3+++
Mdevfs.c | 14+++++++-------
Mfs.c | 105++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Mrichterm.c | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Mrichterm.h | 18+++++++++++-------
5 files changed, 208 insertions(+), 66 deletions(-)

diff --git a/array.c b/array.c @@ -38,6 +38,7 @@ arrayfree(Array *ap) void * arraygrow(Array *ap, long n) { + if (n < 0) return nil; qlock(ap->l); ap->count += n; if (ap->count > ap->n) { @@ -53,6 +54,7 @@ void arraydel(Array *ap, long n) { char *v; + if ((n < 0) || (n > ap->count)) return; qlock(ap->l); v = ap->p + ap->size * n; if (ap->free != nil) ap->free(v); @@ -64,5 +66,6 @@ arraydel(Array *ap, long n) void * arrayget(Array *ap, long n) { + if ((n < 0) || (n > ap->count)) return nil; return (void *)(ap->p + ap->size * n); } diff --git a/devfs.c b/devfs.c @@ -8,7 +8,7 @@ #include "array.h" #include "richterm.h" -File *cons, *consctl; +File *cons, *consctl, *text; void devfs_read(Req *r) @@ -27,8 +27,10 @@ devfs_read(Req *r) respond(r, nil); } else if (f == consctl) { respond(r, "not implemented"); - } - else respond(r, "what"); + }else if (f == text) { + arrayread(r, rich.text); + respond(r, nil); + } else respond(r, "what"); } void @@ -37,10 +39,7 @@ devfs_write(Req *r) File *f; f = r->fid->file; if (f == cons){ - char *buf; - buf = mallocz(r->ifcall.count + 1, 1); - memcpy(buf, r->ifcall.data, r->ifcall.count); - mkobjectftree(newobject(&rich, buf), fsctl->tree->root); + mkobjectftree(newobject(&rich, r->ifcall.data, r->ifcall.count), fsctl->tree->root); redraw(1); r->ofcall.count = r->ifcall.count; respond(r, nil); @@ -67,6 +66,7 @@ initdevfs(void) if (cons == nil) return nil; consctl = createfile(srv.tree->root, "consctl", "richterm", 0666, dctl); if (consctl == nil) return nil; + text = createfile(srv.tree->root, "text", "richterm", 0444, dctl); threadpostmountsrv(&srv, nil, "/dev", MBEFORE); return dctl; } diff --git a/fs.c b/fs.c @@ -66,7 +66,7 @@ fs_open(Req *r) { Fsctl *fsctl; fsctl = new->aux; - newobj = mkobjectftree(newobject(&rich, nil), fsctl->tree->root); + newobj = mkobjectftree(newobject(&rich, nil, 0), fsctl->tree->root); respond(r, nil); } @@ -84,7 +84,7 @@ fs_read(Req *r) readstr(r, newobj->id); respond(r, nil); } else if (aux != nil) { - aux->read(r); + aux->read(r, aux->data); respond(r, nil); } else respond(r, "fs_read: f->aux is nil"); } @@ -106,23 +106,7 @@ fs_write(Req *r) } else if (f == new) { respond(r, "not allowed"); } else if (aux != nil) { - qlock(rich.l); - /* TODO: this is not exactly finished */ - - aux->data->count = 0; - arraygrow(aux->data, r->ifcall.offset + r->ifcall.count + 1); - memcpy(arrayget(aux->data, r->ifcall.offset), - r->ifcall.data, r->ifcall.count); - - r->ofcall.count = r->ifcall.count; - - if (aux->type == FT_FONT) { - char *path; - tokenize(aux->data->p, &path, 1); - aux->obj->font = getfont(fonts, path); - } - - qunlock(rich.l); + aux->read(r, aux->data); respond(r, nil); redraw(1); } else respond(r, "fs_write: f->aux is nil"); @@ -152,21 +136,91 @@ initfs(void) } void -arrayread(Req *r) +arrayread(Req *r, void *v) { - Faux *aux; Array *data; + data = v; qlock(rich.l); - aux = r->fid->file->aux; - data = aux->data; qlock(data->l); - readbuf(r, data->p, data->n); + readbuf(r, data->p, data->count); qunlock(data->l); qunlock(rich.l); } void -arraywrite(Req *) +arraywrite(Req *, void *) { /* stub */ } + +void +textread(Req *r, void *) +{ + Faux *aux; + Object *obj, *oe; + char *s; + usize n; + + qlock(rich.l); + aux = r->fid->file->aux; + obj = aux->obj; + oe = obj->next; + + if (oe == nil) + n = rich.text->count; + + else n = oe->offset; + + s = arrayget(rich.text, obj->offset); + + print("tr: %ulld %ulld\n", n, obj->offset); + + qlock(rich.text->l); + + readbuf(r, s, n - obj->offset); + + qunlock(rich.text->l); + qunlock(rich.l); +} + +void +textwrite(Req *r, void *) +{ + /* TODO: this is not exactly finished */ + /* in particular TRUNK/APPEND handling is needed */ + + char *p, *pe; + Faux *aux; + Object *obj; + long n, m, dn; + + print("textwrite\n"); + + qlock(rich.objects->l); + + aux = r->fid->file->aux; + obj = aux->obj; + p = arrayget(rich.text, obj->offset); + pe = arrayget(rich.text, rich.text->count); + if (obj->next == nil) n = rich.text->count; + else n = obj->next->offset - obj->offset; + m = r->ifcall.count + r->ifcall.offset; + dn = m - n; + + qlock(rich.text->l); + + if (dn > 0) arraygrow(rich.text, dn); + else rich.text->count += dn; + memcpy(p + m, p + n, pe - p); + memcpy(p + r->ifcall.offset, r->ifcall.data, + r->ifcall.count); + + qunlock(rich.text->l); + + for (; obj != nil; obj = obj->next) { + obj->offset += dn; + } + + qunlock(rich.objects->l); + +} +\ No newline at end of file diff --git a/richterm.c b/richterm.c @@ -25,6 +25,8 @@ void msnarf(Rich *); void mplumb(Rich *); void msend(Rich *); +void newdraw(void); + Rich rich; int hostpid = -1; Channel *pidchan; @@ -33,7 +35,7 @@ Keyboardctl *kctl; Devfsctl *dctl; Fsctl *fsctl; Array *fonts; -Image *Iscrollbar, *Ilink, *Inormbg, *Iselbg; +Image *Iscrollbar, *Ilink, *Inormbg, *Iselbg, *Itext; char *mitems[] = {"paste", "snarf", "plumb", nil}; void (*mfunc[])(Rich *) = {mpaste, msnarf, mplumb, nil}; @@ -96,6 +98,8 @@ threadmain(int argc, char **argv) Ilink = allocimage( display, Rect(0,0,1,1), screen->chan, 1, DBlue); + Itext = display->black; + fonts = arraycreate(sizeof(Font *), 2, nil); fp = arraygrow(fonts, 1); *fp = font; @@ -112,7 +116,7 @@ threadmain(int argc, char **argv) qunlock(rich.l); - olast = newobject(&rich, nil); + olast = newobject(&rich, nil, 0); resize(); redraw(1); @@ -144,6 +148,12 @@ threadmain(int argc, char **argv) redraw(1); break; case KBD: + if (kv == 0xf001) { + draw(screen, rich.page.r, display->white, nil, ZP); + newdraw(); + flushimage(display, 1); + break; + } if (kv == 0x7f) shutdown(); /* delete */ if (kv == 0xf00e) { /* d-pad up */ scroll( @@ -190,22 +200,20 @@ threadmain(int argc, char **argv) redraw(1); } if (kv == '\n') { - Object *obj; - - obj = mkobjectftree(newobject(&rich, nil), fsctl->tree->root); - qlock(rich.l); dv = arraycreate(sizeof(char), olast->dtext->n, nil); arraygrow(dv, olast->dtext->count); memcpy(dv->p, olast->dtext->p, dv->count); - arraygrow(obj->dtext, olast->dtext->n); - memcpy(obj->dtext->p, olast->dtext->p, olast->dtext->count); - olast->dtext->count = 0; - qunlock(rich.l); + mkobjectftree( + newobject(&rich, olast->dtext->p, olast->dtext->count), + fsctl->tree->root); + + olast->dtext->count = 0; + nbsend(dctl->rc, &dv); redraw(1); @@ -610,50 +618,56 @@ fauxalloc(Object *obj, Array *data, int type) } Object * -newobject(Rich *rich, char *text) +newobject(Rich *rich, char *p, long n) { - Object *obj, **op; + Object *obj, **op, **old; qlock(rich->l); + old = arrayget(rich->objects, rich->objects->count - 1); + op = arraygrow(rich->objects, 1); if (rich->objects->count > 1) { Object **o1; o1 = arrayget(rich->objects, rich->objects->count - 2); + *op = *o1; op = o1; } + if (rich->objects->count > 2) { + (*(op - 2))->next = *op; + } + obj = mallocz(sizeof(Object), 1); *op = obj; + obj->offset = rich->text->count; + + print("offset %ulld\n", obj->offset); + + obj->id = smprint("%ulld", rich->idcount++); + obj->font = font; + obj->text = rich->text; + obj->dtext = arraycreate(sizeof(char), 4096, nil); obj->dfont = arraycreate(sizeof(char), 4096, nil); obj->dlink = arraycreate(sizeof(char), 4096, nil); obj->dimage = arraycreate(sizeof(char), 4096, nil); - if (text != nil) { - char *p; - p = arraygrow(obj->dtext, strlen(text)); - memcpy(p, text, strlen(text)); + if (p != nil) { + char *pp; + pp = arraygrow(obj->dtext, n); + memcpy(pp, p, n); - p = arraygrow(rich->text, strlen(text)); - memcpy(p, text, strlen(text)); + pp = arraygrow(rich->text, n); + memcpy(pp, p, n); }; arraygrow(obj->dfont, strlen(font->name)); memcpy(obj->dfont->p, font->name, strlen(font->name)); - obj->id = smprint("%ulld", rich->idcount); - - obj->font = font; - - obj->text = rich->text; - obj->offset = rich->text->count; - - rich->idcount++; - qunlock(rich->l); return obj; } @@ -672,6 +686,9 @@ mkobjectftree(Object *obj, File *root) auxlink = fauxalloc(obj, obj->dlink, FT_LINK); auximage = fauxalloc(obj, obj->dimage, FT_IMAGE); + auxtext->read = textread; + auxtext->write = textwrite; + obj->ftext = createfile(obj->dir, "text", "richterm", 0666, auxtext); obj->ffont = createfile(obj->dir, "font", "richterm", 0666, auxfont); obj->flink = createfile(obj->dir, "link", "richterm", 0666, auxlink); @@ -895,3 +912,65 @@ mplumb(Rich *) { } +void +_drawchar(char *p, Point pt, Font *font, Image *fg, Image *bg) +{ + Point ptact, ptnew; + ptact = subpt(addpt(pt, rich.page.r.min), rich.page.scroll); + ptnew = stringnbg(screen, ptact, fg, ZP, font, p, 1, bg, ZP); +} + +void +drawchar(Object *obj, long n, Point *cur) +{ + int tab, cw; + char *p; + p = arrayget(rich.text, n); + cw = stringnwidth(obj->font, p, 1); + + if (cur->x + cw > Dx(rich.page.r)) { + cur->x = 0; + cur->y += obj->font->height; + } + + switch (*p) { + case '\n': + cur->x = 0; + cur->y += obj->font->height; +// obj->nextlinept.y = cur->y + obj->font->height; + break; + case '\t': + tab = stringwidth(font, "0") * 4; + cur->x = (cur->x / tab + 1) * tab; + break; + default: + _drawchar(p, *cur, obj->font, Itext, Inormbg); + cur->x += cw; + } +} + +void +drawobject(Object *obj, Point *cur) +{ + long i, n; + if (obj->next == nil) n = rich.text->count; + else n = obj->next->offset; + for (i = obj->offset; i < n; i++) { + drawchar(obj, i, cur); + } +} + +void +newdraw(void) +{ + Point cur, nextlinept; + Object **op; + long i; + + cur = ZP; + nextlinept = cur; + for (i = 0; i < rich.objects->count; i++) { + op = arrayget(rich.objects, i); + drawobject(*op, &cur); + } +} +\ No newline at end of file diff --git a/richterm.h b/richterm.h @@ -19,6 +19,10 @@ struct Object { Array *text; usize offset; + Object *next; + Point startpt; + Point endpt; + Point nextlinept; }; extern Object *olast; @@ -72,7 +76,7 @@ extern Rich rich; void drawpage(Image *, Rich *); void generatepage(Rich *, long); -Object * newobject(Rich *, char *); +Object * newobject(Rich *, char *, long); typedef struct Devfsctl Devfsctl; @@ -100,8 +104,8 @@ struct Faux { int type; Object *obj; Array *data; - void (*read)(Req *); - void (*write)(Req *); + void (*read)(Req *, void *); + void (*write)(Req *, void *); }; enum { @@ -113,7 +117,7 @@ enum { Faux * fauxalloc(Object *, Array *, int); -void textread(Req *); -void textwrite(Req *); -void arrayread(Req *); -void arraywrite(Req *); +void textread(Req *, void *); +void textwrite(Req *, void *); +void arrayread(Req *, void *); +void arraywrite(Req *, void *);