about summary refs log tree commit diff
path: root/dmenu.c
diff options
context:
space:
mode:
authorAnselm R. Garbe <garbeam@gmail.com>2007-09-17 20:53:14 +0200
committerAnselm R. Garbe <garbeam@gmail.com>2007-09-17 20:53:14 +0200
commitd094ebea968e3d08b985a754aa9df30f56f649c6 (patch)
treeae96ac05dd9ef52067351843232021469a190aea /dmenu.c
parentnext version is 3.3 (diff)
downloaddmenu-d094ebea968e3d08b985a754aa9df30f56f649c6.tar.gz
dmenu-d094ebea968e3d08b985a754aa9df30f56f649c6.tar.bz2
dmenu-d094ebea968e3d08b985a754aa9df30f56f649c6.zip
reorganized
Diffstat (limited to 'dmenu.c')
-rw-r--r--dmenu.c587
1 files changed, 299 insertions, 288 deletions
diff --git a/dmenu.c b/dmenu.c
index b684175..34df9ed 100644
--- a/dmenu.c
+++ b/dmenu.c
@@ -40,134 +40,55 @@ struct Item {
 };
 
 /* 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;
-static int ret = 0;
-static int nitem = 0;
-static unsigned int cmdw = 0;
-static unsigned int promptw = 0;
-static unsigned int numlockmask = 0;
-static Bool running = True;
-static Item *allitems = NULL;	/* first of all items */
-static Item *item = NULL;	/* first of pattern matching items */
-static Item *sel = NULL;
-static Item *next = NULL;
-static Item *prev = NULL;
-static Item *curr = NULL;
-static Window root;
-static Window win;
+void calcoffsets(void);
+void cleanup(void);
+void drawmenu(void);
+void drawtext(const char *text, unsigned long col[ColLast]);
+void *emalloc(unsigned int size);
+void eprint(const char *errstr, ...);
+char *estrdup(const char *str);
+unsigned long getcolor(const char *colstr);
+Bool grabkeyboard(void);
+void initfont(const char *fontstr);
+void kpress(XKeyEvent * e);
+void match(char *pattern);
+void readstdin(void);
+void run(void);
+void setup(Bool bottom);
+int strido(const char *text, const char *pattern);
+unsigned int textnw(const char *text, unsigned int len);
+unsigned int textw(const char *text);
 
 #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
+/* variables */
+char *font = FONT;
+char *maxname = NULL;
+char *normbg = NORMBGCOLOR;
+char *normfg = NORMFGCOLOR;
+char *prompt = NULL;
+char *selbg = SELBGCOLOR;
+char *selfg = SELFGCOLOR;
+char text[4096];
+int screen;
+int ret = 0;
+unsigned int cmdw = 0;
+unsigned int mw, mh;
+unsigned int promptw = 0;
+unsigned int nitem = 0;
+unsigned int numlockmask = 0;
+Bool running = True;
+Display *dpy;
+DC dc = {0};
+Item *allitems = NULL;	/* first of all items */
+Item *item = NULL;	/* first of pattern matching items */
+Item *sel = NULL;
+Item *next = NULL;
+Item *prev = NULL;
+Item *curr = NULL;
+Window root, win;
+
+void
 calcoffsets(void) {
 	unsigned int tw, w;
 
@@ -193,7 +114,27 @@ calcoffsets(void) {
 	}
 }
 
-static void
+void
+cleanup(void) {
+	Item *itm;
+
+	while(allitems) {
+		itm = allitems->next;
+		free(allitems->text);
+		free(allitems);
+		allitems = itm;
+	}
+	if(dc.font.set)
+		XFreeFontSet(dpy, dc.font.set);
+	else
+		XFreeFont(dpy, dc.font.xfont);
+	XFreePixmap(dpy, dc.drawable);
+	XFreeGC(dpy, dc.gc);
+	XDestroyWindow(dpy, win);
+	XUngrabKeyboard(dpy, CurrentTime);
+}
+
+void
 drawmenu(void) {
 	Item *i;
 
@@ -234,20 +175,75 @@ drawmenu(void) {
 	XFlush(dpy);
 }
 
-static Bool
-grabkeyboard(void) {
-	unsigned int len;
+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 };
 
-	for(len = 1000; len; len--) {
-		if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
-			== GrabSuccess)
-			break;
-		usleep(1000);
+	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] = '.';
 	}
