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;