vt: implement snarf support

This commit is contained in:
cinap_lenrek 2017-04-17 05:12:07 +02:00
parent 34f5a83330
commit ddc6c16515
3 changed files with 183 additions and 49 deletions

View file

@ -8,9 +8,7 @@ struct Consstate{
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 @@ enum {
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 char* term;
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 scroll(int,int,int,int);
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;

View file

@ -47,6 +47,7 @@ Menu menu2;
Menu menu3;
Rune *histp;
Rune hist[HISTSIZ];
Rune *onscreen;
int yscrmin, yscrmax;
int attr, defattr;
int wctlout;
@ -56,10 +57,12 @@ Image *cursback;
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 @@ struct ttystate ttystate[2] = { {0, 1}, {0, 1} };
int NS;
int CW;
int XMARGIN;
int YMARGIN;
Consstate *cs;
Mouse mouse;
@ -119,11 +124,13 @@ void set_input(char *);
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 @@ initialize(int argc, char **argv)
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 @@ initialize(int argc, char **argv)
}
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 @@ waitchar(void)
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,13 +557,16 @@ waitchar(void)
continue;
}
curson(wasblocked); /* turn on cursor while we're waiting */
flushimage(display, 1);
do {
newmouse = 0;
switch(eread(blocked ? Emouse|Ekeyboard :
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 @@ putenvint(char *name, int x)
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 @@ resize(void)
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,21 +650,102 @@ setdim(int ht, int wid)
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)
{
@ -693,7 +802,7 @@ readmenu(void)
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 @@ pt(int x, int y)
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 @@ bigscroll(void) /* scroll up half a page */
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 @@ funckey(int key)
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 @@ drawstring(Point p, Rune *str, int attr)
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));
}

View file

@ -687,21 +687,21 @@ print("resetterminal\n");
* 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 @@ print("resetterminal\n");
* 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 @@ print("resetterminal\n");
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 @@ print("resetterminal\n");
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 @@ print("resetterminal\n");
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 @@ Default:
/* line wrap */
if (x > xmax){
if(wraparound){
x = 0;
newline();
x = 0;
}else{
continue;
}
@ -858,7 +858,7 @@ Default:
c = 0;
}
buf[n] = 0;
drawstring(pt(x, y), buf, attr);
drawstring(buf, n, attr);
x += n;
peekc = c;
break;