shithub: pplay

Download patch

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;
--