acme: revise multiline tag code
diff --git a/src/cmd/acme/cols.c b/src/cmd/acme/cols.c
index 31b2780..be5a2aa 100644
--- a/src/cmd/acme/cols.c
+++ b/src/cmd/acme/cols.c
@@ -53,7 +53,7 @@
 {
 	Rectangle r, r1;
 	Window *v;
-	int i, j, minht, t;
+	int i, j, minht, ymax;
 
 	v = nil;
 	r = c->r;
@@ -72,31 +72,38 @@
 		if(i < c->nw)
 			i++;	/* new window will go after v */
 		/*
-		 * if v's too small, grow it first.
+		 * if landing window (v) is too small, grow it first.
 		 */
 		minht = v->tag.fr.font->height+Border+1;
 		j = 0;
 		while(!c->safe || v->body.fr.maxlines<=3 || Dy(v->body.all) <= minht){
 			if(++j > 10){
-fprint(2, "oops: dy=%d\n", Dy(v->body.all));
+				fprint(2, "coladd: bug dy=%d\n", Dy(v->body.all));
 				break;
 			}
 			colgrow(c, v, 1);
 		}
+
+		/*
+		 * figure out where to split v to make room for w
+		 */
 		if(i == c->nw)
-			t = c->r.max.y;
+			ymax = c->r.max.y;
 		else
-			t = c->w[i]->r.min.y-Border;
+			ymax = c->w[i]->r.min.y-Border;
 		y = min(y, v->body.all.min.y+Dy(v->body.all)/2);
-		if(t - y < minht)
-			y = t - minht;
-		if(y < v->body.all.min.y)
-			y = v->body.all.min.y;
+		y = min(y, ymax - minht);
+		y = max(y, v->body.all.min.y);
+		ymax = max(ymax, y+minht);
 		r = v->r;
-		r.max.y = t;
+		r.max.y = ymax;
+
+		/*
+		 * redraw w
+		 */
 		draw(screen, r, textcols[BACK], nil, ZP);
 		r1 = r;
-		y = min(y, t-(v->tag.fr.font->height*v->taglines+v->body.fr.font->height+Border+1));
+		y = min(y, ymax-(v->tag.fr.font->height*v->taglines+v->body.fr.font->height+Border+1));
 		r1.max.y = min(y, v->body.fr.r.min.y+v->body.fr.nlines*v->body.fr.font->height);
 		r1.min.y = winresize(v, r1, FALSE, FALSE);
 		r1.max.y = r1.min.y+Border;
@@ -151,8 +158,8 @@
 		windelete(w);
 		winclose(w);
 	}
-	memmove(c->w+i, c->w+i+1, (c->nw-i-1)*sizeof(Window*));
 	c->nw--;
+	memmove(c->w+i, c->w+i+1, (c->nw-i)*sizeof(Window*));
 	c->w = realloc(c->w, c->nw*sizeof(Window*));
 	if(c->nw == 0){
 		draw(screen, r, display->white, nil, ZP);
@@ -219,8 +226,7 @@
 			r1.max.y = r.max.y;
 		else
 			r1.max.y = r1.min.y+(Dy(w->r)+Border)*Dy(r)/Dy(c->r);
-		if(Dy(r1) < Border+font->height)
-			r1.max.y = r1.min.y + Border+font->height;
+		r1.max.y = max(r1.max.y, r1.min.y + Border+font->height);
 		r2 = r1;
 		r2.max.y = r2.min.y+Border;
 		draw(screen, r2, display->black, nil, ZP);
@@ -307,7 +313,7 @@
 		if(i==c->nw-1 || c->safe==FALSE)
 			r.max.y = cr.max.y;
 		else
-			r.max.y = c->w[i+1]->r.min.y-Border;
+			r.max.y = c->w[i+1]->r.min.y - Border;
 		winresize(w, r, FALSE, TRUE);
 		return;
 	}
@@ -342,7 +348,7 @@
 	}
 	nnl = min(onl + max(min(5, w->taglines-1+w->maxlines), onl/2), tot);
 	if(nnl < w->taglines-1+w->maxlines)
