Hi all,

Attached is a dwm patch that pulls out all of the key and button
handlers, and all of the layouts, into a new file called config.c,
replacing config.h. The idea is that it makes it clearer what is dwm
proper and what is just a part of the default config.

I've sat on this patch for about half a year, and I've still not made
my mind up as to whether it's a good idea or not. But I thought I
might as well post it on here anyway.

Thanks,
cls
commit af3575a3388b6518de395a09e0becad0d486df76
Author: Connor Lane Smith <c...@lubutu.com>
Date:   Mon Nov 23 17:29:28 2015 +0000

    separate config.o

diff --git a/Makefile b/Makefile
index 1ea40b7..f95c9db 100644
--- a/Makefile
+++ b/Makefile
@@ -3,7 +3,7 @@
 
 include config.mk
 
-SRC = drw.c dwm.c util.c
+SRC = config.c drw.c dwm.c util.c
 OBJ = ${SRC:.c=.o}
 
 all: options dwm
@@ -18,11 +18,11 @@ options:
        @echo CC $<
        @${CC} -c ${CFLAGS} $<
 
-${OBJ}: config.h config.mk
+${OBJ}: dwm.h config.mk
 
-config.h:
-       @echo creating $@ from config.def.h
-       @cp config.def.h $@
+config.c:
+       @echo creating $@ from config.def.c
+       @cp config.def.c $@
 
 dwm: ${OBJ}
        @echo CC -o $@
@@ -35,8 +35,8 @@ clean:
 dist: clean
        @echo creating dist tarball
        @mkdir -p dwm-${VERSION}
-       @cp -R LICENSE TODO BUGS Makefile README config.def.h config.mk \
-               dwm.1 drw.h util.h ${SRC} dwm.png transient.c dwm-${VERSION}
+       @cp -R LICENSE TODO BUGS Makefile README config.def.c config.mk \
+               dwm.1 drw.h dwm.h util.h ${SRC} dwm.png transient.c 
dwm-${VERSION}
        @tar -cf dwm-${VERSION}.tar dwm-${VERSION}
        @gzip dwm-${VERSION}.tar
        @rm -rf dwm-${VERSION}
diff --git a/README b/README
index 7abf1cf..1208997 100644
--- a/README
+++ b/README
@@ -47,5 +47,5 @@ like this in your .xinitrc:
 
 Configuration
 -------------
-The configuration of dwm is done by creating a custom config.h
+The configuration of dwm is done by creating a custom config.c
 and (re)compiling the source code.
