From 629c84ae0977af9eb536a6aca9308aa819a3c16b Mon Sep 17 00:00:00 2001
From: justsaumit <justsaumit@draconyan.xyz>
Date: Wed, 2 Mar 2022 12:45:50 +0530
Subject: removed buggy scroll patch

---
 README.md                                        |   2 -
 patches/6.dmenu-navhistory-5.0.diff              | 256 +++++++++++++++++++++++
 patches/6.dmenu-textscroll-20180607-a314412.diff | 245 ----------------------
 patches/7.dmenu-navhistory-5.0.diff              | 256 -----------------------
 4 files changed, 256 insertions(+), 503 deletions(-)
 create mode 100644 patches/6.dmenu-navhistory-5.0.diff
 delete mode 100644 patches/6.dmenu-textscroll-20180607-a314412.diff
 delete mode 100644 patches/7.dmenu-navhistory-5.0.diff

diff --git a/README.md b/README.md
index eb0fe66..b07dbd9 100644
--- a/README.md
+++ b/README.md
@@ -20,8 +20,6 @@ source: `git clone https://git.suckless.org/dmenu`
        - use -n flag to immediately select the only matching option left
     - <b>Mouse support patch</b>
       - dmenu options are mouse clickable
-    - <b>Textscroll / scroll patch</b>
-      - adds support for text scrolling, it doesn't append '...' for long input 
     - <b>navhistory patch</b>
       - uses vimkeys to view the previous and next options in history
 
diff --git a/patches/6.dmenu-navhistory-5.0.diff b/patches/6.dmenu-navhistory-5.0.diff
new file mode 100644
index 0000000..1f7cf6c
--- /dev/null
+++ b/patches/6.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/6.dmenu-textscroll-20180607-a314412.diff b/patches/6.dmenu-textscroll-20180607-a314412.diff
deleted file mode 100644
index 7a7386a..0000000
--- a/patches/6.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/7.dmenu-navhistory-5.0.diff b/patches/7.dmenu-navhistory-5.0.diff
deleted file mode 100644
index 1f7cf6c..0000000
--- a/patches/7.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