micromizing dmenu step 1
							parent
							
								
									b97783b07f
								
							
						
					
					
						commit
						06ae894434
					
				
							
								
								
									
										6
									
								
								Makefile
								
								
								
								
							
							
						
						
									
										6
									
								
								Makefile
								
								
								
								
							|  | @ -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 */ | ||||
							
								
								
									
										149
									
								
								main.c → dmenu.c
								
								
								
								
							
							
						
						
									
										149
									
								
								main.c → dmenu.c
								
								
								
								
							|  | @ -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; | ||||
							
								
								
									
										41
									
								
								dmenu.h
								
								
								
								
							
							
						
						
									
										41
									
								
								dmenu.h
								
								
								
								
							|  | @ -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 */ | ||||
							
								
								
									
										61
									
								
								draw.c
								
								
								
								
							
							
						
						
									
										61
									
								
								draw.c
								
								
								
								
							|  | @ -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); | ||||
| } | ||||
							
								
								
									
										34
									
								
								util.c
								
								
								
								
							
							
						
						
									
										34
									
								
								util.c
								
								
								
								
							|  | @ -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; | ||||
| } | ||||
		Loading…
	
		Reference in New Issue