shithub: patch

ref: 97b0f025ed8634b2c7c9a346330226aea0788f82
dir: /vdir-tweaks/

View raw version
diff 8ffa802e29ca42eb54cc4b10f8c756ba6275e801 uncommitted
--- a/./alert.c
+++ b/./alert.c
@@ -19,11 +19,11 @@
 alert(const char *title, const char *message, const char *err, Mousectl *mctl, Keyboardctl *kctl)
 {
 	Alt alts[3];
-	Rectangle r, sc;
+	Rectangle r;
 	Point o, p;
-	Image *b, *save, *bg, *fg;
+	Image *bg, *fg;
 	Font *tf, *mf;
-	int done, h, w, tw, mw, ew;
+	int i, h, w, tw, mw, ew;
 	Mouse m;
 	Rune k;
 
@@ -46,8 +46,6 @@
 	mf = openfont(display, Messagefont);
 	if(mf==nil)
 		sysfatal("openfont: %r");
-	done = 0;
-	save = nil;
 	h = Padding+tf->height+mf->height+Padding;
 	if(err != nil)
 		h += mf->height;
@@ -55,56 +53,25 @@
 	mw = stringwidth(mf, message);
 	ew = err != nil ? stringwidth(mf, err) : 0;
 	w = Padding+max(tw, max(mw, ew))+Padding;
-	b = screen;
-	sc = b->clipr;
-	replclipr(b, 0, b->r);
-	while(!done){
-		o = addpt(screen->r.min, Pt((Dx(screen->r)-w)/2, (Dy(screen->r)-h)/2));
-		r = Rect(o.x, o.y, o.x+w, o.y+h);
-		if(save==nil){
-			save = allocimage(display, r, b->chan, 0, DNofill);
-			if(save==nil)
-				break;
-			draw(save, r, b, nil, r.min);
-		}
-		draw(b, r, bg, nil, ZP);
-		border(b, r, 2, fg, ZP);
-		p = addpt(o, Pt(Padding, Padding));
-		string(b, p, fg, ZP, tf, title);
-		p.y += tf->height;
-		string(b, p, fg, ZP, mf, message);
-		if(err != nil){
-			p.x = o.x + Padding;
-			p.y += mf->height;
-			string(b, p, fg, ZP, mf, err);
-		}
-		flushimage(display, 1);
-		if(b!=screen || !eqrect(screen->clipr, sc)){
-			freeimage(save);
-			save = nil;
-		}
-		b = screen;
-		sc = b->clipr;
-		replclipr(b, 0, b->r);
-		switch(alt(alts)){
-		default:
-			continue;
+	o = addpt(screen->r.min, Pt((Dx(screen->r)-w)/2, (Dy(screen->r)-h)/2));
+	r = Rect(o.x, o.y, o.x+w, o.y+h);
+	draw(screen, r, bg, nil, ZP);
+	border(screen, r, 2, fg, ZP);
+	p = addpt(o, Pt(Padding, Padding));
+	string(screen, p, fg, ZP, tf, title);
+	p.y += tf->height;
+	string(screen, p, fg, ZP, mf, message);
+	if(err != nil){
+		p.x = o.x + Padding;
+		p.y += mf->height;
+		string(screen, p, fg, ZP, mf, err);
+	}
+	flushimage(display, 1);
+	for(;;){
+		i = alt(alts);
+		if(i == 1 || i == 0 && m.buttons != 0)
 			break;
-		case 1:
-			done = (k=='\n' || k==Kesc);
-			break;
-		case 0:
-			done = m.buttons&1 && ptinrect(m.xy, r);
-			break;
-		}
-		if(save){
-			draw(b, save->r, save, nil, save->r.min);
-			freeimage(save);
-			save = nil;
-		}
-			
 	}
-	replclipr(b, 0, sc);
 	freeimage(bg);
 	freeimage(fg);
 	freefont(tf);
--- a/./icons.h
+++ b/./icons.h
@@ -420,3 +420,181 @@
 	0x46, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,
 	
 };
+
+uchar backdata[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00
+};
+
+uchar refdata[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00
+};
--- a/./theme.c
+++ b/./theme.c
@@ -21,64 +21,57 @@
 	return i;
 }
 
