1 /*
2 * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3 * Copyright (C) 2008-2020 Kim Woelders
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to
7 * deal in the Software without restriction, including without limitation the
8 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in
13 * all copies of the Software, its documentation and marketing & publicity
14 * materials, and acknowledgment shall be given in the documentation, materials
15 * and software packages that this Software was used.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24 #include "config.h"
25
26 #include <ctype.h>
27 #include <string.h>
28
29 #include "E.h"
30 #include "ewins.h"
31 #include "groups.h"
32 #include "util.h"
33
34 EWin *
EwinFindByPtr(const EWin * ewin)35 EwinFindByPtr(const EWin * ewin)
36 {
37 EWin *const *ewins;
38 int i, num;
39
40 ewins = EwinListGetAll(&num);
41 for (i = 0; i < num; i++)
42 {
43 if (ewin == ewins[i])
44 return ewins[i];
45 }
46 return NULL;
47 }
48
49 EWin *
EwinFindByClient(EX_Window win)50 EwinFindByClient(EX_Window win)
51 {
52 EWin *const *ewins;
53 int i, num;
54
55 ewins = EwinListGetAll(&num);
56 for (i = 0; i < num; i++)
57 {
58 if (win == EwinGetClientXwin(ewins[i]))
59 return ewins[i];
60 }
61 return NULL;
62 }
63
64 EWin *
EwinFindGroupMember(EWin * ewin)65 EwinFindGroupMember(EWin * ewin)
66 {
67 EWin *ewin2;
68 EWin *const *ewins;
69 int i, num;
70
71 ewin2 = EwinFindByClient(ewin->icccm.group);
72 if (ewin2 && ewin2 != ewin)
73 return ewin2;
74
75 ewins = EwinListGetAll(&num);
76 for (i = 0; i < num; i++)
77 {
78 ewin2 = ewins[i];
79 if (ewin2 == ewin)
80 continue;
81 if (ewin2->state.iconified)
82 continue;
83 if (ewin2->icccm.group == ewin->icccm.group)
84 return ewin2;
85 }
86
87 return NULL;
88 }
89
90 EWin **
EwinsFindByExpr(const char * match,int * pnum,int * pflags)91 EwinsFindByExpr(const char *match, int *pnum, int *pflags)
92 {
93 EWin *ewin, **lst;
94 EWin *const *ewins;
95 int type;
96 int i, num, len, nfound, match_one, flags;
97
98 if (pnum)
99 *pnum = 0;
100
101 if (!match || !match[0])
102 return NULL;
103
104 ewin = NULL;
105 flags = 0;
106
107 if (!strcmp(match, "*") || !strcmp(match, "=") || !strcmp(match, "current"))
108 {
109 ewin = GetContextEwin();
110 if (!ewin)
111 ewin = GetFocusEwin();
112 if (match[0] == '=')
113 flags = 1; /* Nogroup */
114 goto do_one;
115 }
116
117 if (isdigit(match[0]))
118 {
119 unsigned int win;
120
121 sscanf(match, "%x", &win);
122 ewin = EwinFindByClient(win);
123 goto do_one;
124 }
125
126 match_one = 1;
127 if (!strcmp(match, "all"))
128 {
129 type = 'a';
130 match_one = 0;
131 flags = 1; /* Nogroup */
132 }
133 else if (match[0] == '=')
134 {
135 type = 's';
136 match++;
137 flags = 1; /* Nogroup */
138 }
139 else if (strchr(match, '*'))
140 {
141 type = 'w';
142 match_one = 0;
143 flags = 1; /* Nogroup */
144 }
145 else
146 {
147 type = 's';
148 }
149
150 len = strlen(match);
151 if (len <= 0)
152 return NULL;
153
154 ewins = EwinListGetAll(&num);
155 if (!ewins)
156 return NULL;
157
158 nfound = 0;
159 lst = NULL;
160 for (i = 0; i < num; i++)
161 {
162 ewin = ewins[i];
163
164 if (type == 'a') /* All */
165 {
166 }
167 else if (type == 'w') /* Wildcard */
168 {
169 if (!matchregexp(match, EwinGetIcccmName(ewin)))
170 continue;
171 }
172 else /* Match name (substring) */
173 {
174 const char *name;
175
176 name = EwinGetIcccmName(ewin);
177 if (!name)
178 continue;
179 if (!Estrcasestr(name, match))
180 continue;
181 }
182 nfound++;
183 lst = EREALLOC(EWin *, lst, nfound);
184 lst[nfound - 1] = ewin;
185 if (match_one)
186 break;
187 }
188 goto done;
189
190 do_one:
191 if (!ewin)
192 return NULL;
193 nfound = 1;
194 lst = EMALLOC(EWin *, 1);
195 if (!lst)
196 return NULL;
197 lst[0] = ewin;
198
199 done:
200 if (pnum)
201 *pnum = nfound;
202 if (pflags)
203 *pflags = flags;
204 return lst;
205 }
206
207 EWin *
EwinFindByExpr(const char * match)208 EwinFindByExpr(const char *match)
209 {
210 EWin *ewin, **lst;
211
212 lst = EwinsFindByExpr(match, NULL, NULL);
213 if (!lst)
214 return NULL;
215 ewin = lst[0];
216 Efree(lst);
217 return ewin;
218 }
219
220 EWin **
ListWinGroupMembersForEwin(const EWin * ewin,int action,char nogroup,int * pnum)221 ListWinGroupMembersForEwin(const EWin * ewin, int action, char nogroup,
222 int *pnum)
223 {
224
225 EWin **gwins, *ew;
226 EWin *const *ewins;
227 Group *grp;
228 int i, num, gwcnt;
229
230 if (!ewin)
231 {
232 *pnum = 0;
233 return NULL;
234 }
235
236 gwcnt = 0;
237 gwins = NULL;
238
239 if (nogroup || ewin->num_groups <= 0)
240 goto done;
241
242 ewins = EwinListGetAll(&num);
243 if (!ewins) /* Should not be possible */
244 goto done;
245
246 /* Loop through window stack, bottom up */
247 for (i = num - 1; i >= 0; i--)
248 {
249 ew = ewins[i];
250
251 if (ew == ewin)
252 goto do_add;
253
254 /* To get consistent behaviour, limit groups to a single desktop for now: */
255 if (EoGetDesk(ew) != EoGetDesk(ewin))
256 continue;
257
258 grp = EwinsInGroup(ewin, ew);
259 if (!grp)
260 continue;
261
262 if (!GroupMatchAction(grp, action))
263 continue;
264
265 do_add:
266 gwins = EREALLOC(EWin *, gwins, gwcnt + 1);
267 gwins[gwcnt] = ew;
268 gwcnt++;
269 }
270
271 done:
272 if (!gwins)
273 {
274 gwins = EMALLOC(EWin *, 1);
275 gwins[0] = (EWin *) ewin;
276 gwcnt = 1;
277 }
278 *pnum = gwcnt;
279 return gwins;
280 }
281