Implement rectangular mouse selection.
Thanks Alexander Sedov <alex0player@gmail.com>!
This commit is contained in:
		
							parent
							
								
									e5295629cd
								
							
						
					
					
						commit
						3865e9eaaf
					
				
					 2 changed files with 66 additions and 14 deletions
				
			
		
							
								
								
									
										12
									
								
								config.def.h
									
										
									
									
									
								
							
							
						
						
									
										12
									
								
								config.def.h
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -305,3 +305,15 @@ static Key key[] = {
 | 
			
		|||
	{ XK_F35,           XK_NO_MOD,      "\033[23;5~",    0,    0,    0},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Selection types' masks.
 | 
			
		||||
 * Use the same masks as usual.
 | 
			
		||||
 * Button1Mask is always unset, to make masks match between ButtonPress.
 | 
			
		||||
 * ButtonRelease and MotionNotify.
 | 
			
		||||
 * If no match is found, regular selection is used.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
static uint selmasks[] = {
 | 
			
		||||
	[SEL_RECTANGULAR] = Mod1Mask,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										68
									
								
								st.c
									
										
									
									
									
								
							
							
						
						
									
										68
									
								
								st.c
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -137,6 +137,11 @@ enum window_state {
 | 
			
		|||
	WIN_FOCUSED = 4
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum selection_type {
 | 
			
		||||
	SEL_REGULAR = 1,
 | 
			
		||||
	SEL_RECTANGULAR = 2
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* bit macro */
 | 
			
		||||
#undef B0
 | 
			
		||||
enum { B0=1, B1=2, B2=4, B3=8, B4=16, B5=32, B6=64, B7=128 };
 | 
			
		||||
| 
						 | 
				
			
			@ -234,6 +239,7 @@ typedef struct {
 | 
			
		|||
/* TODO: use better name for vars... */
 | 
			
		||||
typedef struct {
 | 
			
		||||
	int mode;
 | 
			
		||||
	int type;
 | 
			
		||||
	int bx, by;
 | 
			
		||||
	int ex, ey;
 | 
			
		||||
	struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -651,10 +657,23 @@ selected(int x, int y) {
 | 
			
		|||
			|| (y == sel.e.y && x <= sel.e.x))
 | 
			
		||||
			|| (y == sel.b.y && x >= sel.b.x
 | 
			
		||||
				&& (x <= sel.e.x || sel.b.y != sel.e.y));
 | 
			
		||||
	switch(sel.type) {
 | 
			
		||||
	case SEL_REGULAR:
 | 
			
		||||
		return ((sel.b.y < y && y < sel.e.y)
 | 
			
		||||
			|| (y == sel.e.y && x <= sel.e.x))
 | 
			
		||||
			|| (y == sel.b.y && x >= sel.b.x
 | 
			
		||||
				&& (x <= sel.e.x || sel.b.y != sel.e.y));
 | 
			
		||||
	case SEL_RECTANGULAR:
 | 
			
		||||
		return ((sel.b.y <= y && y <= sel.e.y)
 | 
			
		||||
			&& (sel.b.x <= x && x <= sel.e.x));
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
getbuttoninfo(XEvent *e) {
 | 
			
		||||
	int type;
 | 
			
		||||
	uint state = e->xbutton.state &~Button1Mask;
 | 
			
		||||
 | 
			
		||||
	sel.alt = IS_SET(MODE_ALTSCREEN);
 | 
			
		||||
 | 
			
		||||
	sel.ex = x2col(e->xbutton.x);
 | 
			
		||||
| 
						 | 
				
			
			@ -664,6 +683,14 @@ getbuttoninfo(XEvent *e) {
 | 
			
		|||
	sel.b.y = MIN(sel.by, sel.ey);
 | 
			
		||||
	sel.e.x = sel.by < sel.ey ? sel.ex : sel.bx;
 | 
			
		||||
	sel.e.y = MAX(sel.by, sel.ey);
 | 
			
		||||
 | 
			
		||||
	sel.type = SEL_REGULAR;
 | 
			
		||||
	for(type = 1; type < LEN(selmasks); ++type) {
 | 
			
		||||
		if(match(selmasks[type], state)) {
 | 
			
		||||
			sel.type = type;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
| 
						 | 
				
			
			@ -724,6 +751,7 @@ bpress(XEvent *e) {
 | 
			
		|||
			draw();
 | 
			
		||||
		}
 | 
			
		||||
		sel.mode = 1;
 | 
			
		||||
		sel.type = SEL_REGULAR;
 | 
			
		||||
		sel.ex = sel.bx = x2col(e->xbutton.x);
 | 
			
		||||
		sel.ey = sel.by = y2row(e->xbutton.y);
 | 
			
		||||
	} else if(e->xbutton.button == Button4) {
 | 
			
		||||
| 
						 | 
				
			
			@ -746,7 +774,8 @@ selcopy(void) {
 | 
			
		|||
		ptr = str = xmalloc(bufsize);
 | 
			
		||||
 | 
			
		||||
		/* append every set & selected glyph to the selection */
 | 
			
		||||
		for(y = 0; y < term.row; y++) {
 | 
			
		||||
		for(y = sel.b.y; y < sel.e.y + 1; y++) {
 | 
			
		||||
			is_selected = 0;
 | 
			
		||||
			gp = &term.line[y][0];
 | 
			
		||||
			last = gp + term.col;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -754,8 +783,11 @@ selcopy(void) {
 | 
			
		|||
				/* nothing */;
 | 
			
		||||
 | 
			
		||||
			for(x = 0; gp <= last; x++, ++gp) {
 | 
			
		||||
				if(!(is_selected = selected(x, y)))
 | 
			
		||||
				if(!selected(x, y)) {
 | 
			
		||||
					continue;
 | 
			
		||||
				} else {
 | 
			
		||||
					is_selected = 1;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				p = (gp->state & GLYPH_SET) ? gp->c : " ";
 | 
			
		||||
				size = utf8size(p);
 | 
			
		||||
| 
						 | 
				
			
			@ -907,7 +939,7 @@ brelease(XEvent *e) {
 | 
			
		|||
 | 
			
		||||
void
 | 
			
		||||
bmotion(XEvent *e) {
 | 
			
		||||
	int starty, endy, oldey, oldex;
 | 
			
		||||
	int oldey, oldex;
 | 
			
		||||
 | 
			
		||||
	if(IS_SET(MODE_MOUSE)) {
 | 
			
		||||
		mousereport(e);
 | 
			
		||||
| 
						 | 
				
			
			@ -922,9 +954,7 @@ bmotion(XEvent *e) {
 | 
			
		|||
	getbuttoninfo(e);
 | 
			
		||||
 | 
			
		||||
	if(oldey != sel.ey || oldex != sel.ex) {
 | 
			
		||||
		starty = MIN(oldey, sel.ey);
 | 
			
		||||
		endy = MAX(oldey, sel.ey);
 | 
			
		||||
		tsetdirt(starty, endy);
 | 
			
		||||
		tsetdirt(sel.b.y, sel.e.y);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1216,14 +1246,24 @@ selscroll(int orig, int n) {
 | 
			
		|||
			sel.bx = -1;
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		if(sel.by < term.top) {
 | 
			
		||||
			sel.by = term.top;
 | 
			
		||||
			sel.bx = 0;
 | 
			
		||||
		}
 | 
			
		||||
		if(sel.ey > term.bot) {
 | 
			
		||||
			sel.ey = term.bot;
 | 
			
		||||
			sel.ex = term.col;
 | 
			
		||||
		}
 | 
			
		||||
		switch(sel.type) {
 | 
			
		||||
		case SEL_REGULAR:
 | 
			
		||||
			if(sel.by < term.top) {
 | 
			
		||||
				sel.by = term.top;
 | 
			
		||||
				sel.bx = 0;
 | 
			
		||||
			}
 | 
			
		||||
			if(sel.ey > term.bot) {
 | 
			
		||||
				sel.ey = term.bot;
 | 
			
		||||
				sel.ex = term.col;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		case SEL_RECTANGULAR:
 | 
			
		||||
			if(sel.by < term.top)
 | 
			
		||||
				sel.by = term.top;
 | 
			
		||||
			if(sel.ey > term.bot)
 | 
			
		||||
				sel.ey = term.bot;
 | 
			
		||||
			break;
 | 
			
		||||
		};
 | 
			
		||||
		sel.b.y = sel.by, sel.b.x = sel.bx;
 | 
			
		||||
		sel.e.y = sel.ey, sel.e.x = sel.ex;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue