1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, see: <http://www.gnu.org/licenses/>
14 */
15
16 #include "config.h"
17
18 #include <limits.h>
19 #include "libs/wild.h"
20 #include "FvwmIconMan.h"
21
22 #define HASHTAB_SIZE 257
23
24 typedef WinList HashTab[HASHTAB_SIZE];
25 static HashTab hash_tab;
26
print_stringlist(StringList * list)27 void print_stringlist (StringList *list)
28 {
29 StringEl *p;
30 char *s;
31
32 ConsoleDebug (WINLIST, "\tmask = 0x%x\n", list->mask);
33 for (p = list->list; p; p = p->next) {
34 switch (p->type) {
35 case ALL_NAME:
36 s = "all";
37 break;
38
39 case TITLE_NAME:
40 s = "title";
41 break;
42
43 case ICON_NAME:
44 s = "icon";
45 break;
46
47 case RESOURCE_NAME:
48 s = "resource";
49 break;
50
51 case CLASS_NAME:
52 s = "class";
53 break;
54
55 default:
56 s = "unknown type";
57 }
58 ConsoleDebug (WINLIST, "\t%s = %s\n", s, p->string);
59 }
60 }
61
add_to_stringlist(StringList * list,char * s)62 void add_to_stringlist (StringList *list, char *s)
63 {
64 StringEl *new;
65 NameType type;
66 char *pat;
67
68 ConsoleDebug (WINLIST, "In add_to_stringlist: %s\n", s);
69
70 pat = strchr (s, '=');
71 if (pat) {
72 *pat++ = '\0';
73 if (!strcasecmp (s, "icon"))
74 type = ICON_NAME;
75 else if (!strcasecmp (s, "title"))
76 type = TITLE_NAME;
77 else if (!strcasecmp (s, "resource"))
78 type = RESOURCE_NAME;
79 else if (!strcasecmp (s, "class"))
80 type = CLASS_NAME;
81 else {
82 ConsoleMessage ("Bad element in show/dontshow list: %s\n", s);
83 return;
84 }
85 }
86 else {
87 pat = s;
88 type = ALL_NAME;
89 }
90
91 ConsoleDebug (WINLIST, "add_to_stringlist: %s %s\n",
92 type == ALL_NAME ? "all" : s, pat);
93
94 new = (StringEl *)safemalloc (sizeof (StringEl));
95 new->string = (char *)safemalloc ((strlen (pat) + 1) * sizeof (char));
96 new->type = type;
97
98 strcpy (new->string, pat);
99 new->next = list->list;
100 if (list->list)
101 list->mask |= type;
102 else
103 list->mask = type;
104 list->list = new;
105
106 ConsoleDebug (WINLIST, "Exiting add_to_stringlist\n");
107 }
108
matches_string(NameType type,char * pattern,char * tname,char * iname,char * rname,char * cname)109 static int matches_string (NameType type, char *pattern, char *tname,
110 char *iname, char *rname, char *cname)
111 {
112 int ans = 0;
113
114 ConsoleDebug (WINLIST, "matches_string: type: 0x%x pattern: %s\n",
115 type, pattern);
116 ConsoleDebug (WINLIST, "\tstrings: %s:%s %s:%s\n", tname, iname,
117 rname, cname);
118
119 if (tname && (type == ALL_NAME || type == TITLE_NAME)) {
120 ans |= matchWildcards (pattern, tname);
121 }
122 if (iname && (type == ALL_NAME || type == ICON_NAME)) {
123 ans |= matchWildcards (pattern, iname);
124 }
125 if (rname && (type == ALL_NAME || type == RESOURCE_NAME)) {
126 ans |= matchWildcards (pattern, rname);
127 }
128 if (cname && (type == ALL_NAME || type == CLASS_NAME)) {
129 ans |= matchWildcards (pattern, cname);
130 }
131
132 ConsoleDebug (WINLIST, "\tmatches_string: %d\n", ans);
133 return ans;
134 }
135
check_resolution(WinManager * manager,WinData * win)136 int check_resolution(WinManager *manager, WinData *win)
137 {
138 int flag = 0;
139 int reverse = 0;
140 rectangle g;
141
142 assert (manager);
143
144 if (IS_ICONIFIED(win) && !IS_ICON_SUPPRESSED(win))
145 {
146 g = win->icon_g;
147 }
148 else
149 {
150 g.x = win->x;
151 g.y = win->y;
152 g.width = win->width;
153 g.height = win->height;
154 }
155 switch (manager->res) {
156 case SHOW_GLOBAL:
157 flag = 1;
158 break;
159
160 case NO_SHOW_DESKTOP:
161 reverse = 1;
162 /* fall through to next case */
163 case SHOW_DESKTOP:
164 if (IS_STICKY_ACROSS_PAGES(win) || win->desknum == globals.desknum)
165 flag = 1;
166 break;
167
168 case NO_SHOW_PAGE:
169 reverse = 1;
170 /* fall through to next case */
171 case SHOW_PAGE:
172 if (IS_STICKY_ACROSS_PAGES(win)) {
173 flag = 1;
174 } else if (win->desknum == globals.desknum) {
175 /* win and screen intersect if they are not disjoint in x and y */
176 flag = fvwmrect_do_rectangles_intersect(&g, &manager->managed_g);
177 }
178 break;
179
180 case NO_SHOW_SCREEN:
181 reverse = 1;
182 /* fall through to next case */
183 case SHOW_SCREEN:
184 if (win->desknum == globals.desknum) {
185 /* win and screen intersect if they are not disjoint in x and y */
186 flag = fvwmrect_do_rectangles_intersect(&g, &manager->managed_g);
187 }
188 break;
189 }
190 flag ^= reverse;
191
192 return flag;
193 }
194
iconmanager_show(WinManager * man,char * tname,char * iname,char * rname,char * cname)195 static int iconmanager_show (WinManager *man, char *tname, char *iname,
196 char *rname, char *cname)
197 {
198 StringEl *string;
199 int in_showlist = 0, in_dontshowlist = 0;
200
201 assert (man);
202
203 #ifdef FVWM_DEBUG_MSGS
204 ConsoleDebug (WINLIST, "In iconmanager_show: %s:%s : %s %s\n", tname, iname,
205 rname, cname);
206 ConsoleDebug (WINLIST, "dontshow:\n");
207 print_stringlist (&man->dontshow);
208 ConsoleDebug (WINLIST, "show:\n");
209 print_stringlist (&man->show);
210 #endif /* FVWM_DEBUG_MSGS */
211
212 for (string = man->dontshow.list; string; string = string->next) {
213 ConsoleDebug (WINLIST, "Matching: %s\n", string->string);
214 if (matches_string (string->type, string->string, tname, iname,
215 rname, cname)) {
216 ConsoleDebug (WINLIST, "Don't show\n");
217 in_dontshowlist = 1;
218 break;
219 }
220 }
221
222 if (!in_dontshowlist) {
223 if (man->show.list == NULL) {
224 in_showlist = 1;
225 }
226 else {
227 for (string = man->show.list; string; string = string->next) {
228 ConsoleDebug (WINLIST, "Matching: %s\n", string->string);
229 if (matches_string (string->type, string->string, tname, iname,
230 rname, cname)) {
231 ConsoleDebug (WINLIST, "Show\n");
232 in_showlist = 1;
233 break;
234 }
235 }
236 }
237 }
238
239 ConsoleDebug (WINLIST, "returning: %d %d %d\n", in_dontshowlist,
240 in_showlist, !in_dontshowlist && in_showlist);
241
242 return (!in_dontshowlist && in_showlist);
243 }
244
new_windata(void)245 WinData *new_windata (void)
246 {
247 WinData *new = (WinData *)safemalloc (sizeof (WinData));
248
249 memset(new, 0, sizeof(WinData));
250 new->desknum = ULONG_MAX;
251 new->x = ULONG_MAX;
252 new->y = ULONG_MAX;
253 new->app_id = ULONG_MAX;
254
255 return new;
256 }
257
free_windata(WinData * p)258 void free_windata (WinData *p)
259 {
260 if (globals.select_win == p) {
261 ConsoleMessage ("Internal error in free_windata\n");
262 globals.select_win = NULL;
263 abort();
264 }
265
266 Free (p->resname);
267 Free (p->classname);
268 Free (p->iconname);
269 Free (p->titlename);
270 Free (p->display_string);
271 Free (p);
272 }
273
274
275 /* This ALWAYS gets called when one of the name strings changes */
276
figure_win_manager(WinData * win,Uchar name_mask)277 WinManager *figure_win_manager (WinData *win, Uchar name_mask)
278 {
279 int i;
280 char *tname = win->titlename;
281 char *iname = win->iconname;
282 char *rname = win->resname;
283 char *cname = win->classname;
284 WinManager *man;
285
286 assert (tname || iname || rname || cname);
287 ConsoleDebug (WINLIST, "set_win_manager: %s %s %s %s\n", tname, iname, rname, cname);
288
289 for (i = 0, man = &globals.managers[0]; i < globals.num_managers;
290 i++, man++) {
291 if (iconmanager_show (man, tname, iname, rname, cname) &&
292 check_resolution(man, win)) {
293 if (man != win->manager) {
294 assert (man->magic == 0x12344321);
295 }
296 return man;
297 }
298 }
299
300 /* No manager wants this window */
301 return NULL;
302 }
303
check_win_complete(WinData * p)304 int check_win_complete (WinData *p)
305 {
306 if (p->complete)
307 return 1;
308
309 ConsoleDebug (WINLIST, "Checking completeness:\n");
310 ConsoleDebug (WINLIST, "\ttitlename: %s\n",
311 (p->titlename ? p->titlename : "No Title name"));
312 ConsoleDebug (WINLIST, "\ticonname: %s\n",
313 (p->iconname ? p->iconname : "No Icon name"));
314 ConsoleDebug (WINLIST, "\tres: %s\n",
315 (p->resname ? p->resname : "No p->resname"));
316 ConsoleDebug (WINLIST, "\tclass: %s\n",
317 (p->classname ? p->classname : "No p->classname"));
318 ConsoleDebug (WINLIST, "\tdisplaystring: %s\n",
319 (p->display_string ? p->display_string :
320 "No p->display_string"));
321 ConsoleDebug (WINLIST, "\t(x, y): (%ld, %ld)\n", p->x, p->y);
322 ConsoleDebug (WINLIST, "\tapp_id: 0x%lx %d\n", p->app_id, p->app_id_set);
323 ConsoleDebug (WINLIST, "\tdesknum: %ld\n", p->desknum);
324 ConsoleDebug (WINLIST, "\tmanager: 0x%lx\n", (unsigned long)p->manager);
325
326 if (p->geometry_set &&
327 p->resname &&
328 p->classname &&
329 p->iconname &&
330 p->titlename &&
331 p->app_id_set) {
332 p->complete = 1;
333 ConsoleDebug (WINLIST, "\tcomplete: 1\n\n");
334 return 1;
335 }
336
337 ConsoleDebug (WINLIST, "\tcomplete: 0\n\n");
338 return 0;
339 }
340
init_winlists(void)341 void init_winlists (void)
342 {
343 int i;
344 for (i = 0; i < HASHTAB_SIZE; i++) {
345 hash_tab[i].n = 0;
346 hash_tab[i].head = NULL;
347 hash_tab[i].tail = NULL;
348 }
349 }
350
delete_win_hashtab(WinData * win)351 void delete_win_hashtab (WinData *win)
352 {
353 int entry;
354 WinList *list;
355
356 entry = win->app_id & 0xff;
357 list = &hash_tab[entry];
358
359 if (win->win_prev)
360 win->win_prev->win_next = win->win_next;
361 else
362 list->head = win->win_next;
363 if (win->win_next)
364 win->win_next->win_prev = win->win_prev;
365 else
366 list->tail = win->win_prev;
367 list->n--;
368 }
369
insert_win_hashtab(WinData * win)370 void insert_win_hashtab (WinData *win)
371 {
372 int entry;
373 WinList *list;
374 WinData *p;
375
376 entry = win->app_id & 0xff;
377 list = &hash_tab[entry];
378
379 for (p = list->head; p && win->app_id > p->app_id;
380 p = p->win_next);
381
382 if (p) {
383 /* insert win before p */
384 win->win_next = p;
385 win->win_prev = p->win_prev;
386 if (p->win_prev)
387 p->win_prev->win_next = win;
388 else
389 list->head = win;
390 p->win_prev = win;
391 }
392 else {
393 /* put win at end of list */
394 win->win_next = NULL;
395 win->win_prev = list->tail;
396 if (list->tail)
397 list->tail->win_next = win;
398 else
399 list->head = win;
400 list->tail = win;
401 }
402 list->n++;
403 }
404
find_win_hashtab(Ulong id)405 WinData *find_win_hashtab (Ulong id)
406 {
407 WinList *list;
408 int entry = id & 0xff;
409 WinData *p;
410
411 list = &hash_tab[entry];
412
413 for (p = list->head; p && p->app_id != id; p = p->win_next);
414
415 return p;
416 }
417
walk_hashtab(void (* func)(void *))418 void walk_hashtab (void (*func)(void *))
419 {
420 int i;
421 WinData *p;
422
423 for (i = 0; i < HASHTAB_SIZE; i++) {
424 for (p = hash_tab[i].head; p; p = p->win_next)
425 func (p);
426 }
427 }
428
accumulate_walk_hashtab(int (* func)(void *))429 int accumulate_walk_hashtab (int (*func)(void *))
430 {
431 int i, ret = 0;
432 WinData *p;
433
434 for (i = 0; i < HASHTAB_SIZE; i++) {
435 for (p = hash_tab[i].head; p; p = p->win_next)
436 ret += func (p);
437 }
438
439 return ret;
440 }
441