changeset:   2781:3a09477a41ff
user:        Kris Maglione <kris_AT_suckless.org>
date:        Thu Oct 07 16:31:41 2010 -0400
files:       alternative_wmiircs/python/pygmi/util.py cmd/menu/Makefile cmd/menu/caret.c cmd/menu/dat.h cmd/menu/history.c cmd/menu/keys.c cmd/menu/main.c cmd/menu/menu.c cmd/tray/main.c cmd/wmii/bar.c cmd/wmii/client.c cmd/wmii/dat.h cmd/wmii/frame.c cmd/wmii/main.c cmd/wmii/message.c cmd/wmiir.c cmd/x11/wmii9menu.c img/mkfile include/stuff/clientutil.h include/stuff/geom.h include/stuff/util.h include/stuff/x11.h lib/libstuff/client_readconfig.c lib/libstuff/clientutil.c lib/libstuff/x11/drawing/drawstring.c mk/common.mk util/compile
description:
[menu] Add vertical mode.
diff -r e638d4f40d56 -r 3a09477a41ff alternative_wmiircs/python/pygmi/util.py
--- a/alternative_wmiircs/python/pygmi/util.py	Thu Oct 07 16:31:38 2010 -0400
+++ b/alternative_wmiircs/python/pygmi/util.py	Thu Oct 07 16:31:41 2010 -0400
@@ -29,14 +29,14 @@
     call(*args, input=message)
 
 def program_list(path):
-    names = []
+    names = set()
     for d in path:
         try:
             for f in os.listdir(d):
                 p = '%s/%s' % (d, f)
-                if f not in names and os.access(p, os.X_OK) and (
-                    os.path.isfile(p) or os.path.islink(p)):
-                    names.append(f)
+                if (f not in names and os.access(p, os.X_OK) and
+                    os.path.isfile(p)):
+                    names.add(f)
         except Exception:
             pass
     return sorted(names)
diff -r e638d4f40d56 -r 3a09477a41ff cmd/menu/Makefile
--- a/cmd/menu/Makefile	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/menu/Makefile	Thu Oct 07 16:31:41 2010 -0400
@@ -5,12 +5,13 @@
 main.c: $(ROOT)/mk/wmii.mk
 
 bindings.c: keys.txt Makefile
-	( echo "char binding_spec[] = "; \
+	( echo "char binding_spec[] ="; \
           sed 's/.*/	"&\\n"/' keys.txt; \
-	  echo "	;" ) >bindings.c
+	  echo "	;" ) >$@
 
 TARG =	wimenu
 HFILES=	dat.h fns.h
+TAGFILES= dat.h
 
 PACKAGES += $(X11PACKAGES)
 
diff -r e638d4f40d56 -r 3a09477a41ff cmd/menu/caret.c
--- a/cmd/menu/caret.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/menu/caret.c	Thu Oct 07 16:31:41 2010 -0400
@@ -69,9 +69,7 @@
                                 p = next;
                         return p;
                 case CHAR:
-			if(p < end)
-				return p+1;
-			return p;
+			return next_rune(p, &r);
                 }
         }
         else if(dir == BACKWARD) {
@@ -88,9 +86,7 @@
                                 p = next;
                         return p;
                 case CHAR:
-			if(p > end)
-				return prev_rune(end, p, &r);
-			return end;
+			return prev_rune(end, p, &r);
                 }
         }
         input.pos_end = nil;
diff -r e638d4f40d56 -r 3a09477a41ff cmd/menu/dat.h
--- a/cmd/menu/dat.h	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/menu/dat.h	Thu Oct 07 16:31:41 2010 -0400
@@ -11,8 +11,6 @@
 #include <stuff/x.h>
 #include <stuff/util.h>
 
-#define BLOCK(x) do { x; }while(0)
-
 #ifndef EXTERN
 # define EXTERN extern
 #endif
@@ -69,38 +67,40 @@
         int	filter_start;
 } input;
 
+EXTERN struct {
+	Window*		win;
+	Image*		buf;
+	char*		prompt;
+	int		height;
+	int		rows;
+	bool		ontop;
+	Rectangle	itemr;
+	Point		arrow;
+} menu;
+
 extern char	binding_spec[];
 
-EXTERN int	numlock;
-
-EXTERN long	xtime;
-EXTERN Image*	ibuf;
-EXTERN Font*	font;
-EXTERN CTuple	cnorm, csel;
-EXTERN bool	ontop;
-
-EXTERN Cursor	cursor[1];
-EXTERN Visual*	render_visual;
-
 EXTERN IxpServer	srv;
 
-EXTERN Window*	barwin;
+EXTERN struct {
+	Item*	all;
+	Item*	first;
+	Item*	start;
+	Item*	end;
+	Item*	sel;
+	int	maxwidth;
+} match;
 
-EXTERN Item*	items;
-EXTERN Item*	matchfirst;
-EXTERN Item*	matchstart;
-EXTERN Item*	matchend;
-EXTERN Item*	matchidx;
+Font*		font;
+CTuple		cnorm;
+CTuple		csel;
 
 EXTERN Item	hist;
-EXTERN Item*	histidx;
+EXTERN Item*	histsel;
 
-EXTERN int	maxwidth;
+EXTERN int	itempad;
 EXTERN int	result;
 
-EXTERN  char*	(*find)(const char*, const char*);
-EXTERN  int	(*compare)(const char*, const char*, size_t);
+EXTERN char*	(*find)(const char*, const char*);
+EXTERN int	(*compare)(const char*, const char*, size_t);
 
-EXTERN char*	prompt;
-EXTERN int	promptw;
-
diff -r e638d4f40d56 -r 3a09477a41ff cmd/menu/history.c
--- a/cmd/menu/history.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/menu/history.c	Thu Oct 07 16:31:41 2010 -0400
@@ -19,25 +19,25 @@
         Item *i;
 
         if(dir == FORWARD) {
-		if(histidx == &hist)
+		if(histsel == &hist)
                         return hist.string;
-		for(i=histidx->next; i != hist.next; i=i->next)
+		for(i=histsel->next; i != hist.next; i=i->next)
                         if(!i->string || !compare(i->string, string, n)) {
-				histidx = i;
+				histsel = i;
                                 return i->string;
                         }
                 return string;
         }
         assert(dir == BACKWARD);
 
-	if(histidx == &hist) {
+	if(histsel == &hist) {
                 free(hist.string);
                 hist.string = estrdup(input.string);
         }
 
-	for(i=histidx->prev; i != &hist; i=i->prev)
+	for(i=histsel->prev; i != &hist; i=i->prev)
                 if(!compare(i->string, string, n)) {
-			histidx = i;
+			histsel = i;
                         return i->string;
                 }
         return string;
diff -r e638d4f40d56 -r 3a09477a41ff cmd/menu/keys.c
--- a/cmd/menu/keys.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/menu/keys.c	Thu Oct 07 16:31:41 2010 -0400
@@ -13,7 +13,8 @@
         char**	action;
 };
 
-static Key* bindings;
+static Key*	bindings;
+static int	numlock;
 
 /*
  * To do: Find my red black tree implementation.
diff -r e638d4f40d56 -r 3a09477a41ff cmd/menu/main.c
--- a/cmd/menu/main.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/menu/main.c	Thu Oct 07 16:31:41 2010 -0400
@@ -1,8 +1,6 @@
 /* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
  * See LICENSE file for license details.
  */
-#define IXP_NO_P9_
-#define IXP_P9_STRUCTS
 #define EXTERN
 #include "dat.h"
 #include <X11/Xproto.h>
