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