diff --git a/config.def.c b/config.def.c
new file mode 100644
index 0000000..dfa8a17
--- /dev/null
+++ b/config.def.c
@@ -0,0 +1,528 @@
+/* See LICENSE file for copyright and license details. */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <X11/keysym.h>
+#include <X11/Xlib.h>
+#include <X11/Xft/Xft.h>
+
+#include "drw.h"
+#include "util.h"
+#include "dwm.h"
+
+/* appearance */
+const char *fonts[] = {
+    "Sans:size=10.5",
+    "VL Gothic:size=10.5",
+    "WenQuanYi Micro Hei:size=10.5",
+};
+const int nfonts = LENGTH(fonts);
+
+const char normbordercolor[] = "#444444";
+const char normbgcolor[]     = "#222222";
+const char normfgcolor[]     = "#bbbbbb";
+const char selbordercolor[]  = "#005577";
+const char selbgcolor[]      = "#005577";
+const char selfgcolor[]      = "#eeeeee";
+const unsigned int borderpx  = 1;        /* border pixel of windows */
+const unsigned int snap      = 32;       /* snap pixel */
+const int showbar            = 1;        /* 0 means no bar */
+const int topbar             = 1;        /* 0 means bottom bar */
+
+/* tagging */
+const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
+const int ntags = LENGTH(tags);
+
+/* compile-time check if all tags fit into an unsigned int bit array. */
+struct NumTags { char limitexceeded[LENGTH(tags) >= sizeof(unsigned int) * 8 ? 
-1 : 1]; };
+
+const Rule rules[] = {
+       /* xprop(1):
+        *      WM_CLASS(STRING) = instance, class
+        *      WM_NAME(STRING) = title
+        */
+       /* class      instance    title       tags mask     isfloating   
monitor */
+       { "Gimp",     NULL,       NULL,       0,            1,           -1 },
+       { "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 },
+};
+const int nrules = LENGTH(rules);
+
+/* layout(s) */
+const float mfact     = 0.55; /* factor of master area size [0.05..0.95] */
+const int nmaster     = 1;    /* number of clients in master area */
+const int resizehints = 1;    /* 1 means respect size hints in tiled resizals 
*/
+
+static void monocle(Monitor *m);
+static void tile(Monitor *m);
+
+const Layout layouts[] = {
+       /* symbol     arrange function */
+       { "[]=",      tile },    /* first entry is default */
+       { "><>",      NULL },    /* no layout function means floating behavior 
*/
+       { "[M]",      monocle },
+};
+const int nlayouts = LENGTH(layouts);
+
+void
+monocle(Monitor *m)
+{
+       unsigned int n = 0;
+       Client *c;
+
+       for (c = m->clients; c; c = c->next)
+               if (ISVISIBLE(c))
+                       n++;
+       if (n > 0) /* override layout symbol */
+               snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
+       for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
+               resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 
0);
+}
+
+void
+tile(Monitor *m)
+{
+       unsigned int i, n, h, mw, my, ty;
+       Client *c;
+
+       for (n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+       if (n == 0)
+               return;
+
+       if (n > m->nmaster)
+               mw = m->nmaster ? m->ww * m->mfact : 0;
+       else
+               mw = m->ww;
+       for (i = my = ty = 0, c = nexttiled(m->clients); c; c = 
nexttiled(c->next), i++)
+               if (i < m->nmaster) {
+                       h = (m->wh - my) / (MIN(n, m->nmaster) - i);
+                       resize(c, m->wx, m->wy + my, mw - (2*c->bw), h - 
(2*c->bw), 0);
+                       my += HEIGHT(c);
+               }
+               else {
+                       h = (m->wh - ty) / (n - i);
+                       resize(c, m->wx + mw, m->wy + ty, m->ww - mw - 
(2*c->bw), h - (2*c->bw), 0);
+                       ty += HEIGHT(c);
+               }
+}
+
+/* key definitions */
+#define MODKEY Mod1Mask
+#define TAGKEYS(KEY,TAG) \
+       { MODKEY,                       KEY,      view,           {.ui = 1 << 
TAG} }, \
+       { MODKEY|ControlMask,           KEY,      toggleview,     {.ui = 1 << 
TAG} }, \
+       { MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 << 
TAG} }, \
+       { MODKEY|ControlMask|ShiftMask, KEY,      toggletag,      {.ui = 1 << 
TAG} },
+
+/* helper for spawning shell commands in the pre dwm-5.0 fashion */
+#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
+
+/* commands */
+static void focusmon(const Arg *arg);
+static void focusstack(const Arg *arg);
+static void incnmaster(const Arg *arg);
+static void killclient(const Arg *arg);
+static void movemouse(const Arg *arg);
+static void quit(const Arg *arg);
+static void resizemouse(const Arg *arg);
+static void setlayout(const Arg *arg);
+static void setmfact(const Arg *arg);
+static void spawn(const Arg *arg);
+static void tag(const Arg *arg);
+static void tagmon(const Arg *arg);
+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 view(const Arg *arg);
+static void zoom(const Arg *arg);
+
+static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in 
spawn() */
+static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, NULL };
+static const char *termcmd[]  = { "st", NULL };
+
+const 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_i,      incnmaster,     {.i = +1 } },
+       { MODKEY,                       XK_d,      incnmaster,     {.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|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|ShiftMask,             XK_space,  togglefloating, {0} },
+       { MODKEY,                       XK_0,      view,           {.ui = ~0 } 
},
+       { MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } 
},
+       { MODKEY,                       XK_comma,  focusmon,       {.i = -1 } },
+       { MODKEY,                       XK_period, focusmon,       {.i = +1 } },
+       { MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } },
+       { MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } },
+       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} },
+};
+const int nkeys = LENGTH(keys);
+
+/* button definitions */
+/* click can be ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or 
ClkRootWin */
+const 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} },
+};
+const int nbuttons = LENGTH(buttons);
+
+void
+focusmon(const Arg *arg)
+{
+       Monitor *m;
+
+       if (!mons->next)
+               return;
+       if ((m = dirtomon(arg->i)) == selmon)
+               return;
+       unfocus(selmon->sel, 0); /* s/1/0/ fixes input focus issues
+                                       in gedit and anjuta */
+       selmon = m;
+       focus(NULL);
+}
+
+void
+focusstack(const Arg *arg)
+{
+       Client *c = NULL, *i;
+
+       if (!selmon->sel)
+               return;
+       if (arg->i > 0) {
+               for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
+               if (!c)
+                       for (c = selmon->clients; c && !ISVISIBLE(c); c = 
c->next);
+       }
+       else {
+               for (i = selmon->clients; i != selmon->sel; i = i->next)
+                       if (ISVISIBLE(i))
+                               c = i;
+               if (!c)
+                       for (; i; i = i->next)
+                               if (ISVISIBLE(i))
+                                       c = i;
+       }
+       if (c) {
+               focus(c);
+               restack(selmon);
+       }
+}
+
+void
+incnmaster(const Arg *arg)
+{
+       selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
+       arrange(selmon);
+}
+
+void
+killclient(const Arg *arg)
+{
+       if (!selmon->sel)
+               return;
+       if (!sendevent(selmon->sel, wmatom[WMDelete])) {
+               XGrabServer(dpy);
+               XSetErrorHandler(xerrordummy);
+               XSetCloseDownMode(dpy, DestroyAll);
+               XKillClient(dpy, selmon->sel->win);
+               XSync(dpy, 0);
+               XSetErrorHandler(xerror);
+               XUngrabServer(dpy);
+       }
+}
+
+void
+movemouse(const Arg *arg)
+{
+       int x, y, ocx, ocy, nx, ny;
+       Client *c;
+       Monitor *m;
+       XEvent ev;
+       Time lasttime = 0;
+
+       if (!(c = selmon->sel))
+               return;
+       if (c->isfullscreen) /* no support moving fullscreen windows by mouse */
+               return;
+       restack(selmon);
+       ocx = c->x;
+       ocy = c->y;
+       if (XGrabPointer(dpy, root, 0, MOUSEMASK, GrabModeAsync, GrabModeAsync,
+       None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
+               return;
+       if (!getrootptr(&x, &y))
+               return;
+       do {
+               XMaskEvent(dpy, 
MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
+               switch(ev.type) {
+               case ConfigureRequest:
+               case Expose:
+               case MapRequest:
+                       handler[ev.type](&ev);
+                       break;
+               case MotionNotify:
+                       if ((ev.xmotion.time - lasttime) <= (1000 / 60))
+                               continue;
+                       lasttime = ev.xmotion.time;
+
+                       nx = ocx + (ev.xmotion.x - x);
+                       ny = ocy + (ev.xmotion.y - y);
+                       if (nx >= selmon->wx && nx <= selmon->wx + selmon->ww
+                       && ny >= selmon->wy && ny <= selmon->wy + selmon->wh) {
+                               if (abs(selmon->wx - nx) < snap)
+                                       nx = selmon->wx;
+                               else if (abs((selmon->wx + selmon->ww) - (nx + 
WIDTH(c))) < snap)
+                                       nx = selmon->wx + selmon->ww - WIDTH(c);
+                               if (abs(selmon->wy - ny) < snap)
+                                       ny = selmon->wy;
+                               else if (abs((selmon->wy + selmon->wh) - (ny + 
HEIGHT(c))) < snap)
+                                       ny = selmon->wy + selmon->wh - 
HEIGHT(c);
+                               if (!c->isfloating && 
selmon->lt[selmon->sellt]->arrange
+                               && (abs(nx - c->x) > snap || abs(ny - c->y) > 
snap))
+                                       togglefloating(NULL);
+                       }
+                       if (!selmon->lt[selmon->sellt]->arrange || 
c->isfloating)
+                               resize(c, nx, ny, c->w, c->h, 1);
+                       break;
+               }
+       } while (ev.type != ButtonRelease);
+       XUngrabPointer(dpy, CurrentTime);
+       if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
+               sendmon(c, m);
+               selmon = m;
+               focus(NULL);
+       }
+}
+
+void
+quit(const Arg *arg)
+{
+       running = 0;
+}
+
+void
+resizemouse(const Arg *arg)
+{
+       int ocx, ocy, nw, nh;
+       Client *c;
+       Monitor *m;
+       XEvent ev;
+       Time lasttime = 0;
+
+       if (!(c = selmon->sel))
+               return;
+       if (c->isfullscreen) /* no support resizing fullscreen windows by mouse 
*/
+               return;
+       restack(selmon);
+       ocx = c->x;
+       ocy = c->y;
+       if (XGrabPointer(dpy, root, 0, MOUSEMASK, GrabModeAsync, GrabModeAsync,
+                       None, cursor[CurResize]->cursor, CurrentTime) != 
GrabSuccess)
+               return;
+       XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + 
c->bw - 1);
+       do {
+               XMaskEvent(dpy, 
MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
+               switch(ev.type) {
+               case ConfigureRequest:
+               case Expose:
+               case MapRequest:
+                       handler[ev.type](&ev);
+                       break;
+               case MotionNotify:
+                       if ((ev.xmotion.time - lasttime) <= (1000 / 60))
+                               continue;
+                       lasttime = ev.xmotion.time;
+
+                       nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
+                       nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
+                       if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= 
selmon->wx + selmon->ww
+                       && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= 
selmon->wy + selmon->wh)
+                       {
+                               if (!c->isfloating && 
selmon->lt[selmon->sellt]->arrange
+                               && (abs(nw - c->w) > snap || abs(nh - c->h) > 
snap))
+                                       togglefloating(NULL);
+                       }
+                       if (!selmon->lt[selmon->sellt]->arrange || 
c->isfloating)
+                               resize(c, c->x, c->y, nw, nh, 1);
+                       break;
+               }
+       } while (ev.type != ButtonRelease);
+       XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + 
c->bw - 1);
+       XUngrabPointer(dpy, CurrentTime);
+       while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
+       if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
+               sendmon(c, m);
+               selmon = m;
+               focus(NULL);
+       }
+}
+
+void
+setlayout(const Arg *arg)
+{
+       if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
+               selmon->sellt ^= 1;
+       if (arg && arg->v)
+               selmon->lt[selmon->sellt] = (Layout *)arg->v;
+       strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof 
selmon->ltsymbol);
+       if (selmon->sel)
+               arrange(selmon);
+       else
+               drawbar(selmon);
+}
+
+/* arg > 1.0 will set mfact absolutly */
+void
+setmfact(const Arg *arg)
+{
+       float f;
+
+       if (!arg || !selmon->lt[selmon->sellt]->arrange)
+               return;
+       f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
+       if (f < 0.1 || f > 0.9)
+               return;
+       selmon->mfact = f;
+       arrange(selmon);
+}
+
+void
+spawn(const Arg *arg)
+{
+       if (arg->v == dmenucmd)
+               dmenumon[0] = '0' + selmon->num;
+       if (fork() == 0) {
+               if (dpy)
+                       close(ConnectionNumber(dpy));
+               setsid();
+               execvp(((char **)arg->v)[0], (char **)arg->v);
+               fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
+               perror(" failed");
+               exit(EXIT_SUCCESS);
+       }
+}
+
+void
+tag(const Arg *arg)
+{
+       if (selmon->sel && arg->ui & TAGMASK) {
+               selmon->sel->tags = arg->ui & TAGMASK;
+               focus(NULL);
+               arrange(selmon);
+       }
+}
+
+void
+tagmon(const Arg *arg)
+{
+       if (!selmon->sel || !mons->next)
+               return;
+       sendmon(selmon->sel, dirtomon(arg->i));
+}
+
+void
+togglebar(const Arg *arg)
+{
+       selmon->showbar = !selmon->showbar;
+       updatebarpos(selmon);
+       XMoveResizeWindow(dpy, selmon->barwin, selmon->wx, selmon->by, 
selmon->ww, bh);
+       arrange(selmon);
+}
+
+void
+togglefloating(const Arg *arg)
+{
+       if (!selmon->sel)
+               return;
+       if (selmon->sel->isfullscreen) /* no support for fullscreen windows */
+               return;
+       selmon->sel->isfloating = !selmon->sel->isfloating || 
selmon->sel->isfixed;
+       if (selmon->sel->isfloating)
+               resize(selmon->sel, selmon->sel->x, selmon->sel->y,
+                      selmon->sel->w, selmon->sel->h, 0);
+       arrange(selmon);
+}
+
+void
+toggletag(const Arg *arg)
+{
+       unsigned int newtags;
+
+       if (!selmon->sel)
+               return;
+       newtags = selmon->sel->tags ^ (arg->ui & TAGMASK);
+       if (newtags) {
+               selmon->sel->tags = newtags;
+               focus(NULL);
+               arrange(selmon);
+       }
+}
+
+void
+toggleview(const Arg *arg)
+{
+       unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & 
TAGMASK);
+
+       if (newtagset) {
+               selmon->tagset[selmon->seltags] = newtagset;
+               focus(NULL);
+               arrange(selmon);
+       }
+}
+
+void
+view(const Arg *arg)
+{
+       if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
+               return;
+       selmon->seltags ^= 1; /* toggle sel tagset */
+       if (arg->ui & TAGMASK)
+               selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
+       focus(NULL);
+       arrange(selmon);
+}
+
+void
+zoom(const Arg *arg)
+{
+       Client *c = selmon->sel;
+
+       if (!selmon->lt[selmon->sellt]->arrange
+       || (selmon->sel && selmon->sel->isfloating))
+               return;
+       if (c == nexttiled(selmon->clients))
+               if (!c || !(c = nexttiled(c->next)))
+                       return;
+       pop(c);
+}
diff --git a/config.def.h b/config.def.h
deleted file mode 100644
index 7054c06..0000000
--- a/config.def.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* See LICENSE file for copyright and license details. */
-
-/* appearance */
-static const char *fonts[] = {
-       "monospace:size=10"
-};
-static const char dmenufont[]       = "monospace:size=10";
-static const char normbordercolor[] = "#444444";
-static const char normbgcolor[]     = "#222222";
-static const char normfgcolor[]     = "#bbbbbb";
-static const char selbordercolor[]  = "#005577";
-static const char selbgcolor[]      = "#005577";
-static const char selfgcolor[]      = "#eeeeee";
-static const unsigned int borderpx  = 1;        /* border pixel of windows */
-static const unsigned int snap      = 32;       /* snap pixel */
-static const int showbar            = 1;        /* 0 means no bar */
-static const int topbar             = 1;        /* 0 means bottom bar */
-
-/* tagging */
-static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
-
-static const Rule rules[] = {
-       /* xprop(1):
-        *      WM_CLASS(STRING) = instance, class
-        *      WM_NAME(STRING) = title
-        */
-       /* class      instance    title       tags mask     isfloating   
monitor */
-       { "Gimp",     NULL,       NULL,       0,            1,           -1 },
-       { "Firefox",  NULL,       NULL,       1 << 8,       0,           -1 },
-};
-
-/* layout(s) */
-static const float mfact     = 0.55; /* factor of master area size 
[0.05..0.95] */
-static const int nmaster     = 1;    /* number of clients in master area */
-static const int resizehints = 1;    /* 1 means respect size hints in tiled 
resizals */
-
-static const 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) \
-       { MODKEY,                       KEY,      view,           {.ui = 1 << 
TAG} }, \
-       { MODKEY|ControlMask,           KEY,      toggleview,     {.ui = 1 << 
TAG} }, \
-       { MODKEY|ShiftMask,             KEY,      tag,            {.ui = 1 << 
TAG} }, \
-       { MODKEY|ControlMask|ShiftMask, KEY,      toggletag,      {.ui = 1 << 
TAG} },
-
-/* helper for spawning shell commands in the pre dwm-5.0 fashion */
-#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
-
-/* commands */
-static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in 
spawn() */
-static const char *dmenucmd[] = { "dmenu_run", "-m", dmenumon, "-fn", 
dmenufont, "-nb", normbgcolor, "-nf", normfgcolor, "-sb", selbgcolor, "-sf", 
selfgcolor, NULL };
-static const char *termcmd[]  = { "st", 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_i,      incnmaster,     {.i = +1 } },
-       { MODKEY,                       XK_d,      incnmaster,     {.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|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|ShiftMask,             XK_space,  togglefloating, {0} },
-       { MODKEY,                       XK_0,      view,           {.ui = ~0 } 
},
-       { MODKEY|ShiftMask,             XK_0,      tag,            {.ui = ~0 } 
},
-       { MODKEY,                       XK_comma,  focusmon,       {.i = -1 } },
-       { MODKEY,                       XK_period, focusmon,       {.i = +1 } },
-       { MODKEY|ShiftMask,             XK_comma,  tagmon,         {.i = -1 } },
-       { MODKEY|ShiftMask,             XK_period, tagmon,         {.i = +1 } },
-       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 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 = &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 --git a/dwm.c b/dwm.c
index 0362114..7371cf4 100644
--- a/dwm.c
+++ b/dwm.c
@@ -16,7 +16,7 @@
  * on each monitor. 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.
+ * Keys and tagging rules are organized as arrays and defined in config.c.
  *
  * To understand everything else, start reading main().
  */
@@ -31,7 +31,6 @@
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <X11/cursorfont.h>
-#include <X11/keysym.h>
 #include <X11/Xatom.h>
 #include <X11/Xlib.h>
 #include <X11/Xproto.h>
@@ -43,206 +42,34 @@
 
 #include "drw.h"
 #include "util.h"
-
-/* macros */
-#define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
-#define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & 
(ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
-#define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - 
MAX((x),(m)->wx)) \
-                               * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - 
MAX((y),(m)->wy)))
-#define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
-#define LENGTH(X)               (sizeof X / sizeof X[0])
-#define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
-#define WIDTH(X)                ((X)->w + 2 * (X)->bw)
-#define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
-#define TAGMASK                 ((1 << LENGTH(tags)) - 1)
-#define TEXTW(X)                (drw_text(drw, 0, 0, 0, 0, (X), 0) + 
drw->fonts[0]->h)
-
-/* enums */
-enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
-enum { SchemeNorm, SchemeSel, SchemeLast }; /* color schemes */
-enum { NetSupported, NetWMName, NetWMState,
-       NetWMFullscreen, NetActiveWindow, NetWMWindowType,
-       NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
-enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms 
*/
-enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
-       ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
-
-typedef union {
-       int i;
-       unsigned int ui;
-       float f;
-       const void *v;
-} Arg;
-
-typedef struct {
-       unsigned int click;
-       unsigned int mask;
-       unsigned int button;
-       void (*func)(const Arg *arg);
-       const Arg arg;
-} Button;
-
-typedef struct Monitor Monitor;
-typedef struct Client Client;
-struct Client {
-       char name[256];
-       float mina, maxa;
-       int x, y, w, h;
-       int oldx, oldy, oldw, oldh;
-       int basew, baseh, incw, inch, maxw, maxh, minw, minh;
-       int bw, oldbw;
-       unsigned int tags;
-       int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
-       Client *next;
-       Client *snext;
-       Monitor *mon;
-       Window win;
-};
-
-typedef struct {
-       unsigned int mod;
-       KeySym keysym;
-       void (*func)(const Arg *);
-       const Arg arg;
-} Key;
-
-typedef struct {
-       const char *symbol;
-       void (*arrange)(Monitor *);
-} Layout;
-
-struct Monitor {
-       char ltsymbol[16];
-       float mfact;
-       int nmaster;
-       int num;
-       int by;               /* bar geometry */
-       int mx, my, mw, mh;   /* screen size */
-       int wx, wy, ww, wh;   /* window area  */
-       unsigned int seltags;
-       unsigned int sellt;
-       unsigned int tagset[2];
-       int showbar;
-       int topbar;
-       Client *clients;
-       Client *sel;
-       Client *stack;
-       Monitor *next;
-       Window barwin;
-       const Layout *lt[2];
-};
-
-typedef struct {
-       const char *class;
-       const char *instance;
-       const char *title;
-       unsigned int tags;
-       int isfloating;
-       int monitor;
-} Rule;
+#include "dwm.h"
 
 /* function declarations */
-static void applyrules(Client *c);
-static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int 
interact);
-static void arrange(Monitor *m);
-static void arrangemon(Monitor *m);
-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 cleanupmon(Monitor *mon);
-static void clearurgent(Client *c);
 static void clientmessage(XEvent *e);
