diff -Nru /n/sources/plan9/sys/src/cmd/acme/cols.c /sys/src/cmd/acme/cols.c
--- /n/sources/plan9/sys/src/cmd/acme/cols.c Tue Mar 18 21:49:11 2014
+++ /sys/src/cmd/acme/cols.c Sat Mar 5 00:00:00 2016
@@ -75,9 +75,9 @@
r.max.y = t;
draw(screen, r, textcols[BACK], nil, ZP);
r1 = r;
- y = min(y, t-(v->tag.font->height+v->body.font->height+Border+1));
+ y = min(y, t-(v->tag.font->height*v->taglines+v->body.font->height+Border+1));
r1.max.y = min(y, v->body.r.min.y+v->body.nlines*v->body.font->height);
- r1.min.y = winresize(v, r1, FALSE);
+ r1.min.y = winresize(v, r1, FALSE, FALSE);
r1.max.y = r1.min.y+Border;
draw(screen, r1, display->black, nil, ZP);
r.min.y = r1.max.y;
@@ -89,7 +89,7 @@
wininit(w, clone, r);
}else{
w->col = c;
- winresize(w, r, FALSE);
+ winresize(w, r, FALSE, TRUE);
}
w->tag.col = c;
w->tag.row = c->row;
@@ -149,7 +149,7 @@
}
draw(screen, r, textcols[BACK], nil, ZP);
if(c->safe){
- winresize(w, r, FALSE);
+ winresize(w, r, FALSE, TRUE);
USED(up);
if(!didmouse)
movetodel(w);
@@ -191,7 +191,7 @@
clearmouse();
r1 = r;
r1.max.y = r1.min.y + c->tag.font->height;
- textresize(&c->tag, r1);
+ textresize(&c->tag, r1, TRUE);
draw(screen, c->tag.scrollr, colbutton, nil, colbutton->r.min);
r1.min.y = r1.max.y;
r1.max.y += Border;
@@ -208,7 +208,7 @@
r2.max.y = r2.min.y+Border;
draw(screen, r2, display->black, nil, ZP);
r1.min.y = r2.max.y;
- r1.min.y = winresize(w, r1, FALSE);
+ r1.min.y = winresize(w, r1, FALSE, i==c->nw-1);
}
c->r = r;
}
@@ -264,7 +264,7 @@
r1.max.y = r1.min.y+Border;
draw(screen, r1, display->black, nil, ZP);
r.min.y = r1.max.y;
- y = winresize(w, r, FALSE);
+ y = winresize(w, r, FALSE, i==c->nw-1);
}
free(rp);
free(c->w);
@@ -291,7 +291,7 @@
r.max.y = cr.max.y;
else
r.max.y = c->w[i+1]->r.min.y;
- winresize(w, r, FALSE);
+ winresize(w, r, FALSE, TRUE);
return;
}
cr.min.y = c->w[0]->r.min.y;
@@ -302,7 +302,7 @@
c->w[i] = v;
}
draw(screen, cr, textcols[BACK], nil, ZP);
- winresize(w, cr, FALSE);
+ winresize(w, cr, FALSE, TRUE);
for(i=1; i<c->nw; i++)
c->w[i]->body.maxlines = 0;
c->safe = FALSE;
@@ -314,7 +314,7 @@
ny = emalloc(c->nw * sizeof(int));
tot = 0;
for(j=0; j<c->nw; j++){
- l = c->w[j]->body.maxlines;
+ l = c->w[j]->taglines-1 + c->w[j]->body.maxlines;
nl[j] = l;
tot += l;
}
@@ -323,9 +323,9 @@
memset(nl, 0, c->nw * sizeof(int));
goto Pack;
}
- nnl = min(onl + max(min(5, w->maxlines), onl/2), tot);
- if(nnl < w->maxlines)
- nnl = (w->maxlines+nnl)/2;
+ 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;
if(nnl == 0)
nnl = 2;
dnl = nnl - onl;
@@ -355,14 +355,10 @@
v = c->w[j];
r = v->r;
r.min.y = y1;
- r.max.y = y1+Dy(v->tag.all);
+ r.max.y = y1+Dy(v->tagtop);
if(nl[j])
r.max.y += 1 + nl[j]*v->body.font->height;
- if(!c->safe || !eqrect(v->r, r)){
- draw(screen, r, textcols[BACK], nil, ZP);
- winresize(v, r, c->safe);
- }
- r.min.y = v->r.max.y;
+ r.min.y = winresize(v, r, c->safe, FALSE);
r.max.y += Border;
draw(screen, r, display->black, nil, ZP);
y1 = r.max.y;
@@ -372,7 +368,7 @@
for(j=c->nw-1; j>i; j--){
v = c->w[j];
r = v->r;
- r.min.y = y2-Dy(v->tag.all);
+ r.min.y = y2-Dy(v->tagtop);
if(nl[j])
r.min.y -= 1 + nl[j]*v->body.font->height;
r.min.y -= Border;
@@ -382,17 +378,12 @@
/* compute new size of window */
r = w->r;
r.min.y = y1;
- r.max.y = r.min.y+Dy(w->tag.all);
+ r.max.y = y2;
h = w->body.font->height;
- if(y2-r.max.y >= 1+h+Border){
- r.max.y += 1;
- r.max.y += h*((y2-r.max.y)/h);
- }
+ if(Dy(r) < Dy(w->tagtop)+1+h+Border)
+ r.max.y = r.min.y + Dy(w->tagtop)+1+h+Border;
/* draw window */
- if(!c->safe || !eqrect(w->r, r)){
- draw(screen, r, textcols[BACK], nil, ZP);
- winresize(w, r, c->safe);
- }
+ r.max.y = winresize(w, r, c->safe, TRUE);
if(i < c->nw-1){
r.min.y = r.max.y;
r.max.y += Border;
@@ -406,13 +397,10 @@
v = c->w[j];
r = v->r;
r.min.y = y1;
- r.max.y = y1+Dy(v->tag.all);
+ r.max.y = y1+Dy(v->tagtop);
if(nl[j])
r.max.y += 1 + nl[j]*v->body.font->height;
- if(!c->safe || !eqrect(v->r, r)){
- draw(screen, r, textcols[BACK], nil, ZP);
- winresize(v, r, c->safe);
- }
+ winresize(v, r, c->safe, j==c->nw-1);
if(j < c->nw-1){ /* no border on last window */
r.min.y = v->r.max.y;
r.max.y += Border;
@@ -458,6 +446,8 @@
error("can't find window");
Found:
+ 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);
@@ -487,10 +477,10 @@
if(i == 0)
return;
v = c->w[i-1];
- if(p.y < v->tag.all.max.y)
- p.y = v->tag.all.max.y;
- if(p.y > w->r.max.y-Dy(w->tag.all)-Border)
- p.y = w->r.max.y-Dy(w->tag.all)-Border;
+ if(p.y < v->tagtop.max.y)
+ p.y = v->tagtop.max.y;
+ if(p.y > w->r.max.y-Dy(w->tagtop)-Border)
+ p.y = w->r.max.y-Dy(w->tagtop)-Border;
r = v->r;
r.max.y = p.y;
if(r.max.y > v->body.r.min.y){
@@ -498,11 +488,7 @@
if(v->body.r.min.y == v->body.r.max.y)
r.max.y++;
}
- if(!eqrect(v->r, r)){
- draw(screen, r, textcols[BACK], nil, ZP);
- winresize(v, r, c->safe);
- }
- r.min.y = v->r.max.y;
+ r.min.y = winresize(v, r, c->safe, FALSE);
r.max.y = r.min.y+Border;
draw(screen, r, display->black, nil, ZP);
r.min.y = r.max.y;
@@ -510,10 +496,7 @@
r.max.y = c->r.max.y;
else
r.max.y = c->w[i+1]->r.min.y-Border;
- if(!eqrect(w->r, r)){
- draw(screen, r, textcols[BACK], nil, ZP);
- winresize(w, r, c->safe);
- }
+ winresize(w, r, c->safe, TRUE);
c->safe = TRUE;
winmousebut(w);
}
@@ -531,7 +514,7 @@
for(i=0; i<c->nw; i++){
w = c->w[i];
if(ptinrect(p, w->r)){
- if(ptinrect(p, w->tag.all))
+ if(ptinrect(p, w->tagtop) || ptinrect(p, w->tag.all))
return &w->tag;
return &w->body;
}
diff -Nru /n/sources/plan9/sys/src/cmd/acme/dat.h /sys/src/cmd/acme/dat.h
--- /n/sources/plan9/sys/src/cmd/acme/dat.h Wed Mar 23 19:34:19 2005
+++ /sys/src/cmd/acme/dat.h Sat Mar 5 00:00:00 2016
@@ -211,7 +211,7 @@
Rune textreadc(Text*, uint);
void textredraw(Text*, Rectangle, Font*, Image*, int);
void textreset(Text*);
-int textresize(Text*, Rectangle);
+int textresize(Text*, Rectangle, int);
void textscrdraw(Text*);
void textscroll(Text*, int);
void textselect(Text*);
@@ -235,6 +235,7 @@
uchar filemenu;
uchar dirty;
uchar autoindent;
+ uchar showdel;
int id;
Range addr;
Range limit;
@@ -263,6 +264,11 @@
int utflastqid;
int utflastboff;
int utflastq;
+ int tagsafe; /* taglines is correct */
+ int tagexpand;
+ int taglines;
+ Rectangle tagtop;
+ QLock editoutlk;
};
void wininit(Window*, Window*, Rectangle);
@@ -275,7 +281,7 @@
void winsettag(Window*);
void winsettag1(Window*);
void wincommit(Window*, Text*);
-int winresize(Window*, Rectangle, int);
+int winresize(Window*, Rectangle, int, int);
void winclose(Window*);
void windelete(Window*);
int winclean(Window*, int);
diff -Nru /n/sources/plan9/sys/src/cmd/acme/exec.c /sys/src/cmd/acme/exec.c
--- /n/sources/plan9/sys/src/cmd/acme/exec.c Wed Jan 13 17:21:48 2010
+++ /sys/src/cmd/acme/exec.c Sat Mar 5 00:00:00 2016
@@ -1170,7 +1170,7 @@
if(tab > 0){
if(w->body.tabstop != tab){
w->body.tabstop = tab;
- winresize(w, w->r, 1);
+ winresize(w, w->r, FALSE, TRUE);
}
}else
warning(nil, "%.*S: Tab %d\n", w->body.file->nname, w->body.file->name, w->body.tabstop);
diff -Nru /n/sources/plan9/sys/src/cmd/acme/rows.c /sys/src/cmd/acme/rows.c
--- /n/sources/plan9/sys/src/cmd/acme/rows.c Wed Apr 25 19:01:17 2007
+++ /sys/src/cmd/acme/rows.c Sat Mar 5 00:00:00 2016
@@ -102,7 +102,7 @@
row->r = r;
r1 = r;
r1.max.y = r1.min.y + font->height;
- textresize(&row->tag, r1);
+ textresize(&row->tag, r1, TRUE);
r1.min.y = r1.max.y;
r1.max.y += Border;
draw(screen, r1, display->black, nil, ZP);
@@ -271,6 +271,13 @@
else{
winlock(w, 'K');
wintype(w, t, r);
+ /* 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);
+ }
winunlock(w);
}
}
diff -Nru /n/sources/plan9/sys/src/cmd/acme/text.c /sys/src/cmd/acme/text.c
--- /n/sources/plan9/sys/src/cmd/acme/text.c Sat Dec 31 21:27:30 2005
+++ /sys/src/cmd/acme/text.c Sat Mar 5 00:00:00 2016
@@ -45,7 +45,8 @@
frinit(t, r, f, b, t->Frame.cols);
rr = t->r;
rr.min.x -= Scrollwid+Scrollgap; /* back fill to scroll bar */
- draw(t->b, rr, t->cols[BACK], nil, ZP);
+ if(!t->noredraw)
+ draw(t->b, rr, t->cols[BACK], nil, ZP);
/* use no wider than 3-space tabs in a directory */
maxt = maxtab;
if(t->what == Body){
@@ -68,14 +69,14 @@
}
int
-textresize(Text *t, Rectangle r)
+textresize(Text *t, Rectangle r, int keepextra)
{
int odx;
- if(Dy(r) > 0)
- r.max.y -= Dy(r)%t->font->height;
- else
+ if(Dy(r) <= 0)
r.max.y = r.min.y;
+ else if(!keepextra)
+ r.max.y -= Dy(r)%t->font->height;
odx = Dx(t->all);
t->all = r;
t->scrollr = r;
@@ -84,7 +85,14 @@
r.min.x += Scrollwid+Scrollgap;
frclear(t, 0);
textredraw(t, r, t->font, t->b, odx);
- return r.max.y;
+ if(keepextra && t->r.max.y < t->all.max.y && !t->noredraw){
+ /* draw background in bottom fringe of window */
+ r.min.x -= Scrollgap;
+ r.min.y = t->r.max.y;
+ r.max.y = t->all.max.y;
+ draw(screen, r, t->cols[BACK], nil, ZP);
+ }
+ return t->all.max.y;
}
void
@@ -276,7 +284,7 @@
if(u != t){
if(u->org > u->file->nc) /* will be 0 because of reset(), but safety first */
u->org = 0;
- textresize(u, u->all);
+ textresize(u, u->all, TRUE);
textbacknl(u, u->org, 0); /* go to beginning of line */
}
textsetselect(u, q0, q0);
@@ -643,8 +651,11 @@
Rune *rp;
Text *u;
- if(t->what!=Body && r=='\n')
+ if(t->what!=Body && t->what!=Tag && r=='\n')
return;
+ if(t->what == Tag)
+ t->w->tagsafe = FALSE;
+
nr = 1;
rp = &r;
switch(r){
@@ -661,9 +672,13 @@
}
return;
case Kdown:
+ if(t->what == Tag)
+ goto Tagdown;
n = t->maxlines/3;
goto case_Down;
case Kscrollonedown:
+ if(t->what == Tag)
+ goto Tagdown;
n = mousescrollsize(t->maxlines);
if(n <= 0)
n = 1;
@@ -675,9 +690,13 @@
textsetorigin(t, q0, TRUE);
return;
case Kup:
+ if(t->what == Tag)
+ goto Tagup;
n = t->maxlines/3;
goto case_Up;
case Kscrolloneup:
+ if(t->what == Tag)
+ goto Tagup;
n = mousescrollsize(t->maxlines);
goto case_Up;
case Kpgup:
@@ -708,6 +727,23 @@
while(q0<t->file->nc && textreadc(t, q0)!='\n')
q0++;
textshow(t, q0, q0, TRUE);
+ return;
+
+ Tagdown:
+ /* expand tag to show all text */
+ if(!t->w->tagexpand){
+ t->w->tagexpand = TRUE;
+ winresize(t->w, t->w->r, FALSE, TRUE);
+ }
+ return;
+
+ Tagup:
+ /* shrink tag to single line */
+ if(t->w->tagexpand){
+ t->w->tagexpand = FALSE;
+ t->w->taglines = 1;
+ winresize(t->w, t->w->r, FALSE, TRUE);
+ }
return;
}
if(t->what == Body){
diff -Nru /n/sources/plan9/sys/src/cmd/acme/wind.c /sys/src/cmd/acme/wind.c
--- /n/sources/plan9/sys/src/cmd/acme/wind.c Tue Mar 18 21:49:11 2014
+++ /sys/src/cmd/acme/wind.c Sat Mar 5 00:00:00 2016
@@ -23,6 +23,8 @@
int nc;
w->tag.w = w;
+ w->taglines = 1;
+ w->tagexpand = TRUE;
w->body.w = w;
w->id = ++winid;
incref(w);
@@ -31,7 +33,11 @@
w->ctlfid = ~0;
w->utflastqid = -1;
r1 = r;
- r1.max.y = r1.min.y + font->height;
+
+ w->tagtop = r;
+ w->tagtop.max.y = r.min.y + font->height;
+ r1.max.y = r1.min.y + w->taglines*font->height;
+
incref(&reffont);
f = fileaddtext(nil, &w->tag);
textinit(&w->tag, f, r1, &reffont, tagcols);
@@ -48,7 +54,7 @@
textsetselect(&w->tag, nc, nc);
}
r1 = r;
- r1.min.y += font->height + 1;
+ r1.min.y += w->taglines*font->height + 1;
if(r1.max.y < r1.min.y)
r1.max.y = r1.min.y;
f = nil;
@@ -67,7 +73,6 @@
draw(screen, r1, tagcols[BORD], nil, ZP);
textscrdraw(&w->body);
w->r = r;
- w->r.max.y = w->body.r.max.y;
br.min = w->tag.scrollr.min;
br.max.x = br.min.x + Dx(button->r);
br.max.y = br.min.y + Dy(button->r);
@@ -83,6 +88,24 @@
}
}
+/*
+ * Draw the appropriate button.
+ */
+void
+windrawbutton(Window *w)
+{
+ Image *b;
+ Rectangle br;
+
+ b = button;
+ if(!w->isdir && !w->isscratch && (w->body.file->mod || w->body.ncache))
+ b = modbutton;
+ br.min = w->tag.scrollr.min;
+ br.max.x = br.min.x + Dx(b->r);
+ br.max.y = br.min.y + Dy(b->r);
+ draw(screen, br, b, nil, b->r.min);
+}
+
int
delrunepos(Window *w)
{
@@ -111,46 +134,117 @@
moveto(mousectl, addpt(frptofchar(&w->tag, n), Pt(4, w->tag.font->height-4)));
}
+/*
+ * Compute number of tag lines required
+ * to display entire tag text.
+ */
+int
+wintaglines(Window *w, Rectangle r)
+{
+ int n;
+ Rune rune;
+ Point p;
+
+ if(!w->tagexpand && !w->showdel)
+ return 1;
+ w->showdel = FALSE;
+ w->tag.noredraw = 1;
+ textresize(&w->tag, r, TRUE);
+ w->tag.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, n), w->tag.r.min);
+ return 1 + p.y / w->tag.font->height;
+ }
+
+ /* can't use more than we have */
+ if(w->tag.nlines >= w->tag.maxlines)
+ return w->tag.maxlines;
+
+ /* if tag ends with \n, include empty line at end for typing */
+ n = w->tag.nlines;
+ if(w->tag.file->nc > 0){
+ bufread(w->tag.file, w->tag.file->nc-1, &rune, 1);
+ if(rune == '\n')
+ n++;
+ }
+ if(n == 0)
+ n = 1;
+ return n;
+}
+
int
-winresize(Window *w, Rectangle r, int safe)
+winresize(Window *w, Rectangle r, int safe, int keepextra)
{
+ int oy, y, mouseintag, mouseinbody;
+ Point p;
Rectangle r1;
- int y;
- Image *b;
- Rectangle br;
+
+ mouseintag = ptinrect(mouse->xy, w->tag.all);
+ mouseinbody = ptinrect(mouse->xy, w->body.all);
+
+ /* tagtop is first line of tag */
+ w->tagtop = r;
+ w->tagtop.max.y = r.min.y+font->height;
r1 = r;
- r1.max.y = r1.min.y + font->height;
+ 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;
- if(!safe || !eqrect(w->tag.r, r1)){
- y = textresize(&w->tag, r1);
- b = button;
- if(w->body.file->mod && !w->isdir && !w->isscratch)
- b = modbutton;
- br.min = w->tag.scrollr.min;
- br.max.x = br.min.x + Dx(b->r);
- br.max.y = br.min.y + Dy(b->r);
- draw(screen, br, b, nil, b->r.min);
+ if(!safe || !w->tagsafe || !eqrect(w->tag.all, r1)){
+ textresize(&w->tag, r1, TRUE);
+ y = w->tag.r.max.y;
+ windrawbutton(w);
+ w->tagsafe = TRUE;
+
+ /* 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(mouseinbody && ptinrect(mouse->xy, w->tag.all)){
+ p = mouse->xy;
+ p.y = w->tag.all.max.y+3;
+ moveto(mousectl, p);
+ }
}
- if(!safe || !eqrect(w->body.r, r1)){
- if(y+1+font->height > r.max.y){ /* no body */
+
+ /* If needed, resize & redraw body. */
+ r1 = r;
+ r1.min.y = y;
+ if(!safe || !eqrect(w->body.all, r1)){
+ oy = y;
+ if(y+1+w->body.font->height <= r.max.y){ /* room for one line */
+ r1.min.y = y;
+ r1.max.y = y+1;
+ draw(screen, r1, tagcols[BORD], nil, ZP);
+ y++;
+ r1.min.y = min(y, r.max.y);
+ r1.max.y = r.max.y;
+ }else{
r1.min.y = y;
r1.max.y = y;
- textresize(&w->body, r1);
- w->r = r;
- w->r.max.y = y;
- return y;
}
- r1 = r;
- r1.min.y = y;
- r1.max.y = y + 1;
- draw(screen, r1, tagcols[BORD], nil, ZP);
- r1.min.y = y + 1;
- r1.max.y = r.max.y;
- y = textresize(&w->body, r1);
+ y = textresize(&w->body, r1, keepextra);
w->r = r;
w->r.max.y = y;
textscrdraw(&w->body);
+ w->body.all.min.y = oy;
}
w->maxlines = min(w->body.nlines, max(w->maxlines, w->body.maxlines));
return w->r.max.y;
@@ -198,7 +292,8 @@
void
winmousebut(Window *w)
{
- moveto(mousectl, divpt(addpt(w->tag.scrollr.min, w->tag.scrollr.max), 2));
+ moveto(mousectl, addpt(w->tag.scrollr.min,
+ divpt(Pt(Dx(w->tag.scrollr), font->height), 2)));
}
void
@@ -344,11 +439,9 @@
void
winsettag1(Window *w)
{
- int i, j, k, n, bar, dirty;
+ int i, j, k, n, bar, dirty, resize;
Rune *new, *old, *r;
- Image *b;
uint q0, q1;
- Rectangle br;
/* there are races that get us here with stuff in the tag cache, so we take extra care to sync it */
if(w->tag.ncache!=0 || w->tag.file->mod)
@@ -404,7 +497,12 @@
i += 6;
}
}
+ new[i] = 0;
+
+ /* replace tag if the new one is different */
+ resize = 0;
if(runeeq(new, i, old, k) == FALSE){
+ resize = 1;
n = k;
if(n > i)
n = i;
@@ -435,13 +533,11 @@
if(w->tag.q1 > n)
w->tag.q1 = n;
textsetselect(&w->tag, w->tag.q0, w->tag.q1);
- b = button;
- if(!w->isdir && !w->isscratch && (w->body.file->mod || w->body.ncache))
- b = modbutton;
- br.min = w->tag.scrollr.min;
- br.max.x = br.min.x + Dx(b->r);
- br.max.y = br.min.y + Dy(b->r);
- draw(screen, br, b, nil, b->r.min);
+ windrawbutton(w);
+ if(resize){
+ w->tagsafe = 0;
+ winresize(w, w->r, TRUE, TRUE);
+ }
}
void
|