-	return len > 0;
+	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);
+}
+
+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;
 }
 
-static unsigned long
+unsigned long
 getcolor(const char *colstr) {
 	Colormap cmap = DefaultColormap(dpy, screen);
 	XColor color;
@@ -257,7 +253,20 @@ getcolor(const char *colstr) {
 	return color.pixel;
 }
 
-static void
+Bool
+grabkeyboard(void) {
+	unsigned int len;
+
+	for(len = 1000; len; len--) {
+		if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
+			== GrabSuccess)
+			break;
+		usleep(1000);
+	}
+	return len > 0;
+}
+
+void
 initfont(const char *fontstr) {
 	char *def, **missing;
 	int i, n;
@@ -299,65 +308,7 @@ initfont(const char *fontstr) {
 	dc.font.height = dc.font.ascent + dc.font.descent;
 }
 
-static int
-strido(const char *text, const char *pattern) {
-	for(; *text && *pattern; text++)
-		if (*text == *pattern)
-			pattern++;
-	return !*pattern;
-}                                  
-
-static void
-match(char *pattern) {
-	unsigned int plen;
-	Item *i, *j;
-
-	if(!pattern)
-		return;
-	plen = strlen(pattern);
-	item = j = NULL;
-	nitem = 0;
-	for(i = allitems; i; i=i->next)
-		if(!plen || !strncmp(pattern, i->text, plen)) {
-			if(!j)
-				item = i;
-			else
-				j->right = i;
-			i->left = j;
-			i->right = NULL;
-			j = i;
-			nitem++;
-		}
-	for(i = allitems; i; i=i->next)
-		if(plen && strncmp(pattern, i->text, plen)
-				&& strstr(i->text, pattern)) {
-			if(!j)                               
-				item = i;                              
-			else                                     
-				j->right = i;                          
-			i->left = j;      
-			i->right = NULL;                         
-			j = i;                                      
-			nitem++;                                       
-		}                                              
-	for(i = allitems; i; i=i->next)                            
-		if(plen && strncmp(pattern, i->text, plen)             
-				&& !strstr(i->text, pattern)          
-				&& strido(i->text,pattern)) { 
-			if(!j)
-				item = i;
-			else
-				j->right = i;
-			i->left = j;
-			i->right = NULL;
-			j = i;
-			nitem++;
-		}
-	curr = prev = next = sel = item;
-	calcoffsets();
-}
-
-static void
+void
 kpress(XKeyEvent * e) {
 	char buf[32];
 	int i, num;
@@ -528,9 +479,58 @@ kpress(XKeyEvent * e) {
 	drawmenu();
 }
 
-static char *
+void
+match(char *pattern) {
+	unsigned int plen;
+	Item *i, *j;
+
+	if(!pattern)
+		return;
+	plen = strlen(pattern);
+	item = j = NULL;
+	nitem = 0;
+	for(i = allitems; i; i=i->next)
+		if(!plen || !strncmp(pattern, i->text, plen)) {
+			if(!j)
+				item = i;
+			else
+				j->right = i;
+			i->left = j;
+			i->right = NULL;
+			j = i;
+			nitem++;
+		}
+	for(i = allitems; i; i=i->next)
+		if(plen && strncmp(pattern, i->text, plen)
+				&& strstr(i->text, pattern)) {
+			if(!j)                               
+				item = i;                              
+			else                                     
+				j->right = i;                          
+			i->left = j;      
+			i->right = NULL;                         
+			j = i;                                      
+			nitem++;                                       
+		}                                              
+	for(i = allitems; i; i=i->next)                            
+		if(plen && strncmp(pattern, i->text, plen)             
+				&& !strstr(i->text, pattern)          
+				&& strido(i->text,pattern)) { 
+			if(!j)
+				item = i;
+			else
+				j->right = i;
+			i->left = j;
+			i->right = NULL;
+			j = i;
+			nitem++;
+		}
+	curr = prev = next = sel = item;
+	calcoffsets();
+}
+
+void
 readstdin(void) {
-	static char *maxname = NULL;
 	char *p, buf[1024];
 	unsigned int len = 0, max = 0;
 	Item *i, *new;
@@ -554,88 +554,50 @@ readstdin(void) {
 			i->next = new;
 		i = new;
 	}
-
-	return maxname;
 }
 
-static void
-usage(void) {
-	eprint("usage: dmenu [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n"
-		"             [-p <prompt>] [-sb <color>] [-sf <color>] [-v]\n");
+void
+run(void) {
+	XEvent ev;
+
+	/* main event loop */
+	while(running && !XNextEvent(dpy, &ev))
+		switch (ev.type) {
+		default:	/* ignore all crap */
+			break;
+		case KeyPress:
+			kpress(&ev.xkey);
+			break;
+		case Expose:
+			if(ev.xexpose.count == 0)
+				drawmenu();
+			break;
+		}
 }
 
-int
-main(int argc, char *argv[]) {
-	Bool bottom = False;
-	char *font = FONT;
-	char *maxname;
-	char *normbg = NORMBGCOLOR;
-	char *normfg = NORMFGCOLOR;
-	char *selbg = SELBGCOLOR;
-	char *selfg = SELFGCOLOR;
-	int i, j;
-	Item *itm;
-	XEvent ev;
+void
+setup(Bool bottom) {
+	unsigned int i, j;
 	XModifierKeymap *modmap;
 	XSetWindowAttributes wa;
 
-	/* command line args */
-	for(i = 1; i < argc; i++)
-		if(!strcmp(argv[i], "-b")) {
-			bottom = True;
-		}
-		else if(!strcmp(argv[i], "-fn")) {
-			if(++i < argc) font = argv[i];
-		}
-		else if(!strcmp(argv[i], "-nb")) {
-			if(++i < argc) normbg = argv[i];
-		}
-		else if(!strcmp(argv[i], "-nf")) {
-			if(++i < argc) normfg = argv[i];
-		}
-		else if(!strcmp(argv[i], "-p")) {
-			if(++i < argc) prompt = argv[i];
-		}
-		else if(!strcmp(argv[i], "-sb")) {
-			if(++i < argc) selbg = argv[i];
-		}
-		else if(!strcmp(argv[i], "-sf")) {
-			if(++i < argc) selfg = argv[i];
-		}
-		else if(!strcmp(argv[i], "-v"))
-			eprint("dmenu-"VERSION", © 2006-2007 Anselm R. Garbe, Sander van Dijk\n");
-		else
-			usage();
-	setlocale(LC_CTYPE, "");
-	dpy = XOpenDisplay(0);
-	if(!dpy)
-		eprint("dmenu: cannot open display\n");
-	screen = DefaultScreen(dpy);
-	root = RootWindow(dpy, screen);
-	if(isatty(STDIN_FILENO)) {
-		maxname = readstdin();
-		running = grabkeyboard();
-	}
-	else { /* prevent keypress loss */
-		running = grabkeyboard();
-		maxname = readstdin();
-	}
 	/* init modifier map */
 	modmap = XGetModifierMapping(dpy);
-	for (i = 0; i < 8; i++) {
-		for (j = 0; j < modmap->max_keypermod; j++) {
+	for(i = 0; i < 8; i++)
+		for(j = 0; j < modmap->max_keypermod; j++) {
 			if(modmap->modifiermap[i * modmap->max_keypermod + j]
 			== XKeysymToKeycode(dpy, XK_Num_Lock))
 				numlockmask = (1 << i);
 		}
-	}
 	XFreeModifiermap(modmap);
+
 	/* style */
 	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;
 	wa.background_pixmap = ParentRelative;
@@ -647,6 +609,7 @@ main(int argc, char *argv[]) {
 			DefaultDepth(dpy, screen), CopyFromParent,
 			DefaultVisual(dpy, screen),
 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
+
 	/* pixmap */
 	dc.drawable = XCreatePixmap(dpy, root, mw, mh, DefaultDepth(dpy, screen));
 	dc.gc = XCreateGC(dpy, root, 0, 0);
@@ -664,38 +627,86 @@ main(int argc, char *argv[]) {
 	text[0] = 0;
 	match(text);
 	XMapRaised(dpy, win);
-	drawmenu();
-	XSync(dpy, False);
+}
 
-	/* main event loop */
-	while(running && !XNextEvent(dpy, &ev))
-		switch (ev.type) {
-		default:	/* ignore all crap */
-			break;
-		case KeyPress:
-			kpress(&ev.xkey);
-			break;
-		case Expose:
-			if(ev.xexpose.count == 0)
-				drawmenu();
-			break;
+int
+strido(const char *text, const char *pattern) {
+	for(; *text && *pattern; text++)
+		if (*text == *pattern)
+			pattern++;
+	return !*pattern;
+}                                  
+
+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);
+}
+
+unsigned int
+textw(const char *text) {
+	return textnw(text, strlen(text)) + dc.font.height;
+}
+
+int
+main(int argc, char *argv[]) {
+	Bool bottom = False;
+	unsigned int i;
+
+	/* command line args */
+	for(i = 1; i < argc; i++)
+		if(!strcmp(argv[i], "-b")) {
+			bottom = True;
+		}
+		else if(!strcmp(argv[i], "-fn")) {
+			if(++i < argc) font = argv[i];
+		}
+		else if(!strcmp(argv[i], "-nb")) {
+			if(++i < argc) normbg = argv[i];
+		}
+		else if(!strcmp(argv[i], "-nf")) {
+			if(++i < argc) normfg = argv[i];
+		}
+		else if(!strcmp(argv[i], "-p")) {
+			if(++i < argc) prompt = argv[i];
+		}
+		else if(!strcmp(argv[i], "-sb")) {
+			if(++i < argc) selbg = argv[i];
+		}
+		else if(!strcmp(argv[i], "-sf")) {
+			if(++i < argc) selfg = argv[i];
 		}
+		else if(!strcmp(argv[i], "-v"))
+			eprint("dmenu-"VERSION", © 2006-2007 Anselm R. Garbe, Sander van Dijk\n");
+		else
+			eprint("usage: dmenu [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n"
+			"             [-p <prompt>] [-sb <color>] [-sf <color>] [-v]\n");
+	setlocale(LC_CTYPE, "");
+	dpy = XOpenDisplay(0);
+	if(!dpy)
+		eprint("dmenu: cannot open display\n");
+	screen = DefaultScreen(dpy);
+	root = RootWindow(dpy, screen);
 
-	/* cleanup */
-	while(allitems) {
-		itm = allitems->next;
-		free(allitems->text);
-		free(allitems);
-		allitems = itm;
+	if(isatty(STDIN_FILENO)) {
+		readstdin();
+		running = grabkeyboard();
 	}
-	if(dc.font.set)
-		XFreeFontSet(dpy, dc.font.set);
-	else
-		XFreeFont(dpy, dc.font.xfont);
-	XFreePixmap(dpy, dc.drawable);
-	XFreeGC(dpy, dc.gc);
-	XDestroyWindow(dpy, win);
-	XUngrabKeyboard(dpy, CurrentTime);
+	else { /* prevent keypress loss */
+		running = grabkeyboard();
+		readstdin();
+	}
+
+	setup(bottom);
+	drawmenu();
+	XSync(dpy, False);
+	run();
+	cleanup();
 	XCloseDisplay(dpy);
 	return ret;
 }