aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.h1
-rw-r--r--config.mk2
-rwxr-xr-xdmenubin0 -> 44432 bytes
-rw-r--r--dmenu.c91
-rwxr-xr-xstestbin0 -> 17680 bytes
5 files changed, 92 insertions, 2 deletions
diff --git a/config.h b/config.h
index 697d511..5893d0b 100644
--- a/config.h
+++ b/config.h
@@ -3,6 +3,7 @@
3 3
4static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ 4static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
5static const unsigned int alpha = 0xf0; 5static const unsigned int alpha = 0xf0;
6static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */
6/* -fn option overrides fonts[0]; default X11 font or font set */ 7/* -fn option overrides fonts[0]; default X11 font or font set */
7static const char *fonts[] = { 8static const char *fonts[] = {
8 "monospace:size=10" 9 "monospace:size=10"
diff --git a/config.mk b/config.mk
index 566348b..fd0b2c3 100644
--- a/config.mk
+++ b/config.mk
@@ -21,7 +21,7 @@ FREETYPEINC = /usr/include/freetype2
21 21
22# includes and libs 22# includes and libs
23INCS = -I$(X11INC) -I$(FREETYPEINC) 23INCS = -I$(X11INC) -I$(FREETYPEINC)
24LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) 24LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm -lXrender
25 25
26# flags 26# flags
27CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) 27CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
diff --git a/dmenu b/dmenu
new file mode 100755
index 0000000..63f1aea
--- /dev/null
+++ b/dmenu
Binary files differ
diff --git a/dmenu.c b/dmenu.c
index ab2d29a..9cfb1c4 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -1,6 +1,7 @@
1/* See LICENSE file for copyright and license details. */ 1/* See LICENSE file for copyright and license details. */
2#include <ctype.h> 2#include <ctype.h>
3#include <locale.h> 3#include <locale.h>
4#include <math.h>
4#include <stdio.h> 5#include <stdio.h>
5#include <stdlib.h> 6#include <stdlib.h>
6#include <string.h> 7#include <string.h>
@@ -35,6 +36,7 @@ struct item {
35 char *text; 36 char *text;
36 struct item *left, *right; 37 struct item *left, *right;
37 int out; 38 int out;
39 double distance;
38}; 40};
39 41
40static char text[BUFSIZ] = ""; 42static char text[BUFSIZ] = "";
@@ -236,9 +238,94 @@ grabkeyboard(void)
236 die("cannot grab keyboard"); 238 die("cannot grab keyboard");
237} 239}
238 240
241int
242compare_distance(const void *a, const void *b)
243{
244 struct item *da = *(struct item **) a;
245 struct item *db = *(struct item **) b;
246
247 if (!db)
248 return 1;
249 if (!da)
250 return -1;
251
252 return da->distance == db->distance ? 0 : da->distance < db->distance ? -1 : 1;
253}
254
255void
256fuzzymatch(void)
257{
258 /* bang - we have so much memory */
259 struct item *it;
260 struct item **fuzzymatches = NULL;
261 char c;
262 int number_of_matches = 0, i, pidx, sidx, eidx;
263 int text_len = strlen(text), itext_len;
264
265 matches = matchend = NULL;
266
267 /* walk through all items */
268 for (it = items; it && it->text; it++) {
269 if (text_len) {
270 itext_len = strlen(it->text);
271 pidx = 0; /* pointer */
272 sidx = eidx = -1; /* start of match, end of match */
273 /* walk through item text */
274 for (i = 0; i < itext_len && (c = it->text[i]); i++) {
275 /* fuzzy match pattern */
276 if (!fstrncmp(&text[pidx], &c, 1)) {
277 if(sidx == -1)
278 sidx = i;
279 pidx++;
280 if (pidx == text_len) {
281 eidx = i;
282 break;
283 }
284 }
285 }
286 /* build list of matches */
287 if (eidx != -1) {
288 /* compute distance */
289 /* add penalty if match starts late (log(sidx+2))
290 * add penalty for long a match without many matching characters */
291 it->distance = log(sidx + 2) + (double)(eidx - sidx - text_len);
292 /* fprintf(stderr, "distance %s %f\n", it->text, it->distance); */
293 appenditem(it, &matches, &matchend);
294 number_of_matches++;
295 }
296 } else {
297 appenditem(it, &matches, &matchend);
298 }
299 }
300
301 if (number_of_matches) {
302 /* initialize array with matches */
303 if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*))))
304 die("cannot realloc %u bytes:", number_of_matches * sizeof(struct item*));
305 for (i = 0, it = matches; it && i < number_of_matches; i++, it = it->right) {
306 fuzzymatches[i] = it;
307 }
308 /* sort matches according to distance */
309 qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance);
310 /* rebuild list of matches */
311 matches = matchend = NULL;
312 for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \
313 it->text; i++, it = fuzzymatches[i]) {
314 appenditem(it, &matches, &matchend);
315 }
316 free(fuzzymatches);
317 }
318 curr = sel = matches;
319 calcoffsets();
320}
321
239static void 322static void
240match(void) 323match(void)
241{ 324{
325 if (fuzzy) {
326 fuzzymatch();
327 return;
328 }
242 static char **tokv = NULL; 329 static char **tokv = NULL;
243 static int tokn = 0; 330 static int tokn = 0;
244 331
@@ -692,7 +779,7 @@ setup(void)
692 swa.border_pixel = 0; 779 swa.border_pixel = 0;
693 swa.colormap = cmap; 780 swa.colormap = cmap;
694 swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; 781 swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
695 win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width, 782 win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
696 depth, CopyFromParent, visual, 783 depth, CopyFromParent, visual,
697 CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &swa); 784 CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWColormap | CWEventMask, &swa);
698 XSetClassHint(dpy, win, &ch); 785 XSetClassHint(dpy, win, &ch);
@@ -741,6 +828,8 @@ main(int argc, char *argv[])
741 topbar = 0; 828 topbar = 0;
742 else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ 829 else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
743 fast = 1; 830 fast = 1;
831 else if (!strcmp(argv[i], "-F")) /* grabs keyboard before reading stdin */
832 fuzzy = 0;
744 else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ 833 else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
745 fstrncmp = strncasecmp; 834 fstrncmp = strncasecmp;
746 fstrstr = cistrstr; 835 fstrstr = cistrstr;
diff --git a/stest b/stest
new file mode 100755
index 0000000..d2d6ca3
--- /dev/null
+++ b/stest
Binary files differ