oops
[dwm.git] / dwm.c
diff --git a/dwm.c b/dwm.c
index 7861512..4edd7ce 100644 (file)
--- a/dwm.c
+++ b/dwm.c
@@ -29,6 +29,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/wait.h>
 #include <X11/cursorfont.h>
 #include <X11/keysym.h>
@@ -36,6 +37,7 @@
 #include <X11/Xlib.h>
 #include <X11/Xproto.h>
 #include <X11/Xutil.h>
+#include <X11/Xresource.h>
 #ifdef XINERAMA
 #include <X11/extensions/Xinerama.h>
 #endif /* XINERAMA */
@@ -56,7 +58,6 @@
 #define HEIGHT(X)               ((X)->h + 2 * (X)->bw)
 #define TAGMASK                 ((1 << LENGTH(tags)) - 1)
 #define TEXTW(X)                (drw_fontset_getwidth(drw, (X)) + lrpad)
-#define ColBorder               2
 
 /* enums */
 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
@@ -120,6 +121,7 @@ struct Monitor {
        int by;               /* bar geometry */
        int mx, my, mw, mh;   /* screen size */
        int wx, wy, ww, wh;   /* window area  */
+       int gappx;            /* gaps between windows */
        unsigned int seltags;
        unsigned int sellt;
        unsigned int tagset[2];
@@ -142,6 +144,19 @@ typedef struct {
        int monitor;
 } Rule;
 
+/* Xresources preferences */
+enum resource_type {
+       STRING = 0,
+       INTEGER = 1,
+       FLOAT = 2
+};
+
+typedef struct {
+       char *name;
+       enum resource_type type;
+       void *dst;
+} ResourcePref;
+
 /* function declarations */
 static void applyrules(Client *c);
 static int applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact);
@@ -170,6 +185,7 @@ static void focus(Client *c);
 static void focusin(XEvent *e);
 static void focusmon(const Arg *arg);
 static void focusstack(const Arg *arg);
+static Atom getatomprop(Client *c, Atom prop);
 static int getrootptr(int *x, int *y);
 static long getstate(Window w);
 static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
@@ -194,12 +210,14 @@ 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 runautostart(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 setgaps(const Arg *arg);
 static void setlayout(const Arg *arg);
 static void setmfact(const Arg *arg);
 static void setup(void);
@@ -217,15 +235,15 @@ 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 int updategeom(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 updatewindowtype(Client *c);
 static void updatewmhints(Client *c);
 static void view(const Arg *arg);
 static Client *wintoclient(Window w);
@@ -234,9 +252,15 @@ 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);
+static void load_xresources(void);
+static void resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst);
 
 /* variables */
+static const char autostartblocksh[] = "autostart_blocking.sh";
+static const char autostartsh[] = "autostart.sh";
 static const char broken[] = "broken";
+static const char dwmdir[] = "dwm";
+static const char localshare[] = ".local/share";
 static char stext[256];
 static int screen;
 static int sw, sh;           /* X display screen geometry width, height */
@@ -263,7 +287,7 @@ static void (*handler[LASTEvent]) (XEvent *) = {
 static Atom wmatom[WMLast], netatom[NetLast];
 static int running = 1;
 static Cur *cursor[CurLast];
-static Scm *scheme;
+static Clr **scheme;
 static Display *dpy;
 static Drw *drw;
 static Monitor *mons, *selmon;
@@ -522,7 +546,7 @@ clientmessage(XEvent *e)
                if (cme->data.l[1] == netatom[NetWMFullscreen]
                || cme->data.l[2] == netatom[NetWMFullscreen])
                        setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD    */
-                                     || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
+                               || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
        } else if (cme->message_type == netatom[NetActiveWindow]) {
                if (c != selmon->sel && !c->isurgent)
                        seturgent(c, 1);
@@ -639,6 +663,7 @@ createmon(void)
        m->nmaster = nmaster;
        m->showbar = showbar;
        m->topbar = topbar;
+       m->gappx = gappx;
        m->lt[0] = &layouts[0];
        m->lt[1] = &layouts[1 % LENGTH(layouts)];
        strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol);
