JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
added anydot to Copyright holders, because he contributed a lot recently
[dwm.git] / tag.c
1 /* © 2006-2007 Anselm R. Garbe <garbeam at gmail dot com>
2  * © 2006-2007 Sander van Dijk <a dot h dot vandijk at gmail dot com>
3  * © 2007 Premysl Hruby <dfenze at gmail dot com>
4  * See LICENSE file for license details. */
5 #include "dwm.h"
6 #include <regex.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <X11/Xutil.h>
10
11 /* static */
12
13 typedef struct {
14         const char *prop;
15         const char *tags;
16         Bool isfloating;
17 } Rule;
18
19 typedef struct {
20         regex_t *propregex;
21         regex_t *tagregex;
22 } Regs;
23
24 TAGS
25 RULES
26
27 static Regs *regs = NULL;
28 static unsigned int nrules = 0;
29
30 /* extern */
31
32 void
33 compileregs(void) {
34         unsigned int i;
35         regex_t *reg;
36
37         if(regs)
38                 return;
39         nrules = sizeof rule / sizeof rule[0];
40         regs = emallocz(nrules * sizeof(Regs));
41         for(i = 0; i < nrules; i++) {
42                 if(rule[i].prop) {
43                         reg = emallocz(sizeof(regex_t));
44                         if(regcomp(reg, rule[i].prop, REG_EXTENDED))
45                                 free(reg);
46                         else
47                                 regs[i].propregex = reg;
48                 }
49                 if(rule[i].tags) {
50                         reg = emallocz(sizeof(regex_t));
51                         if(regcomp(reg, rule[i].tags, REG_EXTENDED))
52                                 free(reg);
53                         else
54                                 regs[i].tagregex = reg;
55                 }
56         }
57 }
58
59 Bool
60 isvisible(Client *c) {
61         unsigned int i;
62
63         for(i = 0; i < ntags; i++)
64                 if(c->tags[i] && seltag[i])
65                         return True;
66         return False;
67 }
68
69 void
70 settags(Client *c, Client *trans) {
71         char prop[512];
72         unsigned int i, j;
73         regmatch_t tmp;
74         Bool matched = trans != NULL;
75         XClassHint ch = { 0 };
76
77         if(matched)
78                 for(i = 0; i < ntags; i++)
79                         c->tags[i] = trans->tags[i];
80         else {
81                 XGetClassHint(dpy, c->win, &ch);
82                 snprintf(prop, sizeof prop, "%s:%s:%s",
83                                 ch.res_class ? ch.res_class : "",
84                                 ch.res_name ? ch.res_name : "", c->name);
85                 for(i = 0; i < nrules; i++)
86                         if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0)) {
87                                 c->isfloating = rule[i].isfloating;
88                                 for(j = 0; regs[i].tagregex && j < ntags; j++) {
89                                         if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) {
90                                                 matched = True;
91                                                 c->tags[j] = True;
92                                         }
93                                 }
94                         }
95                 if(ch.res_class)
96                         XFree(ch.res_class);
97                 if(ch.res_name)
98                         XFree(ch.res_name);
99         }
100         if(!matched)
101                 for(i = 0; i < ntags; i++)
102                         c->tags[i] = seltag[i];
103 }
104
105 void
106 tag(const char *arg) {
107         int i;
108
109         if(!sel)
110                 return;
111         for(i = 0; i < ntags; i++)
112                 sel->tags[i] = arg == NULL;
113         i = arg ? atoi(arg) : 0;
114         if(i >= 0 && i < ntags)
115                 sel->tags[i] = True;
116         lt->arrange();
117 }
118
119 void
120 toggletag(const char *arg) {
121         int i, j;
122
123         if(!sel)
124                 return;
125         i = arg ? atoi(arg) : 0;
126         sel->tags[i] = !sel->tags[i];
127         for(j = 0; j < ntags && !sel->tags[j]; j++);
128         if(j == ntags)
129                 sel->tags[i] = True;
130         lt->arrange();
131 }
132
133 void
134 toggleview(const char *arg) {
135         int i, j;
136
137         i = arg ? atoi(arg) : 0;
138         seltag[i] = !seltag[i];
139         for(j = 0; j < ntags && !seltag[j]; j++);
140         if(j == ntags)
141                 seltag[i] = True; /* cannot toggle last view */
142         lt->arrange();
143 }
144
145 void
146 view(const char *arg) {
147         int i;
148
149         for(i = 0; i < ntags; i++)
150                 seltag[i] = arg == NULL;
151         i = arg ? atoi(arg) : 0;
152         if(i >= 0 && i < ntags)
153                 seltag[i] = True;
154         lt->arrange();
155 }