diff --git a/dmenu.c b/dmenu.c index 6b8f51b..6544112 100644 --- a/dmenu.c +++ b/dmenu.c @@ -31,7 +31,8 @@ enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ struct item { char *text; struct item *left, *right; - int out; + + int id; /* for multiselect */ }; static char text[BUFSIZ] = ""; @@ -45,6 +46,9 @@ static struct item *matches, *matchend; static struct item *prev, *curr, *next, *sel; static int mon = -1, screen; +static int *selid = NULL; +static unsigned int selidsize = 0; + static Atom clip, utf8; static Display *dpy; static Window root, parentwin, win; @@ -58,6 +62,15 @@ static Clr *scheme[SchemeLast]; static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; static char *(*fstrstr)(const char *, const char *) = strstr; +static int +issel(size_t id) +{ + for (int i = 0;i < selidsize;i++) + if (selid[i] == id) + return 1; + return 0; +} + static void appenditem(struct item *item, struct item **list, struct item **last) { @@ -100,6 +113,7 @@ cleanup(void) drw_free(drw); XSync(dpy, False); XCloseDisplay(dpy); + free(selid); } static char * @@ -118,7 +132,7 @@ drawitem(struct item *item, int x, int y, int w) { if (item == sel) drw_setscheme(drw, scheme[SchemeSel]); - else if (item->out) + else if (issel(item->id)) drw_setscheme(drw, scheme[SchemeOut]); else drw_setscheme(drw, scheme[SchemeNorm]); @@ -367,6 +381,20 @@ keypress(XKeyEvent *ev) goto draw; case XK_Return: case XK_KP_Enter: + if (sel && issel(sel->id)) { + for (int i = 0;i < selidsize;i++) + if (selid[i] == sel->id) + selid[i] = -1; + } else { + for (int i = 0;i < selidsize;i++) + if (selid[i] == -1) { + selid[i] = sel->id; + return; + } + selidsize++; + selid = realloc(selid, (selidsize + 1) * sizeof(int)); + selid[selidsize - 1] = sel->id; + } break; case XK_bracketleft: cleanup(); @@ -464,13 +492,17 @@ insert: break; case XK_Return: case XK_KP_Enter: - puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); if (!(ev->state & ControlMask)) { + for (int i = 0;i < selidsize;i++) + if (selid[i] != -1 && (!sel || sel->id != selid[i])) + puts(items[selid[i]].text); + if (sel && !(ev->state & ShiftMask)) + puts(sel->text); + else + puts(text); cleanup(); exit(0); } - if (sel) - sel->out = 1; break; case XK_Right: if (text[cursor] != '\0') { @@ -534,7 +566,7 @@ readstdin(void) *p = '\0'; if (!(items[i].text = strdup(buf))) die("cannot strdup %u bytes:", strlen(buf) + 1); - items[i].out = 0; + items[i].id = i; /* for multiselect */ drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); if (tmpmax > inputw) { inputw = tmpmax;