-Theme*
-loadtheme(void)
+void
+loadtheme(Theme *theme)
 {
-	Theme *theme;
 	Biobuf *bp;
 	char *s;
 
 	if(access("/dev/theme", AREAD) < 0)
-		return 0;
+		return;
 	bp = Bopen("/dev/theme", OREAD);
 	if(bp == nil)
-		return 0;
-	theme = malloc(sizeof *theme);
-	if(theme == nil){
-		Bterm(bp);
-		return nil;
-	}
+		return;
 	for(;;){
 		s = Brdstr(bp, '\n', 1);
 		if(s == nil)
 			break;
 		if(strncmp(s, "back", 4) == 0)
-			theme->back = ereadcol(s+5);
+			theme->back = strtoul(s+5, nil, 16);
 		else if(strncmp(s, "high", 4) == 0)
-			theme->high = ereadcol(s+5);
+			theme->high = strtoul(s+5, nil, 16);
 		else if(strncmp(s, "border", 6) == 0)
-			theme->border = ereadcol(s+7);
+			theme->border = strtoul(s+7, nil, 16);
 		else if(strncmp(s, "text", 4) == 0)
-			theme->text = ereadcol(s+5);
+			theme->text = strtoul(s+5, nil, 16);
 		else if(strncmp(s, "htext", 5) == 0)
-			theme->htext = ereadcol(s+6);
+			theme->htext = strtoul(s+6, nil, 16);
 		else if(strncmp(s, "title", 5) == 0)
-			theme->title = ereadcol(s+6);
+			theme->title = strtoul(s+6, nil, 16);
 		else if(strncmp(s, "ltitle", 6) == 0)
-			theme->ltitle = ereadcol(s+7);
+			theme->ltitle = strtoul(s+7, nil, 16);
 		else if(strncmp(s, "hold", 4) == 0)
-			theme->hold = ereadcol(s+5);
+			theme->hold = strtoul(s+5, nil, 16);
 		else if(strncmp(s, "lhold", 5) == 0)
-			theme->lhold = ereadcol(s+6);
+			theme->lhold = strtoul(s+6, nil, 16);
 		else if(strncmp(s, "palehold", 8) == 0)
-			theme->palehold = ereadcol(s+9);
+			theme->palehold = strtoul(s+9, nil, 16);
 		else if(strncmp(s, "paletext", 8) == 0)
-			theme->paletext = ereadcol(s+9);
+			theme->paletext = strtoul(s+9, nil, 16);
 		else if(strncmp(s, "size", 4) == 0)
-			theme->size = ereadcol(s+5);
+			theme->size = strtoul(s+5, nil, 16);
 		else if(strncmp(s, "menuback", 8) == 0)
-			theme->menuback = ereadcol(s+9);
+			theme->menuback = strtoul(s+9, nil, 16);
 		else if(strncmp(s, "menuhigh", 8) == 0)
-			theme->menuhigh = ereadcol(s+9);
+			theme->menuhigh = strtoul(s+9, nil, 16);
 		else if(strncmp(s, "menubord", 8) == 0)
-			theme->menubord = ereadcol(s+9);
+			theme->menubord = strtoul(s+9, nil, 16);
 		else if(strncmp(s, "menutext", 8) == 0)
-			theme->menutext = ereadcol(s+9);
+			theme->menutext = strtoul(s+9, nil, 16);
 		else if(strncmp(s, "menuhtext", 5) == 0)
-			theme->menuhtext = ereadcol(s+6);
+			theme->menuhtext = strtoul(s+6, nil, 16);
 		free(s);
 	}
 	Bterm(bp);
-	return theme;
 }
 