-		nnl = (w->taglines-1+w->maxlines+nnl)/2;
+		nnl = (w->taglines-1+w->maxlines + nnl)/2;
 	if(nnl == 0)
 		nnl = 2;
 	dnl = nnl - onl;
@@ -400,7 +406,7 @@
 	if(Dy(r) < Dy(w->tagtop)+1+h+Border)
 		r.max.y = r.min.y + Dy(w->tagtop)+1+h+Border;
 	/* draw window */
-	winresize(w, r, c->safe, TRUE);
+	r.max.y = winresize(w, r, c->safe, i==c->nw-1);
 	if(i < c->nw-1){
 		r.min.y = r.max.y;
 		r.max.y += Border;
@@ -417,7 +423,7 @@
 		r.max.y = y1+Dy(v->tagtop);
 		if(nl[j])
 			r.max.y += 1 + nl[j]*v->body.fr.font->height;
-		y1 = winresize(v, r, c->safe, j+1==c->nw);
+		y1 = winresize(v, r, c->safe, j==c->nw-1);
 		if(j < c->nw-1){	/* no border on last window */
 			r.min.y = y1;
 			r.max.y += Border;
@@ -425,12 +431,6 @@
 			y1 = r.max.y;
 		}
 	}
-/*
-	r = w->r;
-	r.min.y = y1;
-	r.max.y = c->r.max.y;
-	draw(screen, r, textcols[BACK], nil, ZP);
-*/
 	free(nl);
 	free(ny);
 	c->safe = TRUE;
@@ -465,9 +465,8 @@
 	error("can't find window");
 
   Found:
-/* TAG - force recompute tag size (if in auto-expand mode) on mouse op. */
-	w->taglines = 1;
-/* END TAG */
+	if(w->tagexpand)	/* force recomputation of window tag size */
+		w->taglines = 1;
 	p = mouse->xy;
 	if(abs(p.x-op.x)<5 && abs(p.y-op.y)<5){
 		colgrow(c, w, but);
diff --git a/src/cmd/acme/mkfile b/src/cmd/acme/mkfile
index 47ff8d6..a8696a1 100644
--- a/src/cmd/acme/mkfile
+++ b/src/cmd/acme/mkfile
@@ -33,3 +33,19 @@
 <$PLAN9/src/mkdirs
 
 edit.$O ecmd.$O elog.$O:	edit.h
+
+likeplan9:V:
+	mkdir -p likeplan9
+	rm -f likeplan9/*
+	for i in *.c
+	do
+		9 sed 's/->(fcall|lk|b|fr|ref|m|u|u1)\./->/g;
+			s/\.(fcall|lk|b|fr|ref|m|u|u1)([^a-zA-Z0-9_])/\2/g
+			s/&(([a-zA-Z0-9_]|->|\.)*)->(fcall|lk|b|fr|ref|m|u|u1)([^a-zA-Z0-9_])/\1\4/g
+			s/range\(([^,()]+), ([^,()]+)\)/(Range){\1, \2}/g
+		' $i >likeplan9/$i
+	done
+
+diffplan9:V:
+	mk likeplan9
+	9 diff -n plan9 likeplan9 | sed 's;likeplan9/;;'
diff --git a/src/cmd/acme/rows.c b/src/cmd/acme/rows.c
index c60f410..50990d7 100644
--- a/src/cmd/acme/rows.c
+++ b/src/cmd/acme/rows.c
@@ -217,8 +217,8 @@
 	r = c->r;
 	if(dofree)
 		colcloseall(c);
-	memmove(row->col+i, row->col+i+1, (row->ncol-i)*sizeof(Column*));
 	row->ncol--;
+	memmove(row->col+i, row->col+i+1, (row->ncol-i)*sizeof(Column*));
 	row->col = realloc(row->col, row->ncol*sizeof(Column*));
 	if(row->ncol == 0){
 		draw(screen, r, display->white, nil, ZP);
@@ -282,17 +282,13 @@
 		else{
 			winlock(w, 'K');
 			wintype(w, t, r);
-/*
- * TAG If we typed in the tag, might need to make it
- * bigger to show text.  \n causes tag to expand.
- */
+			/* Expand tag if necessary */
 			if(t->what == Tag){
 				t->w->tagsafe = FALSE;
 				if(r == '\n')
 					t->w->tagexpand = TRUE;
 				winresize(w, w->r, TRUE, TRUE);
 			}
-/* END TAG */
 			winunlock(w);
 		}
 	}
