sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

st-keyboard_select-20250816-a1193c1.diff (8896B)


      1 From a1193c14bf3a306996f1dd67d62b6b93427f0d90 Mon Sep 17 00:00:00 2001
      2 From: Tonton Couillon <la.luge@free.fr>
      3 Date: Sat, 16 Aug 2025 15:55:05 +0200
      4 Subject: [PATCH] bump version to st-0.9.3
      5 
      6 ---
      7  config.def.h |   1 +
      8  st.c         | 222 +++++++++++++++++++++++++++++++++++++++++++++++++++
      9  st.h         |   1 +
     10  win.h        |   3 +
     11  x.c          |  16 ++++
     12  5 files changed, 243 insertions(+)
     13 
     14 diff --git a/config.def.h b/config.def.h
     15 index 2cd740a..c2567da 100644
     16 --- a/config.def.h
     17 +++ b/config.def.h
     18 @@ -201,6 +201,7 @@ static Shortcut shortcuts[] = {
     19  	{ TERMMOD,              XK_Y,           selpaste,       {.i =  0} },
     20  	{ ShiftMask,            XK_Insert,      selpaste,       {.i =  0} },
     21  	{ TERMMOD,              XK_Num_Lock,    numlock,        {.i =  0} },
     22 +	{ TERMMOD,              XK_Escape,      keyboard_select,{.i =  0} },
     23  };
     24  
     25  /*
     26 diff --git a/st.c b/st.c
     27 index 8e57991..9edfa12 100644
     28 --- a/st.c
     29 +++ b/st.c
     30 @@ -16,6 +16,8 @@
     31  #include <termios.h>
     32  #include <unistd.h>
     33  #include <wchar.h>
     34 +#include <X11/keysym.h>
     35 +#include <X11/X.h>
     36  
     37  #include "st.h"
     38  #include "win.h"
     39 @@ -2574,6 +2576,9 @@ tresize(int col, int row)
     40  	int *bp;
     41  	TCursor c;
     42  
     43 +	if ( row < term.row  || col < term.col )
     44 +		toggle_winmode(trt_kbdselect(XK_Escape, NULL, 0));
     45 +
     46  	if (col < 1 || row < 1) {
     47  		fprintf(stderr,
     48  		        "tresize: error resizing to %dx%d\n", col, row);
     49 @@ -2699,3 +2704,220 @@ redraw(void)
     50  	tfulldirt();
     51  	draw();
     52  }
     53 +
     54 +void set_notifmode(int type, KeySym ksym) {
     55 +	static char *lib[] = { " MOVE ", " SEL  "};
     56 +	static Glyph *g, *deb, *fin;
     57 +	static int col, bot;
     58 +
     59 +	if ( ksym == -1 ) {
     60 +		free(g);
     61 +		col = term.col, bot = term.bot;
     62 +		g = xmalloc(col * sizeof(Glyph));
     63 +		memcpy(g, term.line[bot], col * sizeof(Glyph));
     64 +
     65 +	}
     66 +	else if ( ksym == -2 )
     67 +		memcpy(term.line[bot], g, col * sizeof(Glyph));
     68 +
     69 +	if ( type < 2 ) {
     70 +		char *z = lib[type];
     71 +		for (deb = &term.line[bot][col - 6], fin = &term.line[bot][col]; deb < fin; z++, deb++)
     72 +			deb->mode = ATTR_REVERSE,
     73 +				deb->u = *z,
     74 +				deb->fg = defaultfg, deb->bg = defaultbg;
     75 +	}
     76 +	else if ( type < 5 )
     77 +		memcpy(term.line[bot], g, col * sizeof(Glyph));
     78 +	else {
     79 +		for (deb = &term.line[bot][0], fin = &term.line[bot][col]; deb < fin; deb++)
     80 +			deb->mode = ATTR_REVERSE,
     81 +				deb->u = ' ',
     82 +				deb->fg = defaultfg, deb->bg = defaultbg;
     83 +		term.line[bot][0].u = ksym;
     84 +	}
     85 +
     86 +	term.dirty[bot] = 1;
     87 +	drawregion(0, bot, col, bot + 1);
     88 +}
     89 +
     90 +void select_or_drawcursor(int selectsearch_mode, int type) {
     91 +	int done = 0;
     92 +
     93 +	if ( selectsearch_mode & 1 ) {
     94 +		selextend(term.c.x, term.c.y, type, done);
     95 +		xsetsel(getsel());
     96 +	}
     97 +	else
     98 +		xdrawcursor(term.c.x, term.c.y, term.line[term.c.y][term.c.x],
     99 +			    term.ocx, term.ocy, term.line[term.ocy][term.ocx]);
    100 +}
    101 +
    102 +void search(int selectsearch_mode, Rune *target, int ptarget, int incr, int type, TCursor *cu) {
    103 +	Rune *r;
    104 +	int i, bound = (term.col * cu->y + cu->x) * (incr > 0) + incr;
    105 +
    106 +	for (i = term.col * term.c.y + term.c.x + incr; i != bound; i += incr) {
    107 +		for (r = target; r - target < ptarget; r++) {
    108 +			if ( *r == term.line[(i + r - target) / term.col][(i + r - target) % term.col].u ) {
    109 +				if ( r - target == ptarget - 1 )     break;
    110 +			} else {
    111 +				r = NULL;
    112 +				break;
    113 +			}
    114 +		}
    115 +		if ( r != NULL )    break;
    116 +	}
    117 +
    118 +	if ( i != bound ) {
    119 +		term.c.y = i / term.col, term.c.x = i % term.col;
    120 +		select_or_drawcursor(selectsearch_mode, type);
    121 +	}
    122 +}
    123 +
    124 +int trt_kbdselect(KeySym ksym, char *buf, int len) {
    125 +	static TCursor cu;
    126 +	static Rune target[64];
    127 +	static int type = 1, ptarget, in_use;
    128 +	static int sens, quant;
    129 +	static char selectsearch_mode;
    130 +	int i, bound, *xy;
    131 +
    132 +
    133 +	if ( selectsearch_mode & 2 ) {
    134 +		if ( ksym == XK_Return ) {
    135 +			selectsearch_mode ^= 2;
    136 +			set_notifmode(selectsearch_mode, -2);
    137 +			if ( ksym == XK_Escape )    ptarget = 0;
    138 +			return 0;
    139 +		}
    140 +		else if ( ksym == XK_BackSpace ) {
    141 +			if ( !ptarget )     return 0;
    142 +			term.line[term.bot][ptarget--].u = ' ';
    143 +		}
    144 +		else if ( len < 1 ) {
    145 +			return 0;
    146 +		}
    147 +		else if ( ptarget == term.col  || ksym == XK_Escape ) {
    148 +			return 0;
    149 +		}
    150 +		else {
    151 +			utf8decode(buf, &target[ptarget++], len);
    152 +			term.line[term.bot][ptarget].u = target[ptarget - 1];
    153 +		}
    154 +
    155 +		if ( ksym != XK_BackSpace )
    156 +			search(selectsearch_mode, &target[0], ptarget, sens, type, &cu);
    157 +
    158 +		term.dirty[term.bot] = 1;
    159 +		drawregion(0, term.bot, term.col, term.bot + 1);
    160 +		return 0;
    161 +	}
    162 +
    163 +	switch ( ksym ) {
    164 +	case -1 :
    165 +		in_use = 1;
    166 +		cu.x = term.c.x, cu.y = term.c.y;
    167 +		set_notifmode(0, ksym);
    168 +		return MODE_KBDSELECT;
    169 +	case XK_s :
    170 +		if ( selectsearch_mode & 1 )
    171 +			selclear();
    172 +		else
    173 +			selstart(term.c.x, term.c.y, 0);
    174 +		set_notifmode(selectsearch_mode ^= 1, ksym);
    175 +		break;
    176 +	case XK_t :
    177 +		selextend(term.c.x, term.c.y, type ^= 3, i = 0);  /* 2 fois */
    178 +		selextend(term.c.x, term.c.y, type, i = 0);
    179 +		break;
    180 +	case XK_slash :
    181 +	case XK_KP_Divide :
    182 +	case XK_question :
    183 +		ksym &= XK_question;                /* Divide to slash */
    184 +		sens = (ksym == XK_slash) ? -1 : 1;
    185 +		ptarget = 0;
    186 +		set_notifmode(15, ksym);
    187 +		selectsearch_mode ^= 2;
    188 +		break;
    189 +	case XK_Escape :
    190 +		if ( !in_use )  break;
    191 +		selclear();
    192 +	case XK_Return :
    193 +		set_notifmode(4, ksym);
    194 +		term.c.x = cu.x, term.c.y = cu.y;
    195 +		select_or_drawcursor(selectsearch_mode = 0, type);
    196 +		in_use = quant = 0;
    197 +		return MODE_KBDSELECT;
    198 +	case XK_n :
    199 +	case XK_N :
    200 +		if ( ptarget )
    201 +			search(selectsearch_mode, &target[0], ptarget, (ksym == XK_n) ? -1 : 1, type, &cu);
    202 +		break;
    203 +	case XK_BackSpace :
    204 +		term.c.x = 0;
    205 +		select_or_drawcursor(selectsearch_mode, type);
    206 +		break;
    207 +	case XK_dollar :
    208 +		term.c.x = term.col - 1;
    209 +		select_or_drawcursor(selectsearch_mode, type);
    210 +		break;
    211 +	case XK_Home :
    212 +		term.c.x = 0, term.c.y = 0;
    213 +		select_or_drawcursor(selectsearch_mode, type);
    214 +		break;
    215 +	case XK_End :
    216 +		term.c.x = cu.x, term.c.y = cu.y;
    217 +		select_or_drawcursor(selectsearch_mode, type);
    218 +		break;
    219 +	case XK_Page_Up :
    220 +	case XK_Page_Down :
    221 +		term.c.y = (ksym == XK_Prior ) ? 0 : cu.y;
    222 +		select_or_drawcursor(selectsearch_mode, type);
    223 +		break;
    224 +	case XK_exclam :
    225 +		term.c.x = term.col >> 1;
    226 +		select_or_drawcursor(selectsearch_mode, type);
    227 +		break;
    228 +	case XK_asterisk :
    229 +	case XK_KP_Multiply :
    230 +		term.c.x = term.col >> 1;
    231 +	case XK_underscore :
    232 +		term.c.y = cu.y >> 1;
    233 +		select_or_drawcursor(selectsearch_mode, type);
    234 +		break;
    235 +	default :
    236 +		if ( ksym >= XK_0 && ksym <= XK_9 ) {               /* 0-9 keyboard */
    237 +			quant = (quant * 10) + (ksym ^ XK_0);
    238 +			return 0;
    239 +		}
    240 +		else if ( ksym >= XK_KP_0 && ksym <= XK_KP_9 ) {    /* 0-9 numpad */
    241 +			quant = (quant * 10) + (ksym ^ XK_KP_0);
    242 +			return 0;
    243 +		}
    244 +		else if ( ksym == XK_k || ksym == XK_h )
    245 +			i = ksym & 1;
    246 +		else if ( ksym == XK_l || ksym == XK_j )
    247 +			i = ((ksym & 6) | 4) >> 1;
    248 +		else if ( (XK_Home & ksym) != XK_Home || (i = (ksym ^ XK_Home) - 1) > 3 )
    249 +			break;
    250 +
    251 +		xy = (i & 1) ? &term.c.y : &term.c.x;
    252 +		sens = (i & 2) ? 1 : -1;
    253 +		bound = (i >> 1 ^ 1) ? 0 : (i ^ 3) ? term.col - 1 : term.bot;
    254 +
    255 +		if ( quant == 0 )
    256 +			quant++;
    257 +
    258 +		if ( *xy == bound && ((sens < 0 && bound == 0) || (sens > 0 && bound > 0)) )
    259 +			break;
    260 +
    261 +		*xy += quant * sens;
    262 +		if ( *xy < 0 || ( bound > 0 && *xy > bound) )
    263 +			*xy = bound;
    264 +
    265 +		select_or_drawcursor(selectsearch_mode, type);
    266 +	}
    267 +	quant = 0;
    268 +	return 0;
    269 +}
    270 diff --git a/st.h b/st.h
    271 index fd3b0d8..9151719 100644
    272 --- a/st.h
    273 +++ b/st.h
    274 @@ -110,6 +110,7 @@ size_t utf8encode(Rune, char *);
    275  void *xmalloc(size_t);
    276  void *xrealloc(void *, size_t);
    277  char *xstrdup(const char *);
    278 +int  trt_kbdselect(KeySym, char *, int);
    279  
    280  /* config.h globals */
    281  extern char *utmp;
    282 diff --git a/win.h b/win.h
    283 index 6de960d..4d25380 100644
    284 --- a/win.h
    285 +++ b/win.h
    286 @@ -21,6 +21,7 @@ enum win_mode {
    287  	MODE_NUMLOCK     = 1 << 17,
    288  	MODE_MOUSE       = MODE_MOUSEBTN|MODE_MOUSEMOTION|MODE_MOUSEX10\
    289  	                  |MODE_MOUSEMANY,
    290 +	MODE_KBDSELECT   = 1 << 18,
    291  };
    292  
    293  void xbell(void);
    294 @@ -38,4 +39,6 @@ void xsetmode(int, unsigned int);
    295  void xsetpointermotion(int);
    296  void xsetsel(char *);
    297  int xstartdraw(void);
    298 +void toggle_winmode(int);
    299 +void keyboard_select(const Arg *);
    300  void xximspot(int, int);
    301 diff --git a/x.c b/x.c
    302 index d73152b..c5807dc 100644
    303 --- a/x.c
    304 +++ b/x.c
    305 @@ -1859,6 +1859,14 @@ kpress(XEvent *ev)
    306  	} else {
    307  		len = XLookupString(e, buf, sizeof buf, &ksym, NULL);
    308  	}
    309 +
    310 +	if ( IS_SET(MODE_KBDSELECT) ) {
    311 +		if ( match(XK_NO_MOD, e->state) ||
    312 +		     (XK_Shift_L | XK_Shift_R) & e->state )
    313 +			win.mode ^= trt_kbdselect(ksym, buf, len);
    314 +		return;
    315 +	}
    316 +	
    317  	/* 1. shortcuts */
    318  	for (bp = shortcuts; bp < shortcuts + LEN(shortcuts); bp++) {
    319  		if (ksym == bp->keysym && match(bp->mod, e->state)) {
    320 @@ -2036,6 +2044,14 @@ usage(void)
    321  	    " [stty_args ...]\n", argv0, argv0);
    322  }
    323  
    324 +void toggle_winmode(int flag) {
    325 +	win.mode ^= flag;
    326 +}
    327 +
    328 +void keyboard_select(const Arg *dummy) {
    329 +	win.mode ^= trt_kbdselect(-1, NULL, 0);
    330 +}
    331 +
    332  int
    333  main(int argc, char *argv[])
    334  {
    335 -- 
    336 2.39.5
    337