--- a/./theme.h
+++ b/./theme.h
@@ -2,24 +2,25 @@
 
 struct Theme
 {
-	Image *back;
-	Image *high;
-	Image *border;
-	Image *text;
-	Image *htext;
-	Image *title;
-	Image *ltitle;
-	Image *hold;
-	Image *lhold;
-	Image *palehold;
-	Image *paletext;
-	Image *size;
-	Image *menubar;
-	Image *menuback;
-	Image *menuhigh;
-	Image *menubord;
-	Image *menutext;
-	Image *menuhtext;
+	u32int back;
+	u32int high;
+	u32int border;
+	u32int text;
+	u32int htext;
+	u32int title;
+	u32int ltitle;
+	u32int hold;
+	u32int lhold;
+	u32int palehold;
+	u32int paletext;
+	u32int size;
+	u32int menubar;
+	u32int menuback;
+	u32int menuhigh;
+	u32int menubord;
+	u32int menutext;
+	u32int menuhtext;
 };
 
-Theme* loadtheme(void);
+void	loadtheme(Theme*);
+Image*	ereadcol(char*);
--- a/./vdir.c
+++ b/./vdir.c
@@ -20,6 +20,13 @@
 	Slowscroll = 10,
 };
 
+enum{
+	Nback = 64,
+};
+char *backlist[Nback];
+int backoff[Nback];
+int backp = -1;
+
 enum
 {
 	Emouse,
@@ -47,6 +54,8 @@
 Rectangle homer;
 Rectangle upr;
 Rectangle cdr;
+Rectangle refr;
+Rectangle backr;
 Rectangle newdirr;
 Rectangle newfiler;
 Rectangle viewr;
@@ -60,6 +69,8 @@
 Image *iup;
 Image *inewfile;
 Image *inewfolder;
+Image *iref;
+Image *iback;
 Image *toolbg;
 Image *toolfg;
 Image *viewbg;
@@ -68,6 +79,7 @@
 Image *selfg;
 Image *scrollbg;
 Image *scrollfg;
+Image *fb;
 int sizew;
 int lineh;
 int nlines;
@@ -121,8 +133,10 @@
 	return 1;
 }
 
+int	scrollclamp(int);
+
 void
-loaddirs(void)
+loaddirs(int fixoff)
 {
 	int fd, i, m;
 
@@ -134,13 +148,11 @@
 	if(dirs!=nil)
 		free(dirs);
 	ndirs = dirreadall(fd, &dirs);
-	if(ndirs > 0)
-		qsort(dirs, ndirs, sizeof *dirs, (int(*)(void*,void*))dircmp);
-	else{
-		ndirs = 0;
-		showerrstr("Unable to read directory");
-	}
-	offset = 0;
+	qsort(dirs, ndirs, sizeof *dirs, (int(*)(void*,void*))dircmp);
+	if(!fixoff)
+		scrollclamp(offset);
+	else
+		offset = 0;
 	close(fd);
 	m = 1;
 	for(i=0; i < ndirs; i++){
@@ -147,14 +159,47 @@
 		if(dirs[i].length>m)
 			m=dirs[i].length;
 	}
-	sizew = m == 0 ? 3 : 1+1+log(m)/log(10);
+	sizew = 1+1+log(m)/log(10);
 }
 
 void
+pushback(void)
+{
+	if(strlen(path) < 1)
+		return;
+	if(backp == Nback-1)
+		memmove(backlist, backlist+1, (Nback-1) * sizeof *backlist);
+	else
+		backp++;
+	if((backlist[backp] = strdup(path)) == nil)
+		sysfatal("strdup: %r");
+	backoff[backp] = offset;
+}
+
+int
+back(void)
+{
+	char *p;
+
+	if(backp < 0)
+		return 0;
+	offset = backoff[backp];
+	backoff[backp] = 0;
+	p = backlist[backp];
+	backlist[backp] = nil;
+	backp--;
+	strecpy(path, path+sizeof path, p);
+	free(p);
+	loaddirs(0);
+	return 1;
+}
+
+void
 up(void)
 {
+	pushback();
 	snprint(path, sizeof path, abspath(path, ".."));
-	loaddirs();
+	loaddirs(1);
 }
 
 void
@@ -162,6 +207,7 @@
 {
 	char newpath[256] = {0};
 
+	pushback();
 	if(dir == nil)
 		snprint(newpath, sizeof path, home);
 	else if(dir[0] == '/')
@@ -172,7 +218,7 @@
 		showerrstr("Directory does not exist");
 	else
 		snprint(path, sizeof path, abspath(path, newpath));
-	loaddirs();
+	loaddirs(1);
 }
 
 void