@@ -319,7 +315,7 @@
 	uint q0, q1;
 	Biobuf *b;
 	char *buf, *a, *fontname;
-	Rune *r, *rp;
+	Rune *r;
 	Column *c;
 	Window *w, *w1;
 	Text *t;
@@ -417,17 +413,10 @@
 			Bwrite(b, buf, strlen(buf));
 			m = min(RBUFSIZE, w->tag.file->b.nc);
 			bufread(&w->tag.file->b, 0, r, m);
-			if(dodollarsigns && r[0] == '$'){
-				rp = runestrdup(r);
-				expandenv(&rp, (uint*)&m);
-			}else
-				rp = r;
 			n = 0;
-			while(n<m && rp[n]!='\n')
+			while(n<m && r[n]!='\n')
 				n++;
-			Bprint(b, "%.*S\n", n, rp);
-			if(rp != r)
-				free(rp);
+			Bprint(b, "%.*S\n", n, r);
 			if(dumped){
 				q0 = 0;
 				q1 = t->file->b.nc;
@@ -705,6 +694,7 @@
 					Bterm(bout);
 					free(bout);
 					close(fd);
+					remove(buf);
 					goto Rescue2;
 				}
 				Bputrune(bout, rune);
@@ -731,7 +721,6 @@
 		w->maxlines = min(w->body.fr.nlines, max(w->maxlines, w->body.fr.maxlines));
 	}
 	Bterm(b);
-
 	fbuffree(buf);
 	return TRUE;
 
diff --git a/src/cmd/acme/text.c b/src/cmd/acme/text.c
index 1a6c09e..729e430 100644
--- a/src/cmd/acme/text.c
+++ b/src/cmd/acme/text.c
@@ -75,7 +75,7 @@
 
 	if(Dy(r) <= 0)
 		r.max.y = r.min.y;
-	if(!keepextra)
+	else if(!keepextra)
 		r.max.y -= Dy(r)%t->fr.font->height;
 	odx = Dx(t->all);
 	t->all = r;
@@ -84,8 +84,9 @@
 	t->lastsr = nullrect;
 	r.min.x += Scrollwid+Scrollgap;
 	frclear(&t->fr, 0);
