From: Ori Bernstein <ori@eigenstate.org>
To: 9front@9front.org
Subject: vt selection patch
Date: Mon, 3 Sep 2018 01:33:43 -0700 [thread overview]
Message-ID: <20180903013343.ba43a69ca7bc0ca8057f1d7c@eigenstate.org> (raw)
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
reply other threads:[~2018-09-03 8:33 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180903013343.ba43a69ca7bc0ca8057f1d7c@eigenstate.org \
--to=ori@eigenstate.org \
--cc=9front@9front.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).