shithub: riscv

Download patch

ref: ddc6c1651574ca04fa73984452cdcc3dddb08256
parent: 34f5a8333090c5090e1d0b6ddbaf900d64340eea
author: cinap_lenrek <[email protected]>
date: Mon Apr 17 01:12:07 EDT 2017

vt: implement snarf support

--- a/sys/src/cmd/vt/cons.h
+++ b/sys/src/cmd/vt/cons.h
@@ -8,9 +8,7 @@
 extern Consstate*	consctl(void);
 extern Consstate*	cs;
 
-#define	XMARGIN	5	/* inset from border of layer */
-#define	YMARGIN	5
-#define	INSET	3
+#define	INSET	2
 #define	BUFS	32
 #define	HISTSIZ	4096	/* number of history characters */
 #define BSIZE	1000
@@ -30,8 +28,8 @@
 	TReverse = (1<<3),
 	TInvisible = (1<<4),
 };
-	
 
+#define	button1()	((mouse.buttons & 07)==1)
 #define	button2()	((mouse.buttons & 07)==2)
 #define	button3()	((mouse.buttons & 07)==4)
 
@@ -55,7 +53,7 @@
 
 extern void	emulate(void);
 extern int	host_avail(void);
-extern void	clear(Rectangle);
+extern void	clear(int,int,int,int);
 extern void	newline(void);
 extern int	get_next_char(void);
 extern void	ringbell(void);
@@ -64,8 +62,9 @@
 extern void	backup(int);
 extern void	sendnchars(int, char *);
 extern Point	pt(int, int);
+extern Point	pos(Point);
 extern void	funckey(int);
-extern void	drawstring(Point, Rune*, int);
+extern void	drawstring(Rune*, int, int);
 
 extern int	debug;
 extern int	yscrmin, yscrmax;
--- a/sys/src/cmd/vt/main.c
+++ b/sys/src/cmd/vt/main.c
@@ -47,6 +47,7 @@
 Menu	menu3;
 Rune	*histp;
 Rune	hist[HISTSIZ];
+Rune	*onscreen;
 int	yscrmin, yscrmax;
 int	attr, defattr;
 int	wctlout;
@@ -56,10 +57,12 @@
 Image	*colors[8];
 Image	*hicolors[8];
 Image	*red;
+Image	*green;
 Image	*fgcolor;
 Image	*bgcolor;
 Image	*fgdefault;
 Image	*bgdefault;
+Image	*highlight;
 
 uint rgbacolors[8] = {
 	0x000000FF,	/* black */
@@ -88,6 +91,8 @@
 
 int	NS;
 int	CW;
+int	XMARGIN;
+int	YMARGIN;
 Consstate *cs;
 Mouse	mouse;
 
@@ -119,11 +124,13 @@
 void	set_host(Event *);
 void	bigscroll(void);
 void	readmenu(void);
+void	selection(void);
 void	eresized(int);
 void	resize(void);
 void	send_interrupt(void);
 int	alnum(int);
 void	escapedump(int,uchar *,int);
+Rune*	onscreenp(int, int);
 
 void
 main(int argc, char **argv)
@@ -210,8 +217,10 @@
 	CW = stringwidth(font, "m");
 
 	red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed);
+	green = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DGreen);
 	bordercol = allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xCCCCCCCC);
 	cursback = allocimage(display, Rect(0, 0, CW+1, NS+1), screen->chan, 0, DNofill);
+	highlight = allocimage(display, Rect(0,0,1,1), CHAN1(CAlpha,8), 1, 0x80);
 
 	for(i=0; i<8; i++){
 		colors[i] = allocimage(display, Rect(0,0,1,1), screen->chan, 1,
@@ -234,14 +243,23 @@
 }
 
 void
-clear(Rectangle r)
+clear(int x1, int y1, int x2, int y2)
 {
-	draw(screen, r, bgcolor, nil, ZP);
+	draw(screen, Rpt(pt(x1,y1), pt(x2,y2)), bgcolor, nil, ZP);
+	while(y1 < y2){
+		if(x1 < x2)
+			memset(onscreenp(x1, y1), 0, (x2-x1)*sizeof(Rune));
+		if(x2 > xmax)
+			*onscreenp(xmax+1, y1) = '\n';
+		y1++;
+	}
 }
 
 void
 newline(void)
 {
+	if(x > xmax)
+		*onscreenp(xmax+1, y) = 0;	/* wrap arround, remove hidden newline */
 	nbacklines--;
 	if(y >= yscrmax) {
 		y = yscrmax;
@@ -427,8 +445,12 @@
 		wasblocked = blocked;
 		if(backp)
 			return(0);
-		if(ecanmouse() && (button2() || button3()))
-			readmenu();
+		if(ecanmouse()){
+			if(button1())
+				selection();
+			else if(button2() || button3())
+				readmenu();
+		}
 		if(snarffp) {
 			static Rune lastc = ~0;
 
@@ -535,6 +557,7 @@
 			continue;
 		}
 		curson(wasblocked);	/* turn on cursor while we're waiting */
+		flushimage(display, 1);
 		do {
 			newmouse = 0;
 			switch(eread(blocked ? Emouse|Ekeyboard : 
@@ -541,7 +564,9 @@
 					       Emouse|Ekeyboard|Ehost, &e)) {
 			case Emouse:
 				mouse = e.mouse;
-				if(button2() || button3())
+				if(button1())
+					selection();
+				else if(button2() || button3())
 					readmenu();
 				else if(resize_flag == 0) {
 					/* eresized() is triggered by special mouse event */
@@ -581,8 +606,8 @@
 void
 exportsize(void)
 {
-	putenvint("XPIXELS", Dx(screen->r)-2*XMARGIN);
-	putenvint("YPIXELS", Dy(screen->r)-2*XMARGIN);
+	putenvint("XPIXELS", (xmax+1)*CW);
+	putenvint("YPIXELS", (ymax+1)*NS);
 	putenvint("LINES", ymax+1);
 	putenvint("COLS", xmax+1);
 	putenv("TERM", term);
@@ -595,17 +620,20 @@
 		fprint(2, "can't reattach to window: %r\n");
 		exits("can't reattach to window");
 	}
-	xmax = (Dx(screen->r)-2*XMARGIN)/CW-1;
-	ymax = (Dy(screen->r)-2*YMARGIN)/NS-1;
-	if(xmax == 0 || ymax == 0)
-		exits("window gone");
+	draw(screen, screen->r, bgcolor, nil, ZP);
+	xmax = (Dx(screen->r) - 2*INSET)/CW-1;
+	ymax = (Dy(screen->r) - 2*INSET)/NS-1;
+	XMARGIN = (Dx(screen->r) - (xmax+1)*CW) / 2;
+	YMARGIN = (Dy(screen->r) - (ymax+1)*NS) / 2;
 	x = 0;
 	y = 0;
 	yscrmin = 0;
 	yscrmax = ymax;
+	free(onscreen);
+	onscreen = mallocz((ymax+1)*(xmax+2)*sizeof(Rune), 1);
 	olines = 0;
 	exportsize();
-	clear(screen->r);
+	clear(0,0,xmax+1,ymax+1);
 	if(resize_flag > 1)
 		backup(backc);
 	resize_flag = 0;
@@ -622,22 +650,103 @@
 		ymax = ht-1;
 	if(wid != -1)
 		xmax = wid-1;
-
 	r.min = screen->r.min;
-	r.max = addpt(screen->r.min,
-			Pt((xmax+1)*CW+2*XMARGIN+2*INSET,
-				(ymax+1)*NS+2*YMARGIN+2*INSET));
+	r.max = addpt(screen->r.min, Pt((xmax+1)*CW+2*INSET, (ymax+1)*NS+2*INSET));
 	fd = open("/dev/wctl", OWRITE);
-	if(fd < 0 || fprint(fd, "resize -dx %d -dy %d\n", Dx(r)+2*Borderwidth,
-	    Dy(r)+2*Borderwidth) < 0){
-		border(screen, r, INSET, bordercol, ZP);
-		exportsize();
-	}
+	if(fd < 0 || fprint(fd, "resize -dx %d -dy %d\n", Dx(r)+2*Borderwidth, Dy(r)+2*Borderwidth) < 0)
+		resize();
 	if(fd >= 0)
 		close(fd);
 }
 
 void
+sendsnarf(void)
+{
+	if(snarffp == nil)
+		snarffp = Bopen("/dev/snarf",OREAD);
+}
+
+int
+writesnarf(Rune *s, Rune *e)
+{
+	Biobuf *b;
+	int z, p;
+
+	if(s >= e)
+		return 0;
+	b = Bopen("/dev/snarf", OWRITE|OTRUNC);
+	if(b == nil)
+		return 0;
+	for(z = p = 0; s < e; s++){
+		if(*s){
+			if(*s == '\n')
+				z = p = 0;
+			else if(p++ == 0){
+				while(z-- > 0) Bputc(b, ' ');
+			}
+			Bputrune(b, *s);
+		} else {
+			z++;
+		}
+	}
+	Bterm(b);
+	return 1;
+}
+
+Rectangle
+drawselection(Rectangle r, Rectangle d, Image *color)
+{
+	while(r.min.y < r.max.y){
+		d = drawselection(Rect(r.min.x, r.min.y, xmax+1, r.min.y), d, color);
+		r.min.x = 0;
+		r.min.y++;
+	}
+	if(r.min.x >= r.max.x)
+		return d;
+	r = Rpt(pt(r.min.x, r.min.y), pt(r.max.x, r.max.y+1));
+	draw(screen, r, color, highlight, r.min);
+	combinerect(&d, r);
+	return d;
+}
+
+void
+selection(void)
+{
+	Point p, q;
+	Rectangle r, d;
+	Image *backup;
+
+	backup = allocimage(display, screen->r, screen->chan, 0, DNofill);
+	draw(backup, backup->r, screen, nil, backup->r.min);
+	p = pos(mouse.xy);
+	do {
+		q = pos(mouse.xy);
+		if(onscreenp(p.x, p.y) > onscreenp(q.x, q.y)){
+			r.min = q;
+			r.max = p;
+		} else {
+			r.min = p;
+			r.max = q;
+		}
+		if(r.max.y > ymax)
+			r.max.x = 0;
+		d = drawselection(r, ZR, red);
+		flushimage(display, 1);
+		mouse = emouse();
+		draw(screen, d, backup, nil, d.min);
+	} while(button1());
+	if((mouse.buttons & 07) == 5)
+		sendsnarf();
+	else if(writesnarf(onscreenp(r.min.x, r.min.y), onscreenp(r.max.x, r.max.y))){
+		d = drawselection(r, ZR, green);
+		flushimage(display, 1);
+		sleep(200);
+		draw(screen, d, backup, nil, d.min);
+	}
+	freeimage(backup);
+}
+
+void
 readmenu(void)
 {
 	if(button3()) {
@@ -693,7 +802,7 @@
 		return;
 
 	case 4:		/* send the snarf buffer */
-		snarffp = Bopen("/dev/snarf",OREAD);
+		sendsnarf();
 		return;
 
 	case 5:		/* pause and clear at end of screen */
@@ -745,12 +854,36 @@
 	return addpt(screen->r.min, Pt(x*CW+XMARGIN,y*NS+YMARGIN));
 }
 
+Point
+pos(Point pt)
+{
+	pt.x -= screen->r.min.x + XMARGIN;
+	pt.y -= screen->r.min.y + YMARGIN;
+	pt.x /= CW;
+	pt.y /= NS;
+	if(pt.x < 0)
+		pt.x = 0;
+	else if(pt.x > xmax+1)
+		pt.x = xmax+1;
+	if(pt.y < 0)
+		pt.y = 0;
+	else if(pt.y > ymax+1)
+		pt.y = ymax+1;
+	return pt;
+}
+
+Rune*
+onscreenp(int x, int y)
+{
+	return onscreen + (y*(xmax+2) + x);
+}
+
 void
 scroll(int sy, int ly, int dy, int cy)	/* source, limit, dest, which line to clear */
 {
+	memmove(onscreenp(0, dy), onscreenp(0, sy), (ly-sy)*(xmax+2)*sizeof(Rune));
 	draw(screen, Rpt(pt(0, dy), pt(xmax+1, dy+ly-sy)), screen, nil, pt(0, sy));
-	clear(Rpt(pt(0, cy), pt(xmax+1, cy+1)));
-	flushimage(display, 1);
+	clear(0, cy, xmax+1, cy+1);
 }
 
 void
@@ -761,16 +894,16 @@
 	if(x == 0 && y == 0)
 		return;
 	if(y < half) {
-		clear(Rpt(pt(0,0),pt(xmax+1,ymax+1)));
+		clear(0, 0, xmax+1, ymax+1);
 		x = y = 0;
 		return;
 	}
 	draw(screen, Rpt(pt(0, 0), pt(xmax+1, ymax+1)), screen, nil, pt(0, half));
-	clear(Rpt(pt(0,y-half+1),pt(xmax+1,ymax+1)));
+	memmove(onscreenp(0, 0), onscreenp(0, half), (ymax-half+1)*(xmax+2)*sizeof(Rune));
+	clear(0, y-half+1, xmax+1, ymax+1);
 	y -= half;
 	if(olines)
 		olines -= half;
-	flushimage(display, 1);
 }
 
 int
@@ -888,11 +1021,12 @@
 
 
 void
-drawstring(Point p, Rune *str, int attr)
+drawstring(Rune *str, int n, int attr)
 {
 	int i;
 	Image *txt, *bg, *tmp;
-	
+	Point p;
+
 	txt = fgcolor;
 	bg = bgcolor;
 	if(attr & TReverse){
@@ -905,7 +1039,8 @@
 			if(txt == colors[i])
 				txt = hicolors[i];
 	}
-
+	p = pt(x, y);
 	draw(screen, Rpt(p, addpt(p, runestringsize(font, str))), bg, nil, p);
 	runestring(screen, p, txt, ZP, font, str);
+	memmove(onscreenp(x, y), str, n*sizeof(Rune));
 }
--- a/sys/src/cmd/vt/vt.c
+++ b/sys/src/cmd/vt/vt.c
@@ -687,21 +687,21 @@
 							 * operand 2:  whole screen.
 							 */
 							case 2:
-								clear(Rpt(pt(0, 0), pt(xmax+1, ymax+1)));
+								clear(0, 0, xmax+1, ymax+1);
 								break;
 							/*
 							 * operand 1: start of screen to active position, inclusive.
 							 */
 							case 1:
-								clear(Rpt(pt(0, 0), pt(xmax+1, y)));
-								clear(Rpt(pt(0, y), pt(x+1, y+1)));
+								clear(0, 0, xmax+1, y);
+								clear(0, y, x+1, y+1);
 								break;
 							/*
 							 * Default:  active position to end of screen, inclusive.
 							 */
 							default:
-								clear(Rpt(pt(x, y), pt(xmax+1, y+1)));
-								clear(Rpt(pt(0, y+1), pt(xmax+1, ymax+1)));
+								clear(x, y, xmax+1, y+1);
+								clear(0, y+1, xmax+1, ymax+1);
 								break;
 						}
 						break;
@@ -715,19 +715,19 @@
 							 * operand 2: whole line.
 							 */
 							case 2:
-								clear(Rpt(pt(0, y), pt(xmax+1, y+1)));
+								clear(0, y, xmax+1, y+1);
 								break;
 							/*
 							 * operand 1: start of line to active position, inclusive.
 							 */
 							case 1:
-								clear(Rpt(pt(0, y), pt(x+1, y+1)));
+								clear(0, y, x+1, y+1);
 								break;
 							/*
 							 * Default: active position to end of line, inclusive.
 							 */
 							default:
-								clear(Rpt(pt(x, y), pt(xmax+1, y+1)));
+								clear(x, y, xmax+1, y+1);
 								break;
 						}
 						break;
@@ -739,7 +739,7 @@
 						fixops(operand);
 						i = x + operand[0];
 						draw(screen, Rpt(pt(x, y), pt(xmax+1, y+1)), screen, nil, pt(i, y));
-						clear(Rpt(pt(xmax-operand[0], y), pt(xmax+1, y+1)));
+						clear(xmax-operand[0], y, xmax+1, y+1);
 						break;
 
 					/*
@@ -749,7 +749,7 @@
 						fixops(operand);
 						i = x + operand[0];
 						draw(screen, Rpt(pt(i, y), pt(xmax+1, y+1)), screen, nil, pt(x, y));
-						clear(Rpt(pt(x, y), pt(i, y+1)));
+						clear(x, y, i, y+1);
 						break;
 
 
@@ -759,7 +759,7 @@
 					case 'X':
 						fixops(operand);
 						i = x + operand[0];
-						clear(Rpt(pt(x, y), pt(i, y+1)));
+						clear(x, y, i, y+1);
 						break;
 
 					/*
@@ -844,8 +844,8 @@
 			/* line wrap */
 			if (x > xmax){
 				if(wraparound){
-					x = 0;
 					newline();
+					x = 0;
 				}else{
 					continue;
 				}
@@ -858,7 +858,7 @@
 				c = 0;
 			}
 			buf[n] = 0;
-			drawstring(pt(x, y), buf, attr);
+			drawstring(buf, n, attr);
 			x += n;
 			peekc = c;
 			break;