@@ -192,7 +238,7 @@
 		goto cleanup;
 	}
 	close(fd);
-	loaddirs();
+	loaddirs(0);
 cleanup:
 	free(p);
 }
@@ -214,7 +260,7 @@
 		goto cleanup;
 	}
 	close(fd);
-	loaddirs();
+	loaddirs(0);
 cleanup:
 	free(p);
 }
@@ -262,7 +308,7 @@
 	if(doexec(cmd) < 0)
 		showerrstr("Cannot remove file/directory");
 	else
-		loaddirs();
+		loaddirs(0);
 }
 
 void
@@ -274,11 +320,11 @@
 	if(doexec(cmd) < 0)
 		showerrstr("Cannot rename file/directory");
 	else
-		loaddirs();
+		loaddirs(0);
 }
 
 int
-plumbfile(char *path, char *name)
+plumbfile(char *path, char *name, int isdir)
 {
 	char *f;
 	int e;
@@ -285,11 +331,14 @@
 
 	f = smprint("%s/%s", path, name);
 	e = access(f, 0)==0;
-	if(e)
-		plumbsendtext(plumbfd, "vdir", nil, path, name);
-	else{
+	if(e){
+	    if(isdir)
+			plumbsendtext(plumbfd, "vdir", nil, nil, f);
+		else
+			plumbsendtext(plumbfd, "vdir", nil, path, name);
+	}else{
 		alert("Error", "File does not exist anymore", nil, mctl, kctl);
-		loaddirs();
+		loaddirs(0);
 		redraw();
 	}
 	free(f);
@@ -299,28 +348,21 @@
 void
 initcolors(void)
 {
-	Theme *theme;
+	Theme theme;
 
-	theme = loadtheme();
-	if(theme == nil){
-		toolbg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xEFEFEFFF);
-		toolfg = display->black;
-		viewbg = display->white;
-		viewfg = display->black;
-		selbg  = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xEFEFEFFF);
-		selfg  = display->black;
-		scrollbg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x999999FF);
-		scrollfg = display->white;
-	}else{
-		toolbg = theme->back;
-		toolfg = theme->text;
-		viewbg = theme->back;
-		viewfg = theme->text;
-		selbg  = theme->border;
-		selfg  = theme->text;
-		scrollbg = theme->border;
-		scrollfg = theme->back;
-	}
+	memset(&theme, 0, sizeof theme);
+	theme.back = 0xEFEFEF;
+	theme.text = 0;
+	theme.border = 0x999999;
+	loadtheme(&theme);
+	toolbg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, theme.back << 8 | 0xff);
+	toolfg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, theme.text << 8 | 0xff);
+	viewbg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, theme.back << 8 | 0xff);
+	viewfg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, theme.text << 8 | 0xff);
+	selbg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, theme.border << 8 | 0xff);
+	selfg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, theme.text << 8 | 0xff);
+	scrollbg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, theme.border << 8 | 0xff);
+	scrollfg = allocimage(display, Rect(0,0,1,1), screen->chan, 1, theme.back << 8 | 0xff);
 }
 
 Image*
@@ -351,6 +393,8 @@
 	iup    = loadicon(big, updata, sizeof updata);
 	inewfile = loadicon(big, newfiledata, sizeof newfiledata);
 	inewfolder = loadicon(big, newfolderdata, sizeof newfolderdata);
+	iref    = loadicon(big, refdata, sizeof refdata);
+	iback    = loadicon(big, backdata, sizeof backdata);
 }
 
 char*
@@ -371,7 +415,7 @@
 
 	p->x += Toolpadding;
 	r = Rect(p->x, p->y, p->x+16, p->y+16);
-	draw(screen, r, c, i, ZP);
+	draw(fb, r, c, i, ZP);
 	p->x += 16+Toolpadding;
 	return r;
 }
@@ -384,12 +428,12 @@
 
 	s = t;
 	if(*s && (p.x+stringwidth(font, s)) > n){
-		p = string(screen, p, i, ZP, font, ellipsis);
+		p = string(fb, p, i, ZP, font, ellipsis);
 		while (*s && (p.x+stringwidth(font, s)) > n) s++;
 	}
 	for( ; *s; s++){
 		s += chartorune(&rn, s) - 1;
-		p = runestringn(screen, p, i, ZP, font, &rn, 1);
+		p = runestringn(fb, p, i, ZP, font, &rn, 1);
 	}
 	return p;
 }
