25 |
25 |
26 static Regs *regs = NULL; |
26 static Regs *regs = NULL; |
27 static unsigned int nrules = 0; |
27 static unsigned int nrules = 0; |
28 static char prop[512]; |
28 static char prop[512]; |
29 |
29 |
30 static void |
|
31 persistconfig(Client *c) { |
|
32 unsigned int i; |
|
33 |
|
34 for(i = 0; i < ntags && i < sizeof prop - 1; i++) |
|
35 prop[i] = c->tags[i] ? '1' : '0'; |
|
36 if(i < sizeof prop - 1) |
|
37 prop[i++] = c->isfloating ? '1' : '0'; |
|
38 prop[i] = '\0'; |
|
39 XChangeProperty(dpy, c->win, dwmconfig, XA_STRING, 8, |
|
40 PropModeReplace, (unsigned char *)prop, i); |
|
41 } |
|
42 |
|
43 static unsigned int |
30 static unsigned int |
44 idxoftag(const char *tag) { |
31 idxoftag(const char *tag) { |
45 unsigned int i; |
32 unsigned int i; |
46 |
33 |
47 for(i = 0; i < ntags; i++) |
34 for(i = 0; i < ntags; i++) |
49 return i; |
36 return i; |
50 return 0; |
37 return 0; |
51 } |
38 } |
52 |
39 |
53 /* extern */ |
40 /* extern */ |
|
41 |
|
42 void |
|
43 applyrules(Client *c) { |
|
44 unsigned int i, j; |
|
45 regmatch_t tmp; |
|
46 Bool matched = False; |
|
47 XClassHint ch = { 0 }; |
|
48 |
|
49 /* rule matching */ |
|
50 XGetClassHint(dpy, c->win, &ch); |
|
51 snprintf(prop, sizeof prop, "%s:%s:%s", |
|
52 ch.res_class ? ch.res_class : "", |
|
53 ch.res_name ? ch.res_name : "", c->name); |
|
54 for(i = 0; i < nrules; i++) |
|
55 if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0)) { |
|
56 c->isfloating = rules[i].isfloating; |
|
57 for(j = 0; regs[i].tagregex && j < ntags; j++) { |
|
58 if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) { |
|
59 matched = True; |
|
60 c->tags[j] = True; |
|
61 } |
|
62 } |
|
63 } |
|
64 if(ch.res_class) |
|
65 XFree(ch.res_class); |
|
66 if(ch.res_name) |
|
67 XFree(ch.res_name); |
|
68 if(!matched) |
|
69 for(i = 0; i < ntags; i++) |
|
70 c->tags[i] = seltags[i]; |
|
71 } |
54 |
72 |
55 void |
73 void |
56 compileregs(void) { |
74 compileregs(void) { |
57 unsigned int i; |
75 unsigned int i; |
58 regex_t *reg; |
76 regex_t *reg; |
88 return True; |
106 return True; |
89 return False; |
107 return False; |
90 } |
108 } |
91 |
109 |
92 void |
110 void |
93 settags(Client *c, Client *trans) { |
|
94 unsigned int i, j; |
|
95 regmatch_t tmp; |
|
96 Bool matched = trans != NULL; |
|
97 XClassHint ch = { 0 }; |
|
98 XTextProperty name; |
|
99 |
|
100 if(matched) { |
|
101 for(i = 0; i < ntags; i++) |
|
102 c->tags[i] = trans->tags[i]; |
|
103 } |
|
104 else { |
|
105 /* check if window has set a property */ |
|
106 name.nitems = 0; |
|
107 XGetTextProperty(dpy, c->win, &name, dwmconfig); |
|
108 if(name.nitems && name.encoding == XA_STRING) { |
|
109 strncpy(prop, (char *)name.value, sizeof prop - 1); |
|
110 prop[sizeof prop - 1] = '\0'; |
|
111 XFree(name.value); |
|
112 for(i = 0; i < ntags && i < sizeof prop - 1 && prop[i] != '\0'; i++) |
|
113 if((c->tags[i] = prop[i] == '1')) |
|
114 matched = True; |
|
115 if(i < sizeof prop - 1 && prop[i] != '\0') |
|
116 c->isfloating = prop[i] == '1'; |
|
117 } |
|
118 } |
|
119 if(!matched) { |
|
120 /* rule matching */ |
|
121 XGetClassHint(dpy, c->win, &ch); |
|
122 snprintf(prop, sizeof prop, "%s:%s:%s", |
|
123 ch.res_class ? ch.res_class : "", |
|
124 ch.res_name ? ch.res_name : "", c->name); |
|
125 for(i = 0; i < nrules; i++) |
|
126 if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0)) { |
|
127 c->isfloating = rules[i].isfloating; |
|
128 for(j = 0; regs[i].tagregex && j < ntags; j++) { |
|
129 if(!regexec(regs[i].tagregex, tags[j], 1, &tmp, 0)) { |
|
130 matched = True; |
|
131 c->tags[j] = True; |
|
132 } |
|
133 } |
|
134 } |
|
135 if(ch.res_class) |
|
136 XFree(ch.res_class); |
|
137 if(ch.res_name) |
|
138 XFree(ch.res_name); |
|
139 } |
|
140 if(!matched) |
|
141 for(i = 0; i < ntags; i++) |
|
142 c->tags[i] = seltags[i]; |
|
143 persistconfig(c); |
|
144 } |
|
145 |
|
146 void |
|
147 tag(const char *arg) { |
111 tag(const char *arg) { |
148 unsigned int i; |
112 unsigned int i; |
149 |
113 |
150 if(!sel) |
114 if(!sel) |
151 return; |
115 return; |
152 for(i = 0; i < ntags; i++) |
116 for(i = 0; i < ntags; i++) |
153 sel->tags[i] = arg == NULL; |
117 sel->tags[i] = arg == NULL; |
154 i = idxoftag(arg); |
118 i = idxoftag(arg); |
155 if(i >= 0 && i < ntags) |
119 if(i >= 0 && i < ntags) |
156 sel->tags[i] = True; |
120 sel->tags[i] = True; |
157 persistconfig(sel); |
121 saveconfig(sel); |
158 arrange(); |
122 arrange(); |
159 } |
123 } |
160 |
124 |
161 void |
125 void |
162 togglefloating(const char *arg) { |
126 togglefloating(const char *arg) { |
163 if(!sel || isfloating()) |
127 if(!sel || isfloating()) |
164 return; |
128 return; |
165 sel->isfloating = !sel->isfloating; |
129 sel->isfloating = !sel->isfloating; |
166 if(sel->isfloating) { |
130 if(sel->isfloating) { |
167 resize(sel, sel->x, sel->y, sel->w, sel->h, True); |
131 resize(sel, sel->x, sel->y, sel->w, sel->h, True); |
168 persistconfig(sel); |
132 saveconfig(sel); |
169 } |
133 } |
170 arrange(); |
134 arrange(); |
171 } |
135 } |
172 |
136 |
173 void |
137 void |