@@ -696,7 +721,7 @@ dirtomon(int dir)
 void
 drawbar(Monitor *m)
 {
-       int x, w, sw = 0;
+       int x, w, tw = 0;
        int boxs = drw->fonts->h / 9;
        int boxw = drw->fonts->h / 6 + 2;
        unsigned int i, occ = 0, urg = 0;
@@ -705,8 +730,8 @@ drawbar(Monitor *m)
        /* draw status first so it can be overdrawn by tags later */
        if (m == selmon) { /* status is only drawn on selected monitor */
                drw_setscheme(drw, scheme[SchemeNorm]);
-               sw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
-               drw_text(drw, m->ww - sw, 0, sw, bh, 0, stext, 0);
+               tw = TEXTW(stext) - lrpad + 2; /* 2px right padding */
+               drw_text(drw, m->ww - tw, 0, tw, bh, 0, stext, 0);
        }
 
        for (c = m->clients; c; c = c->next) {
@@ -721,15 +746,15 @@ drawbar(Monitor *m)
                drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i);
                if (occ & 1 << i)
                        drw_rect(drw, x + boxs, boxs, boxw, boxw,
-                                m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
-                                urg & 1 << i);
+                               m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
+                               urg & 1 << i);
                x += w;
        }
        w = blw = TEXTW(m->ltsymbol);
        drw_setscheme(drw, scheme[SchemeNorm]);
        x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0);
 
-       if ((w = m->ww - sw - x) > bh) {
+       if ((w = m->ww - tw - x) > bh) {
                if (m->sel) {
                        drw_setscheme(drw, scheme[m == selmon ? SchemeSel : SchemeNorm]);
                        drw_text(drw, x, 0, w, bh, lrpad / 2, m->sel->name, 0);
@@ -865,7 +890,7 @@ getatomprop(Client *c, Atom prop)
        Atom da, atom = None;
 
        if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
-                             &da, &di, &dl, &dl, &p) == Success && p) {
+               &da, &di, &dl, &dl, &p) == Success && p) {
                atom = *(Atom *)p;
                XFree(p);
        }
@@ -892,7 +917,7 @@ getstate(Window w)
        Atom real;
 
        if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
-                             &real, &format, &n, &extra, (unsigned char **)&p) != Success)
+               &real, &format, &n, &extra, (unsigned char **)&p) != Success)
                return -1;
        if (n != 0)
                result = *p;
@@ -910,8 +935,7 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size)
        if (!text || size == 0)
                return 0;
        text[0] = '\0';
-       XGetTextProperty(dpy, w, &name, atom);
-       if (!name.nitems)
+       if (!XGetTextProperty(dpy, w, &name, atom) || !name.nitems)
                return 0;
        if (name.encoding == XA_STRING)
                strncpy(text, (char *)name.value, size - 1);
@@ -936,14 +960,14 @@ grabbuttons(Client *c, int focused)
                XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
                if (!focused)
                        XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
-                                   BUTTONMASK, GrabModeSync, GrabModeSync, None, None);
+                               BUTTONMASK, GrabModeSync, GrabModeSync, None, None);
                for (i = 0; i < LENGTH(buttons); i++)
                        if (buttons[i].click == ClkClientWin)
                                for (j = 0; j < LENGTH(modifiers); j++)
                                        XGrabButton(dpy, buttons[i].button,
-                                                   buttons[i].mask | modifiers[j],
-                                                   c->win, False, BUTTONMASK,
-                                                   GrabModeAsync, GrabModeSync, None, None);
+                                               buttons[i].mask | modifiers[j],
+                                               c->win, False, BUTTONMASK,
+                                               GrabModeAsync, GrabModeSync, None, None);
        }
 }
 
@@ -961,7 +985,7 @@ grabkeys(void)
                        if ((code = XKeysymToKeycode(dpy, keys[i].keysym)))
                                for (j = 0; j < LENGTH(modifiers); j++)
                                        XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
-                                                True, GrabModeAsync, GrabModeAsync);
+                                               True, GrabModeAsync, GrabModeAsync);
        }
 }
 
@@ -1048,7 +1072,7 @@ manage(Window w, XWindowAttributes *wa)
        c->x = MAX(c->x, c->mon->mx);
        /* only fix client y-offset, if the client center might cover the bar */
        c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx)
-                  && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
+               && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my);
        c->bw = borderpx;
 
        wc.border_width = c->bw;
@@ -1067,7 +1091,7 @@ manage(Window w, XWindowAttributes *wa)
        attach(c);
        attachstack(c);
        XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend,
-                       (unsigned char *) &(c->win), 1);
+               (unsigned char *) &(c->win), 1);
        XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */
        setclientstate(c, NormalState);
        if (c->mon == selmon)
@@ -1151,7 +1175,7 @@ movemouse(const Arg *arg)
        ocx = c->x;
        ocy = c->y;
        if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
-           None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
+               None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
                return;
        if (!getrootptr(&x, &y))
                return;