-static void configure(Client *c);
 static void configurenotify(XEvent *e);
 static void configurerequest(XEvent *e);
-static Monitor *createmon(void);
 static void destroynotify(XEvent *e);
-static void detach(Client *c);
-static void detachstack(Client *c);
-static Monitor *dirtomon(int dir);
-static void drawbar(Monitor *m);
-static void drawbars(void);
 static void enternotify(XEvent *e);
 static void expose(XEvent *e);
-static void focus(Client *c);
 static void focusin(XEvent *e);
-static void focusmon(const Arg *arg);
-static void focusstack(const Arg *arg);
-static int getrootptr(int *x, int *y);
-static long getstate(Window w);
-static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
-static void grabbuttons(Client *c, int focused);
-static void grabkeys(void);
-static void incnmaster(const Arg *arg);
 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(Monitor *m);
 static void motionnotify(XEvent *e);
-static void movemouse(const Arg *arg);
-static Client *nexttiled(Client *c);
-static void pop(Client *);
 static void propertynotify(XEvent *e);
-static void quit(const Arg *arg);
-static Monitor *recttomon(int x, int y, int w, int h);
-static void resize(Client *c, int x, int y, int w, int h, int interact);
-static void resizeclient(Client *c, int x, int y, int w, int h);
-static void resizemouse(const Arg *arg);
-static void restack(Monitor *m);
 static void run(void);
 static void scan(void);
