[hackers] [st] Implement rectangular mouse selection. || Christoph Lohmann

From: <git_AT_suckless.org>
Date: Tue, 19 Feb 2013 19:11:13 +0100

commit 3865e9eaaf4e1c7820b1f41ce9d0b1d7b109fb26
Author: Christoph Lohmann <20h_AT_r-36.net>
Date: Tue Feb 19 19:08:41 2013 +0100

    Implement rectangular mouse selection.
    
    Thanks Alexander Sedov <alex0player_AT_gmail.com>!

diff --git a/config.def.h b/config.def.h
index 07a22ed..a31a235 100644
--- a/config.def.h
+++ b/config.def.h
_AT_@ -305,3 +305,15 @@ static Key key[] = {
         { XK_F35, XK_NO_MOD, "[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
index 7befdc0..300e5ec 100644
--- a/st.c
+++ b/st.c
_AT_@ -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 };
_AT_@ -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 {
_AT_@ -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);
_AT_@ -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
_AT_@ -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) {
_AT_@ -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;
 
_AT_@ -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);
_AT_@ -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);
_AT_@ -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);
         }
 }
 
_AT_@ -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;
         }
Received on Tue Feb 19 2013 - 19:11:13 CET

This archive was generated by hypermail 2.3.0 : Thu Feb 21 2013 - 19:27:13 CET