@@ -1226,7 +1250,7 @@ propertynotify(XEvent *e)
                default: break;
                case XA_WM_TRANSIENT_FOR:
                        if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) &&
-                          (c->isfloating = (wintoclient(trans)) != NULL))
+                               (c->isfloating = (wintoclient(trans)) != NULL))
                                arrange(c->mon);
                        break;
                case XA_WM_NORMAL_HINTS:
@@ -1306,7 +1330,7 @@ resizemouse(const Arg *arg)
        ocx = c->x;
        ocy = c->y;
        if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
-                       None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess)
+               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 {
@@ -1382,6 +1406,83 @@ run(void)
                        handler[ev.type](&ev); /* call handler */
 }
 
+void
+runautostart(void)
+{
+       char *pathpfx;
+       char *path;
+       char *xdgdatahome;
+       char *home;
+       struct stat sb;
+
+       if ((home = getenv("HOME")) == NULL)
+               /* this is almost impossible */
+               return;
+
+       /* if $XDG_DATA_HOME is set and not empty, use $XDG_DATA_HOME/dwm,
+        * otherwise use ~/.local/share/dwm as autostart script directory
+        */
+       xdgdatahome = getenv("XDG_DATA_HOME");
+       if (xdgdatahome != NULL && *xdgdatahome != '\0') {
+               /* space for path segments, separators and nul */
+               pathpfx = ecalloc(1, strlen(xdgdatahome) + strlen(dwmdir) + 2);
+
+               if (sprintf(pathpfx, "%s/%s", xdgdatahome, dwmdir) <= 0) {
+                       free(pathpfx);
+                       return;
+               }
+       } else {
+               /* space for path segments, separators and nul */
+               pathpfx = ecalloc(1, strlen(home) + strlen(localshare)
+                                    + strlen(dwmdir) + 3);
+
+               if (sprintf(pathpfx, "%s/%s/%s", home, localshare, dwmdir) < 0) {
+                       free(pathpfx);
+                       return;
+               }
+       }
+
+       /* check if the autostart script directory exists */
+       if (! (stat(pathpfx, &sb) == 0 && S_ISDIR(sb.st_mode))) {
+               /* the XDG conformant path does not exist or is no directory
+                * so we try ~/.dwm instead
+                */
+               char *pathpfx_new = realloc(pathpfx, strlen(home) + strlen(dwmdir) + 3);
+               if(pathpfx_new == NULL) {
+                       free(pathpfx);
+                       return;
+               }
+   pathpfx = pathpfx_new;
+
+               if (sprintf(pathpfx, "%s/.%s", home, dwmdir) <= 0) {
+                       free(pathpfx);
+                       return;
+               }
+       }
+
+       /* try the blocking script first */
+       path = ecalloc(1, strlen(pathpfx) + strlen(autostartblocksh) + 2);
+       if (sprintf(path, "%s/%s", pathpfx, autostartblocksh) <= 0) {
+               free(path);
+               free(pathpfx);
+       }
+
+       if (access(path, X_OK) == 0)
+               system(path);
+
+       /* now the non-blocking script */
+       if (sprintf(path, "%s/%s", pathpfx, autostartsh) <= 0) {
+               free(path);
+               free(pathpfx);
+       }
+
+       if (access(path, X_OK) == 0)
+               system(strcat(path, " &"));
+
+       free(pathpfx);
+       free(path);
+}
+
 void
 scan(void)
 {
@@ -1431,7 +1532,7 @@ setclientstate(Client *c, long state)
        long data[] = { state, None };
 
        XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
-                       PropModeReplace, (unsigned char *)data, 2);
+               PropModeReplace, (unsigned char *)data, 2);
 }
 
 int
@@ -1465,8 +1566,8 @@ setfocus(Client *c)
        if (!c->neverfocus) {
                XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
                XChangeProperty(dpy, root, netatom[NetActiveWindow],
-                               XA_WINDOW, 32, PropModeReplace,
-                               (unsigned char *) &(c->win), 1);
+                       XA_WINDOW, 32, PropModeReplace,
+                       (unsigned char *) &(c->win), 1);
        }
        sendevent(c, wmatom[WMTakeFocus]);
 }
@@ -1476,7 +1577,7 @@ setfullscreen(Client *c, int fullscreen)
 {
        if (fullscreen && !c->isfullscreen) {
                XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
-                               PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
+                       PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
                c->isfullscreen = 1;
                c->oldstate = c->isfloating;
                c->oldbw = c->bw;
@@ -1486,7 +1587,7 @@ setfullscreen(Client *c, int fullscreen)
                XRaiseWindow(dpy, c->win);
        } else if (!fullscreen && c->isfullscreen){
                XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32,
-                               PropModeReplace, (unsigned char*)0, 0);
+                       PropModeReplace, (unsigned char*)0, 0);
                c->isfullscreen = 0;
                c->isfloating = c->oldstate;
                c->bw = c->oldbw;
