commit 197a619f167b30880d15a223c6447abb69426016
Author: bit9tream <[email protected]>
Date:   Thu Jun 11 23:49:23 2020 +0300

    patch that allows to select and deselect multiple items
    
    (kinda similar to fzf's multi-select feature)

diff --git 
a/tools.suckless.org/dmenu/patches/multi-selection/dmenu-multi-selection-4.9.diff
 
b/tools.suckless.org/dmenu/patches/multi-selection/dmenu-multi-selection-4.9.diff
new file mode 100644
index 00000000..537ccdc0
--- /dev/null
+++ 
b/tools.suckless.org/dmenu/patches/multi-selection/dmenu-multi-selection-4.9.diff
@@ -0,0 +1,111 @@
+diff --git a/dmenu.c b/dmenu.c
+index 6b8f51b..c1e86b5 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,21 @@ keypress(XKeyEvent *ev)
+                       goto draw;
+               case XK_Return:
+               case XK_KP_Enter:
++                      if (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 +493,19 @@ 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)
++                                      puts(items[selid[i]].text);
++                      if (!issel(sel->id)) {
++                              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] != '+@@ -534,7 +569,7 @@ readstdin(void)
+                       *p = '+                 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;
diff --git a/tools.suckless.org/dmenu/patches/multi-selection/index.md 
b/tools.suckless.org/dmenu/patches/multi-selection/index.md
new file mode 100644
index 00000000..1efbcf2f
--- /dev/null
+++ b/tools.suckless.org/dmenu/patches/multi-selection/index.md
@@ -0,0 +1,15 @@
+Multiple selection
+==============
+
+Description
+-----------
+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.
+
+Download
+--------
+* [dmenu-multi-selection-4.9.diff](dmenu-multi-selection-4.9.diff)
+
+Authors
+-------
+* bit6tream <[email protected]> [bit6tream's 
gitlab](https://gitlab.com/bit9tream)


Reply via email to