From 0c664be40b6a81727bbefaceff053598766cfa2b Mon Sep 17 00:00:00 2001
From: justsaumit <justsaumit@draconyan.xyz>
Date: Wed, 2 Mar 2022 09:21:44 +0530
Subject: removed numbers patch

---
 config.def.h                                     |  24 ---
 patches/4.dmenu-instant-4.7.diff                 |  73 +++++++
 patches/4.dmenu-numbers-4.9.diff                 |  81 -------
 patches/5.dmenu-instant-4.7.diff                 |  73 -------
 patches/5.dmenu-mousesupport-5.1.diff            | 144 +++++++++++++
 patches/6.dmenu-mousesupport-5.1.diff            | 144 -------------
 patches/6.dmenu-textscroll-20180607-a314412.diff | 245 ++++++++++++++++++++++
 patches/7.dmenu-navhistory-5.0.diff              | 256 +++++++++++++++++++++++
 patches/7.dmenu-textscroll-20180607-a314412.diff | 245 ----------------------
 patches/8.dmenu-navhistory-5.0.diff              | 256 -----------------------
 10 files changed, 718 insertions(+), 823 deletions(-)
 delete mode 100644 config.def.h
 create mode 100644 patches/4.dmenu-instant-4.7.diff
 delete mode 100644 patches/4.dmenu-numbers-4.9.diff
 delete mode 100644 patches/5.dmenu-instant-4.7.diff
 create mode 100644 patches/5.dmenu-mousesupport-5.1.diff
 delete mode 100644 patches/6.dmenu-mousesupport-5.1.diff
 create mode 100644 patches/6.dmenu-textscroll-20180607-a314412.diff
 create mode 100644 patches/7.dmenu-navhistory-5.0.diff
 delete mode 100644 patches/7.dmenu-textscroll-20180607-a314412.diff
 delete mode 100644 patches/8.dmenu-navhistory-5.0.diff

