JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
Using a new tags definition (const char [][MAXTAGLEN] - thanks go to Szabolcs!
[dwm.git] / dwm.c
diff --git a/dwm.c b/dwm.c
index 257edcc..bd7ffe3 100644 (file)
--- a/dwm.c
+++ b/dwm.c
@@ -17,9 +17,7 @@
  * set the override_redirect flag.  Clients are organized in a global
  * doubly-linked client list, the focus history is remembered through a global
  * stack list. Each client contains an array of Bools of the same size as the
- * global tags array to indicate the tags of a client.  For each client dwm
- * creates a small title window, which is resized whenever the (_NET_)WM_NAME
- * properties are updated or the client is moved/resized.
+ * global tags array to indicate the tags of a client.  
  *
  * Keys and tagging rules are organized as arrays and defined in config.h.
  *
 /* macros */
 #define BUTTONMASK             (ButtonPressMask | ButtonReleaseMask)
 #define CLEANMASK(mask)                (mask & ~(numlockmask | LockMask))
+#define LENGTH(x)              (sizeof x / sizeof x[0])
+#define MAXTAGLEN              16
 #define MOUSEMASK              (BUTTONMASK | PointerMotionMask)
 
+
 /* enums */
 enum { BarTop, BarBot, BarOff };                       /* bar position */
 enum { CurNormal, CurResize, CurMove, CurLast };       /* cursor */
@@ -143,6 +144,7 @@ unsigned long getcolor(const char *colstr);
 long getstate(Window w);
 Bool gettextprop(Window w, Atom atom, char *text, unsigned int size);
 void grabbuttons(Client *c, Bool focused);
+void grabkeys(void);
 unsigned int idxoftag(const char *tag);
 void initfont(const char *fontstr);
 Bool isoccupied(unsigned int t);
@@ -231,6 +233,8 @@ Regs *regs = NULL;
 /* configuration, allows nested code to access above variables */
 #include "config.h"
 
+Bool prevtags[LENGTH(tags)] = {[0] = True};
+
 /* function implementations */
 void
 applyrules(Client *c) {
@@ -305,7 +309,7 @@ buttonpress(XEvent *e) {
        Client *c;
        XButtonPressedEvent *ev = &e->xbutton;
 
-       if(barwin == ev->window) {
+       if(ev->window == barwin) {
                x = 0;
                for(i = 0; i < LENGTH(tags); i++) {
                        x += textw(tags[i]);
@@ -333,7 +337,7 @@ buttonpress(XEvent *e) {
                if(CLEANMASK(ev->state) != MODKEY)
                        return;
                if(ev->button == Button1) {
-                       if((floating == layout->arrange) || c->isfloating)
+                       if((layout->arrange == floating) || c->isfloating)
                                restack();
                        else
                                togglefloating(NULL);
@@ -664,8 +668,8 @@ void
 expose(XEvent *e) {
        XExposeEvent *ev = &e->xexpose;
 
-       if(0 == ev->count) {
-               if(barwin == ev->window)
+       if(ev->count == 0) {
+               if(ev->window == barwin)
                        drawbar();
        }
 }
@@ -779,7 +783,7 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) {
        int n;
        XTextProperty name;
 
-       if(!text || 0 == size)
+       if(!text || size == 0)
                return False;
        text[0] = '\0';
        XGetTextProperty(dpy, w, &name, atom);
@@ -789,8 +793,7 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size) {
                strncpy(text, (char *)name.value, size - 1);
        else {
                if(XmbTextPropertyToTextList(dpy, &name, &list, &n) >= Success
-               && n > 0 && *list)
-               {
+               && n > 0 && *list) {
                        strncpy(text, *list, size - 1);
                        XFreeStringList(list);
                }
@@ -837,6 +840,25 @@ grabbuttons(Client *c, Bool focused) {
                                GrabModeAsync, GrabModeSync, None, None);
 }
 
+void
+grabkeys(void)  {
+       unsigned int i;
+       KeyCode code;
+
+       XUngrabKey(dpy, AnyKey, AnyModifier, root);
+       for(i = 0; i < LENGTH(keys); i++) {
+               code = XKeysymToKeycode(dpy, keys[i].keysym);
+               XGrabKey(dpy, code, keys[i].mod, root, True,
+                               GrabModeAsync, GrabModeAsync);
+               XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
+                               GrabModeAsync, GrabModeAsync);
+               XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
+                               GrabModeAsync, GrabModeAsync);
+               XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
+                               GrabModeAsync, GrabModeAsync);
+       }
+}
+
 unsigned int
 idxoftag(const char *tag) {
        unsigned int i;
@@ -924,27 +946,10 @@ isvisible(Client *c) {
 
 void
 keypress(XEvent *e) {
-       KEYS
        unsigned int i;
-       KeyCode code;
        KeySym keysym;
        XKeyEvent *ev;
 
-       if(!e) { /* grabkeys */
-               XUngrabKey(dpy, AnyKey, AnyModifier, root);
-               for(i = 0; i < LENGTH(keys); i++) {
-                       code = XKeysymToKeycode(dpy, keys[i].keysym);
-                       XGrabKey(dpy, code, keys[i].mod, root, True,
-                                       GrabModeAsync, GrabModeAsync);
-                       XGrabKey(dpy, code, keys[i].mod | LockMask, root, True,
-                                       GrabModeAsync, GrabModeAsync);
-                       XGrabKey(dpy, code, keys[i].mod | numlockmask, root, True,
-                                       GrabModeAsync, GrabModeAsync);
-                       XGrabKey(dpy, code, keys[i].mod | numlockmask | LockMask, root, True,
-                                       GrabModeAsync, GrabModeAsync);
-               }
-               return;
-       }
        ev = &e->xkey;
        keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
        for(i = 0; i < LENGTH(keys); i++)
@@ -1047,7 +1052,7 @@ mappingnotify(XEvent *e) {
 
        XRefreshKeyboardMapping(ev);
        if(ev->request == MappingKeyboard)
-               keypress(NULL);
+               grabkeys();
 }
 
 void
@@ -1125,7 +1130,7 @@ propertynotify(XEvent *e) {
                        default: break;
                        case XA_WM_TRANSIENT_FOR:
                                XGetTransientForHint(dpy, c->win, &trans);
-                               if(!c->isfloating && (c->isfloating = (NULL != getclient(trans))))
+                               if(!c->isfloating && (c->isfloating = (getclient(trans) != NULL)))
                                        arrange();
                                break;
                        case XA_WM_NORMAL_HINTS:
@@ -1145,6 +1150,7 @@ quit(const char *arg) {
        readin = running = False;
 }
 
+
 void
 resize(Client *c, int x, int y, int w, int h, Bool sizehints) {
        XWindowChanges wc;
@@ -1258,9 +1264,9 @@ restack(void) {
        drawbar();
        if(!sel)
                return;
-       if(sel->isfloating || (floating == layout->arrange))
+       if(sel->isfloating || (layout->arrange == floating))
                XRaiseWindow(dpy, sel->win);
-       if(floating != layout->arrange) {
+       if(layout->arrange != floating) {
                wc.stack_mode = Below;
                wc.sibling = barwin;
                if(!sel->isfloating) {
@@ -1281,14 +1287,18 @@ restack(void) {
 void
 run(void) {
        char *p;
-       int r, xfd;
        fd_set rd;
+       int r, xfd;
+       unsigned int len, offset;
        XEvent ev;
 
        /* main event loop, also reads status text from stdin */
        XSync(dpy, False);
        xfd = ConnectionNumber(dpy);
        readin = True;
+       offset = 0;
+       len = sizeof stext - 1;
+       stext[len] = '\0'; /* 0-terminator is never touched */
        while(running) {
                FD_ZERO(&rd);
                if(readin)
@@ -1300,10 +1310,9 @@ run(void) {
                        eprint("select failed\n");
                }
                if(FD_ISSET(STDIN_FILENO, &rd)) {
-                       switch(r = read(STDIN_FILENO, stext, sizeof stext - 1)) {
+                       switch((r = read(STDIN_FILENO, stext + offset, len - offset))) {
                        case -1:
-                               strncpy(stext, strerror(errno), sizeof stext - 1);
-                               stext[sizeof stext - 1] = '\0';
+                               strncpy(stext, strerror(errno), len);
                                readin = False;
                                break;
                        case 0:
@@ -1311,10 +1320,14 @@ run(void) {
                                readin = False;
                                break;
                        default:
-                               for(stext[r] = '\0', p = stext + strlen(stext) - 1; p >= stext && *p == '\n'; *p-- = '\0');
-                               for(; p >= stext && *p != '\n'; --p);
-                               if(p > stext)
-                                       strncpy(stext, p + 1, sizeof stext);
+                               stext[offset + r] = '\0';
+                               for(p = stext; *p && *p != '\n'; p++);
+                               if(*p == '\n') {
+                                       *p = '\0';
+                                       offset = 0;
+                               }
+                               else
+                                       offset = (offset + r < len - 1) ? offset + r : 0;
                        }
                        drawbar();
                }
@@ -1390,9 +1403,9 @@ setmwfact(const char *arg) {
        if(!domwfact)
                return;
        /* arg handling, manipulate mwfact */
-       if(NULL == arg)
+       if(arg == NULL)
                mwfact = MWFACT;
-       else if(1 == sscanf(arg, "%lf", &delta)) {
+       else if(sscanf(arg, "%lf", &delta) == 1) {
                if(arg[0] == '+' || arg[0] == '-')
                        mwfact += delta;
                else
@@ -1451,7 +1464,7 @@ setup(void) {
        XSelectInput(dpy, root, wa.event_mask);
 
        /* grab keys */
-       keypress(NULL);
+       grabkeys();
 
        /* init tags */
        compileregs();
@@ -1507,8 +1520,8 @@ spawn(const char *arg) {
                return;
        /* The double-fork construct avoids zombie processes and keeps the code
         * clean from stupid signal handlers. */
-       if(0 == fork()) {
-               if(0 == fork()) {
+       if(fork() == 0) {
+               if(fork() == 0) {
                        if(dpy)
                                close(ConnectionNumber(dpy));
                        setsid();
@@ -1569,7 +1582,7 @@ tile(void) {
        nw = 0; /* gcc stupidity requires this */
        for(i = 0, c = mc = nexttiled(clients); c; c = nexttiled(c->next), i++) {
                c->ismax = False;
-               if(0 == i) { /* master */
+               if(i == 0) { /* master */
                        nw = mw - 2 * c->border;
                        nh = wah - 2 * c->border;
                }
@@ -1620,7 +1633,7 @@ togglemax(const char *arg) {
        if(!sel || sel->isfixed)
                return;
        if((sel->ismax = !sel->ismax)) {
-               if((floating == layout->arrange) || sel->isfloating)
+               if((layout->arrange == floating) || sel->isfloating)
                        sel->wasfloating = True;
                else {
                        togglefloating(NULL);
@@ -1862,7 +1875,8 @@ zoom(const char *arg) {
 int
 main(int argc, char *argv[]) {
        if(argc == 2 && !strcmp("-v", argv[1]))
-               eprint("dwm-"VERSION", © 2006-2007 A. R. Garbe, S. van Dijk, J. Salmi, P. Hruby, S. Nagy\n");
+               eprint("dwm-"VERSION", © 2006-2007 Anselm R. Garbe, Sander van Dijk, "
+                      "Jukka Salmi, Premysl Hruby, Szabolcs Nagy\n");
        else if(argc != 1)
                eprint("usage: dwm [-v]\n");