-	textredraw(t, r, t->fr.font, screen, odx);
+	textredraw(t, r, t->fr.font, t->fr.b, odx);
 	if(keepextra && t->fr.r.max.y < t->all.max.y){
+		/* draw background in bottom fringe of window */
 		r.min.x -= Scrollgap;
 		r.min.y = t->fr.r.max.y;
 		r.max.y = t->all.max.y;
@@ -197,7 +198,7 @@
 	char *tmp;
 	Text *u;
 
-	if(t->ncache!=0 || t->file->b.nc || t->w==nil || t!=&t->w->body || (t->w->isdir && t->file->nname==0))
+	if(t->ncache!=0 || t->file->b.nc || t->w==nil || t!=&t->w->body)
 		error("text.load");
 	if(t->w->isdir && t->file->nname==0){
 		warning(nil, "empty directory name");
@@ -653,20 +654,13 @@
 	uint q0, q1;
 	int nnb, nb, n, i;
 	int nr;
-	Point p;
 	Rune *rp;
 	Text *u;
 
-/*
- * TAG
- * Used to disallow \n in tag here.
- * Also if typing in tag, mark that resize might be necessary.
- */
 	if(t->what!=Body && t->what!=Tag && r=='\n')
 		return;
 	if(t->what == Tag)
 		t->w->tagsafe = FALSE;
-/* END TAG */
 
 	nr = 1;
 	rp = &r;
@@ -684,17 +678,13 @@
 		}
 		return;
 	case Kdown:
-/* TAG */
 		if(t->what == Tag)
 			goto Tagdown;
-/* END TAG */
 		n = t->fr.maxlines/3;
 		goto case_Down;
 	case Kscrollonedown:
-/* TAG */
 		if(t->what == Tag)
 			goto Tagdown;
-/* END TAG */
 		n = mousescrollsize(t->fr.maxlines);
 		if(n <= 0)
 			n = 1;
@@ -706,17 +696,13 @@
 		textsetorigin(t, q0, TRUE);
 		return;
 	case Kup:
-/* TAG */
 		if(t->what == Tag)
 			goto Tagup;
-/* END TAG */
 		n = t->fr.maxlines/3;
 		goto case_Up;
 	case Kscrolloneup:
-/* TAG */
 		if(t->what == Tag)
 			goto Tagup;
-/* END TAG */
 		n = mousescrollsize(t->fr.maxlines);
 		goto case_Up;
 	case Kpgup:
@@ -748,7 +734,6 @@
 			q0++;
 		textshow(t, q0, q0, TRUE);
 		return;
-/* TAG policy here */
 	Tagdown:
 		/* expand tag to show all text */
 		if(!t->w->tagexpand){
@@ -762,17 +747,9 @@
 		if(t->w->tagexpand){
 			t->w->tagexpand = FALSE;
 			t->w->taglines = 1;
-			/* move mouse to stay in tag */
-			p = mouse->xy;
-			if(ptinrect(p, t->w->tag.all) 
-			&& !ptinrect(p, t->w->tagtop)){
-				p.y = t->w->tagtop.min.y + Dy(t->w->tagtop)/2;
-				moveto(mousectl, p);
-			}
 			winresize(t->w, t->w->r, FALSE, TRUE);
 		}
 		return;
-/* END TAG */
 	}
 	if(t->what == Body){
 		seq++;
diff --git a/src/cmd/acme/wind.c b/src/cmd/acme/wind.c
index ccb1aaa..afd21af 100644
--- a/src/cmd/acme/wind.c
+++ b/src/cmd/acme/wind.c
@@ -36,8 +36,8 @@
 
 	w->tagtop = r;
 	w->tagtop.max.y = r.min.y + font->height;
-
 	r1.max.y = r1.min.y + w->taglines*font->height;
+
 	incref(&reffont.ref);
 	f = fileaddtext(nil, &w->tag);
 	textinit(&w->tag, f, r1, &reffont, tagcols);
@@ -53,7 +53,6 @@
 		filereset(w->tag.file);
 		textsetselect(&w->tag, nc, nc);
 	}
-/*assert(w->body.w == w); */
 	r1 = r;
 	r1.min.y += w->taglines*font->height + 1;
 	if(r1.max.y < r1.min.y)
@@ -66,7 +65,6 @@
 		rf = rfget(FALSE, FALSE, FALSE, clone->body.reffont->f->name);
 	}else
 		rf = rfget(FALSE, FALSE, FALSE, nil);
-/*assert(w->body.w == w); */
 	f = fileaddtext(f, &w->body);
 	w->body.what = Body;
 	textinit(&w->body, f, r1, rf, textcols);
@@ -82,7 +80,6 @@
 	w->filemenu = TRUE;
 	w->maxlines = w->body.fr.maxlines;
 	w->autoindent = globalautoindent;