@@ -23,7 +21,9 @@
 
 static void
 usage(void) {
-	fatal("usage: wimenu -i [-h <history>] [-a <address>] [-p <prompt>] [-s <screen>]\n");
+	fprint(2, "usage: %s -i [-a <address>] [-h <history>] [-p <prompt>] [-r <rows>] [-s <screen>]\n", argv0);
+	fprint(2, "       See manual page for full usage details.\n");
+	exit(1);
 }
 
 static int
@@ -50,13 +50,13 @@
         bool stop;
 
         stop = !hist && !isatty(buf->fid);
+	ret.next_link = nil;
         i = &ret;
         while((p = Brdstr(buf, '\n', true))) {
                 if(stop && p[0] == '\0')
                         break;
-		link(i, emallocz(sizeof *i));
-		i->next_link = i->next;
-		i = i->next;
+		i->next_link = emallocz(sizeof *i);
+		i = i->next_link;
                 i->string = p;
                 i->retstring = p;
                 if(cmdsep && (p = strstr(p, cmdsep))) {
@@ -65,15 +65,12 @@
                 }
                 if(!hist) {
                         i->len = strlen(i->string);
-			i->width = textwidth_l(font, i->string, i->len);
-			if(i->width > maxwidth)
-				maxwidth = i->width;
+			i->width = textwidth_l(font, i->string, i->len) + itempad;
+			match.maxwidth = max(i->width, match.maxwidth);
                 }
         }
 
-	link(i, &ret);
-	splice(&ret);
-	return ret.next != &ret ? ret.next : nil;
+	return ret.next_link;
 }
 
 static void
@@ -86,7 +83,7 @@
                 return;
         }
         input.filter_start = strtol(s, nil, 10);
-	items = populate_list(cmplbuf, false);
+	match.all = populate_list(cmplbuf, false);
         update_filter(false);
         menu_draw();
 }
@@ -143,8 +140,8 @@
         if(input.pos < input.end)
                 filter = freelater(estrndup(filter, input.pos - filter));
 
-	matchidx = nil;
-	matchfirst = matchstart = filter_list(items, filter);
+	match.sel = nil;
+	match.first = match.start = filter_list(match.all, filter);
         if(print)
                 update_input();
 }
@@ -158,8 +155,7 @@
         int i, n;
 
         rects = xinerama_screens(&n);
