richterm

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

commit 4c04189263d4257c639049b2451c323836cb4050
parent 21755d9ef882a3d8a9e10a717eaa56d8a28b5e3e
Author: Pavel Renev <an2qzavok@gmail.com>
Date:   Tue, 24 Aug 2021 20:07:16 +0000

repair /ctl commands, add some extra generic functions around

Diffstat:
MTODO | 5-----
Marray.c | 23++++++++++++++++-------
Marray.h | 2+-
Mfs.c | 70++++++++++++++++++++++++++++++----------------------------------------
Mrichterm.c | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++----------
Mrichterm.h | 2++
6 files changed, 104 insertions(+), 63 deletions(-)

diff --git a/TODO b/TODO @@ -1,8 +1,3 @@ -# /ctl commands - -- object removal -- screen clearing. - # images draw them diff --git a/array.c b/array.c @@ -73,15 +73,24 @@ arraygrow(Array *ap, long n, void *v) } int -arraydel(Array *ap, long n) +arraydel(Array *ap, long offset, long count) { - char *v; - if (_arraycheck(ap, n, "arraydel") != 0) return -1; + void *v, *ve; + long i; + if (_arraycheck(ap, offset + count, "arraydel") != 0) return -1; + + if (ap->free != nil) { + for (i = offset; i < offset+ count; i++) { + v = arrayget(ap, i, nil); + ap->free(v); + } + } + + v = arrayget(ap, offset, nil); + ve = arrayget(ap, offset + count, nil); qlock(ap->l); - v = ap->p + ap->size * n; - if (ap->free != nil) ap->free(v); - memcpy(v, v + ap->size, (ap->count - n) * ap->size); - ap->count--; + memcpy(v, ve, (ap->count - offset - count) * ap->size); + ap->count -= count; qunlock(ap->l); return 0; } diff --git a/array.h b/array.h @@ -10,7 +10,7 @@ struct Array { }; Array * arraycreate(long size, long n, void (*free)(void *)); -int arraydel(Array *, long); +int arraydel(Array *, long, long); void arrayfree(Array *); void * arraygrow(Array *, long, void *); void * arrayget(Array *, long, void *); diff --git a/fs.c b/fs.c @@ -43,7 +43,8 @@ char * ctlcmd(char *buf) { Object *obj; - int n, i, j; + int n, i, j, k; + long ne; char *args[256]; obj = nil; n = tokenize(buf, args, 256); @@ -55,22 +56,26 @@ ctlcmd(char *buf) arrayget(rich.objects, j, &obj); if (obj == olast) continue; if (strcmp(obj->id, args[i]) == 0) { - // objectfree(obj); - arraydel(rich.objects, j); + objsettext(obj, nil, 0); + rmobjectftree(obj); + objectfree(obj); + free(obj); + arraydel(rich.objects, j, 1); break; } } } } else if (strcmp(args[0], "clear") == 0) { - int k; - k = rich.objects->count; - for (i = 0; i < k; i++) { - arrayget(rich.objects, 0, &obj); - if (obj != olast) { - // objectfree(obj); - arraydel(rich.objects, 0); - } + for (i = 0; i < rich.objects->count; i++) { + arrayget(rich.objects, i, &obj); + if (obj != olast) rmobjectftree(obj); + objectfree(obj); + free(obj); } + rich.objects->count = 0; + rich.text->count = 0; + olast = objectcreate(); + arraygrow(rich.objects, 1, &olast); } else { qunlock(rich.l); return "unknown command"; @@ -104,10 +109,8 @@ fs_open(Req *r) mkobjectftree(newobj, fsctl->tree->root); objinsertbeforelast(newobj); - /* - * Because our newobj is created empty, there's no need - * to move text from olast around. - */ + /* Because our newobj is created empty, there's no need + to move text from olast around. */ } respond(r, nil); @@ -206,39 +209,26 @@ textwrite(Req *r, void *) /* TODO: this is not exactly finished */ /* in particular TRUNK/APPEND handling is needed */ - char *p, *pe; + char *buf; Faux *aux; Object *obj; - long n, m, dn; - - qlock(rich.objects->l); + long n, m, k; aux = r->fid->file->aux; obj = aux->obj; - p = rich.text->p + obj->offset; - pe = rich.text->p + 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; - if (dn > 0) arraygrow(rich.text, dn, nil); - else rich.text->count += dn; + n = r->ifcall.offset + r->ifcall.count; + m = objtextlen(obj); + k = (n > m) ? n : m; + buf = malloc(sizeof(char) * k); - qlock(rich.text->l); - - memcpy(p + m, p + n, pe - p); - memcpy(p + r->ifcall.offset, r->ifcall.data, - r->ifcall.count); - - qunlock(rich.text->l); - - for (obj = obj->next; obj != nil; obj = obj->next) { - obj->offset += dn; - } - - qunlock(rich.objects->l); + qlock(rich.l); + memcpy(buf, arrayget(rich.text, obj->offset, nil), m); + memcpy(buf + r->ifcall.offset, r->ifcall.data, r->ifcall.count); + objsettext(obj, buf, k); + qunlock(rich.l); + free(buf); } void diff --git a/richterm.c b/richterm.c @@ -389,19 +389,31 @@ objectcreate(void) void objectfree(Object *obj) { - /* TODO: following should be in separate function rmobjectftree + arrayfree(obj->dlink); + arrayfree(obj->dimage); +} + +void +rmobjectftree(Object *obj) +{ + free(obj->ftext->aux); + free(obj->ffont->aux); + free(obj->flink->aux); + free(obj->fimage->aux); + + obj->ftext->aux = nil; + obj->ffont->aux = nil; + obj->flink->aux = nil; + obj->fimage->aux = nil; removefile(obj->ftext); removefile(obj->ffont); removefile(obj->flink); removefile(obj->fimage); - removefile(obj->dir); - free(obj->id); */ + removefile(obj->dir); - /* TODO: why is this not working? */ - arrayfree(obj->dlink); - arrayfree(obj->dimage); + free(obj->id); } Object * @@ -409,8 +421,6 @@ mkobjectftree(Object *obj, File *root) { Faux *auxtext, *auxfont, *auxlink, *auximage; - qlock(rich.l); - obj->id = smprint("%ulld", ++rich.idcount); obj->dir = createfile(root, obj->id, "richterm", DMDIR|0555, nil); @@ -431,8 +441,6 @@ mkobjectftree(Object *obj, File *root) obj->flink = createfile(obj->dir, "link", "richterm", 0666, auxlink); obj->fimage = createfile(obj->dir, "image", "richterm", 0666, auximage); - qunlock(rich.l); - return obj; } @@ -767,3 +775,40 @@ objinsertbeforelast(Object *obj) olast->prev = obj; qunlock(rich.l); } + +long +objtextlen(Object *obj) +{ + long n; + n = (obj->next == nil) ? rich.text->count : obj->next->offset; + return n - obj->offset; +} + +void +objsettext(Object *obj, char *data, long count) +{ + long n, m, dn; + char *p, *pe; + + p = arrayget(rich.text, obj->offset, nil); + pe = arrayend(rich.text); + + n = objtextlen(obj); + m = count; + dn = m - n; + + if (dn > 0) arraygrow(rich.text, dn, nil); + else rich.text->count += dn; + + qlock(rich.text->l); + if (p != nil) memcpy(p + m, p + n, pe - p); + else p = pe; + memcpy(p, data, count); + qunlock(rich.text->l); + + qlock(rich.objects->l); + for (obj = obj->next; obj != nil; obj = obj->next) { + obj->offset += dn; + } + qunlock(rich.objects->l); +} diff --git a/richterm.h b/richterm.h @@ -36,6 +36,8 @@ Object * mkobjectftree(Object *, File *); void objinsertbeforelast(Object *); void rmobjectftree(Object *); void objectfree(Object *); +long objtextlen(Object *obj); +void objsettext(Object *, char *, long); extern Array *fonts;