@@ -1499,6 +1600,16 @@ setfullscreen(Client *c, int fullscreen)
        }
 }
 
+void
+setgaps(const Arg *arg)
+{
+       if ((arg->i == 0) || (selmon->gappx + arg->i < 0))
+               selmon->gappx = 0;
+       else
+               selmon->gappx += arg->i;
+       arrange(selmon);
+}
+
 void
 setlayout(const Arg *arg)
 {
@@ -1522,7 +1633,7 @@ setmfact(const Arg *arg)
        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)
+       if (f < 0.05 || f > 0.95)
                return;
        selmon->mfact = f;
        arrange(selmon);
@@ -1569,7 +1680,7 @@ setup(void)
        cursor[CurResize] = drw_cur_create(drw, XC_sizing);
        cursor[CurMove] = drw_cur_create(drw, XC_fleur);
        /* init appearance */
-       scheme = ecalloc(LENGTH(colors), sizeof(Scm));
+       scheme = ecalloc(LENGTH(colors), sizeof(Clr *));
        for (i = 0; i < LENGTH(colors); i++)
                scheme[i] = drw_scm_create(drw, colors[i], 3);
        /* init bars */
@@ -1578,20 +1689,20 @@ setup(void)
        /* supporting window for NetWMCheck */
        wmcheckwin = XCreateSimpleWindow(dpy, root, 0, 0, 1, 1, 0, 0, 0);
        XChangeProperty(dpy, wmcheckwin, netatom[NetWMCheck], XA_WINDOW, 32,
-                       PropModeReplace, (unsigned char *) &wmcheckwin, 1);
+               PropModeReplace, (unsigned char *) &wmcheckwin, 1);
        XChangeProperty(dpy, wmcheckwin, netatom[NetWMName], utf8string, 8,
-                       PropModeReplace, (unsigned char *) "dwm", 4);
+               PropModeReplace, (unsigned char *) "dwm", 3);
        XChangeProperty(dpy, root, netatom[NetWMCheck], XA_WINDOW, 32,
-                       PropModeReplace, (unsigned char *) &wmcheckwin, 1);
+               PropModeReplace, (unsigned char *) &wmcheckwin, 1);
        /* EWMH support per view */
        XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
-                       PropModeReplace, (unsigned char *) netatom, NetLast);
+               PropModeReplace, (unsigned char *) netatom, NetLast);
        XDeleteProperty(dpy, root, netatom[NetClientList]);
        /* select events */
        wa.cursor = cursor[CurNormal]->cursor;
        wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask
-                       |ButtonPressMask|PointerMotionMask|EnterWindowMask
-                       |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
+               |ButtonPressMask|PointerMotionMask|EnterWindowMask
+               |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask;
        XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa);
        XSelectInput(dpy, root, wa.event_mask);
        grabkeys();
@@ -1685,16 +1796,18 @@ tile(Monitor *m)
        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++)
+               mw = m->ww - m->gappx;
+       for (i = 0, my = ty = m->gappx, 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);
+                       h = (m->wh - my) / (MIN(n, m->nmaster) - i) - m->gappx;
+                       resize(c, m->wx + m->gappx, m->wy + my, mw - (2*c->bw) - m->gappx, h - (2*c->bw), 0);
+                       if (my + HEIGHT(c) + m->gappx < m->wh)
+                               my += HEIGHT(c) + m->gappx;
                } 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);
+                       h = (m->wh - ty) / (n - i) - m->gappx;
+                       resize(c, m->wx + mw + m->gappx, m->wy + ty, m->ww - mw - (2*c->bw) - 2*m->gappx, h - (2*c->bw), 0);
+                       if (ty + HEIGHT(c) + m->gappx < m->wh)
+                               ty += HEIGHT(c) + m->gappx;
                }
 }
 
@@ -1717,7 +1830,7 @@ togglefloating(const Arg *arg)
        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);
+                       selmon->sel->w, selmon->sel->h, 0);
        arrange(selmon);
 }
 
@@ -1809,14 +1922,16 @@ updatebars(void)
                .background_pixmap = ParentRelative,
                .event_mask = ButtonPressMask|ExposureMask
        };
