shithub: riscv

Download patch

ref: 5fbc2ea9cebe4c4b1ab944a6d17efc73e0a8982c
parent: 190653f0490801a26123186b2fb4e2ee6f02fab7
parent: 5dae7fcc68a3cfca3f2bef5a07702659a0b0eb62
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Dec 21 13:06:24 EST 2013

merge

--- a/sys/lib/plumb/basic
+++ b/sys/lib/plumb/basic
@@ -33,6 +33,14 @@
 plumb to sendmail
 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
 type is text
 data matches '[a-zA-Z¡-￿0-9_\-./]+'
@@ -40,6 +48,15 @@
 arg isfile	$0
 plumb to image
 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
 # the port is here for reference but is unused
--- a/sys/man/1/page
+++ b/sys/man/1/page
@@ -9,12 +9,13 @@
 .B page
 [
 .B -abirPRvVw
-]
-[
+] [
 .B -p
 .I ppi
-]
-[
+] [
+.B -j
+.I addr
+] [
 .IR file ...
 ]
 .SH DESCRIPTION
@@ -96,6 +97,12 @@
 from standard input but rather to listen
 for ones to load from the plumbing channel.
 .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.
 .PP
 Button 2 raises a menu of operations on the current image or the
@@ -126,6 +133,9 @@
 .B Prev
 Displays the previous page.
 .TP
+.B Snarf
+Writes the current page address to the snarf buffer.
+.TP
 .B Zerox
 Displays the current image in a new page window. 
 Useful for selecting important pages from large documents.
@@ -177,6 +187,10 @@
 .L
 page /usr/inferno/icons/*.bit
 Browse the Inferno bitmap library.
+.TP
+.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
--- a/sys/src/cmd/page.c
+++ b/sys/src/cmd/page.c
@@ -8,7 +8,8 @@
 
 typedef struct Page Page;
 struct Page {
-	char	*label;
+	char	*name;
+	char	*delim;
 
 	QLock;
 	char	*ext;
@@ -38,6 +39,7 @@
 Page lru;
 QLock pagelock;
 int nullfd;
+char *pagewalk = nil;
 
 enum {
 	MiB	= 1024*1024,
@@ -67,6 +69,7 @@
 	Cdummy1,
 	Cnext,
 	Cprev,
+	Csnarf,
 	Czerox,
 	Cwrite,
 	Cext,
@@ -90,6 +93,7 @@
 	[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,
@@ -124,6 +128,7 @@
 	 0x00, 0x00, 0x01, 0xb6, 0x01, 0xb6, 0x00, 0x00, }
 };
 
+int pagewalk1(Page *p);
 void showpage1(Page *);
 void showpage(Page *);
 void drawpage(Page *);
@@ -130,12 +135,13 @@
 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->name = strdup(name);
+	p->delim = "!";
  	p->image = nil;
 	p->data = pdata;
 	p->open = popen;
@@ -152,8 +158,11 @@
 	}
 	qunlock(&pagelock);
 
-	if(up && current == up)
+	if(up && current == up){
+		if(!pagewalk1(p))
+			return p;
 		showpage1(p);
+	}
 	return p;
 }
 
@@ -265,21 +274,52 @@
 	close(pfd[0]);
 }
 
-char*
-shortname(char *s)
+static char*
+shortlabel(char *s)
 {
-	char *x;
+	enum { NR=60 };
+	static char buf[NR*UTFmax];
+	int i, k, l;
+	Rune r;
 
-	while(strlen(s) > 20){
-		if((x = strchr(s, '/')) == nil)
-			break;
-		if(x[1] == 0)
-			break;
-		s = x+1;
+	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
 popenfile(Page*);
 
@@ -401,7 +441,7 @@
 		while(n > 0 && s[n-1] == '\n')
 			n--;
 		s[n] = 0;
-		addpage(p, shortname(buf), popenfile, strdup(buf), -1);
+		addpage(p, buf, popenfile, strdup(buf), -1);
 	}
 	close(fd);
 	return -1;
@@ -439,7 +479,7 @@
 			"(/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;
@@ -477,6 +517,7 @@
 	pdf = 0;
 	ifd = p->fd;
 	p->fd = -1;
+	p->open = nil;
 	seek(ifd, 0, 0);
 	if(read(ifd, buf, 5) != 5)
 		goto Err0;
@@ -699,6 +740,7 @@
 	p->ext = nil;
 	file = p->data;
 	p->data = nil;
+	p->open = nil;
 	if(fd < 0){
 		if((fd = open(file, OREAD)) < 0){
 		Err0:
@@ -724,7 +766,8 @@
 			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);
@@ -1077,11 +1120,11 @@
 		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);
 }
@@ -1104,24 +1147,81 @@
 	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*
 findpage(char *name)
 {
+	static char buf[NPATH], *f[32];
 	Page *p;
 	int n;
 
+	if(name == nil)
+		return nil;
+
 	n = strlen(name);
-	/* look in current document first */
+	/* look in current document */
 	if(current && current->up){
 		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;
 	}
 	/* look everywhere */
