From 8d1c9ab37821fe51e17ccf34a8e0ec126f97fb47 Mon Sep 17 00:00:00 2001 From: justsaumit Date: Wed, 2 Mar 2022 07:46:02 +0530 Subject: new patches --- patches/3.dmenu-highpriority-4.9.diff | 178 ++++++++++++++++ patches/3.dmenu-numbers-4.9.diff | 81 ------- patches/4.dmenu-lineheight-5.0.diff | 106 ---------- patches/4.dmenu-numbers-4.9.diff | 81 +++++++ patches/5.dmenu-highpriority-4.9.diff | 178 ---------------- patches/5.dmenu-instant-4.7.diff | 73 +++++++ patches/6.dmenu-mousesupport-5.1.diff | 144 +++++++++++++ patches/7.dmenu-textscroll-20180607-a314412.diff | 245 ++++++++++++++++++++++ patches/8.dmenu-navhistory-5.0.diff | 256 +++++++++++++++++++++++ patches/9.dmenu-highlight-20201211-fcdc159.diff | 97 --------- patches/9.dmenu-instant-4.7.diff | 73 ------- 11 files changed, 977 insertions(+), 535 deletions(-) create mode 100644 patches/3.dmenu-highpriority-4.9.diff delete mode 100644 patches/3.dmenu-numbers-4.9.diff delete mode 100644 patches/4.dmenu-lineheight-5.0.diff create mode 100644 patches/4.dmenu-numbers-4.9.diff delete mode 100644 patches/5.dmenu-highpriority-4.9.diff create mode 100644 patches/5.dmenu-instant-4.7.diff create mode 100644 patches/6.dmenu-mousesupport-5.1.diff create mode 100644 patches/7.dmenu-textscroll-20180607-a314412.diff create mode 100644 patches/8.dmenu-navhistory-5.0.diff delete mode 100644 patches/9.dmenu-highlight-20201211-fcdc159.diff delete mode 100644 patches/9.dmenu-instant-4.7.diff (limited to 'patches') diff --git a/patches/3.dmenu-highpriority-4.9.diff b/patches/3.dmenu-highpriority-4.9.diff new file mode 100644 index 0000000..03e106a --- /dev/null +++ b/patches/3.dmenu-highpriority-4.9.diff @@ -0,0 +1,178 @@ +From e9e1691a9b4ffa2db45cd5108b76b9a68610ba37 Mon Sep 17 00:00:00 2001 +From: takase1121 +Date: Sun, 17 May 2020 07:05:32 +0800 +Subject: [PATCH] Adds high-priority items. + +This allows users to specify a list of high priority commands that should be +displayed before other matches with the following arrangement: + +match -> prefix && high priority -> prefix -> substring + +As you can see, high priority for substring matches is not implemented or will not +be implemented depending on needs. +--- + config.def.h | 1 + + dmenu.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++----- + 2 files changed, 59 insertions(+), 6 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1edb647..65e03fb 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -12,6 +12,7 @@ static const char *colors[SchemeLast][2] = { + [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; +diff --git a/dmenu.c b/dmenu.c +index 6b8f51b..7bf4099 100644 +--- a/dmenu.c ++++ b/dmenu.c +@@ -26,14 +26,16 @@ + #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) + + /* enums */ +-enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ ++enum { SchemeNorm, SchemeSel, SchemeHp, SchemeOut, SchemeLast }; /* color schemes */ + + struct item { + char *text; + struct item *left, *right; +- int out; ++ int out, hp; + }; + ++static char **hpitems = NULL; ++static int hplength = 0; + static char text[BUFSIZ] = ""; + static char *embed; + static int bh, mw, mh; +@@ -58,6 +60,36 @@ static Clr *scheme[SchemeLast]; + static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; + static char *(*fstrstr)(const char *, const char *) = strstr; + ++static char** ++tokenize(char *source, const char *delim, int *llen) { ++ int listlength = 0; ++ char **list = malloc(1 * sizeof(char*)); ++ char *token = strtok(source, delim); ++ ++ while (token) { ++ if (!(list = realloc(list, sizeof(char*) * (listlength + 1)))) ++ die("Unable to realloc %d bytes\n", sizeof(char*) * (listlength + 1)); ++ if (!(list[listlength] = strdup(token))) ++ die("Unable to strdup %d bytes\n", strlen(token) + 1); ++ token = strtok(NULL, delim); ++ listlength++; ++ } ++ ++ *llen = listlength; ++ return list; ++} ++ ++static int ++arrayhas(char **list, int length, char *item) { ++ for (int i = 0; i < length; i++) { ++ int len1 = strlen(list[i]); ++ int len2 = strlen(item); ++ if (fstrncmp(list[i], item, len1 > len2 ? len2 : len1) == 0) ++ return 1; ++ } ++ return 0; ++} ++ + static void + appenditem(struct item *item, struct item **list, struct item **last) + { +@@ -118,6 +150,8 @@ drawitem(struct item *item, int x, int y, int w) + { + if (item == sel) + drw_setscheme(drw, scheme[SchemeSel]); ++ else if (item->hp) ++ drw_setscheme(drw, scheme[SchemeHp]); + else if (item->out) + drw_setscheme(drw, scheme[SchemeOut]); + else +@@ -219,7 +253,7 @@ match(void) + char buf[sizeof text], *s; + int i, tokc = 0; + size_t len, textsize; +- struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; ++ struct item *item, *lhpprefix, *lprefix, *lsubstr, *hpprefixend, *prefixend, *substrend; + + strcpy(buf, text); + /* separate input text into tokens to be matched individually */ +@@ -228,7 +262,7 @@ match(void) + die("cannot realloc %u bytes:", tokn * sizeof *tokv); + len = tokc ? strlen(tokv[0]) : 0; + +- matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; ++ matches = lhpprefix = lprefix = lsubstr = matchend = hpprefixend = prefixend = substrend = NULL; + textsize = strlen(text) + 1; + for (item = items; item && item->text; item++) { + for (i = 0; i < tokc; i++) +@@ -236,14 +270,24 @@ match(void) + break; + if (i != tokc) /* not all tokens match */ + continue; +- /* exact matches go first, then prefixes, then substrings */ ++ /* exact matches go first, then prefixes with high priority, then prefixes, then substrings */ + if (!tokc || !fstrncmp(text, item->text, textsize)) + appenditem(item, &matches, &matchend); ++ else if (item->hp && !fstrncmp(tokv[0], item->text, len)) ++ appenditem(item, &lhpprefix, &hpprefixend); + else if (!fstrncmp(tokv[0], item->text, len)) + appenditem(item, &lprefix, &prefixend); + else + appenditem(item, &lsubstr, &substrend); + } ++ if (lhpprefix) { ++ if (matches) { ++ matchend->right = lhpprefix; ++ lhpprefix->left = matchend; ++ } else ++ matches = lhpprefix; ++ matchend = hpprefixend; ++ } + if (lprefix) { + if (matches) { + matchend->right = lprefix; +@@ -535,6 +579,7 @@ readstdin(void) + if (!(items[i].text = strdup(buf))) + die("cannot strdup %u bytes:", strlen(buf) + 1); + items[i].out = 0; ++ items[i].hp = arrayhas(hpitems, hplength, items[i].text); + drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); + if (tmpmax > inputw) { + inputw = tmpmax; +@@ -683,7 +728,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" ++ " [-hb color] [-hf color] [-hp items]\n", stderr); + exit(1); + } + +@@ -724,8 +770,14 @@ main(int argc, char *argv[]) + colors[SchemeSel][ColBg] = argv[++i]; + else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ + colors[SchemeSel][ColFg] = argv[++i]; ++ else if (!strcmp(argv[i], "-hb")) /* high priority background color */ ++ colors[SchemeHp][ColBg] = argv[++i]; ++ else if (!strcmp(argv[i], "-hf")) /* low priority background color */ ++ colors[SchemeHp][ColFg] = argv[++i]; + else if (!strcmp(argv[i], "-w")) /* embedding window id */ + embed = argv[++i]; ++ else if (!strcmp(argv[i], "-hp")) ++ hpitems = tokenize(argv[++i], ",", &hplength); + else + usage(); + +-- +2.26.2 + diff --git a/patches/3.dmenu-numbers-4.9.diff b/patches/3.dmenu-numbers-4.9.diff deleted file mode 100644 index 113be80..0000000 --- a/patches/3.dmenu-numbers-4.9.diff +++ /dev/null @@ -1,81 +0,0 @@ -From 61abc60dbfaa8ec63fcd176307308aee88a19e32 Mon Sep 17 00:00:00 2001 -From: Miles Alan -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/4.dmenu-lineheight-5.0.diff b/patches/4.dmenu-lineheight-5.0.diff deleted file mode 100644 index 3b0df3d..0000000 --- a/patches/4.dmenu-lineheight-5.0.diff +++ /dev/null @@ -1,106 +0,0 @@ -From ba103e38ea4ab07f9a3ee90627714b9bea17c329 Mon Sep 17 00:00:00 2001 -From: pskry -Date: Sun, 8 Nov 2020 22:04:22 +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 | 3 +++ - dmenu.1 | 5 +++++ - dmenu.c | 11 ++++++++--- - 3 files changed, 16 insertions(+), 3 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 1edb647..4394dec 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -15,6 +15,9 @@ static const char *colors[SchemeLast][2] = { - }; - /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ - static unsigned int lines = 0; -+/* -h option; minimum height of a menu line */ -+static unsigned int lineheight = 0; -+static unsigned int min_lineheight = 8; - - /* - * Characters not considered part of a word while deleting words -diff --git a/dmenu.1 b/dmenu.1 -index 323f93c..f2a82b4 100644 ---- a/dmenu.1 -+++ b/dmenu.1 -@@ -6,6 +6,8 @@ dmenu \- dynamic menu - .RB [ \-bfiv ] - .RB [ \-l - .IR lines ] -+.RB [ \-h -+.IR height ] - .RB [ \-m - .IR monitor ] - .RB [ \-p -@@ -50,6 +52,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 65f25ce..f2a4047 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) { -@@ -609,6 +609,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 -@@ -689,7 +690,7 @@ setup(void) - static void - usage(void) - { -- fputs("usage: dmenu [-bfiv] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" -+ fputs("usage: dmenu [-bfiv] [-l lines] [-h height] [-p prompt] [-fn font] [-m monitor]\n" - " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n", stderr); - exit(1); - } -@@ -717,6 +718,10 @@ 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 one menu line */ -+ lineheight = atoi(argv[++i]); -+ lineheight = MAX(lineheight, min_lineheight); -+ } - else if (!strcmp(argv[i], "-m")) - mon = atoi(argv[++i]); - else if (!strcmp(argv[i], "-p")) /* adds prompt to left of input field */ --- -2.29.2 - diff --git a/patches/4.dmenu-numbers-4.9.diff b/patches/4.dmenu-numbers-4.9.diff new file mode 100644 index 0000000..113be80 --- /dev/null +++ b/patches/4.dmenu-numbers-4.9.diff @@ -0,0 +1,81 @@ +From 61abc60dbfaa8ec63fcd176307308aee88a19e32 Mon Sep 17 00:00:00 2001 +From: Miles Alan +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-highpriority-4.9.diff b/patches/5.dmenu-highpriority-4.9.diff deleted file mode 100644 index 03e106a..0000000 --- a/patches/5.dmenu-highpriority-4.9.diff +++ /dev/null @@ -1,178 +0,0 @@ -From e9e1691a9b4ffa2db45cd5108b76b9a68610ba37 Mon Sep 17 00:00:00 2001 -From: takase1121 -Date: Sun, 17 May 2020 07:05:32 +0800 -Subject: [PATCH] Adds high-priority items. - -This allows users to specify a list of high priority commands that should be -displayed before other matches with the following arrangement: - -match -> prefix && high priority -> prefix -> substring - -As you can see, high priority for substring matches is not implemented or will not -be implemented depending on needs. ---- - config.def.h | 1 + - dmenu.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++----- - 2 files changed, 59 insertions(+), 6 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 1edb647..65e03fb 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -12,6 +12,7 @@ static const char *colors[SchemeLast][2] = { - [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; -diff --git a/dmenu.c b/dmenu.c -index 6b8f51b..7bf4099 100644 ---- a/dmenu.c -+++ b/dmenu.c -@@ -26,14 +26,16 @@ - #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - - /* enums */ --enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ -+enum { SchemeNorm, SchemeSel, SchemeHp, SchemeOut, SchemeLast }; /* color schemes */ - - struct item { - char *text; - struct item *left, *right; -- int out; -+ int out, hp; - }; - -+static char **hpitems = NULL; -+static int hplength = 0; - static char text[BUFSIZ] = ""; - static char *embed; - static int bh, mw, mh; -@@ -58,6 +60,36 @@ static Clr *scheme[SchemeLast]; - static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; - static char *(*fstrstr)(const char *, const char *) = strstr; - -+static char** -+tokenize(char *source, const char *delim, int *llen) { -+ int listlength = 0; -+ char **list = malloc(1 * sizeof(char*)); -+ char *token = strtok(source, delim); -+ -+ while (token) { -+ if (!(list = realloc(list, sizeof(char*) * (listlength + 1)))) -+ die("Unable to realloc %d bytes\n", sizeof(char*) * (listlength + 1)); -+ if (!(list[listlength] = strdup(token))) -+ die("Unable to strdup %d bytes\n", strlen(token) + 1); -+ token = strtok(NULL, delim); -+ listlength++; -+ } -+ -+ *llen = listlength; -+ return list; -+} -+ -+static int -+arrayhas(char **list, int length, char *item) { -+ for (int i = 0; i < length; i++) { -+ int len1 = strlen(list[i]); -+ int len2 = strlen(item); -+ if (fstrncmp(list[i], item, len1 > len2 ? len2 : len1) == 0) -+ return 1; -+ } -+ return 0; -+} -+ - static void - appenditem(struct item *item, struct item **list, struct item **last) - { -@@ -118,6 +150,8 @@ drawitem(struct item *item, int x, int y, int w) - { - if (item == sel) - drw_setscheme(drw, scheme[SchemeSel]); -+ else if (item->hp) -+ drw_setscheme(drw, scheme[SchemeHp]); - else if (item->out) - drw_setscheme(drw, scheme[SchemeOut]); - else -@@ -219,7 +253,7 @@ match(void) - char buf[sizeof text], *s; - int i, tokc = 0; - size_t len, textsize; -- struct item *item, *lprefix, *lsubstr, *prefixend, *substrend; -+ struct item *item, *lhpprefix, *lprefix, *lsubstr, *hpprefixend, *prefixend, *substrend; - - strcpy(buf, text); - /* separate input text into tokens to be matched individually */ -@@ -228,7 +262,7 @@ match(void) - die("cannot realloc %u bytes:", tokn * sizeof *tokv); - len = tokc ? strlen(tokv[0]) : 0; - -- matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; -+ matches = lhpprefix = lprefix = lsubstr = matchend = hpprefixend = prefixend = substrend = NULL; - textsize = strlen(text) + 1; - for (item = items; item && item->text; item++) { - for (i = 0; i < tokc; i++) -@@ -236,14 +270,24 @@ match(void) - break; - if (i != tokc) /* not all tokens match */ - continue; -- /* exact matches go first, then prefixes, then substrings */ -+ /* exact matches go first, then prefixes with high priority, then prefixes, then substrings */ - if (!tokc || !fstrncmp(text, item->text, textsize)) - appenditem(item, &matches, &matchend); -+ else if (item->hp && !fstrncmp(tokv[0], item->text, len)) -+ appenditem(item, &lhpprefix, &hpprefixend); - else if (!fstrncmp(tokv[0], item->text, len)) - appenditem(item, &lprefix, &prefixend); - else - appenditem(item, &lsubstr, &substrend); - } -+ if (lhpprefix) { -+ if (matches) { -+ matchend->right = lhpprefix; -+ lhpprefix->left = matchend; -+ } else -+ matches = lhpprefix; -+ matchend = hpprefixend; -+ } - if (lprefix) { - if (matches) { - matchend->right = lprefix; -@@ -535,6 +579,7 @@ readstdin(void) - if (!(items[i].text = strdup(buf))) - die("cannot strdup %u bytes:", strlen(buf) + 1); - items[i].out = 0; -+ items[i].hp = arrayhas(hpitems, hplength, items[i].text); - drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); - if (tmpmax > inputw) { - inputw = tmpmax; -@@ -683,7 +728,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" -+ " [-hb color] [-hf color] [-hp items]\n", stderr); - exit(1); - } - -@@ -724,8 +770,14 @@ main(int argc, char *argv[]) - colors[SchemeSel][ColBg] = argv[++i]; - else if (!strcmp(argv[i], "-sf")) /* selected foreground color */ - colors[SchemeSel][ColFg] = argv[++i]; -+ else if (!strcmp(argv[i], "-hb")) /* high priority background color */ -+ colors[SchemeHp][ColBg] = argv[++i]; -+ else if (!strcmp(argv[i], "-hf")) /* low priority background color */ -+ colors[SchemeHp][ColFg] = argv[++i]; - else if (!strcmp(argv[i], "-w")) /* embedding window id */ - embed = argv[++i]; -+ else if (!strcmp(argv[i], "-hp")) -+ hpitems = tokenize(argv[++i], ",", &hplength); - else - usage(); - --- -2.26.2 - diff --git a/patches/5.dmenu-instant-4.7.diff b/patches/5.dmenu-instant-4.7.diff new file mode 100644 index 0000000..a78276f --- /dev/null +++ b/patches/5.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/6.dmenu-mousesupport-5.1.diff b/patches/6.dmenu-mousesupport-5.1.diff new file mode 100644 index 0000000..49824ba --- /dev/null +++ b/patches/6.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/7.dmenu-textscroll-20180607-a314412.diff b/patches/7.dmenu-textscroll-20180607-a314412.diff new file mode 100644 index 0000000..7a7386a --- /dev/null +++ b/patches/7.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/8.dmenu-navhistory-5.0.diff b/patches/8.dmenu-navhistory-5.0.diff new file mode 100644 index 0000000..1f7cf6c --- /dev/null +++ b/patches/8.dmenu-navhistory-5.0.diff @@ -0,0 +1,256 @@ +From a4a08baf35edb6b50ed14f76e99d0c6fe790759d Mon Sep 17 00:00:00 2001 +From: Max Schillinger +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/9.dmenu-highlight-20201211-fcdc159.diff b/patches/9.dmenu-highlight-20201211-fcdc159.diff deleted file mode 100644 index c3ac5c1..0000000 --- a/patches/9.dmenu-highlight-20201211-fcdc159.diff +++ /dev/null @@ -1,97 +0,0 @@ -From fcdc1593ed418166f20b7e691a49b1e6eefc116e Mon Sep 17 00:00:00 2001 -From: Nathaniel Evan -Date: Fri, 11 Dec 2020 11:08:12 +0700 -Subject: [PATCH] Highlight matched text in a different color scheme - ---- - config.def.h | 3 +++ - dmenu.c | 44 +++++++++++++++++++++++++++++++++++++++++--- - 2 files changed, 44 insertions(+), 3 deletions(-) - -diff --git a/config.def.h b/config.def.h -index 1edb647..79be73a 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -11,7 +11,10 @@ static const char *colors[SchemeLast][2] = { - /* fg bg */ - [SchemeNorm] = { "#bbbbbb", "#222222" }, - [SchemeSel] = { "#eeeeee", "#005577" }, -+ [SchemeSelHighlight] = { "#ffc978", "#005577" }, -+ [SchemeNormHighlight] = { "#ffc978", "#222222" }, - [SchemeOut] = { "#000000", "#00ffff" }, -+ [SchemeOutHighlight] = { "#ffc978", "#00ffff" }, - }; - /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ - static unsigned int lines = 0; -diff --git a/dmenu.c b/dmenu.c -index 65f25ce..cce1ad1 100644 ---- a/dmenu.c -+++ b/dmenu.c -@@ -26,8 +26,7 @@ - #define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad) - - /* enums */ --enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ -- -+enum { SchemeNorm, SchemeSel, SchemeOut, SchemeNormHighlight, SchemeSelHighlight, SchemeOutHighlight, SchemeLast }; /* color schemes */ - struct item { - char *text; - struct item *left, *right; -@@ -113,6 +112,43 @@ cistrstr(const char *s, const char *sub) - return NULL; - } - -+static void -+drawhighlights(struct item *item, int x, int y, int maxw) -+{ -+ char restorechar, tokens[sizeof text], *highlight, *token; -+ int indentx, highlightlen; -+ -+ drw_setscheme(drw, scheme[item == sel ? SchemeSelHighlight : item->out ? SchemeOutHighlight : SchemeNormHighlight]); -+ strcpy(tokens, text); -+ for (token = strtok(tokens, " "); token; token = strtok(NULL, " ")) { -+ highlight = fstrstr(item->text, token); -+ while (highlight) { -+ // Move item str end, calc width for highlight indent, & restore -+ highlightlen = highlight - item->text; -+ restorechar = *highlight; -+ item->text[highlightlen] = '\0'; -+ indentx = TEXTW(item->text); -+ item->text[highlightlen] = restorechar; -+ -+ // Move highlight str end, draw highlight, & restore -+ restorechar = highlight[strlen(token)]; -+ highlight[strlen(token)] = '\0'; -+ if (indentx - (lrpad / 2) - 1 < maxw) -+ drw_text( -+ drw, -+ x + indentx - (lrpad / 2) - 1, -+ y, -+ MIN(maxw - indentx, TEXTW(highlight) - lrpad), -+ bh, 0, highlight, 0 -+ ); -+ highlight[strlen(token)] = restorechar; -+ -+ if (strlen(highlight) - strlen(token) < strlen(token)) break; -+ highlight = fstrstr(highlight + strlen(token), token); -+ } -+ } -+} -+ - static int - drawitem(struct item *item, int x, int y, int w) - { -@@ -123,7 +159,9 @@ drawitem(struct item *item, int x, int y, int w) - else - drw_setscheme(drw, scheme[SchemeNorm]); - -- return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); -+ int r = drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); -+ drawhighlights(item, x, y, w); -+ return r; - } - - static void --- -2.29.2 - diff --git a/patches/9.dmenu-instant-4.7.diff b/patches/9.dmenu-instant-4.7.diff deleted file mode 100644 index a78276f..0000000 --- a/patches/9.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 */ -- cgit v1.2.3