ref: 9681dab6c716b544e3a07e39a6c6a52b900de6b4
parent: b3f96670b78750193039bef394414890836b8dbe
author: qwx <qwx@sciops.net>
date: Sun Jan 5 00:46:06 EST 2025
cmd: fix wrong insertions and paste dot recomputation, permit only one read edit at a time
--- a/chunk.c
+++ b/chunk.c
@@ -11,8 +11,6 @@
Ref;
};
-// FIXME: crazy idea, multisnarf with addressable elements; $n registers; fork pplay to display them → ?
-
typedef struct Op Op;
struct Op{
Chunk *p1;
@@ -52,6 +50,21 @@
return fmtprint(fmt, "0x%08p N=%08zux →L=0x%08p ←R=0x%08p", c, c->len, c->left, c->right);
}
+static usize
+clength(Chunk *r)
+{
+ usize len;
+ Chunk *c;
+
+ c = r;
+ len = 0;
+ do{
+ len += c->len;
+ c = c->right;
+ }while(c != r);
+ return len;
+}
+
static void
printchunks(Chunk *r)
{
@@ -61,10 +74,12 @@
c = r;
len = 0;
do{
+ fprint(2, "\t%χ\toff=%08zux\n", c, len);
assert(c->right->left == c);
len += c->len;
c = c->right;
}while(c != r);
+ fprint(2, "\n");
}
void
@@ -211,9 +226,11 @@
static Dot
newdot(Dot *dp)
{
+ usize sz;
Dot d = {0};
Chunk *c;
+ sz = dp->to - dp->from;
d.norris = dp->norris;
d.totalsz = d.norris->len;
/* paranoia */
@@ -220,7 +237,9 @@
for(c=d.norris->right; c!=d.norris; c=c->right)
d.totalsz += c->len;
d.cur = d.from = dp->from < d.totalsz ? dp->from : 0;
- d.to = d.totalsz;
+ d.to = d.from + sz;
+ if(d.to > d.totalsz)
+ d.to = d.totalsz;
d.off = -1;
return d;
}
@@ -258,7 +277,7 @@
return 0;
op = ophead++;
d = op->dot;
- dprint(op->p1, "cmd/unpop dot=%Δ P [%χ][%χ] LR [%χ][%χ]\n",
+ dprint(op->p1, "cmd/unpop dot=%Δ\n\tP [ %χ ][ %χ ]\n\tLR [ %χ ][ %χ ]\n",
d, op->p1, op->p2, op->l, op->r);
linkchunk(op->p1->left, op->l);
unlink(op->p1, op->p2);
@@ -278,7 +297,7 @@
return 0;
op = --ophead;
d = op->dot;
- dprint(op->l, "cmd/pop dot=%Δ P [%χ][%χ] LR [%χ][%χ]\n",
+ dprint(op->l, "cmd/pop dot=%Δ\n\tP [ %χ ][ %χ ]\n\tLR [ %χ ][ %χ ]\n",
d, op->p1, op->p2, op->l, op->r);
linkchunk(op->l->left, op->p1);
unlink(op->l, op->r);
@@ -335,7 +354,7 @@
else
linkchunk(l, r);
}
- dprint(d->norris, "ccrop dot=%Δ P [%χ][%χ] LR [%χ][%χ]\n", d, p1, p2, l, r);
+ dprint(d->norris, "ccrop dot=%Δ\n\tP [ %χ ][ %χ ]\n\tLR [ %χ ][ %χ ]\n", d, p1, p2, l, r);
linkchunk(p1, l);
unlink(p2, p1);
pushop(p1, p2, l, r, d);
@@ -344,13 +363,14 @@
}
/* [p1]..[p2] → [l|p1]..[p2|r] → [l]..c..[r] */
-static int
+int
creplace(Dot *d, Chunk *c)
{
- usize foff, toff;
+ usize sz, foff, toff;
Chunk *p1, *p2, *l, *r;
assert(d->from <= d->totalsz && d->to - d->from > 0);
+ sz = clength(c);
p1 = p2c(d->from, &foff, d);
p2 = p2c(d->to, &toff, d);
l = splitchunk(p1, 0, foff);
@@ -357,12 +377,13 @@
r = splitchunk(p2, toff, p2->len);
linkchunk(l, c);
linkchunk(c, r);
- dprint(d->norris, "creplace dot=%Δ P [%χ][%χ] LR [%χ][%χ]\n", d, p1, p2, l, r);
+ dprint(d->norris, "creplace dot=%Δ\n\tP [ %χ ][ %χ ]\n\tLR [ %χ ][ %χ ]\n", d, p1, p2, l, r);
linkchunk(p1->left, l);
unlink(p1, p2);
pushop(p1, p2, l, r, d);
if(p1 == d->norris)
d->norris = l;
+ d->to = d->from + sz;
*d = newdot(d);
return 0;
}
@@ -371,9 +392,10 @@
static int
cinsert(Dot *d, Chunk *c)
{
- usize off;
+ usize sz, off;
Chunk *p1, *l, *r;
+ sz = clength(c);
assert(d->off != -1);
p1 = p2c(d->off, &off, d);
l = splitchunk(p1, 0, off);
@@ -380,7 +402,7 @@
r = splitchunk(p1, off, p1->len);
linkchunk(l, c);
linkchunk(c, r);
- dprint(d->norris, "cinsert dot=%Δ P [%χ] LR [%χ][%χ]\n", d, p1, l, r);
+ dprint(d->norris, "cinsert dot=%Δ\n\tP [ %χ ]\n\tLR [ %χ ][ %χ ]\n", d, p1, l, r);
linkchunk(p1->left, l);
unlink(p1, p1);
pushop(p1, p1, l, r, d);
@@ -387,7 +409,7 @@
if(p1 == d->norris)
d->norris = l;
d->from = d->off;
- d->to = d->totalsz;
+ d->to = d->from + sz;
*d = newdot(d);
return 0;
}
@@ -436,7 +458,7 @@
linkchunk(l, clone(p1->right, p2->left));
linkchunk(l->left, r);
}
- dprint(d->norris, "ccopy dot=%Δ\n\tP\t[ %χ ]\t[ %χ ]\n\tLR:\t[ %χ ]\t[ %χ ]\n",
+ dprint(d->norris, "ccopy dot=%Δ\n\tP [ %χ ][ %χ ]\n\tLR [ %χ ][ %χ ]\n",
d, p1, p2, l, p1 == p2 ? l : r);
hold.c = l;
hold.Dot = *d;
@@ -464,7 +486,7 @@
p2 = p2c(d->to, &off, d);
r = splitchunk(p2, off, p2->len);
linkchunk(l, r);
- dprint(d->norris, "ccut dot=%Δ\n\tP\t[ %χ ]\t[ %χ ]\n\tLR:\t[ %χ ]\t[ %χ ]\n",
+ dprint(d->norris, "ccut dot=%Δ\n\tP [ %χ ][ %χ ]\n\tLR [ %χ ][ %χ ]\n",
d, p1, p2, l, r);
linkchunk(p1->left, l);
unlink(p1, p2);
@@ -526,6 +548,7 @@
}
d->norris = c;
d->from = 0;
+ d->to = c->len;
*d = newdot(d);
return c;
}
--- a/cmd.c
+++ b/cmd.c
@@ -9,6 +9,9 @@
Dot dot;
int bound = Bend;
+int reader = -1;
+
+static Dot rdot;
static int epfd[2];
static int
@@ -136,12 +139,10 @@
rproc(void *efd)
{
int fd;
- Dot d, cd;
+ Dot cd;
Chunk *c;
- d = dot;
- if(d.from != 0 && d.to != d.totalsz)
- d.off = -1;
+ reader = getpid();
fd = (intptr)efd;
if((c = loadfile(fd, &cd)) == nil){
fprint(2, "failed reading from pipe: %r");
@@ -149,11 +150,13 @@
}
close(fd);
qlock(&lsync);
- chold(c, &d);
- dot = d;
+ dot.from = rdot.from;
+ dot.to = rdot.to;
+ ccopy(&dot);
+ creplace(&dot, c);
+ dot.to = dot.from + cd.totalsz;
qunlock(&lsync);
- if(paste(nil) < 0)
- fprint(2, "paste: %r\n");
+ reader = -1;
redraw(1);
threadexits(nil);
}
@@ -165,8 +168,14 @@
fprint(2, "pipeline: too many backgrounded processes\n");
return -1;
}
- if(rr)
+ if(rr){
+ if(reader >= 0){
+ fprint(2, "pipeline: editing operation already pending\n");
+ return -1;
+ }
reader = 0;
+ rdot = dot;
+ }
if(pipe(epfd) < 0)
sysfatal("pipe: %r");
if(procrfork(rc, arg, mainstacksize, RFFDG|RFNOTEG|RFNAMEG) < 0)
@@ -222,12 +231,14 @@
{
int fd;
+ if(reader >= 0){
+ werrstr("editing operation already pending");
+ return -1;
+ }
if((fd = open(s, OREAD)) < 0)
return -1;
- if(procrfork(rproc, (int*)fd, mainstacksize, RFFDG) < 0){
- fprint(2, "procrfork: %r\n");
+ if((reader = procrfork(rproc, (int*)fd, mainstacksize, RFFDG)) < 0)
return -1;
- }
return 0;
}
--- a/fns.h
+++ b/fns.h
@@ -3,6 +3,7 @@
void killreader(void);
int unpop(char*);
int popop(char*);
+int creplace(Dot*, Chunk*);
int cpaste(Dot*);
Chunk* ccopy(Dot*);
void chold(Chunk*, Dot*);
--- a/pplay.c
+++ b/pplay.c
@@ -11,7 +11,6 @@
int stereo, chan;
int debug, paused, notriob;
-int reader = -1;
Channel *pidc;
static Keyboardctl *kc;
@@ -27,6 +26,7 @@
if(reader <= 0)
return;
postnote(PNGROUP, reader, "kill");
+ reader = -1;
}
static void
@@ -253,8 +253,6 @@
break;
}
assert(i < nelem(pids));
- if(reader == 0)
- reader = pid;
nslots--;
break;
case Await:
@@ -265,8 +263,6 @@
}
if(i == nelem(pids))
fprint(2, "phase error -- no such pid %d\n", w->pid);
- if(w->pid == reader)
- reader = -1;
nslots++;
free(w);
break;
--
⑨