4.9 update

This commit is contained in:
Luke Smith 2019-02-08 16:25:44 -05:00
parent e60466c0a1
commit 274d4f9a7b
No known key found for this signature in database
GPG key ID: 4C50B54A911F6252
7 changed files with 179 additions and 108 deletions

12
LICENSE
View file

@ -1,13 +1,15 @@
MIT/X Consortium License
© 2006-2014 Anselm R Garbe <anselm@garbe.us>
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
© 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>
© 2006-2008 Sander van Dijk <a dot h dot vandijk at gmail dot com>
© 2006-2007 Michał Janeczek <janeczek at gmail dot com>
© 2014-2015 Hiltjo Posthuma <hiltjo@codemadness.org>
© 2010-2012 Connor Lane Smith <cls@lubutu.com>
© 2014-2019 Hiltjo Posthuma <hiltjo@codemadness.org>
© 2015-2018 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"),

View file

@ -4,71 +4,61 @@
include config.mk
SRC = drw.c dmenu.c stest.c util.c
OBJ = ${SRC:.c=.o}
OBJ = $(SRC:.c=.o)
all: options dmenu stest
options:
@echo dmenu build options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
@echo "CFLAGS = $(CFLAGS)"
@echo "LDFLAGS = $(LDFLAGS)"
@echo "CC = $(CC)"
.c.o:
@echo CC $<
@${CC} -c ${CFLAGS} $<
$(CC) -c $(CFLAGS) $<
config.h:
@echo creating $@ from config.def.h
@cp config.def.h $@
cp config.def.h $@
${OBJ}: arg.h config.h config.mk drw.h
$(OBJ): arg.h config.h config.mk drw.h
dmenu: dmenu.o drw.o util.o
@echo CC -o $@
@${CC} -o $@ dmenu.o drw.o util.o ${LDFLAGS}
$(CC) -o $@ dmenu.o drw.o util.o $(LDFLAGS)
stest: stest.o
@echo CC -o $@
@${CC} -o $@ stest.o ${LDFLAGS}
$(CC) -o $@ stest.o $(LDFLAGS)
clean:
@echo cleaning
@rm -f dmenu stest ${OBJ} dmenu-${VERSION}.tar.gz
rm -f dmenu stest $(OBJ) dmenu-$(VERSION).tar.gz
dist: clean
@echo creating dist tarball
@mkdir -p dmenu-${VERSION}
@cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1 \
drw.h util.h dmenu_path dmenu_run stest.1 ${SRC} \
dmenu-${VERSION}
@tar -cf dmenu-${VERSION}.tar dmenu-${VERSION}
@gzip dmenu-${VERSION}.tar
@rm -rf dmenu-${VERSION}
mkdir -p dmenu-$(VERSION)
cp LICENSE Makefile README arg.h config.def.h config.mk dmenu.1\
drw.h util.h dmenu_path dmenu_run stest.1 $(SRC)\
dmenu-$(VERSION)
tar -cf dmenu-$(VERSION).tar dmenu-$(VERSION)
gzip dmenu-$(VERSION).tar
rm -rf dmenu-$(VERSION)
install: all
@echo installing executables to ${DESTDIR}${PREFIX}/bin
@mkdir -p ${DESTDIR}${PREFIX}/bin
@cp -f dmenu dmenu_path dmenu_run stest ${DESTDIR}${PREFIX}/bin
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu_path
@chmod 755 ${DESTDIR}${PREFIX}/bin/dmenu_run
@chmod 755 ${DESTDIR}${PREFIX}/bin/stest
@echo installing manual pages to ${DESTDIR}${MANPREFIX}/man1
@mkdir -p ${DESTDIR}${MANPREFIX}/man1
@sed "s/VERSION/${VERSION}/g" < dmenu.1 > ${DESTDIR}${MANPREFIX}/man1/dmenu.1
@sed "s/VERSION/${VERSION}/g" < stest.1 > ${DESTDIR}${MANPREFIX}/man1/stest.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/dmenu.1
@chmod 644 ${DESTDIR}${MANPREFIX}/man1/stest.1
mkdir -p $(DESTDIR)$(PREFIX)/bin
cp -f dmenu dmenu_path dmenu_run stest $(DESTDIR)$(PREFIX)/bin
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_path
chmod 755 $(DESTDIR)$(PREFIX)/bin/dmenu_run
chmod 755 $(DESTDIR)$(PREFIX)/bin/stest
mkdir -p $(DESTDIR)$(MANPREFIX)/man1
sed "s/VERSION/$(VERSION)/g" < dmenu.1 > $(DESTDIR)$(MANPREFIX)/man1/dmenu.1
sed "s/VERSION/$(VERSION)/g" < stest.1 > $(DESTDIR)$(MANPREFIX)/man1/stest.1
chmod 644 $(DESTDIR)$(MANPREFIX)/man1/dmenu.1
chmod 644 $(DESTDIR)$(MANPREFIX)/man1/stest.1
uninstall:
@echo removing executables from ${DESTDIR}${PREFIX}/bin
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu_path
@rm -f ${DESTDIR}${PREFIX}/bin/dmenu_run
@rm -f ${DESTDIR}${PREFIX}/bin/stest
@echo removing manual page from ${DESTDIR}${MANPREFIX}/man1
@rm -f ${DESTDIR}${MANPREFIX}/man1/dmenu.1
@rm -f ${DESTDIR}${MANPREFIX}/man1/stest.1
rm -f $(DESTDIR)$(PREFIX)/bin/dmenu\
$(DESTDIR)$(PREFIX)/bin/dmenu_path\
$(DESTDIR)$(PREFIX)/bin/dmenu_run\
$(DESTDIR)$(PREFIX)/bin/stest\
$(DESTDIR)$(MANPREFIX)/man1/dmenu.1\
$(DESTDIR)$(MANPREFIX)/man1/stest.1
.PHONY: all options clean dist install uninstall