+       XClassHint ch = {"dwm", "dwm"};
        for (m = mons; m; m = m->next) {
                if (m->barwin)
                        continue;
                m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
-                                         CopyFromParent, DefaultVisual(dpy, screen),
-                                         CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
+                               CopyFromParent, DefaultVisual(dpy, screen),
+                               CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
                XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor);
                XMapRaised(dpy, m->barwin);
+               XSetClassHint(dpy, m->barwin, &ch);
        }
 }
 
@@ -1843,8 +1958,8 @@ updateclientlist()
        for (m = mons; m; m = m->next)
                for (c = m->clients; c; c = c->next)
                        XChangeProperty(dpy, root, netatom[NetClientList],
-                                       XA_WINDOW, 32, PropModeAppend,
-                                       (unsigned char *) &(c->win), 1);
+                               XA_WINDOW, 32, PropModeAppend,
+                               (unsigned char *) &(c->win), 1);
 }
 
 int
@@ -1936,7 +2051,7 @@ updatenumlockmask(void)
        for (i = 0; i < 8; i++)
                for (j = 0; j < modmap->max_keypermod; j++)
                        if (modmap->modifiermap[i * modmap->max_keypermod + j]
-                          == XKeysymToKeycode(dpy, XK_Num_Lock))
+                               == XKeysymToKeycode(dpy, XK_Num_Lock))
                                numlockmask = (1 << i);
        XFreeModifiermap(modmap);
 }
@@ -1981,8 +2096,15 @@ updatesizehints(Client *c)
                c->maxa = (float)size.max_aspect.x / size.max_aspect.y;
        } 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);
+       c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh);
+}
+
+void
+updatestatus(void)
+{
+       if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
+               strcpy(stext, "dwm-"VERSION);
+       drawbar(selmon);
 }
 
 void
@@ -1994,14 +2116,6 @@ updatetitle(Client *c)
                strcpy(c->name, broken);
 }
 
-void
-updatestatus(void)
-{
-       if (!gettextprop(root, XA_WM_NAME, stext, sizeof(stext)))
-               strcpy(stext, "dwm-"VERSION);
-       drawbar(selmon);
-}
-
 void
 updatewindowtype(Client *c)
 {
@@ -2092,7 +2206,7 @@ xerror(Display *dpy, XErrorEvent *ee)
        || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable))
                return 0;
        fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
-               ee->request_code, ee->error_code);
+               ee->request_code, ee->error_code);
        return xerrorxlib(dpy, ee); /* may call exit */
 }
 
@@ -2125,6 +2239,60 @@ zoom(const Arg *arg)
        pop(c);
 }
 
+void
+resource_load(XrmDatabase db, char *name, enum resource_type rtype, void *dst)
+{
+       char *sdst = NULL;
+       int *idst = NULL;
+       float *fdst = NULL;
+
+       sdst = dst;
+       idst = dst;
+       fdst = dst;
+
+       char fullname[256];
+       char *type;
+       XrmValue ret;
+
+       snprintf(fullname, sizeof(fullname), "%s.%s", "dwm", name);
+       fullname[sizeof(fullname) - 1] = '\0';
+
+       XrmGetResource(db, fullname, "*", &type, &ret);
+       if (!(ret.addr == NULL || strncmp("String", type, 64)))
+       {
+               switch (rtype) {
+               case STRING:
+                       strcpy(sdst, ret.addr);
+                       break;
+               case INTEGER:
+                       *idst = strtoul(ret.addr, NULL, 10);
+                       break;
+               case FLOAT:
+                       *fdst = strtof(ret.addr, NULL);
+                       break;
+               }
+       }
+}
+
+void
+load_xresources(void)
+{
+       Display *display;
+       char *resm;
+       XrmDatabase db;
+       ResourcePref *p;
+
+       display = XOpenDisplay(NULL);
+       resm = XResourceManagerString(display);
+       if (!resm)
+               return;
+
+       db = XrmGetStringDatabase(resm);
+       for (p = resources; p < resources + LENGTH(resources); p++)
+               resource_load(db, p->name, p->type, p->dst);
+       XCloseDisplay(display);
+}
+
 int
 main(int argc, char *argv[])
 {
@@ -2137,8 +2305,15 @@ main(int argc, char *argv[])
        if (!(dpy = XOpenDisplay(NULL)))
                die("dwm: cannot open display");
        checkotherwm();
+       XrmInitialize();
+       load_xresources();
        setup();
+#ifdef __OpenBSD__
+       if (pledge("stdio rpath proc exec", NULL) == -1)
+               die("pledge");
+#endif /* __OpenBSD__ */
        scan();
+       runautostart();
        run();
        cleanup();
        XCloseDisplay(dpy);