diff -u dmenu-3.9/config.h dmenu-3.9-fresch/config.h
--- dmenu-3.9/config.h	2008-10-05 02:42:26.000000000 +0200
+++ dmenu-3.9-fresch/config.h	2008-10-05 03:23:14.000000000 +0200
@@ -6,4 +6,7 @@
 static const char *normfgcolor = "#000000";
 static const char *selbgcolor  = "#0066ff";
 static const char *selfgcolor  = "#ffffff";
+static const char *lastbgcolor = "#cccccc";
+static const char *lastfgcolor = "#000000";
 static unsigned int spaceitem  = 30; /* px between menu items */
+static unsigned int maxtokens  = 16; /* max. tokens for pattern matching */
diff -u dmenu-3.9/config.mk dmenu-3.9-fresch/config.mk
--- dmenu-3.9/config.mk	2008-10-05 02:42:26.000000000 +0200
+++ dmenu-3.9-fresch/config.mk	2008-10-05 03:23:14.000000000 +0200
@@ -1,5 +1,5 @@
 # dmenu version
-VERSION = 3.9
+VERSION = 3.9-vertical
 
 # Customize below to fit your system
 
diff -u dmenu-3.9/dmenu.1 dmenu-3.9-fresch/dmenu.1
--- dmenu-3.9/dmenu.1	2008-10-05 02:42:26.000000000 +0200
+++ dmenu-3.9-fresch/dmenu.1	2008-10-05 03:23:14.000000000 +0200
@@ -5,12 +5,27 @@
 .B dmenu
 .RB [ \-i ]
 .RB [ \-b ]
+.RB [ \-r ]
+.RB [ \-x " <xoffset>"]
+.RB [ \-y " <yoffset>"]
+.RB [ \-w " <width>"]
 .RB [ \-fn " <font>"]
 .RB [ \-nb " <color>"]
 .RB [ \-nf " <color>"]
 .RB [ \-p " <prompt>"]
 .RB [ \-sb " <color>"]
 .RB [ \-sf " <color>"]
+.RB [ \-l " <#items>"]
+.RB [ \-h " <height>"]
+.RB [ \-c ]
+.RB [ \-ms ]
+.RB [ \-ml ]
+.RB [ \-lb " <color>"]
+.RB [ \-lf " <color>"]
+.RB [ \-rs ]
+.RB [ \-ni ]
+.RB [ \-nl ]
+.RB [ \-xs ]
 .RB [ \-v ]
 .SH DESCRIPTION
 .SS Overview
@@ -26,6 +41,18 @@
 .B \-b
 defines that dmenu appears at the bottom.
 .TP
+.B \-r
+defines that dmenu appears on the right.
+.TP
+.B \-x
+defines distance to left or right side of the screen, depends on -r.
+.TP
+.B \-y
+defines distance to top or bottom of the screen, depends on -b.
+.TP
+.B \-w
+defines the window width.
+.TP
 .B \-fn <font>
 defines the font.
 .TP
