summarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Rustand2019-07-20 15:00:06 +0200
committerLars Rustand2019-07-20 15:10:52 +0200
commitd3154998249a2713b5d01240f3bdf34022ac8131 (patch)
treed5ba44e63060735d0b224111fc828030b005bda1
parentf1a8b6b7e7c4c2f675bd1f775cf647743b53c6ff (diff)
downloadaur-d3154998249a2713b5d01240f3bdf34022ac8131.tar.gz
Updated to 4.9
-rw-r--r--.SRCINFO26
-rw-r--r--PKGBUILD24
-rw-r--r--break-fix.diff23
-rw-r--r--dmenu-4.5-fuzzy-fixed.diff94
-rw-r--r--dmenu-4.5-height-fixed.diff84
-rw-r--r--dmenu-4.5-history-fixed.diff216
-rw-r--r--dmenu-4.5-mouse-support.diff143
-rw-r--r--dmenu-4.5-xft.diff418
-rw-r--r--dmenu-4.9.tar.gzbin0 -> 15972 bytes
-rw-r--r--dmenu-fuzzymatch-4.9.diff163
-rw-r--r--dmenu-lineheight-4.9.diff94
-rw-r--r--dmenu-mousesupport-4.7.diff156
-rw-r--r--dmenu-xft-mouse-height-fuzzy-history-4.9-1-x86_64.pkg.tar.xzbin0 -> 30580 bytes
13 files changed, 432 insertions, 1009 deletions
diff --git a/.SRCINFO b/.SRCINFO
index f11d6db9fbfb..93ab50ba83c9 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,7 +1,7 @@
pkgbase = dmenu-xft-mouse-height-fuzzy-history
pkgdesc = Dynamic X menu - with xft, mouse, height, history, and fuzzy search support
- pkgver = 4.5
- pkgrel = 5
+ pkgver = 4.9
+ pkgrel = 1
url = http://tools.suckless.org/dmenu/
arch = i686
arch = x86_64
@@ -12,20 +12,14 @@ pkgbase = dmenu-xft-mouse-height-fuzzy-history
provides = dmenu
conflicts = dmenu
conflicts = dmenu2
- source = http://dl.suckless.org/tools/dmenu-4.5.tar.gz
- source = dmenu-4.5-xft.diff
- source = break-fix.diff
- source = dmenu-4.5-history-fixed.diff
- source = dmenu-4.5-fuzzy-fixed.diff
- source = dmenu-4.5-mouse-support.diff
- source = dmenu-4.5-height-fixed.diff
- md5sums = 9c46169ed703732ec52ed946c27d84b4
- md5sums = 0c73d595eb78f159bea83f33bba15e80
- md5sums = 6921f9d8aabb53f22adcbf5630dff6b8
- md5sums = 8541735789d9810d7020fdba62b72296
- md5sums = 71fc82b76c45499fcd46b3754407f59d
- md5sums = eeec3e11ff68f27ebbc3133ad6549f56
- md5sums = 53b286e8bd76d9225f365673fafd6083
+ source = http://dl.suckless.org/tools/dmenu-4.9.tar.gz
+ source = dmenu-fuzzymatch-4.9.diff
+ source = dmenu-mousesupport-4.7.diff
+ source = dmenu-lineheight-4.9.diff
+ md5sums = 9a537ec9a3a2ce9f08963d66b56cc030
+ md5sums = 10f1d55f242fd34aae6b72b51fd50915
+ md5sums = 274972c3f6de489dd00543a6d653b960
+ md5sums = 0832170eeeec1a70febf641828ddcd17
pkgname = dmenu-xft-mouse-height-fuzzy-history
diff --git a/PKGBUILD b/PKGBUILD
index 14c3d338f494..9b65c23aa0c9 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,7 +1,7 @@
# Maintainer: Franklyn Tackitt
pkgname=dmenu-xft-mouse-height-fuzzy-history
-pkgver=4.5
-pkgrel=5
+pkgver=4.9
+pkgrel=1
pkgdesc="Dynamic X menu - with xft, mouse, height, history, and fuzzy search support"
url="http://tools.suckless.org/dmenu/"
arch=('i686' 'x86_64')
@@ -9,20 +9,14 @@ license=('MIT')
depends=('sh' 'libxinerama' 'libxft')
conflicts=('dmenu' 'dmenu2')
provides=('dmenu')
-patches=(dmenu-4.5-xft.diff
- break-fix.diff
- dmenu-4.5-history-fixed.diff
- dmenu-4.5-fuzzy-fixed.diff
- dmenu-4.5-mouse-support.diff
- dmenu-4.5-height-fixed.diff)
+patches=(dmenu-fuzzymatch-4.9.diff
+ dmenu-mousesupport-4.7.diff
+ dmenu-lineheight-4.9.diff)
source=(http://dl.suckless.org/tools/dmenu-$pkgver.tar.gz "${patches[@]}")
-md5sums=('9c46169ed703732ec52ed946c27d84b4'
- '0c73d595eb78f159bea83f33bba15e80'
- '6921f9d8aabb53f22adcbf5630dff6b8'
- '8541735789d9810d7020fdba62b72296'
- '71fc82b76c45499fcd46b3754407f59d'
- 'eeec3e11ff68f27ebbc3133ad6549f56'
- '53b286e8bd76d9225f365673fafd6083')
+md5sums=('9a537ec9a3a2ce9f08963d66b56cc030'
+ '10f1d55f242fd34aae6b72b51fd50915'
+ '274972c3f6de489dd00543a6d653b960'
+ '0832170eeeec1a70febf641828ddcd17')
prepare() {
cd $srcdir/dmenu-$pkgver
for patch in "${patches[@]}"; do
diff --git a/break-fix.diff b/break-fix.diff
deleted file mode 100644
index 989ee6707961..000000000000
--- a/break-fix.diff
+++ /dev/null
@@ -1,23 +0,0 @@
-diff -upr dmenu-4.5-xft/dmenu.c dmenu-4.5-break/dmenu.c
---- dmenu-4.5-xft/dmenu.c 2014-05-04 17:32:10.896300286 -0600
-+++ dmenu-4.5-break/dmenu.c 2014-05-04 17:31:41.406300227 -0600
-@@ -337,8 +337,9 @@ keypress(XKeyEvent *ev) {
- sel = matchend;
- break;
- case XK_Escape:
-- ret = EXIT_FAILURE;
-- running = False;
-+ ret = EXIT_FAILURE;
-+ running = False;
-+ break;
- case XK_Home:
- if(sel == matches) {
- cursor = 0;
-@@ -378,6 +379,7 @@ keypress(XKeyEvent *ev) {
- puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
- ret = EXIT_SUCCESS;
- running = False;
-+ break;
- case XK_Right:
- if(text[cursor] != '\0') {
- cursor = nextrune(+1);
diff --git a/dmenu-4.5-fuzzy-fixed.diff b/dmenu-4.5-fuzzy-fixed.diff
deleted file mode 100644
index 2db2cf2b026d..000000000000
--- a/dmenu-4.5-fuzzy-fixed.diff
+++ /dev/null
@@ -1,94 +0,0 @@
-diff -rupN orig/dmenu.c new/dmenu.c
---- orig/dmenu.c 2015-02-03 11:21:10.802786099 -0700
-+++ new/dmenu.c 2015-02-03 11:22:45.321029644 -0700
-@@ -34,6 +34,9 @@ static void grabkeyboard(void);
- static void insert(const char *str, ssize_t n);
- static void keypress(XKeyEvent *ev);
- static void match(void);
-+static void match_fuzzy(void);
-+static void match_tokens(void);
-+static char *strchri(const char *s, int c);
- static size_t nextrune(int inc);
- static void paste(void);
- static void readitems(void);
-@@ -64,12 +67,14 @@ static Item *matches, *matchend;
- static Item *prev, *curr, *next, *sel;
- static Window win;
- static XIC xic;
-+static Bool fuzzy;
-
- static char *histfile = NULL;
- static Item *histitems, *histend;
-
- static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
- static char *(*fstrstr)(const char *, const char *) = strstr;
-+static char *(*fstrchr)(const char *, const int) = strchr;
-
- int
- main(int argc, char *argv[]) {
-@@ -86,9 +91,12 @@ main(int argc, char *argv[]) {
- topbar = False;
- else if(!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
- fast = True;
-+ else if(!strcmp(argv[i], "-z")) /* enable fuzzy matching */
-+ fuzzy = True;
- else if(!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
- fstrncmp = strncasecmp;
- fstrstr = cistrstr;
-+ fstrchr = strchri;
- }
- else if(i+1 == argc)
- usage();
-@@ -464,8 +472,52 @@ keypress(XKeyEvent *ev) {
- drawmenu();
- }
-
-+char *
-+strchri(const char *s, int c) {
-+ char *u, *l;
-+ if(!isalpha(c)) return strchr(s, c);
-+ if(isupper(c)) {
-+ u = strchr(s, c);
-+ l = strchr(s, tolower(c));
-+ }
-+ else {
-+ l = strchr(s, c);
-+ u = strchr(s, toupper(c));
-+ }
-+
-+ if(u && l) return u < l ? u : l;
-+ return u == NULL ? l : u;
-+}
-+
- void
- match(void) {
-+ if(fuzzy) match_fuzzy();
-+ else match_tokens();
-+}
-+
-+void
-+match_fuzzy(void) {
-+ int i;
-+ size_t len;
-+ Item *item;
-+
-+ char *pos;
-+
-+ len = strlen(text);
-+
-+ matches = matchend = NULL;
-+ for(item = items; item && item->text; item++) {
-+ i = 0;
-+ for(pos = fstrchr(item->text, text[i]); pos && text[i]; i++, pos = fstrchr(pos+1, text[i]));
-+ if(i == len) appenditem(item, &matches, &matchend);
-+ }
-+
-+ curr = sel = matches;
-+ calcoffsets();
-+}
-+
-+void
-+match_tokens(void) {
- static char **tokv = NULL;
- static int tokn = 0;
-
diff --git a/dmenu-4.5-height-fixed.diff b/dmenu-4.5-height-fixed.diff
deleted file mode 100644
index 8186a90f3668..000000000000
--- a/dmenu-4.5-height-fixed.diff
+++ /dev/null
@@ -1,84 +0,0 @@
-diff -rupN orig/dmenu.1 new/dmenu.1
---- orig/dmenu.1 2015-02-03 11:24:25.218280503 -0700
-+++ new/dmenu.1 2015-02-03 11:24:34.434303318 -0700
-@@ -8,6 +8,8 @@ dmenu \- dynamic menu
- .RB [ \-i ]
- .RB [ \-l
- .IR lines ]
-+.RB [ \-h
-+.IR height ]
- .RB [ \-p
- .IR prompt ]
- .RB [ \-fn
-@@ -51,6 +53,9 @@ dmenu matches menu items case insensitiv
- .BI \-l " lines"
- dmenu lists items vertically, with the given number of lines.
- .TP
-+.BI \-h " height"
-+defines the height of the bar in pixels.
-+.TP
- .BI \-p " prompt"
- defines the prompt to be displayed to the left of the input field.
- .TP
-diff -rupN orig/dmenu.c new/dmenu.c
---- orig/dmenu.c 2015-02-03 11:24:25.218280503 -0700
-+++ new/dmenu.c 2015-02-03 11:25:32.430445657 -0700
-@@ -55,7 +55,7 @@ static const char *normbgcolor = "#22222
- static const char *normfgcolor = "#bbbbbb";
- static const char *selbgcolor = "#005577";
- static const char *selfgcolor = "#eeeeee";
--static unsigned int lines = 0;
-+static unsigned int lines, line_height = 0;
- static ColorSet *normcol;
- static ColorSet *selcol;
- static Atom clip, utf8;
-@@ -104,6 +104,8 @@ main(int argc, char *argv[]) {
- /* these options take one argument */
- else if(!strcmp(argv[i], "-l")) /* number of lines in vertical list */
- lines = atoi(argv[++i]);
-+ else if(!strcmp(argv[i], "-h")) /* minimum height of single line */
-+ line_height = atoi(argv[++i]);
- else if(!strcmp(argv[i], "-p")) /* adds prompt to left of input field */
- prompt = argv[++i];
- else if(!strcmp(argv[i], "-fn")) /* font or font set */
-@@ -260,8 +262,8 @@ drawmenu(void) {
- /* draw input field */
- dc->w = (lines > 0 || !matches) ? mw - dc->x : inputw;
- drawtext(dc, text, normcol);
-- if((curpos = textnw(dc, text, cursor) + dc->h/2 - 2) < dc->w)
-- drawrect(dc, curpos, 2, 1, dc->h - 4, True, normcol->FG);
-+ if((curpos = textnw(dc, text, cursor) + dc->font.height/2) < dc->w)
-+ drawrect(dc, curpos, (dc->h - dc->font.height)/2 + 1, 1, dc->font.height -1, True, normcol->FG);
-
- if(lines > 0) {
- /* draw vertical list */
-@@ -800,7 +802,7 @@ setup(void) {
- utf8 = XInternAtom(dc->dpy, "UTF8_STRING", False);
-
- /* calculate menu geometry */
-- bh = dc->font.height + 2;
-+ bh = (line_height > dc->font.height + 2) ? line_height : dc->font.height + 2;
- lines = MAX(lines, 0);
- mh = (lines + 1) * bh;
- #ifdef XINERAMA
-@@ -869,7 +871,7 @@ setup(void) {
-
- void
- usage(void) {
-- fputs("usage: dmenu [-b] [-f] [-i] [-l lines] [-p prompt] [-fn font]\n"
-+ fputs("usage: dmenu [-b] [-f] [-i] [-l lines] [-h height] [-p prompt] [-fn font]\n"
- " [-nb color] [-nf color] [-sb color] [-sf color] [-hist histfile] [-v]\n", stderr);
- exit(EXIT_FAILURE);
- }
-diff -rupN orig/draw.c new/draw.c
---- orig/draw.c 2015-02-03 11:24:25.219280505 -0700
-+++ new/draw.c 2015-02-03 11:24:34.435303320 -0700
-@@ -39,7 +39,7 @@ drawtext(DC *dc, const char *text, Color
- void
- drawtextn(DC *dc, const char *text, size_t n, ColorSet *col) {
- int x = dc->x + dc->font.height/2;
-- int y = dc->y + dc->font.ascent+1;
-+ int y = dc->y + dc->font.ascent + (dc->h - dc->font.height)/2;
-
- XSetForeground(dc->dpy, dc->gc, col->FG);
- if(dc->font.xft_font) {
diff --git a/dmenu-4.5-history-fixed.diff b/dmenu-4.5-history-fixed.diff
deleted file mode 100644
index 4cc660b1334d..000000000000
--- a/dmenu-4.5-history-fixed.diff
+++ /dev/null
@@ -1,216 +0,0 @@
-diff -rupN without/dmenu.1 with/dmenu.1
---- without/dmenu.1 2015-02-03 11:15:59.416937469 -0700
-+++ with/dmenu.1 2015-02-03 11:16:13.160976522 -0700
-@@ -20,6 +20,8 @@ dmenu \- dynamic menu
- .IR color ]
- .RB [ \-sf
- .IR color ]
-+.RB [ \-hist
-+.IR "<filename>" ]
- .RB [ \-v ]
- .P
- .BR dmenu_run " ..."
-@@ -70,6 +72,9 @@ defines the selected background color.
- .BI \-sf " color"
- defines the selected foreground color.
- .TP
-+.BI \-hist " <histfile>"
-+the file to use for history
-+.TP
- .B \-v
- prints version information to stdout, then exits.
- .SH USAGE
-diff -rupN without/dmenu.c with/dmenu.c
---- without/dmenu.c 2015-02-03 11:15:59.416937469 -0700
-+++ with/dmenu.c 2015-02-03 11:19:01.935443821 -0700
-@@ -36,7 +36,7 @@ static void keypress(XKeyEvent *ev);
- static void match(void);
- static size_t nextrune(int inc);
- static void paste(void);
--static void readstdin(void);
-+static void readitems(void);
- static void run(void);
- static void setup(void);
- static void usage(void);
-@@ -65,6 +65,9 @@ static Item *prev, *curr, *next, *sel;
- static Window win;
- static XIC xic;
-
-+static char *histfile = NULL;
-+static Item *histitems, *histend;
-+
- static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
- static char *(*fstrstr)(const char *, const char *) = strstr;
-
-@@ -104,6 +107,8 @@ main(int argc, char *argv[]) {
- selbgcolor = argv[++i];
- else if(!strcmp(argv[i], "-sf")) /* selected foreground color */
- selfgcolor = argv[++i];
-+ else if(!strcmp(argv[i], "-hist"))
-+ histfile = argv[++i];
- else
- usage();
-
-@@ -114,10 +119,10 @@ main(int argc, char *argv[]) {
-
- if(fast) {
- grabkeyboard();
-- readstdin();
-+ readitems();
- }
- else {
-- readstdin();
-+ readitems();
- grabkeyboard();
- }
- setup();
-@@ -127,6 +132,59 @@ main(int argc, char *argv[]) {
- return ret;
- }
-
-+static int
-+writehistory(char *command) {
-+ FILE *f;
-+ Item *histitem;
-+ char *histline;
-+ char *histcmd;
-+ int currcnt = 1;
-+ int histcnt;
-+
-+ if(!histfile || strlen(command) <= 0)
-+ return 0;
-+
-+ if((f = fopen(histfile, "w"))) {
-+ /* get the current count of previous runs for this command */
-+ for(histitem = histitems; histitem && histitem->text; histitem=histitem->right) {
-+ histline = strdup(histitem->text);
-+ histcmd = strsep(&histline, "\t");
-+ if(strcmp(command, histcmd) == 0) {
-+ currcnt = atoi(strsep(&histline, "\t")) + 1;
-+ }
-+ }
-+
-+ /* loop through history printing those with more runs */
-+ for(histitem = histitems; histitem && histitem->text; histitem=histitem->right) {
-+ histline = strdup(histitem->text);
-+ histcmd = strsep(&histline, "\t");
-+ histcnt = atoi(strsep(&histline, "\t"));
-+ if(histcnt > currcnt) {
-+ fprintf(f, "%s", histitem->text);
-+ } else {
-+ break;
-+ }
-+ }
-+
-+ /* print this command now so it's the first in line with this run count */
-+ /* reducing the count by 1 here to keep the next comparison loop simple */
-+ fprintf(f, "%s\t%d\n", command, currcnt--);
-+
-+ /* print all the rest except this command's old line */
-+ for(; histitem && histitem->text; histitem=histitem->right) {
-+ histline = strdup(histitem->text);
-+ histcmd = strsep(&histline, "\t");
-+ histcnt = atoi(strsep(&histline, "\t"));
-+ if(histcnt < currcnt || strcmp(command, histcmd) != 0)
-+ fprintf(f, "%s", histitem->text);
-+ }
-+ fclose(f);
-+ return 1;
-+ }
-+
-+ return 0;
-+}
-+
- void
- appenditem(Item *item, Item **list, Item **last) {
- if(*last)
-@@ -378,6 +436,7 @@ keypress(XKeyEvent *ev) {
- case XK_KP_Enter:
- puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
- ret = EXIT_SUCCESS;
-+ writehistory( (sel == NULL) ? text : sel->text);
- running = False;
- break;
- case XK_Right:
-@@ -484,26 +543,60 @@ paste(void) {
- }
-
- void
--readstdin(void) {
-- char buf[sizeof text], *p, *maxstr = NULL;
-- size_t i, max = 0, size = 0;
-+readitems(void) {
-+ char buf[sizeof text], *p, *maxstr = NULL, *histline, *histcmd;
-+ size_t i = 0, j = 0, k = 0, max = 0, size = 0;
-+ FILE *f;
-+ Bool listed;
-+ Item *histitem;
-+ histitems = histend = NULL;
-+
-+ if(histfile && (f = fopen(histfile, "r"))) {
-+ for(; fgets(buf, sizeof buf, f); i++) {
-+ histitem = malloc(sizeof *histitem);
-+ histitem->text = strdup(buf);
-+ appenditem(histitem, &histitems, &histend);
-+ if(i+1 >= size / sizeof *items)
-+ if(!(items = realloc(items, (size += BUFSIZ))))
-+ eprintf("cannot realloc %u bytes:", size);
-+ if((p = strchr(buf, '\n')))
-+ *p = '\0';
-+ histline = strdup(buf);
-+ histcmd = strsep(&histline, "\t");
-+ if(!(items[i].text = strdup(histcmd)))
-+ eprintf("cannot strdup %u bytes:", strlen(histcmd)+1);
-+ if(strlen(items[i].text) > max)
-+ max = strlen(maxstr = items[i].text);
-+ }
-+ fclose(f);
-+ }
-
- /* read each line from stdin and add it to the item list */
-- for(i = 0; fgets(buf, sizeof buf, stdin); i++) {
-- if(i+1 >= size / sizeof *items)
-- if(!(items = realloc(items, (size += BUFSIZ))))
-- eprintf("cannot realloc %u bytes:", size);
-+ for(j = i; fgets(buf, sizeof buf, stdin); j++) {
- if((p = strchr(buf, '\n')))
- *p = '\0';
-- if(!(items[i].text = strdup(buf)))
-- eprintf("cannot strdup %u bytes:", strlen(buf)+1);
-- if(strlen(items[i].text) > max)
-- max = strlen(maxstr = items[i].text);
-+ listed = False;
-+ for(k = 0; k < i; k++) {
-+ if(strcmp(buf, items[k].text) == 0) {
-+ listed = True;
-+ j--;
-+ break;
-+ }
-+ }
-+ if(!listed) {
-+ if(j+1 >= size / sizeof *items)
-+ if(!(items = realloc(items, (size += BUFSIZ))))
-+ eprintf("cannot realloc %u bytes:", size);
-+ if(!(items[j].text = strdup(buf)))
-+ eprintf("cannot strdup %u bytes:", strlen(buf)+1);
-+ if(strlen(items[j].text) > max)
-+ max = strlen(maxstr = items[j].text);
-+ }
- }
- if(items)
-- items[i].text = NULL;
-+ items[j].text = NULL;
- inputw = maxstr ? textw(dc, maxstr) : 0;
-- lines = MIN(lines, i);
-+ lines = MIN(lines, j);
- }
-
- void
-@@ -617,6 +710,6 @@ setup(void) {
- void
- usage(void) {
- fputs("usage: dmenu [-b] [-f] [-i] [-l lines] [-p prompt] [-fn font]\n"
-- " [-nb color] [-nf color] [-sb color] [-sf color] [-v]\n", stderr);
-+ " [-nb color] [-nf color] [-sb color] [-sf color] [-hist histfile] [-v]\n", stderr);
- exit(EXIT_FAILURE);
- }
diff --git a/dmenu-4.5-mouse-support.diff b/dmenu-4.5-mouse-support.diff
deleted file mode 100644
index d5bb4de2fc8e..000000000000
--- a/dmenu-4.5-mouse-support.diff
+++ /dev/null
@@ -1,143 +0,0 @@
-diff --git a/dmenu.c b/dmenu.c
-index 3962801..a75bf80 100644
---- a/dmenu.c
-+++ b/dmenu.c
-@@ -25,6 +25,7 @@ struct Item {
- };
-
- static void appenditem(Item *item, Item **list, Item **last);
-+static void buttonpress(XEvent *e);
- static void calcoffsets(void);
- static char *cistrstr(const char *s, const char *sub);
- static void drawmenu(void);
-@@ -388,6 +390,109 @@ keypress(XKeyEvent *ev) {
- }
-
- void
-+buttonpress(XEvent *e) {
-+ int curpos;
-+ Item *item;
-+ XButtonPressedEvent *ev = &e->xbutton;
-+
-+ if(ev->window != win)
-+ return;
-+
-+ /* right-click: exit */
-+ if(ev->button == Button3)
-+ exit(EXIT_FAILURE);
-+
-+ dc->x = 0;
-+ dc->y = 0;
-+ dc->h = bh;
-+
-+ if(prompt && *prompt) {
-+ dc->w = promptw;
-+ dc->x = dc->w;
-+ }
-+ /* input field */
-+ dc->w = (lines > 0 || !matches) ? mw - dc->x : inputw;
-+ if((curpos = textnw(dc, text, cursor) + dc->h/2 - 2) < dc->w);
-+
-+ /* left-click on input: clear input,
-+ * NOTE: if there is no left-arrow the space for < is reserved so
-+ * add that to the input width */
-+ if(ev->button == Button1 &&
-+ ((lines <= 0 && ev->x >= 0 && ev->x <= dc->x + dc->w +
-+ ((!prev || !curr->left) ? textw(dc, "<") : 0)) ||
-+ (lines > 0 && ev->y >= dc->y && ev->y <= dc->y + dc->h))) {
-+ insert(NULL, 0 - cursor);
-+ drawmenu();
-+ return;
-+ }
-+ /* middle-mouse click: paste selection */
-+ if(ev->button == Button2) {
-+ XConvertSelection(dc->dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY,
-+ utf8, utf8, win, CurrentTime);
-+ drawmenu();
-+ return;
-+ }
-+ /* scroll up */
-+ if(ev->button == Button4 && prev) {
-+ sel = curr = prev;
-+ calcoffsets();
-+ drawmenu();
-+ return;
-+ }
-+ /* scroll down */
-+ if(ev->button == Button5 && next) {
-+ sel = curr = next;
-+ calcoffsets();
-+ drawmenu();
-+ return;
-+ }
-+ if(ev->button != Button1)
-+ return;
-+ if(lines > 0) {
-+ /* vertical list: left-click on item */
-+ dc->w = mw - dc->x;
-+ for(item = curr; item != next; item = item->right) {
-+ dc->y += dc->h;
-+ if(ev->y >= dc->y && ev->y <= (dc->y + dc->h)) {
-+ puts(item->text);
-+ exit(EXIT_SUCCESS);
-+ }
-+ }
-+ }
-+ else if(matches) {
-+ /* left-click on left arrow */
-+ dc->x += inputw;
-+ dc->w = textw(dc, "<");
-+ if(prev && curr->left) {
-+ if(ev->x >= dc->x && ev->x <= dc->x + dc->w) {
-+ sel = curr = prev;
-+ calcoffsets();
-+ drawmenu();
-+ return;
-+ }
-+ }
-+ /* horizontal list: left-click on item */
-+ for(item = curr; item != next; item = item->right) {
-+ dc->x += dc->w;
-+ dc->w = MIN(textw(dc, item->text), mw - dc->x - textw(dc, ">"));
-+ if(ev->x >= dc->x && ev->x <= (dc->x + dc->w)) {
-+ puts(item->text);
-+ exit(EXIT_SUCCESS);
-+ }
-+ }
-+ /* left-click on right arrow */
-+ dc->w = textw(dc, ">");
-+ dc->x = mw - dc->w;
-+ if(next && ev->x >= dc->x && ev->x <= dc->x + dc->w) {
-+ sel = curr = next;
-+ calcoffsets();
-+ drawmenu();
-+ return;
-+ }
-+ }
-+}
-+
-+void
- match(void) {
- static char **tokv = NULL;
- static int tokn = 0;
-@@ -496,6 +601,9 @@ run(void) {
- if(XFilterEvent(&ev, win))
- continue;
- switch(ev.type) {
-+ case ButtonPress:
-+ buttonpress(&ev);
-+ break;
- case Expose:
- if(ev.xexpose.count == 0)
- mapdc(dc, win, mw, mh);
-@@ -585,8 +693,9 @@ setup(void) {
- /* create menu window */
- swa.override_redirect = True;
- swa.background_pixel = normcol->BG;
-- swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
-+ swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask |
-+ ButtonPressMask;
- win = XCreateWindow(dc->dpy, root, x, y, mw, mh, 0,
- DefaultDepth(dc->dpy, screen), CopyFromParent,
- DefaultVisual(dc->dpy, screen),
- CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
diff --git a/dmenu-4.5-xft.diff b/dmenu-4.5-xft.diff
deleted file mode 100644
index ff93337ca276..000000000000
--- a/dmenu-4.5-xft.diff
+++ /dev/null
@@ -1,418 +0,0 @@
-diff -upr a/config.mk b/config.mk
---- a/config.mk 2012-01-10 19:03:22.000000000 +0200
-+++ b/config.mk 2012-01-10 19:03:38.000000000 +0200
-@@ -12,9 +12,13 @@ X11LIB = /usr/X11R6/lib
- XINERAMALIBS = -lXinerama
- XINERAMAFLAGS = -DXINERAMA
-
-+# Xft, comment if you don't want it
-+XFTINC = -I/usr/include/freetype2
-+XFTLIBS = -lXft -lXrender -lfreetype -lz -lfontconfig
-+
- # includes and libs
--INCS = -I${X11INC}
--LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS}
-+INCS = -I${X11INC} ${XFTINC}
-+LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${XFTLIBS}
-
- # flags
- CPPFLAGS = -D_BSD_SOURCE -D_POSIX_C_SOURCE=2 -DVERSION=\"${VERSION}\" ${XINERAMAFLAGS}
-diff -upr a/dmenu.1 b/dmenu.1
---- a/dmenu.1 2012-01-10 19:14:19.000000000 +0200
-+++ b/dmenu.1 2012-01-10 19:14:23.000000000 +0200
-@@ -53,7 +53,7 @@ dmenu lists items vertically, with the g
- defines the prompt to be displayed to the left of the input field.
- .TP
- .BI \-fn " font"
--defines the font or font set used.
-+defines the font or font set used. eg. "fixed" or "Monospace-12:normal" (an xft font)
- .TP
- .BI \-nb " color"
- defines the normal background color.
-diff -upr a/dmenu.c b/dmenu.c
---- a/dmenu.c 2012-01-10 19:14:19.000000000 +0200
-+++ b/dmenu.c 2012-01-10 19:24:39.000000000 +0200
-@@ -17,6 +17,7 @@
- * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org)))
- #define MIN(a,b) ((a) < (b) ? (a) : (b))
- #define MAX(a,b) ((a) > (b) ? (a) : (b))
-+#define DEFFONT "fixed" /* xft example: "Monospace-11" */
-
- typedef struct Item Item;
- struct Item {
-@@ -26,6 +27,7 @@ struct Item {
-
- static void appenditem(Item *item, Item **list, Item **last);
- static void calcoffsets(void);
-+static void cleanup(void);
- static char *cistrstr(const char *s, const char *sub);
- static void drawmenu(void);
- static void grabkeyboard(void);
-@@ -50,10 +52,12 @@ static const char *normfgcolor = "#bbbbb
- static const char *selbgcolor = "#005577";
- static const char *selfgcolor = "#eeeeee";
- static unsigned int lines = 0;
--static unsigned long normcol[ColLast];
--static unsigned long selcol[ColLast];
-+static ColorSet *normcol;
-+static ColorSet *selcol;
- static Atom clip, utf8;
- static Bool topbar = True;
-+static Bool running = True;
-+static int ret = 0;
- static DC *dc;
- static Item *items = NULL;
- static Item *matches, *matchend;
-@@ -104,7 +108,9 @@ main(int argc, char *argv[]) {
- usage();
-
- dc = initdc();
-- initfont(dc, font);
-+ initfont(dc, font ? font : DEFFONT);
-+ normcol = initcolor(dc, normfgcolor, normbgcolor);
-+ selcol = initcolor(dc, selfgcolor, selbgcolor);
-
- if(fast) {
- grabkeyboard();
-@@ -117,7 +123,8 @@ main(int argc, char *argv[]) {
- setup();
- run();
-
-- return 1; /* unreachable */
-+ cleanup();
-+ return ret;
- }
-
- void
-@@ -160,6 +167,15 @@ cistrstr(const char *s, const char *sub)
- }
-
- void
-+cleanup(void) {
-+ freecol(dc, normcol);
-+ freecol(dc, selcol);
-+ XDestroyWindow(dc->dpy, win);
-+ XUngrabKeyboard(dc->dpy, CurrentTime);
-+ freedc(dc);
-+}
-+
-+void
- drawmenu(void) {
- int curpos;
- Item *item;
-@@ -167,7 +183,7 @@ drawmenu(void) {
- dc->x = 0;
- dc->y = 0;
- dc->h = bh;
-- drawrect(dc, 0, 0, mw, mh, True, BG(dc, normcol));
-+ drawrect(dc, 0, 0, mw, mh, True, normcol->BG);
-
- if(prompt) {
- dc->w = promptw;
-@@ -178,7 +194,7 @@ drawmenu(void) {
- dc->w = (lines > 0 || !matches) ? mw - dc->x : inputw;
- drawtext(dc, text, normcol);
- if((curpos = textnw(dc, text, cursor) + dc->h/2 - 2) < dc->w)
-- drawrect(dc, curpos, 2, 1, dc->h - 4, True, FG(dc, normcol));
-+ drawrect(dc, curpos, 2, 1, dc->h - 4, True, normcol->FG);
-
- if(lines > 0) {
- /* draw vertical list */
-@@ -321,7 +337,8 @@ keypress(XKeyEvent *ev) {
- sel = matchend;
- break;
- case XK_Escape:
-- exit(EXIT_FAILURE);
-+ ret = EXIT_FAILURE;
-+ running = False;
- case XK_Home:
- if(sel == matches) {
- cursor = 0;
-@@ -359,7 +376,8 @@ keypress(XKeyEvent *ev) {
- case XK_Return:
- case XK_KP_Enter:
- puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
-- exit(EXIT_SUCCESS);
-+ ret = EXIT_SUCCESS;
-+ running = False;
- case XK_Right:
- if(text[cursor] != '\0') {
- cursor = nextrune(+1);
-@@ -490,7 +508,7 @@ void
- run(void) {
- XEvent ev;
-
-- while(!XNextEvent(dc->dpy, &ev)) {
-+ while(running && !XNextEvent(dc->dpy, &ev)) {
- if(XFilterEvent(&ev, win))
- continue;
- switch(ev.type) {
-@@ -524,11 +542,6 @@ setup(void) {
- XineramaScreenInfo *info;
- #endif
-
-- normcol[ColBG] = getcolor(dc, normbgcolor);
-- normcol[ColFG] = getcolor(dc, normfgcolor);
-- selcol[ColBG] = getcolor(dc, selbgcolor);
-- selcol[ColFG] = getcolor(dc, selfgcolor);
--
- clip = XInternAtom(dc->dpy, "CLIPBOARD", False);
- utf8 = XInternAtom(dc->dpy, "UTF8_STRING", False);
-
-@@ -582,7 +595,7 @@ setup(void) {
-
- /* create menu window */
- swa.override_redirect = True;
-- swa.background_pixel = normcol[ColBG];
-+ swa.background_pixel = normcol->BG;
- swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
- win = XCreateWindow(dc->dpy, root, x, y, mw, mh, 0,
- DefaultDepth(dc->dpy, screen), CopyFromParent,
-diff -upr a/draw.c b/draw.c
---- a/draw.c 2012-01-10 19:14:19.000000000 +0200
-+++ b/draw.c 2012-01-10 19:14:23.000000000 +0200
-@@ -9,9 +9,6 @@
-
- #define MAX(a, b) ((a) > (b) ? (a) : (b))
- #define MIN(a, b) ((a) < (b) ? (a) : (b))
--#define DEFAULTFN "fixed"
--
--static Bool loadfont(DC *dc, const char *fontstr);
-
- void
- drawrect(DC *dc, int x, int y, unsigned int w, unsigned int h, Bool fill, unsigned long color) {
-@@ -23,7 +20,7 @@ drawrect(DC *dc, int x, int y, unsigned
- }
-
- void
--drawtext(DC *dc, const char *text, unsigned long col[ColLast]) {
-+drawtext(DC *dc, const char *text, ColorSet *col) {
- char buf[BUFSIZ];
- size_t mn, n = strlen(text);
-
-@@ -35,19 +32,24 @@ drawtext(DC *dc, const char *text, unsig
- if(mn < n)
- for(n = MAX(mn-3, 0); n < mn; buf[n++] = '.');
-
-- drawrect(dc, 0, 0, dc->w, dc->h, True, BG(dc, col));
-+ drawrect(dc, 0, 0, dc->w, dc->h, True, col->BG);
- drawtextn(dc, buf, mn, col);
- }
-
- void
--drawtextn(DC *dc, const char *text, size_t n, unsigned long col[ColLast]) {
-+drawtextn(DC *dc, const char *text, size_t n, ColorSet *col) {
- int x = dc->x + dc->font.height/2;
- int y = dc->y + dc->font.ascent+1;
-
-- XSetForeground(dc->dpy, dc->gc, FG(dc, col));
-- if(dc->font.set)
-+ XSetForeground(dc->dpy, dc->gc, col->FG);
-+ if(dc->font.xft_font) {
-+ if (!dc->xftdraw)
-+ eprintf("error, xft drawable does not exist");
-+ XftDrawStringUtf8(dc->xftdraw, &col->FG_xft,
-+ dc->font.xft_font, x, y, (unsigned char*)text, n);
-+ } else if(dc->font.set) {
- XmbDrawString(dc->dpy, dc->canvas, dc->font.set, dc->gc, x, y, text, n);
-- else {
-+ } else {
- XSetFont(dc->dpy, dc->gc, dc->font.xfont->fid);
- XDrawString(dc->dpy, dc->canvas, dc->gc, x, y, text, n);
- }
-@@ -69,16 +71,33 @@ eprintf(const char *fmt, ...) {
- }
-
- void
-+freecol(DC *dc, ColorSet *col) {
-+ if(col) {
-+ if(&col->FG_xft)
-+ XftColorFree(dc->dpy, DefaultVisual(dc->dpy, DefaultScreen(dc->dpy)),
-+ DefaultColormap(dc->dpy, DefaultScreen(dc->dpy)), &col->FG_xft);
-+ free(col);
-+ }
-+}
-+
-+void
- freedc(DC *dc) {
-+ if(dc->font.xft_font) {
-+ XftFontClose(dc->dpy, dc->font.xft_font);
-+ XftDrawDestroy(dc->xftdraw);
-+ }
- if(dc->font.set)
- XFreeFontSet(dc->dpy, dc->font.set);
-- if(dc->font.xfont)
-+ if(dc->font.xfont)
- XFreeFont(dc->dpy, dc->font.xfont);
-- if(dc->canvas)
-+ if(dc->canvas)
- XFreePixmap(dc->dpy, dc->canvas);
-- XFreeGC(dc->dpy, dc->gc);
-- XCloseDisplay(dc->dpy);
-- free(dc);
-+ if(dc->gc)
-+ XFreeGC(dc->dpy, dc->gc);
-+ if(dc->dpy)
-+ XCloseDisplay(dc->dpy);
-+ if(dc)
-+ free(dc);
- }
-
- unsigned long
-@@ -91,6 +110,20 @@ getcolor(DC *dc, const char *colstr) {
- return color.pixel;
- }
-
-+ColorSet *
-+initcolor(DC *dc, const char * foreground, const char * background) {
-+ ColorSet * col = (ColorSet *)malloc(sizeof(ColorSet));
-+ if(!col)
-+ eprintf("error, cannot allocate memory for color set");
-+ col->BG = getcolor(dc, background);
-+ col->FG = getcolor(dc, foreground);
-+ if(dc->font.xft_font)
-+ if(!XftColorAllocName(dc->dpy, DefaultVisual(dc->dpy, DefaultScreen(dc->dpy)),
-+ DefaultColormap(dc->dpy, DefaultScreen(dc->dpy)), foreground, &col->FG_xft))
-+ eprintf("error, cannot allocate xft font color '%s'\n", foreground);
-+ return col;
-+}
-+
- DC *
- initdc(void) {
- DC *dc;
-@@ -109,39 +142,33 @@ initdc(void) {
-
- void
- initfont(DC *dc, const char *fontstr) {
-- if(!loadfont(dc, fontstr ? fontstr : DEFAULTFN)) {
-- if(fontstr != NULL)
-- fprintf(stderr, "cannot load font '%s'\n", fontstr);
-- if(fontstr == NULL || !loadfont(dc, DEFAULTFN))
-- eprintf("cannot load font '%s'\n", DEFAULTFN);
-- }
-- dc->font.height = dc->font.ascent + dc->font.descent;
--}
--
--Bool
--loadfont(DC *dc, const char *fontstr) {
- char *def, **missing, **names;
- int i, n;
- XFontStruct **xfonts;
-
-- if(!*fontstr)
-- return False;
-- if((dc->font.set = XCreateFontSet(dc->dpy, fontstr, &missing, &n, &def))) {
-+ missing = NULL;
-+ if((dc->font.xfont = XLoadQueryFont(dc->dpy, fontstr))) {
-+ dc->font.ascent = dc->font.xfont->ascent;
-+ dc->font.descent = dc->font.xfont->descent;
-+ dc->font.width = dc->font.xfont->max_bounds.width;
-+ } else if((dc->font.set = XCreateFontSet(dc->dpy, fontstr, &missing, &n, &def))) {
- n = XFontsOfFontSet(dc->font.set, &xfonts, &names);
- for(i = 0; i < n; i++) {
- dc->font.ascent = MAX(dc->font.ascent, xfonts[i]->ascent);
- dc->font.descent = MAX(dc->font.descent, xfonts[i]->descent);
- dc->font.width = MAX(dc->font.width, xfonts[i]->max_bounds.width);
- }
-- }
-- else if((dc->font.xfont = XLoadQueryFont(dc->dpy, fontstr))) {
-- dc->font.ascent = dc->font.xfont->ascent;
-- dc->font.descent = dc->font.xfont->descent;
-- dc->font.width = dc->font.xfont->max_bounds.width;
-+ } else if((dc->font.xft_font = XftFontOpenName(dc->dpy, DefaultScreen(dc->dpy), fontstr))) {
-+ dc->font.ascent = dc->font.xft_font->ascent;
-+ dc->font.descent = dc->font.xft_font->descent;
-+ dc->font.width = dc->font.xft_font->max_advance_width;
-+ } else {
-+ eprintf("cannot load font '%s'\n", fontstr);
- }
- if(missing)
- XFreeStringList(missing);
-- return dc->font.set || dc->font.xfont;
-+ dc->font.height = dc->font.ascent + dc->font.descent;
-+ return;
- }
-
- void
-@@ -151,20 +178,29 @@ mapdc(DC *dc, Window win, unsigned int w
-
- void
- resizedc(DC *dc, unsigned int w, unsigned int h) {
-+ int screen = DefaultScreen(dc->dpy);
- if(dc->canvas)
- XFreePixmap(dc->dpy, dc->canvas);
-
- dc->w = w;
- dc->h = h;
- dc->canvas = XCreatePixmap(dc->dpy, DefaultRootWindow(dc->dpy), w, h,
-- DefaultDepth(dc->dpy, DefaultScreen(dc->dpy)));
-+ DefaultDepth(dc->dpy, screen));
-+ if(dc->font.xft_font && !(dc->xftdraw)) {
-+ dc->xftdraw = XftDrawCreate(dc->dpy, dc->canvas, DefaultVisual(dc->dpy,screen), DefaultColormap(dc->dpy,screen));
-+ if(!(dc->xftdraw))
-+ eprintf("error, cannot create xft drawable\n");
-+ }
- }
-
- int
- textnw(DC *dc, const char *text, size_t len) {
-- if(dc->font.set) {
-+ if(dc->font.xft_font) {
-+ XGlyphInfo gi;
-+ XftTextExtentsUtf8(dc->dpy, dc->font.xft_font, (const FcChar8*)text, len, &gi);
-+ return gi.width;
-+ } else if(dc->font.set) {
- XRectangle r;
--
- XmbTextExtents(dc->font.set, text, len, NULL, &r);
- return r.width;
- }
-diff -upr a/draw.h b/draw.h
---- a/draw.h 2012-01-10 19:14:19.000000000 +0200
-+++ b/draw.h 2012-01-10 19:14:23.000000000 +0200
-@@ -1,9 +1,6 @@
- /* See LICENSE file for copyright and license details. */
-
--#define FG(dc, col) ((col)[(dc)->invert ? ColBG : ColFG])
--#define BG(dc, col) ((col)[(dc)->invert ? ColFG : ColBG])
--
--enum { ColBG, ColFG, ColBorder, ColLast };
-+#include <X11/Xft/Xft.h>
-
- typedef struct {
- int x, y, w, h;
-@@ -11,6 +8,7 @@ typedef struct {
- Display *dpy;
- GC gc;
- Pixmap canvas;
-+ XftDraw *xftdraw;
- struct {
- int ascent;
- int descent;
-@@ -18,15 +16,24 @@ typedef struct {
- int width;
- XFontSet set;
- XFontStruct *xfont;
-+ XftFont *xft_font;
- } font;
- } DC; /* draw context */
-
-+typedef struct {
-+ unsigned long FG;
-+ XftColor FG_xft;
-+ unsigned long BG;
-+} ColorSet;
-+
- void drawrect(DC *dc, int x, int y, unsigned int w, unsigned int h, Bool fill, unsigned long color);
--void drawtext(DC *dc, const char *text, unsigned long col[ColLast]);
--void drawtextn(DC *dc, const char *text, size_t n, unsigned long col[ColLast]);
-+void drawtext(DC *dc, const char *text, ColorSet *col);
-+void drawtextn(DC *dc, const char *text, size_t n, ColorSet *col);
-+void freecol(DC *dc, ColorSet *col);
- void eprintf(const char *fmt, ...);
- void freedc(DC *dc);
- unsigned long getcolor(DC *dc, const char *colstr);
-+ColorSet *initcolor(DC *dc, const char *foreground, const char *background);
- DC *initdc(void);
- void initfont(DC *dc, const char *fontstr);
- void mapdc(DC *dc, Window win, unsigned int w, unsigned int h);
diff --git a/dmenu-4.9.tar.gz b/dmenu-4.9.tar.gz
new file mode 100644
index 000000000000..da7255d3f201
--- /dev/null
+++ b/dmenu-4.9.tar.gz
Binary files differ
diff --git a/dmenu-fuzzymatch-4.9.diff b/dmenu-fuzzymatch-4.9.diff
new file mode 100644
index 000000000000..9fd206d8bc9d
--- /dev/null
+++ b/dmenu-fuzzymatch-4.9.diff
@@ -0,0 +1,163 @@
+From 94353eb52055927d9079f3d9e33da1c954abf386 Mon Sep 17 00:00:00 2001
+From: aleks <aleks.stier@icloud.com>
+Date: Wed, 26 Jun 2019 13:25:10 +0200
+Subject: [PATCH] Add support for fuzzy-matching
+
+---
+ config.def.h | 1 +
+ config.mk | 2 +-
+ dmenu.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 91 insertions(+), 1 deletion(-)
+
+diff --git a/config.def.h b/config.def.h
+index 1edb647..51612b9 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -2,6 +2,7 @@
+ /* Default settings; can be overriden by command line. */
+
+ static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
++static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */
+ /* -fn option overrides fonts[0]; default X11 font or font set */
+ static const char *fonts[] = {
+ "monospace:size=10"
+diff --git a/config.mk b/config.mk
+index 0929b4a..d14309a 100644
+--- a/config.mk
++++ b/config.mk
+@@ -20,7 +20,7 @@ FREETYPEINC = /usr/include/freetype2
+
+ # includes and libs
+ INCS = -I$(X11INC) -I$(FREETYPEINC)
+-LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)
++LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm
+
+ # flags
+ CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS)
+diff --git a/dmenu.c b/dmenu.c
+index 6b8f51b..96ddc98 100644
+--- a/dmenu.c
++++ b/dmenu.c
+@@ -1,6 +1,7 @@
+ /* See LICENSE file for copyright and license details. */
+ #include <ctype.h>
+ #include <locale.h>
++#include <math.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+@@ -32,6 +33,7 @@ struct item {
+ char *text;
+ struct item *left, *right;
+ int out;
++ double distance;
+ };
+
+ static char text[BUFSIZ] = "";
+@@ -210,9 +212,94 @@ grabkeyboard(void)
+ die("cannot grab keyboard");
+ }
+
++int
++compare_distance(const void *a, const void *b)
++{
++ struct item *da = *(struct item **) a;
++ struct item *db = *(struct item **) b;
++
++ if (!db)
++ return 1;
++ if (!da)
++ return -1;
++
++ return da->distance == db->distance ? 0 : da->distance < db->distance ? -1 : 1;
++}
++
++void
++fuzzymatch(void)
++{
++ /* bang - we have so much memory */
++ struct item *it;
++ struct item **fuzzymatches = NULL;
++ char c;
++ int number_of_matches = 0, i, pidx, sidx, eidx;
++ int text_len = strlen(text), itext_len;
++
++ matches = matchend = NULL;
++
++ /* walk through all items */
++ for (it = items; it && it->text; it++) {
++ if (text_len) {
++ itext_len = strlen(it->text);
++ pidx = 0; /* pointer */
++ sidx = eidx = -1; /* start of match, end of match */
++ /* walk through item text */
++ for (i = 0; i < itext_len && (c = it->text[i]); i++) {
++ /* fuzzy match pattern */
++ if (!fstrncmp(&text[pidx], &c, 1)) {
++ if(sidx == -1)
++ sidx = i;
++ pidx++;
++ if (pidx == text_len) {
++ eidx = i;
++ break;
++ }
++ }
++ }
++ /* build list of matches */
++ if (eidx != -1) {
++ /* compute distance */
++ /* add penalty if match starts late (log(sidx+2))
++ * add penalty for long a match without many matching characters */
++ it->distance = log(sidx + 2) + (double)(eidx - sidx - text_len);
++ /* fprintf(stderr, "distance %s %f\n", it->text, it->distance); */
++ appenditem(it, &matches, &matchend);
++ number_of_matches++;
++ }
++ } else {
++ appenditem(it, &matches, &matchend);
++ }
++ }
++
++ if (number_of_matches) {
++ /* initialize array with matches */
++ if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*))))
++ die("cannot realloc %u bytes:", number_of_matches * sizeof(struct item*));
++ for (i = 0, it = matches; it && i < number_of_matches; i++, it = it->right) {
++ fuzzymatches[i] = it;
++ }
++ /* sort matches according to distance */
++ qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance);
++ /* rebuild list of matches */
++ matches = matchend = NULL;
++ for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \
++ it->text; i++, it = fuzzymatches[i]) {
++ appenditem(it, &matches, &matchend);
++ }
++ free(fuzzymatches);
++ }
++ curr = sel = matches;
++ calcoffsets();
++}
++
+ static void
+ match(void)
+ {
++ if (fuzzy) {
++ fuzzymatch();
++ return;
++ }
+ static char **tokv = NULL;
+ static int tokn = 0;
+
+@@ -702,6 +789,8 @@ main(int argc, char *argv[])
+ topbar = 0;
+ else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */
+ fast = 1;
++ else if (!strcmp(argv[i], "-F")) /* grabs keyboard before reading stdin */
++ fuzzy = 0;
+ else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
+ fstrncmp = strncasecmp;
+ fstrstr = cistrstr;
+--
+2.22.0
+
diff --git a/dmenu-lineheight-4.9.diff b/dmenu-lineheight-4.9.diff
new file mode 100644
index 000000000000..d12c77afa605
--- /dev/null
+++ b/dmenu-lineheight-4.9.diff
@@ -0,0 +1,94 @@
+From 87f92a561c31246f6f9effc0e89ef92677c87746 Mon Sep 17 00:00:00 2001
+From: astier <aleksandrs.stier@uni-bielefeld.de>
+Date: Wed, 27 Feb 2019 21:44:55 +0100
+Subject: [PATCH] Add an option which defines the lineheight
+
+Despite both the panel and dmenu using the same font (a Terminus 12),
+dmenu is shorter and the panel is visible from under the dmenu bar.
+The appearance can be even more distracting when using similar colors
+for background and selections. With the option added by this patch,
+dmenu can be launched with a '-h 24', thus completely covering the panel.
+---
+ config.def.h | 1 +
+ dmenu.1 | 3 +++
+ dmenu.c | 10 ++++++++--
+ 3 files changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 1edb647..317fa2f 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -15,6 +15,7 @@ static const char *colors[SchemeLast][2] = {
+ };
+ /* -l option; if nonzero, dmenu uses vertical list with given number of lines */
+ static unsigned int lines = 0;
++static unsigned int lineheight = 0; /* -h option; minimum height of a menu line */
+
+ /*
+ * Characters not considered part of a word while deleting words
+diff --git a/dmenu.1 b/dmenu.1
+index 323f93c..7ef34d2 100644
+--- a/dmenu.1
++++ b/dmenu.1
+@@ -50,6 +50,9 @@ dmenu matches menu items case insensitively.
+ .BI \-l " lines"
+ dmenu lists items vertically, with the given number of lines.
+ .TP
++.BI \-h " height"
++dmenu uses a menu line of at least 'height' pixels tall, but no less than 8.
++.TP
+ .BI \-m " monitor"
+ dmenu is displayed on the monitor number supplied. Monitor numbers are starting
+ from 0.
+diff --git a/dmenu.c b/dmenu.c
+index 6b8f51b..45d1946 100644
+--- a/dmenu.c
++++ b/dmenu.c
+@@ -131,7 +131,7 @@ drawmenu(void)
+ {
+ unsigned int curpos;
+ struct item *item;
+- int x = 0, y = 0, w;
++ int x = 0, y = 0, fh = drw->fonts->h, w;
+
+ drw_setscheme(drw, scheme[SchemeNorm]);
+ drw_rect(drw, 0, 0, mw, mh, 1, 1);
+@@ -148,7 +148,7 @@ drawmenu(void)
+ curpos = TEXTW(text) - TEXTW(&text[cursor]);
+ if ((curpos += lrpad / 2 - 1) < w) {
+ drw_setscheme(drw, scheme[SchemeNorm]);
+- drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0);
++ drw_rect(drw, x + curpos, 2 + (bh-fh)/2, 2, fh - 4, 1, 0);
+ }
+
+ if (lines > 0) {
+@@ -604,6 +604,7 @@ setup(void)
+
+ /* calculate menu geometry */
+ bh = drw->fonts->h + 2;
++ bh = MAX(bh,lineheight); /* make a menu line AT LEAST 'lineheight' tall */
+ lines = MAX(lines, 0);
+ mh = (lines + 1) * bh;
+ #ifdef XINERAMA
+@@ -683,6 +684,7 @@ static void
+ usage(void)
+ {
+ fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
++ " [-h height]\n"
+ " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
+ exit(1);
+ }
+@@ -716,6 +718,10 @@ main(int argc, char *argv[])
+ prompt = argv[++i];
+ else if (!strcmp(argv[i], "-fn")) /* font or font set */
+ fonts[0] = argv[++i];
++ else if(!strcmp(argv[i], "-h")) { /* minimum height of one menu line */
++ lineheight = atoi(argv[++i]);
++ lineheight = MAX(lineheight,8); /* reasonable default in case of value too small/negative */
++ }
+ else if (!strcmp(argv[i], "-nb")) /* normal background color */
+ colors[SchemeNorm][ColBg] = argv[++i];
+ else if (!strcmp(argv[i], "-nf")) /* normal foreground color */
+--
+2.21.0
+
diff --git a/dmenu-mousesupport-4.7.diff b/dmenu-mousesupport-4.7.diff
new file mode 100644
index 000000000000..b72bd862b9be
--- /dev/null
+++ b/dmenu-mousesupport-4.7.diff
@@ -0,0 +1,156 @@
+From 27f62488ceb466f73f682f5104825c60712bb5ff Mon Sep 17 00:00:00 2001
+From: Hiltjo Posthuma <hiltjo@codemadness.org>
+Date: Fri, 9 Jun 2017 13:00:06 +0200
+Subject: [PATCH] dmenu mouse support
+
+---
+ dmenu.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
+ 1 file changed, 118 insertions(+), 1 deletion(-)
+
+diff --git a/dmenu.c b/dmenu.c
+index d605ab4..0c8500b 100644
+--- a/dmenu.c
++++ b/dmenu.c
+@@ -459,6 +459,119 @@ keypress(XKeyEvent *ev)
+ }
+
+ static void
++buttonpress(XEvent *e)
++{
++ struct item *item;
++ XButtonPressedEvent *ev = &e->xbutton;
++ int x = 0, y = 0, h = bh, w;
++
++ if (ev->window != win)
++ return;
++
++ /* right-click: exit */
++ if (ev->button == Button3)
++ exit(1);
++
++ if (prompt && *prompt)
++ x += promptw;
++
++ /* input field */
++ w = (lines > 0 || !matches) ? mw - x : inputw;
++
++ /* left-click on input: clear input,
++ * NOTE: if there is no left-arrow the space for < is reserved so
++ * add that to the input width */
++ if (ev->button == Button1 &&
++ ((lines <= 0 && ev->x >= 0 && ev->x <= x + w +
++ ((!prev || !curr->left) ? TEXTW("<") : 0)) ||
++ (lines > 0 && ev->y >= y && ev->y <= y + h))) {
++ insert(NULL, -cursor);
++ drawmenu();
++ return;
++ }
++ /* middle-mouse click: paste selection */
++ if (ev->button == Button2) {
++ XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY,
++ utf8, utf8, win, CurrentTime);
++ drawmenu();
++ return;
++ }
++ /* scroll up */
++ if (ev->button == Button4 && prev) {
++ sel = curr = prev;
++ calcoffsets();
++ drawmenu();
++ return;
++ }
++ /* scroll down */
++ if (ev->button == Button5 && next) {
++ sel = curr = next;
++ calcoffsets();
++ drawmenu();
++ return;
++ }
++ if (ev->button != Button1)
++ return;
++ if (ev->state & ~ControlMask)
++ return;
++ if (lines > 0) {
++ /* vertical list: (ctrl)left-click on item */
++ w = mw - x;
++ for (item = curr; item != next; item = item->right) {
++ y += h;
++ if (ev->y >= y && ev->y <= (y + h)) {
++ puts(item->text);
++ if (!(ev->state & ControlMask))
++ exit(0);
++ sel = item;
++ if (sel) {
++ sel->out = 1;
++ drawmenu();
++ }
++ return;
++ }
++ }
++ } else if (matches) {
++ /* left-click on left arrow */
++ x += inputw;
++ w = TEXTW("<");
++ if (prev && curr->left) {
++ if (ev->x >= x && ev->x <= x + w) {
++ sel = curr = prev;
++ calcoffsets();
++ drawmenu();
++ return;
++ }
++ }
++ /* horizontal list: (ctrl)left-click on item */
++ for (item = curr; item != next; item = item->right) {
++ x += w;
++ w = MIN(TEXTW(item->text), mw - x - TEXTW(">"));
++ if (ev->x >= x && ev->x <= x + w) {
++ puts(item->text);
++ if (!(ev->state & ControlMask))
++ exit(0);
++ sel = item;
++ if (sel) {
++ sel->out = 1;
++ drawmenu();
++ }
++ return;
++ }
++ }
++ /* left-click on right arrow */
++ w = TEXTW(">");
++ x = mw - w;
++ if (next && ev->x >= x && ev->x <= x + w) {
++ sel = curr = next;
++ calcoffsets();
++ drawmenu();
++ return;
++ }
++ }
++}
++
++static void
+ paste(void)
+ {
+ char *p, *q;
+@@ -512,6 +625,9 @@ run(void)
+ if (XFilterEvent(&ev, win))
+ continue;
+ switch(ev.type) {
++ case ButtonPress:
++ buttonpress(&ev);
++ break;
+ case Expose:
+ if (ev.xexpose.count == 0)
+ drw_map(drw, win, 0, 0, mw, mh);
+@@ -609,7 +725,8 @@ setup(void)
+ /* create menu window */
+ swa.override_redirect = True;
+ swa.background_pixel = scheme[SchemeNorm][ColBg].pixel;
+- swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
++ swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask |
++ ButtonPressMask;
+ win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
+ CopyFromParent, CopyFromParent, CopyFromParent,
+ CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
+--
+2.12.2
+
diff --git a/dmenu-xft-mouse-height-fuzzy-history-4.9-1-x86_64.pkg.tar.xz b/dmenu-xft-mouse-height-fuzzy-history-4.9-1-x86_64.pkg.tar.xz
new file mode 100644
index 000000000000..65d9278dae8c
--- /dev/null
+++ b/dmenu-xft-mouse-height-fuzzy-history-4.9-1-x86_64.pkg.tar.xz
Binary files differ