@@ -3,7 +3,7 @@ | |||
include config.mk | |||
SRC = draw.c main.c util.c | |||
SRC = dmenu.c | |||
OBJ = ${SRC:.c=.o} | |||
all: options dmenu | |||
@@ -18,7 +18,7 @@ options: | |||
@echo CC $< | |||
@${CC} -c ${CFLAGS} $< | |||
${OBJ}: dmenu.h config.mk | |||
${OBJ}: config.h config.mk | |||
dmenu: ${OBJ} | |||
@echo CC -o $@ | |||
@@ -31,7 +31,7 @@ clean: | |||
dist: clean | |||
@echo creating dist tarball | |||
@mkdir -p dmenu-${VERSION} | |||
@cp -R LICENSE Makefile README config.mk dmenu.1 dmenu.h dmenu_path ${SRC} dmenu-${VERSION} | |||
@cp -R LICENSE Makefile README config.mk dmenu.1 config.h dmenu_path ${SRC} dmenu-${VERSION} | |||
@tar -cf dmenu-${VERSION}.tar dmenu-${VERSION} | |||
@gzip dmenu-${VERSION}.tar | |||
@rm -rf dmenu-${VERSION} | |||
@@ -0,0 +1,10 @@ | |||
/* See LICENSE file for copyright and license details. */ | |||
/* appearance */ | |||
#define FONT "-*-terminus-medium-r-*-*-12-*-*-*-*-*-iso10646-*" | |||
#define NORMBGCOLOR "#000" | |||
#define NORMFGCOLOR "#ccc" | |||
#define SELBGCOLOR "#00f" | |||
#define SELFGCOLOR "#fff" | |||
/* next macro defines the space between menu items */ | |||
#define SPACE 30 /* px */ |
@@ -1,16 +1,37 @@ | |||
/* See LICENSE file for copyright and license details. */ | |||
#include "dmenu.h" | |||
#include <ctype.h> | |||
#include <locale.h> | |||
#include <stdarg.h> | |||
#include <stdlib.h> | |||
#include <stdio.h> | |||
#include <string.h> | |||
#include <unistd.h> | |||
#include <X11/Xlib.h> | |||
#include <X11/Xutil.h> | |||
#include <X11/keysym.h> | |||
/* macros */ | |||
#define CLEANMASK(mask) (mask & ~(numlockmask | LockMask)) | |||
/* enums */ | |||
enum { ColFG, ColBG, ColLast }; | |||
/* typedefs */ | |||
typedef struct { | |||
int x, y, w, h; | |||
unsigned long norm[ColLast]; | |||
unsigned long sel[ColLast]; | |||
Drawable drawable; | |||
GC gc; | |||
struct { | |||
XFontStruct *xfont; | |||
XFontSet set; | |||
int ascent; | |||
int descent; | |||
int height; | |||
} font; | |||
} DC; /* draw context */ | |||
typedef struct Item Item; | |||
struct Item { | |||
Item *next; /* traverses all items */ | |||
@@ -18,8 +39,29 @@ struct Item { | |||
char *text; | |||
}; | |||
/* static */ | |||
/* forward declarations */ | |||
static void *emalloc(unsigned int size); | |||
static void eprint(const char *errstr, ...); | |||
static char *estrdup(const char *str); | |||
static void drawtext(const char *text, unsigned long col[ColLast]); | |||
static unsigned int textw(const char *text); | |||
static unsigned int textnw(const char *text, unsigned int len); | |||
static void calcoffsets(void); | |||
static void drawmenu(void); | |||
static Bool grabkeyboard(void); | |||
static unsigned long getcolor(const char *colstr); | |||
static void initfont(const char *fontstr); | |||
static int strido(const char *text, const char *pattern); | |||
static void match(char *pattern); | |||
static void kpress(XKeyEvent * e); | |||
static char *readstdin(void); | |||
static void usage(void); | |||
/* variables */ | |||
static int screen; | |||
static Display *dpy; | |||
static DC dc = {0}; | |||
static char text[4096]; | |||
static char *prompt = NULL; | |||
static int mw, mh; | |||
@@ -38,6 +80,93 @@ static Item *curr = NULL; | |||
static Window root; | |||
static Window win; | |||
#include "config.h" | |||
static void * | |||
emalloc(unsigned int size) { | |||
void *res = malloc(size); | |||
if(!res) | |||
eprint("fatal: could not malloc() %u bytes\n", size); | |||
return res; | |||
} | |||
static void | |||
eprint(const char *errstr, ...) { | |||
va_list ap; | |||
va_start(ap, errstr); | |||
vfprintf(stderr, errstr, ap); | |||
va_end(ap); | |||
exit(EXIT_FAILURE); | |||
} | |||
static char * | |||
estrdup(const char *str) { | |||
void *res = strdup(str); | |||
if(!res) | |||
eprint("fatal: could not malloc() %u bytes\n", strlen(str)); | |||
return res; | |||
} | |||
static void | |||
drawtext(const char *text, unsigned long col[ColLast]) { | |||
int x, y, w, h; | |||
static char buf[256]; | |||
unsigned int len, olen; | |||
XRectangle r = { dc.x, dc.y, dc.w, dc.h }; | |||
XSetForeground(dpy, dc.gc, col[ColBG]); | |||
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); | |||
if(!text) | |||
return; | |||
w = 0; | |||
olen = len = strlen(text); | |||
if(len >= sizeof buf) | |||
len = sizeof buf - 1; | |||
memcpy(buf, text, len); | |||
buf[len] = 0; | |||
h = dc.font.ascent + dc.font.descent; | |||
y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; | |||
x = dc.x + (h / 2); | |||
/* shorten text if necessary */ | |||
while(len && (w = textnw(buf, len)) > dc.w - h) | |||
buf[--len] = 0; | |||
if(len < olen) { | |||
if(len > 1) | |||
buf[len - 1] = '.'; | |||
if(len > 2) | |||
buf[len - 2] = '.'; | |||
if(len > 3) | |||
buf[len - 3] = '.'; | |||
} | |||
if(w > dc.w) | |||
return; /* too long */ | |||
XSetForeground(dpy, dc.gc, col[ColFG]); | |||
if(dc.font.set) | |||
XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); | |||
else | |||
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); | |||
} | |||
static unsigned int | |||
textw(const char *text) { | |||
return textnw(text, strlen(text)) + dc.font.height; | |||
} | |||
static unsigned int | |||
textnw(const char *text, unsigned int len) { | |||
XRectangle r; | |||
if(dc.font.set) { | |||
XmbTextExtents(dc.font.set, text, len, NULL, &r); | |||
return r.width; | |||
} | |||
return XTextWidth(dc.font.xfont, text, len); | |||
} | |||
static void | |||
calcoffsets(void) { | |||
unsigned int tw, w; | |||
@@ -119,7 +248,7 @@ grabkeyboard(void) { | |||
} | |||
static unsigned long | |||
initcolor(const char *colstr) { | |||
getcolor(const char *colstr) { | |||
Colormap cmap = DefaultColormap(dpy, screen); | |||
XColor color; | |||
@@ -435,12 +564,6 @@ usage(void) { | |||
" [-p <prompt>] [-sb <color>] [-sf <color>] [-v]\n"); | |||
} | |||
/* extern */ | |||
int screen; | |||
Display *dpy; | |||
DC dc = {0}; | |||
int | |||
main(int argc, char *argv[]) { | |||
Bool bottom = False; | |||
@@ -508,10 +631,10 @@ main(int argc, char *argv[]) { | |||
} | |||
XFreeModifiermap(modmap); | |||
/* style */ | |||
dc.norm[ColBG] = initcolor(normbg); | |||
dc.norm[ColFG] = initcolor(normfg); | |||
dc.sel[ColBG] = initcolor(selbg); | |||
dc.sel[ColFG] = initcolor(selfg); | |||
dc.norm[ColBG] = getcolor(normbg); | |||
dc.norm[ColFG] = getcolor(normfg); | |||
dc.sel[ColBG] = getcolor(selbg); | |||
dc.sel[ColFG] = getcolor(selfg); | |||
initfont(font); | |||
/* menu window */ | |||
wa.override_redirect = 1; |
@@ -1,41 +0,0 @@ | |||
/* See LICENSE file for copyright and license details. */ | |||
#include <X11/Xlib.h> | |||
#define FONT "-*-fixed-medium-r-normal-*-13-*-*-*-*-*-*-*" | |||
#define NORMBGCOLOR "#eeeeee" | |||
#define NORMFGCOLOR "#222222" | |||
#define SELBGCOLOR "#006699" | |||
#define SELFGCOLOR "#ffffff" | |||
#define SPACE 30 /* px */ | |||
/* color */ | |||
enum { ColFG, ColBG, ColLast }; | |||
typedef struct { | |||
int x, y, w, h; | |||
unsigned long norm[ColLast]; | |||
unsigned long sel[ColLast]; | |||
Drawable drawable; | |||
GC gc; | |||
struct { | |||
XFontStruct *xfont; | |||
XFontSet set; | |||
int ascent; | |||
int descent; | |||
int height; | |||
} font; | |||
} DC; /* draw context */ | |||
extern int screen; | |||
extern Display *dpy; | |||
extern DC dc; /* global drawing context */ | |||
/* draw.c */ | |||
void drawtext(const char *text, unsigned long col[ColLast]); | |||
unsigned int textw(const char *text); | |||
unsigned int textnw(const char *text, unsigned int len); | |||
/* util.c */ | |||
void *emalloc(unsigned int size); /* allocates memory, exits on error */ | |||
void eprint(const char *errstr, ...); /* prints errstr and exits with 1 */ | |||
char *estrdup(const char *str); /* duplicates str, exits on allocation error */ |
@@ -1,61 +0,0 @@ | |||
/* See LICENSE file for copyright and license details. */ | |||
#include "dmenu.h" | |||
#include <string.h> | |||
/* extern */ | |||
void | |||
drawtext(const char *text, unsigned long col[ColLast]) { | |||
int x, y, w, h; | |||
static char buf[256]; | |||
unsigned int len, olen; | |||
XRectangle r = { dc.x, dc.y, dc.w, dc.h }; | |||
XSetForeground(dpy, dc.gc, col[ColBG]); | |||
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); | |||
if(!text) | |||
return; | |||
w = 0; | |||
olen = len = strlen(text); | |||
if(len >= sizeof buf) | |||
len = sizeof buf - 1; | |||
memcpy(buf, text, len); | |||
buf[len] = 0; | |||
h = dc.font.ascent + dc.font.descent; | |||
y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent; | |||
x = dc.x + (h / 2); | |||
/* shorten text if necessary */ | |||
while(len && (w = textnw(buf, len)) > dc.w - h) | |||
buf[--len] = 0; | |||
if(len < olen) { | |||
if(len > 1) | |||
buf[len - 1] = '.'; | |||
if(len > 2) | |||
buf[len - 2] = '.'; | |||
if(len > 3) | |||
buf[len - 3] = '.'; | |||
} | |||
if(w > dc.w) | |||
return; /* too long */ | |||
XSetForeground(dpy, dc.gc, col[ColFG]); | |||
if(dc.font.set) | |||
XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len); | |||
else | |||
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len); | |||
} | |||
unsigned int | |||
textw(const char *text) { | |||
return textnw(text, strlen(text)) + dc.font.height; | |||
} | |||
unsigned int | |||
textnw(const char *text, unsigned int len) { | |||
XRectangle r; | |||
if(dc.font.set) { | |||
XmbTextExtents(dc.font.set, text, len, NULL, &r); | |||
return r.width; | |||
} | |||
return XTextWidth(dc.font.xfont, text, len); | |||
} |
@@ -1,34 +0,0 @@ | |||
/* See LICENSE file for copyright and license details. */ | |||
#include "dmenu.h" | |||
#include <stdarg.h> | |||
#include <stdio.h> | |||
#include <stdlib.h> | |||
#include <string.h> | |||
void * | |||
emalloc(unsigned int size) { | |||
void *res = malloc(size); | |||
if(!res) | |||
eprint("fatal: could not malloc() %u bytes\n", size); | |||
return res; | |||
} | |||
void | |||
eprint(const char *errstr, ...) { | |||
va_list ap; | |||
va_start(ap, errstr); | |||
vfprintf(stderr, errstr, ap); | |||
va_end(ap); | |||
exit(EXIT_FAILURE); | |||
} | |||
char * | |||
estrdup(const char *str) { | |||
void *res = strdup(str); | |||
if(!res) | |||
eprint("fatal: could not malloc() %u bytes\n", strlen(str)); | |||
return res; | |||
} |