fix p_realloc macro
[awesome.git] / tag.c
blobd3e5a13b26405ba208ab63b2aa1d024ffc2844f1
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"
27 #include "util.h"
29 extern Client *sel; /* global client list */
31 static Regs *regs = NULL;
33 /** This function returns the index of
34 * the tag given un argument in *tags
35 * \param tag_to_find tag name
36 * \return index of tag
38 static int
39 idxoftag(const char *tag_to_find, char **tags, int ntags)
41 int i;
43 if(!tag_to_find)
44 return 0;
46 for(i = 0; i < ntags; i++)
47 if(!strcmp(tags[i], tag_to_find))
48 return i;
50 return 0;
53 void
54 applyrules(Client * c, awesome_config *awesomeconf)
56 int i, j, len = 0;
57 regmatch_t tmp;
58 Bool matched = False;
59 XClassHint ch = { 0, 0 };
60 char *prop;
62 len += a_strlen(ch.res_class) + a_strlen(ch.res_name) + a_strlen(c->name);
64 prop = p_new(char, len + 1);
66 /* rule matching */
67 XGetClassHint(c->display, c->win, &ch);
68 snprintf(prop, len + 1, "%s:%s:%s",
69 ch.res_class ? ch.res_class : "", ch.res_name ? ch.res_name : "", c->name);
70 for(i = 0; i < awesomeconf->nrules; i++)
71 if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0))
73 c->isfloating = awesomeconf->rules[i].isfloating;
74 for(j = 0; regs[i].tagregex && j < awesomeconf->ntags; j++)
75 if(!regexec(regs[i].tagregex, awesomeconf->tags[j], 1, &tmp, 0))
77 matched = True;
78 c->tags[j] = True;
81 p_delete(&prop);
82 if(ch.res_class)
83 XFree(ch.res_class);
84 if(ch.res_name)
85 XFree(ch.res_name);
86 if(!matched)
87 for(i = 0; i < awesomeconf->ntags; i++)
88 c->tags[i] = awesomeconf->selected_tags[i];
91 void
92 compileregs(Rule * rules, int nrules)
94 int i;
95 regex_t *reg;
97 if(regs)
98 return;
99 regs = p_new(Regs, nrules);
100 for(i = 0; i < nrules; i++)
102 if(rules[i].prop)
104 reg = p_new(regex_t, 1);
105 if(regcomp(reg, rules[i].prop, REG_EXTENDED))
106 p_delete(&reg);
107 else
108 regs[i].propregex = reg;
110 if(rules[i].tags)
112 reg = p_new(regex_t, 1);
113 if(regcomp(reg, rules[i].tags, REG_EXTENDED))
114 p_delete(&reg);
115 else
116 regs[i].tagregex = reg;
122 /** Returns True if a client is tagged
123 * with one of the tags
124 * \param c Client
125 * \param tags tag to check
126 * \param ntags number of tags in *tags
127 * \return True or False
129 Bool
130 isvisible(Client * c, int screen, Bool * tags, int ntags)
132 int i;
134 for(i = 0; i < ntags; i++)
135 if(c->tags[i] && tags[i] && c->screen == screen)
136 return True;
137 return False;
141 /** Tag selected window with tag
142 * \param disp Display ref
143 * \param arg Tag name
144 * \ingroup ui_callback
146 void
147 uicb_tag(Display *disp,
148 DC *drawcontext,
149 awesome_config *awesomeconf,
150 const char *arg)
152 int i;
154 if(!sel)
155 return;
156 for(i = 0; i < awesomeconf->ntags; i++)
157 sel->tags[i] = arg == NULL;
158 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
159 if(i >= 0 && i < awesomeconf->ntags)
160 sel->tags[i] = True;
161 saveprops(sel, awesomeconf->ntags);
162 arrange(disp, drawcontext, awesomeconf);
165 /** Toggle floating state of a client
166 * \param disp Display ref
167 * \param arg unused
168 * \ingroup ui_callback
170 void
171 uicb_togglefloating(Display *disp,
172 DC *drawcontext,
173 awesome_config * awesomeconf,
174 const char *arg __attribute__ ((unused)))
176 if(!sel)
177 return;
178 sel->isfloating = !sel->isfloating;
179 if(sel->isfloating)
180 /*restore last known float dimensions*/
181 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
182 else
184 /*save last known float dimensions*/
185 sel->rx = sel->x;
186 sel->ry = sel->y;
187 sel->rw = sel->w;
188 sel->rh = sel->h;
190 saveprops(sel, awesomeconf->ntags);
191 arrange(disp, drawcontext, awesomeconf);
194 /** Toggle tag view
195 * \param disp Display ref
196 * \param arg Tag name
197 * \ingroup ui_callback
199 void
200 uicb_toggletag(Display *disp,
201 DC *drawcontext,
202 awesome_config *awesomeconf,
203 const char *arg)
205 unsigned int i;
206 int j;
208 if(!sel)
209 return;
210 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
211 sel->tags[i] = !sel->tags[i];
212 for(j = 0; j < awesomeconf->ntags && !sel->tags[j]; j++);
213 if(j == awesomeconf->ntags)
214 sel->tags[i] = True;
215 saveprops(sel, awesomeconf->ntags);
216 arrange(disp, drawcontext, awesomeconf);
219 /** Add a tag to viewed tags
220 * \param disp Display ref
221 * \param arg Tag name
222 * \ingroup ui_callback
224 void
225 uicb_toggleview(Display *disp,
226 DC *drawcontext,
227 awesome_config *awesomeconf,
228 const char *arg)
230 unsigned int i;
231 int j;
233 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
234 awesomeconf->selected_tags[i] = !awesomeconf->selected_tags[i];
235 for(j = 0; j < awesomeconf->ntags && !awesomeconf->selected_tags[j]; j++);
236 if(j == awesomeconf->ntags)
237 awesomeconf->selected_tags[i] = True; /* cannot toggle last view */
238 saveawesomeprops(disp, awesomeconf);
239 arrange(disp, drawcontext, awesomeconf);
242 /** View tag
243 * \param disp Display ref
244 * \param awesomeconf awesome config ref
245 * \param arg tag to view
246 * \ingroup ui_callback
248 void
249 uicb_view(Display *disp,
250 DC *drawcontext,
251 awesome_config *awesomeconf,
252 const char *arg)
254 int i;
256 for(i = 0; i < awesomeconf->ntags; i++)
258 awesomeconf->prev_selected_tags[i] = awesomeconf->selected_tags[i];
259 awesomeconf->selected_tags[i] = arg == NULL;
261 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
262 if(i >= 0 && i < awesomeconf->ntags)
264 awesomeconf->selected_tags[i] = True;
265 awesomeconf->current_layout = awesomeconf->tag_layouts[i];
267 saveawesomeprops(disp, awesomeconf);
268 arrange(disp, drawcontext, awesomeconf);
271 /** View previously selected tags
272 * \param disp Display ref
273 * \param awesomeconf awesome config ref
274 * \param arg unused
275 * \ingroup ui_callback
277 void
278 uicb_viewprevtags(Display * disp,
279 DC *drawcontext,
280 awesome_config *awesomeconf,
281 const char *arg __attribute__ ((unused)))
283 int i;
284 Bool t;
286 for(i = 0; i < awesomeconf->ntags; i++)
288 t = awesomeconf->selected_tags[i];
289 awesomeconf->selected_tags[i] = awesomeconf->prev_selected_tags[i];
290 awesomeconf->prev_selected_tags[i] = t;
292 arrange(disp, drawcontext, awesomeconf);
295 /** View next tag
296 * \param disp Display ref
297 * \param arg unused
298 * \ingroup ui_callback
300 void
301 uicb_tag_viewnext(Display *disp,
302 DC * drawcontext,
303 awesome_config *awesomeconf,
304 const char *arg __attribute__ ((unused)))
306 int i;
307 int firsttag = -1;
309 for(i = 0; i < awesomeconf->ntags; i++)
311 if(firsttag < 0 && awesomeconf->selected_tags[i])
312 firsttag = i;
313 awesomeconf->selected_tags[i] = False;
315 if(++firsttag >= awesomeconf->ntags)
316 firsttag = 0;
317 awesomeconf->selected_tags[firsttag] = True;
318 saveawesomeprops(disp, awesomeconf);
319 arrange(disp, drawcontext, awesomeconf);
322 /** View previous tag
323 * \param disp Display ref
324 * \param arg unused
325 * \ingroup ui_callback
327 void
328 uicb_tag_viewprev(Display *disp,
329 DC *drawcontext,
330 awesome_config *awesomeconf,
331 const char *arg __attribute__ ((unused)))
333 int i;
334 int firsttag = -1;
336 for(i = awesomeconf->ntags - 1; i >= 0; i--)
338 if(firsttag < 0 && awesomeconf->selected_tags[i])
339 firsttag = i;
340 awesomeconf->selected_tags[i] = False;
342 if(--firsttag < 0)
343 firsttag = awesomeconf->ntags - 1;
344 awesomeconf->selected_tags[firsttag] = True;
345 saveawesomeprops(disp, awesomeconf);
346 arrange(disp, drawcontext, awesomeconf);