rndm_luser /dwm-5.2-custom-0.1.diff

Patch against dwm-5.2 which adds the bstack, grid, and per-tag (modified) patches (see http://www.suckless.org/dwm/patches/). It also removes the bar window entirely as well as the toggle layout binding (Mod1-Space). It also adds an isignore and isontop rules to ignore certain windows and/or always keep them on top, respectively. This patch also modifies the manual page and Makefile and adds some custom app settings as well as some fixes from the main dwm repository.
diff -Naurp a/config.def.h b/config.def.h
--- a/config.def.h	2008-09-09 14:46:17.000000000 -0500
+++ b/config.def.h	2008-09-10 07:47:45.000000000 -0500
@@ -1,40 +1,30 @@
 /* See LICENSE file for copyright and license details. */
 
 /* appearance */
-static const char font[]            = "-*-terminus-medium-r-normal-*-14-*-*-*-*-*-*-*";
 static const char normbordercolor[] = "#cccccc";
-static const char normbgcolor[]     = "#cccccc";
-static const char normfgcolor[]     = "#000000";
-static const char selbordercolor[]  = "#0066ff";
-static const char selbgcolor[]      = "#0066ff";
-static const char selfgcolor[]      = "#ffffff";
+static const char selbordercolor[]  = "#ff0000";
 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 */
 
 /* tagging */
-static const char tags[][MAXTAGLEN] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
-static unsigned int tagset[] = {1, 1}; /* after start, first tag is selected */
+#define NUMTAGS   8
 
 static Rule rules[] = {
-	/* class      instance    title       tags mask     isfloating */
-	{ "Gimp",     NULL,       NULL,       0,            True },
-	{ "Firefox",  NULL,       NULL,       1 << 8,       True },
+	/* class      instance    title       tags mask     isfloating      isignored       isontop*/
+	{ "Gimp",     NULL,       NULL,       0,            True,           False,          True },
+	{ "MPlayer",  NULL,       NULL,       0,            True,           False,          True },
+	{ "XLoad",    NULL,       NULL,       ~0,           True,           True,           True },
+	{ "XNetload", NULL,       NULL,       ~0,           True,           True,           True },
+	{ "XMem",     NULL,       NULL,       ~0,           True,           True,           True },
+	{ "XClock",   NULL,       NULL,       ~0,           True,           True,           True },
+	{ "XBiff",    NULL,       NULL,       ~0,           True,           True,           True },
+	{ "XEyes",    NULL,       NULL,       ~0,           True,           True,           True },
 };
 
 /* layout(s) */
 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 */
-	{ "[]=",      tile },    /* first entry is default */
-	{ "><>",      NULL },    /* no layout function means floating behavior */
-	{ "[M]",      monocle },
-};
-
 /* key definitions */
 #define MODKEY Mod1Mask
 #define TAGKEYS(KEY,TAG) \