@@ -412,7 +456,7 @@
 	p = addpt(viewr.min, Pt(Toolpadding, Toolpadding));
 	p.y += n*lineh;
 	r = Rpt(p, addpt(p, Pt(Dx(viewr)-2*Toolpadding, lineh)));
-	draw(screen, r, bg, nil, ZP);
+	draw(fb, r, bg, nil, ZP);
 	t = mdate(d);
 	snprint(buf, sizeof buf, "%*lld  %s", sizew, d.length, t);
 	free(t);
@@ -419,12 +463,12 @@
 	img = (d.qid.type&QTDIR) ? folder : file;
 	p.y -= Padding;
 	dy = (lineh-12)/2;
-	draw(screen, Rect(p.x, p.y+dy, p.x+12, p.y+dy+12), fg, img, ZP);
+	draw(fb, Rect(p.x, p.y+dy, p.x+12, p.y+dy+12), fg, img, ZP);
 	p.x += 12+4+Padding;
 	p.y += Padding;
 	p = drawtext(p, fg, d.name, viewr.max.x - stringwidth(font, buf) - 2*Padding - Toolpadding);
 	p.x = viewr.max.x - stringwidth(font, buf) - 2*Padding - Toolpadding;
-	string(screen, p, fg, ZP, font, buf);
+	string(fb, p, fg, ZP, font, buf);
 }
 
 void
@@ -445,22 +489,25 @@
 	Point p;
 	int i, h, y;
 
-	draw(screen, screen->r, viewbg, nil, ZP);
-	p = addpt(screen->r.min, Pt(0, Toolpadding));
-	draw(screen, toolr, toolbg, nil, ZP);
-	line(screen, Pt(toolr.min.x, toolr.max.y), toolr.max, 0, 0, 0, toolfg, ZP);
+	draw(fb, fb->r, viewbg, nil, ZP);
+	p = Pt(0, Toolpadding);
+	draw(fb, toolr, toolbg, nil, ZP);
+	line(fb, Pt(toolr.min.x, toolr.max.y), toolr.max, 0, 0, 0, toolfg, ZP);
 	homer = drawbutton(&p, toolfg, ihome);
 	cdr = drawbutton(&p, toolfg, icd);
+	backr = drawbutton(&p, toolfg, iback);
 	upr = drawbutton(&p, toolfg, iup);
+	refr = drawbutton(&p, toolfg, iref);
+
 	p.x += Toolpadding;
 	p.y = toolr.min.y + (Toolpadding+16+Toolpadding-font->height)/2;
 	pathr = Rect(p.x, p.y, p.x + stringwidth(font, path), p.y + font->height);
-	p = drawtext(p, toolfg, path, screen->r.max.x - 2*(Toolpadding+16+Toolpadding));
-	p.x = screen->r.max.x - 2*(Toolpadding+16+Toolpadding);
-	p.y = screen->r.min.y + Toolpadding;
+	p = drawtext(p, toolfg, path, fb->r.max.x - 2*(Toolpadding+16+Toolpadding));
+	p.x = fb->r.max.x - 2*(Toolpadding+16+Toolpadding);
+	p.y = fb->r.min.y + Toolpadding;
 	newdirr = drawbutton(&p, toolfg, inewfolder);
 	newfiler = drawbutton(&p, toolfg, inewfile);
-	draw(screen, scrollr, scrollbg, nil, ZP);
+	draw(fb, scrollr, scrollbg, nil, ZP);
 	if(ndirs>0){
 		h = ((double)nlines/ndirs)*Dy(scrollr);
 		y = ((double)offset/ndirs)*Dy(scrollr);
@@ -467,10 +514,11 @@
 		scrposr = Rect(scrollr.min.x, scrollr.min.y+y, scrollr.max.x-1, scrollr.min.y+y+h);
 	}else
 		scrposr = Rect(scrollr.min.x, scrollr.min.y, scrollr.max.x-1, scrollr.max.y);