diff --git a/config.def.h b/config.def.h
deleted file mode 100644
index 65e03fb..0000000
--- a/config.def.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-/* Default settings; can be overriden by command line. */
-
-static int topbar = 1;                      /* -b  option; if 0, dmenu appears at bottom     */
-/* -fn option overrides fonts[0]; default X11 font or font set */
-static const char *fonts[] = {
-	"monospace:size=10"
-};
-static const char *prompt      = NULL;      /* -p  option; prompt to the left of input field */
-static const char *colors[SchemeLast][2] = {
-	/*     fg         bg       */
-	[SchemeNorm] = { "#bbbbbb", "#222222" },
-	[SchemeSel] = { "#eeeeee", "#005577" },
-	[SchemeOut] = { "#000000", "#00ffff" },
-	[SchemeHp] = { "#bbbbbb", "#333333" }
-};
-/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
-static unsigned int lines      = 0;
-
-/*
- * Characters not considered part of a word while deleting words
- * for example: " /?\"&[]"
- */
-static const char worddelimiters[] = " ";
diff --git a/patches/4.dmenu-instant-4.7.diff b/patches/4.dmenu-instant-4.7.diff
new file mode 100644
index 0000000..a78276f
--- /dev/null
+++ b/patches/4.dmenu-instant-4.7.diff
@@ -0,0 +1,73 @@
+diff --git a/config.def.h b/config.def.h
+index 1edb647..37f43d5 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -1,6 +1,7 @@
+ /* See LICENSE file for copyright and license details. */
+ /* Default settings; can be overriden by command line. */
+ 
++static int instant = 0;
+ static int topbar = 1;                      /* -b  option; if 0, dmenu appears at bottom     */
+ /* -fn option overrides fonts[0]; default X11 font or font set */
+ static const char *fonts[] = {
+diff --git a/dmenu.1 b/dmenu.1
+index 9eab758..98d3725 100644
+--- a/dmenu.1
++++ b/dmenu.1
+@@ -3,7 +3,7 @@
+ dmenu \- dynamic menu
+ .SH SYNOPSIS
+ .B dmenu
+-.RB [ \-bfiv ]
++.RB [ \-bfinv ]
+ .RB [ \-l
+ .IR lines ]
+ .RB [ \-m
+@@ -47,6 +47,9 @@ X until stdin reaches end\-of\-file.
+ .B \-i
+ dmenu matches menu items case insensitively.
+ .TP
++.B \-n
++dmenu instantly selects if only one match.
++.TP
+ .BI \-l " lines"
+ dmenu lists items vertically, with the given number of lines.
+ .TP
+diff --git a/dmenu.c b/dmenu.c
+index d605ab4..2c2f03e 100644
+--- a/dmenu.c
++++ b/dmenu.c
+@@ -260,6 +260,13 @@ match(void)
+ 		matchend = substrend;
+ 	}
+ 	curr = sel = matches;
++
++	if(instant && matches && matches==matchend && !lsubstr) {
++		puts(matches->text);
++		cleanup();
++		exit(0);
++	}
++
+ 	calcoffsets();
+ }
+ 
+@@ -636,7 +643,7 @@ setup(void)
+ static void
+ usage(void)
+ {
+-	fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
++	fputs("usage: dmenu [-bfinv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
+ 	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
+ 	exit(1);
+ }
+@@ -659,7 +666,9 @@ main(int argc, char *argv[])
+ 		else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
+ 			fstrncmp = strncasecmp;
+ 			fstrstr = cistrstr;
+-		} else if (i + 1 == argc)
++		} else if (!strcmp(argv[i], "-n")) /* instant select only match */
++			instant = 1;
++		else if (i + 1 == argc)
+ 			usage();
+ 		/* these options take one argument */
+ 		else if (!strcmp(argv[i], "-l"))   /* number of lines in vertical list */
diff --git a/patches/4.dmenu-numbers-4.9.diff b/patches/4.dmenu-numbers-4.9.diff
deleted file mode 100644
index 113be80..0000000
--- a/patches/4.dmenu-numbers-4.9.diff
+++ /dev/null
@@ -1,81 +0,0 @@
-From 61abc60dbfaa8ec63fcd176307308aee88a19e32 Mon Sep 17 00:00:00 2001
-From: Miles Alan <m@milesalan.com>
-Date: Sat, 10 Aug 2019 17:20:08 -0500
-Subject: [PATCH] Display number of matched and total items in top right corner
-
----
- dmenu.c | 25 +++++++++++++++++++++++--
- 1 file changed, 23 insertions(+), 2 deletions(-)
-
-diff --git a/dmenu.c b/dmenu.c
-index 6b8f51b..98c5810 100644
---- a/dmenu.c
-+++ b/dmenu.c
-@@ -24,6 +24,8 @@
-                              * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org)))
- #define LENGTH(X)             (sizeof X / sizeof X[0])
- #define TEXTW(X)              (drw_fontset_getwidth(drw, (X)) + lrpad)
-+#define NUMBERSMAXDIGITS      100
-+#define NUMBERSBUFSIZE        (NUMBERSMAXDIGITS * 2) + 1
- 
- /* enums */
- enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */
-@@ -34,6 +36,7 @@ struct item {
- 	int out;
- };
- 
-+static char numbers[NUMBERSBUFSIZE] = "";
- static char text[BUFSIZ] = "";
- static char *embed;
- static int bh, mw, mh;
-@@ -126,6 +129,21 @@ drawitem(struct item *item, int x, int y, int w)
- 	return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0);
- }
- 
-+static void
-+recalculatenumbers()
-+{
-+	unsigned int numer = 0, denom = 0;
-+	struct item *item;
-+	if (matchend) {
-+		numer++;
-+		for (item = matchend; item && item->left; item = item->left)
-+			numer++;
-+	}
-+	for (item = items; item && item->text; item++)
-+		denom++;
-+	snprintf(numbers, NUMBERSBUFSIZE, "%d/%d", numer, denom);
-+}
-+
- static void
- drawmenu(void)
- {
-@@ -151,6 +169,7 @@ drawmenu(void)
- 		drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0);
- 	}
- 
-+	recalculatenumbers();
- 	if (lines > 0) {
- 		/* draw vertical list */
- 		for (item = curr; item != next; item = item->right)
-@@ -165,13 +184,15 @@ drawmenu(void)
- 		}
- 		x += w;
- 		for (item = curr; item != next; item = item->right)
--			x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">")));
-+			x = drawitem(item, x, 0, MIN(TEXTW(item->text), mw - x - TEXTW(">") - TEXTW(numbers)));
- 		if (next) {
- 			w = TEXTW(">");
- 			drw_setscheme(drw, scheme[SchemeNorm]);
--			drw_text(drw, mw - w, 0, w, bh, lrpad / 2, ">", 0);
-+			drw_text(drw, mw - w - TEXTW(numbers), 0, w, bh, lrpad / 2, ">", 0);
- 		}
- 	}
-+	drw_setscheme(drw, scheme[SchemeNorm]);
-+	drw_text(drw, mw - TEXTW(numbers), 0, TEXTW(numbers), bh, lrpad / 2, numbers, 0);
- 	drw_map(drw, win, 0, 0, mw, mh);
- }
- 
--- 
-2.19.2
-
diff --git a/patches/5.dmenu-instant-4.7.diff b/patches/5.dmenu-instant-4.7.diff
deleted file mode 100644
index a78276f..0000000
--- a/patches/5.dmenu-instant-4.7.diff
+++ /dev/null
@@ -1,73 +0,0 @@
-diff --git a/config.def.h b/config.def.h
-index 1edb647..37f43d5 100644
---- a/config.def.h
-+++ b/config.def.h
-@@ -1,6 +1,7 @@
- /* See LICENSE file for copyright and license details. */
- /* Default settings; can be overriden by command line. */
- 
-+static int instant = 0;
- static int topbar = 1;                      /* -b  option; if 0, dmenu appears at bottom     */
- /* -fn option overrides fonts[0]; default X11 font or font set */
- static const char *fonts[] = {
-diff --git a/dmenu.1 b/dmenu.1
-index 9eab758..98d3725 100644
---- a/dmenu.1
-+++ b/dmenu.1
-@@ -3,7 +3,7 @@
- dmenu \- dynamic menu
- .SH SYNOPSIS
- .B dmenu
--.RB [ \-bfiv ]
-+.RB [ \-bfinv ]
- .RB [ \-l
- .IR lines ]
- .RB [ \-m
-@@ -47,6 +47,9 @@ X until stdin reaches end\-of\-file.
- .B \-i
- dmenu matches menu items case insensitively.
- .TP
-+.B \-n
-+dmenu instantly selects if only one match.
-+.TP
- .BI \-l " lines"
- dmenu lists items vertically, with the given number of lines.
- .TP
-diff --git a/dmenu.c b/dmenu.c
-index d605ab4..2c2f03e 100644
---- a/dmenu.c
-+++ b/dmenu.c
-@@ -260,6 +260,13 @@ match(void)
- 		matchend = substrend;
- 	}
- 	curr = sel = matches;
-+
-+	if(instant && matches && matches==matchend && !lsubstr) {
-+		puts(matches->text);
-+		cleanup();
-+		exit(0);
-+	}
-+
- 	calcoffsets();
- }
- 
-@@ -636,7 +643,7 @@ setup(void)
- static void
- usage(void)
- {
--	fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
-+	fputs("usage: dmenu [-bfinv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
- 	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
- 	exit(1);
- }
-@@ -659,7 +666,9 @@ main(int argc, char *argv[])
- 		else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
- 			fstrncmp = strncasecmp;
- 			fstrstr = cistrstr;
--		} else if (i + 1 == argc)
-+		} else if (!strcmp(argv[i], "-n")) /* instant select only match */
-+			instant = 1;
-+		else if (i + 1 == argc)
- 			usage();
- 		/* these options take one argument */
- 		else if (!strcmp(argv[i], "-l"))   /* number of lines in vertical list */
diff --git a/patches/5.dmenu-mousesupport-5.1.diff b/patches/5.dmenu-mousesupport-5.1.diff
new file mode 100644
index 0000000..49824ba
--- /dev/null
+++ b/patches/5.dmenu-mousesupport-5.1.diff
@@ -0,0 +1,144 @@
+diff --git a/dmenu.c b/dmenu.c
+index d95e6c6..75a79d0 100644
+--- a/dmenu.c
++++ b/dmenu.c
+@@ -518,6 +518,119 @@ draw:
+ 	drawmenu();
+ }
+ 
++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)
+ {
+@@ -579,6 +692,9 @@ run(void)
+ 				break;
+ 			cleanup();
+ 			exit(1);
++		case ButtonPress:
++			buttonpress(&ev);
++			break;
+ 		case Expose:
+ 			if (ev.xexpose.count == 0)
+ 				drw_map(drw, win, 0, 0, mw, mh);
+@@ -676,7 +792,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);
diff --git a/patches/6.dmenu-mousesupport-5.1.diff b/patches/6.dmenu-mousesupport-5.1.diff
deleted file mode 100644
index 49824ba..0000000
--- a/patches/6.dmenu-mousesupport-5.1.diff
+++ /dev/null
@@ -1,144 +0,0 @@
-diff --git a/dmenu.c b/dmenu.c
-index d95e6c6..75a79d0 100644
---- a/dmenu.c
-+++ b/dmenu.c
-@@ -518,6 +518,119 @@ draw:
- 	drawmenu();
- }
- 
-+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)
- {
-@@ -579,6 +692,9 @@ run(void)
- 				break;
- 			cleanup();
- 			exit(1);
-+		case ButtonPress:
-+			buttonpress(&ev);
-+			break;
- 		case Expose:
- 			if (ev.xexpose.count == 0)
- 				drw_map(drw, win, 0, 0, mw, mh);
-@@ -676,7 +792,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);
diff --git a/patches/6.dmenu-textscroll-20180607-a314412.diff b/patches/6.dmenu-textscroll-20180607-a314412.diff
new file mode 100644
index 0000000..7a7386a
--- /dev/null
+++ b/patches/6.dmenu-textscroll-20180607-a314412.diff
@@ -0,0 +1,245 @@
+diff --git a/dmenu.c b/dmenu.c
+index 5c835dd..71efe52 100644
+--- a/dmenu.c
++++ b/dmenu.c
+@@ -131,9 +131,10 @@ drawitem(struct item *item, int x, int y, int w)
+ static void
+ drawmenu(void)
+ {
+-	unsigned int curpos;
++	static int curpos, oldcurlen;
+ 	struct item *item;
+ 	int x = 0, y = 0, w;
++	int curlen, rcurlen;
+ 
+ 	drw_setscheme(drw, scheme[SchemeNorm]);
+ 	drw_rect(drw, 0, 0, mw, mh, 1, 1);
+@@ -144,14 +145,21 @@ drawmenu(void)
+ 	}
+ 	/* draw input field */
+ 	w = (lines > 0 || !matches) ? mw - x : inputw;
+-	drw_setscheme(drw, scheme[SchemeNorm]);
+-	drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0);
++	w -= lrpad / 2;
++	x += lrpad / 2;
+ 
+-	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);
+-	}
++	rcurlen = drw_fontset_getwidth(drw, text + cursor);
++	curlen = drw_fontset_getwidth(drw, text) - rcurlen;
++	curpos += curlen - oldcurlen;
++	curpos = MIN(w, MAX(0, curpos));
++	curpos = MAX(curpos, w - rcurlen);
++	curpos = MIN(curpos, curlen);
++	oldcurlen = curlen;
++
++	drw_setscheme(drw, scheme[SchemeNorm]);
++	drw_text_align(drw, x, 0, curpos, bh, text, cursor, AlignR);
++	drw_text_align(drw, x + curpos, 0, w - curpos, bh, text + cursor, strlen(text) - cursor, AlignL);
++	drw_rect(drw, x + curpos - 1, 2, 2, bh - 4, 1, 0);
+ 
+ 	if (lines > 0) {
+ 		/* draw vertical list */
+diff --git a/drw.c b/drw.c
+index c638323..bfffbc1 100644
+--- a/drw.c
++++ b/drw.c
+@@ -364,6 +364,175 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
+ 	return x + (render ? w : 0);
+ }
+ 
++int
++utf8nextchar(const char *str, int len, int i, int inc)
++{
++	int n;
++
++	for (n = i + inc; n + inc >= 0 && n + inc <= len
++	  && (str[n] & 0xc0) == 0x80; n += inc)
++		;
++	return n;
++}
++
++int
++drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int textlen, int align)
++{
++	int ty;
++	unsigned int ew;
++	XftDraw *d = NULL;
++	Fnt *usedfont, *curfont, *nextfont;
++	size_t len;
++	int utf8strlen, utf8charlen, render = x || y || w || h;
++	long utf8codepoint = 0;
++	const char *utf8str;
++	FcCharSet *fccharset;
++	FcPattern *fcpattern;
++	FcPattern *match;
++	XftResult result;
++	int charexists = 0;
++	int i, n;
++
++	if (!drw || (render && !drw->scheme) || !text || !drw->fonts || textlen <= 0
++	  || (align != AlignL && align != AlignR))
++		return 0;
++
++	if (!render) {
++		w = ~w;
++	} else {
++		XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel);
++		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
++		d = XftDrawCreate(drw->dpy, drw->drawable,
++		                  DefaultVisual(drw->dpy, drw->screen),
++		                  DefaultColormap(drw->dpy, drw->screen));
++	}
++
++	usedfont = drw->fonts;
++	i = align == AlignL ? 0 : textlen;
++	x = align == AlignL ? x : x + w;
++	while (1) {
++		utf8strlen = 0;
++		nextfont = NULL;
++		/* if (align == AlignL) */
++		utf8str = text + i;
++
++		while ((align == AlignL && i < textlen) || (align == AlignR && i > 0)) {
++			if (align == AlignL) {
++				utf8charlen = utf8decode(text + i, &utf8codepoint, MIN(textlen - i, UTF_SIZ));
++				if (!utf8charlen) {
++					textlen = i;
++					break;
++				}
++			} else {
++				n = utf8nextchar(text, textlen, i, -1);
++				utf8charlen = utf8decode(text + n, &utf8codepoint, MIN(textlen - n, UTF_SIZ));
++				if (!utf8charlen) {
++					textlen -= i;
++					text += i;
++					i = 0;
++					break;
++				}
++			}
++			for (curfont = drw->fonts; curfont; curfont = curfont->next) {
++				charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
++				if (charexists) {
++					if (curfont == usedfont) {
++						utf8strlen += utf8charlen;
++						i += align == AlignL ? utf8charlen : -utf8charlen;
++					} else {
++						nextfont = curfont;
++					}
++					break;
++				}
++			}
++
++			if (!charexists || nextfont)
++				break;
++			else
++				charexists = 0;
++		}
++
++		if (align == AlignR)
++			utf8str = text + i;
++
++		if (utf8strlen) {
++			drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
++			/* shorten text if necessary */
++			if (align == AlignL) {
++				for (len = utf8strlen; len && ew > w; ) {
++					len = utf8nextchar(utf8str, len, len, -1);
++					drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
++				}
++			} else {
++				for (len = utf8strlen; len && ew > w; ) {
++					n = utf8nextchar(utf8str, len, 0, +1);
++					utf8str += n;
++					len -= n;
++					drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
++				}
++			}
++
++			if (len) {
++				if (render) {
++					ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
++					XftDrawStringUtf8(d, &drw->scheme[ColFg],
++					                  usedfont->xfont, align == AlignL ? x : x - ew, ty, (XftChar8 *)utf8str, len);
++				}
++				x += align == AlignL ? ew : -ew;
++				w -= ew;
++			}
++			if (len < utf8strlen)
++				break;
++		}
++
++		if ((align == AlignR && i <= 0) || (align == AlignL && i >= textlen)) {
++			break;
++		} else if (nextfont) {
++			charexists = 0;
++			usedfont = nextfont;
++		} else {
++			/* Regardless of whether or not a fallback font is found, the
++			 * character must be drawn. */
++			charexists = 1;
++
++			fccharset = FcCharSetCreate();
++			FcCharSetAddChar(fccharset, utf8codepoint);
++
++			if (!drw->fonts->pattern) {
++				/* Refer to the comment in xfont_create for more information. */
++				die("the first font in the cache must be loaded from a font string.");
++			}
++
++			fcpattern = FcPatternDuplicate(drw->fonts->pattern);
++			FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
++			FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
++
++			FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
++			FcDefaultSubstitute(fcpattern);
++			match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
++
++			FcCharSetDestroy(fccharset);
++			FcPatternDestroy(fcpattern);
++
++			if (match) {
++				usedfont = xfont_create(drw, NULL, match);
++				if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
++					for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
++						; /* NOP */
++					curfont->next = usedfont;
++				} else {
++					xfont_free(usedfont);
++					usedfont = drw->fonts;
++				}
++			}
++		}
++	}
++	if (d)
++		XftDrawDestroy(d);
++
++	return x;
++}
++
+ void
+ drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
+ {
+diff --git a/drw.h b/drw.h
+index 4c67419..b66a83e 100644
+--- a/drw.h
++++ b/drw.h
+@@ -13,6 +13,7 @@ typedef struct Fnt {
+ } Fnt;
+ 
+ enum { ColFg, ColBg }; /* Clr scheme index */
++enum { AlignL, AlignR };
+ typedef XftColor Clr;
+ 
+ typedef struct {
+@@ -52,6 +53,7 @@ void drw_setscheme(Drw *drw, Clr *scm);
+ /* Drawing functions */
+ void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
+ int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
++int drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int textlen, int align);
+ 
+ /* Map functions */
+ void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
diff --git a/patches/7.dmenu-navhistory-5.0.diff b/patches/7.dmenu-navhistory-5.0.diff
new file mode 100644
index 0000000..1f7cf6c
--- /dev/null
+++ b/patches/7.dmenu-navhistory-5.0.diff
@@ -0,0 +1,256 @@
+From a4a08baf35edb6b50ed14f76e99d0c6fe790759d Mon Sep 17 00:00:00 2001
+From: Max Schillinger <maxschillinger@web.de>
+Date: Fri, 9 Jul 2021 17:17:36 +0200
+Subject: [PATCH] Bug fix: Writing first entry to history file was skipped
+
+---
+ config.def.h |   2 +
+ dmenu.1      |   5 ++
+ dmenu.c      | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++-
+ dmenu_run    |   2 +-
+ 4 files changed, 151 insertions(+), 2 deletions(-)
+
+diff --git a/config.def.h b/config.def.h
+index 1edb647..e3e1b53 100644
+--- a/config.def.h
++++ b/config.def.h
+@@ -15,6 +15,8 @@ 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 maxhist    = 64;
++static int histnodup           = 1;	/* if 0, record repeated histories */
+ 
+ /*
+  * Characters not considered part of a word while deleting words
+diff --git a/dmenu.1 b/dmenu.1
+index 323f93c..ff496dd 100644
+--- a/dmenu.1
++++ b/dmenu.1
+@@ -22,6 +22,8 @@ dmenu \- dynamic menu
+ .IR color ]
+ .RB [ \-w
+ .IR windowid ]
++.RB [ \-H
++.IR histfile ]
+ .P
+ .BR dmenu_run " ..."
+ .SH DESCRIPTION
+@@ -80,6 +82,9 @@ prints version information to stdout, then exits.
+ .TP
+ .BI \-w " windowid"
+ embed into windowid.
++.TP
++.BI \-H " histfile"
++save input in histfile and use it for history navigation.
+ .SH USAGE
+ dmenu is completely controlled by the keyboard.  Items are selected using the
+ arrow keys, page up, page down, home, and end.
+diff --git a/dmenu.c b/dmenu.c
+index 65f25ce..5023257 100644
+--- a/dmenu.c
++++ b/dmenu.c
+@@ -53,6 +53,10 @@ static XIC xic;
+ static Drw *drw;
+ static Clr *scheme[SchemeLast];
+ 
++static char *histfile;
++static char **history;
++static size_t histsz, histpos;
++
+ #include "config.h"
+ 
+ static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
+@@ -304,6 +308,129 @@ movewordedge(int dir)
+ 	}
+ }
+ 
++static void
++loadhistory(void)
++{
++	FILE *fp = NULL;
++	static size_t cap = 0;
++	size_t llen;
++	char *line;
++
++	if (!histfile) {
++		return;
++	}
++
++	fp = fopen(histfile, "r");
++	if (!fp) {
++		return;
++	}
++
++	for (;;) {
++		line = NULL;
++		llen = 0;
++		if (-1 == getline(&line, &llen, fp)) {
++			if (ferror(fp)) {
++				die("failed to read history");
++			}
++			free(line);
++			break;
++		}
++
++		if (cap == histsz) {
++			cap += 64 * sizeof(char*);
++			history = realloc(history, cap);
++			if (!history) {
++				die("failed to realloc memory");
++			}
++		}
++		strtok(line, "\n");
++		history[histsz] = line;
++		histsz++;
++	}
++	histpos = histsz;
++
++	if (fclose(fp)) {
++		die("failed to close file %s", histfile);
++	}
++}
++
++static void
++navhistory(int dir)
++{
++	static char def[BUFSIZ];
++	char *p = NULL;
++	size_t len = 0;
++
++	if (!history || histpos + 1 == 0)
++		return;
++
++	if (histsz == histpos) {
++		strncpy(def, text, sizeof(def));
++	}
++
++	switch(dir) {
++	case 1:
++		if (histpos < histsz - 1) {
++			p = history[++histpos];
++		} else if (histpos == histsz - 1) {
++			p = def;
++			histpos++;
++		}
++		break;
++	case -1:
++		if (histpos > 0) {
++			p = history[--histpos];
++		}
++		break;
++	}
++	if (p == NULL) {
++		return;
++	}
++
++	len = MIN(strlen(p), BUFSIZ - 1);
++	strncpy(text, p, len);
++	text[len] = '\0';
++	cursor = len;
++	match();
++}
++
++static void
++savehistory(char *input)
++{
++	unsigned int i;
++	FILE *fp;
++
++	if (!histfile ||
++	    0 == maxhist ||
++	    0 == strlen(input)) {
++		goto out;
++	}
++
++	fp = fopen(histfile, "w");
++	if (!fp) {
++		die("failed to open %s", histfile);
++	}
++	for (i = histsz < maxhist ? 0 : histsz - maxhist; i < histsz; i++) {
++		if (0 >= fprintf(fp, "%s\n", history[i])) {
++			die("failed to write to %s", histfile);
++		}
++	}
++	if (histsz == 0 || !histnodup || (histsz > 0 && strcmp(input, history[histsz-1]) != 0)) { /* TODO */
++		if (0 >= fputs(input, fp)) {
++			die("failed to write to %s", histfile);
++		}
++	}
++	if (fclose(fp)) {
++		die("failed to close file %s", histfile);
++	}
++
++out:
++	for (i = 0; i < histsz; i++) {
++		free(history[i]);
++	}
++	free(history);
++}
++
+ static void
+ keypress(XKeyEvent *ev)
+ {
+@@ -388,6 +515,14 @@ keypress(XKeyEvent *ev)
+ 		case XK_j: ksym = XK_Next;  break;
+ 		case XK_k: ksym = XK_Prior; break;
+ 		case XK_l: ksym = XK_Down;  break;
++		case XK_p:
++			navhistory(-1);
++			buf[0]=0;
++			break;
++		case XK_n:
++			navhistory(1);
++			buf[0]=0;
++			break;
+ 		default:
+ 			return;
+ 		}
+@@ -466,6 +601,8 @@ insert:
+ 	case XK_KP_Enter:
+ 		puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
+ 		if (!(ev->state & ControlMask)) {
++			savehistory((sel && !(ev->state & ShiftMask))
++				    ? sel->text : text);
+ 			cleanup();
+ 			exit(0);
+ 		}
+@@ -690,7 +827,8 @@ static void
+ usage(void)
+ {
+ 	fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
+-	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
++	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n"
++	      "             [-H histfile]", stderr);
+ 	exit(1);
+ }
+ 
+@@ -715,6 +853,8 @@ main(int argc, char *argv[])
+ 		} else if (i + 1 == argc)
+ 			usage();
+ 		/* these options take one argument */
++		else if (!strcmp(argv[i], "-H"))
++			histfile = argv[++i];
+ 		else if (!strcmp(argv[i], "-l"))   /* number of lines in vertical list */
+ 			lines = atoi(argv[++i]);
+ 		else if (!strcmp(argv[i], "-m"))
+@@ -757,6 +897,8 @@ main(int argc, char *argv[])
+ 		die("pledge");
+ #endif
+ 
++	loadhistory();
++
+ 	if (fast && !isatty(0)) {
+ 		grabkeyboard();
+ 		readstdin();
+diff --git a/dmenu_run b/dmenu_run
+index 834ede5..59ec622 100755
+--- a/dmenu_run
++++ b/dmenu_run
+@@ -1,2 +1,2 @@
+ #!/bin/sh
+-dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} &
++dmenu_path | dmenu -H "${XDG_CACHE_HOME:-$HOME/.cache/}/dmenu_run.hist" "$@" | ${SHELL:-"/bin/sh"} &
+-- 
+2.25.1
+
diff --git a/patches/7.dmenu-textscroll-20180607-a314412.diff b/patches/7.dmenu-textscroll-20180607-a314412.diff
deleted file mode 100644
index 7a7386a..0000000
--- a/patches/7.dmenu-textscroll-20180607-a314412.diff
+++ /dev/null
@@ -1,245 +0,0 @@
-diff --git a/dmenu.c b/dmenu.c
-index 5c835dd..71efe52 100644
---- a/dmenu.c
-+++ b/dmenu.c
-@@ -131,9 +131,10 @@ drawitem(struct item *item, int x, int y, int w)
- static void
- drawmenu(void)
- {
--	unsigned int curpos;
-+	static int curpos, oldcurlen;
- 	struct item *item;
- 	int x = 0, y = 0, w;
-+	int curlen, rcurlen;
- 
- 	drw_setscheme(drw, scheme[SchemeNorm]);
- 	drw_rect(drw, 0, 0, mw, mh, 1, 1);
-@@ -144,14 +145,21 @@ drawmenu(void)
- 	}
- 	/* draw input field */
- 	w = (lines > 0 || !matches) ? mw - x : inputw;
--	drw_setscheme(drw, scheme[SchemeNorm]);
--	drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0);
-+	w -= lrpad / 2;
-+	x += lrpad / 2;
- 
--	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);
--	}
-+	rcurlen = drw_fontset_getwidth(drw, text + cursor);
-+	curlen = drw_fontset_getwidth(drw, text) - rcurlen;
-+	curpos += curlen - oldcurlen;
-+	curpos = MIN(w, MAX(0, curpos));
-+	curpos = MAX(curpos, w - rcurlen);
-+	curpos = MIN(curpos, curlen);
-+	oldcurlen = curlen;
-+
-+	drw_setscheme(drw, scheme[SchemeNorm]);
-+	drw_text_align(drw, x, 0, curpos, bh, text, cursor, AlignR);
-+	drw_text_align(drw, x + curpos, 0, w - curpos, bh, text + cursor, strlen(text) - cursor, AlignL);
-+	drw_rect(drw, x + curpos - 1, 2, 2, bh - 4, 1, 0);
- 
- 	if (lines > 0) {
- 		/* draw vertical list */
-diff --git a/drw.c b/drw.c
-index c638323..bfffbc1 100644
---- a/drw.c
-+++ b/drw.c
-@@ -364,6 +364,175 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
- 	return x + (render ? w : 0);
- }
- 
-+int
-+utf8nextchar(const char *str, int len, int i, int inc)
-+{
-+	int n;
-+
-+	for (n = i + inc; n + inc >= 0 && n + inc <= len
-+	  && (str[n] & 0xc0) == 0x80; n += inc)
-+		;
-+	return n;
-+}
-+
-+int
-+drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int textlen, int align)
-+{
-+	int ty;
-+	unsigned int ew;
-+	XftDraw *d = NULL;
-+	Fnt *usedfont, *curfont, *nextfont;
-+	size_t len;
-+	int utf8strlen, utf8charlen, render = x || y || w || h;
-+	long utf8codepoint = 0;
-+	const char *utf8str;
-+	FcCharSet *fccharset;
-+	FcPattern *fcpattern;
-+	FcPattern *match;
-+	XftResult result;
-+	int charexists = 0;
-+	int i, n;
-+
-+	if (!drw || (render && !drw->scheme) || !text || !drw->fonts || textlen <= 0
-+	  || (align != AlignL && align != AlignR))
-+		return 0;
-+
-+	if (!render) {
-+		w = ~w;
-+	} else {
-+		XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel);
-+		XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, y, w, h);
-+		d = XftDrawCreate(drw->dpy, drw->drawable,
-+		                  DefaultVisual(drw->dpy, drw->screen),
-+		                  DefaultColormap(drw->dpy, drw->screen));
-+	}
-+
-+	usedfont = drw->fonts;
-+	i = align == AlignL ? 0 : textlen;
-+	x = align == AlignL ? x : x + w;
-+	while (1) {
-+		utf8strlen = 0;
-+		nextfont = NULL;
-+		/* if (align == AlignL) */
-+		utf8str = text + i;
-+
-+		while ((align == AlignL && i < textlen) || (align == AlignR && i > 0)) {
-+			if (align == AlignL) {
-+				utf8charlen = utf8decode(text + i, &utf8codepoint, MIN(textlen - i, UTF_SIZ));
-+				if (!utf8charlen) {
-+					textlen = i;
-+					break;
-+				}
-+			} else {
-+				n = utf8nextchar(text, textlen, i, -1);
-+				utf8charlen = utf8decode(text + n, &utf8codepoint, MIN(textlen - n, UTF_SIZ));
-+				if (!utf8charlen) {
-+					textlen -= i;
-+					text += i;
-+					i = 0;
-+					break;
-+				}
-+			}
-+			for (curfont = drw->fonts; curfont; curfont = curfont->next) {
-+				charexists = charexists || XftCharExists(drw->dpy, curfont->xfont, utf8codepoint);
-+				if (charexists) {
-+					if (curfont == usedfont) {
-+						utf8strlen += utf8charlen;
-+						i += align == AlignL ? utf8charlen : -utf8charlen;
-+					} else {
-+						nextfont = curfont;
-+					}
-+					break;
-+				}
-+			}
-+
-+			if (!charexists || nextfont)
-+				break;
-+			else
-+				charexists = 0;
-+		}
-+
-+		if (align == AlignR)
-+			utf8str = text + i;
-+
-+		if (utf8strlen) {
-+			drw_font_getexts(usedfont, utf8str, utf8strlen, &ew, NULL);
-+			/* shorten text if necessary */
-+			if (align == AlignL) {
-+				for (len = utf8strlen; len && ew > w; ) {
-+					len = utf8nextchar(utf8str, len, len, -1);
-+					drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
-+				}
-+			} else {
-+				for (len = utf8strlen; len && ew > w; ) {
-+					n = utf8nextchar(utf8str, len, 0, +1);
-+					utf8str += n;
-+					len -= n;
-+					drw_font_getexts(usedfont, utf8str, len, &ew, NULL);
-+				}
-+			}
-+
-+			if (len) {
-+				if (render) {
-+					ty = y + (h - usedfont->h) / 2 + usedfont->xfont->ascent;
-+					XftDrawStringUtf8(d, &drw->scheme[ColFg],
-+					                  usedfont->xfont, align == AlignL ? x : x - ew, ty, (XftChar8 *)utf8str, len);
-+				}
-+				x += align == AlignL ? ew : -ew;
-+				w -= ew;
-+			}
-+			if (len < utf8strlen)
-+				break;
-+		}
-+
-+		if ((align == AlignR && i <= 0) || (align == AlignL && i >= textlen)) {
-+			break;
-+		} else if (nextfont) {
-+			charexists = 0;
-+			usedfont = nextfont;
-+		} else {
-+			/* Regardless of whether or not a fallback font is found, the
-+			 * character must be drawn. */
-+			charexists = 1;
-+
-+			fccharset = FcCharSetCreate();
-+			FcCharSetAddChar(fccharset, utf8codepoint);
-+
-+			if (!drw->fonts->pattern) {
-+				/* Refer to the comment in xfont_create for more information. */
-+				die("the first font in the cache must be loaded from a font string.");
-+			}
-+
-+			fcpattern = FcPatternDuplicate(drw->fonts->pattern);
-+			FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
-+			FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
-+
-+			FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
-+			FcDefaultSubstitute(fcpattern);
-+			match = XftFontMatch(drw->dpy, drw->screen, fcpattern, &result);
-+
-+			FcCharSetDestroy(fccharset);
-+			FcPatternDestroy(fcpattern);
-+
-+			if (match) {
-+				usedfont = xfont_create(drw, NULL, match);
-+				if (usedfont && XftCharExists(drw->dpy, usedfont->xfont, utf8codepoint)) {
-+					for (curfont = drw->fonts; curfont->next; curfont = curfont->next)
-+						; /* NOP */
-+					curfont->next = usedfont;
-+				} else {
-+					xfont_free(usedfont);
-+					usedfont = drw->fonts;
-+				}
-+			}
-+		}
-+	}
-+	if (d)
-+		XftDrawDestroy(d);
-+
-+	return x;
-+}
-+
- void
- drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h)
- {
-diff --git a/drw.h b/drw.h
-index 4c67419..b66a83e 100644
---- a/drw.h
-+++ b/drw.h
-@@ -13,6 +13,7 @@ typedef struct Fnt {
- } Fnt;
- 
- enum { ColFg, ColBg }; /* Clr scheme index */
-+enum { AlignL, AlignR };
- typedef XftColor Clr;
- 
- typedef struct {
-@@ -52,6 +53,7 @@ void drw_setscheme(Drw *drw, Clr *scm);
- /* Drawing functions */
- void drw_rect(Drw *drw, int x, int y, unsigned int w, unsigned int h, int filled, int invert);
- int drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lpad, const char *text, int invert);
-+int drw_text_align(Drw *drw, int x, int y, unsigned int w, unsigned int h, const char *text, int textlen, int align);
- 
- /* Map functions */
- void drw_map(Drw *drw, Window win, int x, int y, unsigned int w, unsigned int h);
diff --git a/patches/8.dmenu-navhistory-5.0.diff b/patches/8.dmenu-navhistory-5.0.diff
deleted file mode 100644
index 1f7cf6c..0000000
--- a/patches/8.dmenu-navhistory-5.0.diff
+++ /dev/null
@@ -1,256 +0,0 @@
-From a4a08baf35edb6b50ed14f76e99d0c6fe790759d Mon Sep 17 00:00:00 2001
-From: Max Schillinger <maxschillinger@web.de>
-Date: Fri, 9 Jul 2021 17:17:36 +0200
-Subject: [PATCH] Bug fix: Writing first entry to history file was skipped
-
----
- config.def.h |   2 +
- dmenu.1      |   5 ++
- dmenu.c      | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++-
- dmenu_run    |   2 +-
- 4 files changed, 151 insertions(+), 2 deletions(-)
-
-diff --git a/config.def.h b/config.def.h
-index 1edb647..e3e1b53 100644
---- a/config.def.h
-+++ b/config.def.h
-@@ -15,6 +15,8 @@ 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 maxhist    = 64;
-+static int histnodup           = 1;	/* if 0, record repeated histories */
- 
- /*
-  * Characters not considered part of a word while deleting words
-diff --git a/dmenu.1 b/dmenu.1
-index 323f93c..ff496dd 100644
---- a/dmenu.1
-+++ b/dmenu.1
-@@ -22,6 +22,8 @@ dmenu \- dynamic menu
- .IR color ]
- .RB [ \-w
- .IR windowid ]
-+.RB [ \-H
-+.IR histfile ]
- .P
- .BR dmenu_run " ..."
- .SH DESCRIPTION
-@@ -80,6 +82,9 @@ prints version information to stdout, then exits.
- .TP
- .BI \-w " windowid"
- embed into windowid.
-+.TP
-+.BI \-H " histfile"
-+save input in histfile and use it for history navigation.
- .SH USAGE
- dmenu is completely controlled by the keyboard.  Items are selected using the
- arrow keys, page up, page down, home, and end.
-diff --git a/dmenu.c b/dmenu.c
-index 65f25ce..5023257 100644
---- a/dmenu.c
-+++ b/dmenu.c
-@@ -53,6 +53,10 @@ static XIC xic;
- static Drw *drw;
- static Clr *scheme[SchemeLast];
- 
-+static char *histfile;
-+static char **history;
-+static size_t histsz, histpos;
-+
- #include "config.h"
- 
- static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
-@@ -304,6 +308,129 @@ movewordedge(int dir)
- 	}
- }
- 
-+static void
-+loadhistory(void)
-+{
-+	FILE *fp = NULL;
-+	static size_t cap = 0;
-+	size_t llen;
-+	char *line;
-+
-+	if (!histfile) {
-+		return;
-+	}
-+
-+	fp = fopen(histfile, "r");
-+	if (!fp) {
-+		return;
-+	}
-+
-+	for (;;) {
-+		line = NULL;
-+		llen = 0;
-+		if (-1 == getline(&line, &llen, fp)) {
-+			if (ferror(fp)) {
-+				die("failed to read history");
-+			}
-+			free(line);
-+			break;
-+		}
-+
-+		if (cap == histsz) {
-+			cap += 64 * sizeof(char*);
-+			history = realloc(history, cap);
-+			if (!history) {
-+				die("failed to realloc memory");
-+			}
-+		}
-+		strtok(line, "\n");
-+		history[histsz] = line;
-+		histsz++;
-+	}
-+	histpos = histsz;
-+
-+	if (fclose(fp)) {
-+		die("failed to close file %s", histfile);
-+	}
-+}
-+
-+static void
-+navhistory(int dir)
-+{
-+	static char def[BUFSIZ];
-+	char *p = NULL;
-+	size_t len = 0;
-+
-+	if (!history || histpos + 1 == 0)
-+		return;
-+
-+	if (histsz == histpos) {
-+		strncpy(def, text, sizeof(def));
-+	}
-+
-+	switch(dir) {
-+	case 1:
-+		if (histpos < histsz - 1) {
-+			p = history[++histpos];
-+		} else if (histpos == histsz - 1) {
-+			p = def;
-+			histpos++;
-+		}
-+		break;
-+	case -1:
-+		if (histpos > 0) {
-+			p = history[--histpos];
-+		}
-+		break;
-+	}
-+	if (p == NULL) {
-+		return;
-+	}
-+
-+	len = MIN(strlen(p), BUFSIZ - 1);
-+	strncpy(text, p, len);
-+	text[len] = '\0';
-+	cursor = len;
-+	match();
-+}
-+
-+static void
-+savehistory(char *input)
-+{
-+	unsigned int i;
-+	FILE *fp;
-+
-+	if (!histfile ||
-+	    0 == maxhist ||
-+	    0 == strlen(input)) {
-+		goto out;
-+	}
-+
-+	fp = fopen(histfile, "w");
-+	if (!fp) {
-+		die("failed to open %s", histfile);
-+	}
-+	for (i = histsz < maxhist ? 0 : histsz - maxhist; i < histsz; i++) {
-+		if (0 >= fprintf(fp, "%s\n", history[i])) {
-+			die("failed to write to %s", histfile);
-+		}
-+	}
-+	if (histsz == 0 || !histnodup || (histsz > 0 && strcmp(input, history[histsz-1]) != 0)) { /* TODO */
-+		if (0 >= fputs(input, fp)) {
-+			die("failed to write to %s", histfile);
-+		}
-+	}
-+	if (fclose(fp)) {
-+		die("failed to close file %s", histfile);
-+	}
-+
-+out:
-+	for (i = 0; i < histsz; i++) {
-+		free(history[i]);
-+	}
-+	free(history);
-+}
-+
- static void
- keypress(XKeyEvent *ev)
- {
-@@ -388,6 +515,14 @@ keypress(XKeyEvent *ev)
- 		case XK_j: ksym = XK_Next;  break;
- 		case XK_k: ksym = XK_Prior; break;
- 		case XK_l: ksym = XK_Down;  break;
-+		case XK_p:
-+			navhistory(-1);
-+			buf[0]=0;
-+			break;
-+		case XK_n:
-+			navhistory(1);
-+			buf[0]=0;
-+			break;
- 		default:
- 			return;
- 		}
-@@ -466,6 +601,8 @@ insert:
- 	case XK_KP_Enter:
- 		puts((sel && !(ev->state & ShiftMask)) ? sel->text : text);
- 		if (!(ev->state & ControlMask)) {
-+			savehistory((sel && !(ev->state & ShiftMask))
-+				    ? sel->text : text);
- 			cleanup();
- 			exit(0);
- 		}
-@@ -690,7 +827,8 @@ static void
- usage(void)
- {
- 	fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
--	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr);
-+	      "             [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n"
-+	      "             [-H histfile]", stderr);
- 	exit(1);
- }
- 
-@@ -715,6 +853,8 @@ main(int argc, char *argv[])
- 		} else if (i + 1 == argc)
- 			usage();
- 		/* these options take one argument */
-+		else if (!strcmp(argv[i], "-H"))
-+			histfile = argv[++i];
- 		else if (!strcmp(argv[i], "-l"))   /* number of lines in vertical list */
- 			lines = atoi(argv[++i]);
- 		else if (!strcmp(argv[i], "-m"))
-@@ -757,6 +897,8 @@ main(int argc, char *argv[])
- 		die("pledge");
- #endif
- 
-+	loadhistory();
-+
- 	if (fast && !isatty(0)) {
- 		grabkeyboard();
- 		readstdin();
-diff --git a/dmenu_run b/dmenu_run
-index 834ede5..59ec622 100755
---- a/dmenu_run
-+++ b/dmenu_run
-@@ -1,2 +1,2 @@
- #!/bin/sh
--dmenu_path | dmenu "$@" | ${SHELL:-"/bin/sh"} &
-+dmenu_path | dmenu -H "${XDG_CACHE_HOME:-$HOME/.cache/}/dmenu_run.hist" "$@" | ${SHELL:-"/bin/sh"} &
--- 
-2.25.1
-
-- 
cgit v1.2.3