diff options
-rw-r--r-- | dmenu.c | 144 |
1 files changed, 64 insertions, 80 deletions
@@ -34,22 +34,6 @@ struct item { | |||
34 | bool out; | 34 | bool out; |
35 | }; | 35 | }; |
36 | 36 | ||
37 | static void appenditem(struct item *, struct item **, struct item **); | ||
38 | static void calcoffsets(void); | ||
39 | static char *cistrstr(const char *, const char *); | ||
40 | static void cleanup(void); | ||
41 | static void drawmenu(void); | ||
42 | static void grabkeyboard(void); | ||
43 | static void insert(const char *, ssize_t); | ||
44 | static void keypress(XKeyEvent *); | ||
45 | static void match(void); | ||
46 | static size_t nextrune(int); | ||
47 | static void paste(void); | ||
48 | static void readstdin(void); | ||
49 | static void run(void); | ||
50 | static void setup(void); | ||
51 | static void usage(void); | ||
52 | |||
53 | static char text[BUFSIZ] = ""; | 37 | static char text[BUFSIZ] = ""; |
54 | static int bh, mw, mh; | 38 | static int bh, mw, mh; |
55 | static int sw, sh; /* X display screen geometry width, height */ | 39 | static int sw, sh; /* X display screen geometry width, height */ |
@@ -216,6 +200,59 @@ grabkeyboard(void) | |||
216 | } | 200 | } |
217 | 201 | ||
218 | static void | 202 | static void |
203 | match(void) | ||
204 | { | ||
205 | static char **tokv = NULL; | ||
206 | static int tokn = 0; | ||
207 | |||
208 | char buf[sizeof text], *s; | ||
209 | int i, tokc = 0; | ||
210 | size_t len; | ||
211 | struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; | ||
212 | |||
213 | strcpy(buf, text); | ||
214 | /* separate input text into tokens to be matched individually */ | ||
215 | for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " ")) | ||
216 | if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv))) | ||
217 | die("cannot realloc %u bytes\n", tokn * sizeof *tokv); | ||
218 | len = tokc ? strlen(tokv[0]) : 0; | ||
219 | |||
220 | matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; | ||
221 | for (item = items; item && item->text; item++) { | ||
222 | for (i = 0; i < tokc; i++) | ||
223 | if (!fstrstr(item->text, tokv[i])) | ||
224 | break; | ||
225 | if (i != tokc) /* not all tokens match */ | ||
226 | continue; | ||
227 | /* exact matches go first, then prefixes, then substrings */ | ||
228 | if (!tokc || !fstrncmp(tokv[0], item->text, len + 1)) | ||
229 | appenditem(item, &matches, &matchend); | ||
230 | else if (!fstrncmp(tokv[0], item->text, len)) | ||
231 | appenditem(item, &lprefix, &prefixend); | ||
232 | else | ||
233 | appenditem(item, &lsubstr, &substrend); | ||
234 | } | ||
235 | if (lprefix) { | ||
236 | if (matches) { | ||
237 | matchend->right = lprefix; | ||
238 | lprefix->left = matchend; | ||
239 | } else | ||
240 | matches = lprefix; | ||
241 | matchend = prefixend; | ||
242 | } | ||
243 | if (lsubstr) { | ||
244 | if (matches) { | ||
245 | matchend->right = lsubstr; | ||
246 | lsubstr->left = matchend; | ||
247 | } else | ||
248 | matches = lsubstr; | ||
249 | matchend = substrend; | ||
250 | } | ||
251 | curr = sel = matches; | ||
252 | calcoffsets(); | ||
253 | } | ||
254 | |||
255 | static void | ||
219 | insert(const char *str, ssize_t n) | 256 | insert(const char *str, ssize_t n) |
220 | { | 257 | { |
221 | if (strlen(text) + n > sizeof text - 1) | 258 | if (strlen(text) + n > sizeof text - 1) |
@@ -228,6 +265,17 @@ insert(const char *str, ssize_t n) | |||
228 | match(); | 265 | match(); |
229 | } | 266 | } |
230 | 267 | ||
268 | static size_t | ||
269 | nextrune(int inc) | ||
270 | { | ||
271 | ssize_t n; | ||
272 | |||
273 | /* return location of next utf8 rune in the given direction (+1 or -1) */ | ||
274 | for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc) | ||
275 | ; | ||
276 | return n; | ||
277 | } | ||
278 | |||
231 | static void | 279 | static void |
232 | keypress(XKeyEvent *ev) | 280 | keypress(XKeyEvent *ev) |
233 | { | 281 | { |
@@ -399,70 +447,6 @@ keypress(XKeyEvent *ev) | |||
399 | } | 447 | } |
400 | 448 | ||
401 | static void | 449 | static void |
402 | match(void) | ||
403 | { | ||
404 | static char **tokv = NULL; | ||
405 | static int tokn = 0; | ||
406 | |||
407 | char buf[sizeof text], *s; | ||
408 | int i, tokc = 0; | ||
409 | size_t len; | ||
410 | struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; | ||
411 | |||
412 | strcpy(buf, text); | ||
413 | /* separate input text into tokens to be matched individually */ | ||
414 | for (s = strtok(buf, " "); s; tokv[tokc - 1] = s, s = strtok(NULL, " ")) | ||
415 | if (++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv))) | ||
416 | die("cannot realloc %u bytes\n", tokn * sizeof *tokv); | ||
417 | len = tokc ? strlen(tokv[0]) : 0; | ||
418 | |||
419 | matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; | ||
420 | for (item = items; item && item->text; item++) { | ||
421 | for (i = 0; i < tokc; i++) | ||
422 | if (!fstrstr(item->text, tokv[i])) | ||
423 | break; | ||
424 | if (i != tokc) /* not all tokens match */ | ||
425 | continue; | ||
426 | /* exact matches go first, then prefixes, then substrings */ | ||
427 | if (!tokc || !fstrncmp(tokv[0], item->text, len + 1)) | ||
428 | appenditem(item, &matches, &matchend); | ||
429 | else if (!fstrncmp(tokv[0], item->text, len)) | ||
430 | appenditem(item, &lprefix, &prefixend); | ||
431 | else | ||
432 | appenditem(item, &lsubstr, &substrend); | ||
433 | } | ||
434 | if (lprefix) { | ||
435 | if (matches) { | ||
436 | matchend->right = lprefix; | ||
437 | lprefix->left = matchend; | ||
438 | } else | ||
439 | matches = lprefix; | ||
440 | matchend = prefixend; | ||
441 | } | ||
442 | if (lsubstr) { | ||
443 | if (matches) { | ||
444 | matchend->right = lsubstr; | ||
445 | lsubstr->left = matchend; | ||
446 | } else | ||
447 | matches = lsubstr; | ||
448 | matchend = substrend; | ||
449 | } | ||
450 | curr = sel = matches; | ||
451 | calcoffsets(); | ||
452 | } | ||
453 | |||
454 | static size_t | ||
455 | nextrune(int inc) | ||
456 | { | ||
457 | ssize_t n; | ||
458 | |||
459 | /* return location of next utf8 rune in the given direction (+1 or -1) */ | ||
460 | for (n = cursor + inc; n + inc >= 0 && (text[n] & 0xc0) == 0x80; n += inc) | ||
461 | ; | ||
462 | return n; | ||
463 | } | ||
464 | |||
465 | static void | ||
466 | paste(void) | 450 | paste(void) |
467 | { | 451 | { |
468 | char *p, *q; | 452 | char *p, *q; |