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();
 }
 

Reply via email to