commit a21f1409dc76f791623689c98f320fab7a4848ba
parent a4496149370ede5cccf574391d8f1b885ab72caa
Author: Erik Letson <hmagellan@hmagellan.com>
Date: Sun, 23 Aug 2020 13:55:46 -0500
added multi-selection
Diffstat:
3 files changed, 141 insertions(+), 1 deletion(-)
diff --git a/README b/README
@@ -42,7 +42,7 @@ patches!
(1). https://tools.suckless.org/dmenu/patches/
- CURRENT PROGRESS: 14/32 patches supported
+ CURRENT PROGRESS: 15/32 patches supported
3/32 patches unsupported
USUPPORTED PATCHES:
diff --git a/patches/multi-selection/USAGE b/patches/multi-selection/USAGE
@@ -0,0 +1,28 @@
+multi-selection - Multiple selection support on Ctrl-Enter
+Source: https://tools.suckless.org/dmenu/patches/multi-selection/dmenu-multi-selection-4.9.diff
+Original Author: bit6tream bit6tream@cock.li bit6tream's gitlab (https://gitlab.com/bit9tream)
+
+Description from source:
+ """
+ Without this patch when you press <Control-Enter> dmenu just outputs current item and you can't undo
+ that. But with this patch dmenu will output all selected items only on exit. And you can also deselect
+ any selected item.
+
+ dmenu_run.sh is a dmenu_run replacement that supports multiple selection patch.
+ """
+
+== YOU MUST ==
+(1). Place the patch file in /etc/portage/patches/x11-misc/dmenu/ and run 'emerge dmenu'
+
+== YOU PROBABLY SHOULD ==
+(1). The patch author provides an alternative implementation of dmenu_run here:
+
+ https://tools.suckless.org/dmenu/patches/multi-selection/dmenu_run.sh
+
+ Consider using that script to launch dmenu in order to get proper support for this patch.
+
+== PATCH MODIFICATIONS ==
+(1). Changed several for-loop declarations to C99 style to appease portage
+
+== INCOMPATIBILITIES ==
+No known specific incompatibilities.
diff --git a/patches/multi-selection/multi-selection.patch b/patches/multi-selection/multi-selection.patch
@@ -0,0 +1,112 @@
+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,16 @@ 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)
++{
++ int i = 0;
++ for (i;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,22 @@ keypress(XKeyEvent *ev)
+ goto draw;
+ case XK_Return:
+ case XK_KP_Enter:
++ if (sel && issel(sel->id)) {
++ int i = 0;
++ for (i;i < selidsize;i++)
++ if (selid[i] == sel->id)
++ selid[i] = -1;
++ } else {
++ int i = 0;
++ for (i;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,18 @@ insert:
+ break;
+ case XK_Return:
+ case XK_KP_Enter:
+- puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
+ if (!(ev->state & ControlMask)) {
++ int i = 0;
++ for (i;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;