typedef struct Page Page;
struct Page {
- char *label;
+ char *name;
+ char *delim;
QLock;
char *ext;
Image *image;
int fd;
- int gen;
Page *up;
Page *next;
Page *down;
Page *tail;
+
+ Page *lnext;
+ Page *lprev;
};
int zoom = 1;
int newwin;
int rotate;
int viewgen;
-int pagegen;
+int forward; /* read ahead direction: >= 0 forwards, < 0 backwards */
Point resize, pos;
Page *root, *current;
+Page lru;
QLock pagelock;
int nullfd;
+char *pagewalk = nil;
+
+enum {
+ MiB = 1024*1024,
+};
+
+ulong imemlimit = 16*MiB;
+ulong imemsize;
Image *frame, *paper, *ground;
enum {
NPROC = 4,
- NAHEAD = 2,
NBUF = 8*1024,
NPATH = 1024,
};
Cdummy1,
Cnext,
Cprev,
+ Csnarf,
Czerox,
Cwrite,
Cext,
[Cdummy1] "", 0, 0, 0,
[Cnext] "next", Kright, ' ', '\n',
[Cprev] "prev", Kleft, Kbs, 0,
+ [Csnarf] "snarf", 's', 0, 0,
[Czerox] "zerox", 'z', 0, 0,
[Cwrite] "write", 'w', 0, 0,
[Cext] "ext", 'x', 0, 0,
0x00, 0x00, 0x01, 0xb6, 0x01, 0xb6, 0x00, 0x00, }
};
+int pagewalk1(Page *p);
void showpage1(Page *);
void showpage(Page *);
void drawpage(Page *);
Point pagesize(Page *);
Page*
-addpage(Page *up, char *label, int (*popen)(Page *), void *pdata, int fd)
+addpage(Page *up, char *name, int (*popen)(Page *), void *pdata, int fd)
{
Page *p;
p = mallocz(sizeof(*p), 1);
- p->label = strdup(label);
- p->gen = pagegen;
- p->image = nil;
+ p->name = strdup(name);
+ p->delim = "!";
+ p->image = nil;
p->data = pdata;
p->open = popen;
p->fd = fd;
- p->down = nil;
- p->tail = nil;
- p->next = nil;
-
qlock(&pagelock);
if(p->up = up){
if(up->tail == nil)
}
qunlock(&pagelock);
- if(up && current == up)
+ if(up && current == up){
+ if(!pagewalk1(p))
+ return p;
showpage1(p);
+ }
return p;
}
return;
/* add rio border */
size = addpt(size, Pt(Borderwidth*2, Borderwidth*2));
- if(display->image){
+ if(display->image != nil){
Point dsize = subpt(display->image->r.max, display->image->r.min);
if(size.x > dsize.x)
size.x = dsize.x;
close(pfd[0]);
}
-char*
-shortname(char *s)
+static char*
+shortlabel(char *s)
{
- char *x;
-
- while(strlen(s) > 20){
- if((x = strchr(s, '/')) == nil)
- break;
- if(x[1] == 0)
- break;
- s = x+1;
+ enum { NR=60 };
+ static char buf[NR*UTFmax];
+ int i, k, l;
+ Rune r;
+
+ l = utflen(s);
+ if(l < NR-2)
+ return s;
+ k = i = 0;
+ while(i < NR/2){
+ k += chartorune(&r, s+k);
+ i++;
}
- return s;
+ strncpy(buf, s, k);
+ strcpy(buf+k, "...");
+ while((l-i) >= NR/2-4){
+ k += chartorune(&r, s+k);
+ i++;
+ }
+ strcat(buf, s+k);
+ return buf;
+}
+
+static char*
+pageaddr1(Page *p, char *s, char *e)
+{
+ if(p == nil || p == root)
+ return s;
+ return seprint(pageaddr1(p->up, s, e), e, "%s%s", p->up->delim, p->name);
+}
+
+/*
+ * returns address string of a page in the form:
+ * /dir/filename!page!subpage!...
+ */
+char*
+pageaddr(Page *p, char *buf, int nbuf)
+{
+ buf[0] = 0;
+ pageaddr1(p, buf, buf+nbuf);
+ return buf;
}
int
if(p->data){
p->ext = p->data;
if(strcmp(p->ext, "ico") == 0)
- snprint(nam, sizeof(nam), "%s -c", p->ext);
+ pipeline(fd, "exec %s -c", p->ext);
else
- snprint(nam, sizeof(nam), "%s -t9", p->ext);
- pipeline(fd, "%s", nam);
+ pipeline(fd, "exec %s -t9", p->ext);
}
/*
{
seek(p->fd, 0, 0);
if(p->data){
- pipeline(p->fd, "%s", (char*)p->data);
+ pipeline(p->fd, "exec %s", (char*)p->data);
p->data = nil;
}
p->open = popenfile;
char mnt[32], cmd[64], *argv[4];
seek(p->fd, 0, 0);
- snprint(mnt, sizeof(mnt), "/n/tapefs.%.12d%.8lux", getpid(), (ulong)p);
- snprint(cmd, sizeof(cmd), "%s -m %s /fd/0", (char*)p->data, mnt);
+ snprint(mnt, sizeof(mnt), "/n/tapefs.%.12d%.8lux", getpid(), (ulong)(uintptr)p);
+ snprint(cmd, sizeof(cmd), "exec %s -m %s /fd/0", (char*)p->data, mnt);
switch(rfork(RFPROC|RFMEM|RFFDG|RFREND)){
case -1:
close(p->fd);
while(n > 0 && s[n-1] == '\n')
n--;
s[n] = 0;
- addpage(p, shortname(buf), popenfile, strdup(buf), -1);
+ addpage(p, s, popenfile, strdup(buf), -1);
}
close(fd);
return -1;
"(/fd/3) (w) file "
"dup flushfile "
"dup (THIS IS NOT AN INFERNO BITMAP\\n) writestring "
- "flushfile\n", p->label);
+ "flushfile\n", p->name);
while((n = read(0, buf, sizeof buf)) > 0){
if(memcmp(buf, "THIS IS NOT AN INFERNO BITMAP\n", 30) == 0)
break;
pdf = 0;
ifd = p->fd;
p->fd = -1;
+ p->open = nil;
seek(ifd, 0, 0);
if(read(ifd, buf, 5) != 5)
goto Err0;
"image/gif", popenimg, "gif",
"image/jpeg", popenimg, "jpg",
"image/png", popenimg, "png",
+ "image/tiff", popenimg, "tif",
"image/ppm", popenimg, "ppm",
"image/bmp", popenimg, "bmp",
"image/tga", popenimg, "tga",
p->ext = nil;
file = p->data;
p->data = nil;
+ p->open = nil;
if(fd < 0){
if((fd = open(file, OREAD)) < 0){
Err0:
p->open = popenepub;
return p->open(p);
}
-
+ if(strcmp(pageaddr(p, buf, sizeof(buf)), file) == 0)
+ p->delim = "/";
if((n = dirreadall(fd, &d)) < 0)
goto Err1;
qsort(d, n, sizeof d[0], dircmp);
Page*
nextpage(Page *p)
{
- if(p && p->down)
+ if(p != nil && p->down != nil)
return p->down;
- while(p){
- if(p->next)
+ while(p != nil){
+ if(p->next != nil)
return p->next;
p = p->up;
}
{
Page *p, *t;
- if(x){
- for(p = root->down; p; p = t)
+ if(x != nil){
+ for(p = root->down; p != nil; p = t)
if((t = nextpage(p)) == x)
return p;
}
p->open = nil;
else {
if(rotate)
- pipeline(fd, "rotate -r %d", rotate);
+ pipeline(fd, "exec rotate -r %d", rotate);
if(resize.x)
- pipeline(fd, "resize -x %d", resize.x);
+ pipeline(fd, "exec resize -x %d", resize.x);
else if(resize.y)
- pipeline(fd, "resize -y %d", resize.y);
+ pipeline(fd, "exec resize -y %d", resize.y);
}
return fd;
}
+static ulong
+imagesize(Image *i)
+{
+ if(i == nil)
+ return 0;
+ return Dy(i->r)*bytesperline(i->r, i->depth);
+}
+
+static void
+lunlink(Page *p)
+{
+ if(p->lnext == nil || p->lnext == p)
+ return;
+ p->lnext->lprev = p->lprev;
+ p->lprev->lnext = p->lnext;
+ p->lnext = nil;
+ p->lprev = nil;
+}
+
+static void
+llinkhead(Page *p)
+{
+ lunlink(p);
+ p->lnext = lru.lnext;
+ p->lprev = &lru;
+ p->lnext->lprev = p;
+ p->lprev->lnext = p;
+}
+
void
loadpage(Page *p)
{
int fd;
- if(p->open && p->image == nil){
+ qlock(&lru);
+ llinkhead(p);
+ qunlock(&lru);
+
+ if(p->open != nil && p->image == nil){
fd = openpage(p);
if(fd >= 0){
- pagegen++;
if((p->image = readimage(display, fd, 1)) == nil)
fprint(2, "readimage: %r\n");
close(fd);
}
if(p->image == nil)
p->open = nil;
+ else {
+ lockdisplay(display);
+ imemsize += imagesize(p->image);
+ unlockdisplay(display);
+ }
}
- p->gen = pagegen;
}
void
unloadpage(Page *p)
{
+ qlock(&lru);
+ lunlink(p);
+ qunlock(&lru);
+
if(p->open == nil || p->image == nil)
return;
lockdisplay(display);
+ imemsize -= imagesize(p->image);
freeimage(p->image);
unlockdisplay(display);
p->image = nil;
}
void
-unloadpages(int age)
+unloadpages(ulong limit)
{
Page *p;
- for(p = root->down; p; p = nextpage(p)){
- if(age == 0) /* synchronous flush */
- qlock(p);
- else if(!canqlock(p))
- continue;
- if((pagegen - p->gen) >= age)
- unloadpage(p);
+ while(imemsize >= limit && (p = lru.lprev) != &lru){
+ qlock(p);
+ unloadpage(p);
qunlock(p);
}
}
void
-loadpages(Page *p, int ahead, int oviewgen)
+loadpages(Page *p, int oviewgen)
{
- int i;
-
- ahead++; /* load at least one */
- unloadpages(ahead*2);
- for(i = 0; i < ahead && p; p = nextpage(p), i++){
- if(viewgen != oviewgen)
+ while(p != nil && viewgen == oviewgen){
+ qlock(p);
+ loadpage(p);
+ if(viewgen != oviewgen){
+ unloadpage(p);
+ qunlock(p);
break;
- if(canqlock(p)){
- loadpage(p);
- if(viewgen != oviewgen){
- unloadpage(p);
- qunlock(p);
- break;
- }
- if(p == current){
- Point size;
-
- esetcursor(nil);
- size = pagesize(p);
- if(size.x && size.y && newwin){
- newwin = 0;
- resizewin(size);
- }
- lockdisplay(display);
- drawpage(p);
- unlockdisplay(display);
+ }
+ if(p == current){
+ Point size;
+
+ esetcursor(nil);
+ size = pagesize(p);
+ if(size.x && size.y && newwin){
+ newwin = 0;
+ resizewin(size);
}
- qunlock(p);
+ lockdisplay(display);
+ drawpage(p);
+ unlockdisplay(display);
+ }
+ qunlock(p);
+ if(p != current && imemsize >= imemlimit)
+ break; /* only one page ahead once we reach the limit */
+ if(forward < 0){
+ if(p->up == nil || p->up->down == p)
+ break;
+ p = prevpage(p);
+ } else {
+ if(p->next == nil)
+ break;
+ p = nextpage(p);
}
}
}
dr = r;
for(sp=dr.min; dr.min.x < r.max.x; sp.x++){
dr.max.x = dr.min.x+1;
- if(b) gendrawdiff(d, dr, top, b, sp, nil, ZP, SoverD);
+ if(b != nil) gendrawdiff(d, dr, top, b, sp, nil, ZP, SoverD);
gendrawdiff(d, dr, top, t, sp, nil, ZP, SoverD);
for(dr.min.x++; ++a.x < f && dr.min.x < r.max.x; dr.min.x++){
dr.max.x = dr.min.x+1;
Point
pagesize(Page *p)
{
- return p->image ? mulpt(subpt(p->image->r.max, p->image->r.min), zoom) : ZP;
+ return p->image != nil ? mulpt(subpt(p->image->r.max, p->image->r.min), zoom) : ZP;
}
void
Rectangle r;
Image *i;
- if(i = p->image){
+ if((i = p->image) != nil){
r = rectaddpt(Rpt(ZP, pagesize(p)), addpt(pos, screen->r.min));
zoomdraw(screen, r, ZR, paper, i, i->r.min, zoom);
} else {
- r = Rpt(ZP, stringsize(font, p->label));
+ r = Rpt(ZP, stringsize(font, p->name));
r = rectaddpt(r, addpt(subpt(divpt(subpt(screen->r.max, screen->r.min), 2),
divpt(r.max, 2)), screen->r.min));
draw(screen, r, paper, nil, ZP);
- string(screen, r.min, display->black, ZP, font, p->label);
+ string(screen, r.min, display->black, ZP, font, p->name);
}
drawframe(r);
}
Image *i;
i = p->image;
- if(i==0 || d.x==0 && d.y==0)
+ if(i==nil || d.x==0 && d.y==0)
return;
r = rectaddpt(Rpt(ZP, pagesize(p)), addpt(pos, screen->r.min));
pos = addpt(pos, d);
nr = rectaddpt(r, d);
- rectclip(&r, screen->r);
- draw(screen, rectaddpt(r, d), screen, nil, r.min);
+ if(rectclip(&r, screen->r))
+ draw(screen, rectaddpt(r, d), screen, nil, r.min);
+ else
+ r = ZR;
zoomdraw(screen, nr, rectaddpt(r, d), paper, i, i->r.min, zoom);
drawframe(nr);
}
+int
+pagewalk1(Page *p)
+{
+ char *s;
+ int n;
+
+ if((s = pagewalk) == nil || *s == 0)
+ return 1;
+ n = strlen(p->name);
+ if(n == 0 || strncmp(s, p->name, n) != 0)
+ return 0;
+ if(s[n] == 0){
+ pagewalk = nil;
+ return 1;
+ }
+ if(s[n] == '/' || s[n] == '!'){
+ pagewalk = s + n+1;
+ return 1;
+ }
+ return 0;
+}
+
+Page*
+trywalk(char *name, char *addr)
+{
+ static char buf[NPATH];
+ Page *p, *a;
+
+ pagewalk = nil;
+ memset(buf, 0, sizeof(buf));
+ snprint(buf, sizeof(buf), "%s%s%s",
+ name != nil ? name : "",
+ (name != nil && addr != nil) ? "!" : "",
+ addr != nil ? addr : "");
+ pagewalk = buf;
+
+ a = nil;
+ if(root != nil){
+ p = root->down;
+ Loop:
+ for(; p != nil; p = p->next)
+ if(pagewalk1(p)){
+ a = p;
+ p = p->down;
+ goto Loop;
+ }
+ }
+ return a;
+}
+
Page*
findpage(char *name)
{
Page *p;
int n;
+ if(name == nil)
+ return nil;
+
n = strlen(name);
- /* look in current document first */
- if(current && current->up){
- for(p = current->up->down; p; p = p->next)
- if(cistrncmp(p->label, name, n) == 0)
+ /* look in current document */
+ if(current != nil && current->up != nil){
+ for(p = current->up->down; p != nil; p = p->next)
+ if(cistrncmp(p->name, name, n) == 0)
return p;
}
/* look everywhere */
- for(p = root->down; p; p = nextpage(p))
- if(cistrncmp(p->label, name, n) == 0)
- return p;
- return nil;
+ if(root != nil){
+ for(p = root->down; p != nil; p = nextpage(p))
+ if(cistrncmp(p->name, name, n) == 0)
+ return p;
+ }
+ /* try bookmark */
+ return trywalk(name, nil);
+}
+
+void
+writeaddr(Page *p, char *file)
+{
+ char buf[NPATH], *s;
+ int fd;
+
+ s = pageaddr(p, buf, sizeof(buf));
+ if((fd = open(file, OWRITE)) >= 0){
+ write(fd, s, strlen(s));
+ close(fd);
+ }
}
Page*
{
Page *p;
- for(p = root->down; i > 0 && p; p = nextpage(p))
+ for(p = root->down; i > 0 && p != nil; p = nextpage(p))
i--;
return i ? nil : p;
}
Page *p;
int i;
- for(i = 0, p = root->down; p && p != x; p = nextpage(p))
+ for(i = 0, p = root->down; p != nil && p != x; p = nextpage(p))
i++;
return (p == x) ? i : -1;
}
pagemenugen(int i)
{
Page *p;
- if(p = pageat(i))
- return p->label;
+
+ if((p = pageat(i)) != nil)
+ return shortlabel(p->name);
return nil;
}
if(p == nil)
return;
esetcursor(&reading);
+ writeaddr(p, "/dev/label");
current = p;
oviewgen = viewgen;
- if(++nproc > NPROC)
- if(waitpid() > 0)
- nproc--;
switch(rfork(RFPROC|RFMEM)){
case -1:
sysfatal("rfork: %r");
case 0:
- loadpages(p, NAHEAD, oviewgen);
+ loadpages(p, oviewgen);
exits(nil);
}
+ if(++nproc >= NPROC)
+ if(waitpid() > 0)
+ nproc--;
}
/* recursive display lock, called from main proc only */
void
showpage(Page *p)
{
+ if(p == nil)
+ return;
drawlock(0);
+ unloadpages(imemlimit);
showpage1(p);
drawlock(1);
}
-void
-shownext(void)
-{
- Page *p;
-
- for(p = nextpage(current); p; p = nextpage(p))
- if(p->image || p->open)
- break;
- showpage(p);
-}
-
-void
-showprev(void)
-{
- Page *p;
-
- for(p = prevpage(current); p; p = prevpage(p))
- if(p->image || p->open)
- break;
- showpage(p);
-}
-
void
zerox(Page *p)
{
void
showext(Page *p)
{
- char buf[128], label[64], *argv[4];
+ char label[64], *argv[4];
Point ps;
int fd;
if(p->ext == nil)
return;
- snprint(label, sizeof(label), "%s %s", p->ext, p->label);
- if(p->image){
- ps = subpt(p->image->r.max, p->image->r.min);
- ps.x += 24;
- ps.y += 24;
- } else
- ps = subpt(screen->r.max, screen->r.min);
+ snprint(label, sizeof(label), "%s %s", p->ext, p->name);
+ ps = Pt(0, 0);
+ if(p->image != nil)
+ ps = addpt(subpt(p->image->r.max, p->image->r.min), Pt(24, 24));
drawlock(0);
if((fd = p->fd) < 0){
if(p->open != popenfile)
fd = dup(fd, -1);
seek(fd, 0, 0);
}
- if(rfork(RFPROC|RFMEM|RFFDG|RFNOTEG|RFNAMEG|RFNOWAIT) == 0){
- snprint(buf, sizeof(buf), "-pid %d -dx %d -dy %d", getpid(), ps.x, ps.y);
- if(newwindow(buf) != -1){
- dupfds(fd, 1, 2, -1);
+ if(rfork(RFPROC|RFMEM|RFFDG|RFNOTEG|RFREND|RFNOWAIT) == 0){
+ if(newwindow(nil) != -1){
+ dupfds(fd, open("/dev/cons", OWRITE), open("/dev/cons", OWRITE), -1);
if((fd = open("/dev/label", OWRITE)) >= 0){
write(fd, label, strlen(label));
close(fd);
}
+ if(ps.x && ps.y)
+ resizewin(ps);
argv[0] = "rc";
argv[1] = "-c";
argv[2] = p->ext;
drawlock(1);
}
-
void
eresized(int new)
{
drawlock(1);
if(new && getwindow(display, Refnone) == -1)
sysfatal("getwindow: %r");
- if(p = current){
+ if((p = current) != nil){
if(canqlock(p)){
drawpage(p);
qunlock(p);
void
usage(void)
{
- fprint(2, "usage: %s [ -iRw ] [ -p ppi ] [ file ... ]\n", argv0);
+ fprint(2, "usage: %s [ -iRw ] [ -m mb ] [ -p ppi ] [ -j addr ] [ file ... ]\n", argv0);
exits("usage");
}
break;
o = subpt(m->xy, screen->r.min);
if(i == Czoomin){
- if(zoom < 0x40000000){
+ if(zoom < 0x1000){
zoom *= 2;
pos = addpt(mulpt(subpt(pos, o), 2), o);
}
case Cwrite:
if(current == nil || !canqlock(current))
break;
- if(current->image){
+ if(current->image != nil){
s = nil;
- if(current->up && current->up != root)
- s = current->up->label;
+ if(current->up != nil && current->up != root)
+ s = current->up->name;
snprint(buf, sizeof(buf), "%s%s%s.bit",
- s ? s : "",
- s ? "." : "",
- current->label);
+ s != nil ? s : "",
+ s != nil ? "." : "",
+ current->name);
if(eenter("Write", buf, sizeof(buf), m) > 0){
if((fd = create(buf, OWRITE, 0666)) < 0){
errstr(buf, sizeof(buf));
showext(current);
qunlock(current);
break;
+ case Csnarf:
+ writeaddr(current, "/dev/snarf");
+ break;
case Cnext:
- shownext();
+ forward = 1;
+ showpage(nextpage(current));
break;
case Cprev:
- showprev();
+ forward = -1;
+ showpage(prevpage(current));
break;
case Czerox:
zerox(current);
}
}
+void
+scroll(int y)
+{
+ Point z;
+ Page *p;
+
+ if(current == nil || !canqlock(current))
+ return;
+ if(y < 0){
+ if(pos.y >= 0){
+ p = prevpage(current);
+ if(p != nil){
+ qunlock(current);
+ z = ZP;
+ if(canqlock(p)){
+ z = pagesize(p);
+ qunlock(p);
+ }
+ if(z.y == 0)
+ z.y = Dy(screen->r);
+ if(pos.y+z.y > Dy(screen->r))
+ pos.y = Dy(screen->r) - z.y;
+ forward = -1;
+ showpage(p);
+ return;
+ }
+ y = 0;
+ }
+ } else {
+ z = pagesize(current);
+ if(pos.y+z.y <= Dy(screen->r)){
+ p = nextpage(current);
+ if(p != nil){
+ qunlock(current);
+ if(pos.y < 0)
+ pos.y = 0;
+ forward = 1;
+ showpage(p);
+ return;
+ }
+ y = 0;
+ }
+ }
+ translate(current, Pt(0, -y));
+ qunlock(current);
+}
+
void
main(int argc, char *argv[])
{
char *s;
int i;
+ quotefmtinstall();
+
ARGBEGIN {
case 'a':
case 'v':
case 'P':
break;
case 'R':
- newwin = -1;
+ if(newwin == 0)
+ newwin = -1;
break;
case 'w':
newwin = 1;
case 'i':
imode = 1;
break;
+ case 'j':
+ trywalk(EARGF(usage()), nil);
+ break;
+ case 'm':
+ imemlimit = atol(EARGF(usage()))*MiB;
+ break;
case 'p':
ppi = atoi(EARGF(usage()));
break;
usage();
} ARGEND;
+ if(newwin > 0){
+ if(newwindow(nil) < 0)
+ sysfatal("newwindow: %r");
+ }
+
/*
* so that we can stop all subprocesses with a note,
* and to isolate rendezvous from other processes
}
cohort = getpid();
atexit(killcohort);
-
- if(newwin > 0){
- s = smprint("-pid %d", getpid());
- if(newwindow(s) < 0)
- sysfatal("newwindow: %r");
- free(s);
- }
if(initdraw(drawerr, nil, argv0) < 0)
sysfatal("initdraw: %r");
paper = display->white;
ground = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x777777FF);
display->locking = 1;
unlockdisplay(display);
- drawlock(1);
einit(Ekeyboard|Emouse);
eplumb(Eplumb, "image");
memset(&m, 0, sizeof(m));
if((nullfd = open("/dev/null", ORDWR)) < 0)
sysfatal("open: %r");
+ dup(nullfd, 1);
+ lru.lprev = &lru;
+ lru.lnext = &lru;
current = root = addpage(nil, "", nil, nil, -1);
+ root->delim = "";
if(*argv == nil && !imode)
addpage(root, "stdin", popenfile, strdup("/fd/0"), -1);
for(; *argv; argv++)
- addpage(root, shortname(*argv), popenfile, strdup(*argv), -1);
+ addpage(root, *argv, popenfile, strdup(*argv), -1);
+ drawlock(1);
for(;;){
drawlock(0);
i=event(&e);
pagemenu.lasthit = pageindex(current);
x = pageat(emenuhit(3, &m, &pagemenu));
qunlock(&pagelock);
+ forward = 0;
showpage(x);
}
+ } else if(m.buttons & 8){
+ scroll(screen->r.min.y - m.xy.y);
+ } else if(m.buttons & 16){
+ scroll(m.xy.y - screen->r.min.y);
}
break;
case Ekeyboard:
switch(e.kbdc){
case Kup:
- if(current == nil || !canqlock(current))
- break;
- if(pos.y < 0){
- translate(current, Pt(0, Dy(screen->r)/2));
- qunlock(current);
- break;
- }
- if(prevpage(current))
- pos.y = 0;
- qunlock(current);
- docmd(Cprev, &m);
+ scroll(-Dy(screen->r)/3);
+ break;
+ case Kpgup:
+ scroll(-Dy(screen->r)/2);
break;
case Kdown:
- if(current == nil || !canqlock(current))
- break;
- o = addpt(pos, pagesize(current));
- if(o.y > Dy(screen->r)){
- translate(current, Pt(0, -Dy(screen->r)/2));
- qunlock(current);
- break;
- }
- if(nextpage(current))
- pos.y = 0;
- qunlock(current);
- docmd(Cnext, &m);
+ scroll(Dy(screen->r)/3);
+ break;
+ case Kpgdown:
+ scroll(Dy(screen->r)/2);
break;
default:
for(i = 0; i<nelem(cmds); i++)
(e.kbdc & 0xFF00) == Spec)
break;
snprint(buf, sizeof(buf), "%C", (Rune)e.kbdc);
- if(eenter("Go to", buf, sizeof(buf), &m) > 0)
+ if(eenter("Go to", buf, sizeof(buf), &m) > 0){
+ forward = 0;
showpage(findpage(buf));
+ }
}
break;
case Eplumb:
pm = e.v;
if(pm && pm->ndata > 0){
+ Page *j;
int fd;
fd = -1;
sprint(s, "%s/%s", pm->wdir, pm->data);
cleanname(s);
}
- showpage(addpage(root, shortname(s), popenfile, s, fd));
+ j = trywalk(s, plumblookup(pm->attr, "addr"));
+ if(j == nil){
+ current = root;
+ drawlock(0);
+ j = addpage(root, s, popenfile, s, fd);
+ drawlock(1);
+ }
+ forward = 0;
+ showpage(j);
}
Plumbfree:
plumbfree(pm);