JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
making Copyright notices more compact
[dwm.git] / tag.c
1 /* © 2004-2007 Anselm R. Garbe <garbeam at gmail dot com>
2  * See LICENSE file for license details. */
3 #include "dwm.h"
4 #include <regex.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <X11/Xutil.h>
8
9 /* static */
10
11 typedef struct {
12         const char *prop;
13         const char *tags;
14         Bool isfloating;
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->isfloating = rule[i].isfloating;
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(const char *arg) {
105         int i;
106
107         if(!sel)
108                 return;
109         for(i = 0; i < ntags; i++)
110                 sel->tags[i] = arg == NULL;
111         i = arg ? atoi(arg) : 0;
112         if(i >= 0 && i < ntags)
113                 sel->tags[i] = True;
114         lt->arrange();
115 }
116
117 void
118 toggletag(const char *arg) {
119         int i, j;
120
121         if(!sel)
122                 return;
123         i = arg ? atoi(arg) : 0;
124         sel->tags[i] = !sel->tags[i];
125         for(j = 0; j < ntags && !sel->tags[j]; j++);
126         if(j == ntags)
127                 sel->tags[i] = True;
128         lt->arrange();
129 }
130
131 void
132 toggleview(const char *arg) {
133         int i, j;
134
135         i = arg ? atoi(arg) : 0;
136         seltag[i] = !seltag[i];
137         for(j = 0; j < ntags && !seltag[j]; j++);
138         if(j == ntags)
139                 seltag[i] = True; /* cannot toggle last view */
140         lt->arrange();
141 }
142
143 void
144 view(const char *arg) {
145         int i;
146
147         for(i = 0; i < ntags; i++)
148                 seltag[i] = arg == NULL;
149         i = arg ? atoi(arg) : 0;
150         if(i >= 0 && i < ntags)
151                 seltag[i] = True;
152         lt->arrange();
153 }