This commit is contained in:
cinap_lenrek 2013-12-21 18:06:24 +01:00
commit 5fbc2ea9ce
3 changed files with 196 additions and 36 deletions

View file

@ -33,6 +33,14 @@ data matches '[a-zA-Z0-9_+.\-]+@[a-zA-Z0-9_+.\-]*'
plumb to sendmail plumb to sendmail
plumb start window rc -c '''echo % mail '''$0'; mail '$0 plumb start window rc -c '''echo % mail '''$0'; mail '$0
# audio
type is text
data matches '[a-zA-Z¡-￿0-9_\-./]+'
data matches '([a-zA-Z¡-￿0-9_\-./]+)\.(mp3|ogg|flac|m3u|pls)'
arg isfile $0
plumb to audio
plumb start window play $0
# image files go to page # image files go to page
type is text type is text
data matches '[a-zA-Z¡-￿0-9_\-./]+' data matches '[a-zA-Z¡-￿0-9_\-./]+'
@ -41,6 +49,15 @@ arg isfile $0
plumb to image plumb to image
plumb client page -wi plumb client page -wi
# page bookmarks
type is text
data matches '(([a-zA-Z¡-￿0-9_\-./]+)\.(ps|PS|eps|EPS|pdf|PDF|dvi|DVI|doc|DOC|epub|EPUB|cb[tz]|CB[TZ]))!(.+)'
arg isfile $1
data set $file
attr add addr=$4
plumb to image
plumb start page -wij $0 $file
# postscript/pdf/dvi/doc go to page but not over the a plumb port # postscript/pdf/dvi/doc go to page but not over the a plumb port
# the port is here for reference but is unused # the port is here for reference but is unused
type is text type is text

View file

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

View file

@ -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;
if(x[1] == 0)
break;
s = x+1;
}
return s; return s;
k = i = 0;
while(i < NR/2){
k += chartorune(&r, s+k);
i++;
}
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 */
if(root){
for(p = root->down; p; p = nextpage(p)) for(p = root->down; p; p = nextpage(p))
if(cistrncmp(p->label, name, n) == 0) if(cistrncmp(p->name, name, n) == 0)
return p; return p;
return nil; }
/* 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);