better fix for font height problem
[awesome.git] / tag.c
blob641b54c95063bc4e11772dd242a4f63c42d0e9e0
1 /*
2 * tag.c - tag management
4 * Copyright © 2007 Julien Danjou <julien@danjou.info>
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 typedef struct
33 regex_t *propregex;
34 regex_t *tagregex;
35 } Regs;
37 static Regs *regs = NULL;
39 /** This function returns the index of
40 * the tag given un argument in *tags
41 * \param tag_to_find tag name
42 * \param tags tag list
43 * \param ntags number of tags in tag list
44 * \return index of tag
46 static int
47 idxoftag(const char *tag_to_find, Tag *tags, int ntags)
49 int i;
51 if(!tag_to_find)
52 return 0;
54 for(i = 0; i < ntags; i++)
55 if(!a_strcmp(tags[i].name, tag_to_find))
56 return i;
58 return 0;
61 void
62 applyrules(Client * c, awesome_config *awesomeconf)
64 int i, j, len = 0;
65 regmatch_t tmp;
66 Bool matched = False;
67 XClassHint ch = { 0, 0 };
68 char *prop;
70 XGetClassHint(c->display, c->win, &ch);
72 len = a_strlen(ch.res_class) + a_strlen(ch.res_name) + a_strlen(c->name);
74 prop = p_new(char, len + 3);
76 /* rule matching */
77 snprintf(prop, len + 3, "%s:%s:%s",
78 ch.res_class ? ch.res_class : "", ch.res_name ? ch.res_name : "", c->name);
79 for(i = 0; i < awesomeconf->nrules; i++)
80 if(regs[i].propregex && !regexec(regs[i].propregex, prop, 1, &tmp, 0))
82 c->isfloating = awesomeconf->rules[i].isfloating;
83 for(j = 0; regs[i].tagregex && j < awesomeconf->ntags; j++)
84 if(!regexec(regs[i].tagregex, awesomeconf->tags[j].name, 1, &tmp, 0))
86 matched = True;
87 c->tags[j] = True;
89 else
90 c->tags[j] = False;
92 p_delete(&prop);
93 if(ch.res_class)
94 XFree(ch.res_class);
95 if(ch.res_name)
96 XFree(ch.res_name);
97 if(!matched)
98 for(i = 0; i < awesomeconf->ntags; i++)
99 c->tags[i] = awesomeconf->tags[i].selected;
102 void
103 compileregs(Rule * rules, int nrules)
105 int i;
106 regex_t *reg;
108 if(regs)
109 return;
110 regs = p_new(Regs, nrules);
111 for(i = 0; i < nrules; i++)
113 if(rules[i].prop)
115 reg = p_new(regex_t, 1);
116 if(regcomp(reg, rules[i].prop, REG_EXTENDED))
117 p_delete(&reg);
118 else
119 regs[i].propregex = reg;
121 if(rules[i].tags)
123 reg = p_new(regex_t, 1);
124 if(regcomp(reg, rules[i].tags, REG_EXTENDED))
125 p_delete(&reg);
126 else
127 regs[i].tagregex = reg;
133 /** Returns True if a client is tagged
134 * with one of the tags
135 * \param c Client
136 * \param tags tag to check
137 * \param ntags number of tags in *tags
138 * \return True or False
140 Bool
141 isvisible(Client * c, int screen, Tag * tags, int ntags)
143 int i;
145 if(c->screen != screen)
146 return False;
148 for(i = 0; i < ntags; i++)
149 if(c->tags[i] && tags[i].selected)
150 return True;
151 return False;
155 /** Tag selected window with tag
156 * \param disp Display ref
157 * \param drawcontext Drawcontext ref
158 * \param arg Tag name
159 * \ingroup ui_callback
161 void
162 uicb_tag(Display *disp,
163 DC *drawcontext,
164 awesome_config *awesomeconf,
165 const char *arg)
167 int i;
169 if(!sel)
170 return;
171 for(i = 0; i < awesomeconf->ntags; i++)
172 sel->tags[i] = arg == NULL;
173 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
174 if(i >= 0 && i < awesomeconf->ntags)
175 sel->tags[i] = True;
176 saveprops(sel, awesomeconf->ntags);
177 arrange(disp, drawcontext, awesomeconf);
180 /** Toggle floating state of a client
181 * \param disp Display ref
182 * \param drawcontext Drawcontext ref
183 * \param arg unused
184 * \ingroup ui_callback
186 void
187 uicb_togglefloating(Display *disp,
188 DC *drawcontext,
189 awesome_config * awesomeconf,
190 const char *arg __attribute__ ((unused)))
192 if(!sel)
193 return;
194 sel->isfloating = !sel->isfloating;
195 if(sel->isfloating)
196 /*restore last known float dimensions*/
197 resize(sel, sel->rx, sel->ry, sel->rw, sel->rh, awesomeconf, True);
198 else
200 /*save last known float dimensions*/
201 sel->rx = sel->x;
202 sel->ry = sel->y;
203 sel->rw = sel->w;
204 sel->rh = sel->h;
206 saveprops(sel, awesomeconf->ntags);
207 arrange(disp, drawcontext, awesomeconf);
210 /** Toggle tag view
211 * \param disp Display ref
212 * \param drawcontext Drawcontext ref
213 * \param arg Tag name
214 * \ingroup ui_callback
216 void
217 uicb_toggletag(Display *disp,
218 DC *drawcontext,
219 awesome_config *awesomeconf,
220 const char *arg)
222 unsigned int i;
223 int j;
225 if(!sel)
226 return;
227 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
228 sel->tags[i] = !sel->tags[i];
229 for(j = 0; j < awesomeconf->ntags && !sel->tags[j]; j++);
230 if(j == awesomeconf->ntags)
231 sel->tags[i] = True;
232 saveprops(sel, awesomeconf->ntags);
233 arrange(disp, drawcontext, awesomeconf);
236 /** Add a tag to viewed tags
237 * \param disp Display ref
238 * \param drawcontext Drawcontext ref
239 * \param arg Tag name
240 * \ingroup ui_callback
242 void
243 uicb_toggleview(Display *disp,
244 DC *drawcontext,
245 awesome_config *awesomeconf,
246 const char *arg)
248 unsigned int i;
249 int j;
251 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
252 awesomeconf->tags[i].selected = !awesomeconf->tags[i].selected;
253 for(j = 0; j < awesomeconf->ntags && !awesomeconf->tags[j].selected; j++);
254 if(j == awesomeconf->ntags)
255 awesomeconf->tags[i].selected = True;
256 saveawesomeprops(disp, awesomeconf);
257 arrange(disp, drawcontext, awesomeconf);
260 /** View tag
261 * \param disp Display ref
262 * \param awesomeconf awesome config ref
263 * \param arg tag to view
264 * \ingroup ui_callback
266 void
267 uicb_view(Display *disp,
268 DC *drawcontext,
269 awesome_config *awesomeconf,
270 const char *arg)
272 int i;
274 for(i = 0; i < awesomeconf->ntags; i++)
276 awesomeconf->tags[i].was_selected = awesomeconf->tags[i].selected;
277 awesomeconf->tags[i].selected = arg == NULL;
279 i = idxoftag(arg, awesomeconf->tags, awesomeconf->ntags);
280 if(i >= 0 && i < awesomeconf->ntags)
282 awesomeconf->tags[i].selected = True;
283 awesomeconf->current_layout = awesomeconf->tags[i].layout;
285 saveawesomeprops(disp, awesomeconf);
286 arrange(disp, drawcontext, awesomeconf);
289 /** View previously selected tags
290 * \param disp Display ref
291 * \param awesomeconf awesome config ref
292 * \param arg unused
293 * \ingroup ui_callback
295 void
296 uicb_tag_prev_selected(Display * disp,
297 DC *drawcontext,
298 awesome_config *awesomeconf,
299 const char *arg __attribute__ ((unused)))
301 int i;
302 Bool t;
304 for(i = 0; i < awesomeconf->ntags; i++)
306 t = awesomeconf->tags[i].selected;
307 awesomeconf->tags[i].selected = awesomeconf->tags[i].was_selected;
308 awesomeconf->tags[i].was_selected = t;
310 arrange(disp, drawcontext, awesomeconf);
313 /** View next tag
314 * \param disp Display ref
315 * \param drawcontext Drawcontext ref
316 * \param arg unused
317 * \ingroup ui_callback
319 void
320 uicb_tag_viewnext(Display *disp,
321 DC * drawcontext,
322 awesome_config *awesomeconf,
323 const char *arg __attribute__ ((unused)))
325 int i;
326 int firsttag = -1;
328 for(i = 0; i < awesomeconf->ntags; i++)
330 if(firsttag < 0 && awesomeconf->tags[i].selected)
331 firsttag = i;
332 awesomeconf->tags[i].selected = False;
334 if(++firsttag >= awesomeconf->ntags)
335 firsttag = 0;
336 awesomeconf->tags[firsttag].selected = True;
337 awesomeconf->current_layout = awesomeconf->tags[firsttag].layout;
338 saveawesomeprops(disp, awesomeconf);
339 arrange(disp, drawcontext, awesomeconf);
342 /** View previous tag
343 * \param disp Display ref
344 * \param drawcontext Drawcontext ref
345 * \param arg unused
346 * \ingroup ui_callback
348 void
349 uicb_tag_viewprev(Display *disp,
350 DC *drawcontext,
351 awesome_config *awesomeconf,
352 const char *arg __attribute__ ((unused)))
354 int i;
355 int firsttag = -1;
357 for(i = awesomeconf->ntags - 1; i >= 0; i--)
359 if(firsttag < 0 && awesomeconf->tags[i].selected)
360 firsttag = i;
361 awesomeconf->tags[i].selected = False;
363 if(--firsttag < 0)
364 firsttag = awesomeconf->ntags - 1;
365 awesomeconf->tags[firsttag].selected = True;
366 awesomeconf->current_layout = awesomeconf->tags[firsttag].layout;
367 saveawesomeprops(disp, awesomeconf);
368 arrange(disp, drawcontext, awesomeconf);