<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>dwm/config.def.h</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,25 +1,29 @@
 MIT/X Consortium License
 
-&#169; 2006-2007 Anselm R. Garbe &lt;garbeam at gmail dot com&gt;
+&#169; 2006-2008 Anselm R Garbe &lt;garbeam at gmail dot com&gt;
 &#169; 2006-2007 Sander van Dijk &lt;a dot h dot vandijk at gmail dot com&gt;
 &#169; 2006-2007 Jukka Salmi &lt;jukka at salmi dot ch&gt;
 &#169; 2007 Premysl Hruby &lt;dfenze at gmail dot com&gt;
 &#169; 2007 Szabolcs Nagy &lt;nszabolcs at gmail dot com&gt;
+&#169; 2007 Christof Musik &lt;christof at sendfax dot de&gt;
+&#169; 2007-2008 Enno Gottox Boland &lt;gottox at s01 dot de&gt;
+&#169; 2007-2008 Peter Hartlich &lt;sgkkr at hartlich dot com&gt;
+&#169; 2008 Martin Hurton &lt;martin dot hurton at gmail dot com&gt;
 
 Permission is hereby granted, free of charge, to any person obtaining a
 copy of this software and associated documentation files (the &quot;Software&quot;),
 to deal in the Software without restriction, including without limitation
 the rights to use, copy, modify, merge, publish, distribute, sublicense,
-and/or sell copies of the Software, and to permit persons to whom the 
+and/or sell copies of the Software, and to permit persons to whom the
 Software is furnished to do so, subject to the following conditions:
 
-The above copyright notice and this permission notice shall be included in 
-all copies or substantial portions of the Software. 
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
 
-THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL 
-THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+THE SOFTWARE IS PROVIDED &quot;AS IS&quot;, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 DEALINGS IN THE SOFTWARE.</diff>
      <filename>dwm/LICENSE</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,5 @@
 # dwm - dynamic window manager
-# &#169; 2006-2007 Anselm R. Garbe, Sander van Dijk
+# See LICENSE file for copyright and license details.
 
 include config.mk
 </diff>
      <filename>dwm/Makefile</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,5 @@
-This is a small &quot;fork&quot; that I use myself, mostly changes to config.h.
+This is my own little &quot;fork&quot; that I use... mostly changes to config.h
+
 
 dwm - dynamic window manager
 ============================</diff>
      <filename>dwm/README</filename>
    </modified>
    <modified>
      <diff>@@ -1,125 +1,125 @@
 /* See LICENSE file for copyright and license details. */
 
 /* appearance */
-#define BARPOS			BarTop /* BarBot, BarOff */
-#define BORDERPX			1
-#define FONT				&quot;-*-terminus-medium-*-*-*-*-*-*-*-*-*-*-*&quot;
-#define NORMBORDERCOLOR	&quot;#cccccc&quot;
-#define NORMBGCOLOR		&quot;#cccccc&quot;
-#define NORMFGCOLOR		&quot;#000000&quot;
-#define SELBORDERCOLOR	&quot;#0033aa&quot;
-#define SELBGCOLOR		&quot;#0033aa&quot;
-#define SELFGCOLOR		&quot;#ffffff&quot;
+static const char font[]            = &quot;-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*&quot;;
+static const char normbordercolor[] = &quot;#cccccc&quot;;
+static const char normbgcolor[]     = &quot;#cccccc&quot;;
+static const char normfgcolor[]     = &quot;#000000&quot;;
+static const char selbordercolor[]  = &quot;#0066ff&quot;;
+static const char selbgcolor[]      = &quot;#0066ff&quot;;
+static const char selfgcolor[]      = &quot;#ffffff&quot;;
+static unsigned int borderpx        = 1;        /* border pixel of windows */
+static unsigned int snap            = 32;       /* snap pixel */
+static Bool showbar                 = True;     /* False means no bar */
+static Bool topbar                  = True;     /* False means bottom bar */
+static Bool readin                  = True;     /* False means do not read stdin */
+static Bool usegrab                 = False;    /* True means grabbing the X server
+                                                   during mouse-based resizals */
 
 /* tagging */
-const char *tags[] = { &quot;www&quot;, &quot;term&quot;, &quot;chat&quot;, &quot;mail&quot;, &quot;5&quot;, &quot;6&quot;, &quot;7&quot;, &quot;8&quot;, &quot;media&quot; };
+static const char tags[][MAXTAGLEN] = { &quot;www&quot;, &quot;term&quot;, &quot;chat&quot;, &quot;mail&quot;, &quot;5&quot;, &quot;6&quot;, &quot;7&quot;, &quot;8&quot;, &quot;media&quot; };
+static unsigned int tagset[] = {2, 2}; /* after start, first tag is selected */
+
 static Rule rules[] = {
-	/* class:instance:title regex	tags regex	isfloating */
-	{ &quot;Gimp&quot;,					NULL,			True },
-	{ &quot;Network Settings&quot;,	NULL, 		True },
-	{ &quot;gksu&quot;,					NULL,			True },
-	{ &quot;System Monitor&quot;,  	NULL,			True },
-	{ &quot;MPlayer&quot;,				&quot;media&quot;,		True },
-	{ &quot;Rhythmbox&quot;,				&quot;media&quot;,		False },
-	{ &quot;cmus&quot;,					&quot;media&quot;,		False },
-	{ &quot;mediacentre&quot;,			&quot;media&quot;,		False },
-	{ &quot;totem&quot;,					&quot;media&quot;,		False },
-	{ &quot;Firefox&quot;,				&quot;www&quot;,		False },
-	{ &quot;Flock&quot;,					&quot;www&quot;,		False },
-	{ &quot;Gecko&quot;,					&quot;www&quot;,		False },
-	{ &quot;lynx&quot;,					&quot;www&quot;,		False },
-	{ &quot;links2&quot;,					&quot;www&quot;,		False },
-	{ &quot;w3m&quot;,						&quot;www&quot;,		False },
-	{ &quot;psi&quot;,						&quot;chat&quot;,		False },
-	{ &quot;chat&quot;,					&quot;chat&quot;,		False },
-	{ &quot;gaim&quot;,					&quot;chat&quot;,		False },
-	{ &quot;sic&quot;,						&quot;chat&quot;,		False },
-	{ &quot;rxvt&quot;,					&quot;term&quot;,		False },
-	{ &quot;gedit&quot;,					&quot;term&quot;,		False },
-	{ &quot;thunar&quot;,					&quot;term&quot;,		False },
-	{ &quot;pdmenu&quot;,					&quot;.*&quot;,			False },
-	{ &quot;mutt&quot;,					&quot;mail&quot;,			False },
+	/* class      instance    title       tags mask     isfloating */
+	{ &quot;Gimp&quot;,     NULL,       NULL,       0,            True },
+	{ NULL,       NULL,       &quot;Passphrase&quot;,       0,    True },
+	{ NULL,       NULL,       &quot;Network Settings&quot;, 0, True },
+	{ NULL,       NULL,       &quot;gksu&quot;,             0, True },
+	{ NULL,       NULL,       &quot;System Monitor&quot;,   0, True },
+	{ &quot;Firefox&quot;,  NULL,       NULL,       1 &lt;&lt; 0,       False },
+	{ &quot;URxvt&quot;,    NULL,       NULL,       1 &lt;&lt; 1,       False },
+	{ &quot;Gedit&quot;,    NULL,       NULL,       1 &lt;&lt; 1,       False },
+	{ &quot;Thunar&quot;,   NULL,       NULL,       1 &lt;&lt; 1,       False },
+	{ NULL,       NULL,       &quot;Psi&quot;,      1 &lt;&lt; 2,       False },
+	{ NULL,       NULL,       &quot;mutt&quot;,     1 &lt;&lt; 3,       False },
+	{ NULL,       NULL,       &quot;cmus&quot;,     1 &lt;&lt; 8,       False },
+	{ NULL,       NULL,       &quot;mediacentre&quot;,      1 &lt;&lt; 8,       False },
 };
 
 /* layout(s) */
-#define ISTILE			isarrange(tile) /* || isarrange(&lt;custom&gt;) */
-#define MWFACT			0.6	/* master width factor [0.1 .. 0.9] */
-#define SNAP			32	/* snap pixel */
-Layout layouts[] = {
-	/* symbol		function */
-	{ &quot;[]=&quot;,		tile }, /* first entry is default */
-	{ &quot;&gt;&lt;&gt;&quot;,		floating },
+static float mfact      = 0.55; /* factor of master area size [0.05..0.95] */
+static Bool resizehints = True; /* False means respect size hints in tiled resizals */
+
+static Layout layouts[] = {
+	/* symbol     arrange function */
+	{ &quot;[]=&quot;,      tile },    /* first entry is default */
+	{ &quot;&gt;&lt;&gt;&quot;,      NULL },    /* no layout function means floating behavior */
+	{ &quot;[M]&quot;,      monocle },
 };
 
 /* key definitions */
-#define MODKEY			Mod1Mask
-#define KEYS \
-Key keys[] = { \
-	/* modifier			key		function	argument */ \
-	{ MODKEY|ShiftMask,			XK_Return,	spawn,		&quot;exec urxvt&quot; }, \
-	{ MODKEY|ControlMask,		XK_Return,	spawn,		&quot;exec urxvt -e pdmenu -c -u&quot; }, \
-	{ MODKEY|ControlMask,		XK_space,		spawn,		&quot;dmenu_path | dmenu | history-exec&quot; }, \
-	{ MODKEY|ControlMask|ShiftMask, XK_space,	spawn, 		&quot;lsw -visible | dmenu&quot; }, \
-	{ MODKEY|ControlMask,		XK_y,			spawn, 		&quot;echo \&quot;y `echo \&quot;- uwace\n- jobmine\n- quest\&quot; | dmenu`\&quot; | history-exec&quot; }, \
-	{ 0,					XK_F4,		spawn, 		&quot;exec rxvt&quot; }, \
-	{ 0,					XK_F5,		spawn, 		&quot;thunar ~/&quot; }, \
-	{ 0,					XK_F6,		spawn, 		&quot;exec urxvt -name cmus -e cmus&quot; }, \
-	{ MODKEY,			XK_F6,		spawn, 		&quot;exec urxvt -name mediacentre -e ssh singpolyma.dnsalias.net&quot; }, \
-	{ 0,					XK_F7,		spawn, 		&quot;firefox&quot; }, \
-	{ MODKEY,			XK_F7,		spawn, 		&quot;psi&quot; }, \
-	{ 0,					XK_F8,		spawn, 		&quot;exec urxvt -name mutt -e mutt&quot; }, \
-	{ MODKEY|ControlMask,		XK_n,		spawn, 		&quot;network-admin&quot; }, \
-	{ MODKEY|ControlMask,		XK_l,		spawn, 		&quot;sleep 0.1 &amp;&amp; slock&quot; }, \
-	{ MODKEY|ControlMask,		XK_Delete,	spawn, 		&quot;gnome-power-cmd.sh shutdown&quot; }, \
-	{ MODKEY,			XK_space,	setlayout,	NULL }, \
-	{ MODKEY,			XK_b,		togglebar,	NULL }, \
-	{ MODKEY,			XK_Tab,		focusprev,	NULL }, \
-	{ MODKEY,			XK_Tab,		zoom,	 	NULL }, \
-	{ MODKEY,			XK_j,		focusnext,	NULL }, \
-	{ MODKEY,			XK_k,		focusprev,	NULL }, \
-	{ MODKEY,			XK_h,		setmwfact,	&quot;-0.05&quot; }, \
-	{ MODKEY,			XK_l,		setmwfact,	&quot;+0.05&quot; }, \
-	{ MODKEY,			XK_m,		togglemax,	NULL }, \
-	{ MODKEY,			XK_Return,	zoom,		NULL }, \
-	{ MODKEY|ShiftMask,		XK_space,	togglefloating,	NULL }, \
-	{ MODKEY,			XK_F4,		killclient,	NULL }, \
-	{ MODKEY,			XK_0,		view,		NULL }, \
-	{ MODKEY,			XK_1,		view,		tags[0] }, \
-	{ MODKEY,			XK_2,		view,		tags[1] }, \
-	{ MODKEY,			XK_3,		view,		tags[2] }, \
-	{ MODKEY,			XK_4,		view,		tags[3] }, \
-	{ MODKEY,			XK_5,		view,		tags[4] }, \
-	{ MODKEY,			XK_6,		view,		tags[5] }, \
-	{ MODKEY,			XK_7,		view,		tags[6] }, \
-	{ MODKEY,			XK_8,		view,		tags[7] }, \
-	{ MODKEY,			XK_9,		view,		tags[8] }, \
-	{ MODKEY|ControlMask,		XK_1,		toggleview,	tags[0] }, \
-	{ MODKEY|ControlMask,		XK_2,		toggleview,	tags[1] }, \
-	{ MODKEY|ControlMask,		XK_3,		toggleview,	tags[2] }, \
-	{ MODKEY|ControlMask,		XK_4,		toggleview,	tags[3] }, \
-	{ MODKEY|ControlMask,		XK_5,		toggleview,	tags[4] }, \
-	{ MODKEY|ControlMask,		XK_6,		toggleview,	tags[5] }, \
-	{ MODKEY|ControlMask,		XK_7,		toggleview,	tags[6] }, \
-	{ MODKEY|ControlMask,		XK_8,		toggleview,	tags[7] }, \
-	{ MODKEY|ControlMask,		XK_9,		toggleview,	tags[8] }, \
-	{ MODKEY|ShiftMask,		XK_0,		tag,		NULL }, \
-	{ MODKEY|ShiftMask,		XK_1,		tag,		tags[0] }, \
-	{ MODKEY|ShiftMask,		XK_2,		tag,		tags[1] }, \
-	{ MODKEY|ShiftMask,		XK_3,		tag,		tags[2] }, \
-	{ MODKEY|ShiftMask,		XK_4,		tag,		tags[3] }, \
-	{ MODKEY|ShiftMask,		XK_5,		tag,		tags[4] }, \
-	{ MODKEY|ShiftMask,		XK_6,		tag,		tags[5] }, \
-	{ MODKEY|ShiftMask,		XK_7,		tag,		tags[6] }, \
-	{ MODKEY|ShiftMask,		XK_8,		tag,		tags[7] }, \
-	{ MODKEY|ShiftMask,		XK_9,		tag,		tags[8] }, \
-	{ MODKEY|ControlMask|ShiftMask,	XK_1,		toggletag,	tags[0] }, \
-	{ MODKEY|ControlMask|ShiftMask,	XK_2,		toggletag,	tags[1] }, \
-	{ MODKEY|ControlMask|ShiftMask,	XK_3,		toggletag,	tags[2] }, \
-	{ MODKEY|ControlMask|ShiftMask,	XK_4,		toggletag,	tags[3] }, \
-	{ MODKEY|ControlMask|ShiftMask,	XK_5,		toggletag,	tags[4] }, \
-	{ MODKEY|ControlMask|ShiftMask,	XK_6,		toggletag,	tags[5] }, \
-	{ MODKEY|ControlMask|ShiftMask,	XK_7,		toggletag,	tags[6] }, \
-	{ MODKEY|ControlMask|ShiftMask,	XK_8,		toggletag,	tags[7] }, \
-	{ MODKEY|ControlMask|ShiftMask,	XK_9,		toggletag,	tags[8] }, \
-	{ MODKEY|ShiftMask,		XK_q,		quit,		NULL }, \
+#define MODKEY Mod1Mask
+#define TAGKEYS(KEY,TAG) \
+	{ MODKEY,                       KEY,      view,           {.ui = 1 &lt;&lt; TAG} }, \
+	{ MODKEY|ControlMask,           KEY,      toggleview,     {.ui = 1 &lt;&lt; TAG} }, \
+	{ MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 &lt;&lt; TAG} }, \
+	{ MODKEY|ControlMask|ShiftMask, KEY,      toggletag,      {.ui = 1 &lt;&lt; TAG} },
+
+/* helper for spawning shell commands in the pre dwm-5.0 fashion */
+#define SHCMD(cmd) { .v = (const char*[]){ &quot;/bin/sh&quot;, &quot;-c&quot;, cmd, NULL } }
+
+/* commands */
+static const char *dmenucmd[] = { &quot;dmenu_run&quot;, &quot;-fn&quot;, font, &quot;-nb&quot;, normbgcolor, &quot;-nf&quot;, normfgcolor, &quot;-sb&quot;, selbgcolor, &quot;-sf&quot;, selfgcolor, NULL };
+static const char *termcmd[]  = { &quot;rxvt&quot;, NULL };
+
+static Key keys[] = {
+	/* modifier                     key        function        argument */
+	{ MODKEY|ControlMask,           XK_space,  spawn,          {.v = dmenucmd } },
+	{ MODKEY|ShiftMask,             XK_Return, spawn,          {.v = termcmd } },
+	{ 0,                            XK_F4,     spawn,          {.v = termcmd } },
+	{ 0,                            XK_F5,     spawn,          SHCMD(&quot;thunar ~/&quot;) },
+	{ 0,                            XK_F6,     spawn,          SHCMD(&quot;exec xterm -name cmus -e cmus&quot;) },
+	{ MODKEY,                       XK_F6,     spawn,          SHCMD(&quot;exec xterm -name mediacentre -e ssh singpolyma.dnsalias.net&quot;) },
+	{ 0,                            XK_F7,     spawn,          SHCMD(&quot;sensible-browser&quot;) },
+	{ MODKEY,                       XK_F7,     spawn,          SHCMD(&quot;psi&quot;) },
+	{ 0,                            XK_F8,     spawn,          SHCMD(&quot;exec xterm -name mutt -e mutt&quot;) },
+	{ MODKEY|ControlMask,           XK_l,      spawn,          SHCMD(&quot;sleep 0.1 &amp;&amp; slock&quot;) },
+	{ MODKEY|ControlMask,           XK_Delete, spawn,          SHCMD(&quot;gnome-power-cmd.sh shutdown&quot;) },
+	{ MODKEY,                       XK_Tab,    focusstack,     {.i = -1} },
+	{ MODKEY,                       XK_Tab,    zoom,           {0} },
+	{ MODKEY,                       XK_F4,     killclient,     {0} },
+	{ MODKEY,                       XK_b,      togglebar,      {0} },
+	{ MODKEY,                       XK_j,      focusstack,     {.i = +1 } },
+	{ MODKEY,                       XK_k,      focusstack,     {.i = -1 } },
+	{ MODKEY,                       XK_h,      setmfact,       {.f = -0.05} },
+	{ MODKEY,                       XK_l,      setmfact,       {.f = +0.05} },
+	{ MODKEY,                       XK_Return, zoom,           {0} },
+	{ MODKEY|ShiftMask,             XK_c,      killclient,     {0} },
+	{ MODKEY,                       XK_t,      setlayout,      {.v = &amp;layouts[0]} },
+	{ MODKEY,                       XK_f,      setlayout,      {.v = &amp;layouts[1]} },
+	{ MODKEY,                       XK_m,      setlayout,      {.v = &amp;layouts[2]} },
+	{ MODKEY,                       XK_space,  setlayout,      {0} },
+	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} },
+	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } },
+	{ MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } },
+	TAGKEYS(                        XK_1,                      0)
+	TAGKEYS(                        XK_2,                      1)
+	TAGKEYS(                        XK_3,                      2)
+	TAGKEYS(                        XK_4,                      3)
+	TAGKEYS(                        XK_5,                      4)
+	TAGKEYS(                        XK_6,                      5)
+	TAGKEYS(                        XK_7,                      6)
+	TAGKEYS(                        XK_8,                      7)
+	TAGKEYS(                        XK_9,                      8)
+	{ MODKEY|ShiftMask,             XK_q,      quit,           {0} },
+};
+
+/* button definitions */
+/* click can be a tag number (starting at 0),
+ * ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
+static Button buttons[] = {
+	/* click                event mask      button          function        argument */
+	{ ClkLtSymbol,          0,              Button1,        setlayout,      {0} },
+	{ ClkLtSymbol,          0,              Button3,        setlayout,      {.v = &amp;layouts[2]} },
+	{ ClkWinTitle,          0,              Button2,        zoom,           {0} },
+	{ ClkStatusText,        0,              Button2,        spawn,          {.v = termcmd } },
+	{ ClkClientWin,         MODKEY,         Button1,        movemouse,      {0} },
+	{ ClkClientWin,         MODKEY,         Button2,        togglefloating, {0} },
+	{ ClkClientWin,         MODKEY,         Button3,        resizemouse,    {0} },
+	{ ClkTagBar,            0,              Button1,        view,           {0} },
+	{ ClkTagBar,            0,              Button3,        toggleview,     {0} },
+	{ ClkTagBar,            MODKEY,         Button1,        tag,            {0} },
+	{ ClkTagBar,            MODKEY,         Button3,        toggletag,      {0} },
 };
