[wiki] [sites] wiki updated

From: <hg_AT_suckless.org>
Date: Fri, 11 Jun 2010 14:47:44 +0000 (UTC)

changeset: 551:6a5aff2c4bb5
tag: tip
user: joten <joten_AT_freenet.de>
date: Fri Jun 11 16:47:32 2010 +0200
files: dwm.suckless.org/patches/flextile-5.8-100510.diff dwm.suckless.org/patches/flextile-5.8.2.diff dwm.suckless.org/patches/flextile.md dwm.suckless.org/patches/keymodes-5.8.2-vim.diff dwm.suckless.org/patches/keymodes-5.8.2.diff dwm.suckless.org/patches/keymodes.md
description:
updated 'flextile' patch and added 'keymode' patch


diff -r 48e2029f6d04 -r 6a5aff2c4bb5 dwm.suckless.org/patches/flextile-5.8-100510.diff
--- a/dwm.suckless.org/patches/flextile-5.8-100510.diff Fri Jun 11 08:39:06 2010 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
_AT_@ -1,384 +0,0 @@
-diff -up ../dwm-5.8-100510/config.def.h ./config.def.h
---- ../dwm-5.8-100510/config.def.h 2010-05-10 18:33:23.597215039 +0200
-+++ ./config.def.h 2010-05-10 18:02:21.014900822 +0200
-_AT_@ -25,6 +25,12 @@ static const Rule rules[] = {
- /* layout(s) */
- static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
- static const Bool resizehints = True; /* True means respect size hints in tiled resizals */
-+static const int layoutaxis[] = {
-+ 1, /* layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top */
-+ 2, /* master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */
-+ 2, /* stack axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */
-+};
-+static const unsigned int mastersplit = 1; /* number of tiled clients in the master area */
-
- static const Layout layouts[] = {
- /* symbol arrange function */
-_AT_@ -81,6 +87,12 @@ static Key keys[] = {
- TAGKEYS( XK_8, 7)
- TAGKEYS( XK_9, 8)
- { MODKEY|ShiftMask, XK_q, quit, {0} },
-+ { MODKEY|ControlMask, XK_t, rotatelayoutaxis, {.i = 0} }, /* 0 = layout axis */
-+ { MODKEY|ControlMask, XK_Tab, rotatelayoutaxis, {.i = 1} }, /* 1 = master axis */
-+ { MODKEY|ControlMask|ShiftMask, XK_Tab, rotatelayoutaxis, {.i = 2} }, /* 2 = stack axis */
-+ { MODKEY|ControlMask, XK_Return, mirrorlayout, {0} },
-+ { MODKEY|ControlMask, XK_j, shiftmastersplit, {.i = -1} },
-+ { MODKEY|ControlMask, XK_k, shiftmastersplit, {.i = +1} },
- };
-
- /* button definitions */
-diff -up ../dwm-5.8-100510/dwm.c ./dwm.c
---- ../dwm-5.8-100510/dwm.c 2010-05-10 18:33:23.623877306 +0200
-+++ ./dwm.c 2010-05-10 18:40:00.117209357 +0200
-_AT_@ -121,26 +121,6 @@ typedef struct {
- void (*arrange)(Monitor *);
- } Layout;
-
--struct Monitor {
-- char ltsymbol[16];
-- float mfact;
-- int num;
-- int by; /* bar geometry */
-- int mx, my, mw, mh; /* screen size */
-- int wx, wy, ww, wh; /* window area */
-- unsigned int seltags;
-- unsigned int sellt;
-- unsigned int tagset[2];
-- Bool showbar;
-- Bool topbar;
-- Client *clients;
-- Client *sel;
-- Client *stack;
-- Monitor *next;
-- Window barwin;
-- const Layout *lt[2];
--};
--
- typedef struct {
- 	const char *class;
- 	const char *instance;
-_AT_@ -239,6 +219,9 @@ static int xerror(Display *dpy, XErrorEv
- static int xerrordummy(Display *dpy, XErrorEvent *ee);
- static int xerrorstart(Display *dpy, XErrorEvent *ee);
- static void zoom(const Arg *arg);
-+static void mirrorlayout(const Arg *arg);
-+static void rotatelayoutaxis(const Arg *arg);
-+static void shiftmastersplit(const Arg *arg);
- 
- /* variables */
- static const char broken[] = "broken";
-_AT_@ -276,6 +259,34 @@ static Window root;
- 
- /* compile-time check if all tags fit into an unsigned int bit array. */
- struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
-+struct Monitor {
-+	char ltsymbol[16];
-+	float mfact;
-+	int num;
-+	int by;               /* bar geometry */
-+	int mx, my, mw, mh;   /* screen size */
-+	int wx, wy, ww, wh;   /* window area  */
-+	unsigned int seltags;
-+	unsigned int sellt;
-+	unsigned int tagset[2];
-+	Bool showbar;
-+	Bool topbar;
-+	Client *clients;
-+	Client *sel;
-+	Client *stack;
-+	Monitor *next;
-+	Window barwin;
-+	const Layout *lt[2];
-+	int curtag;
-+	int prevtag;
-+	const Layout *lts[LENGTH(tags) + 1];
-+	double mfacts[LENGTH(tags) + 1];
-+	Bool showbars[LENGTH(tags) + 1];
-+	int ltaxis[3];
-+	unsigned int msplit;
-+	int ltaxes[LENGTH(tags) + 1][3];
-+	unsigned int msplits[LENGTH(tags) + 1];
-+};
- 
- /* function implementations */
- void
-_AT_@ -617,6 +628,10 @@ createmon(void) {
- 	m->lt[0] = &layouts[0];
- 	m->lt[1] = &layouts[1 % LENGTH(layouts)];
- 	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
-+	m->ltaxis[0] = layoutaxis[0];
-+	m->ltaxis[1] = layoutaxis[1];
-+	m->ltaxis[2] = layoutaxis[2];
-+	m->msplit = mastersplit;
- 	return m;
- }
- 
-_AT_@ -1467,7 +1482,7 @@ setlayout(const Arg *arg) {
- 	if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
- 		selmon->sellt ^= 1;
- 	if(arg && arg->v)
--		selmon->lt[selmon->sellt] = (Layout *)arg->v;
-+		selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag] = (Layout *)arg->v;
- 	strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
- 	if(selmon->sel)
- 		arrange(selmon);
-_AT_@ -1485,14 +1500,16 @@ setmfact(const Arg *arg) {
- 	f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
- 	if(f < 0.1 || f > 0.9)
- 		return;
--	selmon->mfact = f;
-+	selmon->mfact = selmon->mfacts[selmon->curtag] = f;
- 	arrange(selmon);
- }
- 
- void
- setup(void) {
- 	XSetWindowAttributes wa;
--
-+	Monitor *m;
-+	unsigned int i;
-+ 
- 	/* clean up any zombies immediately */
- 	sigchld(0);
- 
-_AT_@ -1526,7 +1543,19 @@ setup(void) {
- 	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
- 	if(!dc.font.set)
- 		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
--	/* init bars */
-+	/* init tags, bars, layouts, axes, msplits and mfacts */
-+	for(m = mons; m; m = m->next) {
-+		m->curtag = m->prevtag = 1;
-+		for(i=0; i < LENGTH(tags) + 1; i++) {
-+			m->showbars[i] = m->showbar;
-+			m->lts[i] = &layouts[0];
-+			m->mfacts[i] = m->mfact;
-+			m->ltaxes[i][0] = m->ltaxis[0];
-+			m->ltaxes[i][1] = m->ltaxis[1];
-+			m->ltaxes[i][2] = m->ltaxis[2];
-+			m->msplits[i] = m->msplit;
-+		}
-+	}
- 	updatebars();
- 	updatestatus();
- 	/* EWMH support per view */
-_AT_@ -1607,37 +1636,132 @@ textnw(const char *text, unsigned int le
- 
- void
- tile(Monitor *m) {
--	int x, y, h, w, mw;
--	unsigned int i, n;
-+	char sym1 = 61, sym2 = 93, sym3 = 61, sym;
-+	int x1 = m->wx, y1 = m->wy, h1 = m->wh, w1 = m->ww, X1 = x1 + w1, Y1 = y1 + h1;
-+	int x2 = m->wx, y2 = m->wy, h2 = m->wh, w2 = m->ww, X2 = x2 + w2, Y2 = y2 + h2;
-+	unsigned int i, n, n1, n2;
- 	Client *c;
- 
- 	for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
-+	if(m->msplit > n)
-+		m->msplit = (n == 0) ? 1 : n;
-+	if(n == 0 && m->ltaxis[1] != 3)
-+		return;
-+	/* layout symbol */
-+	if(abs(m->ltaxis[0]) == m->ltaxis[1])    /* explicitly: ((abs(m->ltaxis[0]) == 1 && m->ltaxis[1] == 1) || (abs(m->ltaxis[0]) == 2 && m->ltaxis[1] == 2)) */
-+		sym1 = 124;
-+	if(abs(m->ltaxis[0]) == m->ltaxis[2])
-+		sym3 = 124;
-+	if(m->ltaxis[1] == 3)
-+		sym1 = (n == 0) ? 0 : m->msplit;
-+	if(m->ltaxis[2] == 3)
-+		sym3 = (n == 0) ? 0 : n - m->msplit;
-+	if(m->ltaxis[0] < 0) {
-+		sym = sym1;
-+		sym1 = sym3;
-+		sym2 = 91;
-+		sym3 = sym;
-+	}
-+	if(m->msplit == 1) {
-+		if(m->ltaxis[0] > 0)
-+			sym1 = 91;
-+		else
-+			sym3 = 93;
-+	}
-+	if(m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[2] == 3)
-+		snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%d", sym1, sym2, sym3);
-+	else if((m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[0] > 0) || (m->ltaxis[2] == 3 && m->ltaxis[0] < 0))
-+		snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%c", sym1, sym2, sym3);
-+	else if((m->ltaxis[2] == 3 && m->ltaxis[0] > 0) || (m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[0] < 0))
-+		snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%d", sym1, sym2, sym3);
-+	else
-+		snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym1, sym2, sym3);
- 	if(n == 0)
- 		return;
-+	/* master and stack area */
-+	if(abs(m->ltaxis[0]) == 1 && n > m->msplit) {
-+		w1 *= m->mfact;
-+		w2 -= w1;
-+		x1 += (m->ltaxis[0] < 0) ? w2 : 0;
-+		x2 += (m->ltaxis[0] < 0) ? 0 : w1;
-+		X1 = x1 + w1;
-+		X2 = x2 + w2;
-+	} else if(abs(m->ltaxis[0]) == 2 && n > m->msplit) {
-+		h1 *= m->mfact;
-+		h2 -= h1;
-+		y1 += (m->ltaxis[0] < 0) ? h2 : 0;
-+		y2 += (m->ltaxis[0] < 0) ? 0 : h1;
-+		Y1 = y1 + h1;
-+		Y2 = y2 + h2;
-+	}
- 	/* master */
--	c = nexttiled(m->clients);
--	mw = m->mfact * m->ww;
--	resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False);
--	if(--n == 0)
--		return;
--	/* tile stack */
--	x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw;
--	y = m->wy;
--	w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw;
--	h = m->wh / n;
--	if(h < bh)
--		h = m->wh;
--	for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
--		resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n)
--		       ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False);
--		if(h != m->wh)
--			y = c->y + HEIGHT(c);
-+	n1 = (m->ltaxis[1] != 1 || w1 / m->msplit < bh) ? 1 : m->msplit;
-+	n2 = (m->ltaxis[1] != 2 || h1 / m->msplit < bh) ? 1 : m->msplit;
-+	for(i = 0, c = nexttiled(m->clients); i < m->msplit; c = nexttiled(c->next), i++) {
-+		resize(c, x1, y1, 
-+			(m->ltaxis[1] == 1 && i + 1 == m->msplit) ? X1 - x1 - 2 * c->bw : w1 / n1 - 2 * c->bw, 
-+			(m->ltaxis[1] == 2 && i + 1 == m->msplit) ? Y1 - y1 - 2 * c->bw : h1 / n2 - 2 * c->bw, False);
-+		if(n1 > 1)
-+			x1 = c->x + WIDTH(c);
-+		if(n2 > 1)
-+			y1 = c->y + HEIGHT(c);
-+	}
-+	/* stack */
-+	if(n > m->msplit) {
-+		n1 = (m->ltaxis[2] != 1 || w2 / (n - m->msplit) < bh) ? 1 : n - m->msplit;
-+		n2 = (m->ltaxis[2] != 2 || h2 / (n - m->msplit) < bh) ? 1 : n - m->msplit;
-+		for(i = 0; c; c = nexttiled(c->next), i++) {
-+			resize(c, x2, y2, 
-+				(m->ltaxis[2] == 1 && i + 1 == n - m->msplit) ? X2 - x2 - 2 * c->bw : w2 / n1 - 2 * c->bw, 
-+				(m->ltaxis[2] == 2 && i + 1 == n - m->msplit) ? Y2 - y2 - 2 * c->bw : h2 / n2 - 2 * c->bw, False);
-+			if(n1 > 1)
-+				x2 = c->x + WIDTH(c);
-+			if(n2 > 1)
-+				y2 = c->y + HEIGHT(c);
-+		}
- 	}
- }
- 
- void
-+mirrorlayout(const Arg *arg) {
-+	if(!selmon->lt[selmon->sellt]->arrange)
-+		return;
-+	selmon->ltaxis[0] *= -1;
-+	selmon->ltaxes[selmon->curtag][0] = selmon->ltaxis[0];
-+	arrange(selmon);
-+}
-+
-+void
-+rotatelayoutaxis(const Arg *arg) {
-+	if(!selmon->lt[selmon->sellt]->arrange)
-+		return;
-+	if(arg->i == 0) {
-+		if(selmon->ltaxis[0] > 0)
-+			selmon->ltaxis[0] = selmon->ltaxis[0] + 1 > 2 ? 1 : selmon->ltaxis[0] + 1;
-+		else
-+			selmon->ltaxis[0] = selmon->ltaxis[0] - 1 < -2 ? -1 : selmon->ltaxis[0] - 1;
-+	} else
-+		selmon->ltaxis[arg->i] = selmon->ltaxis[arg->i] + 1 > 3 ? 1 : selmon->ltaxis[arg->i] + 1;
-+	selmon->ltaxes[selmon->curtag][arg->i] = selmon->ltaxis[arg->i];
-+	arrange(selmon);
-+}
-+
-+void
-+shiftmastersplit(const Arg *arg) {
-+	unsigned int n;
-+	Client *c;
-+
-+	for(n = 0, c = nexttiled(selmon->clients); c; c = nexttiled(c->next), n++);
-+	if(!arg || !selmon->lt[selmon->sellt]->arrange || selmon->msplit + arg->i < 1 || selmon->msplit + arg->i > n)
-+		return;
-+	selmon->msplit += arg->i;
-+	selmon->msplits[selmon->curtag] = selmon->msplit;
-+	arrange(selmon);
-+}
-+
-+void
- togglebar(const Arg *arg) {
--	selmon->showbar = !selmon->showbar;
-+	selmon->showbar = selmon->showbars[selmon->curtag] = !selmon->showbar;
- 	updatebarpos(selmon);
- 	XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
- 	arrange(selmon);
-_AT_@ -1657,12 +1781,31 @@ togglefloating(const Arg *arg) {
- void
- toggletag(const Arg *arg) {
- 	unsigned int newtags;
-+	unsigned int i;
- 
- 	if(!selmon->sel)
- 		return;
- 	newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
- 	if(newtags) {
- 		selmon->sel->tags = newtags;
-+		if(newtags == ~0) {
-+			selmon->prevtag = selmon->curtag;
-+			selmon->curtag = 0;
-+		}
-+		if(!(newtags & 1 << (selmon->curtag - 1))) {
-+			selmon->prevtag = selmon->curtag;
-+			for (i=0; !(newtags & 1 << i); i++);
-+			selmon->curtag = i + 1;
-+		}
-+		selmon->sel->tags = newtags;
-+		selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag];
-+		selmon->mfact = selmon->mfacts[selmon->curtag];
-+		if (selmon->showbar != selmon->showbars[selmon->curtag])
-+			togglebar(NULL);
-+		selmon->ltaxis[0] = selmon->ltaxes[selmon->curtag][0];
-+		selmon->ltaxis[1] = selmon->ltaxes[selmon->curtag][1];
-+		selmon->ltaxis[2] = selmon->ltaxes[selmon->curtag][2];
-+		selmon->msplit = selmon->msplits[selmon->curtag];
- 		arrange(selmon);
- 	}
- }
-_AT_@ -1929,11 +2072,33 @@ updatewmhints(Client *c) {
- 
- void
- view(const Arg *arg) {
-+	unsigned int i;
-+
- 	if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
- 		return;
- 	selmon->seltags ^= 1; /* toggle sel tagset */
--	if(arg->ui & TAGMASK)
-+	if(arg->ui & TAGMASK) {
- 		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
-+		selmon->prevtag = selmon->curtag;
-+		if(arg->ui == ~0)
-+			selmon->curtag = 0;
-+		else {
-+			for (i=0; !(arg->ui & 1 << i); i++);
-+			selmon->curtag = i + 1;
-+		}
-+	} else {
-+		selmon->prevtag = selmon->curtag ^ selmon->prevtag;
-+		selmon->curtag ^= selmon->prevtag;
-+		selmon->prevtag = selmon->curtag ^ selmon->prevtag;
-+	}
-+	selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag];
-+	selmon->mfact = selmon->mfacts[selmon->curtag];
-+	if(selmon->showbar != selmon->showbars[selmon->curtag])
-+		togglebar(NULL);
-+	selmon->ltaxis[0] = selmon->ltaxes[selmon->curtag][0];
-+	selmon->ltaxis[1] = selmon->ltaxes[selmon->curtag][1];
-+	selmon->ltaxis[2] = selmon->ltaxes[selmon->curtag][2];
-+	selmon->msplit = selmon->msplits[selmon->curtag];
- 	arrange(selmon);
- }
- 
diff -r 48e2029f6d04 -r 6a5aff2c4bb5 dwm.suckless.org/patches/flextile-5.8.2.diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwm.suckless.org/patches/flextile-5.8.2.diff	Fri Jun 11 16:47:32 2010 +0200
_AT_@ -0,0 +1,398 @@
+diff -up ../dwm-5.8.2-0/config.def.h ./config.def.h
+--- ../dwm-5.8.2-0/config.def.h	2010-06-10 22:47:51.660949000 +0200
++++ ./config.def.h	2010-06-10 22:55:53.094322000 +0200
+_AT_@ -16,6 +16,9 @@ static const Bool topbar            = Tr
+ /* tagging */
+ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+ 
++/* include(s) depending on the tags array */
++#include "flextile.h"
++
+ static const Rule rules[] = {
+ 	/* class      instance    title       tags mask     isfloating   monitor */
+ 	{ "Gimp",     NULL,       NULL,       0,            True,        -1 },
+_AT_@ -25,6 +28,11 @@ static const Rule rules[] = {
+ /* layout(s) */
+ static const float mfact      = 0.55; /* factor of master area size [0.05..0.95] */
+ static const Bool resizehints = True; /* True means respect size hints in tiled resizals */
++static const int layoutaxis[] = {
++	1,    /* layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top */
++	2,    /* master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */
++	2,    /* stack axis:  1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */
++};
+ 
+ static const Layout layouts[] = {
+ 	/* symbol     arrange function */
+_AT_@ -81,6 +89,12 @@ static Key keys[] = {
+ 	TAGKEYS(                        XK_8,                      7)
+ 	TAGKEYS(                        XK_9,                      8)
+ 	{ MODKEY|ShiftMask,             XK_q,      quit,           {0} },
++	{ MODKEY|ControlMask,           XK_t,      rotatelayoutaxis, {.i = 0} },    /* 0 = layout axis */
++	{ MODKEY|ControlMask,           XK_Tab,    rotatelayoutaxis, {.i = 1} },    /* 1 = master axis */
++	{ MODKEY|ControlMask|ShiftMask, XK_Tab,    rotatelayoutaxis, {.i = 2} },    /* 2 = stack axis */
++	{ MODKEY|ControlMask,           XK_Return, mirrorlayout,     {0} },
++	{ MODKEY|ControlMask,           XK_h,      shiftmastersplit, {.i = -1} },   /* reduce the number of tiled clients in the master area */
++	{ MODKEY|ControlMask,           XK_l,      shiftmastersplit, {.i = +1} },   /* increase the number of tiled clients in the master area */
+ };
+ 
+ /* button definitions */
+diff -up ../dwm-5.8.2-0/dwm.c ./dwm.c
+--- ../dwm-5.8.2-0/dwm.c	2010-06-10 22:47:51.669677000 +0200
++++ ./dwm.c	2010-06-10 22:55:53.128305000 +0200
+_AT_@ -122,26 +122,6 @@ typedef struct {
+ 	void (*arrange)(Monitor *);
+ } Layout;
+ 
+-struct Monitor {
+-	char ltsymbol[16];
+-	float mfact;
+-	int num;
+-	int by;               /* bar geometry */
+-	int mx, my, mw, mh;   /* screen size */
+-	int wx, wy, ww, wh;   /* window area  */
+-	unsigned int seltags;
+-	unsigned int sellt;
+-	unsigned int tagset[2];
+-	Bool showbar;
+-	Bool topbar;
+-	Client *clients;
+-	Client *sel;
+-	Client *stack;
+-	Monitor *next;
+-	Window barwin;
+-	const Layout *lt[2];
+-};
+-
+ typedef struct {
+ 	const char *class;
+ 	const char *instance;
+_AT_@ -621,6 +601,10 @@ createmon(void) {
+ 	m->lt[0] = &layouts[0];
+ 	m->lt[1] = &layouts[1 % LENGTH(layouts)];
+ 	strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
++	m->ltaxis[0] = layoutaxis[0];
++	m->ltaxis[1] = layoutaxis[1];
++	m->ltaxis[2] = layoutaxis[2];
++	m->msplit = 1;
+ 	return m;
+ }
+ 
+_AT_@ -1494,7 +1478,7 @@ setlayout(const Arg *arg) {
+ 	if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
+ 		selmon->sellt ^= 1;
+ 	if(arg && arg->v)
+-		selmon->lt[selmon->sellt] = (Layout *)arg->v;
++		selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag] = (Layout *)arg->v;
+ 	strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol);
+ 	if(selmon->sel)
+ 		arrange(selmon);
+_AT_@ -1512,14 +1496,16 @@ setmfact(const Arg *arg) {
+ 	f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
+ 	if(f < 0.1 || f > 0.9)
+ 		return;
+-	selmon->mfact = f;
++	selmon->mfact = selmon->mfacts[selmon->curtag] = f;
+ 	arrange(selmon);
+ }
+ 
+ void
+ setup(void) {
+ 	XSetWindowAttributes wa;
+-
++	Monitor *m;
++	unsigned int i;
++ 
+ 	/* clean up any zombies immediately */
+ 	sigchld(0);
+ 
+_AT_@ -1555,7 +1541,19 @@ setup(void) {
+ 	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
+ 	if(!dc.font.set)
+ 		XSetFont(dpy, dc.gc, dc.font.xfont->fid);
+-	/* init bars */
++	/* init tags, bars, layouts, axes, msplits and mfacts */
++	for(m = mons; m; m = m->next) {
++		m->curtag = m->prevtag = 1;
++		for(i=0; i < LENGTH(tags) + 1; i++) {
++			m->showbars[i] = m->showbar;
++			m->lts[i] = &layouts[0];
++			m->mfacts[i] = m->mfact;
++			m->ltaxes[i][0] = m->ltaxis[0];
++			m->ltaxes[i][1] = m->ltaxis[1];
++			m->ltaxes[i][2] = m->ltaxis[2];
++			m->msplits[i] = m->msplit;
++		}
++	}
+ 	updatebars();
+ 	updatestatus();
+ 	/* EWMH support per view */
+_AT_@ -1635,38 +1633,8 @@ textnw(const char *text, unsigned int le
+ }
+ 
+ void
+-tile(Monitor *m) {
+-	int x, y, h, w, mw;
+-	unsigned int i, n;
+-	Client *c;
+-
+-	for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+-	if(n == 0)
+-		return;
+-	/* master */
+-	c = nexttiled(m->clients);
+-	mw = m->mfact * m->ww;
+-	resize(c, m->wx, m->wy, (n == 1 ? m->ww : mw) - 2 * c->bw, m->wh - 2 * c->bw, False);
+-	if(--n == 0)
+-		return;
+-	/* tile stack */
+-	x = (m->wx + mw > c->x + c->w) ? c->x + c->w + 2 * c->bw : m->wx + mw;
+-	y = m->wy;
+-	w = (m->wx + mw > c->x + c->w) ? m->wx + m->ww - x : m->ww - mw;
+-	h = m->wh / n;
+-	if(h < bh)
+-		h = m->wh;
+-	for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
+-		resize(c, x, y, w - 2 * c->bw, /* remainder */ ((i + 1 == n)
+-		       ? m->wy + m->wh - y - 2 * c->bw : h - 2 * c->bw), False);
+-		if(h != m->wh)
+-			y = c->y + HEIGHT(c);
+-	}
+-}
+-
+-void
+ togglebar(const Arg *arg) {
+-	selmon->showbar = !selmon->showbar;
++	selmon->showbar = selmon->showbars[selmon->curtag] = !selmon->showbar;
+ 	updatebarpos(selmon);
+ 	XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, selmon->ww, bh);
+ 	arrange(selmon);
+_AT_@ -1686,12 +1654,31 @@ togglefloating(const Arg *arg) {
+ void
+ toggletag(const Arg *arg) {
+ 	unsigned int newtags;
++	unsigned int i;
+ 
+ 	if(!selmon->sel)
+ 		return;
+ 	newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
+ 	if(newtags) {
+ 		selmon->sel->tags = newtags;
++		if(newtags == ~0) {
++			selmon->prevtag = selmon->curtag;
++			selmon->curtag = 0;
++		}
++		if(!(newtags & 1 << (selmon->curtag - 1))) {
++			selmon->prevtag = selmon->curtag;
++			for (i=0; !(newtags & 1 << i); i++);
++			selmon->curtag = i + 1;
++		}
++		selmon->sel->tags = newtags;
++		selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag];
++		selmon->mfact = selmon->mfacts[selmon->curtag];
++		if (selmon->showbar != selmon->showbars[selmon->curtag])
++			togglebar(NULL);
++		selmon->ltaxis[0] = selmon->ltaxes[selmon->curtag][0];
++		selmon->ltaxis[1] = selmon->ltaxes[selmon->curtag][1];
++		selmon->ltaxis[2] = selmon->ltaxes[selmon->curtag][2];
++		selmon->msplit = selmon->msplits[selmon->curtag];
+ 		arrange(selmon);
+ 	}
+ }
+_AT_@ -1959,11 +1946,33 @@ updatewmhints(Client *c) {
+ 
+ void
+ view(const Arg *arg) {
++	unsigned int i;
++
+ 	if((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
+ 		return;
+ 	selmon->seltags ^= 1; /* toggle sel tagset */
+-	if(arg->ui & TAGMASK)
++	if(arg->ui & TAGMASK) {
+ 		selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
++		selmon->prevtag = selmon->curtag;
++		if(arg->ui == ~0)
++			selmon->curtag = 0;
++		else {
++			for (i=0; !(arg->ui & 1 << i); i++);
++			selmon->curtag = i + 1;
++		}
++	} else {
++		selmon->prevtag = selmon->curtag ^ selmon->prevtag;
++		selmon->curtag ^= selmon->prevtag;
++		selmon->prevtag = selmon->curtag ^ selmon->prevtag;
++	}
++	selmon->lt[selmon->sellt] = selmon->lts[selmon->curtag];
++	selmon->mfact = selmon->mfacts[selmon->curtag];
++	if(selmon->showbar != selmon->showbars[selmon->curtag])
++		togglebar(NULL);
++	selmon->ltaxis[0] = selmon->ltaxes[selmon->curtag][0];
++	selmon->ltaxis[1] = selmon->ltaxes[selmon->curtag][1];
++	selmon->ltaxis[2] = selmon->ltaxes[selmon->curtag][2];
++	selmon->msplit = selmon->msplits[selmon->curtag];
+ 	arrange(selmon);
+ }
+ 
+diff -up ../dwm-5.8.2-0/flextile.h ./flextile.h
+--- ../dwm-5.8.2-0/flextile.h	2010-06-10 23:08:24.000000000 +0200
++++ ./flextile.h	2010-06-10 22:59:20.632706000 +0200
+_AT_@ -0,0 +1,159 @@
++/* See LICENSE file for copyright and license details. */
++/* © 2010 joten <joten_AT_freenet.de> */
++
++struct Monitor {
++	char ltsymbol[16];
++	float mfact;
++	double mfacts[LENGTH(tags) + 1];
++	int ltaxis[3];
++	int ltaxes[LENGTH(tags) + 1][3];
++	int num;
++	int curtag;
++	int prevtag;
++	int by;               /* bar geometry */
++	int mx, my, mw, mh;   /* screen size */
++	int wx, wy, ww, wh;   /* window area  */
++	unsigned int msplit;
++	unsigned int msplits[LENGTH(tags) + 1];
++	unsigned int seltags;
++	unsigned int sellt;
++	unsigned int tagset[2];
++	Bool showbar;
++	Bool showbars[LENGTH(tags) + 1];
++	Bool topbar;
++	Client *clients;
++	Client *sel;
++	Client *stack;
++	Monitor *next;
++	Window barwin;
++	const Layout *lt[2];
++	const Layout *lts[LENGTH(tags) + 1];
++};
++
++/* function declarations */
++static void mirrorlayout(const Arg *arg);
++static void rotatelayoutaxis(const Arg *arg);
++static void shiftmastersplit(const Arg *arg);
++
++void
++mirrorlayout(const Arg *arg) {
++	if(!selmon->lt[selmon->sellt]->arrange)
++		return;
++	selmon->ltaxis[0] *= -1;
++	selmon->ltaxes[selmon->curtag][0] = selmon->ltaxis[0];
++	arrange(selmon);
++}
++
++void
++rotatelayoutaxis(const Arg *arg) {
++	if(!selmon->lt[selmon->sellt]->arrange)
++		return;
++	if(arg->i == 0) {
++		if(selmon->ltaxis[0] > 0)
++			selmon->ltaxis[0] = selmon->ltaxis[0] + 1 > 2 ? 1 : selmon->ltaxis[0] + 1;
++		else
++			selmon->ltaxis[0] = selmon->ltaxis[0] - 1 < -2 ? -1 : selmon->ltaxis[0] - 1;
++	} else
++		selmon->ltaxis[arg->i] = selmon->ltaxis[arg->i] + 1 > 3 ? 1 : selmon->ltaxis[arg->i] + 1;
++	selmon->ltaxes[selmon->curtag][arg->i] = selmon->ltaxis[arg->i];
++	arrange(selmon);
++}
++
++void
++shiftmastersplit(const Arg *arg) {
++	unsigned int n;
++	Client *c;
++
++	for(n = 0, c = nexttiled(selmon->clients); c; c = nexttiled(c->next), n++);
++	if(!arg || !selmon->lt[selmon->sellt]->arrange || selmon->msplit + arg->i < 1 || selmon->msplit + arg->i > n)
++		return;
++	selmon->msplit += arg->i;
++	selmon->msplits[selmon->curtag] = selmon->msplit;
++	arrange(selmon);
++}
++
++void
++tile(Monitor *m) {
++	char sym1 = 61, sym2 = 93, sym3 = 61, sym;
++	int x1 = m->wx, y1 = m->wy, h1 = m->wh, w1 = m->ww, X1 = x1 + w1, Y1 = y1 + h1;
++	int x2 = m->wx, y2 = m->wy, h2 = m->wh, w2 = m->ww, X2 = x2 + w2, Y2 = y2 + h2;
++	unsigned int i, n, n1, n2;
++	Client *c;
++
++	for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
++	if(m->msplit > n)
++		m->msplit = (n == 0) ? 1 : n;
++	/* layout symbol */
++	if(abs(m->ltaxis[0]) == m->ltaxis[1])    /* explicitly: ((abs(m->ltaxis[0]) == 1 && m->ltaxis[1] == 1) || (abs(m->ltaxis[0]) == 2 && m->ltaxis[1] == 2)) */
++		sym1 = 124;
++	if(abs(m->ltaxis[0]) == m->ltaxis[2])
++		sym3 = 124;
++	if(m->ltaxis[1] == 3)
++		sym1 = (n == 0) ? 0 : m->msplit;
++	if(m->ltaxis[2] == 3)
++		sym3 = (n == 0) ? 0 : n - m->msplit;
++	if(m->ltaxis[0] < 0) {
++		sym = sym1;
++		sym1 = sym3;
++		sym2 = 91;
++		sym3 = sym;
++	}
++	if(m->msplit == 1) {
++		if(m->ltaxis[0] > 0)
++			sym1 = 91;
++		else
++			sym3 = 93;
++	}
++	if(m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[2] == 3)
++		snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%d", sym1, sym2, sym3);
++	else if((m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[0] > 0) || (m->ltaxis[2] == 3 && m->ltaxis[0] < 0))
++		snprintf(m->ltsymbol, sizeof m->ltsymbol, "%d%c%c", sym1, sym2, sym3);
++	else if((m->ltaxis[2] == 3 && m->ltaxis[0] > 0) || (m->msplit > 1 && m->ltaxis[1] == 3 && m->ltaxis[0] < 0))
++		snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%d", sym1, sym2, sym3);
++	else
++		snprintf(m->ltsymbol, sizeof m->ltsymbol, "%c%c%c", sym1, sym2, sym3);
++	if(n == 0)
++		return;
++	/* master and stack area */
++	if(abs(m->ltaxis[0]) == 1 && n > m->msplit) {
++		w1 *= m->mfact;
++		w2 -= w1;
++		x1 += (m->ltaxis[0] < 0) ? w2 : 0;
++		x2 += (m->ltaxis[0] < 0) ? 0 : w1;
++		X1 = x1 + w1;
++		X2 = x2 + w2;
++	} else if(abs(m->ltaxis[0]) == 2 && n > m->msplit) {
++		h1 *= m->mfact;
++		h2 -= h1;
++		y1 += (m->ltaxis[0] < 0) ? h2 : 0;
++		y2 += (m->ltaxis[0] < 0) ? 0 : h1;
++		Y1 = y1 + h1;
++		Y2 = y2 + h2;
++	}
++	/* master */
++	n1 = (m->ltaxis[1] != 1 || w1 / m->msplit < bh) ? 1 : m->msplit;
++	n2 = (m->ltaxis[1] != 2 || h1 / m->msplit < bh) ? 1 : m->msplit;
++	for(i = 0, c = nexttiled(m->clients); i < m->msplit; c = nexttiled(c->next), i++) {
++		resize(c, x1, y1, 
++			(m->ltaxis[1] == 1 && i + 1 == m->msplit) ? X1 - x1 - 2 * c->bw : w1 / n1 - 2 * c->bw, 
++			(m->ltaxis[1] == 2 && i + 1 == m->msplit) ? Y1 - y1 - 2 * c->bw : h1 / n2 - 2 * c->bw, False);
++		if(n1 > 1)
++			x1 = c->x + WIDTH(c);
++		if(n2 > 1)
++			y1 = c->y + HEIGHT(c);
++	}
++	/* stack */
++	if(n > m->msplit) {
++		n1 = (m->ltaxis[2] != 1 || w2 / (n - m->msplit) < bh) ? 1 : n - m->msplit;
++		n2 = (m->ltaxis[2] != 2 || h2 / (n - m->msplit) < bh) ? 1 : n - m->msplit;
++		for(i = 0; c; c = nexttiled(c->next), i++) {
++			resize(c, x2, y2, 
++				(m->ltaxis[2] == 1 && i + 1 == n - m->msplit) ? X2 - x2 - 2 * c->bw : w2 / n1 - 2 * c->bw, 
++				(m->ltaxis[2] == 2 && i + 1 == n - m->msplit) ? Y2 - y2 - 2 * c->bw : h2 / n2 - 2 * c->bw, False);
++			if(n1 > 1)
++				x2 = c->x + WIDTH(c);
++			if(n2 > 1)
++				y2 = c->y + HEIGHT(c);
++		}
++	}
++}
diff -r 48e2029f6d04 -r 6a5aff2c4bb5 dwm.suckless.org/patches/flextile.md
--- a/dwm.suckless.org/patches/flextile.md	Fri Jun 11 08:39:06 2010 +0000
+++ b/dwm.suckless.org/patches/flextile.md	Fri Jun 11 16:47:32 2010 +0200
_AT_@ -2,20 +2,20 @@
 
 ## Description ##
 
-This patch replaces the tile layout with a more flexible version. The features include the following:
+This patch replaces the `tile` layout with a more flexible version. The features include the following:
 
  * tile like the original version (left single master, right stack)
- * left/right/top/bottom n-master, right/left/bottom/top/no stack/deck (deck is like monocle in the stack area)
+ * left/right/top/bottom n-master, right/left/bottom/top/no stack/deck (deck is like `monocle` in the stack area)
  * per-tag configuration
 
 It therefor provides i. a. the following additional possibilities:
 
- * tile for left-handed people
+ * `tile` for left-handed people
  * compare multiple files with one other each at a time without switching between views
 
 The patch incorporates and expands the following patches:
 
- * bottom stack (bstack and bstackhoriz)
+ * bottom stack (`bstack` and `bstackhoriz`)
  * nmaster
  * pertag
 
_AT_@ -24,19 +24,23 @@
 
  (1) Download the patch and apply it according to the [general instructions](.).
 
- (2) Transfer the changes made by the patch in 'config.def.h' to your 'config.h', if needed.
+ (2) Transfer the changes made by the patch in `config.def.h` to your `config.h`, if needed.
 
-     In the 'layout(s)' section:
+     /* tagging */
+     ...
+     /* include(s) depending on the tags array */
+     #include "flextile.h"
 
-         static const int layoutaxis[] = {
-             1,    /* layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top */
-             2,    /* master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */
-             2,    /* stack axis:  1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */
-         };
-         static const unsigned int mastersplit = 1;    /* number of tiled clients in the master area */
+     /* layout(s) */
+     static const int layoutaxis[] = {
+         1,    /* layout axis: 1 = x, 2 = y; negative values mirror the layout, setting the master area to the right / bottom instead of left / top */
+         2,    /* master axis: 1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */
+         2,    /* stack axis:  1 = x (from left to right), 2 = y (from top to bottom), 3 = z (monocle) */
+     };
+     static const unsigned int mastersplit = 1;    /* number of tiled clients in the master area */
 
-     In the 'keys' array:
-
+     static Key keys[] = {
+     ...
          { MODKEY|ControlMask,           XK_t,      rotatelayoutaxis, {.i = 0} },    /* 0 = layout axis */
          { MODKEY|ControlMask,           XK_Tab,    rotatelayoutaxis, {.i = 1} },    /* 1 = master axis */
          { MODKEY|ControlMask|ShiftMask, XK_Tab,    rotatelayoutaxis, {.i = 2} },    /* 2 = stack axis */
_AT_@ -47,14 +51,16 @@
  
 ## Usage ##
 
-With the default configuration (see above) the original tile layout is emulated. You can change the layout by adjusting the four parameters 'layout axis', 'master axis', 'stack axis' and 'master split' (description see above) by pressing the appropriate keys.
-The original tile layout is only available by setting the above parameters, but not as a discrete layout; the 'monocle' layout is still available by pressing 'ALT+m' (in the default configuration).
+With the default configuration (see above) the original tile layout is emulated. You can change the layout by adjusting the four parameters `layout axis`, `master axis`, `stack axis` and `master split` (description see above) by pressing the appropriate keys.
+The original `tile` layout is only available by setting the above parameters, but not as a discrete layout; the `monocle` layout is still available by pressing `ALT+m` (in the default configuration).
 
 
 ## Download ##
 
- * [flextile-5.8.1.diff][1] (14k) (20100531, joten <joten (at) freenet (dot) de>)
+ * [flextile-5.8.1.diff][1] (14k) (20100531, joten (at) freenet (dot) de)
+ * [flextile-5.8.2.diff][2] (13k, +169 SLOC) (20100611, joten (at) freenet (dot) de)
 
 
 [1]: http://dwm.suckless.org/patches/flextile-5.8.1.diff
+[2]: http://dwm.suckless.org/patches/flextile-5.8.2.diff
 
diff -r 48e2029f6d04 -r 6a5aff2c4bb5 dwm.suckless.org/patches/keymodes-5.8.2-vim.diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwm.suckless.org/patches/keymodes-5.8.2-vim.diff	Fri Jun 11 16:47:32 2010 +0200
_AT_@ -0,0 +1,583 @@
+diff -up ../dwm-5.8.2-1/config.def.h ./config.def.h
+--- ../dwm-5.8.2-1/config.def.h	2010-06-11 01:10:05.465026000 +0200
++++ ./config.def.h	2010-06-11 01:13:49.211525000 +0200
+_AT_@ -19,6 +19,9 @@ static const char *tags[] = { "1", "2",
+ /* include(s) depending on the tags array */
+ #include "flextile.h"
+ 
++/* include(s) defining functions */
++#include "keymodes.pre.h"
++
+ static const Rule rules[] = {
+ 	/* class      instance    title       tags mask     isfloating   monitor */
+ 	{ "Gimp",     NULL,       NULL,       0,            True,        -1 },
+_AT_@ -36,9 +39,9 @@ static const int layoutaxis[] = {
+ 
+ static const Layout layouts[] = {
+ 	/* symbol     arrange function */
+-	{ "[]=",      tile },    /* first entry is default */
++	{ "[M]",      monocle },    /* first entry is default */
++	{ "[]=",      tile },
+ 	{ "><>",      NULL },    /* no layout function means floating behavior */
+-	{ "[M]",      monocle },
+ };
+ 
+ /* key definitions */
+_AT_@ -55,9 +58,11 @@ static const Layout layouts[] = {
+ /* commands */
+ static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
+ static const char *termcmd[]  = { "uxterm", NULL };
++static const char *helpcmd[]  = { "uxterm", "-e", "man", "dwm", NULL };
+ 
+ static Key keys[] = {
+ 	/* modifier                     key        function        argument */
++	{ MODKEY,                       XK_Escape, setkeymode,     {.ui = COMMANDMODE} },
+ 	{ MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } },
+ 	{ MODKEY|ShiftMask,             XK_Return, spawn,          {.v = termcmd } },
+ 	{ MODKEY,                       XK_b,      togglebar,      {0} },
+_AT_@ -68,9 +73,9 @@ static Key keys[] = {
+ 	{ MODKEY,                       XK_Return, zoom,           {0} },
+ 	{ MODKEY,                       XK_Tab,    view,           {0} },
+ 	{ MODKEY|ShiftMask,             XK_c,      killclient,     {0} },
+-	{ MODKEY,                       XK_t,      setlayout,      {.v = &layouts[0]} },
+-	{ MODKEY,                       XK_f,      setlayout,      {.v = &layouts[1]} },
+-	{ MODKEY,                       XK_m,      setlayout,      {.v = &layouts[2]} },
++	{ MODKEY,                       XK_m,      setlayout,      {.v = &layouts[0]} },
++	{ MODKEY,                       XK_t,      setlayout,      {.v = &layouts[1]} },
++	{ MODKEY,                       XK_f,      setlayout,      {.v = &layouts[2]} },
+ 	{ MODKEY,                       XK_space,  setlayout,      {0} },
+ 	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} },
+ 	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } },
+_AT_@ -97,6 +102,54 @@ static Key keys[] = {
+ 	{ MODKEY|ControlMask,           XK_l,      shiftmastersplit, {.i = +1} },   /* increase the number of tiled clients in the master area */
+ };
+ 
++static const int h_master[] = {+1, 2, 2};
++static const int j_master[] = {-2, 1, 1};
++static const int k_master[] = {+2, 1, 1};
++static const int l_master[] = {-1, 2, 2};
++
++static Key cmdkeys[] = {
++	/* modifier                    keys                     function         argument */
++	{ 0,                           XK_Escape,               clearcmd,        {0} },
++	{ ControlMask,                 XK_c,                    clearcmd,        {0} },
++	{ 0,                           XK_i,                    setkeymode,      {.ui = INSERTMODE} },
++};
++static Command commands[] = {
++	/* modifier (4 keys)                          keysyms (4 keys)                                function         argument */
++	{ {0,           0,          0,         0},    {XK_g,      XK_t,     0,         0},            adjacentview,    {.i = +1} },
++	{ {0,           ShiftMask,  0,         0},    {XK_g,      XK_t,     0,         0},            adjacentview,    {.i = -1} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_c,     0,         0},            closewindow,     {0} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_h,     0,         0},            focustiled,      {.i = -1} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_j,     0,         0},            focustiled,      {.i = +2} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_k,     0,         0},            focustiled,      {.i = -2} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_l,     0,         0},            focustiled,      {.i = +1} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_h,     0,         0},            setmaster,       {.v = h_master} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_j,     0,         0},            setmaster,       {.v = j_master} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_k,     0,         0},            setmaster,       {.v = k_master} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_l,     0,         0},            setmaster,       {.v = l_master} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_o,     0,         0},            setlayout,       {.v = &layouts[0]} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_o,     0,         0},            onlyclient,      {0} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_s,     0,         0},            split,           {.ui = 2} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_t,     0,         0},            adjacenttag,     {.i = +1} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_t,     0,         0},            adjacenttag,     {.i = -1} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_v,     0,         0},            split,           {.ui = 1} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_x,     0,         0},            exchangewindow,  {.i = +1} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_x,     0,         0},            exchangewindow,  {.i = -1} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_w,     0,         0},            focuswindow,     {.i = +1} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_w,     0,         0},            focuswindow,     {.i = -1} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_less,  0,         0},            resizemaster,    {.f = -10.05} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_less,  0,         0},            resizemaster,    {.f = +10.05} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_minus, 0,         0},            resizemaster,    {.f = -20.05} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_plus,  0,         0},            resizemaster,    {.f = +20.05} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_0,     0,         0},            setmfact,        {.f = +1.50} },
++	{ {ShiftMask,   0,          0,         0},    {XK_period, XK_e,     0,         0},            spawn,           {.v = dmenucmd} },
++	{ {ShiftMask,   0,          0,         0},    {XK_period, XK_o,     0,         0},            spawn,           {.v = dmenucmd} },
++	{ {ShiftMask,   0,          0,         0},    {XK_period, XK_h,     XK_Return, 0},            spawn,           {.v = helpcmd} },
++	{ {ShiftMask,   0,          0,         0},    {XK_period, XK_q,     XK_Return, 0},            quit,            {0} },
++	{ {ShiftMask,   0,          0,         0},    {XK_period, XK_b,     XK_d,      XK_Return},    killclient,      {0} },
++	{ {ShiftMask,   0,          0,         0},    {XK_period, XK_b,     XK_n,      XK_Return},    focusstack,      {.i = +1} },
++	{ {ShiftMask,   0,          ShiftMask, 0},    {XK_period, XK_b,     XK_n,      XK_Return},    focusstack,      {.i = -1} },
++};
++
+ /* button definitions */
+ /* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
+ static Button buttons[] = {
+_AT_@ -114,3 +167,5 @@ static Button buttons[] = {
+ 	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} },
+ };
+ 
++/* include(s) depending on the configuration variables */
++#include "keymodes.post.h"
+diff -up ../dwm-5.8.2-1/dwm.c ./dwm.c
+--- ../dwm-5.8.2-1/dwm.c	2010-06-11 01:10:05.473958000 +0200
++++ ./dwm.c	2010-06-11 01:13:49.226865000 +0200
+_AT_@ -954,7 +954,7 @@ grabbuttons(Client *c, Bool focused) {
+ }
+ 
+ void
+-grabkeys(void) {
++grabdefkeys(void) {
+ 	updatenumlockmask();
+ 	{
+ 		unsigned int i, j;
+_AT_@ -1036,7 +1036,7 @@ isuniquegeom(XineramaScreenInfo *unique,
+ #endif /* XINERAMA */
+ 
+ void
+-keypress(XEvent *e) {
++defkeypress(XEvent *e) {
+ 	unsigned int i;
+ 	KeySym keysym;
+ 	XKeyEvent *ev;
+diff -up ../dwm-5.8.2-1/keymodes.post.h ./keymodes.post.h
+--- ../dwm-5.8.2-1/keymodes.post.h	2010-06-11 01:12:53.000000000 +0200
++++ ./keymodes.post.h	2010-06-11 01:13:49.287434000 +0200
+_AT_@ -0,0 +1,409 @@
++/* See LICENSE file for copyright and license details. */
++/* © 2010 joten <joten_AT_freenet.de> */
++
++/* function implementations */
++void
++adjacenttag(const Arg *arg) {
++	int nexttag = selmon->curtag + arg->i;
++	Arg a;
++
++	if(nexttag > LENGTH(tags))
++		nexttag = 1;
++	else if(nexttag < 1)
++		nexttag = LENGTH(tags);
++	a.ui = 1 << (nexttag - 1);
++	tag(&a);
++}
++
++void
++adjacentview(const Arg *arg) {
++	int nexttag = selmon->curtag + arg->i;
++	Arg a;
++
++	if(nexttag > LENGTH(tags))
++		nexttag = 1;
++	else if(nexttag < 1)
++		nexttag = LENGTH(tags);
++	a.ui = 1 << (nexttag - 1);
++	view(&a);
++}
++
++void
++clearcmd(const Arg *arg) {
++	unsigned int i;
++
++	for(i = 0; i < LENGTH(cmdkeysym); i++) {
++		cmdkeysym[i] = 0;
++		cmdmod[i] = 0;
++	}
++}
++
++void
++closewindow(const Arg *arg) {
++	unsigned int j, n;
++	Client *i;
++
++	if(!selmon->sel || selmon->sel->isfloating || selmon->lt[selmon->sellt]->arrange != tile)
++		return;
++	for(n = 0, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), n++)
++		if(i == selmon->sel)
++			j = n + 1;
++	if(j == 0 || n < 2)
++		return;
++	if(j <= selmon->msplit) {
++		if(selmon->ltaxis[1] == 3 || selmon->msplit == 1) {
++			selmon->msplits[selmon->curtag] = selmon->msplit = n;
++			selmon->ltaxes[selmon->curtag][1] = selmon->ltaxis[1] = selmon->ltaxis[2];
++			selmon->ltaxes[selmon->curtag][2] = selmon->ltaxis[2] = 3;
++		} else if(j == selmon->msplit && (selmon->ltaxis[2] == 3 || selmon->msplit == n - 1)) {
++			selmon->msplits[selmon->curtag] = selmon->msplit -= 1;
++			selmon->ltaxes[selmon->curtag][2] = selmon->ltaxis[2] = 3;
++		} else
++			selmon->ltaxes[selmon->curtag][1] = selmon->ltaxis[1] = 3;
++	} else {
++		if(selmon->ltaxis[2] == 3 || selmon->msplit == n - 1)
++			selmon->msplits[selmon->curtag] = selmon->msplit = n;
++		else if(j == selmon->msplit + 1 && (selmon->ltaxis[1] == 3 || selmon->msplit == 1)) {
++			selmon->msplits[selmon->curtag] = selmon->msplit += 1;
++			selmon->ltaxes[selmon->curtag][1] = selmon->ltaxis[1] = 3;
++		} else
++			selmon->ltaxes[selmon->curtag][2] = selmon->ltaxis[2] = 3;
++	}
++	arrange(selmon);
++}
++
++void
++exchangewindow(const Arg *arg) {
++	int j = 0, n;
++	Client *c, *i, *sel = selmon->sel;
++
++	if(!sel || sel->isfloating || selmon->lt[selmon->sellt]->arrange != tile)
++		return;
++	for(n = 0, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), n++)
++		if(i == selmon->sel)
++			j = n + 1;
++	if(j == 0 || n < 2 
++	|| (j <= selmon->msplit && selmon->ltaxis[1] == 3 && selmon->msplit > 1 && !(j == 1 && arg->i < 0) && !(j == selmon->msplit && arg->i > 0))
++	|| (j > selmon->msplit && selmon->ltaxis[2] == 3 && n - selmon->msplit > 1 && !(j == selmon->msplit + 1 && arg->i < 0) && !(j == n && arg->i > 0)))
++		return;
++	if(arg->i < 0) {
++		if((c = prevtiled(sel))) {
++			/* attach before c */
++			detach(sel);
++			sel->next = c;
++			if(selmon->clients == c)
++				selmon->clients = sel;
++			else {
++				for(c = selmon->clients; c->next != sel->next; c = c->next);
++				c->next = sel;
++			}
++		} else {
++			/* move to the end */
++			for(c = sel; c->next; c = c->next);
++			detach(sel);
++			sel->next = NULL;
++			c->next = sel;
++		}
++	} else {
++		if((c = nexttiled(sel->next))) {
++			/* attach after c */
++			detach(sel);
++			sel->next = c->next;
++			c->next = sel;
++		} else {
++			/* move to the front */
++			detach(sel);
++			attach(sel);
++		}
++	}
++	focus(sel);
++	arrange(selmon);
++}
++
++void
++focustiled(const Arg *arg) {
++	float f;
++	unsigned int j = 0, k, n;
++	Client *c = NULL, *i;
++	
++	if(!selmon->sel || selmon->sel->isfloating || (selmon->lt[selmon->sellt]->arrange != monocle && selmon->lt[selmon->sellt]->arrange != tile))
++		return;
++	for(n = 0, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), n++)
++		if(i == selmon->sel)
++			j = n + 1;
++	if(n < 2)
++		return;
++	if(arg->i < 0
++	&& ((j > 1 && j <= selmon->msplit && selmon->ltaxis[1] == -(arg->i)) || (j > (selmon->msplit + 1) && j <= n && selmon->ltaxis[2] == -(arg->i)))) {
++		c = prevtiled(selmon->sel);
++	} else if(arg->i > 0
++	&& ((j > 0 && j < selmon->msplit && selmon->ltaxis[1] == arg->i) || (j > selmon->msplit && j < n && selmon->ltaxis[2] == arg->i))) {
++		c = nexttiled(selmon->sel->next);
++	} else if(arg->i < 0 
++	&& n > selmon->msplit 
++	&& j > selmon->msplit && j <= n 
++	&& (selmon->ltaxis[2] - arg->i) == 3)
++		f = (float)(j - selmon->msplit) / (n - selmon->msplit) * selmon->msplit;
++	else if(arg->i > 0 
++	&& n > selmon->msplit 
++	&& j > 0 && j <= selmon->msplit 
++	&& (selmon->ltaxis[1] + arg->i) == 3)
++		f = selmon->msplit + (float)j / selmon->msplit * (n - selmon->msplit);
++	if(f > 0) {
++		k = (unsigned int)f;
++		if(f - k > 0)
++			k++;
++		for(j = 1, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), j++)
++			if(j == k)
++				c = i;
++	}
++	if(c) {
++		focus(c);
++		restack(selmon);
++	}
++}
++
++void
++focuswindow(const Arg *arg) {
++	unsigned int j = 0, k = 0, n;
++	Client *c = NULL, *i;
++
++	if(!selmon->sel || selmon->sel->isfloating || selmon->lt[selmon->sellt]->arrange != tile)
++		return;
++	for(n = 0, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), n++)
++		if(i == selmon->sel)
++			j = n + 1;
++	if(j == 0 || n < 2 || (selmon->msplit == n && selmon->ltaxis[1] == 3))
++		return;
++	if(arg->i < 0) {
++		if((j > 1 && j <= selmon->msplit && selmon->ltaxis[1] == 3) || j == 1) {
++			k = n;
++		} else if(j > selmon->msplit + 1 && j <= n && selmon->ltaxis[2] == 3) {
++			k = selmon->msplit;
++		} else
++			c = prevtiled(selmon->sel);
++	} else {
++		if(j < selmon->msplit && selmon->ltaxis[1] == 3) {
++			k = selmon->msplit + 1;
++		} else if((j > selmon->msplit && j < n && selmon->ltaxis[2] == 3) || j == n) {
++			k = 1;
++		} else
++			c = nexttiled(selmon->sel->next);
++	}
++	if(!c && k)
++		for(j = 1, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), j++)
++			if(j == k)
++				c = i;
++	if(c) {
++		focus(c);
++		restack(selmon);
++	}
++}
++
++void
++grabkeys(void) {
++	if(keymode == INSERTMODE) {
++		grabdefkeys();
++	} else if(keymode == COMMANDMODE) {
++		XUngrabKey(dpy, AnyKey, AnyModifier, root);
++		XGrabKey(dpy, AnyKey, AnyModifier, root,
++			 True, GrabModeAsync, GrabModeAsync);
++	}
++}
++
++void
++keypress(XEvent *e) {
++	unsigned int i, j;
++	Arg a = {0};
++	Bool ismatch = False, maybematch = False;
++	KeySym keysym;
++	XKeyEvent *ev;
++
++	if(keymode == INSERTMODE)
++		defkeypress(e);
++	else if(keymode == COMMANDMODE) {
++		ev = &e->xkey;
++		keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
++		if(keysym < XK_Shift_L || keysym > XK_Hyper_R) {
++			for(i = 0; i < LENGTH(cmdkeys); i++)
++				if(keysym == cmdkeys[i].keysym
++				&& CLEANMASK(cmdkeys[i].mod) == CLEANMASK(ev->state)
++				&& cmdkeys[i].func) {
++					cmdkeys[i].func(&(cmdkeys[i].arg));
++					ismatch = True;
++					break;
++				}
++			if(!ismatch) {
++				for(j = 0; j < LENGTH(cmdkeysym); j++)
++					if(cmdkeysym[j] == 0) {
++						cmdkeysym[j] = keysym;
++						cmdmod[j] = ev->state;
++						break;
++					}
++				for(i = 0; i < LENGTH(commands); i++) {
++					for(j = 0; j < LENGTH(cmdkeysym); j++) {
++						if(cmdkeysym[j] == commands[i].keysym[j] 
++						&& CLEANMASK(cmdmod[j]) == CLEANMASK(commands[i].mod[j]))
++							ismatch = True;
++						else if(cmdkeysym[j] == 0 
++						&& cmdmod[j] == 0) {
++							ismatch = False;
++							maybematch = True;
++							break;
++						} else {
++							ismatch = False;
++							break;
++						}
++					}
++					if(ismatch) {
++						if(commands[i].func)
++							commands[i].func(&(commands[i].arg));
++						clearcmd(&a);
++						break;
++					}
++
++				}
++				if(!maybematch)
++					clearcmd(&a);
++			}
++		}
++	}
++}
++
++void
++onlyclient(const Arg *arg) {
++	Client *c;
++	XEvent ev;
++	
++	if(!selmon->sel)
++		return;
++	for(c = selmon->clients; c; c = c->next)
++		if(c != selmon->sel && ISVISIBLE(c)) {
++			if(isprotodel(c)) {
++				ev.type = ClientMessage;
++				ev.xclient.window = c->win;
++				ev.xclient.message_type = wmatom[WMProtocols];
++				ev.xclient.format = 32;
++				ev.xclient.data.l[0] = wmatom[WMDelete];
++				ev.xclient.data.l[1] = CurrentTime;
++				XSendEvent(dpy, c->win, False, NoEventMask, &ev);
++			}
++			else {
++				XGrabServer(dpy);
++				XSetErrorHandler(xerrordummy);
++				XSetCloseDownMode(dpy, DestroyAll);
++				XKillClient(dpy, c->win);
++				XSync(dpy, False);
++				XSetErrorHandler(xerror);
++				XUngrabServer(dpy);
++			}
++		}
++}
++
++Client *
++prevtiled(Client *c) {
++	Client *i, *p;
++
++	for(i = selmon->clients, p = NULL; i && i != c; i = i->next)
++		if(!i->isfloating && ISVISIBLE(i))
++			p = i;
++	return p;
++}
++
++void
++resizemaster(const Arg *arg) {
++	float f;
++	Arg a;
++	
++	if(!arg || selmon->lt[selmon->sellt]->arrange != tile)
++		return;
++	f = (arg->f < 0 ? -arg->f : arg->f) - selmon->ltaxis[0] * 10;
++	if(f < 0 || f > 1.9)
++		return;
++	a.f = arg->f / abs(arg->f) * f;
++	setmfact(&a);
++}
++
++void
++setkeymode(const Arg *arg) {
++	Arg a = {0};
++
++	if(!arg)
++		return;
++	keymode = arg->ui;
++	clearcmd(&a);
++	grabkeys();
++}
++
++void
++setmaster(const Arg *arg) {
++	unsigned int i;
++	Arg a;
++	
++	if(!arg || (selmon->lt[selmon->sellt]->arrange != monocle && selmon->lt[selmon->sellt]->arrange != tile))
++		return;
++	for(i = 0; i < 3; i++)
++		selmon->ltaxes[selmon->curtag][i] = selmon->ltaxis[i] = ((int *)arg->i)[i];
++	selmon->msplits[selmon->curtag] = selmon->msplit = 1;
++	if(selmon->sel && !selmon->sel->isfloating && selmon->sel != nexttiled(selmon->clients)) {
++		detach(selmon->sel);
++		attach(selmon->sel);
++		focus(selmon->sel);
++	}
++	if(selmon->lt[selmon->sellt]->arrange == monocle) {
++		for(i = 0; i < LENGTH(layouts) && (&layouts[i])->arrange != tile; i++);
++		a.v = &layouts[i];
++		setlayout(&a);
++		if(!selmon->sel)
++			arrange(selmon);
++	} else
++		arrange(selmon);
++}
++
++void
++split(const Arg *arg) {
++	unsigned int j = 0, k, n;
++	Arg a;
++	Client *i;
++	
++	if(!arg || !selmon->sel || selmon->sel->isfloating || (selmon->lt[selmon->sellt]->arrange != monocle && selmon->lt[selmon->sellt]->arrange != tile))
++		return;
++	for(n = 0, i = nexttiled(selmon->clients); i; i = nexttiled(i->next), n++)
++		if(i == selmon->sel)
++			j = n + 1;
++	if(j == 0 || n < 2)
++		return;
++	if(selmon->lt[selmon->sellt]->arrange == monocle) {
++		selmon->ltaxes[selmon->curtag][0] = selmon->ltaxis[0] = arg->i;
++		selmon->ltaxes[selmon->curtag][1] = selmon->ltaxis[1] = 3;
++		selmon->ltaxes[selmon->curtag][2] = selmon->ltaxis[2] = 3;
++		for(k = 0; k < LENGTH(layouts) && (&layouts[k])->arrange != tile; k++);
++		a.v = &layouts[k];
++		setlayout(&a);
++	} else if(j <= selmon->msplit) {
++	        if(selmon->ltaxis[1] == 3 || selmon->msplit == 1) {
++			selmon->ltaxes[selmon->curtag][1] = selmon->ltaxis[1] = arg->i;
++			if(selmon->ltaxis[2] == 3 || selmon->msplit == 1)
++				selmon->msplits[selmon->curtag] = selmon->msplit = 2;
++			arrange(selmon);
++		} else if(selmon->ltaxis[1] == arg->i && selmon->msplit < n) {
++			selmon->msplits[selmon->curtag] = selmon->msplit += 1;
++			arrange(selmon);
++		} else if(selmon->ltaxis[1] + arg->i == 3 && selmon->msplit == n) {
++			selmon->ltaxes[selmon->curtag][0] = selmon->ltaxis[0] = arg->i;
++			selmon->ltaxes[selmon->curtag][2] = selmon->ltaxis[2] = 3;
++			selmon->msplits[selmon->curtag] = selmon->msplit = n - 1;
++			arrange(selmon);
++		}
++	} else if(n > 2) {
++		if(selmon->ltaxis[2] == 3 || selmon->msplit == n - 1) {
++			selmon->ltaxes[selmon->curtag][2] = selmon->ltaxis[2] = arg->i;
++			if(selmon->ltaxis[1] == 3 || selmon->msplit == n - 1)
++				selmon->msplits[selmon->curtag] = selmon->msplit = n - 2;
++			arrange(selmon);
++		} else if(selmon->ltaxis[2] == arg->i && selmon->msplit > 1) {
++			selmon->msplits[selmon->curtag] = selmon->msplit -= 1;
++			arrange(selmon);
++		}
++	}
++}
+diff -up ../dwm-5.8.2-1/keymodes.pre.h ./keymodes.pre.h
+--- ../dwm-5.8.2-1/keymodes.pre.h	2010-06-11 01:12:49.000000000 +0200
++++ ./keymodes.pre.h	2010-06-11 01:13:50.660576000 +0200
+_AT_@ -0,0 +1,34 @@
++/* See LICENSE file for copyright and license details. */
++/* © 2010 joten <joten_AT_freenet.de> */
++
++#define COMMANDMODE             1
++#define INSERTMODE              2
++
++typedef struct {
++	unsigned int mod[4];
++	KeySym keysym[4];
++	void (*func)(const Arg *);
++	const Arg arg;
++} Command;
++
++/* function declarations */
++static void adjacenttag(const Arg *arg);
++static void adjacentview(const Arg *arg);
++static void clearcmd(const Arg *arg);
++static void closewindow(const Arg *arg);
++static void defkeypress(XEvent *e);
++static void exchangewindow(const Arg *arg);
++static void focustiled(const Arg *arg);
++static void focuswindow(const Arg *arg);
++static void grabdefkeys(void);
++static void onlyclient(const Arg *arg);
++static Client *prevtiled(Client *c);
++static void resizemaster(const Arg *arg);
++static void setkeymode(const Arg *arg);
++static void setmaster(const Arg *arg);
++static void split(const Arg *arg);
++
++/* variables */
++static unsigned int cmdmod[4];
++static unsigned int keymode = COMMANDMODE;
++static KeySym cmdkeysym[4];
diff -r 48e2029f6d04 -r 6a5aff2c4bb5 dwm.suckless.org/patches/keymodes-5.8.2.diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwm.suckless.org/patches/keymodes-5.8.2.diff	Fri Jun 11 16:47:32 2010 +0200
_AT_@ -0,0 +1,239 @@
+diff -up ../dwm-5.8.2-0/config.def.h ./config.def.h
+--- ../dwm-5.8.2-0/config.def.h	2010-06-10 22:47:51.660949000 +0200
++++ ./config.def.h	2010-06-11 00:18:55.082073000 +0200
+_AT_@ -16,6 +16,9 @@ static const Bool topbar            = Tr
+ /* tagging */
+ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+ 
++/* include(s) defining functions */
++#include "keymodes.pre.h"
++
+ static const Rule rules[] = {
+ 	/* class      instance    title       tags mask     isfloating   monitor */
+ 	{ "Gimp",     NULL,       NULL,       0,            True,        -1 },
+_AT_@ -47,9 +50,11 @@ static const Layout layouts[] = {
+ /* commands */
+ static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
+ static const char *termcmd[]  = { "uxterm", NULL };
++static const char *helpcmd[]  = { "uxterm", "-e", "man", "dwm", NULL };
+ 
+ static Key keys[] = {
+ 	/* modifier                     key        function        argument */
++	{ MODKEY,                       XK_Escape, setkeymode,     {.ui = COMMANDMODE} },
+ 	{ MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } },
+ 	{ MODKEY|ShiftMask,             XK_Return, spawn,          {.v = termcmd } },
+ 	{ MODKEY,                       XK_b,      togglebar,      {0} },
+_AT_@ -83,6 +88,30 @@ static Key keys[] = {
+ 	{ MODKEY|ShiftMask,             XK_q,      quit,           {0} },
+ };
+ 
++static Key cmdkeys[] = {
++	/* modifier                    keys                     function         argument */
++	{ 0,                           XK_Escape,               clearcmd,        {0} },
++	{ ControlMask,                 XK_c,                    clearcmd,        {0} },
++	{ 0,                           XK_i,                    setkeymode,      {.ui = INSERTMODE} },
++};
++static Command commands[] = {
++	/* modifier (4 keys)                          keysyms (4 keys)                                function         argument */
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_h,     0,         0},            setlayout,       {.v = &layouts[0]} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_o,     0,         0},            setlayout,       {.v = &layouts[2]} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_o,     0,         0},            onlyclient,      {0} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_v,     0,         0},            setlayout,       {.v = &layouts[0]} },
++	{ {ControlMask, 0,          0,         0},    {XK_w,      XK_less,  0,         0},            setmfact,        {.f = -0.05} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_less,  0,         0},            setmfact,        {.f = +0.05} },
++	{ {ControlMask, ShiftMask,  0,         0},    {XK_w,      XK_0,     0,         0},            setmfact,        {.f = +1.50} },
++	{ {ShiftMask,   0,          0,         0},    {XK_period, XK_e,     0,         0},            spawn,           {.v = dmenucmd} },
++	{ {ShiftMask,   0,          0,         0},    {XK_period, XK_o,     0,         0},            spawn,           {.v = dmenucmd} },
++	{ {ShiftMask,   0,          0,         0},    {XK_period, XK_h,     XK_Return, 0},            spawn,           {.v = helpcmd} },
++	{ {ShiftMask,   0,          0,         0},    {XK_period, XK_q,     XK_Return, 0},            quit,            {0} },
++	{ {ShiftMask,   0,          0,         0},    {XK_period, XK_b,     XK_d,      XK_Return},    killclient,      {0} },
++	{ {ShiftMask,   0,          0,         0},    {XK_period, XK_b,     XK_n,      XK_Return},    focusstack,      {.i = +1} },
++	{ {ShiftMask,   0,          ShiftMask, 0},    {XK_period, XK_b,     XK_n,      XK_Return},    focusstack,      {.i = -1} },
++};
++
+ /* button definitions */
+ /* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
+ static Button buttons[] = {
+_AT_@ -100,3 +129,5 @@ static Button buttons[] = {
+ 	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} },
+ };
+ 
++/* include(s) depending on the configuration variables */
++#include "keymodes.post.h"
+diff -up ../dwm-5.8.2-0/dwm.c ./dwm.c
+--- ../dwm-5.8.2-0/dwm.c	2010-06-10 22:47:51.669677000 +0200
++++ ./dwm.c	2010-06-11 00:18:55.106090000 +0200
+_AT_@ -970,7 +970,7 @@ grabbuttons(Client *c, Bool focused) {
+ }
+ 
+ void
+-grabkeys(void) {
++grabdefkeys(void) {
+ 	updatenumlockmask();
+ 	{
+ 		unsigned int i, j;
+_AT_@ -1052,7 +1052,7 @@ isuniquegeom(XineramaScreenInfo *unique,
+ #endif /* XINERAMA */
+ 
+ void
+-keypress(XEvent *e) {
++defkeypress(XEvent *e) {
+ 	unsigned int i;
+ 	KeySym keysym;
+ 	XKeyEvent *ev;
+diff -up ../dwm-5.8.2-0/keymodes.post.h ./keymodes.post.h
+--- ../dwm-5.8.2-0/keymodes.post.h	2010-06-11 00:21:46.000000000 +0200
++++ ./keymodes.post.h	2010-06-11 00:18:55.119222000 +0200
+_AT_@ -0,0 +1,124 @@
++/* See LICENSE file for copyright and license details. */
++/* © 2010 joten <joten_AT_freenet.de> */
++
++/* function implementations */
++void
++clearcmd(const Arg *arg) {
++	unsigned int i;
++
++	for(i = 0; i < LENGTH(cmdkeysym); i++) {
++		cmdkeysym[i] = 0;
++		cmdmod[i] = 0;
++	}
++}
++
++void
++grabkeys(void) {
++	if(keymode == INSERTMODE) {
++		grabdefkeys();
++	} else if(keymode == COMMANDMODE) {
++		XUngrabKey(dpy, AnyKey, AnyModifier, root);
++		XGrabKey(dpy, AnyKey, AnyModifier, root,
++			 True, GrabModeAsync, GrabModeAsync);
++	}
++}
++
++void
++keypress(XEvent *e) {
++	unsigned int i, j;
++	Arg a = {0};
++	Bool ismatch = False, maybematch = False;
++	KeySym keysym;
++	XKeyEvent *ev;
++
++	if(keymode == INSERTMODE)
++		defkeypress(e);
++	else if(keymode == COMMANDMODE) {
++		ev = &e->xkey;
++		keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
++		if(keysym < XK_Shift_L || keysym > XK_Hyper_R) {
++			for(i = 0; i < LENGTH(cmdkeys); i++)
++				if(keysym == cmdkeys[i].keysym
++				&& CLEANMASK(cmdkeys[i].mod) == CLEANMASK(ev->state)
++				&& cmdkeys[i].func) {
++					cmdkeys[i].func(&(cmdkeys[i].arg));
++					ismatch = True;
++					break;
++				}
++			if(!ismatch) {
++				for(j = 0; j < LENGTH(cmdkeysym); j++)
++					if(cmdkeysym[j] == 0) {
++						cmdkeysym[j] = keysym;
++						cmdmod[j] = ev->state;
++						break;
++					}
++				for(i = 0; i < LENGTH(commands); i++) {
++					for(j = 0; j < LENGTH(cmdkeysym); j++) {
++						if(cmdkeysym[j] == commands[i].keysym[j] 
++						&& CLEANMASK(cmdmod[j]) == CLEANMASK(commands[i].mod[j]))
++							ismatch = True;
++						else if(cmdkeysym[j] == 0 
++						&& cmdmod[j] == 0) {
++							ismatch = False;
++							maybematch = True;
++							break;
++						} else {
++							ismatch = False;
++							break;
++						}
++					}
++					if(ismatch) {
++						if(commands[i].func)
++							commands[i].func(&(commands[i].arg));
++						clearcmd(&a);
++						break;
++					}
++
++				}
++				if(!maybematch)
++					clearcmd(&a);
++			}
++		}
++	}
++}
++
++void
++onlyclient(const Arg *arg) {
++	Client *c;
++	XEvent ev;
++	
++	if(!selmon->sel)
++		return;
++	for(c = selmon->clients; c; c = c->next)
++		if(c != selmon->sel && ISVISIBLE(c)) {
++			if(isprotodel(c)) {
++				ev.type = ClientMessage;
++				ev.xclient.window = c->win;
++				ev.xclient.message_type = wmatom[WMProtocols];
++				ev.xclient.format = 32;
++				ev.xclient.data.l[0] = wmatom[WMDelete];
++				ev.xclient.data.l[1] = CurrentTime;
++				XSendEvent(dpy, c->win, False, NoEventMask, &ev);
++			}
++			else {
++				XGrabServer(dpy);
++				XSetErrorHandler(xerrordummy);
++				XSetCloseDownMode(dpy, DestroyAll);
++				XKillClient(dpy, c->win);
++				XSync(dpy, False);
++				XSetErrorHandler(xerror);
++				XUngrabServer(dpy);
++			}
++		}
++}
++
++void
++setkeymode(const Arg *arg) {
++	Arg a = {0};
++
++	if(!arg)
++		return;
++	keymode = arg->ui;
++	clearcmd(&a);
++	grabkeys();
++}
+diff -up ../dwm-5.8.2-0/keymodes.pre.h ./keymodes.pre.h
+--- ../dwm-5.8.2-0/keymodes.pre.h	2010-06-11 00:21:38.000000000 +0200
++++ ./keymodes.pre.h	2010-06-11 00:18:55.121759000 +0200
+_AT_@ -0,0 +1,24 @@
++/* See LICENSE file for copyright and license details. */
++/* © 2010 joten <joten_AT_freenet.de> */
++
++#define COMMANDMODE             1
++#define INSERTMODE              2
++
++typedef struct {
++	unsigned int mod[4];
++	KeySym keysym[4];
++	void (*func)(const Arg *);
++	const Arg arg;
++} Command;
++
++/* function declarations */
++static void clearcmd(const Arg *arg);
++static void defkeypress(XEvent *e);
++static void grabdefkeys(void);
++static void onlyclient(const Arg *arg);
++static void setkeymode(const Arg *arg);
++
++/* variables */
++static unsigned int cmdmod[4];
++static unsigned int keymode = COMMANDMODE;
++static KeySym cmdkeysym[4];
diff -r 48e2029f6d04 -r 6a5aff2c4bb5 dwm.suckless.org/patches/keymodes.md
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dwm.suckless.org/patches/keymodes.md	Fri Jun 11 16:47:32 2010 +0200
_AT_@ -0,0 +1,56 @@
+# KEYMODES #
+
+## Description ##
+
+This patch provides key modes (like in Vim). There are two key modes:
+
+ 1. `COMMANDMODE`: In this mode any key is grabbed and only the registered command keys have any effect.
+ 2. `INSERTMODE`:  This is the normal key mode, in which the original key bindings of dwm and applications are effective and text can be entered.
+
+With key modes you can use any key binding for window management without risking conflicts with existing key bindings in applications.
+
+There are two different patches:
+
+ * keymodes: the minimal patch
+ * vim-keymodes: This patch tries to emulate the key bindings of Vim. Therefor it includes additional functions, which depend on the [flextile patch](../flextile).
+
+
+## Configuration ##
+
+ (1) Download the favoured patch and apply it according to the [general instructions](.). If you choose vim-keymodes you will have to apply the flextile patch first.
+
+ (2) Transfer the changes made by the patch in 'config.def.h' to your 'config.h', if needed; please see the patch file for details.
+
+ (3) Verify the following lines in the aforementioned arrays:
+
+     static Key keys[] = {
+         /* modifier             key                 function       argument */
+         { MODKEY,               XK_Escape,          setkeymode,    {.ui = COMMANDMODE} },
+
+     static Key cmdkeys[] = {
+         /* modifier             keys                function       argument */
+         { 0,                    XK_Escape,          clearcmd,      {0} },
+         { ControlMask,          XK_c,               clearcmd,      {0} },
+         { 0,                    XK_i,               setkeymode,    {.ui = INSERTMODE} },
+     };
+     static Command commands[] = {
+         /* modifier (4 keys)    keysyms (4 keys)    function       argument */
+         ...
+     };
+
+     The entries in the `cmdkeys` array are defined like those in the original `keys` array of dwm and take precedence over the key bindings defined in the `commands` array. The modifier and keysym definitions in the `commands` array are themselves arrays with four entries, whereas the first entry in the modifier array corresponds to the first entry in the keysym array and so forth.
+
+
+## Usage ##
+
+With this patch dwm starts in `COMMANDMODE` and you can use the key bindings as defined in the `commands` array in `config.h`. Press `Escape` or `CTRL+c` to abort a command input and press `i` (in the default configuration) to enter `INSERTMODE` and use dwm normally with the key bindings defined in the `keys` array, navigate in applications and insert text. To get from `INSERTMODE` to `COMMANDMODE` press `ALT+Escape` (in the default configuration).
+
+
+## Download ##
+
+ * [keymodes-5.8.2.diff][1] (8.4k, +152 SLOC) (20100611, joten (at) freenet (dot) de)
+ * [keymodes-5.8.2-vim.diff][2] (22k, +446 SLOC) (20100611, joten (at) freenet (dot) de)
+
+
+[1]: http://dwm.suckless.org/patches/keymodes-5.8.2.diff
+[2]: http://dwm.suckless.org/patches/keymodes-5.8.2-vim.diff
Received on Fri Jun 11 2010 - 16:47:44 CEST

This archive was generated by hypermail 2.3.0 : Thu Sep 13 2012 - 19:31:18 CEST