ref: 3cf7eea579556c5ee9a91476cbd88d2e533cf42d
parent: 8574965a34feb65d5870e3fc9d24df1fcf3d0c1f
author: qwx <[email protected]>
date: Mon Jun 19 07:27:33 EDT 2023
lilu dallas mooltidot and editing fixes (mooltibuf next) - fix insert/replace, crop; describe op with a comment - fix copy/hold improper splits - move all editing semantics to chunk - don't assume static dot anywhere - more descriptive debug fmt - fix truncated ends for input buffers - mandatory dot recalculation until api freezes - leverage legalized 0-size chunks to simplify edits - terminate readproc on error - smooth transitions between chunks - increase defensively athread stacksize incase Outsz increases
--- a/chunk.c
+++ b/chunk.c
@@ -10,7 +10,6 @@
usize bufsz;
Ref;
};
-static Chunk *norris;
// FIXME: crazy idea, multisnarf with addressable elements; $n registers; fork pplay to display them → ?
@@ -20,15 +19,14 @@
Chunk *p2;
Chunk *l;
Chunk *r;
+ Dot *dot;
};
static Op *opbuf, *ophead, *opend;
static usize opbufsz;
static struct{
- Chunk *from;
- usize foff;
- Chunk *to;
- usize toff;
+ Chunk *c;
+ Dot;
} hold;
int
@@ -39,8 +37,8 @@
d = va_arg(fmt->args, Dot*);
if(d == nil)
return fmtstrcpy(fmt, "[??:??:??:??]");
- return fmtprint(fmt, "[from=%08zux cur=%08zux to=%08zux]",
- d->from, d->pos, d->to);
+ return fmtprint(fmt, "[cur=%#p from=%08zux to=%08zux off=%08zux tot=%08zux]",
+ d->norris, d->from, d->to, d->off, d->totalsz);
}
int
@@ -51,7 +49,7 @@
c = va_arg(fmt->args, Chunk*);
if(c == nil)
return fmtstrcpy(fmt, "[]");
- return fmtprint(fmt, "0x%08p:%08zux::0x%08p:0x%08p", c, c->len, c->left, c->right);
+ return fmtprint(fmt, "0x%08p N=%08zux →L=0x%08p ←R=0x%08p", c, c->len, c->left, c->right);
}
static void
@@ -83,7 +81,8 @@
vseprint(s, s+sizeof s, fmt, arg);
va_end(arg);
fprint(2, "%s", s);
- printchunks(c == nil ? norris : c);
+ if(c != nil)
+ printchunks(c);
}
static Chunk *
@@ -95,8 +94,6 @@
c->left = c;
c->right = c;
c->b = b;
- c->boff = 0;
- c->len = b->bufsz;
incref(&b->Ref);
return c;
}
@@ -213,26 +210,29 @@
return n;
}
-void
-checksz(void)
+static Dot
+newdot(Dot *dp)
{
- usize n;
+ Dot d = {0};
+ Chunk *c;
- n = chainlen(norris);
- fprint(2, "totalsz %zd %Δ :: chainlen %zd\n", totalsz, &dot, n);
- assert(n == totalsz);
- assert(dot.from < dot.to);
- assert(dot.from <= totalsz);
- assert(dot.pos >= dot.from && dot.pos < dot.to);
+ d.norris = dp->norris;
+ d.totalsz = d.norris->len;
+ /* paranoia */
+ 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;
+ return d;
}
Chunk *
-p2c(usize p, usize *off)
+p2c(usize p, usize *off, Dot *d)
{
Chunk *c;
- for(c=norris; p>=c->len; c=c->right){
- if(c == norris->left){
+ for(c=d->norris; p>=c->len; c=c->right){
+ if(c == d->norris->left){
assert(p == c->len);
break;
}
@@ -253,21 +253,19 @@
unpop(char *)
{
Op *op;
+ Dot *d;
if(opend == opbuf || ophead == opend)
return 0;
op = ophead++;
+ d = op->dot;
dprint(op->p1, "cmd/unpop dot=%Δ P [%χ][%χ] LR [%χ][%χ]\n",
- &dot, op->p1, op->p2, op->l, op->r);
- totalsz += chainlen(op->l);
+ d, op->p1, op->p2, op->l, op->r);
linkchunk(op->p1->left, op->l);
unlink(op->p1, op->p2);
- totalsz -= chainlen(op->p1);
- if(norris == op->p1)
- norris = op->l;
- dot.from = dot.pos = 0;
- dot.to = totalsz;
- latchedpos = -1;
+ if(d->norris == op->p1)
+ d->norris = op->l;
+ *d = newdot(d);
return 1;
}
@@ -275,26 +273,24 @@
popop(char *)
{
Op *op;
+ Dot *d;
if(ophead == opbuf)
return 0;
op = --ophead;
+ d = op->dot;
dprint(op->l, "cmd/pop dot=%Δ P [%χ][%χ] LR [%χ][%χ]\n",
- &dot, op->p1, op->p2, op->l, op->r);
- totalsz += chainlen(op->p1);
+ d, op->p1, op->p2, op->l, op->r);
linkchunk(op->l->left, op->p1);
unlink(op->l, op->r);
- totalsz -= chainlen(op->l);
- if(norris == op->l)
- norris = op->p1;
- dot.from = dot.pos = 0;
- dot.to = totalsz;
- latchedpos = -1;
+ if(d->norris == op->l)
+ d->norris = op->p1;
+ *d = newdot(d);
return 1;
}
static void
-pushop(Chunk *p1, Chunk *p2, Chunk *l, Chunk *r)
+pushop(Chunk *p1, Chunk *p2, Chunk *l, Chunk *r, Dot *d)
{
Op *op;
@@ -311,164 +307,172 @@
forgetop(op);
memset(ophead, 0, (opend - ophead) * sizeof *ophead);
}
- *ophead++ = (Op){p1, p2, l, r};
+ *ophead++ = (Op){p1, p2, l, r, d};
opend = ophead;
}
+/* ..[p1]..[p2].. → ..[p1|l]..[r|p2].. → [l]..[r] */
void
-ccrop(usize from, usize to)
+ccrop(Dot *d)
{
- usize n, off;
+ usize foff, toff;
Chunk *p1, *p2, *l, *r;
- assert(from < to && to <= totalsz);
-
- p1 = p2c(from, &off);
- if(p1->len - off >= to - from){
- l = splitchunk(p1, off, off);
- p2 = p1;
- r = splitchunk(p2, off, off + to - from);
- if(p1 != norris)
- p1 = p1->left;
- else
- p2 = p2->right;
+ if(d->to == d->from){
+ fprint(2, "empty crop\n");
+ return;
+ }
+ assert(d->from < d->to && d->to <= d->totalsz);
+ p1 = p2c(d->from, &foff, d);
+ p2 = p2c(d->to, &toff, d);
+ if(p1 == p2){
+ l = splitchunk(p1, foff, toff);
+ r = l;
}else{
- p1 = p2c(from, &off);
- l = splitchunk(p1, off, p1->len);
- p2 = p2c(to, &off);
- r = splitchunk(p2, 0, off);
+ l = splitchunk(p1, foff, p1->len);
+ r = splitchunk(p2, 0, toff);
+ if(p1->right != p2)
+ linkchunk(p2->left, r);
+ else
+ linkchunk(l, r);
}
+ dprint(d->norris, "ccrop dot=%Δ P [%χ][%χ] LR [%χ][%χ]\n", d, p1, p2, l, r);
linkchunk(p1, l);
- linkchunk(p2->left, r);
unlink(p2, p1);
- n = chainlen(l);
- totalsz = n;
- pushop(p1, p2, l, r);
- norris = l;
- dot.from = dot.pos = 0;
- dot.to = n;
- latchedpos = -1;
+ pushop(p1, p2, l, r, d);
+ d->norris = l;
+ *d = newdot(d);
}
+/* [p1]..[p2] → [l|p1]..[p2|r] → [l]..c..[r] */
static int
-creplace(usize from, usize to, Chunk *c)
+creplace(Dot *d, Chunk *c)
{
- usize n, off;
+ usize foff, toff;
Chunk *p1, *p2, *l, *r;
- assert(from < to && to <= totalsz);
- p1 = p2c(from, &off);
- l = splitchunk(p1, 0, off);
- p2 = p2c(to, &off);
- r = splitchunk(p2, off, p2->len);
- linkchunk(c, r);
+ assert(d->from <= d->totalsz && d->to - d->from > 0);
+ p1 = p2c(d->from, &foff, d);
+ p2 = p2c(d->to, &toff, d);
+ l = splitchunk(p1, 0, foff);
+ r = splitchunk(p2, toff, p2->len);
linkchunk(l, c);
- n = chainlen(l);
- totalsz += n;
+ linkchunk(c, r);
+ dprint(d->norris, "creplace dot=%Δ P [%χ][%χ] LR [%χ][%χ]\n", d, p1, p2, l, r);
linkchunk(p1->left, l);
unlink(p1, p2);
- totalsz -= chainlen(p1);
- pushop(p1, p2, l, r);
- if(p1 == norris)
- norris = l;
- dot.from = dot.pos = from;
- dot.to = from + n;
- latchedpos = -1;
+ pushop(p1, p2, l, r, d);
+ if(p1 == d->norris)
+ d->norris = l;
+ *d = newdot(d);
return 0;
}
-// FIXME: use a specific Dot (prep for multibuf); generalize
+/* ..[p1].. → ..[l|r].. → ..[l|c|r].. */
static int
-cinsert(usize pos, Chunk *c)
+cinsert(Dot *d, Chunk *c)
{
- usize n, off;
- Chunk *p, *l, *r;
+ usize off;
+ Chunk *p1, *l, *r;
- assert(pos <= totalsz);
- p = p2c(pos, &off);
- l = splitchunk(p, 0, off);
- r = splitchunk(p, off, p->len);
- linkchunk(c, r);
+ assert(d->off != -1ULL);
+ p1 = p2c(d->off, &off, d);
+ l = splitchunk(p1, 0, off);
+ r = splitchunk(p1, off, p1->len);
linkchunk(l, c);
- n = chainlen(l);
- totalsz += n;
- linkchunk(p->left, l);
- unlink(p, p);
- totalsz -= chainlen(p);
- pushop(p, p, l, r);
- if(p == norris)
- norris = l;
- dot.from = dot.pos = pos;
- dot.to = pos + n;
- latchedpos = -1;
+ linkchunk(c, r);
+ dprint(d->norris, "cinsert dot=%Δ P [%χ] LR [%χ][%χ]\n", d, p1, l, r);
+ linkchunk(p1->left, l);
+ unlink(p1, p1);
+ pushop(p1, p1, l, r, d);
+ if(p1 == d->norris)
+ d->norris = l;
+ d->from = d->off;
+ d->to = d->totalsz;
+ *d = newdot(d);
return 0;
}
int
-cpaste(usize from, usize to)
+cpaste(Dot *d)
{
- Chunk *p1, *p2, *l, *r;
+ Chunk *c;
- if(hold.from == nil || hold.to == nil){
+ if(hold.c == nil){
werrstr("cpaste: nothing to paste");
return -1;
}
- p1 = hold.from;
- p2 = hold.to;
- if(p1 == p2)
- l = splitchunk(p1, hold.foff, hold.toff);
- else{
- l = splitchunk(p1, hold.foff, p1->len);
- r = splitchunk(p2, 0, hold.toff);
- if(p1->right != p2)
- linkchunk(l, clone(p1->right, p2->left));
- linkchunk(l->left, r);
- }
- return from == to ? cinsert(from, l) : creplace(from, to, l);
+ dprint(d->norris, "cpaste dot=%Δ hold=%Δ\n", d, &hold.Dot);
+ c = clone(hold.c, hold.c->left);
+ return d->off == -1ULL ? creplace(d, c) : cinsert(d, c);
}
void
-ccopy(usize from, usize to)
+chold(Chunk *c, Dot *d)
{
- hold.from = p2c(from, &hold.foff);
- hold.to = p2c(to, &hold.toff);
+ if(hold.c != nil)
+ freechain(hold.c);
+ hold.c = c;
+ hold.Dot = *d;
}
-void
-chold(Chunk *c)
+/* [p1]..[x]..[p2] → [p1|l]..[x]..[r|p2] → hold = [l]..[x]..[r] */
+Chunk *
+ccopy(Dot *d)
{
- hold.from = hold.to = c;
- hold.foff = hold.toff = 0;
+ usize foff, toff;
+ Chunk *p1, *p2, *l, *r;
+
+ if(hold.c != nil)
+ freechain(hold.c);
+ p1 = p2c(d->from, &foff, d);
+ p2 = p2c(d->to, &toff, d);
+ if(p1 == p2){
+ l = splitchunk(p1, foff, toff);
+ r = nil;
+ }else{
+ l = splitchunk(p1, foff, p1->len);
+ r = splitchunk(p2, 0, toff);
+ if(p1->right != p2)
+ 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",
+ d, p1, p2, l, p1 == p2 ? l : r);
+ hold.c = l;
+ hold.Dot = *d;
+ return hold.c;
}
+/* [p1]..[x]..[p2] → [l|p1]..[x]..[p2|r] → [l][r] */
void
-ccut(usize from, usize to)
+ccut(Dot *d)
{
- usize n;
+ usize off;
Chunk *p1, *p2, *l, *r;
- if(from - to == totalsz){
+ if(d->from - d->to == d->totalsz){
fprint(2, "ccut: not cutting entire buffer\n");
return;
}
- assert(from < to && to <= totalsz);
- ccopy(from, to);
- p1 = hold.from;
- p2 = hold.to;
- l = splitchunk(p1, 0, hold.foff);
- r = splitchunk(p2, hold.toff, p2->len);
+ assert(d->from < d->to && d->to <= d->totalsz);
+ ccopy(d);
+ p1 = p2c(d->from, &off, d);
+ l = splitchunk(p1, 0, off);
+ if(d->from == d->to)
+ p2 = p1;
+ else
+ p2 = p2c(d->to, &off, d);
+ r = splitchunk(p2, off, p2->len);
linkchunk(l, r);
- n = chainlen(l);
- totalsz += n;
+ dprint(d->norris, "ccut dot=%Δ\n\tP\t[ %χ ]\t[ %χ ]\n\tLR:\t[ %χ ]\t[ %χ ]\n",
+ d, p1, p2, l, r);
linkchunk(p1->left, l);
unlink(p1, p2);
- totalsz -= chainlen(p1);
- pushop(p1, p2, l, r);
- if(p1 == norris)
- norris = l;
- dot.from = dot.pos = from;
- dot.to = totalsz;
- latchedpos = -1;
+ pushop(p1, p2, l, r, d);
+ if(p1 == d->norris)
+ d->norris = l;
+ *d = newdot(d);
}
uchar *
@@ -477,12 +481,12 @@
usize n, off;
Chunk *c;
- if(d->pos >= totalsz){
+ if(d->cur >= d->totalsz){
werrstr("out of bounds");
*have = 0;
return nil;
}
- c = p2c(d->pos, &off);
+ c = p2c(d->cur, &off, d);
n = c->len - off;
*have = want > n ? n : want;
return c->b->buf + c->boff + off;
@@ -489,7 +493,7 @@
}
Chunk *
-chunkfile(int fd)
+loadfile(int fd, Dot *d)
{
int n;
Chunk *c;
@@ -499,7 +503,7 @@
b = c->b;
for(;;){
if(b->bufsz - c->len < Chunksz){
- b->buf = erealloc(c->b->buf, 2 * c->b->bufsz, c->b->bufsz);
+ b->buf = erealloc(b->buf, 2 * b->bufsz, b->bufsz);
b->bufsz *= 2;
}
if((n = readn(fd, b->buf + c->len, Chunksz)) < Chunksz)
@@ -508,11 +512,13 @@
yield();
}
if(n < 0){
- fprint(2, "chunkfile: %r\n");
+ fprint(2, "loadfile: %r\n");
freechunk(c);
return nil;
- }else if(c->len == 0){
- fprint(2, "chunkfile: nothing read\n");
+ }
+ c->len += n;
+ if(c->len == 0){
+ fprint(2, "loadfile: nothing read\n");
freechunk(c);
return nil;
}else if(c->len < b->bufsz){
@@ -519,14 +525,7 @@
b->buf = erealloc(b->buf, c->len, b->bufsz);
b->bufsz = c->len;
}
+ d->norris = c;
+ *d = newdot(d);
return c;
-}
-
-void
-initbuf(Chunk *c)
-{
- norris = c;
- totalsz = chainlen(c);
- dot.pos = dot.from = 0;
- dot.to = totalsz;
}
--- a/cmd.c
+++ b/cmd.c
@@ -4,9 +4,9 @@
#include "dat.h"
#include "fns.h"
-Dot dot;
-usize totalsz;
int treadsoftly;
+usize ndots;
+Dot *current, *dots;
static int epfd[2];
@@ -13,20 +13,13 @@
static int
paste(char *)
{
- usize from, to;
-
- from = dot.from;
- to = dot.to;
- if(latchedpos >= 0 && dot.from == 0 && dot.to == totalsz)
- to = from = latchedpos;
- latchedpos = -1;
- return cpaste(from, to) == 0 ? 1 : -1;
+ return cpaste(current) == 0 ? 1 : -1;
}
static int
copy(char *)
{
- ccopy(dot.from, dot.to);
+ ccopy(current);
return 0;
}
@@ -33,12 +26,12 @@
static vlong
cut(char *)
{
- dprint(nil, "cmd/cut %Δ\n", &dot);
- if(dot.from == 0 && dot.to == totalsz){
+ dprint(nil, "cmd/cut %Δ\n", current);
+ if(current->from == 0 && current->to == current->totalsz){
werrstr("cut: can't cut entire buffer");
return -1;
}
- ccut(dot.from, dot.to);
+ ccut(current);
return 1;
}
@@ -45,8 +38,8 @@
static int
crop(char *)
{
- dprint(nil, "cmd/crop %Δ\n", &dot);
- ccrop(dot.from, dot.to);
+ dprint(nil, "cmd/crop %Δ\n", current);
+ ccrop(current);
return 1;
}
@@ -58,11 +51,11 @@
usize n, m, k;
Dot d;
- d = dot;
- d.pos = d.from;
+ d = *current;
+ d.cur = d.from;
if((nio = iounit(fd)) == 0)
nio = 8192;
- for(m=d.to-d.from, b=(uchar*)&d; m>0; m-=n, d.pos+=n){
+ for(m=d.to-d.from, b=(uchar*)&d; m>0; m-=n, d.cur+=n){
k = nio < m ? nio : m;
if((b = getslice(&d, k, &k)) == nil || k <= 0){
fprint(2, "writebuf: couldn\'t snarf: %r\n");
@@ -103,22 +96,23 @@
rproc(void *efd)
{
int fd;
- Dot d;
+ Dot d, cd;
Chunk *c;
- d = dot;
+ d = *current;
treadsoftly++;
fd = (intptr)efd;
- if((c = chunkfile(fd)) == nil){
+ if((c = loadfile(fd, &cd)) == nil){
treadsoftly = 0;
- threadexits("failed reading from pipe: %r");
+ fprint(2, "failed reading from pipe: %r");
+ threadexits("read error");
}
close(fd);
qlock(&lsync);
- dot.from = d.from;
- dot.to = d.to;
- chold(c);
- paste(nil);
+ chold(c, &d);
+ *current = d;
+ if(paste(nil) < 0)
+ fprint(2, "paste: %r\n");
qunlock(&lsync);
treadsoftly--;
redraw(0);
@@ -225,6 +219,7 @@
break;
s += n;
}
+ dprint(current->norris, "current dot=%Δ\n", current);
switch(r){
case '<': x = pipefrom(s); break;
case '^': x = pipethrough(s); break;
@@ -241,8 +236,7 @@
case 'x': x = crop(s); break;
default: werrstr("unknown command %C", r); x = -1; break;
}
- if(debug)
- checksz();
+ dprint(current->norris, "final dot=%Δ\n", current);
return x;
}
@@ -251,28 +245,17 @@
{
usize m;
- assert(d->pos >= d->from && d->pos <= d->to);
+ assert(d->cur >= d->from && d->cur <= d->to);
while(n > 0){
- m = d->to - d->pos > n ? n : d->to - d->pos;
+ m = d->to - d->cur > n ? n : d->to - d->cur;
n -= m;
- d->pos += m;
- if(d->pos == d->to)
- d->pos = d->from;
+ d->cur += m;
+ if(d->cur == d->to)
+ d->cur = d->from;
}
return 0;
}
-int
-loadin(int fd)
-{
- Chunk *c;
-
- if((c = chunkfile(fd)) == nil)
- sysfatal("loadin: %r");
- initbuf(c);
- return 0;
-}
-
static void
catch(void *, char *msg)
{
@@ -281,8 +264,15 @@
noted(NDFLT);
}
-void
-initcmd(void)
+int
+initcmd(int fd)
{
- notify(catch);
+ Dot d;
+
+ if(loadfile(fd, &d) == nil)
+ sysfatal("initcmd: %r");
+ dots = emalloc(++ndots * sizeof *dots);
+ dots[0] = d;
+ current = dots;
+ return 0;
}
--- a/dat.h
+++ b/dat.h
@@ -19,13 +19,16 @@
Chunk *right;
};
extern struct Dot{
- usize pos;
+ usize cur;
usize from;
usize to;
+ usize off;
+ usize totalsz;
+ Chunk *norris;
};
-extern Dot dot;
-extern vlong latchedpos;
-extern usize totalsz;
+extern Dot *dots, *current;
+extern usize ndots;
+
extern int treadsoftly;
extern QLock lsync;
--- a/draw.c
+++ b/draw.c
@@ -7,7 +7,6 @@
QLock lsync;
int debugdraw;
-vlong latchedpos;
enum{
Cbg,
@@ -62,7 +61,7 @@
usize p;
p = va_arg(fmt->args, usize);
- if(p > totalsz)
+ if(p > current->totalsz)
return fmtstrcpy(fmt, "-∞");
b2t(p, &th, &tm, &ts, &tμ);
return fmtprint(fmt, "%02d:%02d:%02d.%03d (%zd)",
@@ -89,7 +88,7 @@
usize p, off;
Chunk *c;
- c = p2c(views, &off);
+ c = p2c(views, &off, current);
for(p=views-off; p<viewe; p+=c->len, c=c->right){
if(p == 0)
continue;
@@ -114,9 +113,10 @@
lockdisplay(display);
draw(viewbg, viewbg->r, col[Cbg], nil, ZP);
unlockdisplay(display);
+ d = *current;
d.from = 0;
- d.pos = views;
- d.to = totalsz;
+ d.cur = views;
+ d.to = d.totalsz;
m = viewe - views;
x = 0;
qlock(&lsync);
@@ -134,7 +134,7 @@
fprint(2, "getslice: %r\n");
goto end;
}
- d.pos += k;
+ d.cur += k;
e = p + k;
while(p < e){
s = (s16int)(p[1] << 8 | p[0]);
@@ -163,7 +163,7 @@
if(stereo)
draw(viewbg, r, col[Csamp], nil, ZP);
unlockdisplay(display);
- x = (d.pos - views) / T;
+ x = (d.cur - views) / T;
if(x % 320 == 0)
update();
}
@@ -178,14 +178,14 @@
char s[256];
Point p;
- seprint(s, s+sizeof s, "T %zd @ %τ", T / Sampsz, dot.pos);
+ seprint(s, s+sizeof s, "T %zd @ %τ", T / Sampsz, current->cur);
p = string(screen, statp, col[Ctext], ZP, font, s);
- if(dot.from > 0 || dot.to < totalsz){
- seprint(s, s+sizeof s, " ↺ %τ - %τ (%τ)", dot.from, dot.to, dot.to - dot.from);
+ if(current->from > 0 || current->to < current->totalsz){
+ seprint(s, s+sizeof s, " ↺ %τ - %τ", current->from, current->to);
p = string(screen, p, col[Cloop], ZP, font, s);
}
- if(latchedpos >= 0){
- seprint(s, s+sizeof s, " ‡ %τ", (usize)latchedpos);
+ if(current->off != current->from){
+ seprint(s, s+sizeof s, " ‡ %τ", current->off);
p = string(screen, p, col[Cins], ZP, font, s);
}
}
@@ -196,10 +196,10 @@
draw(view, view->r, viewbg, nil, ZP);
if(debugdraw)
drawchunks();
- drawpos(dot.from, col[Cloop]);
- drawpos(dot.to, col[Cloop]);
- if(latchedpos >= 0)
- drawpos(latchedpos, col[Cins]);
+ drawpos(current->from, col[Cloop]);
+ drawpos(current->to, col[Cloop]);
+ if(current->off != current->from)
+ drawpos(current->from, col[Cins]);
}
void
@@ -208,7 +208,7 @@
int x;
usize p;
- p = dot.pos;
+ p = current->cur;
lockdisplay(display);
drawview();
draw(screen, screen->r, view, nil, ZP);
@@ -233,7 +233,7 @@
z = zoom / pow(2, -Δz);
else
z = zoom * pow(2, Δz);
- if(z < 1.0 || z > (totalsz / Sampsz) / Dx(screen->r))
+ if(z < 1.0 || z > (current->totalsz / Sampsz) / Dx(screen->r))
return;
zoom = z;
redraw(0);
@@ -245,8 +245,8 @@
if(from < 0)
from = 0;
from &= ~3;
- if(to >= totalsz)
- to = totalsz;
+ if(to >= current->totalsz)
+ to = current->totalsz;
to &= ~3;
if((to - from) / Sampsz < Dx(screen->r)){
werrstr("range too small");
@@ -254,7 +254,7 @@
}
views = from;
viewe = to;
- zoom = (double)totalsz / (to - from);
+ zoom = (double)current->totalsz / (to - from);
redraw(0);
return 0;
}
@@ -290,22 +290,21 @@
{
assert((from & 3) == 0);
assert((to & 3) == 0);
- dot.from = from;
- dot.to = to;
- if(dot.pos < from || dot.pos >= to)
- dot.pos = from;
- latchedpos = -1;
+ current->from = from;
+ current->to = to;
+ if(current->cur < from || current->cur >= to)
+ current->cur = from;
+ current->off = -1ULL;
}
static int
setcur(usize off)
{
- if(off < dot.from || off > dot.to - Outsz){
+ if(off < current->from || off > current->to - Outsz){
werrstr("cannot jump outside of loop bounds\n");
return -1;
}
- dot.pos = off;
- latchedpos = off;
+ current->off = current->cur = off;
update();
return 0;
}
@@ -315,12 +314,12 @@
{
off *= T;
off += views;
- if(off < 0 || off > totalsz)
+ if(off < 0 || off > current->totalsz)
return;
- if(off < dot.pos)
- setrange(off, dot.to);
+ if(off < current->cur)
+ setrange(off, current->to);
else
- setrange(dot.from, off);
+ setrange(current->from, off);
update();
}
@@ -342,7 +341,7 @@
int x;
Rectangle viewr;
- x = screen->r.min.x + (dot.pos - views) / T;
+ x = screen->r.min.x + (current->cur - views) / T;
viewr = rectsubpt(screen->r, screen->r.min);
statp = screen->r.min;
if(stereo)
@@ -367,11 +366,11 @@
usize span;
lockdisplay(display);
- T = (vlong)(totalsz / zoom / Dx(screen->r)) & ~3;
+ T = (vlong)(current->totalsz / zoom / Dx(screen->r)) & ~3;
if(T == 0)
T = 4;
span = Dx(screen->r) * T;
- viewmax = totalsz - span;
+ viewmax = current->totalsz - span;
if(views > viewmax)
views = viewmax;
viewe = views + span;
--- a/fns.h
+++ b/fns.h
@@ -1,17 +1,15 @@
void dprint(Chunk*, char*, ...);
-void checksz(void);
void freechain(Chunk*);
int unpop(char*);
int popop(char*);
-int cpaste(usize, usize);
-void ccopy(usize, usize);
-void chold(Chunk*);
-void ccut(usize, usize);
-void ccrop(usize, usize);
-Chunk* chunkfile(int);
-void initbuf(Chunk*);
+int cpaste(Dot*);
+Chunk* ccopy(Dot*);
+void chold(Chunk*, Dot*);
+void ccut(Dot*);
+void ccrop(Dot*);
+Chunk* loadfile(int, Dot*);
int cmd(char*);
-void initcmd(void);
+int initcmd(int);
void update(void);
void setzoom(int, int);
int zoominto(vlong, vlong);
@@ -24,11 +22,10 @@
void redraw(int);
void initdrw(int);
int advance(Dot*, usize);
-Chunk* p2c(usize, usize*);
+Chunk* p2c(usize, usize*, Dot*);
int setpos(usize);
uchar* getslice(Dot*, usize, usize*);
vlong getbuf(Dot, usize, uchar*, usize);
-int loadin(int);
int χfmt(Fmt*);
int Δfmt(Fmt*);
int τfmt(Fmt*);
--- a/pplay.c
+++ b/pplay.c
@@ -20,27 +20,28 @@
static void
athread(void *)
{
- int m, nerr;
- uchar *b;
- usize n;
+ int nerr;
+ uchar *b, *bp, buf[Outsz];
+ usize n, m;
nerr = 0;
for(;;){
if(afd < 0 || nerr > 10)
return;
- for(m=Outsz; m>0; m-=n){
- if((b = getslice(&dot, Outsz, &n)) == nil || n <= 0){
+ for(bp=buf, m=sizeof buf; bp<buf+sizeof buf; bp+=n, m-=n){
+ if((b = getslice(current, m, &n)) == nil || n <= 0){
fprint(2, "athread: %r\n");
nerr++;
goto skip;
}
- if(write(afd, b, n) != n){
- fprint(2, "athread write: %r\n");
- threadexits("write");
- }
+ memcpy(bp, b, n);
+ advance(current, n);
}
+ if(write(afd, buf, sizeof buf) != sizeof buf){
+ fprint(2, "athread write: %r\n");
+ threadexits("write");
+ }
nerr = 0;
- advance(&dot, n);
update();
skip:
yield();
@@ -58,7 +59,7 @@
play = 0;
return;
}
- if(threadcreate(athread, nil, mainstacksize) < 0)
+ if(threadcreate(athread, nil, 2*mainstacksize) < 0)
sysfatal("threadcreate: %r");
}else{
if(!cat)
@@ -103,13 +104,13 @@
case 'c': cat = 1; break;
default: usage();
}ARGEND
- if((fd = *argv != nil ? open(*argv, OREAD) : 0) < 0)
- sysfatal("open: %r");
fmtinstall(L'Δ', Δfmt);
fmtinstall(L'χ', χfmt);
fmtinstall(L'τ', τfmt);
- if(loadin(fd) < 0)
- sysfatal("inittrack: %r");
+ if((fd = *argv != nil ? open(*argv, OREAD) : 0) < 0)
+ sysfatal("open: %r");
+ if(initcmd(fd) < 0)
+ sysfatal("init: %r");
close(fd);
initdrw(notriob);
if((kc = initkeyboard(nil)) == nil)
@@ -123,7 +124,6 @@
{kc->c, &r, CHANRCV},
{nil, nil, CHANEND}
};
- initcmd();
if(setpri(13) < 0)
fprint(2, "setpri: %r\n");
toggleplay();
@@ -154,10 +154,10 @@
case 'D': debug ^= 1; debugdraw ^= 1; break;
case 'S': stereo ^= 1; redraw(1); break;
case ' ': toggleplay(); break;
- case 'b': setjump(dot.from); break;
- case Kesc: setrange(0, totalsz); update(); break;
- case '\n': zoominto(dot.from, dot.to); break;
- case 'z': zoominto(0, totalsz); break;
+ case 'b': setjump(current->from); break;
+ case Kesc: setrange(0, current->totalsz); update(); break;
+ case '\n': zoominto(current->from, current->to); break;
+ case 'z': zoominto(0, current->totalsz); break;
case '-': setzoom(-1, 0); break;
case '=': setzoom(1, 0); break;
case '_': setzoom(-1, 1); break;