shithub: riscv

Download patch

ref: 74a276d0765df146871381c580256971eed3166e
parent: a67d18ccf157559e23303dc57815402939f2a88e
author: aiju <[email protected]>
date: Thu Aug 14 06:42:39 EDT 2014

spred: command window improvements

--- a/sys/src/cmd/spred/cmdw.c
+++ b/sys/src/cmd/spred/cmdw.c
@@ -69,7 +69,7 @@
 	
 	}
 	frdelete(&w->fr, 0, w->fr.nchars);
-		frinsert(&w->fr, w->runes + w->toprune, w->runes + w->nrunes, 0);
+	frinsert(&w->fr, w->runes + w->toprune, w->runes + w->nrunes, 0);
 	scrollbar(w);
 }
 
@@ -120,6 +120,8 @@
 				cmdscroll(w, 1);
 		}
 	}
+	if(w->opoint > rp)
+		w->opoint += nr;
 	return nr;
 }
 
@@ -137,15 +139,58 @@
 		if(w->toprune >= a)
 			w->toprune = a;
 	}
+	if(a <= w->opoint && w->opoint < b)
+		w->opoint = a;
+	else if(w->opoint >= b)
+		w->opoint -= b -  a;
 }
 
 static void
-cmdkey(Win *w, Rune r)
+setsel(Win *w, int p0, int p1)
 {
+	frdrawsel(&w->fr, frptofchar(&w->fr, w->fr.p0), w->fr.p0, w->fr.p1, 0);
+	w->fr.p0 = p0;
+	w->fr.p1 = p1;
+	frdrawsel(&w->fr, frptofchar(&w->fr, p0), p0, p1, 1);
+}
+
+static void
+cmdline(Win *w)
+{
 	static char buf[4096];
-	char *p;
 	Rune *q;
+	char *p;
 
+	q = w->runes + w->opoint;
+	p = buf;
+	while(q < w->runes + w->nrunes && p < buf + nelem(buf) + 1)
+		p += runetochar(p, q++);
+	*p = 0;
+	w->opoint = w->nrunes;
+	docmd(buf);
+}
+
+static void
+cmdkey(Win *w, Rune r)
+{
+	switch(r){
+	case Kview:
+		cmdscroll(w, 3);
+		return;
+	case Kup:
+		cmdscroll(w, -3);
+		return;
+	case Kleft:
+		if(w->fr.p0 == 0)
+			return;
+		setsel(w, w->fr.p0 - 1, w->fr.p0 - 1);
+		return;
+	case Kright:
+		if(w->toprune + w->fr.p1 == w->nrunes)
+			return;
+		setsel(w, w->fr.p1 + 1, w->fr.p1 + 1);
+		return;
+	}
 	if(w->fr.p0 < w->fr.p1)
 		cmddel(w, w->toprune + w->fr.p0, w->toprune + w->fr.p1);
 	switch(r){
@@ -158,24 +203,111 @@
 		break;
 	case '\n':
 		cmdinsert(w, &r, 1, w->fr.p0 + w->toprune);
-		if(w->toprune + w->fr.p0 == w->nrunes){
-			q = w->runes + w->opoint;
-			p = buf;
-			while(q < w->runes + w->nrunes && p < buf + nelem(buf) + 1)
-				p += runetochar(p, q++);
-			*p = 0;
-			w->opoint = w->nrunes;
-			docmd(buf);
+		if(w->toprune + w->fr.p0 == w->nrunes)
+			cmdline(w);
+		break;
+	default:
+		cmdinsert(w, &r, 1, w->fr.p0 + w->toprune);
+	}
+}
+
+static int
+tosnarf(Win *w, int p0, int p1)
+{
+	int fd;
+	static char buf[512];
+	char *c, *ce;
+	Rune *rp, *re;
+	
+	if(p0 >= p1)
+		return 0;
+	fd = open("/dev/snarf", OWRITE|OTRUNC);
+	if(fd < 0){
+		cmdprint("tosnarf: %r");
+		return -1;
+	}
+	c = buf;
+	ce = buf + sizeof(buf);
+	rp = w->runes + p0;
+	re = w->runes + p1;
+	for(; rp < re; rp++){
+		if(c + UTFmax > ce){
+			write(fd, buf, c - buf);
+			c = buf;
 		}
+		c += runetochar(c, rp);
+	}
+	if(c > buf)
+		write(fd, buf, c - buf);
+	close(fd);
+	return 0;
+}
+
+static int
+fromsnarf(Win *w, int p0)
+{
+	int fd, rc;
+	char *buf, *p;
+	Rune *rbuf, *r;
+	int nc, end;
+	
+	fd = open("/dev/snarf", OREAD);
+	if(fd < 0){
+		cmdprint("fromsnarf: %r");
+		return -1;
+	}
+	buf = nil;
+	nc = 0;
+	for(;;){
+		buf = realloc(buf, nc + 4096);
+		rc = readn(fd, buf + nc, nc + 4096);
+		if(rc <= 0)
+			break;
+		nc += rc;
+		if(rc < 4096)
+			break;
+	}
+	close(fd);
+	rbuf = emalloc(sizeof(Rune) * nc);
+	r = rbuf;
+	for(p = buf; p < buf + nc; r++)
+		p += chartorune(r, p);
+	end = p0 == w->nrunes;
+	cmdinsert(w, rbuf, r - rbuf, p0);
+	if(end && r > rbuf && r[-1] == '\n')
+		cmdline(w);
+	return 0;
+}
+
+static void
+cmdmenu(Win *w, Mousectl *mc)
+{
+	enum {
+		CUT,
+		PASTE,
+		SNARF,
+	};
+	static char *ms[] = {
+		[CUT] "cut",
+		[PASTE] "paste",
+		[SNARF] "snarf",
+		nil,
+	};
+	static Menu m = {ms};
+	
+	switch(menuhit(2, mc, &m, nil)){
+	case CUT:
+		if(tosnarf(w, w->toprune + w->fr.p0, w->toprune + w->fr.p1) >= 0)
+			cmddel(w, w->toprune + w->fr.p0, w->toprune + w->fr.p1);
 		break;
-	case Kview:
-		cmdscroll(w, 3);
+	case SNARF:
+		tosnarf(w, w->toprune + w->fr.p0, w->toprune + w->fr.p1);
 		break;
-	case Kup:
-		cmdscroll(w, -3);
+	case PASTE:
+		if(w->fr.p0 < w->fr.p1)
+			cmddel(w, w->toprune + w->fr.p0, w->toprune + w->fr.p1);
+		fromsnarf(w, w->toprune + w->fr.p0);
 		break;
-	default:
-		cmdinsert(w, &r, 1, w->fr.p0 + w->toprune);
 	}
 }
 
@@ -196,6 +328,7 @@
 	.init = cmdinit,
 	.draw = cmddraw,
 	.click = cmdclick,
+	.menu = cmdmenu,
 	.rmb = cmdrmb,
 	.key = cmdkey,
 	.hexcols = {