diff options
| author | arg@10ksloc.org <unknown> | 2006-08-04 10:23:36 +0200 | 
|---|---|---|
| committer | arg@10ksloc.org <unknown> | 2006-08-04 10:23:36 +0200 | 
| commit | 5077207088b08e6b21601cb19925d20e9d5af573 (patch) | |
| tree | 053bd64a2dc6a33526dbb249d18697fedd74a1ab | |
| parent | 7817523a685f0dbba2e074a448099558a54b1b9c (diff) | |
| download | dmenu-5077207088b08e6b21601cb19925d20e9d5af573.tar.gz | |
rearranged several stuff
| -rw-r--r-- | LICENSE | 1 | ||||
| -rw-r--r-- | config.mk | 2 | ||||
| -rw-r--r-- | dmenu.h | 29 | ||||
| -rw-r--r-- | draw.c | 184 | ||||
| -rw-r--r-- | main.c | 256 | ||||
| -rw-r--r-- | util.c | 18 | 
6 files changed, 220 insertions, 270 deletions
| @@ -1,6 +1,7 @@  MIT/X Consortium License  (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> +(C)opyright MMVI Sander van Dijk <a dot h dot vandijk at gmail dot com>  Permission is hereby granted, free of charge, to any person obtaining a  copy of this software and associated documentation files (the "Software"), @@ -1,4 +1,4 @@ -# dwm version +# dmenu version  VERSION = 0.0  # Customize below to fit your system @@ -7,6 +7,8 @@  #include <X11/Xlib.h>  #include <X11/Xlocale.h> +#define SPACE		30 /* px */ +  typedef struct Brush Brush;  typedef struct DC DC;  typedef struct Fnt Fnt; @@ -29,30 +31,17 @@ struct DC { /* draw context */  	GC gc;  }; -struct Brush { -	GC gc; -	Drawable drawable; -	int x, y, w, h; -	Fnt font; -	unsigned long bg; -	unsigned long fg; -	unsigned long border; -}; - - +extern int screen; +extern Display *dpy; +extern DC dc;  /* draw.c */ -extern void draw(Display *dpy, Brush *b, Bool border, const char *text); -extern void loadcolors(Display *dpy, int screen, Brush *b, -		const char *bg, const char *fg, const char *bo); -extern void loadfont(Display *dpy, Fnt *font, const char *fontstr); -extern unsigned int textnw(Fnt *font, char *text, unsigned int len); -extern unsigned int textw(Fnt *font, char *text); -extern unsigned int texth(Fnt *font); +extern void drawtext(const char *text, Bool invert, Bool border); +extern unsigned long getcolor(const char *colstr); +extern void setfont(const char *fontstr); +extern unsigned int textw(const char *text);  /* util.c */  extern void *emalloc(unsigned int size); -extern void *emallocz(unsigned int size);  extern void eprint(const char *errstr, ...);  extern char *estrdup(const char *str); -extern void swap(void **p1, void **p2); @@ -2,45 +2,62 @@   * (C)opyright MMIV-MMVI Anselm R. Garbe <garbeam at gmail dot com>   * See LICENSE file for license details.   */ - +#include "dmenu.h"  #include <stdio.h>  #include <string.h> +#include <X11/Xlocale.h> -#include "dmenu.h" +/* static */  static void -drawborder(Display *dpy, Brush *b) +drawborder(void)  {  	XPoint points[5]; -	XSetLineAttributes(dpy, b->gc, 1, LineSolid, CapButt, JoinMiter); -	XSetForeground(dpy, b->gc, b->border); -	points[0].x = b->x; -	points[0].y = b->y; -	points[1].x = b->w - 1; + +	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter); +	XSetForeground(dpy, dc.gc, dc.border); +	points[0].x = dc.x; +	points[0].y = dc.y; +	points[1].x = dc.w - 1;  	points[1].y = 0;  	points[2].x = 0; -	points[2].y = b->h - 1; -	points[3].x = -(b->w - 1); +	points[2].y = dc.h - 1; +	points[3].x = -(dc.w - 1);  	points[3].y = 0;  	points[4].x = 0; -	points[4].y = -(b->h - 1); -	XDrawLines(dpy, b->drawable, b->gc, points, 5, CoordModePrevious); +	points[4].y = -(dc.h - 1); +	XDrawLines(dpy, dc.drawable, dc.gc, points, 5, CoordModePrevious); +} + +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);  } +/* extern */ +  void -draw(Display *dpy, Brush *b, Bool border, const char *text) +drawtext(const char *text, Bool invert, Bool border)  { -	unsigned int x, y, w, h, len; +	int x, y, w, h;  	static char buf[256]; +	unsigned int len;  	XGCValues gcv; -	XRectangle r = { b->x, b->y, b->w, b->h }; +	XRectangle r = { dc.x, dc.y, dc.w, dc.h }; -	XSetForeground(dpy, b->gc, b->bg); -	XFillRectangles(dpy, b->drawable, b->gc, &r, 1); +	XSetForeground(dpy, dc.gc, invert ? dc.fg : dc.bg); +	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);  	w = 0;  	if(border) -		drawborder(dpy, b); +		drawborder();  	if(!text)  		return; @@ -51,121 +68,94 @@ draw(Display *dpy, Brush *b, Bool border, const char *text)  	memcpy(buf, text, len);  	buf[len] = 0; -	h = b->font.ascent + b->font.descent; -	y = b->y + (b->h / 2) - (h / 2) + b->font.ascent; -	x = b->x + (h / 2); +	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(&b->font, buf, len)) > b->w - h) +	while(len && (w = textnw(buf, len)) > dc.w - h)  		buf[--len] = 0; -	if(w > b->w) +	if(w > dc.w)  		return; /* too long */ -	gcv.foreground = b->fg; -	gcv.background = b->bg; -	if(b->font.set) { -		XChangeGC(dpy, b->gc, GCForeground | GCBackground, &gcv); -		XmbDrawImageString(dpy, b->drawable, b->font.set, b->gc, +	gcv.foreground = invert ? dc.bg : dc.fg; +	gcv.background = invert ? dc.fg : dc.bg; +	if(dc.font.set) { +		XChangeGC(dpy, dc.gc, GCForeground | GCBackground, &gcv); +		XmbDrawImageString(dpy, dc.drawable, dc.font.set, dc.gc,  				x, y, buf, len);  	}  	else { -		gcv.font = b->font.xfont->fid; -		XChangeGC(dpy, b->gc, GCForeground | GCBackground | GCFont, &gcv); -		XDrawImageString(dpy, b->drawable, b->gc, x, y, buf, len); +		gcv.font = dc.font.xfont->fid; +		XChangeGC(dpy, dc.gc, GCForeground | GCBackground | GCFont, &gcv); +		XDrawImageString(dpy, dc.drawable, dc.gc, x, y, buf, len);  	}  } -static unsigned long -xloadcolors(Display *dpy, Colormap cmap, const char *colstr) +unsigned long +getcolor(const char *colstr)  { +	Colormap cmap = DefaultColormap(dpy, screen);  	XColor color; +  	XAllocNamedColor(dpy, cmap, colstr, &color, &color);  	return color.pixel;  }  void -loadcolors(Display *dpy, int screen, Brush *b, -		const char *bg, const char *fg, const char *border) -{ -	Colormap cmap = DefaultColormap(dpy, screen); -	b->bg = xloadcolors(dpy, cmap, bg); -	b->fg = xloadcolors(dpy, cmap, fg); -	b->border = xloadcolors(dpy, cmap, border); -} - -unsigned int -textnw(Fnt *font, char *text, unsigned int len) -{ -	XRectangle r; -	if(font->set) { -		XmbTextExtents(font->set, text, len, NULL, &r); -		return r.width; -	} -	return XTextWidth(font->xfont, text, len); -} - -unsigned int -textw(Fnt *font, char *text) -{ -	return textnw(font, text, strlen(text)); -} - -unsigned int -texth(Fnt *font) -{ -	return font->height + 4; -} - -void -loadfont(Display *dpy, Fnt *font, const char *fontstr) +setfont(const char *fontstr)  {  	char **missing, *def; -	int n; +	int i, n;  	missing = NULL; -	def = "?";  	setlocale(LC_ALL, ""); -	if(font->set) -		XFreeFontSet(dpy, font->set); -	font->set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); +	if(dc.font.set) +		XFreeFontSet(dpy, dc.font.set); +	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);  	if(missing) {  		while(n--)  			fprintf(stderr, "missing fontset: %s\n", missing[n]);  		XFreeStringList(missing); -		if(font->set) { -			XFreeFontSet(dpy, font->set); -			font->set = NULL; +		if(dc.font.set) { +			XFreeFontSet(dpy, dc.font.set); +			dc.font.set = NULL;  		}  	} -	if(font->set) { +	if(dc.font.set) {  		XFontSetExtents *font_extents;  		XFontStruct **xfonts;  		char **font_names; -		unsigned int i; - -		font->ascent = font->descent = 0; -		font_extents = XExtentsOfFontSet(font->set); -		n = XFontsOfFontSet(font->set, &xfonts, &font_names); -		for(i = 0, font->ascent = 0, font->descent = 0; i < n; i++) { -			if(font->ascent < (*xfonts)->ascent) -				font->ascent = (*xfonts)->ascent; -			if(font->descent < (*xfonts)->descent) -				font->descent = (*xfonts)->descent; + +		dc.font.ascent = dc.font.descent = 0; +		font_extents = XExtentsOfFontSet(dc.font.set); +		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); +		for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { +			if(dc.font.ascent < (*xfonts)->ascent) +				dc.font.ascent = (*xfonts)->ascent; +			if(dc.font.descent < (*xfonts)->descent) +				dc.font.descent = (*xfonts)->descent;  			xfonts++;  		}  	}  	else { -		if(font->xfont) -			XFreeFont(dpy, font->xfont); -		font->xfont = NULL; -		font->xfont = XLoadQueryFont(dpy, fontstr); -		if (!font->xfont) -			font->xfont = XLoadQueryFont(dpy, "fixed"); -		if (!font->xfont) -			eprint("error, cannot load 'fixed' font\n"); -		font->ascent = font->xfont->ascent; -		font->descent = font->xfont->descent; +		if(dc.font.xfont) +			XFreeFont(dpy, dc.font.xfont); +		dc.font.xfont = NULL; +		dc.font.xfont = XLoadQueryFont(dpy, fontstr); +		if (!dc.font.xfont) +			dc.font.xfont = XLoadQueryFont(dpy, "fixed"); +		if (!dc.font.xfont) +			eprint("error, cannot init 'fixed' font\n"); +		dc.font.ascent = dc.font.xfont->ascent; +		dc.font.descent = dc.font.xfont->descent;  	} -	font->height = font->ascent + font->descent; +	dc.font.height = dc.font.ascent + dc.font.descent; +} + +unsigned int +textw(const char *text) +{ +	return textnw(text, strlen(text)) + dc.font.height;  } @@ -16,74 +16,112 @@  #include <X11/keysym.h>  typedef struct Item Item; -  struct Item {  	Item *next;		/* traverses all items */  	Item *left, *right;	/* traverses items matching current search pattern */  	char *text;  }; -static Display *dpy; -static Window root; -static Window win; -static Bool done = False; - -static Item *allitem = NULL;	/* first of all items */ -static Item *item = NULL;	/* first of pattern matching items */ -static Item *sel = NULL; -static Item *nextoff = NULL; -static Item *prevoff = NULL; -static Item *curroff = NULL; +/* static */ -static int screen, mx, my, mw, mh; -static char *title = NULL; -static char text[4096]; +static char *title, text[4096]; +static int mx, my, mw, mh;  static int ret = 0;  static int nitem = 0;  static unsigned int cmdw = 0;  static unsigned int tw = 0;  static unsigned int cw = 0; -static const int seek = 30;		/* 30px */ - -static Brush brush = {0}; - -static void draw_menu(); -static void kpress(XKeyEvent * e); - -static char version[] = "dmenu - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n"; +static Bool done = False; +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;  static void -update_offsets() +calcoffsets()  { -	unsigned int tw, w = cmdw + 2 * seek; +	unsigned int tw, w; -	if(!curroff) +	if(!curr)  		return; -	for(nextoff = curroff; nextoff; nextoff=nextoff->right) { -		tw = textw(&brush.font, nextoff->text); +	w = cmdw + 2 * SPACE; +	for(next = curr; next; next=next->right) { +		tw = textw(next->text);  		if(tw > mw / 3)  			tw = mw / 3; -		w += tw + brush.font.height; +		w += tw;  		if(w > mw)  			break;  	} -	w = cmdw + 2 * seek; -	for(prevoff = curroff; prevoff && prevoff->left; prevoff=prevoff->left) { -		tw = textw(&brush.font, prevoff->left->text); +	w = cmdw + 2 * SPACE; +	for(prev = curr; prev && prev->left; prev=prev->left) { +		tw = textw(prev->left->text);  		if(tw > mw / 3)  			tw = mw / 3; -		w += tw + brush.font.height; +		w += tw;  		if(w > mw)  			break;  	}  }  static void -update_items(char *pattern) +drawmenu() +{ +	Item *i; + +	dc.x = 0; +	dc.y = 0; +	dc.w = mw; +	dc.h = mh; +	drawtext(NULL, False, False); + +	/* print command */ +	if(!title || text[0]) { +		cmdw = cw; +		if(cmdw && item) +			dc.w = cmdw; +		drawtext(text, False, False); +	} +	else { +		cmdw = tw; +		dc.w = cmdw; +		drawtext(title, False, False); +	} +	dc.x += dc.w; + +	if(curr) { +		dc.w = SPACE; +		drawtext((curr && curr->left) ? "<" : NULL, False, False); +		dc.x += dc.w; + +		/* determine maximum items */ +		for(i = curr; i != next; i=i->right) { +			dc.border = False; +			dc.w = textw(i->text); +			if(dc.w > mw / 3) +				dc.w = mw / 3; +			drawtext(i->text, sel == i, sel == i); +			dc.x += dc.w; +		} + +		dc.x = mw - SPACE; +		dc.w = SPACE; +		drawtext(next ? ">" : NULL, False, False); +	} +	XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, mw, mh, 0, 0); +	XFlush(dpy); +} + +static void +input(char *pattern)  { -	unsigned int plen = strlen(pattern); +	unsigned int plen;  	Item *i, *j;  	if(!pattern) @@ -94,10 +132,11 @@ update_items(char *pattern)  	else  		cmdw = tw; +	plen = strlen(pattern);  	item = j = NULL;  	nitem = 0; -	for(i = allitem; i; i=i->next) +	for(i = allitems; i; i=i->next)  		if(!plen || !strncmp(pattern, i->text, plen)) {  			if(!j)  				item = i; @@ -108,7 +147,7 @@ update_items(char *pattern)  			j = i;  			nitem++;  		} -	for(i = allitem; i; i=i->next) +	for(i = allitems; i; i=i->next)  		if(plen && strncmp(pattern, i->text, plen)  				&& strstr(i->text, pattern)) {  			if(!j) @@ -121,75 +160,19 @@ update_items(char *pattern)  			nitem++;  		} -	curroff = prevoff = nextoff = sel = item; - -	update_offsets(); -} - -/* creates brush structs for brush mode drawing */ -static void -draw_menu() -{ -	Item *i; - -	brush.x = 0; -	brush.y = 0; -	brush.w = mw; -	brush.h = mh; -	draw(dpy, &brush, False, 0); - -	/* print command */ -	if(!title || text[0]) { -		cmdw = cw; -		if(cmdw && item) -			brush.w = cmdw; -		draw(dpy, &brush, False, text); -	} -	else { -		cmdw = tw; -		brush.w = cmdw; -		draw(dpy, &brush, False, title); -	} -	brush.x += brush.w; - -	if(curroff) { -		brush.w = seek; -		draw(dpy, &brush, False, (curroff && curroff->left) ? "<" : 0); -		brush.x += brush.w; - -		/* determine maximum items */ -		for(i = curroff; i != nextoff; i=i->right) { -			brush.border = False; -			brush.w = textw(&brush.font, i->text); -			if(brush.w > mw / 3) -				brush.w = mw / 3; -			brush.w += brush.font.height; -			if(sel == i) { -				swap((void **)&brush.fg, (void **)&brush.bg); -				draw(dpy, &brush, True, i->text); -				swap((void **)&brush.fg, (void **)&brush.bg); -			} -			else -				draw(dpy, &brush, False, i->text); -			brush.x += brush.w; -		} - -		brush.x = mw - seek; -		brush.w = seek; -		draw(dpy, &brush, False, nextoff ? ">" : 0); -	} -	XCopyArea(dpy, brush.drawable, win, brush.gc, 0, 0, mw, mh, 0, 0); -	XFlush(dpy); +	curr = prev = next = sel = item; +	calcoffsets();  }  static void  kpress(XKeyEvent * e)  { -	KeySym ksym;  	char buf[32];  	int num, prev_nitem; -	unsigned int i, len = strlen(text); +	unsigned int i, len; +	KeySym ksym; +	len = strlen(text);  	buf[0] = 0;  	num = XLookupString(e, buf, sizeof(buf), &ksym, 0); @@ -210,8 +193,8 @@ kpress(XKeyEvent * e)  		case XK_U:  		case XK_u:  			text[0] = 0; -			update_items(text); -			draw_menu(); +			input(text); +			drawmenu();  			return;  			break;  		case XK_bracketleft: @@ -224,24 +207,24 @@ kpress(XKeyEvent * e)  		if(!(sel && sel->left))  			return;  		sel=sel->left; -		if(sel->right == curroff) { -			curroff = prevoff; -			update_offsets(); +		if(sel->right == curr) { +			curr = prev; +			calcoffsets();  		}  		break;  	case XK_Tab:  		if(!sel)  			return;  		strncpy(text, sel->text, sizeof(text)); -		update_items(text); +		input(text);  		break;  	case XK_Right:  		if(!(sel && sel->right))  			return;  		sel=sel->right; -		if(sel == nextoff) { -			curroff = nextoff; -			update_offsets(); +		if(sel == next) { +			curr = next; +			calcoffsets();  		}  		break;  	case XK_Return: @@ -265,9 +248,9 @@ kpress(XKeyEvent * e)  			prev_nitem = nitem;  			do {  				text[--i] = 0; -				update_items(text); +				input(text);  			} while(i && nitem && prev_nitem == nitem); -			update_items(text); +			input(text);  		}  		break;  	default: @@ -277,14 +260,14 @@ kpress(XKeyEvent * e)  				strncat(text, buf, sizeof(text));  			else  				strncpy(text, buf, sizeof(text)); -			update_items(text); +			input(text);  		}  	} -	draw_menu(); +	drawmenu();  }  static char * -read_allitems() +readinput()  {  	static char *maxname = NULL;  	char *p, buf[1024]; @@ -306,7 +289,7 @@ read_allitems()  		new->next = new->left = new->right = NULL;  		new->text = p;  		if(!i) -			allitem = new; +			allitems = new;  		else   			i->next = new;  		i = new; @@ -315,21 +298,27 @@ read_allitems()  	return maxname;  } +/* extern */ + +int screen; +Display *dpy; +DC dc = {0}; +  int  main(int argc, char *argv[])  { -	int i; -	XSetWindowAttributes wa;  	char *maxname; +	int i;  	XEvent ev; +	XSetWindowAttributes wa;  	/* command line args */  	for(i = 1; i < argc; i++) {  		if (argv[i][0] == '-')  			switch (argv[i][1]) {  			case 'v': -				fprintf(stdout, "%s", version); -				exit(0); +				fputs("dmenu-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout); +				exit(EXIT_SUCCESS);  				break;  			case 't':  				if(++i < argc) { @@ -350,7 +339,7 @@ main(int argc, char *argv[])  	screen = DefaultScreen(dpy);  	root = RootWindow(dpy, screen); -	maxname = read_allitems(); +	maxname = readinput();  	/* grab as early as possible, but after reading all items!!! */  	while(XGrabKeyboard(dpy, root, True, GrabModeAsync, @@ -358,8 +347,10 @@ main(int argc, char *argv[])  		usleep(1000);  	/* style */ -	loadcolors(dpy, screen, &brush, BGCOLOR, FGCOLOR, BORDERCOLOR); -	loadfont(dpy, &brush.font, FONT); +	dc.bg = getcolor(BGCOLOR); +	dc.fg = getcolor(FGCOLOR); +	dc.border = getcolor(BORDERCOLOR); +	setfont(FONT);  	wa.override_redirect = 1;  	wa.background_pixmap = ParentRelative; @@ -367,28 +358,25 @@ main(int argc, char *argv[])  	mx = my = 0;  	mw = DisplayWidth(dpy, screen); -	mh = texth(&brush.font); +	mh = dc.font.height + 4;  	win = XCreateWindow(dpy, root, mx, my, mw, mh, 0,  			DefaultDepth(dpy, screen), CopyFromParent,  			DefaultVisual(dpy, screen),  			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);  	XDefineCursor(dpy, win, XCreateFontCursor(dpy, XC_xterm)); -	XFlush(dpy);  	/* pixmap */ -	brush.gc = XCreateGC(dpy, root, 0, 0); -	brush.drawable = XCreatePixmap(dpy, win, mw, mh, -			DefaultDepth(dpy, screen)); -	XFlush(dpy); +	dc.drawable = XCreatePixmap(dpy, root, mw, mh, DefaultDepth(dpy, screen)); +	dc.gc = XCreateGC(dpy, root, 0, 0);  	if(maxname) -		cw = textw(&brush.font, maxname) + brush.font.height; +		cw = textw(maxname);  	if(cw > mw / 3)  		cw = mw / 3;  	if(title) { -		tw = textw(&brush.font, title) + brush.font.height; +		tw = textw(title);  		if(tw > mw / 3)  			tw = mw / 3;  	} @@ -396,10 +384,10 @@ main(int argc, char *argv[])  	cmdw = title ? tw : cw;  	text[0] = 0; -	update_items(text); +	input(text);  	XMapRaised(dpy, win); -	draw_menu(); -	XFlush(dpy); +	drawmenu(); +	XSync(dpy, False);  	/* main event loop */  	while(!done && !XNextEvent(dpy, &ev)) { @@ -409,7 +397,7 @@ main(int argc, char *argv[])  			break;  		case Expose:  			if(ev.xexpose.count == 0) -				draw_menu(); +				drawmenu();  			break;  		default:  			break; @@ -417,8 +405,8 @@ main(int argc, char *argv[])  	}  	XUngrabKeyboard(dpy, CurrentTime); -	XFreePixmap(dpy, brush.drawable); -	XFreeGC(dpy, brush.gc); +	XFreePixmap(dpy, dc.drawable); +	XFreeGC(dpy, dc.gc);  	XDestroyWindow(dpy, win);  	XCloseDisplay(dpy); @@ -29,16 +29,6 @@ emalloc(unsigned int size)  	return res;  } -void * -emallocz(unsigned int size) -{ -	void *res = calloc(1, size); - -	if(!res) -		bad_malloc(size); -	return res; -} -  void  eprint(const char *errstr, ...)  { @@ -58,11 +48,3 @@ estrdup(const char *str)  		bad_malloc(strlen(str));  	return res;  } - -void -swap(void **p1, void **p2) -{ -	void *tmp = *p1; -	*p1 = *p2; -	*p2 = tmp; -} | 