-	if (screen_hint >= 0 && screen_hint < n)
-		/* We were given a valid screen index, use that. */
+	if(screen_hint >= 0 && screen_hint < n)
                 i = screen_hint;
         else {
                 /* Pick the screen with the pointer, for now. Later,
@@ -178,11 +174,11 @@
 
 int
 main(int argc, char *argv[]) {
-	Item *item;
         static char *address;
         static char *histfile;
         static char *keyfile;
         static bool nokeys;
+	Item *item;
         int i;
         long ndump;
 
@@ -220,7 +216,10 @@
                 ndump = strtol(EARGF(usage()), nil, 10);
                 break;
         case 'p':
-		prompt = EARGF(usage());
+		menu.prompt = EARGF(usage());
+		break;
+	case 'r':
+		menu.rows = strtol(EARGF(usage()), nil, 10);
                 break;
         case 's':
                 screen_hint = strtol(EARGF(usage()), nil, 10);
@@ -249,11 +248,13 @@
         srv.preselect = event_preselect;
         ixp_listen(&srv, ConnectionNumber(display), nil, event_fdready, event_fdclosed);
 
-	ontop = !strcmp(readctl("bar on "), "top");
+	menu.ontop = !strcmp(readctl("/ctl", "bar "), "on top");
         client_readconfig(&cnorm, &csel, &font);
 
+	itempad = (font->height & ~1) + font->pad.min.x + font->pad.max.x;
+
         cmplbuf = Bfdopen(0, OREAD);
-	items = populate_list(cmplbuf, false);
+	match.all = populate_list(cmplbuf, false);
         if(!isatty(cmplbuf->fid))
                 ixp_listen(&srv, cmplbuf->fid, inbuf, check_competions, nil);
 
@@ -268,21 +269,18 @@
                         parse_keys(buffer);
         }
 
-	histidx = &hist;
+	histsel = &hist;
         link(&hist, &hist);
-	if(histfile) {
-		inbuf = Bopen(histfile, OREAD);
-		if(inbuf) {
-			item = populate_list(inbuf, true);
-			if(item) {
-				link(item->prev, &hist);
-				link(&hist, item);
-			}
-			Bterm(inbuf);
+	if(histfile && (inbuf = Bopen(histfile, OREAD))) {
+		item = filter_list(populate_list(inbuf, true), "");
+		if(item->string) {
+			link(item->prev, &hist);
+			link(&hist, item);
                 }
+		Bterm(inbuf);
         }
 
-	if(barwin == nil)
+	if(menu.win == nil)
                 menu_init();
 
         init_screens();
diff -r e638d4f40d56 -r 3a09477a41ff cmd/menu/menu.c
--- a/cmd/menu/menu.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/menu/menu.c	Thu Oct 07 16:31:41 2010 -0400
@@ -4,270 +4,220 @@
 #include <unistd.h>
 #include "fns.h"
 
-static Handlers handlers;
-
-static int	ltwidth;
-
-static void	_menu_draw(bool);
-
-enum {
-	ACCEPT = CARET_LAST,
-	REJECT,
-	HIST,
-	KILL,
-	CMPL_NEXT,
-	CMPL_PREV,
-	CMPL_FIRST,
-	CMPL_LAST,
-	CMPL_NEXT_PAGE,
-	CMPL_PREV_PAGE,
-};
+static Handlers	handlers;
+static int	promptw;
 
 void
 menu_init(void) {
         WinAttr wa;
 
         wa.event_mask = ExposureMask | KeyPressMask;
-	barwin = createwindow(&scr.root, Rect(-1, -1, 1, 1), scr.depth, InputOutput,
-			      &wa, CWEventMask);
+	menu.win = createwindow(&scr.root, Rect(-1, -1, 1, 1), scr.depth, InputOutput,
+				&wa, CWEventMask);
         if(scr.xim)
-		barwin->xic = XCreateIC(scr.xim,
-					XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
-					XNClientWindow, barwin->xid,
-					XNFocusWindow, barwin->xid,
-					nil);
+		menu.win->xic = XCreateIC(scr.xim,
+					  XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
+					  XNClientWindow, menu.win->xid,
+					  XNFocusWindow, menu.win->xid,
+					  nil);
 
-	changeprop_long(barwin, Net("WM_WINDOW_TYPE"), "ATOM",
-			(long[]){ TYPE("MENU") }, 1);
-	changeprop_string(barwin, "_WMII_TAGS", "sel");
-	changeprop_textlist(barwin, "WM_CLASS", "STRING",
-			    (char*[3]){ "wimenu", "wimenu", nil });
+	changeprop_long(menu.win, Net("WM_WINDOW_TYPE"), "ATOM", (long[]){ TYPE("MENU") }, 1);
+	changeprop_string(menu.win, "_WMII_TAGS", "sel");
+	changeprop_textlist(menu.win, "WM_CLASS", "STRING", (char*[3]){ "wimenu", "wimenu" });
 
-	sethandler(barwin, &handlers);
-	mapwin(barwin);
+	sethandler(menu.win, &handlers);
+	mapwin(menu.win);
 
         int i = 0;
-	while(!grabkeyboard(barwin)) {
+	while(!grabkeyboard(menu.win)) {
                 if(i++ > 1000)
                         fatal("can't grab keyboard");
                 usleep(1000);
         }
 }
 
+void
+menu_show(void) {
+	Rectangle r;
+
+	if(menu.prompt)
+		promptw = textwidth(font, menu.prompt) + itempad;
+
+	r = textextents_l(font, "<", 1, nil);
+	menu.arrow = Pt(Dy(r) + itempad/2, Dx(r) + itempad/2);
+
+	menu.height = labelh(font);
+
+	freeimage(menu.buf);
+	menu.buf = allocimage(Dx(scr.rect),
+			      !!menu.rows * 2 * menu.arrow.y + (menu.rows + 1) * menu.height,
+			      menu.win->depth);
+
+	mapwin(menu.win);
+	raisewin(menu.win);
+	menu_draw();
+}
+
+/* I'd prefer to use ⌃ and ⌄, but few fonts support them. */
 static void
-menu_unmap(long id, void *p) {
+drawarrow(Image *img, Rectangle r, int up, Color *col) {
+	Point p[3], pt;
 
-	USED(id, p);
-	unmapwin(barwin);
-	XFlush(display);
+	pt = Pt(menu.arrow.x - itempad/2, menu.arrow.y - itempad/2 & ~1);
+
+	p[1] = Pt(r.min.x + Dx(r)/2,	up ? r.min.y + itempad/4 : r.max.y - itempad/4);
+	p[0] = Pt(p[1].x - pt.x/2,	up ? p[1].y + pt.y	 : p[1].y - pt.y);
+	p[2] = Pt(p[1].x + pt.x/2,	p[0].y);
+	drawpoly(img, p, nelem(p), CapProjecting, 1, col);
+}
+
+static Rectangle
+slice(Rectangle *rp, int x, int y) {
+	Rectangle r;
+
+	r = *rp;
+	if(x)
+		rp->min.x += x, r.max.x = min(rp->min.x, rp->max.x);
+	if(y)
+		rp->min.y += y, r.max.y = min(rp->min.y, rp->max.y);
+	return r;
+}
+
+static bool
+nextrect(Item *i, Rectangle *rp, Rectangle *src) {
+	Rectangle r;
+
+	if(menu.rows)
+		r = slice(src, 0, menu.height);
+	else
+		r = slice(src, i->width, 0);
+	return (Dx(*src) >= 0 && Dy(*src) >= 0) && (*rp = r, 1);
+}
+
+void
+menu_draw(void) {
+	Rectangle barr, extent, itemr, inputr, r, r2;
+	Item *item;
+	int inputw, offset;
+
+	barr = r2 = Rect(0, 0, Dx(menu.win->r), menu.height);
+
+	inputw = max(match.maxwidth + textwidth_l(font, input.string, min(input.filter_start, strlen(input.string))),
+		     max(itempad    + textwidth(font, input.string),
+			 Dx(barr) / 3));
+
+	/* Calculate items box, w/ and w/o arrows */
+	if(menu.rows) {
+		menu.itemr = barr;
+		menu.itemr.max.y += Dy(barr) * (menu.rows - 1);
+		if(menu.ontop)
+			menu.itemr = rectaddpt(menu.itemr, Pt(0, Dy(barr)));
+		itemr = menu.itemr;
+		if(match.start != match.first)
+			menu.itemr = rectaddpt(menu.itemr, Pt(0, menu.arrow.y));
+	}
+	else {
+		itemr = r2;
+		slice(&itemr, inputw + promptw, 0);
+		menu.itemr = Rect(itemr.min.x + menu.arrow.x, itemr.min.y,
+				  itemr.max.x - menu.arrow.x, itemr.max.y);
+	}
+
+	fill(menu.buf, menu.buf->r, &cnorm.bg);
+
+	/* Draw items */
+	item = match.start, r2 = menu.itemr;
+	nextrect(item, &r, &r2);
+	do {
+		match.end = item;
+		if(item->string)
+			fillstring(menu.buf, font, r, West, item->string,
+				   (item == match.sel ? &csel : &cnorm), 0);
+		item = item->next;
+	} while(item != match.first && nextrect(item, &r, &r2));
+
+	/* Adjust dimensions for arrows/number of items */
+	if(menu.rows)
+		itemr.max.y = r.max.y + (match.end->next != match.first ? menu.arrow.y : 0);
+	else
+		itemr.max.x = r.max.x + menu.arrow.x;
+	if(menu.rows && !menu.ontop)
+		barr = rectaddpt(barr, Pt(0, itemr.max.y));
+
+	/* Draw indicators */
+	if(!menu.rows && match.start != match.first)
+		drawstring(menu.buf, font, itemr, West, "<", &cnorm.fg);
+	if(!menu.rows && match.end->next != match.first)
+		drawstring(menu.buf, font, itemr, East, ">", &cnorm.fg);
+
+	if(menu.rows && match.start != match.first)
+		drawarrow(menu.buf, itemr, 1, &cnorm.fg);
+	if(menu.rows && match.end->next != match.first)
+		drawarrow(menu.buf, itemr, 0, &cnorm.fg);
+
+	/* Draw prompt */
+	r2 = barr;
+	if(menu.prompt)
+		drawstring(menu.buf, font, slice(&r2, promptw, 0),
+			   West, menu.prompt, &cnorm.fg);
+
+	/* Border input/horizontal items */
+	border(menu.buf, r2, 1, &cnorm.border);
+
+	/* Draw input */
+	inputr = slice(&r2, inputw, 0);
+	drawstring(menu.buf, font, inputr, West, input.string, &cnorm.fg);
+
+	/* Draw cursor */
+	extent = textextents_l(font, input.string, input.pos - input.string, &offset);
+	r2 = insetrect(inputr, 2);
+	r2.min.x = inputr.min.x - extent.min.x + offset + font->pad.min.x + itempad/2 - 1;
+	r2.max.x = r2.min.x + 1;
+	fill(menu.buf, r2, &cnorm.border);
+
+	/* Reshape window */
+	r = scr.rect;
+	if(menu.ontop)
+		r.max.y = r.min.y + itemr.max.y;
+	else
+		r.min.y = r.max.y - barr.max.y;
+	reshapewin(menu.win, r);
+
+	/* Border window */
+	r = rectsubpt(r, r.min);
+	border(menu.buf, r, 1, &cnorm.border);
+	copyimage(menu.win, r, menu.buf, ZP);
+}
+
+static Item*
+pagestart(Item *i) {
+	Rectangle r, r2;
+
+	r = menu.itemr;
+	nextrect(i, &r2, &r);
+	while(i->prev != match.first->prev && nextrect(i->prev, &r2, &r))
+		i = i->prev;
+	return i;
 }
 
 static void
 selectitem(Item *i) {
-	if(i != matchidx) {
+	if(i != match.sel) {
                 caret_set(input.filter_start, input.pos - input.string);
                 caret_insert(i->string, 0);
-		matchidx = i;
+		match.sel = i;
+		if(i == match.start->prev)
+			match.start = pagestart(i);
+		if(i == match.end->next)
+			match.start = i;
         }
 }
 
-static void
-menu_cmd(int op, int motion) {
-	int n;
-
-	switch(op) {
-	case HIST:
-		n = input.pos - input.string;
-		caret_insert(history_search(motion, input.string, n), true);
-		input.pos = input.string + n;
-		break;
-	case KILL:
-		caret_delete(BACKWARD, motion);
-		break;
-	default:
-		goto next;
-	}
-	update_filter(true);
-next:
-	switch(op) {
-	case ACCEPT:
-		srv.running = false;
-		if(!matchidx && matchfirst->retstring && !motion)
-		if(input.filter_start == 0 && input.pos == input.end)
-			menu_cmd(CMPL_FIRST, 0);
-		if(!motion && matchidx && !strcmp(input.string, matchidx->string))
-			lprint(1, "%s", matchidx->retstring);
-		else
-			lprint(1, "%s", input.string);
-		break;
-	case REJECT:
-		srv.running = false;
-		result = 1;
-		break;
-	case BACKWARD:
-	case FORWARD:
-		caret_move(op, motion);
-		update_input();
-		break;
-	case CMPL_NEXT:
-		selectitem(matchidx ? matchidx->next : matchfirst);
-		break;
-	case CMPL_PREV:
-		selectitem((matchidx ? matchidx : matchstart)->prev);
-		break;
-	case CMPL_FIRST:
-		matchstart = matchfirst;
-		matchend = nil;
-		selectitem(matchstart);
-		break;
-	case CMPL_LAST:
-		selectitem(matchfirst->prev);
-		break;
-	case CMPL_NEXT_PAGE:
-		if(matchend)
-			selectitem(matchend->next);
-		break;
-	case CMPL_PREV_PAGE:
-		matchend = matchstart->prev;
-		matchidx = nil;
-		_menu_draw(false);
-		selectitem(matchstart);
-		break;
-	}
-	menu_draw();
-}
-
-static void
-_menu_draw(bool draw) {
-	Rectangle r, rd, rp, r2, extent;
-	CTuple *c;
-	Item *i;
-	int inputw, itemoff, end, pad, n, offset;
-
-	r = barwin->r;
-	r = rectsetorigin(r, ZP);
-
-	pad = (font->height & ~1) + font->pad.min.x + font->pad.max.x;
-
-	rd = r;
-	rp = ZR; // SET(rp)
-	if (prompt) {
-		if (!promptw)
-			promptw = textwidth(font, prompt) + 2 * ltwidth + pad;
-		rd.min.x += promptw;
-
-		rp = r;
-		rp.max.x = promptw;
-	}
-
-	inputw = min(Dx(rd) / 3, maxwidth);
-	inputw = max(inputw, textwidth(font, input.string)) + pad;
-	itemoff = inputw + 2 * ltwidth;
-	end = Dx(rd) - ltwidth;
-
-	fill(ibuf, r, &cnorm.bg);
-
-	if(matchend && matchidx == matchend->next)
-		matchstart = matchidx;
-	else if(matchidx == matchstart->prev)
-		matchend = matchidx;
-	if (matchend == nil)
-		matchend = matchstart;
-
-	if(matchend == matchstart->prev && matchstart != matchidx) {
-		n = itemoff;
-		matchstart = matchend;
-		for(i=matchend; ; i=i->prev) {
-			n += i->width + pad;
-			if(n > end)
-				break;
-			matchstart = i;
-			if(i == matchfirst)
-				break;
-		}
-	}
-
-	if(!draw)
-		return;
-
-	r2 = rd;
-	for(i=matchstart; i->string; i=i->next) {
-		r2.min.x = promptw + itemoff;
-		itemoff  = itemoff + i->width + pad;
-		r2.max.x = promptw + min(itemoff, end);
-		if(i != matchstart && itemoff > end)
-			break;
-
-		c = (i == matchidx) ? &csel : &cnorm;
-		fill(ibuf, r2, &c->bg);
-		drawstring(ibuf, font, r2, Center, i->string, &c->fg);
-		matchend = i;
-		if(i->next == matchfirst)
-			break;
-	}
-
-	r2 = rd;
-	r2.min.x = promptw + inputw;
-	if(matchstart != matchfirst)
-		drawstring(ibuf, font, r2, West, "<", &cnorm.fg);
-	if(matchend->next != matchfirst)
-		drawstring(ibuf, font, r2, East, ">", &cnorm.fg);
-
-	r2 = rd;
-	r2.max.x = promptw + inputw;
-	drawstring(ibuf, font, r2, West, input.string, &cnorm.fg);
-
-	extent = textextents_l(font, input.string, input.pos - input.string, &offset);
-	r2.min.x = promptw + offset + font->pad.min.x - extent.min.x + pad/2 - 1;
-	r2.max.x = r2.min.x + 2;
-	r2.min.y++;
-	r2.max.y--;
-	border(ibuf, r2, 1, &cnorm.border);
-
-	if (prompt)
-		drawstring(ibuf, font, rp, West, prompt, &cnorm.fg);
-
-	border(ibuf, rd, 1, &cnorm.border);
-	copyimage(barwin, r, ibuf, ZP);
-}
-
-void
-menu_draw(void) {
-	_menu_draw(true);
-}
-
-void
-menu_show(void) {
-	Rectangle r;
-	int height, pad;
-
-	USED(menu_unmap);
-
-	ltwidth = textwidth(font, "<");
-
-	pad = (font->height & ~1)/2;
-	height = labelh(font);
-
-	r = scr.rect;
-	if(ontop)
-		r.max.y = r.min.y + height;
-	else
-		r.min.y = r.max.y - height;
-	reshapewin(barwin, r);
-
-	freeimage(ibuf);
-	ibuf = allocimage(Dx(r), Dy(r), scr.depth);
-
-	mapwin(barwin);
-	raisewin(barwin);
-	menu_draw();
-}
-
 static bool
 kdown_event(Window *w, void *aux, XKeyEvent *e) {
         char **action, **p;
         char *key;
-	char buf[32];
+	char buf[128];
         int num, status;
         KeySym ksym;
 
@@ -276,8 +226,7 @@
 
         status = XLookupBoth;
         if(w->xic)
-		num = Xutf8LookupString(w->xic, e, buf, sizeof buf - 1, &ksym,
-					&status);
+		num = Xutf8LookupString(w->xic, e, buf, sizeof buf - 1, &ksym, &status);
         else
                 num = XLookupString(e, buf, sizeof buf - 1, &ksym, nil);
 
@@ -319,37 +268,65 @@
                         have(LWORD) ? WORD :
                         have(LLINE) ? LINE :
                         -1);
+
                 switch(getsym(action[0])) {
+		default:
+			return false;
+		case LHISTORY:
+			num = input.pos - input.string;
+			amount = have(LBACKWARD) ? BACKWARD : FORWARD;
+			caret_insert(history_search(amount, input.string, num), true);
+			input.pos = input.string + num;
+			update_filter(true);
+			break;
+		case LKILL:
+			caret_delete(BACKWARD, amount);
+			update_filter(true);
+			break;
+
                 case LACCEPT:
-			menu_cmd(ACCEPT, have(LLITERAL));
+			srv.running = false;
+			if(!have(LLITERAL) && !match.sel && match.start->retstring)
+				if(input.filter_start == 0 && input.pos == input.end)
+					selectitem(match.start);
+
+			if(!have(LLITERAL) && match.sel && !strcmp(input.string, match.sel->string))
+				lprint(1, "%s", match.sel->retstring);
+			else
+				lprint(1, "%s", input.string);
                         break;
                 case LBACKWARD:
-			menu_cmd(BACKWARD, amount);
+			caret_move(BACKWARD, amount);
+			update_input();
                         break;
                 case LCOMPLETE:
-			amount = (
-				have(LNEXT)     ? CMPL_NEXT  :
-				have(LPREV)     ? CMPL_PREV  :
-				have(LNEXTPAGE) ? CMPL_NEXT_PAGE :
-				have(LPREVPAGE) ? CMPL_PREV_PAGE :
-				have(LFIRST)    ? CMPL_FIRST :
-				have(LLAST)     ? CMPL_LAST  :
-				CMPL_NEXT);
-			menu_cmd(amount, 0);
+			if(have(LNEXT))
+				selectitem(match.sel ? match.sel->next : match.first);
+			else if(have(LPREV))
+				selectitem((match.sel ? match.sel : match.start)->prev);
+			else if(have(LFIRST)) {
+				match.start = match.first;
+				selectitem(match.start);
+			}
+			else if(have(LLAST))
+				selectitem(match.first->prev);
+			else if(have(LNEXTPAGE))
+				selectitem(match.end->next);
+			else if(have(LPREVPAGE)) {
+				match.start = pagestart(match.start->prev);
+				selectitem(match.start);
+			}
                         break;
                 case LFORWARD:
-			menu_cmd(FORWARD, amount);
-			break;
-		case LHISTORY:
-			menu_cmd(HIST, have(LBACKWARD) ? BACKWARD : FORWARD);
-			break;
-		case LKILL:
-			menu_cmd(KILL, amount);
+			caret_move(FORWARD, amount);
+			update_input();
                         break;
                 case LREJECT:
-			menu_cmd(REJECT, 0);
+			srv.running = false;
+			result = 1;
                         break;
                 }
+		menu_draw();
         }
         return false;
 }
diff -r e638d4f40d56 -r 3a09477a41ff cmd/tray/main.c
--- a/cmd/tray/main.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/tray/main.c	Thu Oct 07 16:31:41 2010 -0400
@@ -191,7 +191,7 @@
         client_init(nil);
 
         if(tray.edge == 0)
-		tray.edge = West | (!strcmp(readctl("bar on "), "top") ? North : South);
+		tray.edge = West | (!strcmp(readctl("/ctl", "bar on "), "top") ? North : South);
 
         client_readconfig(&tray.normcolors, &tray.selcolors, &tray.font);
 
diff -r e638d4f40d56 -r 3a09477a41ff cmd/wmii/bar.c
--- a/cmd/wmii/bar.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/wmii/bar.c	Thu Oct 07 16:31:41 2010 -0400
@@ -195,9 +195,7 @@
                 align = Center;
                 if(b == s->bar[BRight])
                         align = East;
-		fill(ibuf, b->r, &b->colors.bg);
-		drawstring(ibuf, def.font, b->r, align, b->text, &b->colors.fg);
-		border(ibuf, b->r, 1, &b->colors.border);
+		fillstring(ibuf, def.font, b->r, align, b->text, &b->colors, 1);
         }
 
         if(s->barwin_rgba != (s->barwin->depth == 32))
