add compute_new_value_from_arg() to do the +/- job in uicb fcts
[awesome.git] / tag.c
blobf4d9ca31655ae1b48509f3c2442805bd7c4b4639
1 /*
2 * tag.c - tag management
3 *
4 * Copyright © 2007 Julien Danjou <julien@danjou.info>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 #include <stdio.h>
23 #include <X11/Xutil.h>
25 #include "layout.h"
26 #include "tag.h"
28 extern Client *sel; /* global client list */
30 static Regs *regs = NULL;
32 /** This function returns the index of
33 * the tag given un argument in *tags
34 * \param tag_to_find tag name
35 * \return index of tag
37 static int
38 idxoftag(const char *tag_to_find, const char **tags, int ntags)
40 int i;
42 if(!tag_to_find)
43 return 0;
45 for(i = 0; i < ntags; i++)
46 if(!strcmp(tags[i], tag_to_find))
47 return i;
49 return 0;
52 void
53 applyrules(Client * c, awesome_config *awesomeconf)
55 int i, j, len = 0;
56 regmatch_t tmp;
57 Bool matched = False;
58 XClassHint ch = { 0, 0 };
59 char *prop;
61 len += a_strlen(ch.res_class) + a_strlen(ch.res_name) + a_strlen(c->name);
63 prop = p_new(char, len + 1);
65 /* rule matching */
66 XGetClassHint(c->display, c->win, &ch);
67 snprintf(prop, len + 1, "%s:%s:%s",
68 ch.res_class ? ch.res_class : "", ch.res_name ? ch.res_name : "", c->name);
69 for(i = 0; i < awesomeconf->nrules; i++)
70 if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0))
72 c->isfloating = awesomeconf->rules[i].isfloating;
73 for(j = 0; regs[i].tagregex && j < awesomeconf->ntags; j++)
74 if(!regexec(regs[i].tagregex, awesomeconf->tags[j], 1, &tmp, 0))
76 matched = True;
77 c->tags[j] = True;
80 p_delete(&prop);
81 if(ch.res_class)
82 XFree(ch.res_class);
83 if(ch.res_name)
84 XFree(ch.res_name);
85 if(!matched)
86 for(i = 0; i < awesomeconf->ntags; i++)
87 c->tags[i] = awesomeconf->selected_tags[i];
90 void
91 compileregs(Rule * rules, int nrules)
93 int i;
94 regex_t *reg;
96 if(regs)
97 return;
98 regs = p_new(Regs, nrules);
99 for(i = 0; i < nrules; i++)
101 if(rules[i].prop)
103 reg = p_new(regex_t, 1);
104 if(regcomp(reg, rules[i].prop, REG_EXTENDED))
105 p_delete(&reg);
106 else
107 regs[i].propregex = reg;
109 if(rules[i].tags)
111 reg = p_new(regex_t, 1);
112 if(regcomp(reg, rules[i].tags, REG_EXTENDED))
113 p_delete(&reg);
114 else
115 regs[i].tagregex = reg;
121 /** Returns True if a client is tagged
122 * with one of the tags
123 * \param c Client
124 * \param tags tag to check
125 * \param ntags number of tags in *tags
126 * \return True or False
128 Bool
129 isvisible(Client * c, Bool * tags, int ntags)
131 int i;
133 for(i = 0; i < ntags; i++)
134 if(c->tags[i] && tags[i])
135 return True;
136 return False;
140 /** Tag selected window with tag
141 * \param disp Display ref
142 * \param arg Tag name
143 * \ingroup ui_callback
145 void
146 uicb_tag(Display *disp,
147 DC *drawcontext,
148 awesome_config *awesomeconf,
149 const char *arg)
151 int i;
153 if(!sel)
154 return;
155 for(i = 0; i < awesomeconf->ntags; i++)
156 sel->tags[i] = arg == NULL;
157 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
158 if(i >= 0 && i < awesomeconf->ntags)
159 sel->tags[i] = True;
160 saveprops(sel, awesomeconf->ntags);
161 arrange(disp, drawcontext, awesomeconf);
164 /** Toggle floating state of a client
165 * \param disp Display ref
166 * \param arg unused
167 * \ingroup ui_callback
169 void
170 uicb_togglefloating(Display *disp,
171 DC *drawcontext,
172 awesome_config * awesomeconf,
173 const char *arg __attribute__ ((unused)))
175 if(!sel)
176 return;
177 sel->isfloating = !sel->isfloating;
178 if(sel->isfloating)
179 /*restore last known float dimensions*/
180 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
181 else
183 /*save last known float dimensions*/
184 sel->rx = sel->x;
185 sel->ry = sel->y;
186 sel->rw = sel->w;
187 sel->rh = sel->h;
189 saveprops(sel, awesomeconf->ntags);
190 arrange(disp, drawcontext, awesomeconf);
193 /** Toggle tag view
194 * \param disp Display ref
195 * \param arg Tag name
196 * \ingroup ui_callback
198 void
199 uicb_toggletag(Display *disp,
200 DC *drawcontext,
201 awesome_config *awesomeconf,
202 const char *arg)
204 unsigned int i;
205 int j;
207 if(!sel)
208 return;
209 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
210 sel->tags[i] = !sel->tags[i];
211 for(j = 0; j < awesomeconf->ntags && !sel->tags[j]; j++);
212 if(j == awesomeconf->ntags)
213 sel->tags[i] = True;
214 saveprops(sel, awesomeconf->ntags);
215 arrange(disp, drawcontext, awesomeconf);
218 /** Add a tag to viewed tags
219 * \param disp Display ref
220 * \param arg Tag name
221 * \ingroup ui_callback
223 void
224 uicb_toggleview(Display *disp,
225 DC *drawcontext,
226 awesome_config *awesomeconf,
227 const char *arg)
229 unsigned int i;
230 int j;
232 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
233 awesomeconf->selected_tags[i] = !awesomeconf->selected_tags[i];
234 for(j = 0; j < awesomeconf->ntags && !awesomeconf->selected_tags[j]; j++);
235 if(j == awesomeconf->ntags)
236 awesomeconf->selected_tags[i] = True; /* cannot toggle last view */
237 saveawesomeprops(disp, awesomeconf);
238 arrange(disp, drawcontext, awesomeconf);
241 /** View tag
242 * \param disp Display ref
243 * \param awesomeconf awesome config ref
244 * \param arg tag to view
245 * \ingroup ui_callback
247 void
248 uicb_view(Display *disp,
249 DC *drawcontext,
250 awesome_config *awesomeconf,
251 const char *arg)
253 int i;
255 for(i = 0; i < awesomeconf->ntags; i++)
257 awesomeconf->prev_selected_tags[i] = awesomeconf->selected_tags[i];
258 awesomeconf->selected_tags[i] = arg == NULL;
260 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
261 if(i >= 0 && i < awesomeconf->ntags)
263 awesomeconf->selected_tags[i] = True;
264 awesomeconf->current_layout = awesomeconf->tag_layouts[i];
266 saveawesomeprops(disp, awesomeconf);
267 arrange(disp, drawcontext, awesomeconf);
270 /** View previously selected tags
271 * \param disp Display ref
272 * \param awesomeconf awesome config ref
273 * \param arg unused
274 * \ingroup ui_callback
276 void
277 uicb_viewprevtags(Display * disp,
278 DC *drawcontext,
279 awesome_config *awesomeconf,
280 const char *arg __attribute__ ((unused)))
282 int i;
283 Bool t;
285 for(i = 0; i < awesomeconf->ntags; i++)
287 t = awesomeconf->selected_tags[i];
288 awesomeconf->selected_tags[i] = awesomeconf->prev_selected_tags[i];
289 awesomeconf->prev_selected_tags[i] = t;
291 arrange(disp, drawcontext, awesomeconf);
294 /** View next tag
295 * \param disp Display ref
296 * \param arg unused
297 * \ingroup ui_callback
299 void
300 uicb_tag_viewnext(Display *disp,
301 DC * drawcontext,
302 awesome_config *awesomeconf,
303 const char *arg __attribute__ ((unused)))
305 int i;
306 int firsttag = -1;
308 for(i = 0; i < awesomeconf->ntags; i++)
310 if(firsttag < 0 && awesomeconf->selected_tags[i])
311 firsttag = i;
312 awesomeconf->selected_tags[i] = False;
314 if(++firsttag >= awesomeconf->ntags)
315 firsttag = 0;
316 awesomeconf->selected_tags[firsttag] = True;
317 saveawesomeprops(disp, awesomeconf);
318 arrange(disp, drawcontext, awesomeconf);
321 /** View previous tag
322 * \param disp Display ref
323 * \param arg unused
324 * \ingroup ui_callback
326 void
327 uicb_tag_viewprev(Display *disp,
328 DC *drawcontext,
329 awesome_config *awesomeconf,
330 const char *arg __attribute__ ((unused)))
332 int i;
333 int firsttag = -1;
335 for(i = awesomeconf->ntags - 1; i >= 0; i--)
337 if(firsttag < 0 && awesomeconf->selected_tags[i])
338 firsttag = i;
339 awesomeconf->selected_tags[i] = False;
341 if(--firsttag < 0)
342 firsttag = awesomeconf->ntags - 1;
343 awesomeconf->selected_tags[firsttag] = True;
344 saveawesomeprops(disp, awesomeconf);
345 arrange(disp, drawcontext, awesomeconf);