-	draw(screen, scrposr, scrollfg, nil, ZP);
+	draw(fb, scrposr, scrollfg, nil, ZP);
 	for(i = 0; i<nlines && offset+i<ndirs; i++){
 		drawdir(i, 0);
 	}
+	draw(screen, screen->r, fb, nil, ZP);
 	flushimage(display, 1);
 }
 
@@ -511,18 +559,42 @@
 }
 
 void
+scroll(Mouse m)
+{
+	int dy;
+
+	if(m.buttons & 1){
+		dy = 1+nlines*((double)(m.xy.y - scrollr.min.y)/Dy(scrollr));
+		scrollup(dy);
+	}else if(m.buttons & 2){
+		if(nlines<ndirs){
+			offset = scrollclamp((m.xy.y-Dy(scrposr)/2 - (scrollr.min.y)) * ndirs/Dy(scrollr));
+			redraw();
+		}
+	}else if(m.buttons & 4){
+		dy = 1+nlines*((double)(m.xy.y - scrollr.min.y)/Dy(scrollr));
+		scrolldown(dy);
+	}
+}
+
+void
 evtresize(void)
 {
 	if(getwindow(display, Refnone)<0)
 		sysfatal("cannot reattach: %r");
 	lineh = Padding+font->height+Padding;
-	toolr = screen->r;
+	freeimage(fb);
+	if((fb = allocimage(display,
+		Rect(0,0,Dx(screen->r),Dy(screen->r)),
+		screen->chan, 0, DNofill)) == nil)
+		sysfatal("allocimage: %r");
+	toolr = fb->r;
 	toolr.max.y = toolr.min.y+16+2*Toolpadding;
-	scrollr = screen->r;
+	scrollr = fb->r;
 	scrollr.min.y = toolr.max.y+1;
 	scrollr.max.x = scrollr.min.x + Scrollwidth;
 	scrollr = insetrect(scrollr, 1);
-	viewr = screen->r;
+	viewr = fb->r;
 	viewr.min.x += Scrollwidth;
 	viewr.min.y = toolr.max.y+1;
 	nlines = Dy(viewr)/lineh;
@@ -543,17 +615,38 @@
 	case Kpgdown:
 		scrolldown(nlines);
 		break;
+	case 'k':
+	case Kup:
+		scrollup(1);
+		break;
+	case 'j':
+	case Kdown:
+		scrolldown(1);
+		break;
 	case Khome:
-		cd(nil);
+		scrollup(ndirs);
+		break;
+	case Kend:
+		scrolldown(ndirs);
+		break;
+	case 'r':
+	case Kesc:
+		loaddirs(0);
 		redraw();
 		break;
-	case Kup:
+	case 'h':
 		up();
 		redraw();
 		break;
-	case 0x20:
-		plumbsendtext(plumbfd, "vdir", nil, nil, path);
+	case 'b':
+	case Kbs:
+		back();
+		redraw();
 		break;
+	case 'l':
+	case 0x0a:
+		plumbsendtext(plumbfd, "vdirw", nil, nil, path);
+		break;
 	}
 }
 
@@ -562,9 +655,8 @@
 {
 	Point p;
 
-	p = screen->r.min;
-	p.x += (Dx(screen->r)-stringwidth(font, text)-4)/2;
-	p.y += (Dy(screen->r)-font->height-4)/2;
+	p.x = (Dx(fb->r)-stringwidth(font, text)-4)/2;
+	p.y = (Dy(fb->r)-font->height-4)/2;
 	return p;
 }
 
