~pkal/dmenu

f2fa5de27dc28a366e7c3ef39717616d8d210c6f — Philip K 2 years ago eb18990 + 8930e35
Merge branch 'patch/navhistory-search' into local
2 files changed, 117 insertions(+), 76 deletions(-)

M config.def.h
M dmenu.c
M config.def.h => config.def.h +0 -3
@@ 25,6 25,3 @@ static int histnodup           = 1;	/* if 0, record repeated histories */
 * for example: " /?\"&[]"
 */
static const char worddelimiters[] = " ";

/* Size of the window border */
static const unsigned int border_width = 5;

M dmenu.c => dmenu.c +117 -73
@@ 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);
}