-static int sendevent(Client *c, Atom proto);
-static void sendmon(Client *c, Monitor *m);
-static void setclientstate(Client *c, long state);
-static void setfocus(Client *c);
-static void setfullscreen(Client *c, int fullscreen);
-static void setlayout(const Arg *arg);
-static void setmfact(const Arg *arg);
 static void setup(void);
-static void showhide(Client *c);
 static void sigchld(int unused);
-static void spawn(const Arg *arg);
-static void tag(const Arg *arg);
-static void tagmon(const Arg *arg);
-static void tile(Monitor *);
-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 unfocus(Client *c, int setfocus);
-static void unmanage(Client *c, int destroyed);
 static void unmapnotify(XEvent *e);
-static int updategeom(void);
-static void updatebarpos(Monitor *m);
-static void updatebars(void);
-static void updateclientlist(void);
-static void updatenumlockmask(void);
-static void updatesizehints(Client *c);
-static void updatestatus(void);
-static void updatewindowtype(Client *c);
-static void updatetitle(Client *c);
-static void updatewmhints(Client *c);
-static void view(const Arg *arg);
-static Client *wintoclient(Window w);
-static Monitor *wintomon(Window w);
-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 */
-static const char broken[] = "broken";
-static char stext[256];
-static int screen;
-static int sw, sh;           /* X display screen geometry width, height */
-static int bh, blw = 0;      /* bar geometry */
-static int (*xerrorxlib)(Display *, XErrorEvent *);
-static unsigned int numlockmask = 0;
-static void (*handler[LASTEvent]) (XEvent *) = {
+/* global variables */
+int bh;
+void (*handler[LASTEvent])(XEvent *) = {
        [ButtonPress] = buttonpress,
        [ClientMessage] = clientmessage,
        [ConfigureRequest] = configurerequest,
@@ -258,20 +85,23 @@ static void (*handler[LASTEvent]) (XEvent *) = {
        [PropertyNotify] = propertynotify,
        [UnmapNotify] = unmapnotify
 };
-static Atom wmatom[WMLast], netatom[NetLast];
-static int running = 1;
-static Cur *cursor[CurLast];
+Atom wmatom[WMLast], netatom[NetLast];
+int running = 1;
+Cur *cursor[CurLast];
+Display *dpy;
+Monitor *mons, *selmon;
+Window root;
+
+/* static variables */
+static const char broken[] = "broken";
+static char stext[256];
+static int screen;
+static int sw, sh;           /* X display screen geometry width, height */
+static int blw = 0;          /* bar geometry */
+static int (*xerrorxlib)(Display *, XErrorEvent *);
+static unsigned int numlockmask = 0;
 static ClrScheme scheme[SchemeLast];
-static Display *dpy;
 static Drw *drw;
-static Monitor *mons, *selmon;
-static Window root;
-
-/* configuration, allows nested code to access above variables */
-#include "config.h"
-
-/* compile-time check if all tags fit into an unsigned int bit array. */
-struct NumTags { char limitexceeded[LENGTH(tags) > 31 ? -1 : 1]; };
 
 /* function implementations */
 void
@@ -290,7 +120,7 @@ applyrules(Client *c)
        class    = ch.res_class ? ch.res_class : broken;
        instance = ch.res_name  ? ch.res_name  : broken;
 
-       for (i = 0; i < LENGTH(rules); i++) {
+       for (i = 0; i < nrules; i++) {
                r = &rules[i];
                if ((!r->title || strstr(c->name, r->title))
                && (!r->class || strstr(class, r->class))
@@ -432,8 +262,8 @@ buttonpress(XEvent *e)
                i = x = 0;
                do
                        x += TEXTW(tags[i]);
-               while (ev->x >= x && ++i < LENGTH(tags));
-               if (i < LENGTH(tags)) {
+               while (ev->x >= x && ++i < ntags);
+               if (i < ntags) {
                        click = ClkTagBar;
                        arg.ui = 1 << i;
                } else if (ev->x < x + blw)
@@ -446,7 +276,7 @@ buttonpress(XEvent *e)
                focus(c);
                click = ClkClientWin;
        }
-       for (i = 0; i < LENGTH(buttons); i++)
+       for (i = 0; i < nbuttons; 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);
@@ -466,12 +296,12 @@ checkotherwm(void)
 void
 cleanup(void)
 {
-       Arg a = {.ui = ~0};
+       /*Arg a = {.ui = ~0};*/
        Layout foo = { "", NULL };
        Monitor *m;
        size_t i;
 
-       view(&a);
+       /*view(&a);*/
        selmon->lt[selmon->sellt] = &foo;
        for (m = mons; m; m = m->next)
                while (m->stack)
@@ -648,7 +478,7 @@ createmon(void)
        m->showbar = showbar;
        m->topbar = topbar;
        m->lt[0] = &layouts[0];
-       m->lt[1] = &layouts[1 % LENGTH(layouts)];
+       m->lt[1] = &layouts[1 % nlayouts];
        strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
        return m;
 }
@@ -716,7 +546,7 @@ drawbar(Monitor *m)
                        urg |= c->tags;
        }
        x = 0;
-       for (i = 0; i < LENGTH(tags); i++) {
+       for (i = 0; i < ntags; i++) {
                w = TEXTW(tags[i]);
                drw_setscheme(drw, m->tagset[m->seltags] & 1 << i ? 
&scheme[SchemeSel] : &scheme[SchemeNorm]);
                drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i);
@@ -827,47 +657,6 @@ focusin(XEvent *e)
                setfocus(selmon->sel);
 }
 
-void
-focusmon(const Arg *arg)
-{
-       Monitor *m;
-
-       if (!mons->next)
-               return;
-       if ((m = dirtomon(arg->i)) == selmon)
-               return;
-       unfocus(selmon->sel, 0); /* s/1/0/ fixes input focus issues
-                                       in gedit and anjuta */
-       selmon = m;
-       focus(NULL);
-}
-
-void
-focusstack(const Arg *arg)
-{
-       Client *c = NULL, *i;
-
-       if (!selmon->sel)
-               return;
-       if (arg->i > 0) {
-               for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next);
-               if (!c)
-                       for (c = selmon->clients; c && !ISVISIBLE(c); c = 
c->next);
-       } else {
-               for (i = selmon->clients; i != selmon->sel; i = i->next)
-                       if (ISVISIBLE(i))
-                               c = i;
-               if (!c)
-                       for (; i; i = i->next)
-                               if (ISVISIBLE(i))
-                                       c = i;
-       }
-       if (c) {
-               focus(c);
-               restack(selmon);
-       }
-}
-
 Atom
 getatomprop(Client *c, Atom prop)
 {
@@ -947,7 +736,7 @@ grabbuttons(Client *c, int focused)
                unsigned int modifiers[] = { 0, LockMask, numlockmask, 
numlockmask|LockMask };
                XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
                if (focused) {
-                       for (i = 0; i < LENGTH(buttons); i++)
+                       for (i = 0; i < nbuttons; i++)
                                if (buttons[i].click == ClkClientWin)
                                        for (j = 0; j < LENGTH(modifiers); j++)
                                                XGrabButton(dpy, 
buttons[i].button,
@@ -970,7 +759,7 @@ grabkeys(void)
                KeyCode code;
 
                XUngrabKey(dpy, AnyKey, AnyModifier, root);
-               for (i = 0; i < LENGTH(keys); i++)
+               for (i = 0; i < nkeys; i++)
                        if ((code = XKeysymToKeycode(dpy, keys[i].keysym)))
                                for (j = 0; j < LENGTH(modifiers); j++)
                                        XGrabKey(dpy, code, keys[i].mod | 
modifiers[j], root,
@@ -978,13 +767,6 @@ grabkeys(void)
        }
 }
 
-void
-incnmaster(const Arg *arg)
-{
-       selmon->nmaster = MAX(selmon->nmaster + arg->i, 0);
-       arrange(selmon);
-}
-
 #ifdef XINERAMA
 static int
 isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info)
@@ -1006,7 +788,7 @@ keypress(XEvent *e)
 
        ev = &e->xkey;
        keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
-       for (i = 0; i < LENGTH(keys); i++)
+       for (i = 0; i < nkeys; i++)
                if (keysym == keys[i].keysym
                && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
                && keys[i].func)
@@ -1014,22 +796,6 @@ keypress(XEvent *e)
 }
 
 void
-killclient(const Arg *arg)
-{
-       if (!selmon->sel)
-               return;
-       if (!sendevent(selmon->sel, wmatom[WMDelete])) {
-               XGrabServer(dpy);
-               XSetErrorHandler(xerrordummy);
-               XSetCloseDownMode(dpy, DestroyAll);
-               XKillClient(dpy, selmon->sel->win);
-               XSync(dpy, False);
-               XSetErrorHandler(xerror);
-               XUngrabServer(dpy);
-       }
-}
-
-void
 manage(Window w, XWindowAttributes *wa)
 {
        Client *c, *t = NULL;
@@ -1115,21 +881,6 @@ maprequest(XEvent *e)
 }
 
 void
-monocle(Monitor *m)
-{
-       unsigned int n = 0;
-       Client *c;
-
-       for (c = m->clients; c; c = c->next)
-               if (ISVISIBLE(c))
-                       n++;
-       if (n > 0) /* override layout symbol */
-               snprintf(m->ltsymbol, sizeof m->ltsymbol, "[%d]", n);
-       for (c = nexttiled(m->clients); c; c = nexttiled(c->next))
-               resize(c, m->wx, m->wy, m->ww - 2 * c->bw, m->wh - 2 * c->bw, 
0);
-}
-
-void
 motionnotify(XEvent *e)
 {
        static Monitor *mon = NULL;
@@ -1146,69 +897,6 @@ motionnotify(XEvent *e)
        mon = m;
 }
 
-void
-movemouse(const Arg *arg)
-{
-       int x, y, ocx, ocy, nx, ny;
-       Client *c;
-       Monitor *m;
-       XEvent ev;
-       Time lasttime = 0;
-
-       if (!(c = selmon->sel))
-               return;
-       if (c->isfullscreen) /* no support moving fullscreen windows by mouse */
-               return;
-       restack(selmon);
-       ocx = c->x;
-       ocy = c->y;
-       if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, 
GrabModeAsync,
-       None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
-               return;
-       if (!getrootptr(&x, &y))
-               return;
-       do {
-               XMaskEvent(dpy, 
MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
-               switch(ev.type) {
-               case ConfigureRequest:
-               case Expose:
-               case MapRequest:
-                       handler[ev.type](&ev);
-                       break;
-               case MotionNotify:
-                       if ((ev.xmotion.time - lasttime) <= (1000 / 60))
-                               continue;
-                       lasttime = ev.xmotion.time;
-
-                       nx = ocx + (ev.xmotion.x - x);
-                       ny = ocy + (ev.xmotion.y - y);
-                       if (nx >= selmon->wx && nx <= selmon->wx + selmon->ww
-                       && ny >= selmon->wy && ny <= selmon->wy + selmon->wh) {
-                               if (abs(selmon->wx - nx) < snap)
-                                       nx = selmon->wx;
-                               else if (abs((selmon->wx + selmon->ww) - (nx + 
WIDTH(c))) < snap)
-                                       nx = selmon->wx + selmon->ww - WIDTH(c);
-                               if (abs(selmon->wy - ny) < snap)
-                                       ny = selmon->wy;
-                               else if (abs((selmon->wy + selmon->wh) - (ny + 
HEIGHT(c))) < snap)
-                                       ny = selmon->wy + selmon->wh - 
HEIGHT(c);
-                               if (!c->isfloating && 
selmon->lt[selmon->sellt]->arrange
-                               && (abs(nx - c->x) > snap || abs(ny - c->y) > 
snap))
-                                       togglefloating(NULL);
-                       }
-                       if (!selmon->lt[selmon->sellt]->arrange || 
c->isfloating)
-                               resize(c, nx, ny, c->w, c->h, 1);
-                       break;
-               }
-       } while (ev.type != ButtonRelease);
-       XUngrabPointer(dpy, CurrentTime);
-       if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
-               sendmon(c, m);
-               selmon = m;
-               focus(NULL);
-       }
-}
-
 Client *
 nexttiled(Client *c)
 {
@@ -1262,12 +950,6 @@ propertynotify(XEvent *e)
        }
 }
 
-void
-quit(const Arg *arg)
-{
-       running = 0;
-}
-
 Monitor *
 recttomon(int x, int y, int w, int h)
 {
@@ -1305,63 +987,6 @@ resizeclient(Client *c, int x, int y, int w, int h)
 }
 
 void
-resizemouse(const Arg *arg)
-{
-       int ocx, ocy, nw, nh;
-       Client *c;
-       Monitor *m;
-       XEvent ev;
-       Time lasttime = 0;
-
-       if (!(c = selmon->sel))
-               return;
-       if (c->isfullscreen) /* no support resizing fullscreen windows by mouse 
*/
-               return;
-       restack(selmon);
-       ocx = c->x;
-       ocy = c->y;
-       if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, 
GrabModeAsync,
-                       None, cursor[CurResize]->cursor, CurrentTime) != 
GrabSuccess)
-               return;
-       XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + 
c->bw - 1);
-       do {
-               XMaskEvent(dpy, 
MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev);
-               switch(ev.type) {
-               case ConfigureRequest:
-               case Expose:
-               case MapRequest:
-                       handler[ev.type](&ev);
-                       break;
-               case MotionNotify:
-                       if ((ev.xmotion.time - lasttime) <= (1000 / 60))
-                               continue;
-                       lasttime = ev.xmotion.time;
-
-                       nw = MAX(ev.xmotion.x - ocx - 2 * c->bw + 1, 1);
-                       nh = MAX(ev.xmotion.y - ocy - 2 * c->bw + 1, 1);
-                       if (c->mon->wx + nw >= selmon->wx && c->mon->wx + nw <= 
selmon->wx + selmon->ww
-                       && c->mon->wy + nh >= selmon->wy && c->mon->wy + nh <= 
selmon->wy + selmon->wh)
-                       {
-                               if (!c->isfloating && 
selmon->lt[selmon->sellt]->arrange
-                               && (abs(nw - c->w) > snap || abs(nh - c->h) > 
snap))
-                                       togglefloating(NULL);
-                       }
-                       if (!selmon->lt[selmon->sellt]->arrange || 
c->isfloating)
-                               resize(c, c->x, c->y, nw, nh, 1);
-                       break;
-               }
-       } while (ev.type != ButtonRelease);
-       XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + 
c->bw - 1);
-       XUngrabPointer(dpy, CurrentTime);
-       while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
-       if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
-               sendmon(c, m);
-               selmon = m;
-               focus(NULL);
-       }
-}
-
-void
 restack(Monitor *m)
 {
        Client *c;
@@ -1515,35 +1140,6 @@ setfullscreen(Client *c, int fullscreen)
 }
 
 void