View file

@ -1,9 +1,9 @@
# dmenu version
VERSION = 4.7
VERSION = 4.9
# paths
PREFIX = /usr/local
MANPREFIX = ${PREFIX}/share/man
MANPREFIX = $(PREFIX)/share/man
X11INC = /usr/X11R6/include
X11LIB = /usr/X11R6/lib
@ -16,16 +16,16 @@ XINERAMAFLAGS = -DXINERAMA
FREETYPELIBS = -lfontconfig -lXft
FREETYPEINC = /usr/include/freetype2
# OpenBSD (uncomment)
#FREETYPEINC = ${X11INC}/freetype2
#FREETYPEINC = $(X11INC)/freetype2
# includes and libs
INCS = -I${X11INC} -I${FREETYPEINC}
LIBS = -L${X11LIB} -lX11 ${XINERAMALIBS} ${FREETYPELIBS}
INCS = -I$(X11INC) -I$(FREETYPEINC)
LIBS = -L$(X11LIB) -lX11 $(XINERAMALIBS) $(FREETYPELIBS)
# 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}
LDFLAGS = -s ${LIBS}
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)
LDFLAGS = $(LIBS)
# compiler and linker
CC = cc

68
dmenu.1
View file

@ -41,8 +41,8 @@ which lists programs in the user's $PATH and runs the result in their $SHELL.
dmenu appears at the bottom of the screen.
.TP
.B \-f
dmenu grabs the keyboard before reading stdin. This is faster, but will lock up
X until stdin reaches end\-of\-file.
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.
@ -100,82 +100,94 @@ Confirm input. Prints the input text to stdout and exits, returning success.
.B Escape
Exit without selecting an item, returning failure.
.TP
C\-a
.B Ctrl-Left
Move cursor to the start of the current word
.TP
.B Ctrl-Right
Move cursor to the end of the current word
.TP
.B C\-a
Home
.TP
C\-b
.B C\-b
Left
.TP
C\-c
.B C\-c
Escape
.TP
C\-d
.B C\-d
Delete
.TP
C\-e
.B C\-e
End
.TP
C\-f
.B C\-f
Right
.TP
C\-g
.B C\-g
Escape
.TP
C\-h
.B C\-h
Backspace
.TP
C\-i
.B C\-i
Tab
.TP
C\-j
.B C\-j
Return
.TP
C\-J
.B C\-J
Shift-Return
.TP
C\-k
.B C\-k
Delete line right
.TP
C\-m
.B C\-m
Return
.TP
C\-M
.B C\-M
Shift-Return
.TP
C\-n
.B C\-n
Down
.TP
C\-p
.B C\-p
Up
.TP
C\-u
.B C\-u
Delete line left
.TP
C\-w
.B C\-w
Delete word left
.TP
C\-y
.B C\-y
Paste from primary X selection
.TP
C\-Y
.B C\-Y
Paste from X clipboard
.TP
M\-g
.B M\-b
Move cursor to the start of the current word
.TP
.B M\-f
Move cursor to the end of the current word
.TP
.B M\-g
Home
.TP
M\-G
.B M\-G
End
.TP
M\-h
.B M\-h
Up
.TP
M\-j
.B M\-j
Page down
.TP
M\-k
.B M\-k
Page up
.TP
M\-l
.B M\-l
Down
.SH SEE ALSO
.IR dwm (1),