diff -r e638d4f40d56 -r 3a09477a41ff cmd/wmii/client.c
--- a/cmd/wmii/client.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/wmii/client.c	Thu Oct 07 16:31:41 2010 -0400
@@ -220,7 +220,8 @@
         bool ret, more;
 
         ret = true;
-	for(r=def.rules.rule; r; r=r->next)
+	more = true;
+	for(r=def.rules.rule; r && more; r=r->next)
                 if(regexec(r->regex, c->props, nil, 0)) {
                         more = false;
                         for(rv=r->values; rv; rv=rv->next) {
@@ -234,15 +235,15 @@
                                 }else {
                                         bufclear();
                                         bufprint("%s %s", rv->key, rv->value);
-					m = ixp_message(buffer, sizeof buffer, MsgPack);
-					if(!waserror()) {
+					m = ixp_message(buffer, _buf_end - buffer, MsgPack);
+					if(waserror())
+						warning("processing rule %q=%q: %r", rv->key, rv->value);
+					else {
                                                 message_client(c, &m);
                                                 poperror();
                                         }
                                 }
                         }
-			if(!more)
-				return ret;
                 }
         return ret;
 }
@@ -1093,6 +1094,11 @@
         toks[i] = nil;
         tags = comm(CLeft, toks, c->retags);
 