@@ -44,8 +71,47 @@
 .B \-sf <color>
 defines the selected foreground color (#RGB, #RRGGBB, and color names are supported).
 .TP
+.B \-nl
+seperates standard output by newlines.
+.TP
+.B \-xs
+xmms-like pattern matching.
+.TP
 .B \-v
 prints version information to standard output, then exits.
+.SS Vertical Mode Options
+.TP
+.B \-l <#items>
+activates vertical list mode.
+window-size will be adjusted for displaying the given number of items.
+.TP
+.B \-h
+activates vertical list mode and defines the window height.
+don't expect exact results. given height is used to calculate
+#items. gets overridden by -l.
+.TP
+.B \-c
+displays a counter showing hits on applied filter.
+.TP
+.B \-ms
+multi-select; selecting an item and pressing return won't terminate dmenu.
+.TP
+.B \-ml
+marks last selected item using the colors defined with -lb and -lf.
+only useful when used with -ms.
+.TP
+.B \-lb <color>
+defines the last-selected background color (#RGB, #RRGGBB, and color names are supported).
+.TP
+.B \-lf <color>
+defines the last-selected foreground color (#RGB, #RRGGBB, and color names are supported).
+.TP
+.B \-rs
+resize; adjust window-size for displaying the matching items.
+-l or -h define the maximum.
+.TP
+.B \-ni
+don't display indicators.
 .SH USAGE
 dmenu reads a list of newline-separated items from standard input and creates a
 menu.  When the user selects an item or enters any text and presses Return, his/her
diff -u dmenu-3.9/dmenu.c dmenu-3.9-fresch/dmenu.c
--- dmenu-3.9/dmenu.c	2008-10-05 02:42:26.000000000 +0200
+++ dmenu-3.9-fresch/dmenu.c	2008-10-05 03:23:14.000000000 +0200
@@ -28,6 +28,7 @@
 	int x, y, w, h;
 	unsigned long norm[ColLast];
 	unsigned long sel[ColLast];
+	unsigned long last[ColLast];
 	Drawable drawable;
 	GC gc;
 	struct {
@@ -48,20 +49,23 @@
 
 /* forward declarations */
 static void appenditem(Item *i, Item **list, Item **last);
-static void calcoffsets(void);
+static void calcoffsetsh(void);
+static void calcoffsetsv(void);
 static char *cistrstr(const char *s, const char *sub);
 static void cleanup(void);
-static void drawmenu(void);
+static void drawmenuh(void);
+static void drawmenuv(void);
 static void drawtext(const char *text, unsigned long col[ColLast]);
 static void eprint(const char *errstr, ...);
 static unsigned long getcolor(const char *colstr);
 static Bool grabkeyboard(void);
 static void initfont(const char *fontstr);
 static void kpress(XKeyEvent * e);
+static void resizewindow(void);
 static void match(char *pattern);
 static void readstdin(void);
 static void run(void);
-static void setup(Bool topbar);
+static void setup(void);
 static int textnw(const char *text, unsigned int len);
 static int textw(const char *text);
 
@@ -70,14 +74,34 @@
 /* variables */
 static char *maxname = NULL;
 static char *prompt = NULL;
+static char *lastitem = NULL; 
+static char *nl = "";
+static char **tokens = NULL;
 static char text[4096];
+static char hitstxt[16];
 static int cmdw = 0;
 static int promptw = 0;
 static int ret = 0;
 static int screen;
+static int x, y;
 static unsigned int mw, mh;
 static unsigned int numlockmask = 0;
+static unsigned int hits = 0;
+static unsigned int lines = 0;
+static unsigned int xoffset = 0;
+static unsigned int yoffset = 0;
+static unsigned int width = 0;
+static unsigned int height = 0;
 static Bool running = True;
+static Bool topbar = True;
+static Bool vlist = False;
+static Bool hitcounter = False;
+static Bool alignright = False;
+static Bool multiselect = False;
+static Bool resize = False;
+static Bool marklastitem = False;
+static Bool indicators = True;
+static Bool xmms = False;
 static Display *dpy;
 static DC dc;
 static Item *allitems = NULL;	/* first of all items */
@@ -89,6 +113,8 @@
 static Window root, win;
 static int (*fstrncmp)(const char *, const char *, size_t n) = strncmp;
 static char *(*fstrstr)(const char *, const char *) = strstr;
+static void (*calcoffsets)(void) = calcoffsetsh;
+static void (*drawmenu)(void) = drawmenuh;
 
 void
 appenditem(Item *i, Item **list, Item **last) {
@@ -99,12 +125,13 @@
 	i->left = *last;
 	i->right = NULL;
 	*last = i;
+	++hits;
 }
 
 void
-calcoffsets(void) {
-	int tw;
-	unsigned int w;
+calcoffsetsh(void) {
+	static int tw;
+	static unsigned int w;
 
 	if(!curr)
 		return;
@@ -128,6 +155,26 @@
 	}
 }
 
+void
+calcoffsetsv(void) {
+	static unsigned int w;
+
+	if(!curr)
+		return;
+	w = (dc.font.height + 2) * (lines + 1);
+	for(next = curr; next; next=next->right) {
+		w -= dc.font.height + 2;
+		if(w <= 0)
+			break;
+	}
+	w = (dc.font.height + 2) * (lines + 1);
+	for(prev = curr; prev && prev->left; prev=prev->left) {
+		w -= dc.font.height + 2;
+		if(w <= 0)
+			break;
+	}
+}
+
 char *
 cistrstr(const char *s, const char *sub) {
 	int c, csub;
@@ -169,11 +216,12 @@
 	XFreeGC(dpy, dc.gc);
 	XDestroyWindow(dpy, win);
 	XUngrabKeyboard(dpy, CurrentTime);
+	free(tokens);
 }
 
 void
-drawmenu(void) {
-	Item *i;
+drawmenuh(void) {
+	static Item *i;
 
 	dc.x = 0;
 	dc.y = 0;
@@ -213,6 +261,87 @@
 }
 
 void
+drawmenuv(void) {
+	static Item *i;
+
+	dc.x = 0;
+	dc.y = 0;
+	dc.h = mh;
+	drawtext(NULL, dc.norm);
+	/* print prompt? */
+	if(promptw) {
+		dc.w = promptw;
+		drawtext(prompt, dc.sel);
+	}
+	dc.x += promptw;
+	dc.w = mw - promptw - (hitcounter ? textnw(hitstxt, strlen(hitstxt)) : 0);
+
+	drawtext(text[0] ? text : NULL, dc.norm);
+	if(curr) {
+		if (hitcounter) {
+			dc.w = textw(hitstxt);
+			dc.x = mw - textw(hitstxt);
+			drawtext(hitstxt, dc.norm);
+		}
+		dc.x = 0;
+		dc.w = mw;
+		if (indicators) {	
+			dc.y += dc.font.height + 2;
+			drawtext((curr && curr->left) ? "^" : NULL, dc.norm);
+		}
+		dc.y += dc.font.height + 2;
+		/* determine maximum items */
+		for(i = curr; i != next; i=i->right) {
+			if((sel != i) && marklastitem && lastitem && !strncmp(lastitem, i->text, strlen(i->text)))
+				drawtext(i->text, dc.last);
+			else
+				drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
+			dc.y += dc.font.height + 2;
+		}
+		drawtext(indicators && next ? "v" : NULL, dc.norm);
+	} else {
+		if (hitcounter) {
+			dc.w = textw(hitstxt);
+			dc.x = mw - textw(hitstxt);
+			dc.y = 0;
+			drawtext(hitstxt, dc.norm);
+		}
+		dc.x = 0;
+		dc.w = mw;
+		dc.h = mh;
+		dc.y += dc.font.height + 2;
+		drawtext(NULL, dc.norm);
+	} 
+	XCopyArea(dpy, dc.drawable, win, dc.gc, 0, 0, mw, mh, 0, 0);
+	XFlush(dpy);
+}
+
+void
+updatemenuv(Bool updown) {
+	static Item *i;
+	
+	if(curr) {
+		dc.x = 0;
+		dc.y = (dc.font.height + 2) * (indicators?2:1);
+		dc.w = mw;
+		dc.h = mh;
+		for(i = curr; i != next; i = i->right) {
+			if(((i == sel->left) && !updown) || (i == sel)
+			||((i == sel->right) && updown)) {
+				if((sel != i) && marklastitem && lastitem && !strncmp(lastitem, i->text, strlen(i->text)))
+					drawtext(i->text, dc.last);
+				else
+					drawtext(i->text, (sel == i) ? dc.sel : dc.norm);
+				XCopyArea(dpy, dc.drawable, win, dc.gc, dc.x, dc.y,
+					dc.w, dc.font.height + 2, dc.x, dc.y);
+			}
+			dc.y += dc.font.height + 2;
+		}
+	}			
+	XFlush(dpy);
+}
+
+void
 drawtext(const char *text, unsigned long col[ColLast]) {
 	char buf[256];
 	int i, x, y, h, len, olen;
@@ -223,8 +352,8 @@
 	if(!text)
 		return;
 	olen = strlen(text);
-	h = dc.font.ascent + dc.font.descent;
-	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
+	h = dc.font.height;
+	y = dc.y + ((h + 2) / 2) - (h / 2) + dc.font.ascent;
 	x = dc.x + (h / 2);
 	/* shorten text if necessary */
 	for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
@@ -430,12 +559,21 @@
 		calcoffsets();
 		break;
 	case XK_Left:
+	case XK_Up:
 		if(!(sel && sel->left))
 			return;
 		sel=sel->left;
 		if(sel->right == curr) {
-			curr = prev;
+			if (vlist)
+				curr = curr->left;
+			else
+				curr = prev;
 			calcoffsets();
+		} else {
+			if (vlist) {
+				updatemenuv(True);
+				return;
+			}
 		}
 		break;
 	case XK_Next:
@@ -452,21 +590,32 @@
 		break;
 	case XK_Return:
 		if((e->state & ShiftMask) && *text)
-			fprintf(stdout, "%s", text);
-		else if(sel)
-			fprintf(stdout, "%s", sel->text);
+			fprintf(stdout, "%s%s", text, nl);
+		else if(sel) {
+			fprintf(stdout, "%s%s", sel->text, nl);
+			lastitem = sel->text;
+		}
 		else if(*text)
-			fprintf(stdout, "%s", text);
+			fprintf(stdout, "%s%s", text, nl);
 		fflush(stdout);
-		running = False;
+		running = multiselect;
 		break;
 	case XK_Right:
+	case XK_Down:
 		if(!(sel && sel->right))
 			return;
 		sel=sel->right;
 		if(sel == next) {
-			curr = next;
+			if (vlist)
+				curr = curr->right;
+			else
+				curr = next;
 			calcoffsets();
+		} else {
+			if (vlist) {
+				updatemenuv(False);
+				return;
+			}
 		}
 		break;
 	case XK_Tab:
@@ -479,22 +628,68 @@
 	drawmenu();
 }
 
+void resizewindow(void)
+{
+	if (resize) {
+		static int rlines, ry, rmh;
+
+		rlines = (hits > lines ? lines : hits) + (indicators?3:1);
+		rmh = vlist ? (dc.font.height + 2) * rlines : mh;
+		ry = topbar ? y + yoffset : y - rmh + (dc.font.height + 2) - yoffset;
+		XMoveResizeWindow(dpy, win, x, ry, mw, rmh);
+	}
+}
+
+unsigned int tokenize(char *pat, char **tok)
+{
+	unsigned int i = 0;
+	char tmp[4096] = {0};
+
+	strncpy(tmp, pat, strlen(pat));
+	tok[0] = strtok(tmp, " ");
+
+	while(tok[i] && i < maxtokens)
+		tok[++i] = strtok(NULL, " ");
+	return i;
+}
+
 void
 match(char *pattern) {
-	unsigned int plen;
+	unsigned int plen, tokencnt = 0;
+	char append = 0;
 	Item *i, *itemend, *lexact, *lprefix, *lsubstr, *exactend, *prefixend, *substrend;
 
 	if(!pattern)
 		return;
-	plen = strlen(pattern);
+
+	if(!xmms)
+		tokens[(tokencnt = 1)-1] = pattern;
+	else
+		if(!(tokencnt = tokenize(pattern, tokens)))
+			tokens[(tokencnt = 1)-1] = "";
+
 	item = lexact = lprefix = lsubstr = itemend = exactend = prefixend = substrend = NULL;
-	for(i = allitems; i; i = i->next)
-		if(!fstrncmp(pattern, i->text, plen + 1))
+	for(i = allitems; i; i = i->next) {
+		for(int j = 0; j < tokencnt; ++j) {
+			plen = strlen(tokens[j]);
+			if(!fstrncmp(tokens[j], i->text, plen + 1))
+				append = !append || append > 1 ? 1 : append;
+			else if(!fstrncmp(tokens[j], i->text, plen ))
+				append = !append || append > 2 ? 2 : append;
+			else if(fstrstr(i->text, tokens[j]))
+				append = append > 0 && append < 3 ? append : 3;
+			else {
+				append = 0;
+				break;
+			}
+		}
+		if(append == 1)
 			appenditem(i, &lexact, &exactend);
-		else if(!fstrncmp(pattern, i->text, plen))
+		else if(append == 2)
 			appenditem(i, &lprefix, &prefixend);
-		else if(fstrstr(i->text, pattern))
+		else if(append == 3)
 			appenditem(i, &lsubstr, &substrend);
+	}
 	if(lexact) {
 		item = lexact;
 		itemend = exactend;
@@ -518,6 +713,9 @@
 	}
 	curr = prev = next = sel = item;
 	calcoffsets();
+	resizewindow();
+	snprintf(hitstxt, sizeof(hitstxt), "(%d)", hits);
+	hits = 0;
 }
 
 void
@@ -569,8 +767,8 @@
 }
 
 void
-setup(Bool topbar) {
-	int i, j, x, y;
+setup(void) {
+	int i, j, sy, slines;
 #if XINERAMA
 	int n;
 	XineramaScreenInfo *info = NULL;
@@ -593,6 +791,8 @@
 	dc.norm[ColFG] = getcolor(normfgcolor);
 	dc.sel[ColBG] = getcolor(selbgcolor);
 	dc.sel[ColFG] = getcolor(selfgcolor);
+	dc.last[ColBG] = getcolor(lastbgcolor);
+	dc.last[ColFG] = getcolor(lastfgcolor);
 	initfont(font);
 
 	/* menu window */
@@ -627,7 +827,15 @@
 		mw = DisplayWidth(dpy, screen);
 	}
 
-	win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
+	/* update menu window geometry */
+	
+	slines = (lines ? lines : (lines = height / (dc.font.height + 2))) + (indicators?3:1);
+	mh = vlist ? (dc.font.height + 2) * slines : mh;
+	sy = topbar ? y + yoffset : y - mh + (dc.font.height + 2) - yoffset;
+	x = alignright ? mw - (width ? width : mw) - xoffset : xoffset;
+	mw = width ? width : mw;
+
+	win = XCreateWindow(dpy, root, x, sy, mw, mh, 0,
 			DefaultDepth(dpy, screen), CopyFromParent,
 			DefaultVisual(dpy, screen),
 			CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
@@ -647,6 +855,7 @@
 	if(promptw > mw / 5)
 		promptw = mw / 5;
 	text[0] = 0;
+	tokens = malloc((xmms?maxtokens:1)*sizeof(char*));
 	match(text);
 	XMapRaised(dpy, win);
 }
@@ -670,7 +879,6 @@
 int
 main(int argc, char *argv[]) {
 	unsigned int i;
-	Bool topbar = True;
 
 	/* command line args */
 	for(i = 1; i < argc; i++)
@@ -680,6 +888,16 @@
 		}
 		else if(!strcmp(argv[i], "-b"))
 			topbar = False;
+		else if(!strcmp(argv[i], "-r"))
+			alignright = True;
+		else if(!strcmp(argv[i], "-l")) {
+			vlist = True;
+			calcoffsets = calcoffsetsv;
+			drawmenu = drawmenuv;
+			if(++i < argc) lines += atoi(argv[i]);
+		}
+		else if(!strcmp(argv[i], "-c"))
+			hitcounter = True;
 		else if(!strcmp(argv[i], "-fn")) {
 			if(++i < argc) font = argv[i];
 		}
@@ -698,11 +916,47 @@
 		else if(!strcmp(argv[i], "-sf")) {
 			if(++i < argc) selfgcolor = argv[i];
 		}
+		else if(!strcmp(argv[i], "-lb")) {
+			if(++i < argc) lastbgcolor = argv[i];
+		}
+		else if(!strcmp(argv[i], "-lf")) {
+			if(++i < argc) lastfgcolor = argv[i];
+		}
+		else if(!strcmp(argv[i], "-w")) {
+			if(++i < argc) width = atoi(argv[i]);
+		}
+		else if(!strcmp(argv[i], "-h")) {
+			vlist = True;
+			calcoffsets = calcoffsetsv;
+			drawmenu = drawmenuv;
+			if(++i < argc) height = atoi(argv[i]);
+		}
+		else if(!strcmp(argv[i], "-x")) {
+			if(++i < argc) xoffset = atoi(argv[i]);
+		}
+		else if(!strcmp(argv[i], "-y")) {
+			if(++i < argc) yoffset = atoi(argv[i]);
+		}
+		else if(!strcmp(argv[i], "-nl"))
+			nl = "\n";
+		else if(!strcmp(argv[i], "-rs"))
+			resize = True;
+		else if(!strcmp(argv[i], "-ms"))
+			multiselect = True;
+		else if(!strcmp(argv[i], "-ml"))
+			marklastitem = True;
+		else if(!strcmp(argv[i], "-ni"))
+			indicators = False;
+		else if(!strcmp(argv[i], "-xs"))
+			xmms = True;
 		else if(!strcmp(argv[i], "-v"))
 			eprint("dmenu-"VERSION", © 2006-2008 dmenu engineers, see LICENSE for details\n");
 		else
-			eprint("usage: dmenu [-i] [-b] [-fn <font>] [-nb <color>] [-nf <color>]\n"
-			       "             [-p <prompt>] [-sb <color>] [-sf <color>] [-v]\n");
+			eprint("usage: dmenu [-i] [-b] [-r] [-x <xoffset> [-y <yoffset>] [-w <width]\n"
+			       "[-fn <font>] [-nb <color>] [-nf <color>] [-p <prompt>] [-sb <color>]\n"
+			       "[-sf <color>] [-l <#items>] [-h <height>] [-c] [-ms]\n"
+			       "[-ml] [-lb <color>] [-lf <color>] [-rs] [-ni] [-nl] [-xs] [-v]\n");
+
 	if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
 		fprintf(stderr, "warning: no locale support\n");
 	if(!(dpy = XOpenDisplay(0)))
@@ -718,8 +972,8 @@
 		running = grabkeyboard();
 		readstdin();
 	}
-
-	setup(topbar);
+	
+	setup();
 	drawmenu();
 	XSync(dpy, False);
 	run();

