@@ 40,7 40,7 @@ static int bh, mw, mh;
static int inputw = 0, promptw;
static int lrpad; /* sum of left and right padding */
static size_t cursor;
static struct item *items = NULL;
static struct item *items = NULL, *backup_items;
static struct item *matches, *matchend;
static struct item *prev, *curr, *next, *sel;
static int mon = -1, screen;
@@ 54,8 54,8 @@ static Drw *drw;
static Clr *scheme[SchemeLast];
static char *histfile;
static char *histbuf, *histptr;
static size_t histsz;
static char **history;
static size_t histsz, histpos;
#include "config.h"
@@ 321,107 321,130 @@ static void
loadhistory(void)
{
FILE *fp = NULL;
size_t sz;
static size_t cap = 0;
size_t llen;
char *line;
if (!histfile)
if (!histfile) {
return;
if (!(fp = fopen(histfile, "r")))
}
fp = fopen(histfile, "r");
if (!fp) {
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;
}
for (;;) {
line = NULL;
llen = 0;
if (-1 == getline(&line, &llen, fp)) {
if (ferror(fp)) {
die("failed to read history");
}
if (histptr[-1] != '\n')
*histptr++ = '\n';
histptr[BUFSIZ - 1] = '\0';
*histptr = '\0';
histsz = histptr - histbuf + BUFSIZ;
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);
}
fclose(fp);
}
static void
navhistory(int dir)
{
char *p;
size_t len = 0, textlen;
static char def[BUFSIZ];
char *p = NULL;
size_t len = 0;
if (!histbuf)
if (!history || histpos + 1 == 0)
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';
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++;
}
for (histptr--; histptr != histbuf && histptr[-1] != '\n';
histptr--, len++);
break;
case -1:
if (histpos > 0) {
p = history[--histpos];
}
break;
}
if (p == NULL) {
return;
}
len = MIN(len, BUFSIZ - 1);
strncpy(text, histptr, len);
len = MIN(strlen(p), BUFSIZ - 1);
strncpy(text, p, len);
text[len] = '\0';
cursor = len;
match();
}
static void
savehistory(char *str)
savehistory(char *input)
{
unsigned int n, len = 0;
size_t slen;
char *p;
unsigned int i;
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;
}
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);
}
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);
if (!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];
int len;
int len, i;
KeySym ksym;
Status status;
@@ 472,6 495,26 @@ keypress(XKeyEvent *ev)
XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY,
utf8, utf8, win, CurrentTime);
return;
case XK_r:
if (histfile) {
if (!backup_items) {
backup_items = items;
items = calloc(histsz + 1, sizeof(struct item));
if (!items) {
die("cannot allocate memory");
}
for (i = 0; i < histsz; i++) {
items[i].text = history[i];
}
} else {
free(items);
items = backup_items;
backup_items = NULL;
}
}
match();
goto draw;
case XK_Left:
movewordedge(-1);
goto draw;
@@ 827,7 870,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);
}