+	if(i == 1 && !c->tagre.regex && !c->tagvre.regex) {
+		free(tags);
+		return nil;
+	}
+
         fmtstrinit(&fmt);
         if(i > 1)
                 join(tags, "+", &fmt);
@@ -1131,17 +1137,16 @@
                 /* Check for regex. */
                 if(cur[0] == '/') {
                         cur++;
-			*strchr(cur, '/') = '\0';
+			*strrchr(cur, '/') = '\0';
                         if(add == '+')
                                 reinit(&c->tagre, cur);
                         else if(add == '-')
                                 reinit(&c->tagvre, cur);
                 }
-
-		trim(cur, " \t\r\n");
-		if(!strcmp(cur, "~"))
+		else if(!strcmp(cur, "~"))
                         c->floating = add ? On : Never;
                 else {
+			trim(cur, " \t\r\n");
                         if(!strcmp(cur, "sel"))
                                 cur = selview->name;
                         else if(Mbsearch(cur, badtags, bsstrcmp))
diff -r e638d4f40d56 -r 3a09477a41ff cmd/wmii/dat.h
--- a/cmd/wmii/dat.h	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/wmii/dat.h	Thu Oct 07 16:31:41 2010 -0400
@@ -313,8 +313,7 @@
         uint	keyssz;
         Ruleset	colrules;
         Ruleset	rules;
-	char	grabmod[5];
-	ulong	mod;
+	long	mod;
         uint	border;
         uint	snap;
         int	colmode;
diff -r e638d4f40d56 -r 3a09477a41ff cmd/wmii/frame.c
--- a/cmd/wmii/frame.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/wmii/frame.c	Thu Oct 07 16:31:41 2010 -0400
@@ -398,6 +398,7 @@
         w = min(w, Dx(*rp) - 30); /* Magic number. */
         if(w > 0) {
                 r = *rp;
+		r.min.x = r.max.x - w;
                 rp->max.x -= w;
                 if(0)
                 drawline(img, Pt(rp->max.x, r.min.y+2),
@@ -406,6 +407,7 @@
                 drawstring(img, def.font, r, East,
                            s, &col->fg);
         }
+	free(s);
 }
 
 void
@@ -415,7 +417,6 @@
         CTuple *col;
         Image *img;
         char *s;
-	uint w;
         int n, m;
 
         if(f == nil || f->view != selview || f->area == nil)
@@ -443,6 +444,9 @@
         f->titlebar = insetrect(r, 3);
         f->titlebar.max.y += 3;
 
+	f->grabbox = insetrect(r, 2);
+	f->grabbox.max.x = f->grabbox.min.x + Dy(f->grabbox);
+
         /* Odd focus. Unselected, with keyboard focus. */
         /* Draw a border just inside the titlebar. */
         if(c != selclient() && c == disp.focus) {
@@ -450,15 +454,9 @@
                 border(img, insetrect(r, 2), 1, &def.focuscolor.border);
         }
 
-	/* grabbox */
-	r.min = Pt(2, 2);
-	r.max.y -= 2;
-	r.max.x = r.min.x + Dy(r);
-	f->grabbox = r;
-
         if(c->urgent)
-		fill(img, r, &col->fg);
-	border(img, r, 1, &col->border);
+		fill(img, f->grabbox, &col->fg);
+	border(img, f->grabbox, 1, &col->border);
 
         /* Odd focus. Selected, without keyboard focus. */
         /* Draw a border around the grabbox. */
@@ -466,38 +464,34 @@
                 border(img, insetrect(r, -1), 1, &def.normcolor.bg);
 
         /* Draw a border on borderless+titleless selected apps. */
-	if(f->area->floating && c->borderless && c->titleless && !c->fullscreen && c == selclient())
+	if(c->borderless && c->titleless && f->area->floating && !c->fullscreen && c == selclient())
                 setborder(c->framewin, def.border, &def.focuscolor.border);
         else
                 setborder(c->framewin, 0, &def.focuscolor.border);
 
         /* Label */
-	r.min.x = r.max.x;
-	r.max.x = fr.max.x;
-	r.min.y = 0;
-	r.max.y = labelh(def.font);
+	r = Rect(f->grabbox.max.x, 0, fr.max.x, labelh(def.font));
+
         /* Draw count on frames in 'max' columns. */
         if(f->area->max && !resizing) {
-		/* XXX */
                 n = stack_count(f, &m);
-		s = smprint("%d/%d", m, n);
+		pushlabel(img, &r, smprint("%d/%d", m, n), col);
+	}
+
+	/* Label clients with extra tags. */
+	if((s = client_extratags(c)))
                 pushlabel(img, &r, s, col);
-		free(s);
-	}
-	/* Label clients with extra tags. */
-	if((s = client_extratags(c))) {
-		pushlabel(img, &r, s, col);
-		free(s);
-	}else if(f->area->floating)  /* Make sure floating clients have room for their indicators. */
-		r.max.x -= Dx(f->grabbox);
+
+	if(f->area->floating)  /* Make sure floating clients have room for their indicators. */
+		r.max.x -= f->grabbox.max.x;
 
         if(!ewmh_responsive_p(c))
                 r.min.x += drawstring(img, def.font, r, West, "(wedged) ", &col->fg);
