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