+</diff>
      <filename>dwm/config.h</filename>
    </modified>
    <modified>
      <diff>@@ -1,29 +1,31 @@
 # dwm version
-VERSION = 4.6
+VERSION = 5.3.1
 
 # Customize below to fit your system
 
 # paths
-PREFIX = /usr
+PREFIX = /usr/local
 MANPREFIX = ${PREFIX}/share/man
 
 X11INC = /usr/X11R6/include
 X11LIB = /usr/X11R6/lib
 
+# Xinerama, un-comment if you want it
+#XINERAMALIBS = -L${X11LIB} -lXinerama
+#XINERAMAFLAGS = -DXINERAMA
+
 # includes and libs
 INCS = -I. -I/usr/include -I${X11INC}
-LIBS = -L/usr/lib -lc -L${X11LIB} -lX11
+LIBS = -L/usr/lib -lc -L${X11LIB} -lX11 ${XINERAMALIBS}
 
 # flags
-CFLAGS = -Os ${INCS} -DVERSION=\&quot;${VERSION}\&quot;
+CPPFLAGS = -DVERSION=\&quot;${VERSION}\&quot; ${XINERAMAFLAGS}
+CFLAGS = -std=c99 -pedantic -Wall -Os ${INCS} ${CPPFLAGS}
 LDFLAGS = -s ${LIBS}
-CFLAGS = -g -std=c99 -pedantic -Wall -O2 ${INCS} -DVERSION=\&quot;${VERSION}\&quot;
-LDFLAGS = -g ${LIBS}
 
 # Solaris
 #CFLAGS = -fast ${INCS} -DVERSION=\&quot;${VERSION}\&quot;
 #LDFLAGS = ${LIBS}
-#CFLAGS += -xtarget=ultra
 
 # compiler and linker
 CC = cc</diff>
      <filename>dwm/config.mk</filename>
    </modified>
    <modified>
      <diff>@@ -5,22 +5,23 @@ dwm \- dynamic window manager
 .B dwm
 .RB [ \-v ]
 .SH DESCRIPTION
-dwm is a dynamic window manager for X. It manages windows in tiled and
-floating layouts. Either layout can be applied dynamically, optimizing the
+dwm is a dynamic window manager for X. It manages windows in tiled, monocle
+and floating layouts. Either layout can be applied dynamically, optimising the
 environment for the application in use and the task performed.
 .P
-In tiled layout windows are managed in a master and stacking area. The master
+In tiled layouts windows are managed in a master and stacking area. The master
 area contains the window which currently needs most attention, whereas the
-stacking area contains all other windows. In floating layout windows can be
-resized and moved freely. Dialog windows are always managed floating,
-regardless of the layout applied.
+stacking area contains all other windows. In monocle layout all windows are
+maximised to the screen size. In floating layout windows can be resized and
+moved freely. Dialog windows are always managed floating, regardless of the
+layout applied.
 .P
 Windows are grouped by tags. Each window can be tagged with one or multiple
 tags. Selecting certain tags displays all windows with these tags.
 .P
 dwm contains a small status bar which displays all available tags, the layout,
 the title of the focused window, and the text read from standard input. A
-floating window is indicated with an empty square and a maximized
+floating window is indicated with an empty square and a maximised
 floating window is indicated with a filled square before the windows
 title.  The selected tags are indicated with a different color. The tags of
 the focused window are indicated with a filled square in the top left
@@ -56,17 +57,20 @@ click on a tag label adds/removes that tag to/from the focused window.
 Start
 .BR xterm.
 .TP
-.B Mod1\-Return
-Zooms/cycles current window to/from master area (tiled layout only).
+.B Mod1\-b
+Toggles bar on and off.
 .TP
-.B Mod1\-Tab
-Toggles to the previously selected tags.
+.B Mod1\-t
+Sets tiled layout.
 .TP
-.B Mod1\-b
-Shows/hides the status bar.
+.B Mod1\-f
+Sets floating layout.
 .TP
-.B Mod1\-h
-Decreases the master area width about 5% (tiled layout only).
+.B Mod1\-m
+Sets monocle layout.
+.TP
+.B Mod1\-space
+Toggles between current and previous layout.
 .TP
 .B Mod1\-j
 Focus next window.
@@ -74,33 +78,36 @@ Focus next window.
 .B Mod1\-k
 Focus previous window.
 .TP
+.B Mod1\-h
+Decrease master area size.
+.TP
 .B Mod1\-l
-Increases the master area width about 5% (tiled layout only).
+Increase master area size.
 .TP
-.B Mod1\-m
-Toggles maximization of current window.
+.B Mod1\-Return
+Zooms/cycles focused window to/from master area (tiled layouts only).
+.TP
+.B Mod1\-Shift\-c
+Close focused window.
+.TP
+.B Mod1\-Shift\-space
+Toggle focused window between tiled and floating state.
+.TP
+.B Mod1\-Tab
+Toggles to the previously selected tags.
 .TP
 .B Mod1\-Shift\-[1..n]
 Apply
 .RB nth
-tag to current window.
+tag to focused window.
 .TP
 .B Mod1\-Shift\-0
-Apply all tags to current window.
+Apply all tags to focused window.
 .TP
 .B Mod1\-Control\-Shift\-[1..n]
 Add/remove
 .B nth
-tag to/from current window.
-.TP
-.B Mod1\-Shift\-c
-Close focused window.
-.TP
-.B Mod1\-space
-Toggle between tiled and floating layout (affects all windows).
-.TP
-.B Mod1\-Shift\-space
-Toggle focused window between tiled and floating state.
+tag to/from focused window.
 .TP
 .B Mod1\-[1..n]
 View all windows with
@@ -120,13 +127,13 @@ Quit dwm.
 .SS Mouse commands
 .TP
 .B Mod1\-Button1
-Move current window while dragging. Tiled windows will be toggled to the floating state.
+Move focused window while dragging. Tiled windows will be toggled to the floating state.
 .TP
 .B Mod1\-Button2
-Zooms/cycles current window to/from master area. If it is floating (but not fixed) it will be toggled to the tiled state instead.
+Toggles focused window between floating and tiled state.
 .TP
 .B Mod1\-Button3
-Resize current window while dragging. Tiled windows will be toggled to the floating state.
+Resize focused window while dragging. Tiled windows will be toggled to the floating state.
 .SH CUSTOMIZATION
 dwm is customized by creating a custom config.h and (re)compiling the source
 code. This keeps it fast, secure and simple.
@@ -147,7 +154,7 @@ can set the following environment variable (to use the older Motif
 backend instead):
 .BR AWT_TOOLKIT=MToolkit .
 .P
-Recent GTK 2.10.9+ versions contain a broken
+GTK 2.10.9+ versions contain a broken
 .BR Save\-As
 file dialog implementation,
 which requests to reconfigure its window size in an endless loop. However, its</diff>
      <filename>dwm/dwm.1</filename>
    </modified>
    <modified>
      <diff>@@ -15,11 +15,9 @@
  *
  * Each child of the root window is called a client, except windows which have
  * set the override_redirect flag.  Clients are organized in a global
- * doubly-linked client list, the focus history is remembered through a global
- * stack list. Each client contains an array of Bools of the same size as the
- * global tags array to indicate the tags of a client.  For each client dwm
- * creates a small title window, which is resized whenever the (_NET_)WM_NAME
- * properties are updated or the client is moved/resized.
+ * linked client list, the focus history is remembered through a global
+ * stack list. Each client contains a bit array to indicate the tags of a
+ * client.
  *
  * Keys and tagging rules are organized as arrays and defined in config.h.
  *
@@ -35,40 +33,64 @@
 #include &lt;sys/select.h&gt;
 #include &lt;sys/types.h&gt;
 #include &lt;sys/wait.h&gt;
-#include &lt;regex.h&gt;
 #include &lt;X11/cursorfont.h&gt;
 #include &lt;X11/keysym.h&gt;
 #include &lt;X11/Xatom.h&gt;
 #include &lt;X11/Xlib.h&gt;
 #include &lt;X11/Xproto.h&gt;
 #include &lt;X11/Xutil.h&gt;
+#ifdef XINERAMA
+#include &lt;X11/extensions/Xinerama.h&gt;
+#endif
 
 /* macros */
-#define BUTTONMASK		(ButtonPressMask | ButtonReleaseMask)
-#define CLEANMASK(mask)		(mask &amp; ~(numlockmask | LockMask))
-#define MOUSEMASK		(BUTTONMASK | PointerMotionMask)
+#define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
+#define CLEANMASK(mask)         (mask &amp; ~(numlockmask|LockMask))
+#define INRECT(X,Y,RX,RY,RW,RH) ((X) &gt;= (RX) &amp;&amp; (X) &lt; (RX) + (RW) &amp;&amp; (Y) &gt;= (RY) &amp;&amp; (Y) &lt; (RY) + (RH))
+#define ISVISIBLE(x)            (x-&gt;tags &amp; tagset[seltags])
+#define LENGTH(x)               (sizeof x / sizeof x[0])
+#define MAX(a, b)               ((a) &gt; (b) ? (a) : (b))
+#define MIN(a, b)               ((a) &lt; (b) ? (a) : (b))
+#define MAXTAGLEN               16
+#define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
+#define WIDTH(x)                ((x)-&gt;w + 2 * (x)-&gt;bw)
+#define HEIGHT(x)               ((x)-&gt;h + 2 * (x)-&gt;bw)
+#define TAGMASK                 ((int)((1LL &lt;&lt; LENGTH(tags)) - 1))
+#define TEXTW(x)                (textnw(x, strlen(x)) + dc.font.height)
 
 /* enums */
-enum { BarTop, BarBot, BarOff };			/* bar position */
-enum { CurNormal, CurResize, CurMove, CurLast };	/* cursor */
-enum { ColBorder, ColFG, ColBG, ColLast };		/* color */
-enum { NetSupported, NetWMName, NetLast };		/* EWMH atoms */
-enum { WMProtocols, WMDelete, WMName, WMState, WMLast };/* default atoms */
+enum { CurNormal, CurResize, CurMove, CurLast };        /* cursor */
+enum { ColBorder, ColFG, ColBG, ColLast };              /* color */
+enum { NetSupported, NetWMName, NetLast };              /* EWMH atoms */
+enum { WMProtocols, WMDelete, WMState, WMLast };        /* default atoms */
+enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
+       ClkClientWin, ClkRootWin, ClkLast };             /* clicks */
+
+typedef union {
+	int i;
+	unsigned int ui;
+	float f;
+	void *v;
+} Arg;
+
+typedef struct {
+	unsigned int click;
+	unsigned int mask;
+	unsigned int button;
+	void (*func)(const Arg *arg);
+	const Arg arg;
+} Button;
 
