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; inw; 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; jnw; 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; inw; 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(q0file->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