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