-/* typedefs */
 typedef struct Client Client;
 struct Client {
 	char name[256];
+	float mina, maxa;
 	int x, y, w, h;
-	int rx, ry, rw, rh; /* revert geometry */
 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
-	int minax, maxax, minay, maxay;
-	long flags;
-	unsigned int border, oldborder;
-	Bool isbanned, isfixed, ismax, isfloating, wasfloating;
-	Bool *tags;
+	int bw, oldbw;
+	unsigned int tags;
+	Bool isfixed, isfloating, isurgent;
 	Client *next;
-	Client *prev;
 	Client *snext;
 	Window win;
 };
@@ -89,10 +111,10 @@ typedef struct {
 } DC; /* draw context */
 
 typedef struct {
-	unsigned long mod;
+	unsigned int mod;
 	KeySym keysym;
-	void (*func)(const char *arg);
-	const char *arg;
+	void (*func)(const Arg *);
+	const Arg arg;
 } Key;
 
 typedef struct {
@@ -101,191 +123,165 @@ typedef struct {
 } Layout;
 
 typedef struct {
-	const char *prop;
-	const char *tags;
+	const char *class;
+	const char *instance;
+	const char *title;
+	unsigned int tags;
 	Bool isfloating;
 } Rule;
 
-typedef struct {
-	regex_t *propregex;
-	regex_t *tagregex;
-} Regs;
-
 /* function declarations */
-void applyrules(Client *c);
-void arrange(void);
-void attach(Client *c);
-void attachstack(Client *c);
-void ban(Client *c);
-void buttonpress(XEvent *e);
-void checkotherwm(void);
-void cleanup(void);
-void compileregs(void);
-void configure(Client *c);
-void configurenotify(XEvent *e);
-void configurerequest(XEvent *e);
-void destroynotify(XEvent *e);
-void detach(Client *c);
-void detachstack(Client *c);
-void drawbar(void);
-void drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]);
-void drawtext(const char *text, unsigned long col[ColLast]);
-void *emallocz(unsigned int size);
-void enternotify(XEvent *e);
-void eprint(const char *errstr, ...);
-void expose(XEvent *e);
-void floating(void); /* default floating layout */
-void focus(Client *c);
-void focusnext(const char *arg);
-void focusprev(const char *arg);
-Client *getclient(Window w);
-unsigned long getcolor(const char *colstr);
-long getstate(Window w);
-Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
-void grabbuttons(Client *c, Bool focused);
-unsigned int idxoftag(const char *tag);
-void initfont(const char *fontstr);
-Bool isarrange(void (*func)());
-Bool isoccupied(unsigned int t);
-Bool isprotodel(Client *c);
-Bool isvisible(Client *c);
-void keypress(XEvent *e);
-void killclient(const char *arg);
-void leavenotify(XEvent *e);
-void manage(Window w, XWindowAttributes *wa);
-void mappingnotify(XEvent *e);
-void maprequest(XEvent *e);
-void movemouse(Client *c);
-Client *nexttiled(Client *c);
-void propertynotify(XEvent *e);
-void quit(const char *arg);
-void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
-void resizemouse(Client *c);
-void restack(void);
-void run(void);
-void scan(void);
-void setclientstate(Client *c, long state);
-void setlayout(const char *arg);
-void setmwfact(const char *arg);
-void setup(void);
-void spawn(const char *arg);
-void tag(const char *arg);
-unsigned int textnw(const char *text, unsigned int len);
-unsigned int textw(const char *text);
-void tile(void);
-void togglebar(const char *arg);
-void togglefloating(const char *arg);
-void togglemax(const char *arg);
-void toggletag(const char *arg);
-void toggleview(const char *arg);
-void unban(Client *c);
-void unmanage(Client *c);
-void unmapnotify(XEvent *e);
-void updatebarpos(void);
-void updatesizehints(Client *c);
-void updatetitle(Client *c);
-void view(const char *arg);
-void viewprevtag(const char *arg);	/* views previous selected tags */
-int xerror(Display *dpy, XErrorEvent *ee);
-int xerrordummy(Display *dsply, XErrorEvent *ee);
-int xerrorstart(Display *dsply, XErrorEvent *ee);
-void zoom(const char *arg);
+static void applyrules(Client *c);
+static void arrange(void);
+static void attach(Client *c);
+static void attachstack(Client *c);
+static void buttonpress(XEvent *e);
+static void checkotherwm(void);
+static void cleanup(void);
+static void clearurgent(Client *c);
+static void configure(Client *c);
+static void configurenotify(XEvent *e);
+static void configurerequest(XEvent *e);
+static void destroynotify(XEvent *e);
+static void detach(Client *c);
+static void detachstack(Client *c);
+static void die(const char *errstr, ...);
+static void drawbar(void);
+static void drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]);
+static void drawtext(const char *text, unsigned long col[ColLast], Bool invert);
+static void enternotify(XEvent *e);
+static void expose(XEvent *e);
+static void focus(Client *c);
+static void focusin(XEvent *e);
+static void focusstack(const Arg *arg);
+static Client *getclient(Window w);
+static unsigned long getcolor(const char *colstr);
+static long getstate(Window w);
+static Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
+static void grabbuttons(Client *c, Bool focused);
+static void grabkeys(void);
+static void initfont(const char *fontstr);
+static Bool isprotodel(Client *c);
+static void keypress(XEvent *e);
+static void killclient(const Arg *arg);
+static void manage(Window w, XWindowAttributes *wa);
+static void mappingnotify(XEvent *e);
+static void maprequest(XEvent *e);
+static void monocle(void);
+static void movemouse(const Arg *arg);
+static Client *nexttiled(Client *c);
+static void propertynotify(XEvent *e);
+static void quit(const Arg *arg);
+static void resize(Client *c, int x, int y, int w, int h, Bool sizehints);
+static void resizemouse(const Arg *arg);
+static void restack(void);
+static void run(void);
+static void scan(void);
+static void setclientstate(Client *c, long state);
+static void setlayout(const Arg *arg);
+static void setmfact(const Arg *arg);
+static void setup(void);
+static void showhide(Client *c);
+static void spawn(const Arg *arg);
+static void tag(const Arg *arg);
+static int textnw(const char *text, unsigned int len);
+static void tile(void);
+static void togglebar(const Arg *arg);
+static void togglefloating(const Arg *arg);
+static void toggletag(const Arg *arg);
+static void toggleview(const Arg *arg);
+static void unmanage(Client *c);
+static void unmapnotify(XEvent *e);
+static void updatebar(void);
+static void updategeom(void);
+static void updatenumlockmask(void);
+static void updatesizehints(Client *c);
+static void updatetitle(Client *c);
+static void updatewmhints(Client *c);
+static void view(const Arg *arg);
+static int xerror(Display *dpy, XErrorEvent *ee);
+static int xerrordummy(Display *dpy, XErrorEvent *ee);
+static int xerrorstart(Display *dpy, XErrorEvent *ee);
+static void zoom(const Arg *arg);
 
 /* variables */
