acme: mouse movement for Del

If the mouse was in the tag of the old window,
it was most likely pointing at Del. If bringing up a
new window from below and not moving the mouse
somewhere else, adjust it so that it ends up pointing
at Del in the replacement window's tag too.
This makes it easy to Del a sequence of windows in
a column, from top to bottom.

http://www.youtube.com/watch?v=ET8w6RT6u5M

R=r
http://codereview.appspot.com/6558047
diff --git a/src/cmd/acme/cols.c b/src/cmd/acme/cols.c
index 424358e..5e16c21 100644
--- a/src/cmd/acme/cols.c
+++ b/src/cmd/acme/cols.c
@@ -157,7 +157,7 @@
 colclose(Column *c, Window *w, int dofree)
 {
 	Rectangle r;
-	int i;
+	int i, didmouse, up;
 
 	/* w is locked */
 	if(!c->safe)
@@ -171,7 +171,7 @@
 	w->tag.col = nil;
 	w->body.col = nil;
 	w->col = nil;
-	restoremouse(w);
+	didmouse = restoremouse(w);
 	if(dofree){
 		windelete(w);
 		winclose(w);
@@ -183,17 +183,24 @@
 		draw(screen, r, display->white, nil, ZP);
 		return;
 	}
+	up = 0;
 	if(i == c->nw){		/* extend last window down */
 		w = c->w[i-1];
 		r.min.y = w->r.min.y;
 		r.max.y = c->r.max.y;
 	}else{			/* extend next window up */
+		up = 1;
 		w = c->w[i];
 		r.max.y = w->r.max.y;
 	}
 	draw(screen, r, textcols[BACK], nil, ZP);
-	if(c->safe)
+	if(c->safe) {
+		if(!didmouse && up)
+			w->showdel = TRUE;
 		winresize(w, r, FALSE, TRUE);
+		if(!didmouse && up)
+			movetodel(w);
+	}
 }
 
 void
@@ -535,7 +542,7 @@
 		r.max.y = c->w[i+1]->r.min.y-Border;
 	winresize(w, r, c->safe, TRUE);
 	c->safe = TRUE;
-    	winmousebut(w);
+	winmousebut(w);
 }
 
 Text*
diff --git a/src/cmd/acme/dat.h b/src/cmd/acme/dat.h
index 0da2a12..0539d1a 100644
--- a/src/cmd/acme/dat.h
+++ b/src/cmd/acme/dat.h
@@ -239,6 +239,7 @@
 	uchar	filemenu;
 	uchar	dirty;
 	uchar	autoindent;
+	uchar	showdel;
 	int		id;
 	Range	addr;
 	Range	limit;
diff --git a/src/cmd/acme/fns.h b/src/cmd/acme/fns.h
index 8738d2d..af06344 100644
--- a/src/cmd/acme/fns.h
+++ b/src/cmd/acme/fns.h
@@ -22,10 +22,11 @@
 void	undo(Text*, Text*, Text*, int, int, Rune*, int);
 void	scrsleep(uint);
 void	savemouse(Window*);
-void	restoremouse(Window*);
+int	restoremouse(Window*);
 void	clearmouse(void);
 void	allwindows(void(*)(Window*, void*), void*);
 uint loadfile(int, uint, int*, int(*)(void*, uint, Rune*, int), void*);
+void	movetodel(Window*);
 
 Window*	errorwin(Mntdir*, int);
 Window*	errorwinforwin(Window*);
diff --git a/src/cmd/acme/util.c b/src/cmd/acme/util.c
index 7675346..de6cdf8 100644
--- a/src/cmd/acme/util.c
+++ b/src/cmd/acme/util.c
@@ -383,12 +383,18 @@
 	mousew = w;
 }
 
-void
+int
 restoremouse(Window *w)
 {
-	if(mousew!=nil && mousew==w)
+	int did;
+
+	did = 0;
+	if(mousew!=nil && mousew==w) {
 		moveto(mousectl, prevmouse);
+		did = 1;
+	}
 	mousew = nil;
+	return did;
 }
 
 void
diff --git a/src/cmd/acme/wind.c b/src/cmd/acme/wind.c
index bfe4bec..378c3cc 100644
--- a/src/cmd/acme/wind.c
+++ b/src/cmd/acme/wind.c
@@ -106,6 +106,34 @@
 	draw(screen, br, b, nil, b->r.min);
 }
 
+int
+delrunepos(Window *w)
+{
+	int n;
+	Rune rune;
+	
+	for(n=0; n<w->tag.file->b.nc; n++) {
+		bufread(&w->tag.file->b, n, &rune, 1);
+		if(rune == ' ')
+			break;
+	}
+	n += 2;
+	if(n >= w->tag.file->b.nc)
+		return -1;
+	return n;
+}
+
+void
+movetodel(Window *w)
+{
+	int n;
+	
+	n = delrunepos(w);
+	if(n < 0)
+		return;
+	moveto(mousectl, addpt(frptofchar(&w->tag.fr, n), Pt(4, w->tag.fr.font->height-4)));
+}
+
 /*
  * Compute number of tag lines required
  * to display entire tag text.
@@ -115,14 +143,25 @@
 {
 	int n;
 	Rune rune;
+	Point p;
 
-	if(!w->tagexpand)
+	if(!w->tagexpand && !w->showdel)
 		return 1;
+	w->showdel = FALSE;
 	w->tag.fr.noredraw = 1;
 	textresize(&w->tag, r, TRUE);
 	w->tag.fr.noredraw = 0;
 	w->tagsafe = FALSE;
 	
+	if(!w->tagexpand) {
+		/* use just as many lines as needed to show the Del */
+		n = delrunepos(w);
+		if(n < 0)
+			return 1;
+		p = subpt(frptofchar(&w->tag.fr, n), w->tag.fr.r.min);
+		return 1 + p.y / w->tag.fr.font->height;
+	}
+		
 	/* can't use more than we have */
 	if(w->tag.fr.nlines >= w->tag.fr.maxlines)
 		return w->tag.fr.maxlines;