-	w = drawstring(img, def.font, r, West, c->name, &col->fg);
+	r.min.x += drawstring(img, def.font, r, West, c->name, &col->fg);
 
         /* Draw inner border on floating clients. */
         if(f->area->floating) {
-		r.min.x = r.min.x + w + 10;
+		r.min.x += 10;
                 r.max.x += Dx(f->grabbox);
                 r.min.y = f->grabbox.min.y;
                 r.max.y = f->grabbox.max.y;
diff -r e638d4f40d56 -r 3a09477a41ff cmd/wmii/main.c
--- a/cmd/wmii/main.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/wmii/main.c	Thu Oct 07 16:31:41 2010 -0400
@@ -372,8 +372,7 @@
         initdisplay();
 
         traperrors(true);
-	selectinput(&scr.root, EnterWindowMask
-			     | SubstructureRedirectMask);
+	selectinput(&scr.root, SubstructureRedirectMask);
         if(traperrors(false))
                 fatal("another window manager is already running");
 
@@ -388,7 +387,7 @@
 
         sock = ixp_announce(address);
         if(sock < 0)
-		fatal("Can't create socket '%s': %r", address);
+		fatal("Can't create socket %q: %r", address);
         closeexec(ConnectionNumber(display));
         closeexec(sock);
 
@@ -413,7 +412,6 @@
         def.incmode = ISqueeze;
 
         def.mod = Mod1Mask;
-	strcpy(def.grabmod, "Mod1");
 
         loadcolor(&def.focuscolor, FOCUSCOLORS, nil);
         loadcolor(&def.normcolor, NORMCOLORS, nil);
diff -r e638d4f40d56 -r 3a09477a41ff cmd/wmii/message.c
--- a/cmd/wmii/message.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/wmii/message.c	Thu Oct 07 16:31:41 2010 -0400
@@ -656,7 +656,6 @@
                 if(!parsekey(s, &i, nil) || i == 0)
                         return Ebadvalue;
 
-		utflcpy(def.grabmod, s, sizeof def.grabmod);
                 def.mod = i;
                 break;
         case LINCMODE:
@@ -700,7 +699,7 @@
         bufprint("font %s\n", def.font->name);
         bufprint("fontpad %d %d %d %d\n", def.font->pad.min.x, def.font->pad.max.x,
                  def.font->pad.max.y, def.font->pad.min.y);
-	bufprint("grabmod %s\n", def.grabmod);
+	bufprint("grabmod %s\n", (Mask){&def.mod, modkey_names});
         bufprint("incmode %s\n", incmodetab[def.incmode]);
         bufprint("normcolors %s\n", def.normcolor.colstr);
         bufprint("view %s\n", selview->name);
diff -r e638d4f40d56 -r 3a09477a41ff cmd/wmiir.c
--- a/cmd/wmiir.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/wmiir.c	Thu Oct 07 16:31:41 2010 -0400
@@ -426,7 +426,7 @@
         path = ixp_namespace();
         if(path == nil)
                 fatal("can't find namespace: %r\n");
-	Blprint(outbuf, "%s\n", path);
+	Blprint(outbuf, "%s", path);
         return 0;
 }
 
diff -r e638d4f40d56 -r 3a09477a41ff cmd/x11/wmii9menu.c
--- a/cmd/x11/wmii9menu.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/cmd/x11/wmii9menu.c	Thu Oct 07 16:31:41 2010 -0400
@@ -58,15 +58,8 @@
 
 static int	wborder;
 
-char	buffer[8092];
-char*	_buffer;
-
-/* for XSetWMProperties to use */
-int g_argc;
-char **g_argv;
-
-char *initial = "";
-int cur;
+static char*	initial = "";
+static int	cur;
 
 static char**	labels;		/* list of labels and commands */
 static char**	commands;
@@ -78,13 +71,7 @@
 void size_window(int, int);
 void redraw(int, int);
 void warpmouse(int, int);
-void memory(void);
-int args(void);
 
-Cursor cursor[1];
-Visual* render_visual;
-
-void init_screens(void);
 void
 init_screens(void) {
         Rectangle *rects;
@@ -111,9 +98,6 @@
         char *cp;
         int i;
 
-	g_argc = argc;
-	g_argv = argv;
-
         ARGBEGIN{
         case 'v':
                 lprint(1, "%s\n", version);
@@ -137,29 +121,24 @@
         create_window();
 
         numitems = argc;
-
         labels = emalloc(numitems * sizeof *labels);
         commands = emalloc(numitems * sizeof *labels);
 
         for(i = 0; i < numitems; i++) {
                 labels[i] = argv[i];
+		commands[i] = argv[i];
                 if((cp = strchr(labels[i], ':')) != nil) {
                         *cp++ = '\0';
                         commands[i] = cp;
-		} else
-			commands[i] = labels[i];
+		}
                 if(strcmp(labels[i], initial) == 0)
                         cur = i;
         }
 
         client_init(address);
 
-	wborder = strtol(readctl("border "), nil, 10);
-	loadcolor(&cnorm, readctl("normcolors "), nil);
-	loadcolor(&csel, readctl("focuscolors "), nil);
-	font = loadfont(readctl("font "));
-	if(!font)
-		fatal("Can't load font");
+	wborder = strtol(readctl("/ctl", "border "), nil, 10);
+	client_readconfig(&cnorm, &csel, &font);
 
         run_menu();
 
@@ -167,28 +146,22 @@
         return 0;
 }
 
-/* usage --- print a usage message and die */
-
 void
 usage(void)
 {
-	lprint(2, "usage: %s -v\n", argv0);
-	lprint(2, "       %s [-a <address>] [-i <arg>] menitem[:command] ...\n", argv0);
+	lprint(2, "usage: %s [-a <address>] [-i <arg>] <menitem>[:<command>] ...\n", argv0);
+	lprint(2, "       %s -v\n", argv0);
         exit(0);
 }
 
