ref: 3cc271e1e7ba83030e354802edd077156dbfcd0c
parent: 4f75866d56184b1a5ccc0c7b3a7713f3a5c610e6
author: qwx <[email protected]>
date: Mon Nov 21 20:58:43 EST 2022
fix links, insertion; always recompute range on split; experimental support for all other dot operations
--- a/cmd.c
+++ b/cmd.c
@@ -21,8 +21,12 @@
fprint(2, "chunklist dot %zux %zux %zux: ",
dot.from.pos, dot.pos, dot.to.pos);
- for(c=r->right; c!=r; c=c->right)
+ c = r;
+ do{
fprint(2, "%#p:%zux ", c, c->bufsz);
+ assert(c->right->left == c);
+ c = c->right;
+ }while(c != r);
fprint(2, "\n");
}
@@ -64,8 +68,8 @@
linkchunk(Chunk *left, Chunk *c)
{
c->left->right = left->right;
- c->left = left;
left->right->left = c->left;
+ c->left = left;
left->right = c;
}
@@ -134,10 +138,10 @@
}
static int
-holdchunk(int cut)
+holdchunk(Chunk *c, int cut)
{
if(held != nil){
- if(held == p2c(dot.pos, nil))
+ if(held == c)
return 0;
else if(cutheld){
unlinkchunk(held);
@@ -144,7 +148,7 @@
freechunk(held);
}
}
- held = p2c(dot.from.pos, nil);
+ held = c;
cutheld = cut;
if(cut){
setpos(dot.from.pos);
@@ -171,18 +175,21 @@
return 0;
}
-static void
-splitright(Chunk *c, usize off)
+static Chunk *
+splitright(Chunk *left, usize off)
{
- usize Δ;
- Chunk *nc;
+ usize p, Δ;
+ Chunk *c;
- Δ = c->bufsz - off;
- nc = newchunk(Δ);
- memcpy(nc->buf, c->buf+off, Δ);
- linkchunk(c, nc);
- c->buf = erealloc(c->buf, off, c->bufsz);
- c->bufsz = off;
+ Δ = left->bufsz - off;
+ c = newchunk(Δ);
+ memcpy(c->buf, left->buf+off, Δ);
+ linkchunk(left, c);
+ left->buf = erealloc(left->buf, off, left->bufsz);
+ left->bufsz = off;
+ p = c2p(c);
+ setrange(p, p+Δ);
+ return c;
}
static Chunk *
@@ -208,8 +215,7 @@
c = mergedot(&p);
splitright(c, p + dot.to.pos - dot.from.pos);
- splitright(c, p);
- return c;
+ return splitright(c, p);
}
uchar *
@@ -284,11 +290,14 @@
}
static int
-replace(char *)
+replace(char *, Chunk *c)
{
- Chunk *c, *l, *dotc;
+ Chunk *l, *dotc;
- c = clonechunk();
+ if(c == nil && (c = clonechunk()) == nil){
+ werrstr("replace: no buffer");
+ return -1;
+ }
dotc = p2c(dot.pos, nil);
l = dotc->left;
totalsz -= dotc->bufsz;
@@ -301,12 +310,18 @@
}
static int
-insert(char *)
+insert(char *, Chunk *c)
{
- Chunk *c;
+ usize p;
+ Chunk *left;
- c = clonechunk();
- linkchunk(p2c(dot.pos, nil), c);
+ if(c == nil && (c = clonechunk()) == nil){
+ werrstr("insert: no buffer");
+ return -1;
+ }
+ left = p2c(dot.pos, &p);
+ splitright(left, p);
+ linkchunk(left, c);
setrange(dot.pos, dot.pos + c->bufsz);
totalsz += c->bufsz;
return 1;
@@ -313,10 +328,20 @@
}
static int
+paste(char *s, Chunk *c)
+{
+ if(dot.from.pos == 0 && dot.to.pos == totalsz)
+ return insert(s, c);
+ return replace(s, c);
+}
+
+static int
copy(char *)
{
- splitdot();
- holdchunk(0);
+ Chunk *c;
+
+ c = splitdot();
+ holdchunk(c, 0);
return 0;
}
@@ -327,7 +352,7 @@
c = splitdot();
totalsz -= c->bufsz;
- holdchunk(1);
+ holdchunk(c, 1);
return 1;
}
@@ -389,14 +414,13 @@
static Chunk *
readintochunks(int fd)
{
- int n;
+ int n, m;
usize off;
Chunk *rc, *c, *nc;
rc = newchunk(Iochunksz);
- for(off=0, c=rc;; off+=n){
+ for(off=0, m=0, c=rc;; m+=n, off+=n){
if(off == Iochunksz){
- totalsz += Iochunksz;
nc = newchunk(Iochunksz);
linkchunk(c, nc);
c = nc;
@@ -406,16 +430,35 @@
break;
}
close(fd);
- if(n < 0)
+ if(n < 0){
fprint(2, "readintochunks: %r\n");
+ if(m == 0){
+ freechunk(rc);
+ return nil;
+ }
+ }
c->buf = erealloc(c->buf, off, c->bufsz);
c->bufsz = off;
- totalsz += c->bufsz;
- printchunks(rc);
+ totalsz += m;
return rc;
}
static int
+readfrom(char *s)
+{
+ int fd;
+ Chunk *c;
+
+ if((fd = open(s, OREAD)) < 0)
+ return -1;
+ c = readintochunks(fd);
+ close(fd);
+ if(c == nil)
+ return -1;
+ return paste(nil, c);
+}
+
+static int
writebuf(int fd)
{
usize n, m;
@@ -453,6 +496,8 @@
static int
pipeline(char *arg, int rr, int wr)
{
+ Chunk *c;
+
if(pipe(epfd) < 0)
sysfatal("pipe: %r");
if(procrfork(rc, arg, mainstacksize, RFFDG|RFNOTEG|RFNAMEG) < 0)
@@ -460,7 +505,11 @@
if(wr)
writebuf(epfd[1]);
close(epfd[1]);
- USED(rr);
+ if(rr){
+ if((c = readintochunks(epfd[0])) == nil)
+ return -1;
+ paste(nil, c);
+ }
close(epfd[0]);
return 0;
}
@@ -524,14 +573,14 @@
s += n;
}
switch(r){
-// case '<': return pipefrom(s);
-// case '^': return exchange(s);
+ case '<': return pipefrom(s);
+ case '^': return pipethrough(s);
case '|': return pipeto(s);
case 'c': return copy(s);
case 'd': return cut(s);
case 'm': return forcemerge(s);
- case 'p': return dot.from.pos == 0 && dot.to.pos == totalsz ? insert(s) : replace(s);
-// case 'r': return readfrom(s);
+ case 'p': return paste(s, nil);
+ case 'r': return readfrom(s);
case 'w': return writeto(s);
case 'x': return crop(s);
default: werrstr("unknown command %C", r); break;
@@ -547,7 +596,6 @@
if((c = readintochunks(fd)) == nil)
sysfatal("loadin: %r");
linkchunk(&norris, c);
- printchunks(&norris);
setrange(0, totalsz);
return 0;
}