shithub: riscv

Download patch

ref: ba7c22f781dafd30d0b97179c941476639022285
parent: 12ecb3e568312f881bfcb22bef71d5a00cfab196
author: mveety <mveety@gmail.com>
date: Wed Aug 28 19:01:23 EDT 2013

Added the p9p acme patch the allows multiline tags (thanks rsc and lf94).

--- a/sys/src/cmd/acme/dat.h
+++ b/sys/src/cmd/acme/dat.h
@@ -191,6 +191,7 @@
 	int		ncachealloc;
 	Rune	*cache;
 	int	nofill;
+	int	needundo;
 };
 
 uint		textbacknl(Text*, uint, uint);
@@ -235,6 +236,8 @@
 	uchar	filemenu;
 	uchar	dirty;
 	uchar	autoindent;
+	uchar	showdel;
+	uint		noredraw;
 	int		id;
 	Range	addr;
 	Range	limit;
@@ -263,6 +266,10 @@
 	int		utflastqid;
 	int		utflastboff;
 	int		utflastq;
+	int		tagsafe;		/* taglines is correct */
+	int		tagexpand;
+	int		taglines;
+	Rectangle	tagtop;
 };
 
 void	wininit(Window*, Window*, Rectangle);
--- a/sys/src/cmd/acme/wind.c
+++ b/sys/src/cmd/acme/wind.c
@@ -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);
@@ -32,6 +34,8 @@
 	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;
 	incref(&reffont);
 	f = fileaddtext(nil, &w->tag);
 	textinit(&w->tag, f, r1, &reffont, tagcols);
@@ -48,7 +52,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;
@@ -77,6 +81,7 @@
 	w->autoindent = globalautoindent;
 	if(clone){
 		w->dirty = clone->dirty;
+		w->autoindent = clone->autoindent;
 		textsetselect(&w->body, clone->body.q0, clone->body.q1);
 		winsettag(w);
 		w->autoindent = clone->autoindent;
@@ -84,18 +89,106 @@
 }
 
 int
+delrunepos(Window *w)
+{
+	int n;
+	Rune rune;
+	
+	for(n=0; n<w->tag.file->nc; n++) {
+		bufread(w->tag.file, n, &rune, 1);
+		if(rune == ' ')
+			break;
+	}
+	n += 2;
+	if(n >= w->tag.file->nc)
+		return -1;
+	return n;
+}
+
+void
+movetodel(Window *w)
+{
+	int n;
+	
+	n = delrunepos(w);
+	if(n < 0)
+		return;
+	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->noredraw = 1;
+	textresize(&w->tag, r);
+	w->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)
 {
+	int oy, 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);
+
+	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(!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);
+	}
+
 	y = r1.max.y;
 	if(!safe || !eqrect(w->tag.r, r1)){
-		y = textresize(&w->tag, r1);
+		textresize(&w->tag, r1);
+		y = w->tag.r.max.y;
 		b = button;
 		if(w->body.file->mod && !w->isdir && !w->isscratch)
 			b = modbutton;
@@ -103,26 +196,42 @@
 		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);
+
+		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 */
+		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);
 		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;
@@ -170,7 +279,7 @@
 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
@@ -316,7 +425,7 @@
 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;
@@ -376,6 +485,9 @@
 			i += 6;
 		}
 	}
+
+	new[i] = 0;
+	/* replace tag if the new one is different */
 	if(runeeq(new, i, old, k) == FALSE){
 		n = k;
 		if(n > i)
@@ -414,6 +526,9 @@
 	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);
+
+	w->tagsafe = 0;
+	winresize(w, w->r, TRUE);
 }
 
 void
@@ -557,7 +672,7 @@
 	if(b == nil)
 		error("vsmprint failed");
 	n = strlen(b);
-	w->events = realloc(w->events, w->nevents+1+n);
+	w->events = erealloc(w->events, w->nevents+1+n);
 	w->events[w->nevents++] = w->owner;
 	memmove(w->events+w->nevents, b, n);
 	free(b);
--