-setlayout(const Arg *arg)
-{
-       if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt])
-               selmon->sellt ^= 1;
-       if (arg && arg->v)
-               selmon->lt[selmon->sellt] = (Layout *)arg->v;
-       strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof 
selmon->ltsymbol);
-       if (selmon->sel)
-               arrange(selmon);
-       else
-               drawbar(selmon);
-}
-
-/* arg > 1.0 will set mfact absolutly */
-void
-setmfact(const Arg *arg)
-{
-       float f;
-
-       if (!arg || !selmon->lt[selmon->sellt]->arrange)
-               return;
-       f = arg->f < 1.0 ? arg->f + selmon->mfact : arg->f - 1.0;
-       if (f < 0.1 || f > 0.9)
-               return;
-       selmon->mfact = f;
-       arrange(selmon);
-}
-
-void
 setup(void)
 {
        XSetWindowAttributes wa;
@@ -1557,7 +1153,7 @@ setup(void)
        sh = DisplayHeight(dpy, screen);
        root = RootWindow(dpy, screen);
        drw = drw_create(dpy, screen, root, sw, sh);
-       drw_load_fonts(drw, fonts, LENGTH(fonts));
+       drw_load_fonts(drw, fonts, nfonts);
        if (!drw->fontcount)
                die("no fonts could be loaded.\n");
        bh = drw->fonts[0]->h + 2;
@@ -1630,40 +1226,6 @@ sigchld(int unused)
 }
 
 void