-	for(p = root->down; p; p = nextpage(p))
-		if(cistrncmp(p->label, name, n) == 0)
-			return p;
-	return nil;
+	if(root){
+		for(p = root->down; p; p = nextpage(p))
+			if(cistrncmp(p->name, name, n) == 0)
+				return p;
+	}
+	/* try bookmark */
+	return trywalk(name, nil);
 }
 
 Page*
@@ -1149,8 +1249,9 @@
 pagemenugen(int i)
 {
 	Page *p;
+
 	if(p = pageat(i))
-		return p->label;
+		return shortlabel(p->name);
 	return nil;
 }
 
@@ -1274,7 +1375,7 @@
 
 	if(p->ext == nil)
 		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);
 	if(p->image)
 		ps = addpt(subpt(p->image->r.max, p->image->r.min), Pt(24, 24));
@@ -1310,6 +1411,19 @@
 
 
 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
 eresized(int new)
 {
 	Page *p;
@@ -1344,7 +1458,7 @@
 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");
 }
 
@@ -1411,11 +1525,11 @@
 		if(current->image){
 			s = nil;
 			if(current->up && current->up != root)
-				s = current->up->label;
+				s = current->up->name;
 			snprint(buf, sizeof(buf), "%s%s%s.bit",
 				s ? s : "",
 				s ? "." : "",
-				current->label);
+				current->name);
 			if(eenter("Write", buf, sizeof(buf), m) > 0){
 				if((fd = create(buf, OWRITE, 0666)) < 0){
 					errstr(buf, sizeof(buf));
@@ -1436,6 +1550,9 @@
 		showext(current);
 		qunlock(current);
 		break;
+	case Csnarf:
+		snarfaddr(current);
+		break;
 	case Cnext:
 		shownext();
 		break;
@@ -1462,6 +1579,8 @@
 	char *s;
 	int i;
 
+	quotefmtinstall();
+
 	ARGBEGIN {
 	case 'a':
 	case 'v':
@@ -1478,6 +1597,9 @@
 	case 'i':
 		imode = 1;
 		break;
+	case 'j':
+		trywalk(EARGF(usage()), nil);
+		break;
 	case 'm':
 		imemlimit = atol(EARGF(usage()))*MiB;
 		break;
@@ -1523,10 +1645,11 @@
 	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);
 
 	for(;;){
 		drawlock(0);
@@ -1615,6 +1738,7 @@
 		case Eplumb:
 			pm = e.v;
 			if(pm && pm->ndata > 0){
+				Page *j;
 				int fd;
 
 				fd = -1;
@@ -1639,7 +1763,12 @@
 					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;
+					j = addpage(root, s, popenfile, s, fd);
+				}
+				showpage(j);
 			}
 		Plumbfree:
 			plumbfree(pm);
--