JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
hotfix of settags
[dwm.git] / tag.c
1 /*
2  * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3  * See LICENSE file for license details.
4  */
5 #include "dwm.h"
6 #include <regex.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <sys/types.h>
10 #include <X11/Xutil.h>
11
12 /* static */
13
14 typedef struct {
15         const char *pattern;
16         Bool tags[TLast];
17         Bool isfloat;
18 } Rule;
19
20 TAGS
21 RULES
22
23 void (*arrange)(Arg *) = DEFMODE;
24
25 /* extern */
26
27 void
28 appendtag(Arg *arg)
29 {
30         if(!sel)
31                 return;
32
33         sel->tags[arg->i] = True;
34         arrange(NULL);
35 }
36
37 void
38 dofloat(Arg *arg)
39 {
40         Client *c;
41
42         for(c = clients; c; c = c->next) {
43                 c->ismax = False;
44                 if(c->tags[tsel]) {
45                         resize(c, True, TopLeft);
46                 }
47                 else
48                         ban(c);
49         }
50         if(sel && !sel->tags[tsel]) {
51                 if((sel = getnext(clients))) {
52                         higher(sel);
53                         focus(sel);
54                 }
55                 else
56                         XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
57         }
58         drawall();
59 }
60
61 void
62 dotile(Arg *arg)
63 {
64         int n, i, w, h;
65         Client *c;
66
67         w = sw - mw;
68         for(n = 0, c = clients; c; c = c->next)
69                 if(c->tags[tsel] && !c->isfloat)
70                         n++;
71
72         if(n > 1)
73                 h = (sh - bh) / (n - 1);
74         else
75                 h = sh - bh;
76
77         for(i = 0, c = clients; c; c = c->next) {
78                 c->ismax = False;
79                 if(c->tags[tsel]) {
80                         if(c->isfloat) {
81                                 higher(c);
82                                 resize(c, True, TopLeft);
83                                 continue;
84                         }
85                         if(n == 1) {
86                                 c->x = sx;
87                                 c->y = sy + bh;
88                                 c->w = sw - 2;
89                                 c->h = sh - 2 - bh;
90                         }
91                         else if(i == 0) {
92                                 c->x = sx;
93                                 c->y = sy + bh;
94                                 c->w = mw - 2;
95                                 c->h = sh - 2 - bh;
96                         }
97                         else if(h > bh) {
98                                 c->x = sx + mw;
99                                 c->y = sy + (i - 1) * h + bh;
100                                 c->w = w - 2;
101                                 c->h = h - 2;
102                         }
103                         else { /* fallback if h < bh */
104                                 c->x = sx + mw;
105                                 c->y = sy + bh;
106                                 c->w = w - 2;
107                                 c->h = sh - 2 - bh;
108                         }
109                         resize(c, False, TopLeft);
110                         i++;
111                 }
112                 else
113                         ban(c);
114         }
115         if(!sel || (sel && !sel->tags[tsel])) {
116                 if((sel = getnext(clients))) {
117                         higher(sel);
118                         focus(sel);
119                 }
120                 else
121                         XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
122         }
123         drawall();
124 }
125
126 Client *
127 getnext(Client *c)
128 {
129         for(; c && !c->tags[tsel]; c = c->next);
130         return c;
131 }
132
133 Client *
134 getprev(Client *c)
135 {
136         for(; c && !c->tags[tsel]; c = c->prev);
137         return c;
138 }
139
140 void
141 replacetag(Arg *arg)
142 {
143         int i;
144
145         if(!sel)
146                 return;
147
148         for(i = 0; i < TLast; i++)
149                 sel->tags[i] = False;
150         appendtag(arg);
151 }
152
153 void
154 settags(Client *c)
155 {
156         char classinst[256];
157         static unsigned int len = sizeof(rule) / sizeof(rule[0]);
158         unsigned int i, j;
159         regex_t regex;
160         regmatch_t tmp;
161         Bool matched = False;
162         XClassHint ch;
163
164         if(XGetClassHint(dpy, c->win, &ch)) {
165                 snprintf(classinst, sizeof(classinst), "%s:%s",
166                                 ch.res_class ? ch.res_class : "",
167                                 ch.res_name ? ch.res_name : "");
168                 for(i = 0; !matched && i < len; i++) {
169                         if(!regcomp(&regex, rule[i].pattern, 0)) {
170                                 if(!regexec(&regex, classinst, 1, &tmp, 0)) {
171                                         for(j = 0; j < TLast; j++) {
172                                                 if((c->tags[j] = rule[i].tags[j]))
173                                                         matched = True;
174                                         }
175                                         c->isfloat = rule[i].isfloat;
176                                 }
177                                 regfree(&regex);
178                         }
179                 }
180                 if(ch.res_class)
181                         XFree(ch.res_class);
182                 if(ch.res_name)
183                         XFree(ch.res_name);
184         }
185         if(!matched)
186                 c->tags[tsel] = True;
187 }
188
189 void
190 togglemode(Arg *arg)
191 {
192         arrange = arrange == dofloat ? dotile : dofloat;
193         arrange(NULL);
194 }
195
196 void
197 view(Arg *arg)
198 {
199         tsel = arg->i;
200         arrange(NULL);
201         drawall();
202 }
203
204 void
205 viewnext(Arg *arg)
206 {
207         arg->i = (tsel < TLast-1) ? tsel+1 : 0;
208         view(arg);
209 }
210
211 void
212 viewprev(Arg *arg)
213 {
214         arg->i = (tsel > 0) ? tsel-1 : TLast-1;
215         view(arg);
216 }