87
dmenu.c
View file

@ -6,6 +6,7 @@
#include <string.h>
#include <strings.h>
#include <time.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
@ -144,7 +145,7 @@ drawmenu(void)
drw_setscheme(drw, scheme[SchemeNorm]);
drw_text(drw, x, 0, w, bh, lrpad / 2, text, 0);
drw_font_getexts(drw->fonts, text, cursor, &curpos, NULL);
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);
@ -287,18 +288,42 @@ nextrune(int inc)
return n;
}
static void
movewordedge(int dir)
{
if (dir < 0) { /* move cursor to the start of the word*/
while (cursor > 0 && strchr(worddelimiters, text[nextrune(-1)]))
cursor = nextrune(-1);
while (cursor > 0 && !strchr(worddelimiters, text[nextrune(-1)]))
cursor = nextrune(-1);
} else { /* move cursor to the end of the word */
while (text[cursor] && strchr(worddelimiters, text[cursor]))
cursor = nextrune(+1);
while (text[cursor] && !strchr(worddelimiters, text[cursor]))
cursor = nextrune(+1);
}
}
static void
keypress(XKeyEvent *ev)
{
char buf[32];
int len;
KeySym ksym = NoSymbol;
KeySym ksym;
Status status;
len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status);
if (status == XBufferOverflow)
switch (status) {
default: /* XLookupNone, XBufferOverflow */
return;
if (ev->state & ControlMask)
case XLookupChars:
goto insert;
case XLookupKeySym:
case XLookupBoth:
break;
}
if (ev->state & ControlMask) {
switch(ksym) {
case XK_a: ksym = XK_Home; break;
case XK_b: ksym = XK_Left; break;
@ -334,6 +359,12 @@ keypress(XKeyEvent *ev)
XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY,
utf8, utf8, win, CurrentTime);
return;
case XK_Left:
movewordedge(-1);
goto draw;
case XK_Right:
movewordedge(+1);
goto draw;
case XK_Return:
case XK_KP_Enter:
break;
@ -343,8 +374,14 @@ keypress(XKeyEvent *ev)
default:
return;
}
else if (ev->state & Mod1Mask)
} else if (ev->state & Mod1Mask) {
switch(ksym) {
case XK_b:
movewordedge(-1);
goto draw;
case XK_f:
movewordedge(+1);
goto draw;
case XK_g: ksym = XK_Home; break;
case XK_G: ksym = XK_End; break;
case XK_h: ksym = XK_Up; break;
@ -354,8 +391,11 @@ keypress(XKeyEvent *ev)
default:
return;
}
}
switch(ksym) {
default:
insert:
if (!iscntrl(*buf))
insert(buf, len);
break;
@ -455,6 +495,8 @@ keypress(XKeyEvent *ev)
match();
break;
}
draw:
drawmenu();
}
@ -467,10 +509,12 @@ paste(void)
Atom da;
/* we have been given the current selection, now insert it into input */
XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False,
utf8, &da, &di, &dl, &dl, (unsigned char **)&p);
insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p));
XFree(p);
if (XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False,
utf8, &da, &di, &dl, &dl, (unsigned char **)&p)
== Success && p) {
insert(p, (q = strchr(p, '\n')) ? q - p : (ssize_t)strlen(p));
XFree(p);
}
drawmenu();
}
@ -509,7 +553,7 @@ run(void)
XEvent ev;
while (!XNextEvent(dpy, &ev)) {
if (XFilterEvent(&ev, win))
if (XFilterEvent(&ev, None))
continue;
switch(ev.type) {
case Expose:
@ -539,22 +583,21 @@ run(void)
static void
setup(void)
{
int x, y, i = 0;
int x, y, i, j;
unsigned int du;
XSetWindowAttributes swa;
XIM xim;
Window w, dw, *dws;
XWindowAttributes wa;
XClassHint ch = {"dmenu", "dmenu"};
#ifdef XINERAMA
XineramaScreenInfo *info;
Window pw;
int a, j, di, n, area = 0;
int a, di, n, area = 0;
#endif
/* init appearance */
scheme[SchemeNorm] = drw_scm_create(drw, colors[SchemeNorm], 2);
scheme[SchemeSel] = drw_scm_create(drw, colors[SchemeSel], 2);
scheme[SchemeOut] = drw_scm_create(drw, colors[SchemeOut], 2);
for (j = 0; j < SchemeLast; j++)
scheme[j] = drw_scm_create(drw, colors[j], 2);
clip = XInternAtom(dpy, "CLIPBOARD", False);
utf8 = XInternAtom(dpy, "UTF8_STRING", False);
@ -564,6 +607,7 @@ setup(void)
lines = MAX(lines, 0);
mh = (lines + 1) * bh;
#ifdef XINERAMA
i = 0;
if (parentwin == root && (info = XineramaQueryScreens(dpy, &n))) {
XGetInputFocus(dpy, &w, &di);
if (mon >= 0 && mon < n)
@ -613,6 +657,7 @@ setup(void)
win = XCreateWindow(dpy, parentwin, x, y, mw, mh, 0,
CopyFromParent, CopyFromParent, CopyFromParent,
CWOverrideRedirect | CWBackPixel | CWEventMask, &swa);
XSetClassHint(dpy, win, &ch);
/* open input methods */
xim = XOpenIM(dpy, NULL, NULL, NULL);
@ -620,6 +665,7 @@ setup(void)
XNClientWindow, win, XNFocusWindow, win, NULL);
XMapRaised(dpy, win);
XSetInputFocus(dpy, win, RevertToParent, CurrentTime);
if (embed) {
XSelectInput(dpy, parentwin, FocusChangeMask);
if (XQueryTree(dpy, parentwin, &dw, &w, &dws, &du) && dws) {
@ -685,6 +731,8 @@ main(int argc, char *argv[])
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
fputs("warning: no locale support\n", stderr);
if (!XSetLocaleModifiers(""))
fputs("warning: no locale modifiers support\n", stderr);
if (!(dpy = XOpenDisplay(NULL)))
die("cannot open display");
screen = DefaultScreen(dpy);
@ -699,7 +747,12 @@ main(int argc, char *argv[])
die("no fonts could be loaded.");
lrpad = drw->fonts->h;
if (fast) {
#ifdef __OpenBSD__
if (pledge("stdio rpath", NULL) == -1)
die("pledge");
#endif
if (fast && !isatty(0)) {
grabkeyboard();
readstdin();
} else {

View file

@ -1,10 +1,10 @@
#!/bin/sh
cachedir=${XDG_CACHE_HOME:-"$HOME/.cache"}
if [ -d "$cachedir" ]; then
cache=$cachedir/dmenu_run
else
cache=$HOME/.dmenu_cache # if no xdg dir, fall back to dotfile in ~
fi
cachedir="${XDG_CACHE_HOME:-"$HOME/.cache"}"
cache="$cachedir/dmenu_run"
[ ! -e "$cachedir" ] && mkdir -p "$cachedir"
IFS=:
if stest -dqr -n "$cache" $PATH; then
stest -flx $PATH | sort -u | tee "$cache"

14
drw.c
View file

@ -132,6 +132,19 @@ 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;
@ -337,6 +350,7 @@ 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);