-/* run_menu --- put up the window, execute selected commands */
-
 enum {
-	MouseMask = 
-		  ButtonPressMask
-		| ButtonReleaseMask
-		| ButtonMotionMask
-		| PointerMotionMask,
-	MenuMask =
-		  MouseMask
-		| StructureNotifyMask
-		| ExposureMask
+	MouseMask = ButtonPressMask
+		  | ButtonReleaseMask
+		  | ButtonMotionMask
+		  | PointerMotionMask,
+	MenuMask = MouseMask
+		 | StructureNotifyMask
+		 | ExposureMask
 };
 
 void
@@ -197,8 +170,8 @@
         XEvent ev;
         int i, old, wide, high;
 
+	high = labelh(font);
         wide = 0;
-	high = labelh(font);
         for(i = 0; i < numitems; i++)
                 wide = max(wide, textwidth(font, labels[i]));
         wide += font->height & ~1;
@@ -231,12 +204,10 @@
                                 break;
                         redraw(high, wide);
                         break;
-		case MapNotify:
-			redraw(high, wide);
-			break;
                 case Expose:
                         redraw(high, wide);
                         break;
+		case MapNotify:
                 case ConfigureNotify:
                 case MappingNotify:
                         break;
@@ -244,13 +215,10 @@
         }
 }
 
-/* set_wm_hints --- set all the window manager hints */
-
 void
 create_window(void)
 {
         WinAttr wa = { 0 };
-	XEvent e;
 
         wa.override_redirect = true;
         menuwin = createwindow(&scr.root, Rect(-1, -1, 0, 0),
@@ -258,10 +226,8 @@
                                &wa, CWOverrideRedirect);
         selectinput(menuwin, MenuMask);
         mapwin(menuwin);
-	XMaskEvent(display, StructureNotifyMask, &e);
         if(!grabpointer(menuwin, nil, 0, MouseMask))
                 fatal("Failed to grab the mouse\n");
-	XSetCommand(display, menuwin->xid, g_argv, g_argc);
 }
 
 void
@@ -284,34 +250,22 @@
         p.y = min(p.y, scr.rect.max.y - h);
 
         reshapewin(menuwin, rectaddpt(r, p));
-
-	//XSetWindowBackground(display, menuwin->xid, cnorm.bg);
         setborder(menuwin, 1, &cnorm.border);
 }
 
-/* redraw --- actually redraw the menu */
-
 void
 redraw(int high, int wide)
 {
         Rectangle r;
-	CTuple *c;
         int i;
 
         r = Rect(0, 0, wide, high);
         for(i = 0; i < numitems; i++) {
-		if(cur == i)
-			c = &csel;
-		else
-			c = &cnorm;
                 r = rectsetorigin(r, Pt(0, i * high));
-		fill(menuwin, r, &c->bg);
-		drawstring(menuwin, font, r, Center, labels[i], &c->fg);
+		fillstring(menuwin, font, r, Center, labels[i], (cur == i ? &csel : &cnorm), 0);
         }
 }
 
