diff options
Diffstat (limited to 'dmenu-zir-5.0.diff')
-rw-r--r-- | dmenu-zir-5.0.diff | 910 |
1 files changed, 0 insertions, 910 deletions
diff --git a/dmenu-zir-5.0.diff b/dmenu-zir-5.0.diff deleted file mode 100644 index a7ba6b0..0000000 --- a/dmenu-zir-5.0.diff +++ /dev/null @@ -1,910 +0,0 @@ -diff --git a/config.def.h b/config.def.h -index 1edb647..24cbb58 100644 ---- a/config.def.h -+++ b/config.def.h -@@ -2,22 +2,43 @@ - /* Default settings; can be overriden by command line. */ - - static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */ -+static int fuzzy = 1; /* -F option; if 0, dmenu doesn't use fuzzy matching */ -+static int centered = 0; /* -c option; centers dmenu on screen */ -+static int min_width = 500; /* minimum width when centered */ - /* -fn option overrides fonts[0]; default X11 font or font set */ - static const char *fonts[] = { -- "monospace:size=10" -+ "monospace:size=10", -+ "mononoki Nerd Font:size=12", - }; - static const char *prompt = NULL; /* -p option; prompt to the left of input field */ --static const char *colors[SchemeLast][2] = { -+static const char *colors[SchemeLast][10] = { - /* fg bg */ -- [SchemeNorm] = { "#bbbbbb", "#222222" }, -- [SchemeSel] = { "#eeeeee", "#005577" }, -- [SchemeOut] = { "#000000", "#00ffff" }, -+ [SchemeNorm] = { "#bbbbbb", "#222222", "#222222" }, -+ [SchemeSel] = { "#eeeeee", "#005577", "#005577" }, -+ [SchemeNormHighlight] = { "#ffc978", "#222222", "#222222" }, -+ [SchemeSelHighlight] = { "#ffc978", "#005577", "#005577" }, -+ [SchemeOut] = { "#000000", "#00ffff", "#00ffff" }, -+ [SchemeHighlight] = {"#f1fa8c", "#596377", "#3E485B"}, -+ [SchemeHover] = {"#ffffff", "#353D4B", "#3E485B"}, -+ [SchemeGreen] = {"#ffffff", "#52E067", "#41b252"}, -+ [SchemeRed] = {"#ffffff", "#e05252", "#c24343"}, -+ [SchemeYellow] = {"#ffffff", "#e0c452", "#bca33f"}, -+ [SchemeBlue] = {"#ffffff", "#5280e0", "#3a62b3"}, -+ [SchemePurple] = {"#ffffff", "#9952e0", "#7439b0"}, - }; - /* -l option; if nonzero, dmenu uses vertical list with given number of lines */ - static unsigned int lines = 0; -+static unsigned int lineheight = 0; /* -h option; minimum height of a menu line */ -+static unsigned int min_lineheight = 8; -+static int sely = 0; -+static int commented = 0; -+static int animated = 0; - - /* - * Characters not considered part of a word while deleting words - * for example: " /?\"&[]" - */ - static const char worddelimiters[] = " "; -+ -+/* Size of the window border */ -+static unsigned int border_width = 0; -diff --git a/config.mk b/config.mk -index 05d5a3e..cbb87eb 100644 ---- a/config.mk -+++ b/config.mk -@@ -20,11 +20,11 @@ FREETYPEINC = /usr/include/freetype2 - - # includes and libs - INCS = -I$(X11INC) -I$(FREETYPEINC) --LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -+LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS) -lm - - # flags - CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_POSIX_C_SOURCE=200809L -DVERSION=\"$(VERSION)\" $(XINERAMAFLAGS) --CFLAGS = -std=c99 -pedantic -Wall -Os $(INCS) $(CPPFLAGS) -+CFLAGS = -std=c99 -pedantic -Wall -O3 -march=native $(INCS) $(CPPFLAGS) - LDFLAGS = $(LIBS) - - # compiler and linker -diff --git a/dmenu.1 b/dmenu.1 -index 323f93c..36926c2 100644 ---- a/dmenu.1 -+++ b/dmenu.1 -@@ -3,9 +3,11 @@ - dmenu \- dynamic menu - .SH SYNOPSIS - .B dmenu --.RB [ \-bfiv ] -+.RB [ \-bfsrvP ] - .RB [ \-l - .IR lines ] -+.RB [ \-h -+.IR height ] - .RB [ \-m - .IR monitor ] - .RB [ \-p -@@ -20,8 +22,20 @@ dmenu \- dynamic menu - .IR color ] - .RB [ \-sf - .IR color ] -+.RB [ \-nhb -+.IR color ] -+.RB [ \-nhf -+.IR color ] -+.RB [ \-shb -+.IR color ] -+.RB [ \-shf -+.IR color ] - .RB [ \-w - .IR windowid ] -+.RB [ \-d -+.IR separator ] -+.RB [ \-D -+.IR separator ] - .P - .BR dmenu_run " ..." - .SH DESCRIPTION -@@ -40,16 +54,28 @@ which lists programs in the user's $PATH and runs the result in their $SHELL. - .B \-b - dmenu appears at the bottom of the screen. - .TP -+.B \-c -+dmenu appears centered on the screen. -+.TP - .B \-f - dmenu grabs the keyboard before reading stdin if not reading from a tty. This - is faster, but will lock up X until stdin reaches end\-of\-file. - .TP --.B \-i --dmenu matches menu items case insensitively. -+.B \-s -+dmenu matches menu items case sensitively. -+.TP -+.B \-P -+dmenu will not directly display the keyboard input, but instead replace it with dots. All data from stdin will be ignored. -+.TP -+.B \-r -+dmenu will reject any input which would result in no matching option left. - .TP - .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. -@@ -75,11 +101,31 @@ defines the selected background color. - .BI \-sf " color" - defines the selected foreground color. - .TP -+.BI \-nhb " color" -+defines the normal highlight background color. -+.TP -+.BI \-nhf " color" -+defines the normal highlight foreground color. -+.TP -+.BI \-shb " color" -+defines the selected highlight background color. -+.TP -+.BI \-shf " color" -+defines the selected highlight foreground color. -+.TP - .B \-v - prints version information to stdout, then exits. - .TP - .BI \-w " windowid" - embed into windowid. -+.TP -+.BI \-d " separator" -+separate the input into two halves on the first occurrence of the given charcter. -+Display only the first half in dmenu and print the second half to stdout upon selection. -+Appending '|' to the separator reverses the display/printing order. -+.TP -+.BI \-D " separator" -+same as \-d but separate based on the last occurrence. - .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..0f4d6b4 100644 ---- a/dmenu.c -+++ b/dmenu.c -@@ -1,6 +1,7 @@ - /* See LICENSE file for copyright and license details. */ - #include <ctype.h> - #include <locale.h> -+#include <math.h> - #include <stdio.h> - #include <stdlib.h> - #include <string.h> -@@ -22,23 +23,49 @@ - /* macros */ - #define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ - * MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) -+#define INTERSECTBOOL(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ -+ && 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) - - /* enums */ --enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ -+enum { -+ SchemeNorm, -+ SchemeFade, -+ SchemeHighlight, -+ SchemeHover, -+ SchemeSel, -+ SchemeNormHighlight, -+ SchemeSelHighlight, -+ SchemeOut, -+ SchemeGreen, -+ SchemeYellow, -+ SchemeBlue, -+ SchemePurple, -+ SchemeRed, -+ SchemeLast -+}; /* color schemes */ - - struct item { - char *text; -+ char *text_output; - struct item *left, *right; - int out; -+ double distance; - }; - - static char text[BUFSIZ] = ""; - static char *embed; -+static char separator; -+static int separator_greedy; -+static int separator_reverse; - static int bh, mw, mh; --static int inputw = 0, promptw; -+static int dmx = 0; /* put dmenu at this x offset */ -+static int dmy = 0; /* put dmenu at this y offset (measured from the bottom if topbar is 0) */ -+static unsigned int dmw = 0; /* make dmenu this wide */ -+static int inputw = 0, promptw, passwd = 0; - static int lrpad; /* sum of left and right padding */ -+static int reject_no_match = 0; - static size_t cursor; - static struct item *items = NULL; - static struct item *matches, *matchend; -@@ -55,8 +82,9 @@ static Clr *scheme[SchemeLast]; - - #include "config.h" - --static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; --static char *(*fstrstr)(const char *, const char *) = strstr; -+static char * cistrstr(const char *s, const char *sub); -+static int (*fstrncmp)(const char *, const char *, size_t) = strncasecmp; -+static char *(*fstrstr)(const char *, const char *) = cistrstr; - - static void - appenditem(struct item *item, struct item **list, struct item **last) -@@ -89,6 +117,15 @@ calcoffsets(void) - break; - } - -+static int -+max_textw(void) -+{ -+ int len = 0; -+ for (struct item *item = items; item && item->text; item++) -+ len = MAX(TEXTW(item->text), len); -+ return len; -+} -+ - static void - cleanup(void) - { -@@ -113,17 +150,160 @@ cistrstr(const char *s, const char *sub) - return NULL; - } - --static int --drawitem(struct item *item, int x, int y, int w) -+static void -+drawhighlights(struct item *item, int x, int y, int maxw) - { -- if (item == sel) -- drw_setscheme(drw, scheme[SchemeSel]); -- else if (item->out) -- drw_setscheme(drw, scheme[SchemeOut]); -- else -- drw_setscheme(drw, scheme[SchemeNorm]); -+ int i, indent; -+ char *highlight; -+ char c; -+ -+ if (!(strlen(item->text) && strlen(text))) -+ return; -+ -+ drw_setscheme(drw, scheme[item == sel -+ ? SchemeSelHighlight -+ : SchemeNormHighlight]); -+ -+ for (i = 0, highlight = item->text; *highlight && text[i];) { -+ if (*highlight == text[i]) { -+ /* get indentation */ -+ c = *highlight; -+ *highlight = '\0'; -+ indent = TEXTW(item->text); -+ *highlight = c; -+ -+ /* highlight character */ -+ c = highlight[1]; -+ highlight[1] = '\0'; -+ drw_text( -+ drw, -+ x + indent - (lrpad / 2), -+ y, -+ MIN(maxw - indent, TEXTW(highlight) - lrpad), -+ bh, 0, highlight, 0 -+ ); -+ highlight[1] = c; -+ i++; -+ } -+ highlight++; -+ } -+} - -- return drw_text(drw, x, y, w, bh, lrpad / 2, item->text, 0); -+static int -+drawitem(struct item *item, int x, int y, int w) { -+ int r; -+ int iscomment = 0; -+ if (item->text[0] == '>') { -+ if (item->text[1] == '>') { -+ iscomment = 3; -+ switch (item->text[2]) { -+ case 'r': -+ drw_setscheme(drw, scheme[SchemeRed]); -+ break; -+ case 'g': -+ drw_setscheme(drw, scheme[SchemeGreen]); -+ break; -+ case 'y': -+ drw_setscheme(drw, scheme[SchemeYellow]); -+ break; -+ case 'b': -+ drw_setscheme(drw, scheme[SchemeBlue]); -+ break; -+ case 'p': -+ drw_setscheme(drw, scheme[SchemePurple]); -+ break; -+ case 'h': -+ drw_setscheme(drw, scheme[SchemeHighlight]); -+ break; -+ case 's': -+ drw_setscheme(drw, scheme[SchemeSel]); -+ break; -+ default: -+ iscomment = 1; -+ drw_setscheme(drw, scheme[SchemeNorm]); -+ break; -+ } -+ } else { -+ drw_setscheme(drw, scheme[SchemeNorm]); -+ iscomment = 1; -+ } -+ -+ } else if (item->text[0] == ':') { -+ iscomment = 2; -+ if (item == sel) { -+ switch (item->text[1]) { -+ case 'r': -+ drw_setscheme(drw, scheme[SchemeRed]); -+ break; -+ case 'g': -+ drw_setscheme(drw, scheme[SchemeGreen]); -+ break; -+ case 'y': -+ drw_setscheme(drw, scheme[SchemeYellow]); -+ break; -+ case 'b': -+ drw_setscheme(drw, scheme[SchemeBlue]); -+ break; -+ case 'p': -+ drw_setscheme(drw, scheme[SchemePurple]); -+ break; -+ case 'h': -+ drw_setscheme(drw, scheme[SchemeHighlight]); -+ break; -+ case 's': -+ drw_setscheme(drw, scheme[SchemeSel]); -+ break; -+ default: -+ drw_setscheme(drw, scheme[SchemeSel]); -+ iscomment = 0; -+ break; -+ } -+ } else { -+ drw_setscheme(drw, scheme[SchemeNorm]); -+ } -+ } else { -+ if (item == sel) -+ drw_setscheme(drw, scheme[SchemeSel]); -+ else if (item->out) -+ drw_setscheme(drw, scheme[SchemeOut]); -+ else -+ drw_setscheme(drw, scheme[SchemeNorm]); -+ } -+ -+ int temppadding; -+ temppadding = 0; -+ if (iscomment == 2) { -+ if (item->text[2] == ' ') { -+ temppadding = drw->fonts->h * 3; -+ animated = 1; -+ char dest[1000]; -+ strcpy(dest, item->text); -+ dest[6] = '\0'; -+ drw_text(drw, x, y, temppadding, lineheight, temppadding / 2.6, dest + 3, 0); -+ iscomment = 6; -+ drw_setscheme(drw, sel == item ? scheme[SchemeHover] : scheme[SchemeNorm]); -+ } -+ } -+ -+ char *output; -+ if (commented) { -+ static char onestr[2]; -+ onestr[0] = item->text[0]; -+ onestr[1] = '\0'; -+ output = onestr; -+ } else { -+ output = item->text; -+ } -+ -+ if (item == sel) -+ sely = y; -+ r = drw_text( -+ drw, x + ((iscomment == 6) ? temppadding : 0), y, -+ commented ? bh : (w - ((iscomment == 6) ? temppadding : 0)), bh, -+ commented ? (bh - drw_fontset_getwidth(drw, (output))) / 2 : lrpad / 2, -+ output + iscomment, 0); -+ drawhighlights(item, x, y, w); -+ return r; - } - - static void -@@ -131,7 +311,8 @@ drawmenu(void) - { - unsigned int curpos; - struct item *item; -- int x = 0, y = 0, w; -+ int x = 0, y = 0, fh = drw->fonts->h, w; -+ char *censort; - - drw_setscheme(drw, scheme[SchemeNorm]); - drw_rect(drw, 0, 0, mw, mh, 1, 1); -@@ -143,12 +324,17 @@ 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); -+ if (passwd) { -+ censort = ecalloc(1, sizeof(text)); -+ memset(censort, '.', strlen(text)); -+ drw_text(drw, x, 0, w, bh, lrpad / 2, censort, 0); -+ free(censort); -+ } else drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0); - - 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) { -@@ -210,9 +396,94 @@ grabkeyboard(void) - die("cannot grab keyboard"); - } - -+int -+compare_distance(const void *a, const void *b) -+{ -+ struct item *da = *(struct item **) a; -+ struct item *db = *(struct item **) b; -+ -+ if (!db) -+ return 1; -+ if (!da) -+ return -1; -+ -+ return da->distance == db->distance ? 0 : da->distance < db->distance ? -1 : 1; -+} -+ -+void -+fuzzymatch(void) -+{ -+ /* bang - we have so much memory */ -+ struct item *it; -+ struct item **fuzzymatches = NULL; -+ char c; -+ int number_of_matches = 0, i, pidx, sidx, eidx; -+ int text_len = strlen(text), itext_len; -+ -+ matches = matchend = NULL; -+ -+ /* walk through all items */ -+ for (it = items; it && it->text; it++) { -+ if (text_len) { -+ itext_len = strlen(it->text); -+ pidx = 0; /* pointer */ -+ sidx = eidx = -1; /* start of match, end of match */ -+ /* walk through item text */ -+ for (i = 0; i < itext_len && (c = it->text[i]); i++) { -+ /* fuzzy match pattern */ -+ if (!fstrncmp(&text[pidx], &c, 1)) { -+ if(sidx == -1) -+ sidx = i; -+ pidx++; -+ if (pidx == text_len) { -+ eidx = i; -+ break; -+ } -+ } -+ } -+ /* build list of matches */ -+ if (eidx != -1) { -+ /* compute distance */ -+ /* add penalty if match starts late (log(sidx+2)) -+ * add penalty for long a match without many matching characters */ -+ it->distance = log(sidx + 2) + (double)(eidx - sidx - text_len); -+ /* fprintf(stderr, "distance %s %f\n", it->text, it->distance); */ -+ appenditem(it, &matches, &matchend); -+ number_of_matches++; -+ } -+ } else { -+ appenditem(it, &matches, &matchend); -+ } -+ } -+ -+ if (number_of_matches) { -+ /* initialize array with matches */ -+ if (!(fuzzymatches = realloc(fuzzymatches, number_of_matches * sizeof(struct item*)))) -+ die("cannot realloc %u bytes:", number_of_matches * sizeof(struct item*)); -+ for (i = 0, it = matches; it && i < number_of_matches; i++, it = it->right) { -+ fuzzymatches[i] = it; -+ } -+ /* sort matches according to distance */ -+ qsort(fuzzymatches, number_of_matches, sizeof(struct item*), compare_distance); -+ /* rebuild list of matches */ -+ matches = matchend = NULL; -+ for (i = 0, it = fuzzymatches[i]; i < number_of_matches && it && \ -+ it->text; i++, it = fuzzymatches[i]) { -+ appenditem(it, &matches, &matchend); -+ } -+ free(fuzzymatches); -+ } -+ curr = sel = matches; -+ calcoffsets(); -+} -+ - static void - match(void) - { -+ if (fuzzy) { -+ fuzzymatch(); -+ return; -+ } - static char **tokv = NULL; - static int tokn = 0; - -@@ -269,12 +540,26 @@ insert(const char *str, ssize_t n) - { - if (strlen(text) + n > sizeof text - 1) - return; -+ -+ static char last[BUFSIZ] = ""; -+ if(reject_no_match) { -+ /* store last text value in case we need to revert it */ -+ memcpy(last, text, BUFSIZ); -+ } -+ - /* move existing text out of the way, insert new text, and update cursor */ - memmove(&text[cursor + n], &text[cursor], sizeof text - cursor - MAX(n, 0)); - if (n > 0) - memcpy(&text[cursor], str, n); - cursor += n; - match(); -+ -+ if(!matches && reject_no_match) { -+ /* revert to last text value if theres no match */ -+ memcpy(text, last, BUFSIZ); -+ cursor -= n; -+ match(); -+ } - } - - static size_t -@@ -464,7 +749,7 @@ insert: - break; - case XK_Return: - case XK_KP_Enter: -- puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); -+ puts((sel && !(ev->state & ShiftMask)) ? sel->text_output : text); - if (!(ev->state & ControlMask)) { - cleanup(); - exit(0); -@@ -500,6 +785,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) - { -@@ -524,6 +922,11 @@ readstdin(void) - char buf[sizeof text], *p; - size_t i, imax = 0, size = 0; - unsigned int tmpmax = 0; -+ if(passwd){ -+ inputw = lines = 0; -+ return; -+ } -+ - - /* read each line from stdin and add it to the item list */ - for (i = 0; fgets(buf, sizeof buf, stdin); i++) { -@@ -534,6 +937,18 @@ readstdin(void) - *p = '\0'; - if (!(items[i].text = strdup(buf))) - die("cannot strdup %u bytes:", strlen(buf) + 1); -+ if (separator && (p = (separator_greedy) ? -+ strrchr(items[i].text, separator) : strchr(items[i].text, separator))) { -+ *p = '\0'; -+ items[i].text_output = ++p; -+ } else { -+ items[i].text_output = items[i].text; -+ } -+ if (separator_reverse) { -+ char *tmp = items[i].text; -+ items[i].text = items[i].text_output; -+ items[i].text_output = tmp; -+ } - items[i].out = 0; - drw_font_getexts(drw->fonts, buf, strlen(buf), &tmpmax, NULL); - if (tmpmax > inputw) { -@@ -561,6 +976,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); -@@ -609,8 +1027,10 @@ 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; -+ promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; - #ifdef XINERAMA - i = 0; - if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) { -@@ -634,12 +1054,18 @@ setup(void) - /* no focused window is on screen, so use pointer location instead */ - if (mon < 0 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) - for (i = 0; i < n; i++) -- if (INTERSECT(x, y, 1, 1, info[i])) -+ if (INTERSECTBOOL(x, y, 1, 1, info[i])) - break; - -- x = info[i].x_org; -- y = info[i].y_org + (topbar ? 0 : info[i].height - mh); -- mw = info[i].width; -+ if (centered) { -+ mw = MIN(MAX(max_textw() + promptw, min_width), info[i].width); -+ x = info[i].x_org + ((info[i].width - mw) / 2); -+ y = info[i].y_org + ((info[i].height - mh) / 2); -+ } else { -+ x = info[i].x_org; -+ y = info[i].y_org + (topbar ? 0 : info[i].height - mh); -+ mw = info[i].width; -+ } - XFree(info); - } else - #endif -@@ -647,21 +1073,29 @@ setup(void) - if (!XGetWindowAttributes(dpy, parentwin, &wa)) - die("could not get embedding window attributes: 0x%lx", - parentwin); -- x = 0; -- y = topbar ? 0 : wa.height - mh; -- mw = wa.width; -+ if (centered) { -+ mw = MIN(MAX(max_textw() + promptw, min_width), wa.width); -+ x = (wa.width - mw) / 2; -+ y = (wa.height - mh) / 2; -+ } else { -+ x = dmx; -+ y = topbar ? dmy : wa.height - mh; -+ mw = wa.width; -+ } - } -- promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0; - inputw = MIN(inputw, mw/3); - match(); - - /* create menu window */ - swa.override_redirect = True; - swa.background_pixel = scheme[SchemeNorm][ColBg].pixel; -- swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; -- win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0, -+ swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask | -+ ButtonPressMask; -+ win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width, - CopyFromParent, CopyFromParent, CopyFromParent, - CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); -+ if (border_width) -+ XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel); - XSetClassHint(dpy, win, &ch); - - -@@ -689,8 +1123,10 @@ setup(void) - 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); -+ fputs("usage: dmenu [-bfsrvP] [-l lines] [-h height] [-p prompt] [-fn font] [-m monitor]\n" -+ " [-x xoffset] [-y yoffset] [-z width] [-nb color] [-nf color] [-sb color] [-sf color]\n" -+ " [-nhb color] [-nhf color] [-shb color] [-shf color] [-w windowid]\n" -+ " [-d separator] [-D separator]\n", stderr); - exit(1); - } - -@@ -709,14 +1145,32 @@ main(int argc, char *argv[]) - topbar = 0; - else if (!strcmp(argv[i], "-f")) /* grabs keyboard before reading stdin */ - fast = 1; -- else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */ -- fstrncmp = strncasecmp; -- fstrstr = cistrstr; -- } else if (i + 1 == argc) -+ else if (!strcmp(argv[i], "-F")) /* is not fuzzy search */ -+ fuzzy = 0; -+ else if (!strcmp(argv[i], "-c")) /* centers dmenu on screen */ -+ centered = 1; -+ else if (!strcmp(argv[i], "-s")) { /* case-sensitive item matching */ -+ fstrncmp = strncmp; -+ fstrstr = strstr; -+ } else if (!strcmp(argv[i], "-r")) /* reject input which results in no match */ -+ reject_no_match = 1; -+ else if (!strcmp(argv[i], "-P")) /* is the input a password */ -+ passwd = 1; -+ else if (i + 1 == argc) - usage(); - /* 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], "-x")) /* window x offset */ -+ dmx = atoi(argv[++i]); -+ else if (!strcmp(argv[i], "-y")) /* window x offset */ -+ dmy = atoi(argv[++i]); -+ else if (!strcmp(argv[i], "-z")) /* window x offset */ -+ dmw = 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 */ -@@ -731,8 +1185,23 @@ 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], "-nhb")) /* normal hi background color */ -+ colors[SchemeNormHighlight][ColBg] = argv[++i]; -+ else if (!strcmp(argv[i], "-nhf")) /* normal hi foreground color */ -+ colors[SchemeNormHighlight][ColFg] = argv[++i]; -+ else if (!strcmp(argv[i], "-shb")) /* selected hi background color */ -+ colors[SchemeSelHighlight][ColBg] = argv[++i]; -+ else if (!strcmp(argv[i], "-shf")) /* selected hi foreground color */ -+ colors[SchemeSelHighlight][ColFg] = argv[++i]; - else if (!strcmp(argv[i], "-w")) /* embedding window id */ - embed = argv[++i]; -+ else if (!strcmp(argv[i], "-bw")) /* border width */ -+ border_width = atoi(argv[++i]); -+ else if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "-D")) { /* field separator */ -+ separator_reverse = (*(argv[i+1]+1) == '|'); -+ separator_greedy = !strcmp(argv[i], "-D"); -+ separator = *argv[++i]; -+ } - else - usage(); - -@@ -752,6 +1221,9 @@ main(int argc, char *argv[]) - die("no fonts could be loaded."); - lrpad = drw->fonts->h; - -+ if (lineheight == -1) -+ lineheight = drw->fonts->h * 2.5; -+ - #ifdef __OpenBSD__ - if (pledge("stdio rpath", NULL) == -1) - die("pledge"); |