| st-keyboard_select-0.8.1.diff - sites - public wiki contents of suckless.org | |
| git clone git://git.suckless.org/sites | |
| Log | |
| Files | |
| 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 = … | |
| 7 { TERMMOD, XK_Num_Lock, numlock, {.i = … | |
| 8 { TERMMOD, XK_I, iso14755, {.i = … | |
| 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]… | |
| 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 … | |
| 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,… | |
| 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 += in… | |
| 94 + for (r = target; r - target < ptarget; r++) { | |
| 95 + if ( *r == term.line[(i + r - target) / term.col][(i + r - … | |
| 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, … | |
| 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_… | |
| 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 keyb… | |
| 224 + quant = (quant * 10) + (ksym ^ XK_0); | |
| 225 + return 0; | |
| 226 + } | |
| 227 + else if ( ksym >= XK_KP_0 && ksym <= XK_KP_9 ) { /* 0-9 nump… | |
| 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) … | |
| 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 && … | |
| 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, &statu… | |
| 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 { |