-char stext[256];
-double mwfact;
-int screen, sx, sy, sw, sh, wax, way, waw, wah;
-int (*xerrorxlib)(Display *, XErrorEvent *);
-unsigned int bh, bpos;
-unsigned int blw = 0;
-unsigned int ltidx = 0; /* default */
-unsigned int nlayouts = 0;
-unsigned int nrules = 0;
-unsigned int numlockmask = 0;
-void (*handler[LASTEvent]) (XEvent *) = {
+static char stext[256];
+static int screen;
+static int sx, sy, sw, sh; /* X display screen geometry x, y, width, height */ 
+static int by, bh, blw;    /* bar geometry y, height and layout symbol width */
+static int wx, wy, ww, wh; /* window area geometry x, y, width, height, bar excluded */
+static unsigned int seltags = 0, sellt = 0;
+static int (*xerrorxlib)(Display *, XErrorEvent *);
+static unsigned int numlockmask = 0;
+static void (*handler[LASTEvent]) (XEvent *) = {
 	[ButtonPress] = buttonpress,
 	[ConfigureRequest] = configurerequest,
 	[ConfigureNotify] = configurenotify,
 	[DestroyNotify] = destroynotify,
 	[EnterNotify] = enternotify,
-	[LeaveNotify] = leavenotify,
 	[Expose] = expose,
+	[FocusIn] = focusin,
 	[KeyPress] = keypress,
 	[MappingNotify] = mappingnotify,
 	[MapRequest] = maprequest,
 	[PropertyNotify] = propertynotify,
 	[UnmapNotify] = unmapnotify
 };
-Atom wmatom[WMLast], netatom[NetLast];
-Bool otherwm, readin;
-Bool running = True;
-Bool selscreen = True;
-Client *clients = NULL;
-Client *sel = NULL;
-Client *stack = NULL;
-Cursor cursor[CurLast];
-Display *dpy;
-DC dc = {0};
-Window barwin, root;
-Regs *regs = NULL;
-
+static Atom wmatom[WMLast], netatom[NetLast];
+static Bool otherwm;
+static Bool running = True;
+static Client *clients = NULL;
+static Client *sel = NULL;
+static Client *stack = NULL;
+static Cursor cursor[CurLast];
+static Display *dpy;
+static DC dc;
+static Layout *lt[] = { NULL, NULL };
+static Window root, barwin;
 /* configuration, allows nested code to access above variables */
 #include &quot;config.h&quot;
 
-#define NTAGS (sizeof tags / sizeof tags[0])
-Bool seltags[NTAGS] = {[0] = True};
-Bool prevtags[NTAGS] = {[0] = True};
+/* compile-time check if all tags fit into an unsigned int bit array. */
+struct NumTags { char limitexceeded[sizeof(unsigned int) * 8 &lt; LENGTH(tags) ? -1 : 1]; };
 
 /* function implementations */
 void
 applyrules(Client *c) {
-	static char buf[512];
-	unsigned int i, j;
-	regmatch_t tmp;
-	Bool matched = False;
+	unsigned int i;
+	Rule *r;
 	XClassHint ch = { 0 };
 
 	/* rule matching */
-	XGetClassHint(dpy, c-&gt;win, &amp;ch);
-	snprintf(buf, sizeof buf, &quot;%s:%s:%s&quot;,
-			ch.res_class ? ch.res_class : &quot;&quot;,
-			ch.res_name ? ch.res_name : &quot;&quot;, c-&gt;name);
-	for(i = 0; i &lt; nrules; i++)
-		if(regs[i].propregex &amp;&amp; !regexec(regs[i].propregex, buf, 1, &amp;tmp, 0)) {
-			c-&gt;isfloating = rules[i].isfloating;
-			for(j = 0; regs[i].tagregex &amp;&amp; j &lt; NTAGS; j++) {
-				if(!regexec(regs[i].tagregex, tags[j], 1, &amp;tmp, 0)) {
-					matched = True;
-					c-&gt;tags[j] = True;
-				}
+	if(XGetClassHint(dpy, c-&gt;win, &amp;ch)) {
+		for(i = 0; i &lt; LENGTH(rules); i++) {
+			r = &amp;rules[i];
+			if((!r-&gt;title || strstr(c-&gt;name, r-&gt;title))
+			&amp;&amp; (!r-&gt;class || (ch.res_class &amp;&amp; strstr(ch.res_class, r-&gt;class)))
+			&amp;&amp; (!r-&gt;instance || (ch.res_name &amp;&amp; strstr(ch.res_name, r-&gt;instance)))) {
+				c-&gt;isfloating = r-&gt;isfloating;
+				c-&gt;tags |= r-&gt;tags &amp; TAGMASK;
 			}
 		}
-	if(ch.res_class)
-		XFree(ch.res_class);
-	if(ch.res_name)
-		XFree(ch.res_name);
-	if(!matched)
-		memcpy(c-&gt;tags, seltags, sizeof seltags);
+		if(ch.res_class)
+			XFree(ch.res_class);
+		if(ch.res_name)
+			XFree(ch.res_name);
+	}
+	if(!c-&gt;tags)
+		c-&gt;tags = tagset[seltags];
 }
 
 void
 arrange(void) {
-	Client *c;
-
-	for(c = clients; c; c = c-&gt;next)
-		if(isvisible(c))
-			unban(c);
-		else
-			ban(c);
-	layouts[ltidx].arrange();
+	showhide(stack);
 	focus(NULL);
+	if(lt[sellt]-&gt;arrange)
+		lt[sellt]-&gt;arrange();
 	restack();
 }
 
 void
 attach(Client *c) {
-	if(clients)
-		clients-&gt;prev = c;
 	c-&gt;next = clients;
 	clients = c;
 }
@@ -297,92 +293,62 @@ attachstack(Client *c) {
 }
 
 void
-ban(Client *c) {
-	if(c-&gt;isbanned)
-		return;
-	XMoveWindow(dpy, c-&gt;win, c-&gt;x + 2 * sw, c-&gt;y);
-	c-&gt;isbanned = True;
-}
-
-void
 buttonpress(XEvent *e) {
-	unsigned int i, x;
+	unsigned int i, x, click;
+	Arg arg = {0};
 	Client *c;
 	XButtonPressedEvent *ev = &amp;e-&gt;xbutton;
 
-	if(barwin == ev-&gt;window) {
-		x = 0;
-		for(i = 0; i &lt; NTAGS; i++) {
-			x += textw(tags[i]);
-			if(ev-&gt;x &lt; x) {
-				if(ev-&gt;button == Button1) {
-					if(ev-&gt;state &amp; MODKEY)
-						tag(tags[i]);
-					else
-						view(tags[i]);
-				}
-				else if(ev-&gt;button == Button3) {
-					if(ev-&gt;state &amp; MODKEY)
-						toggletag(tags[i]);
-					else
-						toggleview(tags[i]);
-				}
-				return;
-			}
+	click = ClkRootWin;
+	if(ev-&gt;window == barwin) {
+		i = x = 0;
+		do x += TEXTW(tags[i]); while(ev-&gt;x &gt;= x &amp;&amp; ++i &lt; LENGTH(tags));
+		if(i &lt; LENGTH(tags)) {
+			click = ClkTagBar;
+			arg.ui = 1 &lt;&lt; i;
 		}
-		if((ev-&gt;x &lt; x + blw) &amp;&amp; ev-&gt;button == Button1)
-			setlayout(NULL);
+		else if(ev-&gt;x &lt; x + blw)
+			click = ClkLtSymbol;
+		else if(ev-&gt;x &gt; wx + ww - TEXTW(stext))
+			click = ClkStatusText;
+		else
+			click = ClkWinTitle;
 	}
 	else if((c = getclient(ev-&gt;window))) {
 		focus(c);
-		if(CLEANMASK(ev-&gt;state) != MODKEY)
-			return;
-		if(ev-&gt;button == Button1) {
-			if(isarrange(floating) || c-&gt;isfloating)
-				restack();
-			else
-				togglefloating(NULL);
-			movemouse(c);
-		}
-		else if(ev-&gt;button == Button2) {
-			if((ISTILE) &amp;&amp; !c-&gt;isfixed &amp;&amp; c-&gt;isfloating)
-				togglefloating(NULL);
-			else
-				zoom(NULL);
-		}
-		else if(ev-&gt;button == Button3 &amp;&amp; !c-&gt;isfixed) {
-			if(isarrange(floating) || c-&gt;isfloating)
-				restack();
-			else
-				togglefloating(NULL);
-			resizemouse(c);
-		}
+		click = ClkClientWin;
 	}
+
+	for(i = 0; i &lt; LENGTH(buttons); i++)
+		if(click == buttons[i].click &amp;&amp; buttons[i].func &amp;&amp; buttons[i].button == ev-&gt;button
+		   &amp;&amp; CLEANMASK(buttons[i].mask) == CLEANMASK(ev-&gt;state))
+			buttons[i].func(click == ClkTagBar &amp;&amp; buttons[i].arg.i == 0 ? &amp;arg : &amp;buttons[i].arg);
 }
 
 void
 checkotherwm(void) {
 	otherwm = False;
-	XSetErrorHandler(xerrorstart);
+	xerrorxlib = XSetErrorHandler(xerrorstart);
 
 	/* this causes an error if some other window manager is running */
-	XSelectInput(dpy, root, SubstructureRedirectMask);
+	XSelectInput(dpy, DefaultRootWindow(dpy), SubstructureRedirectMask);
 	XSync(dpy, False);
 	if(otherwm)
-		eprint(&quot;dwm: another window manager is already running\n&quot;);
-	XSync(dpy, False);
-	XSetErrorHandler(NULL);
-	xerrorxlib = XSetErrorHandler(xerror);
+		die(&quot;dwm: another window manager is already running\n&quot;);
+	XSetErrorHandler(xerror);
 	XSync(dpy, False);
 }
 
 void
 cleanup(void) {
+	Arg a = {.ui = ~0};
+	Layout foo = { &quot;&quot;, NULL };
+
 	close(STDIN_FILENO);
-	while(stack) {
-		unban(stack);
+	view(&amp;a);
+	lt[sellt] = &amp;foo;
+	while(stack)
 		unmanage(stack);
-	}
 	if(dc.font.set)
 		XFreeFontSet(dpy, dc.font.set);
 	else
@@ -390,39 +356,24 @@ cleanup(void) {
 	XUngrabKey(dpy, AnyKey, AnyModifier, root);
 	XFreePixmap(dpy, dc.drawable);
 	XFreeGC(dpy, dc.gc);
-	XDestroyWindow(dpy, barwin);
 	XFreeCursor(dpy, cursor[CurNormal]);
 	XFreeCursor(dpy, cursor[CurResize]);
 	XFreeCursor(dpy, cursor[CurMove]);
-	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
+	XDestroyWindow(dpy, barwin);
 	XSync(dpy, False);
+	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
 }
 
 void
-compileregs(void) {
-	unsigned int i;
-	regex_t *reg;
+clearurgent(Client *c) {
+	XWMHints *wmh;
 
-	if(regs)
+	c-&gt;isurgent = False;
+	if(!(wmh = XGetWMHints(dpy, c-&gt;win)))
 		return;
-	nrules = sizeof rules / sizeof rules[0];
-	regs = emallocz(nrules * sizeof(Regs));
-	for(i = 0; i &lt; nrules; i++) {
-		if(rules[i].prop) {
-			reg = emallocz(sizeof(regex_t));
-			if(regcomp(reg, rules[i].prop, REG_EXTENDED))
-				free(reg);
-			else
-				regs[i].propregex = reg;
-		}
-		if(rules[i].tags) {
-			reg = emallocz(sizeof(regex_t));
-			if(regcomp(reg, rules[i].tags, REG_EXTENDED))
-				free(reg);
-			else
-				regs[i].tagregex = reg;
-		}
-	}
+	wmh-&gt;flags &amp;= ~XUrgencyHint;
+	XSetWMHints(dpy, c-&gt;win, wmh);
+	XFree(wmh);
 }
 
 void
@@ -437,7 +388,7 @@ configure(Client *c) {
 	ce.y = c-&gt;y;
 	ce.width = c-&gt;w;
 	ce.height = c-&gt;h;
-	ce.border_width = c-&gt;border;
+	ce.border_width = c-&gt;bw;
 	ce.above = None;
 	ce.override_redirect = False;
 	XSendEvent(dpy, c-&gt;win, False, StructureNotifyMask, (XEvent *)&amp;ce);
@@ -450,10 +401,8 @@ configurenotify(XEvent *e) {
 	if(ev-&gt;window == root &amp;&amp; (ev-&gt;width != sw || ev-&gt;height != sh)) {
 		sw = ev-&gt;width;
 		sh = ev-&gt;height;
-		XFreePixmap(dpy, dc.drawable);
-		dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
-		XResizeWindow(dpy, barwin, sw, bh);
-		updatebarpos();
+		updategeom();
+		updatebar();
 		arrange();
 	}
 }
@@ -465,26 +414,24 @@ configurerequest(XEvent *e) {
 	XWindowChanges wc;
 
 	if((c = getclient(ev-&gt;window))) {
-		c-&gt;ismax = False;
 		if(ev-&gt;value_mask &amp; CWBorderWidth)
-			c-&gt;border = ev-&gt;border_width;
-		if(c-&gt;isfixed || c-&gt;isfloating || isarrange(floating)) {
+			c-&gt;bw = ev-&gt;border_width;
+		else if(c-&gt;isfloating || !lt[sellt]-&gt;arrange) {
 			if(ev-&gt;value_mask &amp; CWX)
-				c-&gt;x = ev-&gt;x;
+				c-&gt;x = sx + ev-&gt;x;
 			if(ev-&gt;value_mask &amp; CWY)
-				c-&gt;y = ev-&gt;y;
+				c-&gt;y = sy + ev-&gt;y;
 			if(ev-&gt;value_mask &amp; CWWidth)
 				c-&gt;w = ev-&gt;width;
 			if(ev-&gt;value_mask &amp; CWHeight)
 				c-&gt;h = ev-&gt;height;
-			if((c-&gt;x + c-&gt;w) &gt; sw &amp;&amp; c-&gt;isfloating)
-				c-&gt;x = sw / 2 - c-&gt;w / 2; /* center in x direction */
-			if((c-&gt;y + c-&gt;h) &gt; sh &amp;&amp; c-&gt;isfloating)
-				c-&gt;y = sh / 2 - c-&gt;h / 2; /* center in y direction */
-			if((ev-&gt;value_mask &amp; (CWX | CWY))
-			&amp;&amp; !(ev-&gt;value_mask &amp; (CWWidth | CWHeight)))
+			if((c-&gt;x - sx + c-&gt;w) &gt; sw &amp;&amp; c-&gt;isfloating)
+				c-&gt;x = sx + (sw / 2 - c-&gt;w / 2); /* center in x direction */
+			if((c-&gt;y - sy + c-&gt;h) &gt; sh &amp;&amp; c-&gt;isfloating)
+				c-&gt;y = sy + (sh / 2 - c-&gt;h / 2); /* center in y direction */
+			if((ev-&gt;value_mask &amp; (CWX|CWY)) &amp;&amp; !(ev-&gt;value_mask &amp; (CWWidth|CWHeight)))
 				configure(c);
-			if(isvisible(c))
+			if(ISVISIBLE(c))
 				XMoveResizeWindow(dpy, c-&gt;win, c-&gt;x, c-&gt;y, c-&gt;w, c-&gt;h);
 		}
 		else
@@ -514,70 +461,85 @@ destroynotify(XEvent *e) {
 
 void
 detach(Client *c) {
-	if(c-&gt;prev)
-		c-&gt;prev-&gt;next = c-&gt;next;
-	if(c-&gt;next)
-		c-&gt;next-&gt;prev = c-&gt;prev;
-	if(c == clients)
-		clients = c-&gt;next;
-	c-&gt;next = c-&gt;prev = NULL;
+	Client **tc;
+
+	for(tc = &amp;clients; *tc &amp;&amp; *tc != c; tc = &amp;(*tc)-&gt;next);
+	*tc = c-&gt;next;
 }
 
 void
 detachstack(Client *c) {
 	Client **tc;
 
-	for(tc=&amp;stack; *tc &amp;&amp; *tc != c; tc=&amp;(*tc)-&gt;snext);
+	for(tc = &amp;stack; *tc &amp;&amp; *tc != c; tc = &amp;(*tc)-&gt;snext);
 	*tc = c-&gt;snext;
 }
 
 void
+die(const char *errstr, ...) {
+	va_list ap;
+
+	va_start(ap, errstr);
+	vfprintf(stderr, errstr, ap);
+	va_end(ap);
+	exit(EXIT_FAILURE);
+}
+
+void
 drawbar(void) {
-	int i, x;
-
-	dc.x = dc.y = 0;
-	for(i = 0; i &lt; NTAGS; i++) {
-		dc.w = textw(tags[i]);
-		if(seltags[i]) {
-			drawtext(tags[i], dc.sel);
-			drawsquare(sel &amp;&amp; sel-&gt;tags[i], isoccupied(i), dc.sel);
-		}
-		else {
-			drawtext(tags[i], dc.norm);
-			drawsquare(sel &amp;&amp; sel-&gt;tags[i], isoccupied(i), dc.norm);
-		}
+	int x;
+	unsigned int i, occ = 0, urg = 0;
+	unsigned long *col;
+	Client *c;
+
+	for(c = clients; c; c = c-&gt;next) {
+		occ |= c-&gt;tags;
+		if(c-&gt;isurgent)
+			urg |= c-&gt;tags;
+	}
+
+	dc.x = 0;
+	for(i = 0; i &lt; LENGTH(tags); i++) {
+		dc.w = TEXTW(tags[i]);
+		col = tagset[seltags] &amp; 1 &lt;&lt; i ? dc.sel : dc.norm;
+		drawtext(tags[i], col, urg &amp; 1 &lt;&lt; i);
+		drawsquare(sel &amp;&amp; sel-&gt;tags &amp; 1 &lt;&lt; i, occ &amp; 1 &lt;&lt; i, urg &amp; 1 &lt;&lt; i, col);
 		dc.x += dc.w;
 	}
-	dc.w = blw;
-	drawtext(layouts[ltidx].symbol, dc.norm);
-	x = dc.x + dc.w;
-	dc.w = textw(stext);
-	dc.x = sw - dc.w;
+	if(blw &gt; 0) {
+		dc.w = blw;
+		drawtext(lt[sellt]-&gt;symbol, dc.norm, False);
+		x = dc.x + dc.w;
+	}
+	else
+		x = dc.x;
+	dc.w = TEXTW(stext);
+	dc.x = ww - dc.w;
 	if(dc.x &lt; x) {
 		dc.x = x;
-		dc.w = sw - x;
+		dc.w = ww - x;
 	}
-	drawtext(stext, dc.norm);
+	drawtext(stext, dc.norm, False);
 	if((dc.w = dc.x - x) &gt; bh) {
 		dc.x = x;
 		if(sel) {
-			drawtext(sel-&gt;name, dc.sel);
-			drawsquare(sel-&gt;ismax, sel-&gt;isfloating, dc.sel);
+			drawtext(sel-&gt;name, dc.sel, False);
+			drawsquare(sel-&gt;isfixed, sel-&gt;isfloating, False, dc.sel);
 		}
 		else
-			drawtext(NULL, dc.norm);
+			drawtext(NULL, dc.norm, False);
 	}
-	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, sw, bh, 0, 0);
+	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, ww, bh, 0, 0);
 	XSync(dpy, False);
 }
 
 void
-drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) {
+drawsquare(Bool filled, Bool empty, Bool invert, unsigned long col[ColLast]) {
 	int x;
 	XGCValues gcv;
 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
 
-	gcv.foreground = col[ColFG];
+	gcv.foreground = col[invert ? ColBG : ColFG];
 	XChangeGC(dpy, dc.gc, GCForeground, &amp;gcv);
 	x = (dc.font.ascent + dc.font.descent + 2) / 4;
 	r.x = dc.x + 1;
@@ -593,148 +555,104 @@ drawsquare(Bool filled, Bool empty, unsigned long col[ColLast]) {
 }
 
 void
-drawtext(const char *text, unsigned long col[ColLast]) {
-	int x, y, w, h;
-	static char buf[256];
-	unsigned int len, olen;
+drawtext(const char *text, unsigned long col[ColLast], Bool invert) {
+	char buf[256];
+	int i, x, y, h, len, olen;
 	XRectangle r = { dc.x, dc.y, dc.w, dc.h };
 
-	XSetForeground(dpy, dc.gc, col[ColBG]);
+	XSetForeground(dpy, dc.gc, col[invert ? ColFG : ColBG]);
 	XFillRectangles(dpy, dc.drawable, dc.gc, &amp;r, 1);
 	if(!text)
 		return;
-	w = 0;
-	olen = len = strlen(text);
-	if(len &gt;= sizeof buf)
-		len = sizeof buf - 1;
-	memcpy(buf, text, len);
-	buf[len] = 0;
+	olen = strlen(text);
 	h = dc.font.ascent + dc.font.descent;
 	y = dc.y + (dc.h / 2) - (h / 2) + dc.font.ascent;
 	x = dc.x + (h / 2);
 	/* shorten text if necessary */
-	while(len &amp;&amp; (w = textnw(buf, len)) &gt; dc.w - h)
-		buf[--len] = 0;
-	if(len &lt; olen) {
-		if(len &gt; 1)
-			buf[len - 1] = '.';
-		if(len &gt; 2)
-			buf[len - 2] = '.';
-		if(len &gt; 3)
-			buf[len - 3] = '.';
-	}
-	if(w &gt; dc.w)
-		return; /* too long */
-	XSetForeground(dpy, dc.gc, col[ColFG]);
+	for(len = MIN(olen, sizeof buf); len &amp;&amp; textnw(text, len) &gt; dc.w - h; len--);
+	if(!len)
+		return;
+	memcpy(buf, text, len);
+	if(len &lt; olen)
+		for(i = len; i &amp;&amp; i &gt; len - 3; buf[--i] = '.');
+	XSetForeground(dpy, dc.gc, col[invert ? ColBG : ColFG]);
 	if(dc.font.set)
 		XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, buf, len);
 	else
 		XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
 }
 
-void *
-emallocz(unsigned int size) {
-	void *res = calloc(1, size);
-
-	if(!res)
-		eprint(&quot;fatal: could not malloc() %u bytes\n&quot;, size);
-	return res;
-}
-
 void
 enternotify(XEvent *e) {
 	Client *c;
 	XCrossingEvent *ev = &amp;e-&gt;xcrossing;
 
-	if(ev-&gt;mode != NotifyNormal || ev-&gt;detail == NotifyInferior)
+	if((ev-&gt;mode != NotifyNormal || ev-&gt;detail == NotifyInferior) &amp;&amp; ev-&gt;window != root)
 		return;
 	if((c = getclient(ev-&gt;window)))
 		focus(c);
-	else if(ev-&gt;window == root) {
-		selscreen = True;
+	else
 		focus(NULL);
-	}
-}
-
-void
-eprint(const char *errstr, ...) {
-	va_list ap;
-
-	va_start(ap, errstr);
-	vfprintf(stderr, errstr, ap);
-	va_end(ap);
-	exit(EXIT_FAILURE);
 }
 
 void
 expose(XEvent *e) {
 	XExposeEvent *ev = &amp;e-&gt;xexpose;
 
-	if(ev-&gt;count == 0) {
-		if(barwin == ev-&gt;window)
-			drawbar();
-	}
-}
-
-void
-floating(void) { /* default floating layout */
-	Client *c;
-
-	for(c = clients; c; c = c-&gt;next)
-		if(isvisible(c))
-			resize(c, c-&gt;x, c-&gt;y, c-&gt;w, c-&gt;h, True);
+	if(ev-&gt;count == 0 &amp;&amp; (ev-&gt;window == barwin))
+		drawbar();
 }
 
 void
 focus(Client *c) {
-	if((!c &amp;&amp; selscreen) || (c &amp;&amp; !isvisible(c)))
-		for(c = stack; c &amp;&amp; !isvisible(c); c = c-&gt;snext);
+	if(!c || !ISVISIBLE(c))
+		for(c = stack; c &amp;&amp; !ISVISIBLE(c); c = c-&gt;snext);
 	if(sel &amp;&amp; sel != c) {
 		grabbuttons(sel, False);
 		XSetWindowBorder(dpy, sel-&gt;win, dc.norm[ColBorder]);
 	}
 	if(c) {
+		if(c-&gt;isurgent)
+			clearurgent(c);
 		detachstack(c);
 		attachstack(c);
 		grabbuttons(c, True);
-	}
-	sel = c;
-	drawbar();
-	if(!selscreen)
-		return;
-	if(c) {
 		XSetWindowBorder(dpy, c-&gt;win, dc.sel[ColBorder]);
 		XSetInputFocus(dpy, c-&gt;win, RevertToPointerRoot, CurrentTime);
 	}
 	else
 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
+	sel = c;
+	drawbar();
 }
 
 void
-focusnext(const char *arg) {
-	Client *c;
+focusin(XEvent *e) { /* there are some broken focus acquiring clients */
+	XFocusChangeEvent *ev = &amp;e-&gt;xfocus;
 
-	if(!sel)
-		return;
-	for(c = sel-&gt;next; c &amp;&amp; !isvisible(c); c = c-&gt;next);
-	if(!c)
-		for(c = clients; c &amp;&amp; !isvisible(c); c = c-&gt;next);
-	if(c) {
-		focus(c);
-		restack();
-	}
+	if(sel &amp;&amp; ev-&gt;window != sel-&gt;win)
+		XSetInputFocus(dpy, sel-&gt;win, RevertToPointerRoot, CurrentTime);
 }
 
 void
-focusprev(const char *arg) {
-	Client *c;
+focusstack(const Arg *arg) {
+	Client *c = NULL, *i;
 
 	if(!sel)
 		return;
-	for(c = sel-&gt;prev; c &amp;&amp; !isvisible(c); c = c-&gt;prev);
-	if(!c) {
-		for(c = clients; c &amp;&amp; c-&gt;next; c = c-&gt;next);
-		for(; c &amp;&amp; !isvisible(c); c = c-&gt;prev);
+	if (arg-&gt;i &gt; 0) {
+		for(c = sel-&gt;next; c &amp;&amp; !ISVISIBLE(c); c = c-&gt;next);
+		if(!c)
+			for(c = clients; c &amp;&amp; !ISVISIBLE(c); c = c-&gt;next);
+	}
+	else {
+		for(i = clients; i != sel; i = i-&gt;next)
+			if(ISVISIBLE(i))
+				c = i;
+		if(!c)
+			for(; i; i = i-&gt;next)
+				if(ISVISIBLE(i))
+					c = i;
 	}
 	if(c) {
 		focus(c);
@@ -756,7 +674,7 @@ getcolor(const char *colstr) {
 	XColor color;
 
 	if(!XAllocNamedColor(dpy, cmap, colstr, &amp;color, &amp;color))
-		eprint(&quot;error, cannot allocate color '%s'\n&quot;, colstr);
+		die(&quot;error, cannot allocate color '%s'\n&quot;, colstr);
 	return color.pixel;
 }
 
@@ -794,8 +712,7 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) {
 		strncpy(text, (char *)name.value, size - 1);
 	else {
 		if(XmbTextPropertyToTextList(dpy, &amp;name, &amp;list, &amp;n) &gt;= Success
-		&amp;&amp; n &gt; 0 &amp;&amp; *list)
-		{
+		&amp;&amp; n &gt; 0 &amp;&amp; *list) {
 			strncpy(text, *list, size - 1);
 			XFreeStringList(list);
 		}
@@ -807,47 +724,38 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) {
 
 void
 grabbuttons(Client *c, Bool focused) {
-	XUngrabButton(dpy, AnyButton, AnyModifier, c-&gt;win);
-
-	if(focused) {
-		XGrabButton(dpy, Button1, MODKEY, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
-		XGrabButton(dpy, Button1, MODKEY | LockMask, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
-		XGrabButton(dpy, Button1, MODKEY | numlockmask, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
-		XGrabButton(dpy, Button1, MODKEY | numlockmask | LockMask, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
-
-		XGrabButton(dpy, Button2, MODKEY, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
-		XGrabButton(dpy, Button2, MODKEY | LockMask, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
-		XGrabButton(dpy, Button2, MODKEY | numlockmask, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
-		XGrabButton(dpy, Button2, MODKEY | numlockmask | LockMask, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
-
-		XGrabButton(dpy, Button3, MODKEY, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
-		XGrabButton(dpy, Button3, MODKEY | LockMask, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
-		XGrabButton(dpy, Button3, MODKEY | numlockmask, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
-		XGrabButton(dpy, Button3, MODKEY | numlockmask | LockMask, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
+	updatenumlockmask();
+	{
+		unsigned int i, j;
+		unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
+		XUngrabButton(dpy, AnyButton, AnyModifier, c-&gt;win);
+		if(focused) {
+			for(i = 0; i &lt; LENGTH(buttons); i++)
+				if(buttons[i].click == ClkClientWin)
+					for(j = 0; j &lt; LENGTH(modifiers); j++)
+						XGrabButton(dpy, buttons[i].button, buttons[i].mask | modifiers[j], c-&gt;win, False, BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
+		} else
+			XGrabButton(dpy, AnyButton, AnyModifier, c-&gt;win, False,
+			            BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
 	}
-	else
-		XGrabButton(dpy, AnyButton, AnyModifier, c-&gt;win, False, BUTTONMASK,
-				GrabModeAsync, GrabModeSync, None, None);
 }
 
-unsigned int
-idxoftag(const char *tag) {
-	unsigned int i;
+void
+grabkeys(void) {
+	updatenumlockmask();
+	{ /* grab keys */
+		unsigned int i, j;
+		unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
+		KeyCode code;
 
-	for(i = 0; (i &lt; NTAGS) &amp;&amp; (tags[i] != tag); i++);
-	return (i &lt; NTAGS) ? i : 0;
+		XUngrabKey(dpy, AnyKey, AnyModifier, root);
+		for(i = 0; i &lt; LENGTH(keys); i++) {
+			if((code = XKeysymToKeycode(dpy, keys[i].keysym)))
+				for(j = 0; j &lt; LENGTH(modifiers); j++)
+					XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
+						 True, GrabModeAsync, GrabModeAsync);
+		}
+	}
 }
 
 void
@@ -856,8 +764,6 @@ initfont(const char *fontstr) {
 	int i, n;
 
 	missing = NULL;
-	if(dc.font.set)
-		XFreeFontSet(dpy, dc.font.set);
 	dc.font.set = XCreateFontSet(dpy, fontstr, &amp;missing, &amp;n, &amp;def);
 	if(missing) {
 		while(n--)
@@ -872,20 +778,15 @@ initfont(const char *fontstr) {
 		font_extents = XExtentsOfFontSet(dc.font.set);
 		n = XFontsOfFontSet(dc.font.set, &amp;xfonts, &amp;font_names);
 		for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i &lt; n; i++) {
-			if(dc.font.ascent &lt; (*xfonts)-&gt;ascent)
-				dc.font.ascent = (*xfonts)-&gt;ascent;
-			if(dc.font.descent &lt; (*xfonts)-&gt;descent)
-				dc.font.descent = (*xfonts)-&gt;descent;
+			dc.font.ascent = MAX(dc.font.ascent, (*xfonts)-&gt;ascent);
+			dc.font.descent = MAX(dc.font.descent,(*xfonts)-&gt;descent);
 			xfonts++;
 		}
 	}
 	else {
-		if(dc.font.xfont)
-			XFreeFont(dpy, dc.font.xfont);
-		dc.font.xfont = NULL;
 		if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
 		&amp;&amp; !(dc.font.xfont = XLoadQueryFont(dpy, &quot;fixed&quot;)))
-			eprint(&quot;error, cannot load font: '%s'\n&quot;, fontstr);
+			die(&quot;error, cannot load font: '%s'\n&quot;, fontstr);
 		dc.font.ascent = dc.font.xfont-&gt;ascent;
 		dc.font.descent = dc.font.xfont-&gt;descent;
 	}
@@ -893,22 +794,6 @@ initfont(const char *fontstr) {
 }
 
 Bool
-isarrange(void (*func)())
-{
-	return func == layouts[ltidx].arrange;
-}
-
-Bool
-isoccupied(unsigned int t) {
-	Client *c;
-
-	for(c = clients; c; c = c-&gt;next)
-		if(c-&gt;tags[t])
-			return True;
-	return False;
-}
-
-Bool
 isprotodel(Client *c) {
 	int i, n;
 	Atom *protocols;
@@ -923,53 +808,23 @@ isprotodel(Client *c) {
 	return ret;
 }
 
-Bool
-isvisible(Client *c) {
-	unsigned int i;
-
-	for(i = 0; i &lt; NTAGS; i++)
-		if(c-&gt;tags[i] &amp;&amp; seltags[i])
-			return True;
-	return False;
-}
-
 void
 keypress(XEvent *e) {
-	KEYS
-	unsigned int len = sizeof keys / sizeof keys[0];
 	unsigned int i;
-	KeyCode code;
 	KeySym keysym;
 	XKeyEvent *ev;
 
-	if(!e) { /* grabkeys */
-		XUngrabKey(dpy, AnyKey, AnyModifier, root);
-		for(i = 0; i &lt; len; i++) {
-			code = XKeysymToKeycode(dpy, keys[i].keysym);
-			XGrabKey(dpy, code, keys[i].mod, root, True,
-					GrabModeAsync, GrabModeAsync);
-			XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
-					GrabModeAsync, GrabModeAsync);
-			XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
-					GrabModeAsync, GrabModeAsync);
-			XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
-					GrabModeAsync, GrabModeAsync);
-		}
-		return;
-	}
 	ev = &amp;e-&gt;xkey;
 	keysym = XKeycodeToKeysym(dpy, (KeyCode)ev-&gt;keycode, 0);
-	for(i = 0; i &lt; len; i++)
+	for(i = 0; i &lt; LENGTH(keys); i++)
 		if(keysym == keys[i].keysym
-		&amp;&amp; CLEANMASK(keys[i].mod) == CLEANMASK(ev-&gt;state))
-		{
-			if(keys[i].func)
-				keys[i].func(keys[i].arg);
-		}
+		   &amp;&amp; CLEANMASK(keys[i].mod) == CLEANMASK(ev-&gt;state)
+		   &amp;&amp; keys[i].func)
+			keys[i].func(&amp;(keys[i].arg));
 }
 
 void
-killclient(const char *arg) {
+killclient(const Arg *arg) {
 	XEvent ev;
 
 	if(!sel)
@@ -988,66 +843,60 @@ killclient(const char *arg) {
 }
 
 void
-leavenotify(XEvent *e) {
-	XCrossingEvent *ev = &amp;e-&gt;xcrossing;
-
-	if((ev-&gt;window == root) &amp;&amp; !ev-&gt;same_screen) {
-		selscreen = False;
-		focus(NULL);
-	}
-}
-
-void
 manage(Window w, XWindowAttributes *wa) {
+	static Client cz;
 	Client *c, *t = NULL;
-	Window trans;
-	Status rettrans;
+	Window trans = None;
 	XWindowChanges wc;
 
-	c = emallocz(sizeof(Client));
-	c-&gt;tags = emallocz(sizeof seltags);
+	if(!(c = malloc(sizeof(Client))))
+		die(&quot;fatal: could not malloc() %u bytes\n&quot;, sizeof(Client));
+	*c = cz;
 	c-&gt;win = w;
+
+	/* geometry */
 	c-&gt;x = wa-&gt;x;
 	c-&gt;y = wa-&gt;y;
 	c-&gt;w = wa-&gt;width;
 	c-&gt;h = wa-&gt;height;
-	c-&gt;oldborder = wa-&gt;border_width;
+	c-&gt;oldbw = wa-&gt;border_width;
 	if(c-&gt;w == sw &amp;&amp; c-&gt;h == sh) {
 		c-&gt;x = sx;
 		c-&gt;y = sy;
-		c-&gt;border = wa-&gt;border_width;
+		c-&gt;bw = 0;
 	}
 	else {
-		if(c-&gt;x + c-&gt;w + 2 * c-&gt;border &gt; wax + waw)
-			c-&gt;x = wax + waw - c-&gt;w - 2 * c-&gt;border;
-		if(c-&gt;y + c-&gt;h + 2 * c-&gt;border &gt; way + wah)
-			c-&gt;y = way + wah - c-&gt;h - 2 * c-&gt;border;
-		if(c-&gt;x &lt; wax)
-			c-&gt;x = wax;
-		if(c-&gt;y &lt; way)
-			c-&gt;y = way;
-		c-&gt;border = BORDERPX;
+		if(c-&gt;x + WIDTH(c) &gt; sx + sw)
+			c-&gt;x = sx + sw - WIDTH(c);
+		if(c-&gt;y + HEIGHT(c) &gt; sy + sh)
+			c-&gt;y = sy + sh - HEIGHT(c);
+		c-&gt;x = MAX(c-&gt;x, sx);
+		/* only fix client y-offset, if the client center might cover the bar */
+		c-&gt;y = MAX(c-&gt;y, ((by == 0) &amp;&amp; (c-&gt;x + (c-&gt;w / 2) &gt;= wx) &amp;&amp; (c-&gt;x + (c-&gt;w / 2) &lt; wx + ww)) ? bh : sy);
+		c-&gt;bw = borderpx;
 	}
-	wc.border_width = c-&gt;border;
+
+	wc.border_width = c-&gt;bw;
 	XConfigureWindow(dpy, w, CWBorderWidth, &amp;wc);
 	XSetWindowBorder(dpy, w, dc.norm[ColBorder]);
 	configure(c); /* propagates border_width, if size doesn't change */
 	updatesizehints(c);
-	XSelectInput(dpy, w,
-		StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
+	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
 	grabbuttons(c, False);
 	updatetitle(c);
-	if((rettrans = XGetTransientForHint(dpy, w, &amp;trans) == Success))
-		for(t = clients; t &amp;&amp; t-&gt;win != trans; t = t-&gt;next);
+	if(XGetTransientForHint(dpy, w, &amp;trans))
+		t = getclient(trans);
 	if(t)
-		memcpy(c-&gt;tags, t-&gt;tags, sizeof seltags);
-	applyrules(c);
+		c-&gt;tags = t-&gt;tags;
+	else
+		applyrules(c);
 	if(!c-&gt;isfloating)
-		c-&gt;isfloating = (rettrans == Success) || c-&gt;isfixed;
+		c-&gt;isfloating = trans != None || c-&gt;isfixed;
+	if(c-&gt;isfloating)
+		XRaiseWindow(dpy, c-&gt;win);
 	attach(c);
 	attachstack(c);
-	XMoveResizeWindow(dpy, c-&gt;win, c-&gt;x, c-&gt;y, c-&gt;w, c-&gt;h); /* some windows require this */
-	ban(c);
+	XMoveResizeWindow(dpy, c-&gt;win, c-&gt;x + 2 * sw, c-&gt;y, c-&gt;w, c-&gt;h); /* some windows require this */
 	XMapWindow(dpy, c-&gt;win);
 	setclientstate(c, NormalState);
 	arrange();
@@ -1059,7 +908,7 @@ mappingnotify(XEvent *e) {
 
 	XRefreshKeyboardMapping(ev);
 	if(ev-&gt;request == MappingKeyboard)
-		keypress(NULL);
+		grabkeys();
 }
 
 void
@@ -1076,51 +925,70 @@ maprequest(XEvent *e) {
 }
 
 void
-movemouse(Client *c) {
-	int x1, y1, ocx, ocy, di, nx, ny;
+monocle(void) {
+	Client *c;
+
+	for(c = nexttiled(clients); c; c = nexttiled(c-&gt;next))
+		resize(c, wx, wy, ww - 2 * c-&gt;bw, wh - 2 * c-&gt;bw, resizehints);
+}
+
+void
+movemouse(const Arg *arg) {
+	int x, y, ocx, ocy, di, nx, ny;
 	unsigned int dui;
+	Client *c;
 	Window dummy;
 	XEvent ev;
 
-	ocx = nx = c-&gt;x;
-	ocy = ny = c-&gt;y;
+	if(!(c = sel))
+		return;
+	restack();
+	ocx = c-&gt;x;
+	ocy = c-&gt;y;
 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
-			None, cursor[CurMove], CurrentTime) != GrabSuccess)
+	None, cursor[CurMove], CurrentTime) != GrabSuccess)
 		return;
-	c-&gt;ismax = False;
-	XQueryPointer(dpy, root, &amp;dummy, &amp;dummy, &amp;x1, &amp;y1, &amp;di, &amp;di, &amp;dui);
-	for(;;) {
-		XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &amp;ev);
+	XQueryPointer(dpy, root, &amp;dummy, &amp;dummy, &amp;x, &amp;y, &amp;di, &amp;di, &amp;dui);
+	if(usegrab)
+		XGrabServer(dpy);
+	do {
+		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &amp;ev);
 		switch (ev.type) {
-		case ButtonRelease:
-			XUngrabPointer(dpy, CurrentTime);
-			return;
 		case ConfigureRequest:
 		case Expose:
 		case MapRequest:
 			handler[ev.type](&amp;ev);
 			break;
 		case MotionNotify:
-			XSync(dpy, False);
-			nx = ocx + (ev.xmotion.x - x1);
-			ny = ocy + (ev.xmotion.y - y1);
-			if(abs(wax + nx) &lt; SNAP)
-				nx = wax;
-			else if(abs((wax + waw) - (nx + c-&gt;w + 2 * c-&gt;border)) &lt; SNAP)
-				nx = wax + waw - c-&gt;w - 2 * c-&gt;border;
-			if(abs(way - ny) &lt; SNAP)
-				ny = way;
-			else if(abs((way + wah) - (ny + c-&gt;h + 2 * c-&gt;border)) &lt; SNAP)
-				ny = way + wah - c-&gt;h - 2 * c-&gt;border;
-			resize(c, nx, ny, c-&gt;w, c-&gt;h, False);
+			nx = ocx + (ev.xmotion.x - x);
+			ny = ocy + (ev.xmotion.y - y);
+			if(snap &amp;&amp; nx &gt;= wx &amp;&amp; nx &lt;= wx + ww
+			        &amp;&amp; ny &gt;= wy &amp;&amp; ny &lt;= wy + wh) {
+				if(abs(wx - nx) &lt; snap)
+					nx = wx;
+				else if(abs((wx + ww) - (nx + WIDTH(c))) &lt; snap)
+					nx = wx + ww - WIDTH(c);
+				if(abs(wy - ny) &lt; snap)
+					ny = wy;
+				else if(abs((wy + wh) - (ny + HEIGHT(c))) &lt; snap)
+					ny = wy + wh - HEIGHT(c);
+				if(!c-&gt;isfloating &amp;&amp; lt[sellt]-&gt;arrange &amp;&amp; (abs(nx - c-&gt;x) &gt; snap || abs(ny - c-&gt;y) &gt; snap))
+					togglefloating(NULL);
+			}
+			if(!lt[sellt]-&gt;arrange || c-&gt;isfloating)
+				resize(c, nx, ny, c-&gt;w, c-&gt;h, False);
 			break;
 		}
 	}
+	while(ev.type != ButtonRelease);
+	if(usegrab)
+		XUngrabServer(dpy);
+	XUngrabPointer(dpy, CurrentTime);
 }
 
 Client *
 nexttiled(Client *c) {
-	for(; c &amp;&amp; (c-&gt;isfloating || !isvisible(c)); c = c-&gt;next);
+	for(; c &amp;&amp; (c-&gt;isfloating || !ISVISIBLE(c)); c = c-&gt;next);
 	return c;
 }
 
@@ -1134,15 +1002,19 @@ propertynotify(XEvent *e) {
 		return; /* ignore */
 	if((c = getclient(ev-&gt;window))) {
 		switch (ev-&gt;atom) {
-			default: break;
-			case XA_WM_TRANSIENT_FOR:
-				XGetTransientForHint(dpy, c-&gt;win, &amp;trans);
-				if(!c-&gt;isfloating &amp;&amp; (c-&gt;isfloating = (NULL != getclient(trans))))
-					arrange();
-				break;
-			case XA_WM_NORMAL_HINTS:
-				updatesizehints(c);
-				break;
+		default: break;
+		case XA_WM_TRANSIENT_FOR:
+			XGetTransientForHint(dpy, c-&gt;win, &amp;trans);
+			if(!c-&gt;isfloating &amp;&amp; (c-&gt;isfloating = (getclient(trans) != NULL)))
+				arrange();
+			break;
+		case XA_WM_NORMAL_HINTS:
+			updatesizehints(c);
+			break;
+		case XA_WM_HINTS:
+			updatewmhints(c);
+			drawbar();
+			break;
 		}
 		if(ev-&gt;atom == XA_WM_NAME || ev-&gt;atom == netatom[NetWMName]) {
 			updatetitle(c);
@@ -1153,7 +1025,7 @@ propertynotify(XEvent *e) {
 }
 
 void
-quit(const char *arg) {
+quit(const Arg *arg) {
 	readin = running = False;
 }
 
@@ -1162,22 +1034,29 @@ resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
 	XWindowChanges wc;
 
 	if(sizehints) {
+		/* see last two sentences in ICCCM 4.1.2.3 */
+		Bool baseismin = c-&gt;basew == c-&gt;minw &amp;&amp; c-&gt;baseh == c-&gt;minh;
+
 		/* set minimum possible */
-		if (w &lt; 1)
-			w = 1;
-		if (h &lt; 1)
-			h = 1;
+		w = MAX(1, w);
+		h = MAX(1, h);
 
-		/* temporarily remove base dimensions */
-		w -= c-&gt;basew;
-		h -= c-&gt;baseh;
+		if(!baseismin) { /* temporarily remove base dimensions */
+			w -= c-&gt;basew;
+			h -= c-&gt;baseh;
+		}
 
 		/* adjust for aspect limits */
-		if (c-&gt;minay &gt; 0 &amp;&amp; c-&gt;maxay &gt; 0 &amp;&amp; c-&gt;minax &gt; 0 &amp;&amp; c-&gt;maxax &gt; 0) {
-			if (w * c-&gt;maxay &gt; h * c-&gt;maxax)
-				w = h * c-&gt;maxax / c-&gt;maxay;
-			else if (w * c-&gt;minay &lt; h * c-&gt;minax)
-				h = w * c-&gt;minay / c-&gt;minax;
+		if(c-&gt;mina &gt; 0 &amp;&amp; c-&gt;maxa &gt; 0) {
+			if(c-&gt;maxa &lt; (float)w / h)
+				w = h * c-&gt;maxa;
+			else if(c-&gt;mina &lt; (float)h / w)
+				h = w * c-&gt;mina;
+		}
+
+		if(baseismin) { /* increment calculation requires this */
+			w -= c-&gt;basew;
+			h -= c-&gt;baseh;
 		}
 
 		/* adjust for increment value */
@@ -1190,75 +1069,89 @@ resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
 		w += c-&gt;basew;
 		h += c-&gt;baseh;
 
-		if(c-&gt;minw &gt; 0 &amp;&amp; w &lt; c-&gt;minw)
-			w = c-&gt;minw;
-		if(c-&gt;minh &gt; 0 &amp;&amp; h &lt; c-&gt;minh)
-			h = c-&gt;minh;
-		if(c-&gt;maxw &gt; 0 &amp;&amp; w &gt; c-&gt;maxw)
-			w = c-&gt;maxw;
-		if(c-&gt;maxh &gt; 0 &amp;&amp; h &gt; c-&gt;maxh)
-			h = c-&gt;maxh;
+		w = MAX(w, c-&gt;minw);
+		h = MAX(h, c-&gt;minh);
+
+		if(c-&gt;maxw)
+			w = MIN(w, c-&gt;maxw);
+
+		if(c-&gt;maxh)
+			h = MIN(h, c-&gt;maxh);
 	}
 	if(w &lt;= 0 || h &lt;= 0)
 		return;
-	/* offscreen appearance fixes */
-	if(x &gt; sw)
-		x = sw - w - 2 * c-&gt;border;
-	if(y &gt; sh)
-		y = sh - h - 2 * c-&gt;border;
-	if(x + w + 2 * c-&gt;border &lt; sx)
+	if(x &gt; sx + sw)
+		x = sw - WIDTH(c);
+	if(y &gt; sy + sh)
+		y = sh - HEIGHT(c);
+	if(x + w + 2 * c-&gt;bw &lt; sx)
 		x = sx;
-	if(y + h + 2 * c-&gt;border &lt; sy)
+	if(y + h + 2 * c-&gt;bw &lt; sy)
 		y = sy;
+	if(h &lt; bh)
+		h = bh;
+	if(w &lt; bh)
+		w = bh;
 	if(c-&gt;x != x || c-&gt;y != y || c-&gt;w != w || c-&gt;h != h) {
 		c-&gt;x = wc.x = x;
 		c-&gt;y = wc.y = y;
 		c-&gt;w = wc.width = w;
 		c-&gt;h = wc.height = h;
-		wc.border_width = c-&gt;border;
-		XConfigureWindow(dpy, c-&gt;win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &amp;wc);
+		wc.border_width = c-&gt;bw;
+		XConfigureWindow(dpy, c-&gt;win,
+				CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &amp;wc);
 		configure(c);
 		XSync(dpy, False);
 	}
 }
 
 void
-resizemouse(Client *c) {
+resizemouse(const Arg *arg) {
 	int ocx, ocy;
 	int nw, nh;
+	Client *c;
 	XEvent ev;
 
+	if(!(c = sel))
+		return;
+	restack();
 	ocx = c-&gt;x;
 	ocy = c-&gt;y;
 	if(XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
-			None, cursor[CurResize], CurrentTime) != GrabSuccess)
+	None, cursor[CurResize], CurrentTime) != GrabSuccess)
 		return;
-	c-&gt;ismax = False;
-	XWarpPointer(dpy, None, c-&gt;win, 0, 0, 0, 0, c-&gt;w + c-&gt;border - 1, c-&gt;h + c-&gt;border - 1);
-	for(;;) {
-		XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &amp;ev);
+	XWarpPointer(dpy, None, c-&gt;win, 0, 0, 0, 0, c-&gt;w + c-&gt;bw - 1, c-&gt;h + c-&gt;bw - 1);
+	if(usegrab)
+		XGrabServer(dpy);
+	do {
+		XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &amp;ev);
 		switch(ev.type) {
-		case ButtonRelease:
-			XWarpPointer(dpy, None, c-&gt;win, 0, 0, 0, 0,
-					c-&gt;w + c-&gt;border - 1, c-&gt;h + c-&gt;border - 1);
-			XUngrabPointer(dpy, CurrentTime);
-			while(XCheckMaskEvent(dpy, EnterWindowMask, &amp;ev));
-			return;
 		case ConfigureRequest:
 		case Expose:
 		case MapRequest:
 			handler[ev.type](&amp;ev);
 			break;
 		case MotionNotify:
-			XSync(dpy, False);
-			if((nw = ev.xmotion.x - ocx - 2 * c-&gt;border + 1) &lt;= 0)
-				nw = 1;
-			if((nh = ev.xmotion.y - ocy - 2 * c-&gt;border + 1) &lt;= 0)
-				nh = 1;
-			resize(c, c-&gt;x, c-&gt;y, nw, nh, True);
+			nw = MAX(ev.xmotion.x - ocx - 2*c-&gt;bw + 1, 1);
+			nh = MAX(ev.xmotion.y - ocy - 2*c-&gt;bw + 1, 1);
+
+			if(snap &amp;&amp; nw &gt;= wx &amp;&amp; nw &lt;= wx + ww
+			        &amp;&amp; nh &gt;= wy &amp;&amp; nh &lt;= wy + wh) {
+				if(!c-&gt;isfloating &amp;&amp; lt[sellt]-&gt;arrange
+				   &amp;&amp; (abs(nw - c-&gt;w) &gt; snap || abs(nh - c-&gt;h) &gt; snap))
+					togglefloating(NULL);
+			}
+			if(!lt[sellt]-&gt;arrange || c-&gt;isfloating)
+				resize(c, c-&gt;x, c-&gt;y, nw, nh, True);
 			break;
 		}
 	}
+	while(ev.type != ButtonRelease);
+	if(usegrab)
+		XUngrabServer(dpy);
+	XWarpPointer(dpy, None, c-&gt;win, 0, 0, 0, 0, c-&gt;w + c-&gt;bw - 1, c-&gt;h + c-&gt;bw - 1);
+	XUngrabPointer(dpy, CurrentTime);
+	while(XCheckMaskEvent(dpy, EnterWindowMask, &amp;ev));
 }
 
 void
@@ -1270,21 +1163,16 @@ restack(void) {
 	drawbar();
 	if(!sel)
 		return;
-	if(sel-&gt;isfloating || isarrange(floating))
+	if(sel-&gt;isfloating || !lt[sellt]-&gt;arrange)
 		XRaiseWindow(dpy, sel-&gt;win);
-	if(!isarrange(floating)) {
+	if(lt[sellt]-&gt;arrange) {
 		wc.stack_mode = Below;
 		wc.sibling = barwin;
-		if(!sel-&gt;isfloating) {
-			XConfigureWindow(dpy, sel-&gt;win, CWSibling | CWStackMode, &amp;wc);
-			wc.sibling = sel-&gt;win;
-		}
-		for(c = nexttiled(clients); c; c = nexttiled(c-&gt;next)) {
-			if(c == sel)
-				continue;
-			XConfigureWindow(dpy, c-&gt;win, CWSibling | CWStackMode, &amp;wc);
-			wc.sibling = c-&gt;win;
-		}
+		for(c = stack; c; c = c-&gt;snext)
+			if(!c-&gt;isfloating &amp;&amp; ISVISIBLE(c)) {
+				XConfigureWindow(dpy, c-&gt;win, CWSibling|CWStackMode, &amp;wc);
+				wc.sibling = c-&gt;win;
+			}
 	}
 	XSync(dpy, False);
 	while(XCheckMaskEvent(dpy, EnterWindowMask, &amp;ev));
@@ -1293,14 +1181,18 @@ restack(void) {
 void
 run(void) {
 	char *p;
-	int r, xfd;
+	char sbuf[sizeof stext];
 	fd_set rd;
+	int r, xfd;
+	unsigned int len, offset;
 	XEvent ev;
 
 	/* main event loop, also reads status text from stdin */
 	XSync(dpy, False);
 	xfd = ConnectionNumber(dpy);
-	readin = True;
+	offset = 0;
+	len = sizeof stext - 1;
+	sbuf[len] = stext[len] = '\0'; /* 0-terminator is never touched */
 	while(running) {
 		FD_ZERO(&amp;rd);
 		if(readin)
@@ -1309,13 +1201,12 @@ run(void) {
 		if(select(xfd + 1, &amp;rd, NULL, NULL, NULL) == -1) {
 			if(errno == EINTR)
 				continue;
-			eprint(&quot;select failed\n&quot;);
+			die(&quot;select failed\n&quot;);
 		}
 		if(FD_ISSET(STDIN_FILENO, &amp;rd)) {
-			switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) {
+			switch((r = read(STDIN_FILENO, sbuf + offset, len - offset))) {
 			case -1:
-				strncpy(stext, strerror(errno), sizeof stext - 1);
-				stext[sizeof stext - 1] = '\0';
+				strncpy(stext, strerror(errno), len);
 				readin = False;
 				break;
 			case 0:
@@ -1323,10 +1214,18 @@ run(void) {
 				readin = False;
 				break;
 			default:
-				for(stext[r] = '\0', p = stext + strlen(stext) - 1; p &gt;= stext &amp;&amp; *p == '\n'; *p-- = '\0');
-				for(; p &gt;= stext &amp;&amp; *p != '\n'; --p);
-				if(p &gt; stext)
-					strncpy(stext, p + 1, sizeof stext);
+				for(p = sbuf + offset; r &gt; 0; p++, r--, offset++)
+					if(*p == '\n' || *p == '\0') {
+						*p = '\0';
+						strncpy(stext, sbuf, len);
+						p += r - 1; /* p is sbuf + offset + r - 1 */
+						for(r = 0; *(p - r) &amp;&amp; *(p - r) != '\n'; r++);
+						offset = r;
+						if(r)
+							memmove(sbuf, p - r + 1, r);
+						break;
+					}
+				break;
 			}
 			drawbar();
 		}
@@ -1341,10 +1240,9 @@ run(void) {
 void
 scan(void) {
 	unsigned int i, num;
-	Window *wins, d1, d2;
+	Window d1, d2, *wins = NULL;
 	XWindowAttributes wa;
 
-	wins = NULL;
 	if(XQueryTree(dpy, root, &amp;d1, &amp;d2, &amp;wins, &amp;num)) {
 		for(i = 0; i &lt; num; i++) {
 			if(!XGetWindowAttributes(dpy, wins[i], &amp;wa)
@@ -1360,9 +1258,9 @@ scan(void) {
 			&amp;&amp; (wa.map_state == IsViewable || getstate(wins[i]) == IconicState))
 				manage(wins[i], &amp;wa);
 		}
+		if(wins)
+			XFree(wins);
 	}
-	if(wins)
-		XFree(wins);
 }
 
 void
@@ -1374,149 +1272,124 @@ setclientstate(Client *c, long state) {
 }
 
 void
-setlayout(const char *arg) {
-	unsigned int i;
-
-	if(!arg) {
-		if(++ltidx == nlayouts)
-			ltidx = 0;;
-	}
-	else {
-		for(i = 0; i &lt; nlayouts; i++)
-			if(!strcmp(arg, layouts[i].symbol))
-				break;
-		if(i == nlayouts)
-			return;
-		ltidx = i;
-	}
+setlayout(const Arg *arg) {
+	if(!arg || !arg-&gt;v || arg-&gt;v != lt[sellt])
+		sellt ^= 1;
+	if(arg &amp;&amp; arg-&gt;v)
+		lt[sellt] = (Layout *)arg-&gt;v;
 	if(sel)
 		arrange();
 	else
 		drawbar();
 }
 
+/* arg &gt; 1.0 will set mfact absolutly */
 void
-setmwfact(const char *arg) {
-	double delta;
+setmfact(const Arg *arg) {
+	float f;
 
-	if(!(ISTILE))
+	if(!arg || !lt[sellt]-&gt;arrange)
 		return;
-	/* arg handling, manipulate mwfact */
-	if(arg == NULL)
-		mwfact = MWFACT;
-	else if(1 == sscanf(arg, &quot;%lf&quot;, &amp;delta)) {
-		if(arg[0] == '+' || arg[0] == '-')
-			mwfact += delta;
-		else
-			mwfact = delta;
-		if(mwfact &lt; 0.1)
-			mwfact = 0.1;
-		else if(mwfact &gt; 0.9)
-			mwfact = 0.9;
-	}
+	f = arg-&gt;f &lt; 1.0 ? arg-&gt;f + mfact : arg-&gt;f - 1.0;
+	if(f &lt; 0.1 || f &gt; 0.9)
+		return;
+	mfact = f;
 	arrange();
 }
 
 void
 setup(void) {
-	int d;
-	unsigned int i, j, mask;
-	Window w;
-	XModifierKeymap *modmap;
+	unsigned int i;
+	int w;
 	XSetWindowAttributes wa;
 
+	/* init screen */
+	screen = DefaultScreen(dpy);
+	root = RootWindow(dpy, screen);
+	initfont(font);
+	sx = 0;
+	sy = 0;
+	sw = DisplayWidth(dpy, screen);
+	sh = DisplayHeight(dpy, screen);
+	bh = dc.h = dc.font.height + 2;
+	lt[0] = &amp;layouts[0];
+	lt[1] = &amp;layouts[1 % LENGTH(layouts)];
+	updategeom();
+
 	/* init atoms */
 	wmatom[WMProtocols] = XInternAtom(dpy, &quot;WM_PROTOCOLS&quot;, False);
 	wmatom[WMDelete] = XInternAtom(dpy, &quot;WM_DELETE_WINDOW&quot;, False);
-	wmatom[WMName] = XInternAtom(dpy, &quot;WM_NAME&quot;, False);
 	wmatom[WMState] = XInternAtom(dpy, &quot;WM_STATE&quot;, False);
 	netatom[NetSupported] = XInternAtom(dpy, &quot;_NET_SUPPORTED&quot;, False);
 	netatom[NetWMName] = XInternAtom(dpy, &quot;_NET_WM_NAME&quot;, False);
-	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
-			PropModeReplace, (unsigned char *) netatom, NetLast);
 
 	/* init cursors */
-	cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
+	wa.cursor = cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
 	cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
 	cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
 
-	/* init geometry */
-	sx = sy = 0;
-	sw = DisplayWidth(dpy, screen);
-	sh = DisplayHeight(dpy, screen);
-
-	/* init modifier map */
-	modmap = XGetModifierMapping(dpy);
-	for(i = 0; i &lt; 8; i++)
-		for(j = 0; j &lt; modmap-&gt;max_keypermod; j++) {
-			if(modmap-&gt;modifiermap[i * modmap-&gt;max_keypermod + j]
-			== XKeysymToKeycode(dpy, XK_Num_Lock))
-				numlockmask = (1 &lt;&lt; i);
-		}
-	XFreeModifiermap(modmap);
-
-	/* select for events */
-	wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask
-		| EnterWindowMask | LeaveWindowMask | StructureNotifyMask;
-	wa.cursor = cursor[CurNormal];
-	XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &amp;wa);
-	XSelectInput(dpy, root, wa.event_mask);
-
-	/* grab keys */
-	keypress(NULL);
-
-	/* init tags */
-	compileregs();
-
 	/* init appearance */
-	dc.norm[ColBorder] = getcolor(NORMBORDERCOLOR);
-	dc.norm[ColBG] = getcolor(NORMBGCOLOR);
-	dc.norm[ColFG] = getcolor(NORMFGCOLOR);
-	dc.sel[ColBorder] = getcolor(SELBORDERCOLOR);
-	dc.sel[ColBG] = getcolor(SELBGCOLOR);
-	dc.sel[ColFG] = getcolor(SELFGCOLOR);
-	initfont(FONT);
-	dc.h = bh = dc.font.height + 2;
-
-	/* init layouts */
-	mwfact = MWFACT;
-	nlayouts = sizeof layouts / sizeof layouts[0];
-	for(blw = i = 0; i &lt; nlayouts; i++) {
-		j = textw(layouts[i].symbol);
-		if(j &gt; blw)
-			blw = j;
-	}
+	dc.norm[ColBorder] = getcolor(normbordercolor);
+	dc.norm[ColBG] = getcolor(normbgcolor);
+	dc.norm[ColFG] = getcolor(normfgcolor);
+	dc.sel[ColBorder] = getcolor(selbordercolor);
+	dc.sel[ColBG] = getcolor(selbgcolor);
+	dc.sel[ColFG] = getcolor(selfgcolor);
+	dc.drawable = XCreatePixmap(dpy, root, DisplayWidth(dpy, screen), bh, DefaultDepth(dpy, screen));
+	dc.gc = XCreateGC(dpy, root, 0, 0);
+	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
+	if(!dc.font.set)
+		XSetFont(dpy, dc.gc, dc.font.xfont-&gt;fid);
 
 	/* init bar */
-	bpos = BARPOS;
+	for(blw = i = 0; LENGTH(layouts) &gt; 1 &amp;&amp; i &lt; LENGTH(layouts); i++) {
+		w = TEXTW(layouts[i].symbol);
+		blw = MAX(blw, w);
+	}
+
 	wa.override_redirect = 1;
 	wa.background_pixmap = ParentRelative;
-	wa.event_mask = ButtonPressMask | ExposureMask;
-	barwin = XCreateWindow(dpy, root, sx, sy, sw, bh, 0,
-			DefaultDepth(dpy, screen), CopyFromParent, DefaultVisual(dpy, screen),
-			CWOverrideRedirect | CWBackPixmap | CWEventMask, &amp;wa);
+	wa.event_mask = ButtonPressMask|ExposureMask;
+
+	barwin = XCreateWindow(dpy, root, wx, by, ww, bh, 0, DefaultDepth(dpy, screen),
+			CopyFromParent, DefaultVisual(dpy, screen),
+			CWOverrideRedirect|CWBackPixmap|CWEventMask, &amp;wa);
 	XDefineCursor(dpy, barwin, cursor[CurNormal]);
-	updatebarpos();
 	XMapRaised(dpy, barwin);
 	strcpy(stext, &quot;dwm-&quot;VERSION);
-	dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
-	dc.gc = XCreateGC(dpy, root, 0, 0);
-	XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
-	if(!dc.font.set)
-		XSetFont(dpy, dc.gc, dc.font.xfont-&gt;fid);
+	drawbar();
 
-	/* multihead support */
-	selscreen = XQueryPointer(dpy, root, &amp;w, &amp;w, &amp;d, &amp;d, &amp;d, &amp;d, &amp;mask);
+	/* EWMH support per view */
+	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
+			PropModeReplace, (unsigned char *) netatom, NetLast);
+
+	/* select for events */
+	wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask
+			|EnterWindowMask|LeaveWindowMask|StructureNotifyMask;
+	XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &amp;wa);
+	XSelectInput(dpy, root, wa.event_mask);
+
+	grabkeys();
 }
 
 void
-spawn(const char *arg) {
-	static char *shell = NULL;
-
-	if(!shell &amp;&amp; !(shell = getenv(&quot;SHELL&quot;)))
-		shell = &quot;/bin/sh&quot;;
-	if(!arg)
+showhide(Client *c) {
+	if(!c)
 		return;
+	if(ISVISIBLE(c)) { /* show clients top down */
+		XMoveWindow(dpy, c-&gt;win, c-&gt;x, c-&gt;y);
+		if(!lt[sellt]-&gt;arrange || c-&gt;isfloating)
+			resize(c, c-&gt;x, c-&gt;y, c-&gt;w, c-&gt;h, True);
+		showhide(c-&gt;snext);
+	}
+	else { /* hide clients bottom up */
+		showhide(c-&gt;snext);
+		XMoveWindow(dpy, c-&gt;win, c-&gt;x + 2 * sw, c-&gt;y);
+	}
+}
+
+void
+spawn(const Arg *arg) {
 	/* The double-fork construct avoids zombie processes and keeps the code
 	 * clean from stupid signal handlers. */
 	if(fork() == 0) {
@@ -1524,8 +1397,8 @@ spawn(const char *arg) {
 			if(dpy)
 				close(ConnectionNumber(dpy));
 			setsid();
-			execl(shell, shell, &quot;-c&quot;, arg, (char *)NULL);
-			fprintf(stderr, &quot;dwm: execl '%s -c %s'&quot;, shell, arg);
+			execvp(((char **)arg-&gt;v)[0], (char **)arg-&gt;v);
+			fprintf(stderr, &quot;dwm: execvp %s&quot;, ((char **)arg-&gt;v)[0]);
 			perror(&quot; failed&quot;);
 		}
 		exit(0);
@@ -1534,18 +1407,14 @@ spawn(const char *arg) {
 }
 
 void
-tag(const char *arg) {
-	unsigned int i;
-
-	if(!sel)
-		return;
-	for(i = 0; i &lt; NTAGS; i++)
-		sel-&gt;tags[i] = (NULL == arg);
-	sel-&gt;tags[idxoftag(arg)] = True;
-	arrange();
+tag(const Arg *arg) {
+	if(sel &amp;&amp; arg-&gt;ui &amp; TAGMASK) {
+		sel-&gt;tags = arg-&gt;ui &amp; TAGMASK;
+		arrange();
+	}
 }
 
-unsigned int
+int
 textnw(const char *text, unsigned int len) {
 	XRectangle r;
 
@@ -1556,141 +1425,87 @@ textnw(const char *text, unsigned int len) {
 	return XTextWidth(dc.font.xfont, text, len);
 }
 
-unsigned int
-textw(const char *text) {
-	return textnw(text, strlen(text)) + dc.font.height;
-}
-
 void
 tile(void) {
-	unsigned int i, n, nx, ny, nw, nh, mw, th;
-	Client *c, *mc;
-
-	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c-&gt;next))
-		n++;
-
-	/* window geoms */
-	mw = (n == 1) ? waw : mwfact * waw;
-	th = (n &gt; 1) ? wah / (n - 1) : 0;
-	if(n &gt; 1 &amp;&amp; th &lt; bh)
-		th = wah;
-
-	nx = wax;
-	ny = way;
-	nw = 0; /* gcc stupidity requires this */
-	for(i = 0, c = mc = nexttiled(clients); c; c = nexttiled(c-&gt;next), i++) {
-		c-&gt;ismax = False;
-		if(i == 0) { /* master */
-			nw = mw - 2 * c-&gt;border;
-			nh = wah - 2 * c-&gt;border;
-		}
-		else {  /* tile window */
-			if(i == 1) {
-				ny = way;
-				nx += mc-&gt;w + 2 * mc-&gt;border;
-				nw = waw - nx - 2 * c-&gt;border;
-			}
-			if(i + 1 == n) /* remainder */
-				nh = (way + wah) - ny - 2 * c-&gt;border;
-			else
-				nh = th - 2 * c-&gt;border;
-		}
-		resize(c, nx, ny, nw, nh, True);
-		if((c-&gt;h &lt; bh) || (c-&gt;h &gt; nh) || (c-&gt;w &lt; bh) || (c-&gt;w &gt; nw))
-			/* client doesn't accept size constraints */
-			resize(c, nx, ny, nw, nh, False);
-		if(n &gt; 1 &amp;&amp; th != wah)
-			ny = c-&gt;y + c-&gt;h + 2 * c-&gt;border;
+	int x, y, h, w, mw;
+	unsigned int i, n;
+	Client *c;
+
+	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c-&gt;next), n++);
+	if(n == 0)
+		return;
+
+	/* master */
+	c = nexttiled(clients);
+	mw = mfact * ww;
+	resize(c, wx, wy, (n == 1 ? ww : mw) - 2 * c-&gt;bw, wh - 2 * c-&gt;bw, resizehints);
+
+	if(--n == 0)
+		return;
+
+	/* tile stack */
+	x = (wx + mw &gt; c-&gt;x + c-&gt;w) ? c-&gt;x + c-&gt;w + 2 * c-&gt;bw : wx + mw;
+	y = wy;
+	w = (wx + mw &gt; c-&gt;x + c-&gt;w) ? wx + ww - x : ww - mw;
+	h = wh / n;
+	if(h &lt; bh)
+		h = wh;
+
+	for(i = 0, c = nexttiled(c-&gt;next); c; c = nexttiled(c-&gt;next), i++) {
+		resize(c, x, y, w - 2 * c-&gt;bw, /* remainder */ ((i + 1 == n)
+		       ? wy + wh - y - 2 * c-&gt;bw : h - 2 * c-&gt;bw), resizehints);
+		if(h != wh)
+			y = c-&gt;y + HEIGHT(c);
 	}
 }
 
 void
-togglebar(const char *arg) {
-	if(bpos == BarOff)
-		bpos = (BARPOS == BarOff) ? BarTop : BARPOS;
-	else
-		bpos = BarOff;
-	updatebarpos();
+togglebar(const Arg *arg) {
+	showbar = !showbar;
+	updategeom();
+	updatebar();
 	arrange();
 }
 
 void
-togglefloating(const char *arg) {
+togglefloating(const Arg *arg) {
 	if(!sel)
 		return;
-	sel-&gt;isfloating = !sel-&gt;isfloating;
+	sel-&gt;isfloating = !sel-&gt;isfloating || sel-&gt;isfixed;
 	if(sel-&gt;isfloating)
 		resize(sel, sel-&gt;x, sel-&gt;y, sel-&gt;w, sel-&gt;h, True);
 	arrange();
 }
 
 void
-togglemax(const char *arg) {
-	XEvent ev;
+toggletag(const Arg *arg) {
+	unsigned int mask;
 
-	if(!sel || sel-&gt;isfixed)
+	if (!sel)
 		return;
-	if((sel-&gt;ismax = !sel-&gt;ismax)) {
-		if(isarrange(floating) || sel-&gt;isfloating)
-			sel-&gt;wasfloating = True;
-		else {
-			togglefloating(NULL);
-			sel-&gt;wasfloating = False;
-		}
-		sel-&gt;rx = sel-&gt;x;
-		sel-&gt;ry = sel-&gt;y;
-		sel-&gt;rw = sel-&gt;w;
-		sel-&gt;rh = sel-&gt;h;
-		resize(sel, wax, way, waw - 2 * sel-&gt;border, wah - 2 * sel-&gt;border, True);
-	}
-	else {
-		resize(sel, sel-&gt;rx, sel-&gt;ry, sel-&gt;rw, sel-&gt;rh, True);
-		if(!sel-&gt;wasfloating)
-			togglefloating(NULL);
+	
+	mask = sel-&gt;tags ^ (arg-&gt;ui &amp; TAGMASK);
+	if(sel &amp;&amp; mask) {
+		sel-&gt;tags = mask;
+		arrange();
 	}
-	drawbar();
-	while(XCheckMaskEvent(dpy, EnterWindowMask, &amp;ev));
 }
 
 void
-toggletag(const char *arg) {
-	unsigned int i, j;
+toggleview(const Arg *arg) {
+	unsigned int mask = tagset[seltags] ^ (arg-&gt;ui &amp; TAGMASK);
 
-	if(!sel)
-		return;
-	i = idxoftag(arg);
-	sel-&gt;tags[i] = !sel-&gt;tags[i];
-	for(j = 0; j &lt; NTAGS &amp;&amp; !sel-&gt;tags[j]; j++);
-	if(j == NTAGS)
-		sel-&gt;tags[i] = True; /* at least one tag must be enabled */
-	arrange();
-}
-
-void
-toggleview(const char *arg) {
-	unsigned int i, j;
-
-	i = idxoftag(arg);
-	seltags[i] = !seltags[i];
-	for(j = 0; j &lt; NTAGS &amp;&amp; !seltags[j]; j++);
-	if(j == NTAGS)
-		seltags[i] = True; /* at least one tag must be viewed */
-	arrange();
-}
-
-void
-unban(Client *c) {
-	if(!c-&gt;isbanned)
-		return;
-	XMoveWindow(dpy, c-&gt;win, c-&gt;x, c-&gt;y);
-	c-&gt;isbanned = False;
+	if(mask) {
+		tagset[seltags] = mask;
+		arrange();
+	}
 }
 
 void
 unmanage(Client *c) {
 	XWindowChanges wc;
 
-	wc.border_width = c-&gt;oldborder;
+	wc.border_width = c-&gt;oldbw;
 	/* The server grab construct avoids race conditions. */
 	XGrabServer(dpy);
 	XSetErrorHandler(xerrordummy);
@@ -1701,7 +1516,6 @@ unmanage(Client *c) {
 		focus(NULL);
 	XUngrabButton(dpy, AnyButton, AnyModifier, c-&gt;win);
 	setclientstate(c, WithdrawnState);
-	free(c-&gt;tags);
 	free(c);
 	XSync(dpy, False);
 	XSetErrorHandler(xerror);
@@ -1719,29 +1533,61 @@ unmapnotify(XEvent *e) {
 }
 
 void
-updatebarpos(void) {
-	XEvent ev;
+updatebar(void) {
+	if(dc.drawable != 0)
+		XFreePixmap(dpy, dc.drawable);
+	dc.drawable = XCreatePixmap(dpy, root, ww, bh, DefaultDepth(dpy, screen));
+	XMoveResizeWindow(dpy, barwin, wx, by, ww, bh);
+}
 
-	wax = sx;
-	way = sy;
-	wah = sh;
-	waw = sw;
-	switch(bpos) {
-	default:
-		wah -= bh;
-		way += bh;
-		XMoveWindow(dpy, barwin, sx, sy);
-		break;
-	case BarBot:
-		wah -= bh;
-		XMoveWindow(dpy, barwin, sx, sy + wah);
-		break;
-	case BarOff:
-		XMoveWindow(dpy, barwin, sx, sy - bh);
-		break;
+void
+updategeom(void) {
+#ifdef XINERAMA
+	int n, i = 0;
+	XineramaScreenInfo *info = NULL;
+
+	/* window area geometry */
+	if(XineramaIsActive(dpy) &amp;&amp; (info = XineramaQueryScreens(dpy, &amp;n))) { 
+		if(n &gt; 1) {
+			int di, x, y;
+			unsigned int dui;
+			Window dummy;
+			if(XQueryPointer(dpy, root, &amp;dummy, &amp;dummy, &amp;x, &amp;y, &amp;di, &amp;di, &amp;dui))
+				for(i = 0; i &lt; n; i++)
+					if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
+						break;
+		}
+		wx = info[i].x_org;
+		wy = showbar &amp;&amp; topbar ?  info[i].y_org + bh : info[i].y_org;
+		ww = info[i].width;
+		wh = showbar ? info[i].height - bh : info[i].height;
+		XFree(info);
 	}
-	XSync(dpy, False);
-	while(XCheckMaskEvent(dpy, EnterWindowMask, &amp;ev));
+	else
+#endif
+	{
+		wx = sx;
+		wy = showbar &amp;&amp; topbar ? sy + bh : sy;
+		ww = sw;
+		wh = showbar ? sh - bh : sh;
+	}
+
+	/* bar position */
+	by = showbar ? (topbar ? wy - bh : wy + wh) : -bh;
+}
+
+void
+updatenumlockmask(void) {
+	unsigned int i, j;
+	XModifierKeymap *modmap;
+
+	numlockmask = 0;
+	modmap = XGetModifierMapping(dpy);
+	for(i = 0; i &lt; 8; i++)
+		for(j = 0; j &lt; modmap-&gt;max_keypermod; j++)
+			if(modmap-&gt;modifiermap[i * modmap-&gt;max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock))
+				numlockmask = (1 &lt;&lt; i);
+	XFreeModifiermap(modmap);
 }
 
 void
@@ -1749,57 +1595,81 @@ updatesizehints(Client *c) {
 	long msize;
 	XSizeHints size;
 
-	if(!XGetWMNormalHints(dpy, c-&gt;win, &amp;size, &amp;msize) || !size.flags)
-		size.flags = PSize;
-	c-&gt;flags = size.flags;
-	if(c-&gt;flags &amp; PBaseSize) {
+	if(!XGetWMNormalHints(dpy, c-&gt;win, &amp;size, &amp;msize))
+		/* size is uninitialized, ensure that size.flags aren't used */
+		size.flags = PSize; 
+	if(size.flags &amp; PBaseSize) {
 		c-&gt;basew = size.base_width;
 		c-&gt;baseh = size.base_height;
 	}
-	else if(c-&gt;flags &amp; PMinSize) {
+	else if(size.flags &amp; PMinSize) {
 		c-&gt;basew = size.min_width;
 		c-&gt;baseh = size.min_height;
 	}
 	else
 		c-&gt;basew = c-&gt;baseh = 0;
-	if(c-&gt;flags &amp; PResizeInc) {
+	if(size.flags &amp; PResizeInc) {
 		c-&gt;incw = size.width_inc;
 		c-&gt;inch = size.height_inc;
 	}
 	else
 		c-&gt;incw = c-&gt;inch = 0;
-	if(c-&gt;flags &amp; PMaxSize) {
+	if(size.flags &amp; PMaxSize) {
 		c-&gt;maxw = size.max_width;
 		c-&gt;maxh = size.max_height;
 	}
 	else
 		c-&gt;maxw = c-&gt;maxh = 0;
-	if(c-&gt;flags &amp; PMinSize) {
+	if(size.flags &amp; PMinSize) {
 		c-&gt;minw = size.min_width;
 		c-&gt;minh = size.min_height;
 	}
-	else if(c-&gt;flags &amp; PBaseSize) {
+	else if(size.flags &amp; PBaseSize) {
 		c-&gt;minw = size.base_width;
 		c-&gt;minh = size.base_height;
 	}
 	else
 		c-&gt;minw = c-&gt;minh = 0;
-	if(c-&gt;flags &amp; PAspect) {
-		c-&gt;minax = size.min_aspect.x;
-		c-&gt;maxax = size.max_aspect.x;
-		c-&gt;minay = size.min_aspect.y;
-		c-&gt;maxay = size.max_aspect.y;
+	if(size.flags &amp; PAspect) {
+		c-&gt;mina = (float)size.min_aspect.y / (float)size.min_aspect.x;
+		c-&gt;maxa = (float)size.max_aspect.x / (float)size.max_aspect.y;
 	}
 	else
-		c-&gt;minax = c-&gt;maxax = c-&gt;minay = c-&gt;maxay = 0;
+		c-&gt;maxa = c-&gt;mina = 0.0;
 	c-&gt;isfixed = (c-&gt;maxw &amp;&amp; c-&gt;minw &amp;&amp; c-&gt;maxh &amp;&amp; c-&gt;minh
-			&amp;&amp; c-&gt;maxw == c-&gt;minw &amp;&amp; c-&gt;maxh == c-&gt;minh);
+	             &amp;&amp; c-&gt;maxw == c-&gt;minw &amp;&amp; c-&gt;maxh == c-&gt;minh);
 }
 
 void
 updatetitle(Client *c) {
 	if(!gettextprop(c-&gt;win, netatom[NetWMName], c-&gt;name, sizeof c-&gt;name))
-		gettextprop(c-&gt;win, wmatom[WMName], c-&gt;name, sizeof c-&gt;name);
+		gettextprop(c-&gt;win, XA_WM_NAME, c-&gt;name, sizeof c-&gt;name);
+}
+
+void
+updatewmhints(Client *c) {
+	XWMHints *wmh;
+
+	if((wmh = XGetWMHints(dpy, c-&gt;win))) {
+		if(ISVISIBLE(c) &amp;&amp; wmh-&gt;flags &amp; XUrgencyHint) {
+			wmh-&gt;flags &amp;= ~XUrgencyHint;
+			XSetWMHints(dpy, c-&gt;win, wmh);
+		}
+		else
+			c-&gt;isurgent = (wmh-&gt;flags &amp; XUrgencyHint) ? True : False;
+
+		XFree(wmh);
+	}
+}
+
+void
+view(const Arg *arg) {
+	if((arg-&gt;ui &amp; TAGMASK) == tagset[seltags])
+		return;
+	seltags ^= 1; /* toggle sel tagset */
+	if(arg-&gt;ui &amp; TAGMASK)
+		tagset[seltags] = arg-&gt;ui &amp; TAGMASK;
+	arrange();
 }
 
 /* There's no way to check accesses to destroyed windows, thus those cases are
@@ -1813,56 +1683,36 @@ xerror(Display *dpy, XErrorEvent *ee) {
 	|| (ee-&gt;request_code == X_PolyFillRectangle &amp;&amp; ee-&gt;error_code == BadDrawable)
 	|| (ee-&gt;request_code == X_PolySegment &amp;&amp; ee-&gt;error_code == BadDrawable)
 	|| (ee-&gt;request_code == X_ConfigureWindow &amp;&amp; ee-&gt;error_code == BadMatch)
+	|| (ee-&gt;request_code == X_GrabButton &amp;&amp; ee-&gt;error_code == BadAccess)
 	|| (ee-&gt;request_code == X_GrabKey &amp;&amp; ee-&gt;error_code == BadAccess)
 	|| (ee-&gt;request_code == X_CopyArea &amp;&amp; ee-&gt;error_code == BadDrawable))
 		return 0;
 	fprintf(stderr, &quot;dwm: fatal error: request code=%d, error code=%d\n&quot;,
-		ee-&gt;request_code, ee-&gt;error_code);
+			ee-&gt;request_code, ee-&gt;error_code);
 	return xerrorxlib(dpy, ee); /* may call exit */
 }
 
 int
-xerrordummy(Display *dsply, XErrorEvent *ee) {
+xerrordummy(Display *dpy, XErrorEvent *ee) {
 	return 0;
 }
 
 /* Startup Error handler to check if another window manager
  * is already running. */
 int
-xerrorstart(Display *dsply, XErrorEvent *ee) {
+xerrorstart(Display *dpy, XErrorEvent *ee) {
 	otherwm = True;
 	return -1;
 }
 
 void
-view(const char *arg) {
-	unsigned int i;
-
-	memcpy(prevtags, seltags, sizeof seltags);
-	for(i = 0; i &lt; NTAGS; i++)
-		seltags[i] = arg == NULL;
-	seltags[idxoftag(arg)] = True;
-	arrange();
-}
-
-void
-viewprevtag(const char *arg) {
-	static Bool tmptags[sizeof tags / sizeof tags[0]];
+zoom(const Arg *arg) {
+	Client *c = sel;
 
-	memcpy(tmptags, seltags, sizeof seltags);
-	memcpy(seltags, prevtags, sizeof seltags);
-	memcpy(prevtags, tmptags, sizeof seltags);
-	arrange();
-}
-
-void
-zoom(const char *arg) {
-	Client *c;
-
-	if(!sel || !(ISTILE) || sel-&gt;isfloating)
+	if(!lt[sellt]-&gt;arrange || lt[sellt]-&gt;arrange == monocle || (sel &amp;&amp; sel-&gt;isfloating))
 		return;
-	if((c = sel) == nexttiled(clients))
-		if(!(c = nexttiled(c-&gt;next)))
+	if(c == nexttiled(clients))
+		if(!c || !(c = nexttiled(c-&gt;next)))
 			return;
 	detach(c);
 	attach(c);
@@ -1873,19 +1723,18 @@ zoom(const char *arg) {
 int
 main(int argc, char *argv[]) {
 	if(argc == 2 &amp;&amp; !strcmp(&quot;-v&quot;, argv[1]))
-		eprint(&quot;dwm-&quot;VERSION&quot;, &#169; 2006-2007 A. R. Garbe, S. van Dijk, J. Salmi, P. Hruby, S. Nagy\n&quot;);
+		die(&quot;dwm-&quot;VERSION&quot;, &#169; 2006-2008 dwm engineers, see LICENSE for details\n&quot;);
 	else if(argc != 1)
-		eprint(&quot;usage: dwm [-v]\n&quot;);
+		die(&quot;usage: dwm [-v]\n&quot;);
+
+	if(!setlocale(LC_CTYPE, &quot;&quot;) || !XSupportsLocale())
+		fprintf(stderr, &quot;warning: no locale support\n&quot;);
 
-	setlocale(LC_CTYPE, &quot;&quot;);
 	if(!(dpy = XOpenDisplay(0)))
-		eprint(&quot;dwm: cannot open display\n&quot;);
-	screen = DefaultScreen(dpy);
-	root = RootWindow(dpy, screen);
+		die(&quot;dwm: cannot open display\n&quot;);
 
 	checkotherwm();
 	setup();
-	drawbar();
 	scan();
 	run();
 	cleanup();</diff>
      <filename>dwm/dwm.c</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>d3fbd21b97fdde9e68416e6135d7a45445ffdd3b</id>
    </parent>
  </parents>
  <author>
    <name>Stephen Paul Weber</name>
    <email>singpolyma@singpolyma.net</email>
  </author>
  <url>http://github.com/singpolyma/singpolyma/commit/cda0429418235ac56c49786793b37a79c206ba00</url>
  <id>cda0429418235ac56c49786793b37a79c206ba00</id>
  <committed-date>2009-01-03T21:06:52-08:00</committed-date>
  <authored-date>2009-01-03T21:06:52-08:00</authored-date>
  <message>new dwm version</message>
  <tree>0ab3e0db820d927d16e37d60a54597952e7fbd55</tree>
  <committer>
    <name>Stephen Paul Weber</name>
    <email>singpolyma@singpolyma.net</email>
  </committer>
</commit>
