page: implement bookmarks (thanks trav_ for starting it)
add new functions pageaddr() that returns a string describing the page to be loaded. it is in the form of: /path/to/file!pagename!subpage!.... one can jump to such a page by calling trywalk(name, addr) where name and addr get concatinated with ! to form a page address and then the currently loaded pages are walked up to the nearest page which is then returned. (or nil when not found). the remaining address will be set in the global pagewalk variable. once pages get loaded (asynchronously), pagewalk1() gets called again on addpage() and continues the walking up to the last page. new program flag -j <addr> was added to jump to a page on startup. page address (without filename) can also be supplied in plumb message with the "addr" attribute.
This commit is contained in:
parent
803bc88a5f
commit
48d2f14f80
2 changed files with 179 additions and 36 deletions
|
@ -9,12 +9,13 @@ files
|
||||||
.B page
|
.B page
|
||||||
[
|
[
|
||||||
.B -abirPRvVw
|
.B -abirPRvVw
|
||||||
]
|
] [
|
||||||
[
|
|
||||||
.B -p
|
.B -p
|
||||||
.I ppi
|
.I ppi
|
||||||
]
|
] [
|
||||||
[
|
.B -j
|
||||||
|
.I addr
|
||||||
|
] [
|
||||||
.IR file ...
|
.IR file ...
|
||||||
]
|
]
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
|
@ -96,6 +97,12 @@ to not load any graphics files nor to read
|
||||||
from standard input but rather to listen
|
from standard input but rather to listen
|
||||||
for ones to load from the plumbing channel.
|
for ones to load from the plumbing channel.
|
||||||
.PP
|
.PP
|
||||||
|
The
|
||||||
|
.B -j
|
||||||
|
option with a page address
|
||||||
|
.I addr
|
||||||
|
jumps to the specified page on startup.
|
||||||
|
.PP
|
||||||
Pressing and holding button 1 permits panning about the page.
|
Pressing and holding button 1 permits panning about the page.
|
||||||
.PP
|
.PP
|
||||||
Button 2 raises a menu of operations on the current image or the
|
Button 2 raises a menu of operations on the current image or the
|
||||||
|
@ -126,6 +133,9 @@ Displays the next page.
|
||||||
.B Prev
|
.B Prev
|
||||||
Displays the previous page.
|
Displays the previous page.
|
||||||
.TP
|
.TP
|
||||||
|
.B Snarf
|
||||||
|
Writes the current page address to the snarf buffer.
|
||||||
|
.TP
|
||||||
.B Zerox
|
.B Zerox
|
||||||
Displays the current image in a new page window.
|
Displays the current image in a new page window.
|
||||||
Useful for selecting important pages from large documents.
|
Useful for selecting important pages from large documents.
|
||||||
|
@ -179,6 +189,10 @@ page /usr/inferno/icons/*.bit
|
||||||
Browse the Inferno bitmap library.
|
Browse the Inferno bitmap library.
|
||||||
.TP
|
.TP
|
||||||
.L
|
.L
|
||||||
|
page -j /sys/doc/troff.pdf!7 /sys/doc/troff.pdf
|
||||||
|
Jump to page 7 in the troff manual.
|
||||||
|
.TP
|
||||||
|
.L
|
||||||
man -t page | page -w
|
man -t page | page -w
|
||||||
Preview this manual in a new window.
|
Preview this manual in a new window.
|
||||||
.SH "SEE ALSO
|
.SH "SEE ALSO
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
|
|
||||||
typedef struct Page Page;
|
typedef struct Page Page;
|
||||||
struct Page {
|
struct Page {
|
||||||
char *label;
|
char *name;
|
||||||
|
char *delim;
|
||||||
|
|
||||||
QLock;
|
QLock;
|
||||||
char *ext;
|
char *ext;
|
||||||
|
@ -38,6 +39,7 @@ Page *root, *current;
|
||||||
Page lru;
|
Page lru;
|
||||||
QLock pagelock;
|
QLock pagelock;
|
||||||
int nullfd;
|
int nullfd;
|
||||||
|
char *pagewalk = nil;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MiB = 1024*1024,
|
MiB = 1024*1024,
|
||||||
|
@ -67,6 +69,7 @@ enum {
|
||||||
Cdummy1,
|
Cdummy1,
|
||||||
Cnext,
|
Cnext,
|
||||||
Cprev,
|
Cprev,
|
||||||
|
Csnarf,
|
||||||
Czerox,
|
Czerox,
|
||||||
Cwrite,
|
Cwrite,
|
||||||
Cext,
|
Cext,
|
||||||
|
@ -90,6 +93,7 @@ struct {
|
||||||
[Cdummy1] "", 0, 0, 0,
|
[Cdummy1] "", 0, 0, 0,
|
||||||
[Cnext] "next", Kright, ' ', '\n',
|
[Cnext] "next", Kright, ' ', '\n',
|
||||||
[Cprev] "prev", Kleft, Kbs, 0,
|
[Cprev] "prev", Kleft, Kbs, 0,
|
||||||
|
[Csnarf] "snarf", 's', 0, 0,
|
||||||
[Czerox] "zerox", 'z', 0, 0,
|
[Czerox] "zerox", 'z', 0, 0,
|
||||||
[Cwrite] "write", 'w', 0, 0,
|
[Cwrite] "write", 'w', 0, 0,
|
||||||
[Cext] "ext", 'x', 0, 0,
|
[Cext] "ext", 'x', 0, 0,
|
||||||
|
@ -124,18 +128,20 @@ Cursor reading = {
|
||||||
0x00, 0x00, 0x01, 0xb6, 0x01, 0xb6, 0x00, 0x00, }
|
0x00, 0x00, 0x01, 0xb6, 0x01, 0xb6, 0x00, 0x00, }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int pagewalk1(Page *p);
|
||||||
void showpage1(Page *);
|
void showpage1(Page *);
|
||||||
void showpage(Page *);
|
void showpage(Page *);
|
||||||
void drawpage(Page *);
|
void drawpage(Page *);
|
||||||
Point pagesize(Page *);
|
Point pagesize(Page *);
|
||||||
|
|
||||||
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;
|
Page *p;
|
||||||
|
|
||||||
p = mallocz(sizeof(*p), 1);
|
p = mallocz(sizeof(*p), 1);
|
||||||
p->label = strdup(label);
|
p->name = strdup(name);
|
||||||
|
p->delim = "!";
|
||||||
p->image = nil;
|
p->image = nil;
|
||||||
p->data = pdata;
|
p->data = pdata;
|
||||||
p->open = popen;
|
p->open = popen;
|
||||||
|
@ -152,8 +158,11 @@ addpage(Page *up, char *label, int (*popen)(Page *), void *pdata, int fd)
|
||||||
}
|
}
|
||||||
qunlock(&pagelock);
|
qunlock(&pagelock);
|
||||||
|
|
||||||
if(up && current == up)
|
if(up && current == up){
|
||||||
|
if(!pagewalk1(p))
|
||||||
|
return p;
|
||||||
showpage1(p);
|
showpage1(p);
|
||||||
|
}
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,19 +274,50 @@ pipeline(int fd, char *fmt, ...)
|
||||||
close(pfd[0]);
|
close(pfd[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
char*
|
static char*
|
||||||
shortname(char *s)
|
shortlabel(char *s)
|
||||||
{
|
{
|
||||||
char *x;
|
enum { NR=60 };
|
||||||
|
static char buf[NR*UTFmax];
|
||||||
|
int i, k, l;
|
||||||
|
Rune r;
|
||||||
|
|
||||||
while(strlen(s) > 20){
|
l = utflen(s);
|
||||||
if((x = strchr(s, '/')) == nil)
|
if(l < NR-2)
|
||||||
break;
|
return s;
|
||||||
if(x[1] == 0)
|
k = i = 0;
|
||||||
break;
|
while(i < NR/2){
|
||||||
s = x+1;
|
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
|
int
|
||||||
|
@ -401,7 +441,7 @@ popenepub(Page *p)
|
||||||
while(n > 0 && s[n-1] == '\n')
|
while(n > 0 && s[n-1] == '\n')
|
||||||
n--;
|
n--;
|
||||||
s[n] = 0;
|
s[n] = 0;
|
||||||
addpage(p, shortname(buf), popenfile, strdup(buf), -1);
|
addpage(p, buf, popenfile, strdup(buf), -1);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -439,7 +479,7 @@ popenpdf(Page *p)
|
||||||
"(/fd/3) (w) file "
|
"(/fd/3) (w) file "
|
||||||
"dup flushfile "
|
"dup flushfile "
|
||||||
"dup (THIS IS NOT AN INFERNO BITMAP\\n) writestring "
|
"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){
|
while((n = read(0, buf, sizeof buf)) > 0){
|
||||||
if(memcmp(buf, "THIS IS NOT AN INFERNO BITMAP\n", 30) == 0)
|
if(memcmp(buf, "THIS IS NOT AN INFERNO BITMAP\n", 30) == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -477,6 +517,7 @@ popengs(Page *p)
|
||||||
pdf = 0;
|
pdf = 0;
|
||||||
ifd = p->fd;
|
ifd = p->fd;
|
||||||
p->fd = -1;
|
p->fd = -1;
|
||||||
|
p->open = nil;
|
||||||
seek(ifd, 0, 0);
|
seek(ifd, 0, 0);
|
||||||
if(read(ifd, buf, 5) != 5)
|
if(read(ifd, buf, 5) != 5)
|
||||||
goto Err0;
|
goto Err0;
|
||||||
|
@ -699,6 +740,7 @@ popenfile(Page *p)
|
||||||
p->ext = nil;
|
p->ext = nil;
|
||||||
file = p->data;
|
file = p->data;
|
||||||
p->data = nil;
|
p->data = nil;
|
||||||
|
p->open = nil;
|
||||||
if(fd < 0){
|
if(fd < 0){
|
||||||
if((fd = open(file, OREAD)) < 0){
|
if((fd = open(file, OREAD)) < 0){
|
||||||
Err0:
|
Err0:
|
||||||
|
@ -724,7 +766,8 @@ popenfile(Page *p)
|
||||||
p->open = popenepub;
|
p->open = popenepub;
|
||||||
return p->open(p);
|
return p->open(p);
|
||||||
}
|
}
|
||||||
|
if(strcmp(pageaddr(p, buf, sizeof(buf)), file) == 0)
|
||||||
|
p->delim = "/";
|
||||||
if((n = dirreadall(fd, &d)) < 0)
|
if((n = dirreadall(fd, &d)) < 0)
|
||||||
goto Err1;
|
goto Err1;
|
||||||
qsort(d, n, sizeof d[0], dircmp);
|
qsort(d, n, sizeof d[0], dircmp);
|
||||||
|
@ -1077,11 +1120,11 @@ drawpage(Page *p)
|
||||||
r = rectaddpt(Rpt(ZP, pagesize(p)), addpt(pos, screen->r.min));
|
r = rectaddpt(Rpt(ZP, pagesize(p)), addpt(pos, screen->r.min));
|
||||||
zoomdraw(screen, r, ZR, paper, i, i->r.min, zoom);
|
zoomdraw(screen, r, ZR, paper, i, i->r.min, zoom);
|
||||||
} else {
|
} 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),
|
r = rectaddpt(r, addpt(subpt(divpt(subpt(screen->r.max, screen->r.min), 2),
|
||||||
divpt(r.max, 2)), screen->r.min));
|
divpt(r.max, 2)), screen->r.min));
|
||||||
draw(screen, r, paper, nil, ZP);
|
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);
|
drawframe(r);
|
||||||
}
|
}
|
||||||
|
@ -1104,24 +1147,81 @@ translate(Page *p, Point d)
|
||||||
drawframe(nr);
|
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 ? name : "",
|
||||||
|
(name && addr) ? "!" : "",
|
||||||
|
addr ? addr : "");
|
||||||
|
pagewalk = buf;
|
||||||
|
|
||||||
|
a = nil;
|
||||||
|
if(root){
|
||||||
|
p = root->down;
|
||||||
|
Loop:
|
||||||
|
for(; p; p = p->next)
|
||||||
|
if(pagewalk1(p)){
|
||||||
|
a = p;
|
||||||
|
p = p->down;
|
||||||
|
goto Loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
Page*
|
Page*
|
||||||
findpage(char *name)
|
findpage(char *name)
|
||||||
{
|
{
|
||||||
|
static char buf[NPATH], *f[32];
|
||||||
Page *p;
|
Page *p;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
|
if(name == nil)
|
||||||
|
return nil;
|
||||||
|
|
||||||
n = strlen(name);
|
n = strlen(name);
|
||||||
/* look in current document first */
|
/* look in current document */
|
||||||
if(current && current->up){
|
if(current && current->up){
|
||||||
for(p = current->up->down; p; p = p->next)
|
for(p = current->up->down; p; p = p->next)
|
||||||
if(cistrncmp(p->label, name, n) == 0)
|
if(cistrncmp(p->name, name, n) == 0)
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
/* look everywhere */
|
/* look everywhere */
|
||||||
for(p = root->down; p; p = nextpage(p))
|
if(root){
|
||||||
if(cistrncmp(p->label, name, n) == 0)
|
for(p = root->down; p; p = nextpage(p))
|
||||||
return p;
|
if(cistrncmp(p->name, name, n) == 0)
|
||||||
return nil;
|
return p;
|
||||||
|
}
|
||||||
|
/* try bookmark */
|
||||||
|
return trywalk(name, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
Page*
|
Page*
|
||||||
|
@ -1149,8 +1249,9 @@ char*
|
||||||
pagemenugen(int i)
|
pagemenugen(int i)
|
||||||
{
|
{
|
||||||
Page *p;
|
Page *p;
|
||||||
|
|
||||||
if(p = pageat(i))
|
if(p = pageat(i))
|
||||||
return p->label;
|
return shortlabel(p->name);
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1274,7 +1375,7 @@ showext(Page *p)
|
||||||
|
|
||||||
if(p->ext == nil)
|
if(p->ext == nil)
|
||||||
return;
|
return;
|
||||||
snprint(label, sizeof(label), "%s %s", p->ext, p->label);
|
snprint(label, sizeof(label), "%s %s", p->ext, p->name);
|
||||||
ps = Pt(0, 0);
|
ps = Pt(0, 0);
|
||||||
if(p->image)
|
if(p->image)
|
||||||
ps = addpt(subpt(p->image->r.max, p->image->r.min), Pt(24, 24));
|
ps = addpt(subpt(p->image->r.max, p->image->r.min), Pt(24, 24));
|
||||||
|
@ -1309,6 +1410,19 @@ showext(Page *p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
snarfaddr(Page *p)
|
||||||
|
{
|
||||||
|
char buf[NPATH], *s;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
s = pageaddr(p, buf, sizeof(buf));
|
||||||
|
if((fd = open("/dev/snarf", OWRITE)) >= 0){
|
||||||
|
write(fd, s, strlen(s));
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
eresized(int new)
|
eresized(int new)
|
||||||
{
|
{
|
||||||
|
@ -1344,7 +1458,7 @@ void drawerr(Display *, char *msg)
|
||||||
void
|
void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
fprint(2, "usage: %s [ -iRw ] [ -m mb ] [ -p ppi ] [ file ... ]\n", argv0);
|
fprint(2, "usage: %s [ -iRw ] [ -m mb ] [ -p ppi ] [ -j addr ] [ file ... ]\n", argv0);
|
||||||
exits("usage");
|
exits("usage");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1411,11 +1525,11 @@ docmd(int i, Mouse *m)
|
||||||
if(current->image){
|
if(current->image){
|
||||||
s = nil;
|
s = nil;
|
||||||
if(current->up && current->up != root)
|
if(current->up && current->up != root)
|
||||||
s = current->up->label;
|
s = current->up->name;
|
||||||
snprint(buf, sizeof(buf), "%s%s%s.bit",
|
snprint(buf, sizeof(buf), "%s%s%s.bit",
|
||||||
s ? s : "",
|
s ? s : "",
|
||||||
s ? "." : "",
|
s ? "." : "",
|
||||||
current->label);
|
current->name);
|
||||||
if(eenter("Write", buf, sizeof(buf), m) > 0){
|
if(eenter("Write", buf, sizeof(buf), m) > 0){
|
||||||
if((fd = create(buf, OWRITE, 0666)) < 0){
|
if((fd = create(buf, OWRITE, 0666)) < 0){
|
||||||
errstr(buf, sizeof(buf));
|
errstr(buf, sizeof(buf));
|
||||||
|
@ -1436,6 +1550,9 @@ docmd(int i, Mouse *m)
|
||||||
showext(current);
|
showext(current);
|
||||||
qunlock(current);
|
qunlock(current);
|
||||||
break;
|
break;
|
||||||
|
case Csnarf:
|
||||||
|
snarfaddr(current);
|
||||||
|
break;
|
||||||
case Cnext:
|
case Cnext:
|
||||||
shownext();
|
shownext();
|
||||||
break;
|
break;
|
||||||
|
@ -1462,6 +1579,8 @@ main(int argc, char *argv[])
|
||||||
char *s;
|
char *s;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
quotefmtinstall();
|
||||||
|
|
||||||
ARGBEGIN {
|
ARGBEGIN {
|
||||||
case 'a':
|
case 'a':
|
||||||
case 'v':
|
case 'v':
|
||||||
|
@ -1478,6 +1597,9 @@ main(int argc, char *argv[])
|
||||||
case 'i':
|
case 'i':
|
||||||
imode = 1;
|
imode = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'j':
|
||||||
|
trywalk(EARGF(usage()), nil);
|
||||||
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
imemlimit = atol(EARGF(usage()))*MiB;
|
imemlimit = atol(EARGF(usage()))*MiB;
|
||||||
break;
|
break;
|
||||||
|
@ -1523,10 +1645,11 @@ main(int argc, char *argv[])
|
||||||
lru.lprev = &lru;
|
lru.lprev = &lru;
|
||||||
lru.lnext = &lru;
|
lru.lnext = &lru;
|
||||||
current = root = addpage(nil, "", nil, nil, -1);
|
current = root = addpage(nil, "", nil, nil, -1);
|
||||||
|
root->delim = "";
|
||||||
if(*argv == nil && !imode)
|
if(*argv == nil && !imode)
|
||||||
addpage(root, "stdin", popenfile, strdup("/fd/0"), -1);
|
addpage(root, "stdin", popenfile, strdup("/fd/0"), -1);
|
||||||
for(; *argv; argv++)
|
for(; *argv; argv++)
|
||||||
addpage(root, shortname(*argv), popenfile, strdup(*argv), -1);
|
addpage(root, *argv, popenfile, strdup(*argv), -1);
|
||||||
|
|
||||||
for(;;){
|
for(;;){
|
||||||
drawlock(0);
|
drawlock(0);
|
||||||
|
@ -1615,6 +1738,7 @@ main(int argc, char *argv[])
|
||||||
case Eplumb:
|
case Eplumb:
|
||||||
pm = e.v;
|
pm = e.v;
|
||||||
if(pm && pm->ndata > 0){
|
if(pm && pm->ndata > 0){
|
||||||
|
Page *j;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
fd = -1;
|
fd = -1;
|
||||||
|
@ -1639,7 +1763,12 @@ main(int argc, char *argv[])
|
||||||
sprint(s, "%s/%s", pm->wdir, pm->data);
|
sprint(s, "%s/%s", pm->wdir, pm->data);
|
||||||
cleanname(s);
|
cleanname(s);
|
||||||
}
|
}
|
||||||
showpage(addpage(root, shortname(s), popenfile, s, fd));
|
j = trywalk(s, plumblookup(pm->attr, "addr"));
|
||||||
|
if(j == nil){
|
||||||
|
current = root;
|
||||||
|
j = addpage(root, s, popenfile, s, fd);
|
||||||
|
}
|
||||||
|
showpage(j);
|
||||||
}
|
}
|
||||||
Plumbfree:
|
Plumbfree:
|
||||||
plumbfree(pm);
|
plumbfree(pm);
|
||||||
|
|
Loading…
Reference in a new issue