-spawn(const Arg *arg)
-{
-       if (arg->v == dmenucmd)
-               dmenumon[0] = '0' + selmon->num;
-       if (fork() == 0) {
-               if (dpy)
-                       close(ConnectionNumber(dpy));
-               setsid();
-               execvp(((char **)arg->v)[0], (char **)arg->v);
-               fprintf(stderr, "dwm: execvp %s", ((char **)arg->v)[0]);
-               perror(" failed");
-               exit(EXIT_SUCCESS);
-       }
-}
-
-void
-tag(const Arg *arg)
-{
-       if (selmon->sel && arg->ui & TAGMASK) {
-               selmon->sel->tags = arg->ui & TAGMASK;
-               focus(NULL);
-               arrange(selmon);
-       }
-}
-
-void
-tagmon(const Arg *arg)
-{
-       if (!selmon->sel || !mons->next)
-               return;
-       sendmon(selmon->sel, dirtomon(arg->i));
-}
-
-void
 tile(Monitor *m)
 {
        unsigned int i, n, h, mw, my, ty;
@@ -2028,18 +1590,6 @@ updatewmhints(Client *c)
        }
 }
 
-void
-view(const Arg *arg)
-{
-       if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
-               return;
-       selmon->seltags ^= 1; /* toggle sel tagset */
-       if (arg->ui & TAGMASK)
-               selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
-       focus(NULL);
-       arrange(selmon);
-}
-
 Client *
 wintoclient(Window w)
 {
@@ -2106,20 +1656,6 @@ xerrorstart(Display *dpy, XErrorEvent *ee)
        return -1;
 }
 
