aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dmenu.c144
1 files changed, 64 insertions, 80 deletions
diff --git a/dmenu.c b/dmenu.c
index 050b858..32a8330 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -34,22 +34,6 @@ struct item {
34 bool out; 34 bool out;
35}; 35};
36 36
37static void appenditem(struct item *, struct item **, struct item **);
38static void calcoffsets(void);
39static char *cistrstr(const char *, const char *);
40static void cleanup(void);
41static void drawmenu(void);
42static void grabkeyboard(void);
43static void insert(const char *, ssize_t);
44static void keypress(XKeyEvent *);
45static void match(void);
46static size_t nextrune(int);
47static void paste(void);
48static void readstdin(void);
49static void run(void);
50static void setup(void);
51static void usage(void);
52
53static char text[BUFSIZ] = ""; 37static char text[BUFSIZ] = "";
54static int bh, mw, mh; 38static int bh, mw, mh;
55static int sw, sh; /* X display screen geometry width, height */ 39static int sw, sh; /* X display screen geometry width, height */
@@ -216,6 +200,59 @@ grabkeyboard(void)
216} 200}
217 201
218static void 202static void
203match(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
255static void
219insert(const char *str, ssize_t n) 256insert(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
268static size_t
269nextrune(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
231static void 279static void
232keypress(XKeyEvent *ev) 280keypress(XKeyEvent *ev)
233{ 281{
@@ -399,70 +447,6 @@ keypress(XKeyEvent *ev)
399} 447}
400 448
401static void 449static void
402match(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
454static size_t
455nextrune(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
465static void
466paste(void) 450paste(void)
467{ 451{
468 char *p, *q; 452 char *p, *q;