summaryrefslogtreecommitdiff
path: root/dmenu.c
diff options
context:
space:
mode:
Diffstat (limited to 'dmenu.c')
-rw-r--r--dmenu.c157
1 files changed, 154 insertions, 3 deletions
diff --git a/dmenu.c b/dmenu.c
index f2542a4..61f6af6 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -60,6 +60,10 @@ static Clr *scheme[SchemeLast];
static char *colortemp[4];
static char *tempfonts;
+static char *histfile;
+static char **history;
+static size_t histsz, histpos;
+
#include "config.h"
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp;
@@ -374,6 +378,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)
{
char buf[32];
@@ -456,9 +583,26 @@ keypress(XKeyEvent *ev)
case XK_g: ksym = XK_Home; break;
case XK_G: ksym = XK_End; break;
case XK_h: ksym = XK_Up; break;
- case XK_j: ksym = XK_Next; break;
- case XK_k: ksym = XK_Prior; break;
+ //case XK_j: ksym = XK_Next; break;
+ //case XK_k: ksym = XK_Prior; break;
case XK_l: ksym = XK_Down; break;
+
+ case XK_j:
+ navhistory(-1);
+ buf[0]=0;
+ break;
+ case XK_k:
+ navhistory(1);
+ buf[0]=0;
+ break;
+ case XK_p:
+ navhistory(-1);
+ buf[0]=0;
+ break;
+ case XK_n:
+ navhistory(1);
+ buf[0]=0;
+ break;
default:
return;
}
@@ -544,6 +688,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);
}
@@ -899,7 +1045,8 @@ usage(void)
{
fputs("usage: dmenu [-bfinvP] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
" [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]\n"
- " [-hb color] [-hf color] [-hp items]\n", stderr);
+ " [-hb color] [-hf color] [-hp items]\n"
+ " [-H histfile]", stderr);
exit(1);
}
@@ -965,6 +1112,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"))
@@ -1028,6 +1177,8 @@ main(int argc, char *argv[])
die("pledge");
#endif
+ loadhistory();
+
if (fast && !isatty(0)) {
grabkeyboard();
readstdin();