all repos — st @ 3865e9eaaf4e1c7820b1f41ce9d0b1d7b109fb26

st (suckless terminal) config

Implement rectangular mouse selection.

Thanks Alexander Sedov <alex0player@gmail.com>!
Christoph Lohmann 20h@r-36.net
commit

3865e9eaaf4e1c7820b1f41ce9d0b1d7b109fb26

parent

e5295629cdffb711001f3fdffbb9aa4ef772add0

2 files changed, 66 insertions(+), 14 deletions(-)

jump to
M config.def.hconfig.def.h

@@ -305,3 +305,15 @@ { XK_F34, XK_NO_MOD, "\033[21;5~", 0, 0, 0},

{ 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, +}; +
M st.cst.c

@@ -137,6 +137,11 @@ WIN_REDRAW = 2,

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 @@

/* TODO: use better name for vars... */ typedef struct { int mode; + int type; int bx, by; int ex, ey; struct {

@@ -651,10 +657,23 @@ 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 +683,14 @@ sel.b.x = sel.by < sel.ey ? sel.bx : sel.ex;

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 @@ tsetdirt(sel.b.y, sel.e.y);

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 @@ bufsize = (term.col+1) * (sel.e.y-sel.b.y+1) * UTF_SIZ;

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 @@ while(--last >= gp && !(last->state & GLYPH_SET))

/* 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 @@ }

void bmotion(XEvent *e) { - int starty, endy, oldey, oldex; + int oldey, oldex; if(IS_SET(MODE_MOUSE)) { mousereport(e);

@@ -922,9 +954,7 @@ oldex = sel.ex;

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 @@ if((sel.by += n) > term.bot || (sel.ey += n) < term.top) {

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; }