From c5ea653b1d1883fc5f929876bdd4bdc66448a665 Mon Sep 17 00:00:00 2001 From: Alexander Sedov Date: Tue, 19 Feb 2013 17:10:53 +0400 Subject: [PATCH] Rectangular selection support added. --- config.def.h | 11 ++++++++++ st.c | 67 +++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 63 insertions(+), 15 deletions(-) diff --git a/config.def.h b/config.def.h index 07a22ed..7ea623a 100644 --- a/config.def.h +++ b/config.def.h @@ -305,3 +305,14 @@ 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 index 5d1cfde..edd8fea 100644 --- 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 { @@ -646,15 +652,23 @@ selected(int x, int y) { ex = MAX(sel.bx, sel.ex); return BETWEEN(x, bx, ex); } - - 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)); + 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 +678,13 @@ 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 +745,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) { @@ -747,6 +769,7 @@ selcopy(void) { /* append every set & selected glyph to the selection */ for(y = 0; y < term.row; y++) { + is_selected = 0; gp = &term.line[y][0]; last = gp + term.col; @@ -754,8 +777,10 @@ 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 +932,7 @@ brelease(XEvent *e) { void bmotion(XEvent *e) { - int starty, endy, oldey, oldex; + int /*starty, endy,*/ oldey, oldex; if(IS_SET(MODE_MOUSE)) { mousereport(e); @@ -922,9 +947,11 @@ 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,13 +1243,23 @@ 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; -- 1.7.10.4