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