-/*assert(w->body.w == w); */
 	if(clone){
 		w->dirty = clone->dirty;
 		w->autoindent = clone->autoindent;
@@ -119,8 +116,6 @@
 	int n;
 	Rune rune;
 
-/* TAG policy here */
-
 	if(!w->tagexpand)
 		return 1;
 	w->tag.fr.noredraw = 1;
@@ -151,57 +146,50 @@
 	Point p;
 	Rectangle r1;
 
-if(0) fprint(2, "winresize %d %R safe=%d keep=%d h=%d\n", w->id, r, safe, keepextra, font->height);
+	/* tagtop is first line of tag */
 	w->tagtop = r;
 	w->tagtop.max.y = r.min.y+font->height;
 
-/* 
- * TAG If necessary, recompute the number of lines that should
- * be in the tag.
- */
 	r1 = r;
 	r1.max.y = min(r.max.y, r1.min.y + w->taglines*font->height);
-	y = r1.max.y;
 	mouseintag = ptinrect(mouse->xy, w->tag.all);
-	if(!safe || !w->tagsafe || !eqrect(w->tag.all, r1))
-		w->taglines = wintaglines(w, r);
-/* END TAG */
 
-	r1 = r;
-	r1.max.y = min(r.max.y, r1.min.y + w->taglines*font->height);
+	/* If needed, recompute number of lines in tag. */
+	if(!safe || !w->tagsafe || !eqrect(w->tag.all, r1)){
+		w->taglines = wintaglines(w, r);
+		r1.max.y = min(r.max.y, r1.min.y + w->taglines*font->height);
+	}
+
+	/* If needed, resize & redraw tag. */
 	y = r1.max.y;
 	tagresized = 0;
-if(0) fprint(2, "winresize tag %R %R\n", w->tag.all, r1);
 	if(!safe || !w->tagsafe || !eqrect(w->tag.all, r1)){
 		tagresized = 1;
-if(0) fprint(2, "resize tag %R => %R\n", w->tag.all, r1);
 		textresize(&w->tag, r1, TRUE);
-if(0) fprint(2, "=> %R (%R)\n", w->tag.all, w->tag.fr.r);
 		y = w->tag.fr.r.max.y;
 		windrawbutton(w);
 		w->tagsafe = TRUE;
-/* TAG */
+
 		/* If mouse is in tag, pull up as tag closes. */
 		if(mouseintag && !ptinrect(mouse->xy, w->tag.all)){
 			p = mouse->xy;
 			p.y = w->tag.all.max.y-3;
 			moveto(mousectl, p);
 		}
+
 		/* If mouse is in body, push down as tag expands. */
 		if(!mouseintag && ptinrect(mouse->xy, w->tag.all)){
 			p = mouse->xy;
 			p.y = w->tag.all.max.y+3;
 			moveto(mousectl, p);
 		}
-/* END TAG */
 	}
-
 	
+	/* If needed, resize & redraw body. */
 	r1 = r;
 	r1.min.y = y;
 	if(tagresized || !safe || !eqrect(w->body.all, r1)){
 		oy = y;
-if(0) fprint(2, "resizing body; safe=%d all=%R r1=%R\n", safe, w->body.all, r1);
 		if(y+1+w->body.fr.font->height <= r.max.y){	/* room for one line */
 			r1.min.y = y;
 			r1.max.y = y+1;
@@ -213,10 +201,9 @@
 			r1.min.y = y;
 			r1.max.y = y;
 		}
-if(0) fprint(2, "resizing body; new r=%R; r1=%R\n", r, r1);
+		y = textresize(&w->body, r1, keepextra);
 		w->r = r;
-		w->r.max.y = textresize(&w->body, r1, keepextra);
-if(0) fprint(2, "after textresize: body.all=%R\n", w->body.all);
+		w->r.max.y = y;
 		textscrdraw(&w->body);
 		w->body.all.min.y = oy;
 	}
@@ -354,6 +341,7 @@
 	int i;
 	static Rune Lslashguide[] = { '/', 'g', 'u', 'i', 'd', 'e', 0 };
 	static Rune Lpluserrors[] = { '+', 'E', 'r', 'r', 'o', 'r', 's', 0 };
+
 	t = &w->body;
 	if(runeeq(t->file->name, t->file->nname, name, n) == TRUE)
 		return;
@@ -559,7 +547,6 @@
 	for(i=0; i<w->tag.file->b.nc; i++)
 		if(r[i]==' ' || r[i]=='\t')
 			break;
-	expandenv(&r, (uint*)&i);
 	if(runeeq(r, i, w->body.file->name, w->body.file->nname) == FALSE){
 		seq++;
 		filemark(w->body.file);
@@ -678,4 +665,3 @@
 		sendp(x->c, nil);
 	}
 }
-