aewl

annotate tag.c @ 280:87cdbff4962e

removed finished message
author Anselm R.Garbe <arg@10ksloc.org>
date Mon, 14 Aug 2006 16:11:54 +0200
parents 9a0a351dd910
children 5f5c56e104de
rev   line source
garbeam@75 1 /*
garbeam@75 2 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
garbeam@75 3 * See LICENSE file for license details.
garbeam@75 4 */
garbeam@76 5 #include "dwm.h"
arg@114 6 #include <regex.h>
arg@114 7 #include <stdio.h>
arg@191 8 #include <stdlib.h>
garbeam@75 9 #include <string.h>
arg@114 10 #include <sys/types.h>
garbeam@75 11 #include <X11/Xutil.h>
garbeam@75 12
garbeam@76 13
arg@114 14 typedef struct {
arg@191 15 const char *clpattern;
arg@191 16 const char *tpattern;
arg@114 17 Bool isfloat;
arg@114 18 } Rule;
arg@114 19
arg@191 20 typedef struct {
arg@191 21 regex_t *clregex;
arg@191 22 regex_t *tregex;
arg@191 23 } RReg;
arg@191 24
arg@191 25 /* static */
arg@191 26
arg@146 27 TAGS
arg@146 28 RULES
garbeam@84 29
arg@191 30 static RReg *rreg = NULL;
arg@191 31 static unsigned int len = 0;
arg@191 32
arg@156 33 void (*arrange)(Arg *) = DEFMODE;
arg@125 34
arg@125 35 /* extern */
arg@125 36
garbeam@76 37 void
garbeam@76 38 appendtag(Arg *arg)
garbeam@75 39 {
arg@277 40 if(!sel)
garbeam@76 41 return;
garbeam@75 42
arg@277 43 sel->tags[arg->i] = True;
arg@277 44 settitle(sel);
garbeam@75 45 }
garbeam@75 46
garbeam@75 47 void
garbeam@75 48 dofloat(Arg *arg)
garbeam@75 49 {
garbeam@75 50 Client *c;
garbeam@75 51
garbeam@75 52 for(c = clients; c; c = c->next) {
arg@124 53 c->ismax = False;
arg@261 54 if(isvisible(c)) {
arg@99 55 resize(c, True, TopLeft);
garbeam@95 56 }
garbeam@75 57 else
garbeam@75 58 ban(c);
garbeam@75 59 }
arg@194 60 if((sel = getnext(clients))) {
arg@194 61 focus(sel);
arg@270 62 restack();
garbeam@75 63 }
arg@194 64 else
arg@194 65 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
garbeam@75 66 }
garbeam@75 67
garbeam@75 68 void
garbeam@75 69 dotile(Arg *arg)
garbeam@75 70 {
arg@270 71 int h, i, n, w;
garbeam@75 72 Client *c;
garbeam@75 73
garbeam@75 74 w = sw - mw;
garbeam@75 75 for(n = 0, c = clients; c; c = c->next)
arg@261 76 if(isvisible(c) && !c->isfloat)
garbeam@75 77 n++;
garbeam@75 78
garbeam@75 79 if(n > 1)
garbeam@75 80 h = (sh - bh) / (n - 1);
garbeam@75 81 else
garbeam@75 82 h = sh - bh;
garbeam@75 83
garbeam@75 84 for(i = 0, c = clients; c; c = c->next) {
arg@124 85 c->ismax = False;
arg@261 86 if(isvisible(c)) {
garbeam@80 87 if(c->isfloat) {
arg@99 88 resize(c, True, TopLeft);
garbeam@75 89 continue;
garbeam@75 90 }
garbeam@75 91 if(n == 1) {
arg@115 92 c->x = sx;
arg@115 93 c->y = sy + bh;
arg@164 94 c->w = sw - 2;
arg@164 95 c->h = sh - 2 - bh;
garbeam@75 96 }
garbeam@75 97 else if(i == 0) {
arg@115 98 c->x = sx;
arg@115 99 c->y = sy + bh;
arg@164 100 c->w = mw - 2;
arg@164 101 c->h = sh - 2 - bh;
garbeam@75 102 }
arg@104 103 else if(h > bh) {
arg@115 104 c->x = sx + mw;
arg@115 105 c->y = sy + (i - 1) * h + bh;
arg@164 106 c->w = w - 2;
arg@240 107 if(i + 1 == n)
arg@240 108 c->h = sh - c->y - 2;
arg@240 109 else
arg@240 110 c->h = h - 2;
garbeam@75 111 }
arg@104 112 else { /* fallback if h < bh */
arg@115 113 c->x = sx + mw;
arg@115 114 c->y = sy + bh;
arg@164 115 c->w = w - 2;
arg@164 116 c->h = sh - 2 - bh;
arg@104 117 }
arg@99 118 resize(c, False, TopLeft);
garbeam@75 119 i++;
garbeam@75 120 }
garbeam@75 121 else
garbeam@75 122 ban(c);
garbeam@75 123 }
arg@270 124 if((sel = getnext(clients)))
arg@194 125 focus(sel);
arg@194 126 else
arg@194 127 XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
arg@270 128 restack();
garbeam@75 129 }
garbeam@75 130
garbeam@76 131 Client *
arg@142 132 getnext(Client *c)
garbeam@75 133 {
arg@261 134 for(; c && !isvisible(c); c = c->next);
garbeam@76 135 return c;
garbeam@75 136 }
garbeam@75 137
arg@127 138 Client *
arg@127 139 getprev(Client *c)
arg@127 140 {
arg@261 141 for(; c && !isvisible(c); c = c->prev);
arg@127 142 return c;
arg@127 143 }
arg@127 144
garbeam@75 145 void
arg@191 146 initrregs()
arg@191 147 {
arg@191 148 unsigned int i;
arg@191 149 regex_t *reg;
arg@191 150
arg@191 151 if(rreg)
arg@191 152 return;
arg@191 153 len = sizeof(rule) / sizeof(rule[0]);
arg@191 154 rreg = emallocz(len * sizeof(RReg));
arg@191 155
arg@191 156 for(i = 0; i < len; i++) {
arg@191 157 if(rule[i].clpattern) {
arg@191 158 reg = emallocz(sizeof(regex_t));
arg@191 159 if(regcomp(reg, rule[i].clpattern, 0))
arg@191 160 free(reg);
arg@191 161 else
arg@191 162 rreg[i].clregex = reg;
arg@191 163 }
arg@191 164 if(rule[i].tpattern) {
arg@191 165 reg = emallocz(sizeof(regex_t));
arg@191 166 if(regcomp(reg, rule[i].tpattern, 0))
arg@191 167 free(reg);
arg@191 168 else
arg@191 169 rreg[i].tregex = reg;
arg@191 170 }
arg@191 171 }
arg@191 172 }
arg@191 173
arg@261 174 Bool
arg@261 175 isvisible(Client *c)
arg@261 176 {
arg@261 177 unsigned int i;
arg@261 178
arg@261 179 for(i = 0; i < ntags; i++)
arg@262 180 if(c->tags[i] && seltag[i])
arg@261 181 return True;
arg@261 182 return False;
arg@261 183 }
arg@261 184
arg@191 185 void
garbeam@75 186 replacetag(Arg *arg)
garbeam@75 187 {
garbeam@75 188 int i;
arg@123 189
garbeam@75 190 if(!sel)
garbeam@75 191 return;
garbeam@75 192
arg@178 193 for(i = 0; i < ntags; i++)
arg@173 194 sel->tags[i] = False;
garbeam@75 195 appendtag(arg);
garbeam@75 196 }
garbeam@75 197
garbeam@76 198 void
arg@270 199 restack()
arg@270 200 {
arg@270 201 static unsigned int nwins = 0;
arg@270 202 static Window *wins = NULL;
arg@270 203 unsigned int f, fi, m, mi, n;
arg@270 204 Client *c;
arg@270 205 XEvent ev;
arg@270 206
arg@270 207 for(f = 0, m = 0, c = clients; c; c = c->next)
arg@270 208 if(isvisible(c)) {
arg@270 209 if(c->isfloat || arrange == dofloat)
arg@270 210 f++;
arg@270 211 else
arg@270 212 m++;
arg@270 213 }
arg@272 214 if(!(n = 2 * (f + m))) {
arg@272 215 drawstatus();
arg@272 216 return;
arg@272 217 }
arg@270 218 if(nwins < n) {
arg@270 219 nwins = n;
arg@270 220 wins = erealloc(wins, nwins * sizeof(Window));
arg@270 221 }
arg@270 222
arg@270 223 fi = 0;
arg@270 224 mi = 2 * f;
arg@270 225 if(sel->isfloat || arrange == dofloat) {
arg@270 226 wins[fi++] = sel->title;
arg@270 227 wins[fi++] = sel->win;
arg@270 228 }
arg@270 229 else {
arg@270 230 wins[mi++] = sel->title;
arg@270 231 wins[mi++] = sel->win;
arg@270 232 }
arg@270 233 for(c = clients; c; c = c->next)
arg@270 234 if(isvisible(c) && c != sel) {
arg@270 235 if(c->isfloat || arrange == dofloat) {
arg@270 236 wins[fi++] = c->title;
arg@270 237 wins[fi++] = c->win;
arg@270 238 }
arg@270 239 else {
arg@270 240 wins[mi++] = c->title;
arg@270 241 wins[mi++] = c->win;
arg@270 242 }
arg@270 243 }
arg@270 244 XRestackWindows(dpy, wins, n);
arg@270 245 drawall();
arg@270 246 XSync(dpy, False);
arg@270 247 while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
arg@270 248 }
arg@270 249
arg@270 250 void
garbeam@76 251 settags(Client *c)
garbeam@76 252 {
arg@114 253 char classinst[256];
arg@191 254 unsigned int i, j;
arg@114 255 regmatch_t tmp;
garbeam@76 256 Bool matched = False;
arg@114 257 XClassHint ch;
garbeam@76 258
garbeam@76 259 if(XGetClassHint(dpy, c->win, &ch)) {
arg@114 260 snprintf(classinst, sizeof(classinst), "%s:%s",
arg@114 261 ch.res_class ? ch.res_class : "",
arg@114 262 ch.res_name ? ch.res_name : "");
arg@191 263 for(i = 0; !matched && i < len; i++)
arg@191 264 if(rreg[i].clregex && !regexec(rreg[i].clregex, classinst, 1, &tmp, 0)) {
arg@191 265 c->isfloat = rule[i].isfloat;
arg@191 266 for(j = 0; rreg[i].tregex && j < ntags; j++) {
arg@191 267 if(!regexec(rreg[i].tregex, tags[j], 1, &tmp, 0)) {
arg@191 268 matched = True;
arg@191 269 c->tags[j] = True;
arg@191 270 }
garbeam@76 271 }
arg@114 272 }
garbeam@76 273 if(ch.res_class)
garbeam@76 274 XFree(ch.res_class);
garbeam@76 275 if(ch.res_name)
garbeam@76 276 XFree(ch.res_name);
garbeam@76 277 }
garbeam@76 278 if(!matched)
arg@261 279 for(i = 0; i < ntags; i++)
arg@262 280 c->tags[i] = seltag[i];
garbeam@76 281 }
garbeam@76 282
garbeam@76 283 void
arg@124 284 togglemode(Arg *arg)
arg@124 285 {
arg@124 286 arrange = arrange == dofloat ? dotile : dofloat;
arg@124 287 arrange(NULL);
arg@124 288 }
arg@124 289
arg@124 290 void
garbeam@76 291 view(Arg *arg)
garbeam@76 292 {
arg@261 293 unsigned int i;
arg@261 294
arg@261 295 for(i = 0; i < ntags; i++)
arg@262 296 seltag[i] = False;
arg@262 297 seltag[arg->i] = True;
arg@262 298 arrange(NULL);
arg@262 299 }
arg@262 300
arg@262 301 void
arg@263 302 toggleview(Arg *arg)
arg@262 303 {
arg@262 304 unsigned int i;
arg@262 305
arg@262 306 seltag[arg->i] = !seltag[arg->i];
arg@262 307 for(i = 0; !seltag[i] && i < ntags; i++);
arg@262 308 if(i == ntags)
arg@262 309 seltag[arg->i] = True; /* cannot toggle last view */
garbeam@76 310 arrange(NULL);
garbeam@76 311 }