-/* warpmouse --- bring the mouse to the menu */
-
 void
 warpmouse(int wide, int high)
 {
diff -r e638d4f40d56 -r 3a09477a41ff img/mkfile
--- a/img/mkfile	Thu Oct 07 16:31:38 2010 -0400
+++ b/img/mkfile	Thu Oct 07 16:31:41 2010 -0400
@@ -2,18 +2,22 @@
 path=$PLAN9/bin $path
 
 eps = wmii.eps
-calc = rc -c 'hoc -e $"*'
+calc = rc -c 'echo 4k $* p | dc}
 
-epsbox = `{sed -n '/^%%BoundingBox:/{s/.*://p; q;}' $eps}
-iconwidth = 154
-iconscale = `{*=$epsbox; $calc $iconwidth / '('$3 - $1')'}
-iconheight = `{*=$epsbox; $calc '('$4 - $2') *' $iconscale}
+iconwidth  = 16
+imagewidth = 154
 
-%.png: %.eps
+%.pdf: %.eps
+	sh epstopdf $stem.eps
+
+%-small.png: %.eps
+	epsbox = `{sed -n '/^%%BoundingBox:/{s/.*://p; q;}' $stem.eps}
+	iconscale = `{*=$epsbox; $calc $iconwidth $3 $1 -/}
+	iconheight = `{*=$epsbox; $calc $4 $2 - $iconscale '*'}
         * = `{hoc -e'-('$epsbox')'}
         x = $1
         y = $2
-	gs -q -dBATCH -dNOPAUSE -s'DEVICE=pngalpha' -s'OutputFile='$target -g$iconwidth'x'$iconheight - <<!
+	gs -q -dBATCH -dNOPAUSE -s'DEVICE=pngalpha' -s'OutputFile='$target -g$iconwidth^x^$iconheight - <<!
                 $iconscale $iconscale scale
                 $x $y translate
                 ($eps) run
@@ -22,18 +26,15 @@
         !
         optipng -fix $target
 
-%.pdf: %.eps
-	sh epstopdf $stem.eps
-
-%-small.png: %.eps
-	iconwidth = 16
-	iconscale = `{*=$epsbox; hoc -e $iconwidth/'('$3-' '$1')'}
-	iconheight = `{*=$epsbox; hoc -e '('$4-' '$2')*'$iconscale}
+%.png: %.eps
+	epsbox = `{sed -n '/^%%BoundingBox:/{s/.*://p; q;}' $stem.eps}
+	imagescale = `{*=$epsbox; $calc $imagewidth $3 $1 -/}
+	imageheight = `{*=$epsbox; $calc $4 $2 - $imagescale '*'}
         * = `{hoc -e'-('$epsbox')'}
         x = $1
         y = $2
-	gs -q -dBATCH -dNOPAUSE -s'DEVICE=pngalpha' -s'OutputFile='$target -g$iconwidth'x'$iconheight - <<!
-		$iconscale $iconscale scale
+	gs -q -dBATCH -dNOPAUSE -s'DEVICE=pngalpha' -s'OutputFile='$target -g$imagewidth^x^$imageheight - <<!
+		$imagescale $imagescale scale
                 $x $y translate
                 ($eps) run
                 showpage
diff -r e638d4f40d56 -r 3a09477a41ff include/stuff/clientutil.h
--- a/include/stuff/clientutil.h	Thu Oct 07 16:31:38 2010 -0400
+++ b/include/stuff/clientutil.h	Thu Oct 07 16:31:41 2010 -0400
@@ -6,7 +6,7 @@
 #  define CLIENTEXTERN extern
 #endif
 
-char*	readctl(char*);
+char*	readctl(char*, char*);
 void	client_init(char*);
 
 CLIENTEXTERN IxpClient*	client;
diff -r e638d4f40d56 -r 3a09477a41ff include/stuff/geom.h
--- a/include/stuff/geom.h	Thu Oct 07 16:31:38 2010 -0400
+++ b/include/stuff/geom.h	Thu Oct 07 16:31:41 2010 -0400
@@ -30,8 +30,8 @@
 #define Dx(r) ((r).max.x - (r).min.x)
 #define Dy(r) ((r).max.y - (r).min.y)
 #define Pt(x, y) ((Point){(x), (y)})
-#define Rpt(p, q) ((Rectangle){p, q})
-#define Rect(x0, y0, x1, y1) ((Rectangle){Pt(x0, y0), Pt(x1, y1)})
+#define Rpt(p, q) ((Rectangle){(p), (q)})
+#define Rect(x0, y0, x1, y1) Rpt(Pt(x0, y0), Pt(x1, y1))
 
 Point		addpt(Point, Point);
 Point		divpt(Point, Point);
diff -r e638d4f40d56 -r 3a09477a41ff include/stuff/util.h
--- a/include/stuff/util.h	Thu Oct 07 16:31:38 2010 -0400
+++ b/include/stuff/util.h	Thu Oct 07 16:31:41 2010 -0400
@@ -42,13 +42,10 @@
 
 int	Blprint(Biobuf*, const char*, ...);
 int	Bvlprint(Biobuf*, const char*, va_list);
-extern char*	_buffer;
 void	_die(char*, int, char*, ...);
 void	backtrace(char*);
-extern char	buffer[8092];
 void	closeexec(int);
 char**	comm(int, char**, char**);
-extern char*	const _buf_end;
 int	doublefork(void);
 void*	emalloc(uint);
 void*	emallocz(uint);
@@ -90,6 +87,10 @@
 int	utflcpy(char*, const char*, int);
 int	vlprint(int, const char*, va_list);
 char*	vsxprint(const char*, va_list);
+
+extern char*	_buffer;
+extern char	buffer[8092];
+extern char*	const _buf_end;
 #define bufclear() \
         BLOCK( _buffer = buffer; _buffer[0] = '\0' )
 #define bufprint(...) \
diff -r e638d4f40d56 -r 3a09477a41ff include/stuff/x11.h
--- a/include/stuff/x11.h	Thu Oct 07 16:31:38 2010 -0400
+++ b/include/stuff/x11.h	Thu Oct 07 16:31:41 2010 -0400
@@ -261,6 +261,7 @@
 uint	drawstring(Image*, Font*, Rectangle, Align, const char*, Color*);
 void	fill(Image*, Rectangle, Color*);
 void	fillpoly(Image*, Point*, int, Color*);
+uint	fillstring(Image*, Font*, Rectangle, Align, const char*, CTuple*, int border);
 Window*	findwin(XWindow);
 void	freefont(Font*);
 void	freeimage(Image *);
diff -r e638d4f40d56 -r 3a09477a41ff lib/libstuff/client_readconfig.c
--- a/lib/libstuff/client_readconfig.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/lib/libstuff/client_readconfig.c	Thu Oct 07 16:31:41 2010 -0400
@@ -11,13 +11,13 @@
 client_readconfig(CTuple *norm, CTuple *focus, Font **font) {
 
         if(norm)
-		loadcolor(norm, readctl("normcolors "), nil);
+		loadcolor(norm, readctl("/ctl", "normcolors "), nil);
         if(focus)
-		loadcolor(focus, readctl("focuscolors "), nil);
-	*font = loadfont(readctl("font "));
+		loadcolor(focus, readctl("/ctl", "focuscolors "), nil);
+	*font = loadfont(readctl("/ctl", "font "));
         if(!*font)
-		fatal("Can't load font %q", readctl("font "));
-	sscanf(readctl("fontpad "), "%d %d %d %d",
+		fatal("Can't load font %q", readctl("/ctl", "font "));
+	sscanf(readctl("/ctl", "fontpad "), "%d %d %d %d",
                &(*font)->pad.min.x, &(*font)->pad.max.x,
                &(*font)->pad.min.x, &(*font)->pad.max.y);
 }
diff -r e638d4f40d56 -r 3a09477a41ff lib/libstuff/clientutil.c
--- a/lib/libstuff/clientutil.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/lib/libstuff/clientutil.c	Thu Oct 07 16:31:41 2010 -0400
@@ -10,20 +10,21 @@
 #include <stuff/clientutil.h>
 #include <stuff/util.h>
 
-static IxpCFid*	ctlfid;
-static char 	ctl[1024];
-static char*	ectl;
-
 char*
-readctl(char *key) {
+readctl(char *ctlname, char *key) {
+	static char	ctlfile[128];
+	static char 	ctl[1024];
+	static char*	ectl;
+	IxpCFid *fid;
         char *s, *p;
         int nkey, n;
 
-	if(ctlfid == nil) {
-		ctlfid = ixp_open(client, "ctl", OREAD);
-		n = ixp_read(ctlfid, ctl, 1023);
+	if(strcmp(ctlname, ctlfile)) {
+		strncpy(ctlfile, ctlname, sizeof ctlfile);
+		fid = ixp_open(client, ctlfile, OREAD);
+		n = ixp_read(fid, ctl, sizeof ctl - 1);
                 ectl = ctl + n;
-		ixp_close(ctlfid);
+		ixp_close(fid);
         }
 
         nkey = strlen(key);
@@ -36,7 +37,7 @@
                         n = (s ? s : ectl) - p;
                         s = freelater(emalloc(n + 1));
                         s[n] = '\0';
-			return strncpy(s, p, n);
+			return memcpy(s, p, n);
                 }
         } while((p = strchr(p, '\n')));
         return "";
diff -r e638d4f40d56 -r 3a09477a41ff lib/libstuff/x11/drawing/drawstring.c
--- a/lib/libstuff/x11/drawing/drawstring.c	Thu Oct 07 16:31:38 2010 -0400
+++ b/lib/libstuff/x11/drawing/drawstring.c	Thu Oct 07 16:31:41 2010 -0400
@@ -5,6 +5,17 @@
 #include "../x11.h"
 
 uint
+fillstring(Image *dst, Font *font,
+	   Rectangle r, Align align,
+	   const char *text, CTuple *col, int borderw) {
+
+	fill(dst, r, &col->bg);
+	if(borderw)
+		border(dst, r, borderw, &col->border);
+	return drawstring(dst, font, r, align, text, &col->fg);
+}
+
+uint
 drawstring(Image *dst, Font *font,
            Rectangle r, Align align,
            const char *text, Color *col) {
diff -r e638d4f40d56 -r 3a09477a41ff mk/common.mk
--- a/mk/common.mk	Thu Oct 07 16:31:38 2010 -0400
+++ b/mk/common.mk	Thu Oct 07 16:31:41 2010 -0400
@@ -41,8 +41,8 @@
         for f in $(OBJ); do \
                 [ -f "$$f.c" ] && files="$$files $$f.c"; \
         done; \
-	echo CTAGS $$files $(TAGFILES) || \
-	ctags $$files $(TAGFILES)
+	echo CTAGS $$files $(TAGFILES); \
+	$(DEBUG) $(CTAGS) $$files $(TAGFILES)
 
 .PHONY: all options clean dist install uninstall depend cleandep tags
 .PHONY: simpleuninstall simpleinstall
diff -r e638d4f40d56 -r 3a09477a41ff util/compile
--- a/util/compile	Thu Oct 07 16:31:38 2010 -0400
+++ b/util/compile	Thu Oct 07 16:31:41 2010 -0400
@@ -49,7 +49,7 @@
                 nl=0
                 maxl=6
         }
-	/: (error|note): .?Each undeclared identifier|: error: for each function it appears|is dangerous, better use|is almost always misused|: In function |: At top level:|support .long long.|use of C99 long long|ISO C forbids conversion|warning:.*warn_unused_result/ {
+	tolower($0) ~ /: (error|note): .?each undeclared identifier|: error: for each function it appears|is dangerous, better use|is almost always misused|: in function |: at top level:|support .long long.|use of c99 long long|iso c forbids conversion|warning:.*warn_unused_result/ {
                 next
         }
         $1 == "warning:" {
Received on Fri Oct 08 2010 - 20:41:49 CEST
This archive was generated by hypermail 2.2.0 : Fri Oct 08 2010 - 20:48:04 CEST