@@ -584,63 +676,36 @@
 void
 evtmouse(Mouse m)
 {
-	int n, dy;
+	int n;
 	Dir d;
 	char buf[256] = {0};
 
-	if(oldbuttons == 0 && m.buttons != 0 && ptinrect(m.xy, scrollr))
+	m.xy = subpt(m.xy, screen->r.min);
+	if(m.buttons != 0 && (ptinrect(m.xy, scrollr) || scrolling)){
 		scrolling = 1;
-	else if(m.buttons == 0)
+		scroll(m);
+	}else
 		scrolling = 0;
 
-	if(m.buttons&1){
-		if(scrolling){
-			dy = 1+nlines*((double)(m.xy.y - scrollr.min.y)/Dy(scrollr));
-			scrollup(dy);
-		}
-	}else if(m.buttons&2){
-		if(ptinrect(m.xy, viewr)){
-			n = indexat(m.xy);
-			if(n==-1)
-				return;
-			d = dirs[offset+n];
-			switch(menuhit(2, mctl, &menu2, nil)){
-			case Mdelete:
-				rm(d.name);
-				redraw();
-				break;
-			case Mrename:
-				snprint(buf, sizeof buf, "%s", d.name);
-				if(enter("Rename to", buf, sizeof buf, mctl, kctl, nil)>0){
-					mv(d.name, buf);
-					redraw();
-				}
-				break;
-			}
-		}else if(scrolling){
-			if(nlines<ndirs){
-				offset = scrollclamp((m.xy.y - scrollr.min.y) * ndirs/Dy(scrollr));
-				redraw();
-			}
-		}
-	}if((m.buttons&4) && oldbuttons == 0){
-		if(scrolling){
-			dy = 1+nlines*((double)(m.xy.y - scrollr.min.y)/Dy(scrollr));
-			scrolldown(dy);
-		}else if(ptinrect(m.xy, homer)){
+	if(m.buttons&1 && oldbuttons == 0){
+		if(ptinrect(m.xy, homer)){
 			cd(nil);
 			redraw();
 		}else if(ptinrect(m.xy, upr)){
 			up();
 			redraw();
-		}else if(ptinrect(m.xy, cdr)){
+		}else if(ptinrect(m.xy, refr)){
+			loaddirs(0);
+			redraw();
+		}else if(ptinrect(m.xy, backr)){
+			if(back())
+				redraw();
+		}else if(ptinrect(m.xy, cdr) || ptinrect(m.xy, pathr)){
 			m.xy = cept("Go to directory");
 			if(enter("Go to directory", buf, sizeof buf, mctl, kctl, nil)>0){
 				cd(buf);
 				redraw();
 			}
-		}else if(ptinrect(m.xy, pathr)){
-			plumbsendtext(plumbfd, "vdir", nil, nil, path);
 		}else if(ptinrect(m.xy, newdirr)){
 			m.xy = cept("Create directory");
 			if(enter("Create directory", buf, sizeof buf, mctl, kctl, nil)>0){
@@ -661,11 +726,40 @@
 			if(d.qid.type & QTDIR){
 				cd(d.name);
 				redraw();
-			}else{
-				if(plumbfile(path, d.name))
-					flash(n);
 			}
 		}
+	}else if(m.buttons&2 && oldbuttons == 0){
+		if(ptinrect(m.xy, viewr)){
+			n = indexat(m.xy);
+			if(n==-1)
+				return;
+			d = dirs[offset+n];
+			menu2.lasthit = 0;
+			switch(menuhit(2, mctl, &menu2, nil)){
+			case Mdelete:
+				rm(d.name);
+				redraw();
+				break;
+			case Mrename:
+				snprint(buf, sizeof buf, "%s", d.name);
+				if(enter("Rename to", buf, sizeof buf, mctl, kctl, nil)>0){
+					mv(d.name, buf);
+					redraw();
+				}
+				break;
+			}
+		}
+	}if((m.buttons&4) && oldbuttons == 0){
+		if(ptinrect(m.xy, pathr)){
+			plumbsendtext(plumbfd, "vdirw", nil, nil, path);
+		}else if(ptinrect(m.xy, viewr)){
+			n = indexat(m.xy);
+			if(n==-1)
+				return;
+			d = dirs[offset+n];
+			if(plumbfile(path, d.name, d.qid.type & QTDIR))
+				flash(n);
+		}
 	}else if(m.buttons&8)
 		scrollup(Slowscroll);
 	else if(m.buttons&16)
@@ -741,7 +835,7 @@
 	alts[Eresize].c = mctl->resizec;
 	alts[Ekeyboard].c = kctl->c;
 	readhome();
-	loaddirs();
+	loaddirs(1);
 	initcolors();
 	initimages();
 	evtresize();