add a_strncpy functions
[awesome.git] / tag.c
blobdb46eaddba1e343d04e6893fdf1f41bfbe8d0a22
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 * \param tags tag list
37 * \param ntags number of tags in tag list
38 * \return index of tag
40 static int
41 idxoftag(const char *tag_to_find, Tag *tags, int ntags)
43 int i;
45 if(!tag_to_find)
46 return 0;
48 for(i = 0; i < ntags; i++)
49 if(!a_strcmp(tags[i].name, tag_to_find))
50 return i;
52 return 0;
55 void
56 applyrules(Client * c, awesome_config *awesomeconf)
58 int i, j, len = 0;
59 regmatch_t tmp;
60 Bool matched = False;
61 XClassHint ch = { 0, 0 };
62 char *prop;
64 len += a_strlen(ch.res_class) + a_strlen(ch.res_name) + a_strlen(c->name);
66 prop = p_new(char, len + 1);
68 /* rule matching */
69 XGetClassHint(c->display, c->win, &ch);
70 snprintf(prop, len + 1, "%s:%s:%s",
71 ch.res_class ? ch.res_class : "", ch.res_name ? ch.res_name : "", c->name);
72 for(i = 0; i < awesomeconf->nrules; i++)
73 if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0))
75 c->isfloating = awesomeconf->rules[i].isfloating;
76 for(j = 0; regs[i].tagregex && j < awesomeconf->ntags; j++)
77 if(!regexec(regs[i].tagregex, awesomeconf->tags[j].name, 1, &tmp, 0))
79 matched = True;
80 c->tags[j] = True;
83 p_delete(&prop);
84 if(ch.res_class)
85 XFree(ch.res_class);
86 if(ch.res_name)
87 XFree(ch.res_name);
88 if(!matched)
89 for(i = 0; i < awesomeconf->ntags; i++)
90 c->tags[i] = awesomeconf->tags[i].selected;
93 void
94 compileregs(Rule * rules, int nrules)
96 int i;
97 regex_t *reg;
99 if(regs)
100 return;
101 regs = p_new(Regs, nrules);
102 for(i = 0; i < nrules; i++)
104 if(rules[i].prop)
106 reg = p_new(regex_t, 1);
107 if(regcomp(reg, rules[i].prop, REG_EXTENDED))
108 p_delete(&reg);
109 else
110 regs[i].propregex = reg;
112 if(rules[i].tags)
114 reg = p_new(regex_t, 1);
115 if(regcomp(reg, rules[i].tags, REG_EXTENDED))
116 p_delete(&reg);
117 else
118 regs[i].tagregex = reg;
124 /** Returns True if a client is tagged
125 * with one of the tags
126 * \param c Client
127 * \param tags tag to check
128 * \param ntags number of tags in *tags
129 * \return True or False
131 Bool
132 isvisible(Client * c, int screen, Tag * tags, int ntags)
134 int i;
136 for(i = 0; i < ntags; i++)
137 if(c->tags[i] && tags[i].selected && c->screen == screen)
138 return True;
139 return False;
143 /** Tag selected window with tag
144 * \param disp Display ref
145 * \param drawcontext Drawcontext ref
146 * \param arg Tag name
147 * \ingroup ui_callback
149 void
150 uicb_tag(Display *disp,
151 DC *drawcontext,
152 awesome_config *awesomeconf,
153 const char *arg)
155 int i;
157 if(!sel)
158 return;
159 for(i = 0; i < awesomeconf->ntags; i++)
160 sel->tags[i] = arg == NULL;
161 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
162 if(i >= 0 && i < awesomeconf->ntags)
163 sel->tags[i] = True;
164 saveprops(sel, awesomeconf->ntags);
165 arrange(disp, drawcontext, awesomeconf);
168 /** Toggle floating state of a client
169 * \param disp Display ref
170 * \param drawcontext Drawcontext ref
171 * \param arg unused
172 * \ingroup ui_callback
174 void
175 uicb_togglefloating(Display *disp,
176 DC *drawcontext,
177 awesome_config * awesomeconf,
178 const char *arg __attribute__ ((unused)))
180 if(!sel)
181 return;
182 sel->isfloating = !sel->isfloating;
183 if(sel->isfloating)
184 /*restore last known float dimensions*/
185 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, True);
186 else
188 /*save last known float dimensions*/
189 sel->rx = sel->x;
190 sel->ry = sel->y;
191 sel->rw = sel->w;
192 sel->rh = sel->h;
194 saveprops(sel, awesomeconf->ntags);
195 arrange(disp, drawcontext, awesomeconf);
198 /** Toggle tag view
199 * \param disp Display ref
200 * \param drawcontext Drawcontext ref
201 * \param arg Tag name
202 * \ingroup ui_callback
204 void
205 uicb_toggletag(Display *disp,
206 DC *drawcontext,
207 awesome_config *awesomeconf,
208 const char *arg)
210 unsigned int i;
211 int j;
213 if(!sel)
214 return;
215 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
216 sel->tags[i] = !sel->tags[i];
217 for(j = 0; j < awesomeconf->ntags && !sel->tags[j]; j++);
218 if(j == awesomeconf->ntags)
219 sel->tags[i] = True;
220 saveprops(sel, awesomeconf->ntags);
221 arrange(disp, drawcontext, awesomeconf);
224 /** Add a tag to viewed tags
225 * \param disp Display ref
226 * \param drawcontext Drawcontext ref
227 * \param arg Tag name
228 * \ingroup ui_callback
230 void
231 uicb_toggleview(Display *disp,
232 DC *drawcontext,
233 awesome_config *awesomeconf,
234 const char *arg)
236 unsigned int i;
237 int j;
239 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
240 awesomeconf->tags[i].selected = !awesomeconf->tags[i].selected;
241 for(j = 0; j < awesomeconf->ntags && !awesomeconf->tags[j].selected; j++);
242 if(j == awesomeconf->ntags)
243 awesomeconf->tags[i].selected = True;
244 saveawesomeprops(disp, awesomeconf);
245 arrange(disp, drawcontext, awesomeconf);
248 /** View tag
249 * \param disp Display ref
250 * \param awesomeconf awesome config ref
251 * \param arg tag to view
252 * \ingroup ui_callback
254 void
255 uicb_view(Display *disp,
256 DC *drawcontext,
257 awesome_config *awesomeconf,
258 const char *arg)
260 int i;
262 for(i = 0; i < awesomeconf->ntags; i++)
264 awesomeconf->tags[i].was_selected = awesomeconf->tags[i].selected;
265 awesomeconf->tags[i].selected = arg == NULL;
267 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
268 if(i >= 0 && i < awesomeconf->ntags)
270 awesomeconf->tags[i].selected = True;
271 awesomeconf->current_layout = awesomeconf->tags[i].layout;
273 saveawesomeprops(disp, awesomeconf);
274 arrange(disp, drawcontext, awesomeconf);
277 /** View previously selected tags
278 * \param disp Display ref
279 * \param awesomeconf awesome config ref
280 * \param arg unused
281 * \ingroup ui_callback
283 void
284 uicb_tag_prev_selected(Display * disp,
285 DC *drawcontext,
286 awesome_config *awesomeconf,
287 const char *arg __attribute__ ((unused)))
289 int i;
290 Bool t;
292 for(i = 0; i < awesomeconf->ntags; i++)
294 t = awesomeconf->tags[i].selected;
295 awesomeconf->tags[i].selected = awesomeconf->tags[i].was_selected;
296 awesomeconf->tags[i].was_selected = t;
298 arrange(disp, drawcontext, awesomeconf);
301 /** View next tag
302 * \param disp Display ref
303 * \param drawcontext Drawcontext ref
304 * \param arg unused
305 * \ingroup ui_callback
307 void
308 uicb_tag_viewnext(Display *disp,
309 DC * drawcontext,
310 awesome_config *awesomeconf,
311 const char *arg __attribute__ ((unused)))
313 int i;
314 int firsttag = -1;
316 for(i = 0; i < awesomeconf->ntags; i++)
318 if(firsttag < 0 && awesomeconf->tags[i].selected)
319 firsttag = i;
320 awesomeconf->tags[i].selected = False;
322 if(++firsttag >= awesomeconf->ntags)
323 firsttag = 0;
324 awesomeconf->tags[firsttag].selected = True;
325 saveawesomeprops(disp, awesomeconf);
326 arrange(disp, drawcontext, awesomeconf);
329 /** View previous tag
330 * \param disp Display ref
331 * \param drawcontext Drawcontext ref
332 * \param arg unused
333 * \ingroup ui_callback
335 void
336 uicb_tag_viewprev(Display *disp,
337 DC *drawcontext,
338 awesome_config *awesomeconf,
339 const char *arg __attribute__ ((unused)))
341 int i;
342 int firsttag = -1;
344 for(i = awesomeconf->ntags - 1; i >= 0; i--)
346 if(firsttag < 0 && awesomeconf->tags[i].selected)
347 firsttag = i;
348 awesomeconf->tags[i].selected = False;
350 if(--firsttag < 0)
351 firsttag = awesomeconf->ntags - 1;
352 awesomeconf->tags[firsttag].selected = True;
353 saveawesomeprops(disp, awesomeconf);
354 arrange(disp, drawcontext, awesomeconf);