-void
-zoom(const Arg *arg)
-{
-       Client *c = selmon->sel;
-
-       if (!selmon->lt[selmon->sellt]->arrange
-       || (selmon->sel && selmon->sel->isfloating))
-               return;
-       if (c == nexttiled(selmon->clients))
-               if (!c || !(c = nexttiled(c->next)))
-                       return;
-       pop(c);
-}
-
 int
 main(int argc, char *argv[])
 {
diff --git a/dwm.h b/dwm.h
new file mode 100644
index 0000000..df48e7d
--- /dev/null
+++ b/dwm.h
@@ -0,0 +1,190 @@
+/* See LICENSE file for copyright and license details. */
+
+/* macros */
+#define BUTTONMASK              (ButtonPressMask|ButtonReleaseMask)
+#define CLEANMASK(mask)         (mask & ~(numlockmask|LockMask) & 
(ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask))
+#define INTERSECT(x,y,w,h,m)    (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - 
MAX((x),(m)->wx)) \
+                               * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - 
MAX((y),(m)->wy)))
+#define ISVISIBLE(C)            ((C->tags & C->mon->tagset[C->mon->seltags]))
+#define LENGTH(X)               (sizeof X / sizeof X[0])
+#define MOUSEMASK               (BUTTONMASK|PointerMotionMask)
+#define WIDTH(X)                ((X)->w + 2 * (X)->bw)
+#define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
+#define TAGMASK                 ((1 << ntags) - 1)
+#define TEXTW(X)                (drw_text(drw, 0, 0, 0, 0, (X), 0) + 
drw->fonts[0]->h)
+
+/* enums */
+enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
+enum { SchemeNorm, SchemeSel, SchemeLast }; /* color schemes */
+enum { NetSupported, NetWMName, NetWMState,
+       NetWMFullscreen, NetActiveWindow, NetWMWindowType,
+       NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */
+enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms 
*/
+enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
+       ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
+
+typedef union {
+       int i;
+       unsigned int ui;
+       float f;
+       const void *v;
+} Arg;
+
+typedef struct {
+       unsigned int click;
+       unsigned int mask;
+       unsigned int button;
+       void (*func)(const Arg *arg);
+       const Arg arg;
+} Button;
+
+typedef struct Monitor Monitor;
+typedef struct Client Client;
+struct Client {
+       char name[256];
+       float mina, maxa;
+       int x, y, w, h;
+       int oldx, oldy, oldw, oldh;
+       int basew, baseh, incw, inch, maxw, maxh, minw, minh;
+       int bw, oldbw;
+       unsigned int tags;
+       Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+       Client *next;
+       Client *snext;
+       Monitor *mon;
+       Window win;
+};
+
+typedef struct {
+       unsigned int mod;
+       KeySym keysym;
+       void (*func)(const Arg *);
+       const Arg arg;
+} Key;
+
+typedef struct {
+       const char *symbol;
+       void (*arrange)(Monitor *);
+} Layout;
+
+struct Monitor {
+       char ltsymbol[16];
+       float mfact;
+       int nmaster;
+       int num;
+       int by;               /* bar geometry */
+       int mx, my, mw, mh;   /* screen size */
+       int wx, wy, ww, wh;   /* window area  */
+       unsigned int seltags;
+       unsigned int sellt;
+       unsigned int tagset[2];
+       Bool showbar;
+       Bool topbar;
+       Client *clients;
+       Client *sel;
+       Client *stack;
+       Monitor *next;
+       Window barwin;
+       const Layout *lt[2];
+};
+
+typedef struct {
+       const char *class;
+       const char *instance;
+       const char *title;
+       unsigned int tags;
+       Bool isfloating;
+       int monitor;
+} Rule;
+
+extern const char *fonts[];
+extern const int nfonts;
+extern const char normbordercolor[];
+extern const char normbgcolor[];
+extern const char normfgcolor[];
+extern const char selbordercolor[];
+extern const char selbgcolor[];
+extern const char selfgcolor[];
+extern const unsigned int borderpx;
+extern const unsigned int snap;
+extern const Bool showbar;
+extern const Bool topbar;
+
+extern const const char *tags[];
+extern const int ntags;
+
+extern const Rule rules[];
+extern const int nrules;
+
+extern const float mfact;
+extern const int nmaster;
+extern const Bool resizehints;
+
+extern const Layout layouts[];
+extern const int nlayouts;
+
+extern const Key keys[];
+extern const int nkeys;
+
+extern const Button buttons[];
+extern const int nbuttons;
+
+extern void (*handler[LASTEvent])(XEvent *);
+extern int bh;
+extern Atom wmatom[WMLast], netatom[NetLast];
+extern Bool running;
+extern Cur *cursor[CurLast];
+extern Display *dpy;
+extern Monitor *mons, *selmon;
+extern Window root;
+
+void applyrules(Client *c);
+Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact);
+void arrange(Monitor *m);
+void arrangemon(Monitor *m);
+void attach(Client *c);
+void attachstack(Client *c);
+void cleanupmon(Monitor *mon);
+void clearurgent(Client *c);
+void configure(Client *c);
+Monitor *createmon(void);
+void detach(Client *c);
+void detachstack(Client *c);
+Monitor *dirtomon(int dir);
+void drawbar(Monitor *m);
+void drawbars(void);
+void focus(Client *c);
+Bool getrootptr(int *x, int *y);
+long getstate(Window w);
+Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
+void grabbuttons(Client *c, Bool focused);
+void grabkeys(void);
+void manage(Window w, XWindowAttributes *wa);
+Client *nexttiled(Client *c);
+void pop(Client *);
+Monitor *recttomon(int x, int y, int w, int h);
+void resize(Client *c, int x, int y, int w, int h, Bool interact);
+void resizeclient(Client *c, int x, int y, int w, int h);
+void restack(Monitor *m);
+Bool sendevent(Client *c, Atom proto);
+void sendmon(Client *c, Monitor *m);
+void setclientstate(Client *c, long state);
+void setfocus(Client *c);
+void setfullscreen(Client *c, Bool fullscreen);
+void showhide(Client *c);
+void unfocus(Client *c, Bool setfocus);
+void unmanage(Client *c, Bool destroyed);
+void updatebarpos(Monitor *m);
+Bool updategeom(void);
+void updatebars(void);
+void updateclientlist(void);
+void updatenumlockmask(void);
+void updatesizehints(Client *c);
+void updatestatus(void);
+void updatewindowtype(Client *c);
+void updatetitle(Client *c);
+void updatewmhints(Client *c);
+Client *wintoclient(Window w);
+Monitor *wintomon(Window w);
+int xerror(Display *dpy, XErrorEvent *ee);
+int xerrordummy(Display *dpy, XErrorEvent *ee);

Reply via email to