diff -urp dmenu-4.6/config.def.h dmenu-4.6-patched/config.def.h --- dmenu-4.6/config.def.h 2015-11-09 06:42:21.000000000 +0800 +++ dmenu-4.6-patched/config.def.h 2016-04-03 10:59:02.413544865 +0800 @@ -15,3 +15,5 @@ static const char *outbgcolor = "#00fff static const char *outfgcolor = "#000000"; /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ static unsigned int lines = 0; +static unsigned int maxhist = 15; +static int histnodup = 1; /* if 0, record repeated histories */ diff -urp dmenu-4.6/dmenu.c dmenu-4.6-patched/dmenu.c --- dmenu-4.6/dmenu.c 2015-11-09 06:42:21.000000000 +0800 +++ dmenu-4.6-patched/dmenu.c 2016-04-03 10:54:51.798552270 +0800 @@ -52,6 +52,10 @@ static XIC xic; static ClrScheme scheme[SchemeLast]; static Drw *drw; +static char *histfile; +static char *histbuf, *histptr; +static size_t histsz; + #include "config.h" static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; @@ -278,6 +282,105 @@ nextrune(int inc) } static void +loadhistory(void) +{ + FILE *fp = NULL; + size_t sz; + + if (!histfile) + return; + if (!(fp = fopen(histfile, "r"))) + return; + fseek(fp, 0, SEEK_END); + sz = ftell(fp); + fseek(fp, 0, SEEK_SET); + if (sz) { + histsz = sz + 1 + BUFSIZ; + if (!(histbuf = malloc(histsz))) { + fprintf(stderr, "warning: cannot malloc %lu "\ + "bytes", histsz); + } else { + histptr = histbuf + fread(histbuf, 1, sz, fp); + if (histptr <= histbuf) { /* fread error */ + free(histbuf); + histbuf = NULL; + return; + } + if (histptr[-1] != '\n') + *histptr++ = '\n'; + histptr[BUFSIZ - 1] = '\0'; + *histptr = '\0'; + histsz = histptr - histbuf + BUFSIZ; + } + } + fclose(fp); +} + +static void +navhistory(int dir) +{ + char *p; + size_t len = 0, textlen; + + if (!histbuf) + return; + if (dir > 0) { + if (histptr == histbuf + histsz - BUFSIZ) + return; + while (*histptr && *histptr++ != '\n'); + for (p = histptr; *p && *p++ != '\n'; len++); + } else { + if (histptr == histbuf) + return; + if (histptr == histbuf + histsz - BUFSIZ) { + textlen = strlen(text); + textlen = MIN(textlen, BUFSIZ - 1); + strncpy(histptr, text, textlen); + histptr[textlen] = '\0'; + } + for (histptr--; histptr != histbuf && histptr[-1] != '\n'; + histptr--, len++); + } + len = MIN(len, BUFSIZ - 1); + strncpy(text, histptr, len); + text[len] = '\0'; + cursor = len; + match(); +} +static void +savehistory(char *str) +{ + unsigned int n, len = 0; + size_t slen; + char *p; + FILE *fp; + + if (!histfile || !maxhist) + return; + if (!(slen = strlen(str))) + return; + if (histbuf && maxhist > 1) { + p = histbuf + histsz - BUFSIZ - 1; /* skip the last newline */ + if (histnodup) { + for (; p != histbuf && p[-1] != '\n'; p--, len++); + n++; + if (slen == len && !strncmp(p, str, len)) { + return; + } + } + for (; p != histbuf; p--, len++) + if (p[-1] == '\n' && ++n + 1 > maxhist) + break; + fp = fopen(histfile, "w"); + fwrite(p, 1, len + 1, fp); /* plus the last newline */ + } else { + fp = fopen(histfile, "w"); + } + fwrite(str, 1, strlen(str), fp); + fclose(fp); +} + +static void keypress(XKeyEvent *ev) { char buf[32]; @@ -341,6 +444,8 @@ 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; } @@ -416,6 +521,8 @@ keypress(XKeyEvent *ev) 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); } @@ -608,7 +715,7 @@ setup(void) static void usage(void) { - fputs("usage: dmenu [-b] [-f] [-i] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" + fputs("usage: dmenu [-b] [-f] [-H histfile] [-i] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" " [-nb color] [-nf color] [-sb color] [-sf color] [-v]\n", stderr); exit(1); } @@ -633,6 +740,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")) @@ -665,6 +774,7 @@ main(int argc, char *argv[]) if (!drw->fontcount) die("no fonts could be loaded.\n"); drw_setscheme(drw, &scheme[SchemeNorm]); + loadhistory(); if (fast) { grabkeyboard();