NEWS/Changelog for previous commit.
[fvwm.git] / modules / FvwmIconMan / winlist.c
blob9cb4436ee60031a6eff4482e178f56d82b9e76b3
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.
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.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 #include "config.h"
19 #include <limits.h>
20 #include "libs/wild.h"
21 #include "FvwmIconMan.h"
23 #define HASHTAB_SIZE 257
25 typedef WinList HashTab[HASHTAB_SIZE];
26 static HashTab hash_tab;
28 void print_stringlist (StringList *list)
30 StringEl *p;
31 char *s;
33 ConsoleDebug (WINLIST, "\tmask = 0x%x\n", list->mask);
34 for (p = list->list; p; p = p->next) {
35 switch (p->type) {
36 case ALL_NAME:
37 s = "all";
38 break;
40 case TITLE_NAME:
41 s = "title";
42 break;
44 case ICON_NAME:
45 s = "icon";
46 break;
48 case RESOURCE_NAME:
49 s = "resource";
50 break;
52 case CLASS_NAME:
53 s = "class";
54 break;
56 default:
57 s = "unknown type";
59 ConsoleDebug (WINLIST, "\t%s = %s\n", s, p->string);
63 void add_to_stringlist (StringList *list, char *s)
65 StringEl *new;
66 NameType type;
67 char *pat;
69 ConsoleDebug (WINLIST, "In add_to_stringlist: %s\n", s);
71 pat = strchr (s, '=');
72 if (pat) {
73 *pat++ = '\0';
74 if (!strcasecmp (s, "icon"))
75 type = ICON_NAME;
76 else if (!strcasecmp (s, "title"))
77 type = TITLE_NAME;
78 else if (!strcasecmp (s, "resource"))
79 type = RESOURCE_NAME;
80 else if (!strcasecmp (s, "class"))
81 type = CLASS_NAME;
82 else {
83 ConsoleMessage ("Bad element in show/dontshow list: %s\n", s);
84 return;
87 else {
88 pat = s;
89 type = ALL_NAME;
92 ConsoleDebug (WINLIST, "add_to_stringlist: %s %s\n",
93 type == ALL_NAME ? "all" : s, pat);
95 new = (StringEl *)safemalloc (sizeof (StringEl));
96 new->string = (char *)safemalloc ((strlen (pat) + 1) * sizeof (char));
97 new->type = type;
99 strcpy (new->string, pat);
100 new->next = list->list;
101 if (list->list)
102 list->mask |= type;
103 else
104 list->mask = type;
105 list->list = new;
107 ConsoleDebug (WINLIST, "Exiting add_to_stringlist\n");
110 static int matches_string (NameType type, char *pattern, char *tname,
111 char *iname, char *rname, char *cname)
113 int ans = 0;
115 ConsoleDebug (WINLIST, "matches_string: type: 0x%x pattern: %s\n",
116 type, pattern);
117 ConsoleDebug (WINLIST, "\tstrings: %s:%s %s:%s\n", tname, iname,
118 rname, cname);
120 if (tname && (type == ALL_NAME || type == TITLE_NAME)) {
121 ans |= matchWildcards (pattern, tname);
123 if (iname && (type == ALL_NAME || type == ICON_NAME)) {
124 ans |= matchWildcards (pattern, iname);
126 if (rname && (type == ALL_NAME || type == RESOURCE_NAME)) {
127 ans |= matchWildcards (pattern, rname);
129 if (cname && (type == ALL_NAME || type == CLASS_NAME)) {
130 ans |= matchWildcards (pattern, cname);
133 ConsoleDebug (WINLIST, "\tmatches_string: %d\n", ans);
134 return ans;
137 int check_resolution(WinManager *manager, WinData *win)
139 int flag = 0;
140 int reverse = 0;
141 rectangle g;
143 assert (manager);
145 if (IS_ICONIFIED(win) && !IS_ICON_SUPPRESSED(win))
147 g = win->icon_g;
149 else
151 g.x = win->x;
152 g.y = win->y;
153 g.width = win->width;
154 g.height = win->height;
156 switch (manager->res) {
157 case SHOW_GLOBAL:
158 flag = 1;
159 break;
161 case NO_SHOW_DESKTOP:
162 reverse = 1;
163 /* fall through to next case */
164 case SHOW_DESKTOP:
165 if (IS_STICKY_ACROSS_PAGES(win) || win->desknum == globals.desknum)
166 flag = 1;
167 break;
169 case NO_SHOW_PAGE:
170 reverse = 1;
171 /* fall through to next case */
172 case SHOW_PAGE:
173 if (IS_STICKY_ACROSS_PAGES(win)) {
174 flag = 1;
175 } else if (win->desknum == globals.desknum) {
176 /* win and screen intersect if they are not disjoint in x and y */
177 flag = fvwmrect_do_rectangles_intersect(&g, &manager->managed_g);
179 break;
181 case NO_SHOW_SCREEN:
182 reverse = 1;
183 /* fall through to next case */
184 case SHOW_SCREEN:
185 if (win->desknum == globals.desknum) {
186 /* win and screen intersect if they are not disjoint in x and y */
187 flag = fvwmrect_do_rectangles_intersect(&g, &manager->managed_g);
189 break;
191 flag ^= reverse;
193 return flag;
196 static int iconmanager_show (WinManager *man, char *tname, char *iname,
197 char *rname, char *cname)
199 StringEl *string;
200 int in_showlist = 0, in_dontshowlist = 0;
202 assert (man);
204 #ifdef FVWM_DEBUG_MSGS
205 ConsoleDebug (WINLIST, "In iconmanager_show: %s:%s : %s %s\n", tname, iname,
206 rname, cname);
207 ConsoleDebug (WINLIST, "dontshow:\n");
208 print_stringlist (&man->dontshow);
209 ConsoleDebug (WINLIST, "show:\n");
210 print_stringlist (&man->show);
211 #endif /* FVWM_DEBUG_MSGS */
213 for (string = man->dontshow.list; string; string = string->next) {
214 ConsoleDebug (WINLIST, "Matching: %s\n", string->string);
215 if (matches_string (string->type, string->string, tname, iname,
216 rname, cname)) {
217 ConsoleDebug (WINLIST, "Dont show\n");
218 in_dontshowlist = 1;
219 break;
223 if (!in_dontshowlist) {
224 if (man->show.list == NULL) {
225 in_showlist = 1;
227 else {
228 for (string = man->show.list; string; string = string->next) {
229 ConsoleDebug (WINLIST, "Matching: %s\n", string->string);
230 if (matches_string (string->type, string->string, tname, iname,
231 rname, cname)) {
232 ConsoleDebug (WINLIST, "Show\n");
233 in_showlist = 1;
234 break;
240 ConsoleDebug (WINLIST, "returning: %d %d %d\n", in_dontshowlist,
241 in_showlist, !in_dontshowlist && in_showlist);
243 return (!in_dontshowlist && in_showlist);
246 WinData *new_windata (void)
248 WinData *new = (WinData *)safemalloc (sizeof (WinData));
250 memset(new, 0, sizeof(WinData));
251 new->desknum = ULONG_MAX;
252 new->x = ULONG_MAX;
253 new->y = ULONG_MAX;
254 new->app_id = ULONG_MAX;
256 return new;
259 void free_windata (WinData *p)
261 if (globals.select_win == p) {
262 ConsoleMessage ("Internal error in free_windata\n");
263 globals.select_win = NULL;
264 abort();
267 Free (p->resname);
268 Free (p->classname);
269 Free (p->iconname);
270 Free (p->titlename);
271 Free (p->display_string);
272 Free (p);
276 /* This ALWAYS gets called when one of the name strings changes */
278 WinManager *figure_win_manager (WinData *win, Uchar name_mask)
280 int i;
281 char *tname = win->titlename;
282 char *iname = win->iconname;
283 char *rname = win->resname;
284 char *cname = win->classname;
285 WinManager *man;
287 assert (tname || iname || rname || cname);
288 ConsoleDebug (WINLIST, "set_win_manager: %s %s %s %s\n", tname, iname, rname, cname);
290 for (i = 0, man = &globals.managers[0]; i < globals.num_managers;
291 i++, man++) {
292 if (iconmanager_show (man, tname, iname, rname, cname) &&
293 check_resolution(man, win)) {
294 if (man != win->manager) {
295 assert (man->magic == 0x12344321);
297 return man;
301 /* No manager wants this window */
302 return NULL;
305 int check_win_complete (WinData *p)
307 if (p->complete)
308 return 1;
310 ConsoleDebug (WINLIST, "Checking completeness:\n");
311 ConsoleDebug (WINLIST, "\ttitlename: %s\n",
312 (p->titlename ? p->titlename : "No Title name"));
313 ConsoleDebug (WINLIST, "\ticonname: %s\n",
314 (p->iconname ? p->iconname : "No Icon name"));
315 ConsoleDebug (WINLIST, "\tres: %s\n",
316 (p->resname ? p->resname : "No p->resname"));
317 ConsoleDebug (WINLIST, "\tclass: %s\n",
318 (p->classname ? p->classname : "No p->classname"));
319 ConsoleDebug (WINLIST, "\tdisplaystring: %s\n",
320 (p->display_string ? p->display_string :
321 "No p->display_string"));
322 ConsoleDebug (WINLIST, "\t(x, y): (%ld, %ld)\n", p->x, p->y);
323 ConsoleDebug (WINLIST, "\tapp_id: 0x%lx %d\n", p->app_id, p->app_id_set);
324 ConsoleDebug (WINLIST, "\tdesknum: %ld\n", p->desknum);
325 ConsoleDebug (WINLIST, "\tmanager: 0x%lx\n", (unsigned long)p->manager);
327 if (p->geometry_set &&
328 p->resname &&
329 p->classname &&
330 p->iconname &&
331 p->titlename &&
332 p->app_id_set) {
333 p->complete = 1;
334 ConsoleDebug (WINLIST, "\tcomplete: 1\n\n");
335 return 1;
338 ConsoleDebug (WINLIST, "\tcomplete: 0\n\n");
339 return 0;
342 void init_winlists (void)
344 int i;
345 for (i = 0; i < HASHTAB_SIZE; i++) {
346 hash_tab[i].n = 0;
347 hash_tab[i].head = NULL;
348 hash_tab[i].tail = NULL;
352 void delete_win_hashtab (WinData *win)
354 int entry;
355 WinList *list;
357 entry = win->app_id & 0xff;
358 list = &hash_tab[entry];
360 if (win->win_prev)
361 win->win_prev->win_next = win->win_next;
362 else
363 list->head = win->win_next;
364 if (win->win_next)
365 win->win_next->win_prev = win->win_prev;
366 else
367 list->tail = win->win_prev;
368 list->n--;
371 void insert_win_hashtab (WinData *win)
373 int entry;
374 WinList *list;
375 WinData *p;
377 entry = win->app_id & 0xff;
378 list = &hash_tab[entry];
380 for (p = list->head; p && win->app_id > p->app_id;
381 p = p->win_next);
383 if (p) {
384 /* insert win before p */
385 win->win_next = p;
386 win->win_prev = p->win_prev;
387 if (p->win_prev)
388 p->win_prev->win_next = win;
389 else
390 list->head = win;
391 p->win_prev = win;
393 else {
394 /* put win at end of list */
395 win->win_next = NULL;
396 win->win_prev = list->tail;
397 if (list->tail)
398 list->tail->win_next = win;
399 else
400 list->head = win;
401 list->tail = win;
403 list->n++;
406 WinData *find_win_hashtab (Ulong id)
408 WinList *list;
409 int entry = id & 0xff;
410 WinData *p;
412 list = &hash_tab[entry];
414 for (p = list->head; p && p->app_id != id; p = p->win_next);
416 return p;
419 void walk_hashtab (void (*func)(void *))
421 int i;
422 WinData *p;
424 for (i = 0; i < HASHTAB_SIZE; i++) {
425 for (p = hash_tab[i].head; p; p = p->win_next)
426 func (p);
430 int accumulate_walk_hashtab (int (*func)(void *))
432 int i, ret = 0;
433 WinData *p;
435 for (i = 0; i < HASHTAB_SIZE; i++) {
436 for (p = hash_tab[i].head; p; p = p->win_next)
437 ret += func (p);
440 return ret;