@@ -47,25 +37,27 @@ static Layout layouts[] = {
 #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
 
 /* commands */
-static const char *dmenucmd[] = { "dmenu_run", "-fn", font, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", selfgcolor, NULL };
+static const char *dmenucmd[] = { "dmenu_run", "-fn", "-misc-fixed-medium-r-semicondensed-*-13-*-*-*-*-*-*-*", "-nb", "#cccccc", "-nf", "#000000", "-sb", "#ff0000", "-sf", "#ffffff", NULL };
 static const char *termcmd[]  = { "uxterm", NULL };
 
 static Key keys[] = {
 	/* modifier                     key        function        argument */
 	{ MODKEY,                       XK_p,      spawn,          {.v = dmenucmd } },
 	{ MODKEY|ShiftMask,             XK_Return, spawn,          {.v = termcmd } },
-	{ 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,                       XK_Tab,    view,           {0} },
+	{ MODKEY,                       XK_r,      raisewin,       {.i = +1 } },
+	{ MODKEY|ShiftMask,             XK_r,      raisewin,       {.i = -1 } },
 	{ MODKEY|ShiftMask,             XK_c,      killclient,     {0} },
-	{ MODKEY,                       XK_t,      setlayout,      {.v = &layouts[0]} },
-	{ MODKEY,                       XK_f,      setlayout,      {.v = &layouts[1]} },
-	{ MODKEY,                       XK_m,      setlayout,      {.v = &layouts[2]} },
-	{ MODKEY,                       XK_space,  setlayout,      {0} },
+	{ MODKEY,                       XK_t,      setlayout,      {.func = tile} },
+	{ MODKEY,                       XK_f,      setlayout,      {.func = NULL} },
+	{ MODKEY,                       XK_m,      setlayout,      {.func = monocle} },
+	{ MODKEY,                       XK_b,      setlayout,      {.func = bstack} },
+	{ MODKEY,                       XK_g,      setlayout,      {.func = grid} },
 	{ MODKEY|ShiftMask,             XK_space,  togglefloating, {0} },
 	{ MODKEY,                       XK_0,      view,           {.ui = ~0 } },
 	{ MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } },
@@ -82,20 +74,11 @@ static Key keys[] = {
 };
 
 /* button definitions */
-/* click can be a tag number (starting at 0),
- * ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
+/* click can be a tag number (starting at 0), either ClkClientWin or ClkRootWin */
 static Button buttons[] = {
 	/* click                event mask      button          function        argument */
-	{ ClkLtSymbol,          0,              Button1,        setlayout,      {0} },
-	{ ClkLtSymbol,          0,              Button3,        setlayout,      {.v = &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 -Naurp a/config.mk b/config.mk
--- a/config.mk	2008-09-09 14:46:17.000000000 -0500
+++ b/config.mk	2008-09-10 07:47:45.000000000 -0500
@@ -1,5 +1,5 @@
 # dwm version
-VERSION = 5.2
+VERSION = 5.1-custom-0.1
 
 # Customize below to fit your system
 
@@ -11,8 +11,8 @@ X11INC = /usr/X11R6/include
 X11LIB = /usr/X11R6/lib
 
 # Xinerama, comment if you don't want it
-XINERAMALIBS = -L${X11LIB} -lXinerama
-XINERAMAFLAGS = -DXINERAMA
+#XINERAMALIBS = -L${X11LIB} -lXinerama
+#XINERAMAFLAGS = -DXINERAMA
 
 # includes and libs
 INCS = -I. -I/usr/include -I${X11INC}
diff -Naurp a/dwm.1 b/dwm.1
--- a/dwm.1	2008-09-09 14:46:17.000000000 -0500
+++ b/dwm.1	2008-09-10 07:47:45.000000000 -0500
@@ -19,47 +19,18 @@ layout applied.
 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 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
-corner.  The tags which are applied to one or more windows are indicated
-with an empty square in the top left corner.
-.P
 dwm draws a small border around windows to indicate the focus state.
 .SH OPTIONS
 .TP
 .B \-v
 prints version information to standard output, then exits.
 .SH USAGE
-.SS Status bar
-.TP
-.B Standard input
-is read and displayed in the status text area.
-.TP
-.B Button1
-click on a tag label to display all windows with that tag, click on the layout
-label toggles between tiled and floating layout.
-.TP
-.B Button3
-click on a tag label adds/removes all windows with that tag to/from the view.
-.TP
-.B Mod1\-Button1
-click on a tag label applies that tag to the focused window.
-.TP
-.B Mod1\-Button3
-click on a tag label adds/removes that tag to/from the focused window.
 .SS Keyboard commands
 .TP
 .B Mod1\-Shift\-Return
 Start
 .BR xterm.
 .TP
-.B Mod1\-b
-Toggles bar on and off.
-.TP
 .B Mod1\-t
 Sets tiled layout.
 .TP
@@ -69,8 +40,11 @@ Sets floating layout.
 .B Mod1\-m
 Sets monocle layout.
 .TP
-.B Mod1\-space
-Toggles between current and previous layout.
+.B Mod1\-b
+Sets bstack layout.
+.TP
+.B Mod1\-g
+Sets grid layout.
 .TP
 .B Mod1\-j
 Focus next window.
@@ -139,12 +113,6 @@ dwm is customized by creating a custom c
 code. This keeps it fast, secure and simple.
 .SH SEE ALSO
 .BR dmenu (1)
-.SH BUGS
-The status bar may display
-.BR "EOF"
-when dwm has been started by an X session manager like
-.BR xdm (1),
-because those close standard output before executing dwm.
 .P
 Java applications which use the XToolkit/XAWT backend may draw grey windows
 only. The XToolkit/XAWT backend breaks ICCCM-compliance in recent JDK 1.5 and early
diff -Naurp a/dwm.c b/dwm.c
--- a/dwm.c	2008-09-09 14:46:17.000000000 -0500
+++ b/dwm.c	2008-09-10 08:00:59.000000000 -0500
@@ -6,12 +6,9 @@
  * events about window (dis-)appearance.  Only one X connection at a time is
  * allowed to select for this event mask.
  *
- * Calls to fetch an X event from the event queue are blocking.  Due reading
- * status text from standard input, a select()-driven main loop has been
- * implemented which selects for reads on the X connection and STDIN_FILENO to
- * handle all data smoothly. The event handlers of dwm are organized in an
- * array which is accessed whenever a new event has been fetched. This allows
- * event dispatching in O(1) time.
+ * The event handlers of dwm are organized in an array which is accessed
+ * whenever a new event has been fetched. This allows event dispatching in
+ * O(1) time.
  *
  * 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
@@ -24,7 +21,6 @@
  * To understand everything else, start reading main().
  */
 #include 
-#include 
 #include 
 #include 
 #include 
@@ -54,22 +50,21 @@
 #define MAXTAGLEN               16
 #define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
 #define NOBORDER(x)             ((x) - 2 * c->bw)
-#define TAGMASK                 ((int)((1LL << LENGTH(tags)) - 1))
-#define TEXTW(x)                (textnw(x, strlen(x)) + dc.font.height)
+#define TAGMASK                 ((int)((1LL << NUMTAGS) - 1))
 
 /* enums */
 enum { CurNormal, CurResize, CurMove, CurLast };        /* cursor */
-enum { ColBorder, ColFG, ColBG, ColLast };              /* color */
+enum { ColBorder, ColLast };                            /* color */
 enum { NetSupported, NetWMName, NetLast };              /* EWMH atoms */
 enum { WMProtocols, WMDelete, WMState, WMLast };        /* default atoms */
-enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
-       ClkClientWin, ClkRootWin, ClkLast };             /* clicks */
+enum { ClkClientWin, ClkRootWin, ClkLast };             /* clicks */
 
 typedef union {
 	int i;
 	unsigned int ui;
 	float f;
 	void *v;
+	void (*func)(void);
 } Arg;
 
 typedef struct {
@@ -88,7 +83,7 @@ struct Client {
 	int basew, baseh, incw, inch, maxw, maxh, minw, minh;
 	int bw, oldbw;
 	unsigned int tags;
-	Bool isfixed, isfloating, isurgent;
+	Bool isfixed, isfloating, isignored, isontop;
 	Client *next;
 	Client *snext;
 	Window win;
@@ -98,15 +93,7 @@ typedef struct {
 	int x, y, w, h;
 	unsigned long norm[ColLast];
 	unsigned long sel[ColLast];
-	Drawable drawable;
 	GC gc;
-	struct {
-		int ascent;
-		int descent;
-		int height;
-		XFontSet set;
-		XFontStruct *xfont;
-	} font;
 } DC; /* draw context */
 
 typedef struct {
@@ -117,16 +104,13 @@ typedef struct {
 } Key;
 
 typedef struct {
-	const char *symbol;
-	void (*arrange)(void);
-} Layout;
-
-typedef struct {
 	const char *class;
 	const char *instance;
 	const char *title;
 	unsigned int tags;
 	Bool isfloating;
+	Bool isignored;
+	Bool isontop;
 } Rule;
 
 /* function declarations */
@@ -134,10 +118,10 @@ static void applyrules(Client *c);
 static void arrange(void);
 static void attach(Client *c);
 static void attachstack(Client *c);
+static void bstack(void);
 static void buttonpress(XEvent *e);
 static void checkotherwm(void);
 static void cleanup(void);
-static void clearurgent(void);
 static void configure(Client *c);
 static void configurenotify(XEvent *e);
 static void configurerequest(XEvent *e);
@@ -145,21 +129,16 @@ 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 void grid(void);
 static Bool isprotodel(Client *c);
 static void keypress(XEvent *e);
 static void killclient(const Arg *arg);
@@ -171,6 +150,7 @@ static void movemouse(const Arg *arg);
 static Client *nexttiled(Client *c);
 static void propertynotify(XEvent *e);
 static void quit(const Arg *arg);
+static void raisewin(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);
@@ -180,23 +160,17 @@ static void setclientstate(Client *c, lo
 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);
@@ -204,10 +178,8 @@ static int xerrorstart(Display *dpy, XEr
 static void zoom(const Arg *arg);
 
 /* variables */
-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 sx, sy, sw, sh; /* X display screen geometry x, y, width, height */
 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 *);
@@ -218,7 +190,6 @@ static void (*handler[LASTEvent]) (XEven
 	[ConfigureNotify] = configurenotify,
 	[DestroyNotify] = destroynotify,
 	[EnterNotify] = enternotify,
-	[Expose] = expose,
 	[FocusIn] = focusin,
 	[KeyPress] = keypress,
 	[MappingNotify] = mappingnotify,
@@ -227,21 +198,26 @@ static void (*handler[LASTEvent]) (XEven
 	[UnmapNotify] = unmapnotify
 };
 static Atom wmatom[WMLast], netatom[NetLast];
-static Bool otherwm;
+static Bool otherwm, readin;
 static Bool running = True;
+static unsigned int tagset[] = {1, 1}; /* after start, first tag is selected */
 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;
+static DC dc = {0};
+static void (*lt[])(void) = { NULL, NULL };
+static Window root;
 /* configuration, allows nested code to access above variables */
 #include "config.h"
 
+static int curtag = 1, prevtag = 1;
+static void (*lts[NUMTAGS + 1])(void);
+static double mfacts[NUMTAGS + 1];
+
 /* compile-time check if all tags fit into an unsigned int bit array. */
-struct NumTags { char limitexceeded[sizeof(unsigned int) * 8 < LENGTH(tags) ? -1 : 1]; };
+struct NumTags { char limitexceeded[sizeof(unsigned int) * 8 < NUMTAGS ? -1 : 1]; };
 
 /* function implementations */
 void
@@ -259,6 +235,8 @@ applyrules(Client *c) {
 			&& (!r->instance || (ch.res_name && strstr(ch.res_name, r->instance)))) {
 				c->isfloating = r->isfloating;
 				c->tags |= r->tags & TAGMASK;
+				c->isignored = r->isignored;
+                c->isontop = r->isontop;
 			}
 		}
 		if(ch.res_class)
@@ -272,10 +250,21 @@ applyrules(Client *c) {
 
 void
 arrange(void) {
-	showhide(stack);
+	Client *c;
+
+	for(c = clients; c; c = c->next)
+		if(ISVISIBLE(c)) {
+			XMoveWindow(dpy, c->win, c->x, c->y);
+			if(!lt[sellt] || c->isfloating)
+				resize(c, c->x, c->y, c->w, c->h, True);
+		}
+		else {
+			XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
+		}
+
 	focus(NULL);
-	if(lt[sellt]->arrange)
-		lt[sellt]->arrange();
+	if(lt[sellt])
+		lt[sellt]();
 	restack();
 }
 
@@ -292,28 +281,45 @@ attachstack(Client *c) {
 }
 
 void
+bstack(void) {
+	int x, y, h, w, mh;
+	unsigned int i, n;
+	Client *c;
+
+	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next), n++);
+	if(n == 0)
+		return;
+
+	/* master */
+	c = nexttiled(clients);
+	mh = mfact * wh;
+	resize(c, wx, wy, NOBORDER(ww), NOBORDER(n == 1 ? wh : mh), resizehints);
+
+	if(--n == 0)
+		return;
+
+	/* tile stack */
+	x = wx;
+	y = (wy + mh > c->y + c->h) ? c->y + c->h + 2 * c->bw : wy + mh;
+	w = ww / n;
+	h = (wy + mh > c->y + c->h) ? wy + wh - y : wh - mh;
+
+	for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
+        resize(c, x, y, ((i + 1 == n) ? NOBORDER(wx + ww) - x : w),
+                NOBORDER(h), resizehints);
+		if(w != ww)
+			x = c->x + c->w + 2 * c->bw;	
+	}
+}
+
+void
 buttonpress(XEvent *e) {
-	unsigned int i, x, click;
-	Arg arg = {0};
+	unsigned int i, click;
 	Client *c;
 	XButtonPressedEvent *ev = &e->xbutton;
 
 	click = ClkRootWin;
-	if(ev->window == barwin) {
-		i = x = 0;
-		do x += TEXTW(tags[i]); while(ev->x >= x && ++i < LENGTH(tags));
-		if(i < LENGTH(tags)) {
-			click = ClkTagBar;
-			arg.ui = 1 << i;
-		}
-		else if(ev->x < x + blw)
-			click = ClkLtSymbol;
-		else if(ev->x > wx + ww - TEXTW(stext))
-			click = ClkStatusText;
-		else
-			click = ClkWinTitle;
-	}
-	else if((c = getclient(ev->window))) {
+	if((c = getclient(ev->window))) {
 		focus(c);
 		click = ClkClientWin;
 	}
@@ -321,7 +327,7 @@ buttonpress(XEvent *e) {
 	for(i = 0; i < LENGTH(buttons); i++)
 		if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
 		   && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
-			buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
+			buttons[i].func(&buttons[i].arg);
 }
 
 void
@@ -341,46 +347,21 @@ checkotherwm(void) {
 void
 cleanup(void) {
 	Arg a = {.ui = ~0};
-	Layout foo = { "", NULL };
 
-	close(STDIN_FILENO);
 	view(&a);
-	lt[sellt] = &foo;
+	lt[sellt] = NULL;
 	while(stack)
 		unmanage(stack);
-	if(dc.font.set)
-		XFreeFontSet(dpy, dc.font.set);
-	else
-		XFreeFont(dpy, dc.font.xfont);
 	XUngrabKey(dpy, AnyKey, AnyModifier, root);
-	XFreePixmap(dpy, dc.drawable);
 	XFreeGC(dpy, dc.gc);
 	XFreeCursor(dpy, cursor[CurNormal]);
 	XFreeCursor(dpy, cursor[CurResize]);
 	XFreeCursor(dpy, cursor[CurMove]);
-	XDestroyWindow(dpy, barwin);
 	XSync(dpy, False);
 	XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
 }
 
 void
-clearurgent(void) {
-	XWMHints *wmh;
-	Client *c;
-
-	for(c = clients; c; c = c->next)
-		if(ISVISIBLE(c) && c->isurgent) {
-			c->isurgent = False;
-			if (!(wmh = XGetWMHints(dpy, c->win)))
-				continue;
-
-			wmh->flags &= ~XUrgencyHint;
-			XSetWMHints(dpy, c->win, wmh);
-			XFree(wmh);
-		}
-}
-
-void
 configure(Client *c) {
 	XConfigureEvent ce;
 
@@ -406,7 +387,6 @@ configurenotify(XEvent *e) {
 		sw = ev->width;
 		sh = ev->height;
 		updategeom();
-		updatebar();
 		arrange();
 	}
 }
@@ -420,7 +400,7 @@ configurerequest(XEvent *e) {
 	if((c = getclient(ev->window))) {
 		if(ev->value_mask & CWBorderWidth)
 			c->bw = ev->border_width;
-		else if(c->isfloating || !lt[sellt]->arrange) {
+		else if(c->isfloating || !lt[sellt]) {
 			if(ev->value_mask & CWX)
 				c->x = sx + ev->x;
 			if(ev->value_mask & CWY)
@@ -490,103 +470,6 @@ die(const char *errstr, ...) {
 }
 
 void
-drawbar(void) {
-	int x;
-	unsigned int i, occ = 0, urg = 0;
-	unsigned long *col;
-	Client *c;
-
-	for(c = clients; c; c = c->next) {
-		occ |= c->tags;
-		if(c->isurgent)
-			urg |= c->tags;
-	}
-
-	dc.x = 0;
-	for(i = 0; i < LENGTH(tags); i++) {
-		dc.w = TEXTW(tags[i]);
-		col = tagset[seltags] & 1 << i ? dc.sel : dc.norm;
-		drawtext(tags[i], col, urg & 1 << i);
-		drawsquare(sel && sel->tags & 1 << i, occ & 1 << i, urg & 1 << i, col);
-		dc.x += dc.w;
-	}
-	if(blw > 0) {
-		dc.w = blw;
-		drawtext(lt[sellt]->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 < x) {
-		dc.x = x;
-		dc.w = ww - x;
-	}
-	drawtext(stext, dc.norm, False);
-	if((dc.w = dc.x - x) > bh) {
-		dc.x = x;
-		if(sel) {
-			drawtext(sel->name, dc.sel, False);
-			drawsquare(sel->isfixed, sel->isfloating, False, dc.sel);
-		}
-		else
-			drawtext(NULL, dc.norm, False);
-	}
-	XCopyArea(dpy, dc.drawable, barwin, dc.gc, 0, 0, ww, bh, 0, 0);
-	XSync(dpy, False);
-}
-
-void
-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[invert ? ColBG : ColFG];
-	XChangeGC(dpy, dc.gc, GCForeground, &gcv);
-	x = (dc.font.ascent + dc.font.descent + 2) / 4;
-	r.x = dc.x + 1;
-	r.y = dc.y + 1;
-	if(filled) {
-		r.width = r.height = x + 1;
-		XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
-	}
-	else if(empty) {
-		r.width = r.height = x;
-		XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
-	}
-}
-
-void
-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[invert ? ColFG : ColBG]);
-	XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
-	if(!text)
-		return;
-	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 */
-	for(len = MIN(olen, sizeof buf); len && textnw(text, len) > dc.w - h; len--);
-	if(!len)
-		return;
-	memcpy(buf, text, len);
-	if(len < olen)
-		for(i = len; i && i > 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
 enternotify(XEvent *e) {
 	Client *c;
 	XCrossingEvent *ev = &e->xcrossing;
@@ -600,17 +483,9 @@ enternotify(XEvent *e) {
 }
 
 void
-expose(XEvent *e) {
-	XExposeEvent *ev = &e->xexpose;
-
-	if(ev->count == 0 && (ev->window == barwin))
-		drawbar();
-}
-
-void
 focus(Client *c) {
 	if(!c || !ISVISIBLE(c))
-		for(c = stack; c && !ISVISIBLE(c); c = c->snext);
+		for(c = stack; c && (!ISVISIBLE(c) || c->isignored); c = c->snext);
 	if(sel && sel != c) {
 		grabbuttons(sel, False);
 		XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
@@ -625,7 +500,6 @@ focus(Client *c) {
 	else
 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
 	sel = c;
-	drawbar();
 }
 
 void
@@ -642,18 +516,18 @@ focusstack(const Arg *arg) {
 
 	if(!sel)
 		return;
-	if (arg->i > 0) {
-		for(c = sel->next; c && !ISVISIBLE(c); c = c->next);
+	if(arg->i > 0) {
+		for(c = sel->next; c && (!ISVISIBLE(c) || c->isignored); c = c->next);
 		if(!c)
-			for(c = clients; c && !ISVISIBLE(c); c = c->next);
+			for(c = clients; c && (!ISVISIBLE(c) || c->isignored); c = c->next);
 	}
 	else {
 		for(i = clients; i != sel; i = i->next)
-			if(ISVISIBLE(i))
+			if(ISVISIBLE(i) && !i->isignored)
 				c = i;
 		if(!c)
 			for(; i; i = i->next)
-				if(ISVISIBLE(i))
+				if(ISVISIBLE(i) && !i->isignored)
 					c = i;
 	}
 	if(c) {
@@ -698,32 +572,6 @@ getstate(Window w) {
 	return result;
 }
 
-Bool
-gettextprop(Window w, Atom atom, char *text, unsigned int size) {
-	char **list = NULL;
-	int n;
-	XTextProperty name;
-
-	if(!text || size == 0)
-		return False;
-	text[0] = '\0';
-	XGetTextProperty(dpy, w, &name, atom);
-	if(!name.nitems)
-		return False;
-	if(name.encoding == XA_STRING)
-		strncpy(text, (char *)name.value, size - 1);
-	else {
-		if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
-		&& n > 0 && *list) {
-			strncpy(text, *list, size - 1);
-			XFreeStringList(list);
-		}
-	}
-	text[size - 1] = '\0';
-	XFree(name.value);
-	return True;
-}
-
 void
 grabbuttons(Client *c, Bool focused) {
 	updatenumlockmask();
@@ -761,38 +609,29 @@ grabkeys(void) {
 }
 
 void
-initfont(const char *fontstr) {
-	char *def, **missing;
-	int i, n;
+grid() {
+	unsigned int i, n, cx, cy, cw, ch, aw, ah, cols, rows;
+	Client *c;
 
-	missing = NULL;
-	dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def);
-	if(missing) {
-		while(n--)
-			fprintf(stderr, "dwm: missing fontset: %s\n", missing[n]);
-		XFreeStringList(missing);
-	}
-	if(dc.font.set) {
-		XFontSetExtents *font_extents;
-		XFontStruct **xfonts;
-		char **font_names;
-		dc.font.ascent = dc.font.descent = 0;
-		font_extents = XExtentsOfFontSet(dc.font.set);
-		n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names);
-		for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) {
-			dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent);
-			dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent);
-			xfonts++;
-		}
-	}
-	else {
-		if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr))
-		&& !(dc.font.xfont = XLoadQueryFont(dpy, "fixed")))
-			die("error, cannot load font: '%s'\n", fontstr);
-		dc.font.ascent = dc.font.xfont->ascent;
-		dc.font.descent = dc.font.xfont->descent;
+	for(n = 0, c = nexttiled(clients); c; c = nexttiled(c->next))
+		n++;
+	/* grid dimensions */
+	for(rows = 0; rows <= n/2; rows++)
+		if(rows*rows >= n)
+			break;
+	cols = (rows && (rows - 1) * rows >= n) ? rows - 1 : rows;
+	/* window geoms (cell height/width) */
+	ch = wh / (rows ? rows : 1);
+	cw = ww / (cols ? cols : 1);
+	for(i = 0, c = nexttiled(clients); c; c = nexttiled(c->next)) {
+		cx = (i / rows) * cw;
+		cy = (i % rows) * ch;
+		/* adjust height/width of last row/column's windows */
+		ah = ((i + 1) % rows == 0) ? wh - ch * rows : 0;
+		aw = (i >= rows * (cols - 1)) ? ww - cw * cols : 0;
+		resize(c, cx, cy, cw - 2 * c->bw + aw, ch - 2 * c->bw + ah, False);
+		i++;
 	}
-	dc.font.height = dc.font.ascent + dc.font.descent;
 }
 
 Bool
@@ -845,15 +684,23 @@ killclient(const Arg *arg) {
 }
 
 void
+raisewin(const Arg *arg) {
+    if(!sel)
+        return;
+    if(arg->i > 0)
+        XRaiseWindow(dpy, sel->win);
+    else if(!sel->isontop)
+        XLowerWindow(dpy, sel->win);
+}
+
+void
 manage(Window w, XWindowAttributes *wa) {
-	static Client cz;
 	Client *c, *t = NULL;
 	Window trans = None;
 	XWindowChanges wc;
 
-	if(!(c = malloc(sizeof(Client))))
-		die("fatal: could not malloc() %u bytes\n", sizeof(Client));
-	*c = cz;
+	if(!(c = calloc(1, sizeof(Client))))
+		die("fatal: could not calloc() %u bytes\n", sizeof(Client));
 	c->win = w;
 
 	/* geometry */
@@ -873,8 +720,7 @@ manage(Window w, XWindowAttributes *wa) 
 		if(c->y + c->h + 2 * c->bw > sy + sh)
 			c->y = sy + sh - NOBORDER(c->h);
 		c->x = MAX(c->x, sx);
-		/* only fix client y-offset, if the client center might cover the bar */
-		c->y = MAX(c->y, ((by == 0) && (c->x + (c->w / 2) >= wx) && (c->x + (c->w / 2) < wx + ww)) ? bh : sy);
+		c->y = MAX(c->y, sy);
 		c->bw = borderpx;
 	}
 
@@ -885,7 +731,6 @@ manage(Window w, XWindowAttributes *wa) 
 	updatesizehints(c);
 	XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
 	grabbuttons(c, False);
-	updatetitle(c);
 	if(XGetTransientForHint(dpy, w, &trans))
 		t = getclient(trans);
 	if(t)
@@ -894,7 +739,7 @@ manage(Window w, XWindowAttributes *wa) 
 		applyrules(c);
 	if(!c->isfloating)
 		c->isfloating = trans != None || c->isfixed;
-	if(c->isfloating)
+	if(c->isfloating || c->isontop)
 		XRaiseWindow(dpy, c->win);
 	attach(c);
 	attachstack(c);
@@ -973,10 +818,10 @@ movemouse(const Arg *arg) {
 					ny = wy;
 				else if(abs((wy + wh) - (ny + c->h + 2 * c->bw)) < snap)
 					ny = wy + wh - NOBORDER(c->h);
-				if(!c->isfloating && lt[sellt]->arrange && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
+				if(!c->isfloating && lt[sellt] && (abs(nx - c->x) > snap || abs(ny - c->y) > snap))
 					togglefloating(NULL);
 			}
-			if(!lt[sellt]->arrange || c->isfloating)
+			if(!lt[sellt] || c->isfloating)
 				resize(c, nx, ny, c->w, c->h, False);
 			break;
 		}
@@ -1010,15 +855,6 @@ propertynotify(XEvent *e) {
 		case XA_WM_NORMAL_HINTS:
 			updatesizehints(c);
 			break;
-		case XA_WM_HINTS:
-			updatewmhints(c);
-			drawbar();
-			break;
-		}
-		if(ev->atom == XA_WM_NAME || ev->atom == netatom[NetWMName]) {
-			updatetitle(c);
-			if(c == sel)
-				drawbar();
 		}
 	}
 }
@@ -1031,8 +867,8 @@ quit(const Arg *arg) {
 void
 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
 	XWindowChanges wc;
-
-	if(sizehints) {
+	
+	if(sizehints) { 
 		/* see last two sentences in ICCCM 4.1.2.3 */
 		Bool baseismin = c->basew == c->minw && c->baseh == c->minh;
 
@@ -1049,7 +885,7 @@ resize(Client *c, int x, int y, int w, i
 		if(c->mina > 0 && c->maxa > 0) {
 			if(c->maxa < (float)w / h)
 				w = h * c->maxa;
-			else if(c->mina < (float)h / w)
+			else if(c->mina > (float)h / w)
 				h = w * c->mina;
 		}
 
@@ -1087,10 +923,6 @@ resize(Client *c, int x, int y, int w, i
 		x = sx;
 	if(y + h + 2 * c->bw < sy)
 		y = sy;
-	if(h < bh)
-		h = bh;
-	if(w < bh)
-		w = bh;
 	if(c->x != x || c->y != y || c->w != w || c->h != h) {
 		c->x = wc.x = x;
 		c->y = wc.y = y;
@@ -1135,11 +967,11 @@ resizemouse(const Arg *arg) {
 
 			if(snap && nw >= wx && nw <= wx + ww
 			        && nh >= wy && nh <= wy + wh) {
-				if(!c->isfloating && lt[sellt]->arrange
+				if(!c->isfloating && lt[sellt]
 				   && (abs(nw - c->w) > snap || abs(nh - c->h) > snap))
 					togglefloating(NULL);
 			}
-			if(!lt[sellt]->arrange || c->isfloating)
+			if(!lt[sellt] || c->isfloating)
 				resize(c, c->x, c->y, nw, nh, True);
 			break;
 		}
@@ -1156,19 +988,17 @@ restack(void) {
 	XEvent ev;
 	XWindowChanges wc;
 
-	drawbar();
 	if(!sel)
 		return;
-	if(sel->isfloating || !lt[sellt]->arrange)
-		XRaiseWindow(dpy, sel->win);
-	if(lt[sellt]->arrange) {
+	if(lt[sellt]) {
 		wc.stack_mode = Below;
-		wc.sibling = barwin;
 		for(c = stack; c; c = c->snext)
-			if(!c->isfloating && ISVISIBLE(c)) {
+			if((!c->isfloating || !c->isontop || !lt[sellt]) && ISVISIBLE(c)) {
 				XConfigureWindow(dpy, c->win, CWSibling|CWStackMode, &wc);
 				wc.sibling = c->win;
 			}
+			else
+				XRaiseWindow(dpy, c->win);
 	}
 	XSync(dpy, False);
 	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
@@ -1176,60 +1006,14 @@ restack(void) {
 
 void
 run(void) {
-	char *p;
-	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 */
+	/* main event loop */
 	XSync(dpy, False);
-	xfd = ConnectionNumber(dpy);
-	offset = 0;
-	len = sizeof stext - 1;
-	sbuf[len] = stext[len] = '\0'; /* 0-terminator is never touched */
 	while(running) {
-		FD_ZERO(&rd);
-		if(readin)
-			FD_SET(STDIN_FILENO, &rd);
-		FD_SET(xfd, &rd);
-		if(select(xfd + 1, &rd, NULL, NULL, NULL) == -1) {
-			if(errno == EINTR)
-				continue;
-			die("select failed\n");
-		}
-		if(FD_ISSET(STDIN_FILENO, &rd)) {
-			switch((r = read(STDIN_FILENO, sbuf + offset, len - offset))) {
-			case -1:
-				strncpy(stext, strerror(errno), len);
-				readin = False;
-				break;
-			case 0:
-				strncpy(stext, "EOF", 4);
-				readin = False;
-				break;
-			default:
-				for(p = sbuf + offset; r > 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) && *(p - r) != '\n'; r++);
-						offset = r;
-						if(r)
-							memmove(sbuf, p - r + 1, r);
-						break;
-					}
-				break;
-			}
-			drawbar();
-		}
-		while(XPending(dpy)) {
-			XNextEvent(dpy, &ev);
-			if(handler[ev.type])
-				(handler[ev.type])(&ev); /* call handler */
-		}
+		XNextEvent(dpy, &ev);
+		if(handler[ev.type])
+			(handler[ev.type])(&ev); /* call handler */
 	}
 }
 
@@ -1269,47 +1053,40 @@ setclientstate(Client *c, long state) {
 
 void
 setlayout(const Arg *arg) {
-	if(!arg || !arg->v || arg->v != lt[sellt])
-		sellt ^= 1;
-	if(arg && arg->v)
-		lt[sellt] = (Layout *)arg->v;
+	if(arg && arg->func != lt[sellt])
+		lt[sellt] = lts[curtag] = arg->func;
 	if(sel)
 		arrange();
-	else
-		drawbar();
 }
 
-/* arg > 1.0 will set mfact absolutly */
+/* arg > 1.0 will set mfact absolutely */
 void
 setmfact(const Arg *arg) {
 	float f;
 
-	if(!arg || !lt[sellt]->arrange)
+	if(!arg || !lt[sellt])
 		return;
 	f = arg->f < 1.0 ? arg->f + mfact : arg->f - 1.0;
 	if(f < 0.1 || f > 0.9)
 		return;
-	mfact = f;
+	mfact = mfacts[curtag] = f;
 	arrange();
 }
 
 void
 setup(void) {
 	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] = &layouts[0];
-	lt[1] = &layouts[1 % LENGTH(layouts)];
+	lt[0] = tile;
+	lt[1] = NULL;
 	updategeom();
 
 	/* init atoms */
@@ -1326,35 +1103,22 @@ setup(void) {
 
 	/* 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);
-	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->fid);
 
-	/* init bar */
-	for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) {
-		w = TEXTW(layouts[i].symbol);
-		blw = MAX(blw, w);
-	}
+	/* init mfacts */
+	for(i = 0; i < NUMTAGS + 1; i++)
+		mfacts[i] = mfact;
+
+	/* init layouts */
+	for(i = 0; i < NUMTAGS + 1; i++)
+		lts[i] = tile;
 
 	wa.override_redirect = 1;
 	wa.background_pixmap = ParentRelative;
 	wa.event_mask = ButtonPressMask|ExposureMask;
 
-	barwin = XCreateWindow(dpy, root, wx, by, ww, bh, 0, DefaultDepth(dpy, screen),
-			CopyFromParent, DefaultVisual(dpy, screen),
-			CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
-	XDefineCursor(dpy, barwin, cursor[CurNormal]);
-	XMapRaised(dpy, barwin);
-	strcpy(stext, "dwm-"VERSION);
-	drawbar();
-
 	/* EWMH support per view */
 	XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
 			PropModeReplace, (unsigned char *) netatom, NetLast);
@@ -1365,26 +1129,11 @@ setup(void) {
 	XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
 	XSelectInput(dpy, root, wa.event_mask);
 
+	/* grab keys */
 	grabkeys();
 }
 
 void
-showhide(Client *c) {
-	if(!c)
-		return;
-	if(ISVISIBLE(c)) { /* show clients top down */
-		XMoveWindow(dpy, c->win, c->x, c->y);
-		if(!lt[sellt]->arrange || c->isfloating)
-			resize(c, c->x, c->y, c->w, c->h, True);
-		showhide(c->snext);
-	}
-	else { /* hide clients bottom up */
-		showhide(c->snext);
-		XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
-	}
-}
-
-void
 spawn(const Arg *arg) {
 	/* The double-fork construct avoids zombie processes and keeps the code
 	 * clean from stupid signal handlers. */
@@ -1410,17 +1159,6 @@ tag(const Arg *arg) {
 	}
 }
 
-int
-textnw(const char *text, unsigned int len) {
-	XRectangle r;
-
-	if(dc.font.set) {
-		XmbTextExtents(dc.font.set, text, len, NULL, &r);
-		return r.width;
-	}
-	return XTextWidth(dc.font.xfont, text, len);
-}
-
 void
 tile(void) {
 	int x, y, h, w, mw;
@@ -1444,8 +1182,6 @@ tile(void) {
 	y = wy;
 	w = (wx + mw > c->x + c->w) ? wx + ww - x : ww - mw;
 	h = wh / n;
-	if(h < bh)
-		h = wh;
 
 	for(i = 0, c = nexttiled(c->next); c; c = nexttiled(c->next), i++) {
 		resize(c, x, y, NOBORDER(w), /* remainder */ ((i + 1 == n)
@@ -1456,14 +1192,6 @@ tile(void) {
 }
 
 void
-togglebar(const Arg *arg) {
-	showbar = !showbar;
-	updategeom();
-	updatebar();
-	arrange();
-}
-
-void
 togglefloating(const Arg *arg) {
 	if(!sel)
 		return;
@@ -1477,11 +1205,10 @@ void
 toggletag(const Arg *arg) {
 	unsigned int mask;
 
-	if (!sel)
-		return;
-	
-	mask = sel->tags ^ (arg->ui & TAGMASK);
-	if(sel && mask) {
+    if(!sel)
+        return;
+    mask = sel->tags ^ (arg->ui & TAGMASK);
+	if(mask) {
 		sel->tags = mask;
 		arrange();
 	}
@@ -1489,13 +1216,27 @@ toggletag(const Arg *arg) {
 
 void
 toggleview(const Arg *arg) {
-	unsigned int mask = tagset[seltags] ^ (arg->ui & TAGMASK);
-
+	unsigned int i, mask = tagset[seltags] ^ (arg->ui & TAGMASK);
+	
 	if(mask) {
 		tagset[seltags] = mask;
-		clearurgent();
 		arrange();
 	}
+	if(mask) {
+		if(mask == ~0) {
+			prevtag = curtag;
+			curtag = 0;
+		}
+		if(!(mask & 1 << (curtag - 1))) {
+			prevtag = curtag;
+			for(i=0; !(mask & 1 << i); i++);
+			curtag = i + 1;
+		}
+		tagset[seltags] = mask;
+		lt[sellt] = lts[curtag];
+		mfact = mfacts[curtag];
+		arrange();
+    }
 }
 
 void
@@ -1530,14 +1271,6 @@ unmapnotify(XEvent *e) {
 }
 
 void
-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);
-}
-
-void
 updategeom(void) {
 #ifdef XINERAMA
 	int n, i = 0;
@@ -1555,22 +1288,19 @@ updategeom(void) {
 						break;
 		}
 		wx = info[i].x_org;
-		wy = showbar && topbar ?  info[i].y_org + bh : info[i].y_org;
+		wy = info[i].y_org;
 		ww = info[i].width;
-		wh = showbar ? info[i].height - bh : info[i].height;
+		wh = info[i].height;
 		XFree(info);
 	}
 	else
 #endif
 	{
 		wx = sx;
-		wy = showbar && topbar ? sy + bh : sy;
+		wy = sy;
 		ww = sw;
-		wh = showbar ? sh - bh : sh;
+		wh = sh;
 	}
-
-	/* bar position */
-	by = showbar ? (topbar ? wy - bh : wy + wh) : -bh;
 }
 
 void
@@ -1634,40 +1364,34 @@ updatesizehints(Client *c) {
 	else
 		c->maxa = c->mina = 0.0;
 	c->isfixed = (c->maxw && c->minw && c->maxh && c->minh
-	             && c->maxw == c->minw && c->maxh == c->minh);
-}
-
-void
-updatetitle(Client *c) {
-	if(!gettextprop(c->win, netatom[NetWMName], c->name, sizeof c->name))
-		gettextprop(c->win, XA_WM_NAME, c->name, sizeof c->name);
-}
-
-void
-updatewmhints(Client *c) {
-	XWMHints *wmh;
-
-	if((wmh = XGetWMHints(dpy, c->win))) {
-		if(ISVISIBLE(c) && wmh->flags & XUrgencyHint) {
-			wmh->flags &= ~XUrgencyHint;
-			XSetWMHints(dpy, c->win, wmh);
-		}
-		else
-			c->isurgent = (wmh->flags & XUrgencyHint) ? True : False;
-
-		XFree(wmh);
-	}
+			&& c->maxw == c->minw && c->maxh == c->minh);
 }
 
+/* FIXME */
 void
 view(const Arg *arg) {
+	unsigned int i;
+
 	if((arg->ui & TAGMASK) == tagset[seltags])
 		return;
 	seltags ^= 1; /* toggle sel tagset */
-	if(arg->ui & TAGMASK)
+	if(arg->ui & TAGMASK) {
 		tagset[seltags] = arg->ui & TAGMASK;
-	clearurgent();
-	arrange();
+		prevtag = curtag;
+		if(arg->ui == ~0)
+			curtag = 0;
+		else {
+			for(i=0; !(arg->ui & 1 << i); i++);
+			curtag = i + 1;
+		}
+	} else {
+		prevtag= curtag ^ prevtag;
+		curtag^= prevtag;
+		prevtag= curtag ^ prevtag;
+	}
+	lt[sellt]= lts[curtag];
+	mfact = mfacts[curtag];
+ 	arrange();
 }
 
 /* There's no way to check accesses to destroyed windows, thus those cases are
@@ -1707,7 +1431,7 @@ void
 zoom(const Arg *arg) {
 	Client *c = sel;
 
-	if(!lt[sellt]->arrange || lt[sellt]->arrange == monocle || (sel && sel->isfloating))
+	if(!lt[sellt] || lt[sellt] == monocle || (sel && sel->isfloating))
 		return;
 	if(c == nexttiled(clients))
 		if(!c || !(c = nexttiled(c->next)))
@@ -1725,9 +1449,6 @@ main(int argc, char *argv[]) {
 	else if(argc != 1)
 		die("usage: dwm [-v]\n");
 
-	if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())
-		fprintf(stderr, "warning: no locale support\n");
-
 	if(!(dpy = XOpenDisplay(0)))
 		die("dwm: cannot open display\n");