# st

Unnamed repository; edit this file 'description' to name the repository.

| Log | Files | Refs | README | LICENSE

    commit 3865e9eaaf4e1c7820b1f41ce9d0b1d7b109fb26
    parent e5295629cdffb711001f3fdffbb9aa4ef772add0
    Author: Christoph Lohmann <20h@r-36.net>
    Date:   Tue, 19 Feb 2013 19:08:41 +0100

    Implement rectangular mouse selection.

    Thanks Alexander Sedov <alex0player@gmail.com>!

    Diffstat:
    Mconfig.def.h | 12++++++++++++
    Mst.c | 68++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------

    2 files changed, 66 insertions(+), 14 deletions(-)
    diff --git a/config.def.h b/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,
    +};
    +
    diff --git a/st.c b/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;
     	}