9front - general discussion about 9front
 help / color / mirror / Atom feed
* vt selection patch
@ 2018-09-03  8:33 Ori Bernstein
  0 siblings, 0 replies; only message in thread
From: Ori Bernstein @ 2018-09-03  8:33 UTC (permalink / raw)
  To: 9front

I finally got around to taking another shot at this vt patch. This change
gets rid of implicit snarfing, and instead makes selection the way you
select text for snarfing or plumbing. Select, then use a menu entry.

It would probably be nice to have double click to expand the selection,
rio-style, along with plumbing implicitly taking the current word, but
that can be a separate patch.

This change also punts on scrolling for simplicity -- it clears the
selection instead of trying to handle the cases where the selection
goes offscreen.

diff -r 3d56a0fc4645 sys/src/cmd/vt/main.c
--- a/sys/src/cmd/vt/main.c	Fri Aug 31 22:39:46 2018 +0200
+++ b/sys/src/cmd/vt/main.c	Mon Sep 03 00:35:16 2018 -0700
@@ -11,25 +11,48 @@
 #include <bio.h>
 #include <mouse.h>
 #include <keyboard.h>
+#include <plumb.h>
+
+enum menuact2{
+	Mbackup,
+	Mforward,
+	Mreset,
+	Mclear,
+	Mpaste,
+	Msnarf,
+	Mplumb,
+	Mpage,
+};
+
+enum menuact3{
+	M24x80,
+	Mcrnl,
+	Mnl,
+	Mraw,
+	Mblocksel,
+	Mexit,
+};
 
 char	*menutext2[] = {
-	"backup",
-	"forward",
-	"reset",
-	"clear",
-	"paste",
-	"page",
-	0
+	[Mbackup]	"backup",
+	[Mforward]	"forward",
+	[Mreset]	"reset",
+	[Mclear]	"clear",
+	[Mpaste]	"paste",
+	[Msnarf]	"snarf",
+	[Mplumb]	"plumb",
+	[Mpage]		"page",
+	nil
 };
 
 char	*menutext3[] = {
-	"24x80",
-	"crnl",
-	"nl",
-	"raw",
-	"blocksel",
-	"exit",
-	0
+	[M24x80]	"24x80",
+	[Mcrnl]		"crnl",
+	[Mnl]		"nl",
+	[Mraw]		"raw",
+	[Mblocksel]	"blocksel",
+	[Mexit]		"exit",
+	nil
 };
 
 /* variables associated with the screen */
@@ -60,6 +83,9 @@
 #define onscreena(x, y) &onscreenabuf[((y)*(xmax+2) + (x))]
 #define onscreenc(x, y) &onscreencbuf[((y)*(xmax+2) + (x))]
 
+#define MIN(a, b)	(((a) < (b)) ? (a) : (b))
+#define MAX(a, b)	(((a) > (b)) ? (a) : (b))
+
 uchar	*screenchangebuf;
 uint	scrolloff;
 
@@ -68,6 +94,8 @@
 int	yscrmin, yscrmax;
 int	attr, defattr;
 
+Rectangle selrect;
+
 Image	*cursorsave;
 Image	*bordercol;
 Image	*colors[8];
@@ -76,6 +104,8 @@
 Image	*green;
 Image	*fgcolor;
 Image	*bgcolor;
+Image	*fgselected;
+Image	*bgselected;
 Image	*highlight;
 
 uint rgbacolors[8] = {
@@ -138,11 +168,15 @@
 void	bigscroll(void);
 void	readmenu(void);
 void	selection(void);
+int	selected(int, int);
 void	resize(void);
 void	drawcursor(void);
 void	send_interrupt(void);
 int	alnum(int);
 void	escapedump(int,uchar *,int);
+void	paste(void);
+void	snarfsel(void);
+void	plumbsel(void);
 
 static Channel *pidchan;
 
@@ -296,6 +330,8 @@
 	}
 	bgcolor = (blkbg? display->black: display->white);
 	fgcolor = (blkbg? display->white: display->black);
+	bgselected = allocimage(display, Rect(0,0,1,1), CMAP8, 1, blkbg ? 0x333333FF : 0xCCCCCCFF);
+	fgselected = allocimage(display, Rect(0,0,1,1), CMAP8, 1, blkbg ? 0xCCCCCCFF : 0x333333FF);;
 	resize();
 
 	pidchan = chancreate(sizeof(int), 0);
@@ -306,8 +342,10 @@
 }
 
 Image*
