Hi,
This is realization of Gottox's proposal discuted on IRC today.
It handles tags not as Bool [], but as bit-array saved in int.
There's only one problem, as I don't find easy solution (in compile time)
for check if there's no more tags than sizeof(int)*8.
Maybe it can be "asserted" with someting like (possibly global, compiler
take it away as it's not used anywhere):
static char too_many_tags_test[sizeof(int)*8 - LENGTH(tags)];
Has anyone better solution?
-Ph
--
Premysl "Anydot" Hruby, http://www.redrum.cz/
diff -r cd9fd0986555 dwm.c
--- a/dwm.c Mon May 19 20:29:57 2008 +0100
+++ b/dwm.c Tue May 20 18:05:46 2008 +0200
@@ -51,6 +51,10 @@
#define LENGTH(x) (sizeof x / sizeof x[0])
#define MAXTAGLEN 16
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
+#define TMASK(p) (1<<(p))
+#define ISSET(t,p) ((t)&TMASK(p))
+#define SET(t,p,v) {if(v) (t)|=TMASK(p); else (t)&= ~TMASK(p);}
+#define TOGGLE(t,p) ((t) ^= TMASK(p))
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
@@ -68,7 +72,7 @@
long flags;
unsigned int bw, oldbw;
Bool isbanned, isfixed, isfloating, isurgent;
- Bool *tags;
+ int tags;
Client *next;
Client *prev;
Client *snext;
@@ -218,7 +222,7 @@
Atom wmatom[WMLast], netatom[NetLast];
Bool otherwm, readin;
Bool running = True;
-Bool *tagset[2];
+int tagset[2] = {1, 1}; /* after start, first tag is selected */
Client *clients = NULL;
Client *sel = NULL;
Client *stack = NULL;
@@ -231,7 +235,6 @@
/* configuration, allows nested code to access above variables */
#include "config.h"
-#define TAGSZ (LENGTH(tags) * sizeof(Bool))
/* function implementations */
@@ -251,7 +254,7 @@
&& (!r->instance || (ch.res_name && strstr(ch.res_name, r->instance)))) {
c->isfloating = r->isfloating;
if(r->tag) {
- c->tags[idxoftag(r->tag)] = True;
+ SET(c->tags, idxoftag(r->tag), 1);
matched = True;
}
}
@@ -261,7 +264,7 @@
if(ch.res_name)
XFree(ch.res_name);
if(!matched)
- memcpy(c->tags, tagset[seltags], TAGSZ);
+ c->tags = tagset[seltags];
}
void
@@ -501,13 +504,13 @@
for(c = stack; c && !isvisible(c); c = c->snext);
for(i = 0; i < LENGTH(tags); i++) {
dc.w = textw(tags[i]);
- if(tagset[seltags][i]) {
+ if(ISSET(tagset[seltags], i)) {
drawtext(tags[i], dc.sel, isurgent(i));
- drawsquare(c && c->tags[i], isoccupied(i), isurgent(i), dc.sel);
+ drawsquare(c && ISSET(c->tags, i), isoccupied(i), isurgent(i), dc.sel);
}
else {
drawtext(tags[i], dc.norm, isurgent(i));
- drawsquare(c && c->tags[i], isoccupied(i), isurgent(i), dc.norm);
+ drawsquare(c && ISSET(c->tags, i), isoccupied(i), isurgent(i), dc.norm);
}
dc.x += dc.w;
}
@@ -861,7 +864,7 @@
Client *c;
for(c = clients; c; c = c->next)
- if(c->tags[t])
+ if(ISSET(c->tags, t))
return True;
return False;
}
@@ -886,19 +889,14 @@
Client *c;
for(c = clients; c; c = c->next)
- if(c->isurgent && c->tags[t])
+ if(c->isurgent && ISSET(c->tags, t))
return True;
return False;
}
Bool
isvisible(Client *c) {
- unsigned int i;
-
- for(i = 0; i < LENGTH(tags); i++)
- if(c->tags[i] && tagset[seltags][i])
- return True;
- return False;
+ return c->tags & tagset[seltags];
}
void
@@ -945,7 +943,6 @@
XWindowChanges wc;
c = emallocz(sizeof(Client));
- c->tags = emallocz(TAGSZ);
c->win = w;
/* geometry */
@@ -980,7 +977,7 @@
if((rettrans = XGetTransientForHint(dpy, w, &trans) == Success))
for(t = clients; t && t->win != trans; t = t->next);
if(t)
- memcpy(c->tags, t->tags, TAGSZ);
+ c->tags = t->tags;
else
applyrules(c);
if(!c->isfloating)
@@ -1396,11 +1393,6 @@
if(!dc.font.set)
XSetFont(dpy, dc.gc, dc.font.xfont->fid);
- /* init tags */
- tagset[0] = emallocz(TAGSZ);
- tagset[1] = emallocz(TAGSZ);
- tagset[0][0] = tagset[1][0] = True;
-
/* init bar */
for(blw = i = 0; LENGTH(layouts) > 1 && i < LENGTH(layouts); i++) {
w = textw(layouts[i].symbol);
@@ -1464,9 +1456,11 @@
if(!sel)
return;
- for(i = 0; i < LENGTH(tags); i++)
- sel->tags[i] = (arg == NULL);
- sel->tags[idxoftag(arg)] = True;
+ if (arg)
+ sel->tags = TMASK(idxoftag(arg));
+ else
+ sel->tags = TMASK(LENGTH(tags) + 1) - 1;
+
arrange();
}
@@ -1580,22 +1574,20 @@
if(!sel)
return;
i = idxoftag(arg);
- sel->tags[i] = !sel->tags[i];
- for(j = 0; j < LENGTH(tags) && !sel->tags[j]; j++);
- if(j == LENGTH(tags))
- sel->tags[i] = True; /* at least one tag must be enabled */
+ TOGGLE(sel->tags, i);
+ if (!sel->tags) /* at least one tag must be selected */
+ SET(sel->tags, i, 1);
arrange();
}
void
toggleview(const char *arg) {
unsigned int i, j;
-
+
i = idxoftag(arg);
- tagset[seltags][i] = !tagset[seltags][i];
- for(j = 0; j < LENGTH(tags) && !tagset[seltags][j]; j++);
- if(j == LENGTH(tags))
- tagset[seltags][i] = True; /* at least one tag must be viewed */
+ TOGGLE(tagset[seltags], i);
+ if (!tagset[seltags])
+ SET(tagset[seltags], i, 1); /* at least one tag must be viewed */
arrange();
}
@@ -1622,7 +1614,6 @@
focus(NULL);
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
setclientstate(c, WithdrawnState);
- free(c->tags);
free(c);
XSync(dpy, False);
XSetErrorHandler(xerror);
@@ -1771,8 +1762,10 @@
void
view(const char *arg) {
seltags ^= 1; /* toggle sel tagset */
- memset(tagset[seltags], (NULL == arg), TAGSZ);
- tagset[seltags][idxoftag(arg)] = True;
+ if (arg)
+ tagset[seltags] = TMASK(idxoftag(arg));
+ else
+ tagset[seltags] = TMASK(LENGTH(tags) + 1) - 1;
arrange();
}