summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorozpv <39195175+ozpv@users.noreply.github.com>2024-03-03 19:53:06 +0000
committerGitHub <noreply@github.com>2024-03-03 19:53:06 +0000
commit43e54b66235e89e2ba2f16b70a00f56a2ef04d57 (patch)
tree973a8a3a666218bb2bdd30e90b80036ab734f33d
parentdd471a8ff3c9cf006098a95583f181c6859b3c0d (diff)
update to 5.2
-rw-r--r--LICENSE30
-rw-r--r--config.def.h29
-rw-r--r--config.mk2
-rw-r--r--dmenu.c108
-rw-r--r--drw.c14
-rw-r--r--util.c23
6 files changed, 138 insertions, 68 deletions
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..2a64b28
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+MIT/X Consortium License
+
+© 2006-2019 Anselm R Garbe <anselm@garbe.ca>
+© 2006-2008 Sander van Dijk <a.h.vandijk@gmail.com>
+© 2006-2007 Michał Janeczek <janeczek@gmail.com>
+© 2007 Kris Maglione <jg@suckless.org>
+© 2009 Gottox <gottox@s01.de>
+© 2009 Markus Schnalke <meillo@marmaro.de>
+© 2009 Evan Gates <evan.gates@gmail.com>
+© 2010-2012 Connor Lane Smith <cls@lubutu.com>
+© 2014-2022 Hiltjo Posthuma <hiltjo@codemadness.org>
+© 2015-2019 Quentin Rameau <quinq@fifth.space>
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/config.def.h b/config.def.h
new file mode 100644
index 0000000..94330f1
--- /dev/null
+++ b/config.def.h
@@ -0,0 +1,29 @@
+/* See LICENSE file for copyright and license details. */
+/* Default settings; can be overriden by command line. */
+
+static int centered = 1;
+static int min_width = 500;
+static int topbar = 1; /* -b option; if 0, dmenu appears at bottom */
+static int draw_input = 1; /* -noi option; if 0, the input will not be drawn by default */
+/* -fn option overrides fonts[0]; default X11 font or font set */
+static const char *fonts[] = {
+ "monospace:size=10"
+};
+static const char *prompt = NULL; /* -p option; prompt to the left of input field */
+static const char *colors[SchemeLast][2] = {
+ /* fg bg */
+ [SchemeNorm] = { "#ebdbb2", "#282828" },
+ [SchemeSel] = { "#ebdbb2", "#928374" },
+ [SchemeOut] = { "#ebdbb2", "#8ec07c" },
+};
+/* -l option; if nonzero, dmenu uses vertical list with given number of lines */
+static unsigned int lines = 22;
+
+/*
+ * 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 = 2;
diff --git a/config.mk b/config.mk
index b0bd246..566348b 100644
--- a/config.mk
+++ b/config.mk
@@ -1,5 +1,5 @@
# dmenu version
-VERSION = 5.1
+VERSION = 5.2
# paths
PREFIX = /usr/local
diff --git a/dmenu.c b/dmenu.c
index 9385e60..ec9beac 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -157,30 +157,32 @@ drawmenu(void)
{
unsigned int curpos;
struct item *item;
- int x = 0, y = 0, w;
+ int x = 0, y = 0, w = 0;
drw_setscheme(drw, scheme[SchemeNorm]);
drw_rect(drw, 0, 0, mw, mh, 1, 1);
if (prompt && *prompt) {
drw_setscheme(drw, scheme[SchemeSel]);
- x = drw_text(drw, x, 0, promptw, bh, lrpad / 2, prompt, 0);
+ x = drw_text(drw, x, 0, ((!draw_input) ? mw : promptw), bh, lrpad / 2, prompt, 0);
}
- /* 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);
- curpos = TEXTW(text) - TEXTW(&text[cursor]);
- if ((curpos += lrpad / 2 - 1) < w) {
+ if (draw_input) {
+ w = (lines > 0 || !matches) ? mw - x : inputw;
drw_setscheme(drw, scheme[SchemeNorm]);
- drw_rect(drw, x + curpos, 2, 2, bh - 4, 1, 0);
+ 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);
+ }
}
if (lines > 0) {
/* draw vertical list */
for (item = curr; item != next; item = item->right)
- drawitem(item, x - promptw, y += bh, mw);
+ drawitem(item, !draw_input ? x - mw : x - promptw, y += bh, mw);
} else if (matches) {
/* draw horizontal list */
x += inputw;
@@ -188,8 +190,8 @@ drawmenu(void)
if (curr->left) {
drw_setscheme(drw, scheme[SchemeNorm]);
drw_text(drw, x, 0, w, bh, lrpad / 2, "<", 0);
+ x += w;
}
- x += w;
for (item = curr; item != next; item = item->right)
x = drawitem(item, x, 0, textw_clamp(item->text, mw - x - TEXTW(">")));
if (next) {
@@ -368,16 +370,19 @@ keypress(XKeyEvent *ev)
case XK_p: ksym = XK_Up; break;
case XK_k: /* delete right */
- text[cursor] = '\0';
- match();
+ if (draw_input) {
+ text[cursor] = '\0';
+ match();
+ }
break;
case XK_u: /* delete left */
- insert(NULL, 0 - cursor);
+ if (draw_input)
+ insert(NULL, 0 - cursor);
break;
case XK_w: /* delete word */
- while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)]))
+ while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)]) && draw_input)
insert(NULL, nextrune(-1) - cursor);
- while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)]))
+ while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)]) && draw_input)
insert(NULL, nextrune(-1) - cursor);
break;
case XK_y: /* paste selection */
@@ -424,23 +429,23 @@ keypress(XKeyEvent *ev)
switch(ksym) {
default:
insert:
- if (!iscntrl((unsigned char)*buf))
+ if (!iscntrl((unsigned char)*buf) && draw_input)
insert(buf, len);
break;
case XK_Delete:
case XK_KP_Delete:
- if (text[cursor] == '\0')
+ if (text[cursor] == '\0' || !draw_input)
return;
cursor = nextrune(+1);
/* fallthrough */
case XK_BackSpace:
- if (cursor == 0)
+ if (cursor == 0 || !draw_input)
return;
insert(NULL, nextrune(-1) - cursor);
break;
case XK_End:
case XK_KP_End:
- if (text[cursor] != '\0') {
+ if (text[cursor] != '\0' && draw_input) {
cursor = strlen(text);
break;
}
@@ -524,11 +529,11 @@ insert:
}
break;
case XK_Tab:
- if (!sel)
+ if (!sel || !draw_input)
return;
- strncpy(text, sel->text, sizeof text - 1);
- text[sizeof text - 1] = '\0';
- cursor = strlen(text);
+ cursor = strnlen(sel->text, sizeof text - 1);
+ memcpy(text, sel->text, cursor);
+ text[cursor] = '\0';
match();
break;
}
@@ -558,18 +563,18 @@ paste(void)
static void
readstdin(void)
{
- char buf[sizeof text], *p;
- size_t i, size = 0;
+ char *line = NULL;
+ size_t i, junk, size = 0;
+ ssize_t len;
/* read each line from stdin and add it to the item list */
- for (i = 0; fgets(buf, sizeof buf, stdin); i++) {
+ for (i = 0; (len = getline(&line, &junk, stdin)) != -1; i++, line = NULL) {
if (i + 1 >= size / sizeof *items)
if (!(items = realloc(items, (size += BUFSIZ))))
die("cannot realloc %zu bytes:", size);
- if ((p = strchr(buf, '\n')))
- *p = '\0';
- if (!(items[i].text = strdup(buf)))
- die("cannot strdup %zu bytes:", strlen(buf) + 1);
+ if (line[len - 1] == '\n')
+ line[len - 1] = '\0';
+ items[i].text = line;
items[i].out = 0;
}
if (items)
@@ -668,9 +673,16 @@ setup(void)
if (INTERSECT(x, y, 1, 1, info[i]) != 0)
break;
- mw = MIN(MAX(max_textw() + promptw, 100), info[i].width);
- x = info[i].x_org + ((info[i].width - mw) / 2);
- y = info[i].y_org + ((info[i].height - mh) / 2);
+ 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
@@ -678,11 +690,19 @@ setup(void)
if (!XGetWindowAttributes(dpy, parentwin, &wa))
die("could not get embedding window attributes: 0x%lx",
parentwin);
- mw = MIN(MAX(max_textw() + promptw, 100), wa.width);
- x = (wa.width - mw) / 2;
- y = (wa.height - mh) / 2;
+
+ if (centered) {
+ mw = MIN(MAX(max_textw() + promptw, min_width), wa.width);
+ x = (wa.width - mw) / 2;
+ y = (wa.height - mh) / 2;
+ } else {
+ x = 0;
+ y = topbar ? 0 : wa.height - mh;
+ mw = wa.width;
+ }
}
- inputw = mw / 3; /* input width: ~33% of monitor width */
+ promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
+ inputw = !draw_input ? 0 : mw / 3; /* input width: ~33% of monitor width */
match();
/* create menu window */
@@ -692,7 +712,8 @@ setup(void)
win = XCreateWindow(dpy, parentwin, x, y, mw, mh, border_width,
CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
- XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel);
+ if (border_width)
+ XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel);
XSetClassHint(dpy, win, &ch);
@@ -720,9 +741,8 @@ 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);
- exit(1);
+ die("usage: dmenu [-bfiv] [-noi] [-l lines] [-p prompt] [-fn font] [-m monitor]\n"
+ " [-nb color] [-nf color] [-sb color] [-sf color] [-w windowid]");
}
int
@@ -740,6 +760,8 @@ 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], "-noi")) /* no input field. intended to be used with a prompt */
+ draw_input = 0;
else if (!strcmp(argv[i], "-i")) { /* case-insensitive item matching */
fstrncmp = strncasecmp;
fstrstr = cistrstr;
@@ -764,6 +786,8 @@ main(int argc, char *argv[])
colors[SchemeSel][ColFg] = argv[++i];
else if (!strcmp(argv[i], "-w")) /* embedding window id */
embed = argv[++i];
+ else if (!strcmp(argv[i], "-bw"))
+ border_width = atoi(argv[++i]); /* border width */
else
usage();
diff --git a/drw.c b/drw.c
index ced7d37..a58a2b4 100644
--- a/drw.c
+++ b/drw.c
@@ -133,19 +133,6 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern)
die("no font specified.");
}
- /* Do not allow using color fonts. This is a workaround for a BadLength
- * error from Xft with color glyphs. Modelled on the Xterm workaround. See
- * https://bugzilla.redhat.com/show_bug.cgi?id=1498269
- * https://lists.suckless.org/dev/1701/30932.html
- * https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=916349
- * and lots more all over the internet.
- */
- FcBool iscol;
- if(FcPatternGetBool(xfont->pattern, FC_COLOR, 0, &iscol) == FcResultMatch && iscol) {
- XftFontClose(drw->dpy, xfont);
- return NULL;
- }
-
font = ecalloc(1, sizeof(Fnt));
font->xfont = xfont;
font->pattern = pattern;
@@ -368,7 +355,6 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp
fcpattern = FcPatternDuplicate(drw->fonts->pattern);
FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset);
FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue);
- FcPatternAddBool(fcpattern, FC_COLOR, FcFalse);
FcConfigSubstitute(NULL, fcpattern, FcMatchPattern);
FcDefaultSubstitute(fcpattern);
diff --git a/util.c b/util.c
index fe044fc..96b82c9 100644
--- a/util.c
+++ b/util.c
@@ -6,18 +6,9 @@
#include "util.h"
-void *
-ecalloc(size_t nmemb, size_t size)
-{
- void *p;
-
- if (!(p = calloc(nmemb, size)))
- die("calloc:");
- return p;
-}
-
void
-die(const char *fmt, ...) {
+die(const char *fmt, ...)
+{
va_list ap;
va_start(ap, fmt);
@@ -33,3 +24,13 @@ die(const char *fmt, ...) {
exit(1);
}
+
+void *
+ecalloc(size_t nmemb, size_t size)
+{
+ void *p;
+
+ if (!(p = calloc(nmemb, size)))
+ die("calloc:");
+ return p;
+}