-bgcol(int a, int c)
+bgcol(int a, int c, int sel)
 {
+	if(sel)
+		return bgselected;
 	if(nocolor || (c & (1<<0)) == 0){
 		if(a & TReverse)
 			return fgcolor;
@@ -319,8 +357,10 @@
 }
 
 Image*
-fgcol(int a, int c)
+fgcol(int a, int c, int sel)
 {
+	if(sel)
+		return fgselected;
 	if(nocolor || (c & (1<<4)) == 0){
 		if(a & TReverse)
 			return bgcolor;
@@ -366,8 +406,8 @@
 		for(x = 0; x <= xmax; x += n){
 			cp = onscreenc(x, y);
 			ap = onscreena(x, y);
-			c = bgcol(*ap, *cp);
-			for(n = 1; x+n <= xmax && bgcol(ap[n], cp[n]) == c; n++)
+			c = bgcol(*ap, *cp, selected(x, y));
+			for(n = 1; x+n <= xmax && bgcol(ap[n], cp[n], selected(x + n, y)) == c; n++)
 				;
 			draw(screen, Rpt(pt(x, y), pt(x+n, y+1)), c, nil, ZP);
 		}
@@ -381,8 +421,8 @@
 			}
 			ap = onscreena(x, y);
 			cp = onscreenc(x, y);
-			c = fgcol(*ap, *cp);
-			for(n = 1; x+n <= xmax && rp[n] != 0 && fgcol(ap[n], cp[n]) == c
+			c = fgcol(*ap, *cp, selected(x, y));
+			for(n = 1; x+n <= xmax && rp[n] != 0 && fgcol(ap[n], cp[n], selected(x + n, y)) == c
 			&& ((ap[n] ^ *ap) & TUnderline) == 0; n++)
 				;
 			p = pt(x, y);
@@ -451,7 +491,7 @@
 	nbacklines--;
 	if(y >= yscrmax) {
 		y = yscrmax;
-		if(pagemode && olines >= yscrmax) {
+		if(pagemode && olines >= yscrmax){
 			blocked = 1;
 			return;
 		}
@@ -472,7 +512,7 @@
 	while(c <= 0) {
 		if(backp) {
 			c = *backp;
-			if(c && nbacklines >= 0) {
+			if(c && nbacklines >= 0){
 				backp++;
 				if(backp >= &hist[HISTSIZ])
 					backp = hist;
@@ -876,108 +916,138 @@
 	werrstr("");		/* clear spurious error messages */
 }
 
+Rune *
+selrange(Rune *r, int x0, int y0, int x1, int y1)
+{
+	Rune *p, *sr, *er;
+
+	p = r;
+	sr = onscreenr(x0, y0);
+	er = onscreenr(x1, y1);
+	for(; sr != er; sr++)
+		if(*sr)
+			*p++ = *sr;
+	*p = 0;
+	return p;
+}
+
+Rune*
+selrunes(void)
+{
+	Rune *r, *p;
+	int sz;
+	int y;
+
+	/* generous, but we can spare a few bytes for a few microseconds */
+	sz = xmax*(selrect.max.y - selrect.min.y + 2) + 1;
+	r = p = malloc(sizeof(Rune)*sz + 1);
+	if(!r)
+		return nil;
+	if(blocksel){
+		for(y = selrect.min.y; y <= selrect.max.y; y++){
+			p = selrange(p, selrect.min.x, y, selrect.max.x, y);
+			*p++ = '\n';
+		}
+		*p = 0;
+	}
+	else
+		selrange(r, selrect.min.x, selrect.min.y, selrect.max.x, selrect.max.y);
+	return r;
+}
+
 void
-sendsnarf(void)
+snarfsel(void)
+{
+	Biobuf *b;
+	Rune *r;
+
+	b = Bopen("/dev/snarf", OWRITE|OTRUNC);
+	if(b == nil)
+		return;
+	r = selrunes();
+	if(!r)
+		return;
+	Bprint(b, "%S", r);
+	Bterm(b);
+	free(r);
+
+}
+
+void
+plumbsel(void)
+{
+	char buf[1024], wdir[512];
+	Rune *r;
+	int plumb;
+
+	print("plumb\n");
+	if(getwd(wdir, sizeof wdir) == 0)
+		return;
+	if((r = selrunes()) == nil)
+		return;
+	print("wdir: %s, runes: %S\n", wdir, r);
+	if((plumb = plumbopen("send", OWRITE)) != -1){
+		snprint(buf, sizeof buf, "%S", r);
+		print("buf: '%s'\n", buf);
+		plumbsendtext(plumb, "vt", nil, wdir, buf);
+	}
+	close(plumb);
+	free(r);
+}
+
+void
+paste(void)
 {
 	if(snarffp == nil)
 		snarffp = Bopen("/dev/snarf",OREAD);
 }
 
 void
-seputrunes(Biobuf *b, Rune *s, Rune *e)
+selection(void)
 {
-	int z, p;
+	Point p, q;
+	int y;
 
-	if(s >= e)
-		return;
-	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++;
-		}
+
+	p = pos(mc->xy);
+	do{
+		/* Clear the old selection rectangle. */
+		for(y = selrect.min.y; y <= selrect.max.y; y++)
+			screenchange(y) = 1;
+		q = pos(mc->xy);
+		selrect.min.x = MIN(p.x, q.x);
+		selrect.min.y = MIN(p.y, q.y);
+		selrect.max.x = MAX(p.x, q.x);
+		selrect.max.y = MAX(p.y, q.y);
+		/* And mark the new one as changed. */
+		for(y = selrect.min.y; y <= selrect.max.y; y++)
+			screenchange(y) = 1;
+		readmouse(mc);
+		drawscreen();
+	} while(button1());
+	switch(mc->buttons & 0x7){
+	case 3:	snarfsel();	break;
+	case 5:	paste();	break;
 	}
 }
 
 int
-snarfrect(Rectangle r)
+selected(int x, int y)
 {
-	Biobuf *b;
+	int s;
 
-	b = Bopen("/dev/snarf", OWRITE|OTRUNC);
-	if(b == nil)
-		return 0;
-	if(blocksel){
-		while(r.min.y <= r.max.y){
-			seputrunes(b, onscreenr(r.min.x, r.min.y), onscreenr(r.max.x, r.min.y));
-			Bputrune(b, L'\n');
-			r.min.y++;
-		}
-	} else {
-		seputrunes(b, onscreenr(r.min.x, r.min.y), onscreenr(r.max.x, r.max.y));
+	s = y >= selrect.min.y && y <= selrect.max.y;
+	if (blocksel)
+		s = s && x >= selrect.min.x && x < selrect.max.x;
+	else{
+		if(y == selrect.min.y)
+			s = s && x >= selrect.min.x;
+		if(y == selrect.max.y)
+			s = s && x < selrect.max.x;
+		if(y > selrect.min.y && y < selrect.max.y)
+			s = 1;
 	}
-	Bterm(b);
-	return 1;
-}
-
-Rectangle
-drawselection(Rectangle r, Rectangle d, Image *color)
-{
-	if(!blocksel){
-		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(mc->xy);
-	do {
-		q = pos(mc->xy);
-		if(onscreenr(p.x, p.y) > onscreenr(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);
-		readmouse(mc);
-		draw(screen, d, backup, nil, d.min);
-	} while(button1());
-	if((mc->buttons & 07) == 5)
-		sendsnarf();
-	else if(snarfrect(r)){
-		d = drawselection(r, ZR, green);
-		flushimage(display, 1);
-		sleep(200);
-		draw(screen, d, backup, nil, d.min);
-	}
-	freeimage(backup);
+	return s;
 }
 
 void
@@ -990,39 +1060,39 @@
 		menu3.item[4] = blocksel ? "linesel" : "blocksel";
 
 		switch(menuhit(3, mc, &menu3, nil)) {
-		case 0:		/* 24x80 */
+		case M24x80:		/* 24x80 */
 			setdim(24, 80);
 			return;
-		case 1:		/* newline after cr? */
+		case Mcrnl:		/* newline after cr? */
 			ttystate[cs->raw].crnl = !ttystate[cs->raw].crnl;
 			return;
-		case 2:		/* cr after newline? */
+		case Mnl:		/* cr after newline? */
 			ttystate[cs->raw].nlcr = !ttystate[cs->raw].nlcr;
 			return;
-		case 3:		/* switch raw mode */
+		case Mraw:		/* switch raw mode */
 			cs->raw = !cs->raw;
 			return;
-		case 4:
+		case Mblocksel:
 			blocksel = !blocksel;
+			selrect = ZR;
 			return;
-		case 5:
+		case Mexit:
 			exits(0);
 		}
 		return;
 	}
 
-	menu2.item[5] = pagemode? "scroll": "page";
+	menu2.item[Mpage] = pagemode? "scroll": "page";
 
 	switch(menuhit(2, mc, &menu2, nil)) {
-
-	case 0:		/* back up */
-		if(atend == 0) {
+	case Mbackup:		/* back up */
+		if(atend == 0){
 			backc++;
 			backup(backc);
 		}
 		return;
 
-	case 1:		/* move forward */
+	case Mforward:		/* move forward */
 		backc--;
 		if(backc >= 0)
 			backup(backc);
@@ -1030,20 +1100,28 @@
 			backc = 0;
 		return;
 
-	case 2:		/* reset */
+	case Mreset:		/* reset */
 		backc = 0;
 		backup(0);
 		return;
 
-	case 3:		/* clear screen */
+	case Mclear:		/* clear screen */
 		resize_flag = 1;
 		return;
 
-	case 4:		/* send the snarf buffer */
-		sendsnarf();
+	case Mpaste:		/* paste the snarf buffer */
+		paste();
 		return;
 
-	case 5:		/* pause and clear at end of screen */
+	case Msnarf:		/* send the snarf buffer */
+		snarfsel();
+		return;
+
+	case Mplumb:
+		plumbsel();
+		return;
+
+	case Mpage:		/* pause and clear at end of screen */
 		pagemode = 1-pagemode;
 		if(blocked && !pagemode) {
 			resize_flag = 1;
@@ -1060,6 +1138,7 @@
 	int n;
 
 	resize_flag = 1;
+	selrect = ZR; /* punt for now: scrolling clears selection */
 	if(count == 0 && !pagemode) {
 		n = ymax;
 		nbacklines = HISTSIZ;	/* make sure we scroll to the very end */
@@ -1135,6 +1214,7 @@
 	if(sy < 0 || sy > ymax || dy < 0 || dy > ymax)
 		return;
 
+	selrect = ZR;
 	n = ly - sy;
 	if(sy + n > ymax+1)
 		n = ymax+1 - sy;

-- 
    Ori Bernstein


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2018-09-03  8:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-09-03  8:33 vt selection patch Ori Bernstein

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).