/* -*-c-*- */ /* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #include "libs/wild.h" #include "FvwmIconMan.h" #define HASHTAB_SIZE 257 typedef WinList HashTab[HASHTAB_SIZE]; static HashTab hash_tab; void print_stringlist (StringList *list) { StringEl *p; char *s; ConsoleDebug (WINLIST, "\tmask = 0x%x\n", list->mask); for (p = list->list; p; p = p->next) { switch (p->type) { case ALL_NAME: s = "all"; break; case TITLE_NAME: s = "title"; break; case ICON_NAME: s = "icon"; break; case RESOURCE_NAME: s = "resource"; break; case CLASS_NAME: s = "class"; break; default: s = "unknown type"; } ConsoleDebug (WINLIST, "\t%s = %s\n", s, p->string); } } void add_to_stringlist (StringList *list, char *s) { StringEl *new; NameType type; char *pat; ConsoleDebug (WINLIST, "In add_to_stringlist: %s\n", s); pat = strchr (s, '='); if (pat) { *pat++ = '\0'; if (!strcasecmp (s, "icon")) type = ICON_NAME; else if (!strcasecmp (s, "title")) type = TITLE_NAME; else if (!strcasecmp (s, "resource")) type = RESOURCE_NAME; else if (!strcasecmp (s, "class")) type = CLASS_NAME; else { ConsoleMessage ("Bad element in show/dontshow list: %s\n", s); return; } } else { pat = s; type = ALL_NAME; } ConsoleDebug (WINLIST, "add_to_stringlist: %s %s\n", type == ALL_NAME ? "all" : s, pat); new = (StringEl *)safemalloc (sizeof (StringEl)); new->string = (char *)safemalloc ((strlen (pat) + 1) * sizeof (char)); new->type = type; strcpy (new->string, pat); new->next = list->list; if (list->list) list->mask |= type; else list->mask = type; list->list = new; ConsoleDebug (WINLIST, "Exiting add_to_stringlist\n"); } static int matches_string (NameType type, char *pattern, char *tname, char *iname, char *rname, char *cname) { int ans = 0; ConsoleDebug (WINLIST, "matches_string: type: 0x%x pattern: %s\n", type, pattern); ConsoleDebug (WINLIST, "\tstrings: %s:%s %s:%s\n", tname, iname, rname, cname); if (tname && (type == ALL_NAME || type == TITLE_NAME)) { ans |= matchWildcards (pattern, tname); } if (iname && (type == ALL_NAME || type == ICON_NAME)) { ans |= matchWildcards (pattern, iname); } if (rname && (type == ALL_NAME || type == RESOURCE_NAME)) { ans |= matchWildcards (pattern, rname); } if (cname && (type == ALL_NAME || type == CLASS_NAME)) { ans |= matchWildcards (pattern, cname); } ConsoleDebug (WINLIST, "\tmatches_string: %d\n", ans); return ans; } int check_resolution(WinManager *manager, WinData *win) { int flag = 0; int reverse = 0; rectangle g; assert (manager); if (IS_ICONIFIED(win) && !IS_ICON_SUPPRESSED(win)) { g = win->icon_g; } else { g.x = win->x; g.y = win->y; g.width = win->width; g.height = win->height; } switch (manager->res) { case SHOW_GLOBAL: flag = 1; break; case NO_SHOW_DESKTOP: reverse = 1; /* fall through to next case */ case SHOW_DESKTOP: if (IS_STICKY_ACROSS_PAGES(win) || win->desknum == globals.desknum) flag = 1; break; case NO_SHOW_PAGE: reverse = 1; /* fall through to next case */ case SHOW_PAGE: if (IS_STICKY_ACROSS_PAGES(win)) { flag = 1; } else if (win->desknum == globals.desknum) { /* win and screen intersect if they are not disjoint in x and y */ flag = fvwmrect_do_rectangles_intersect(&g, &manager->managed_g); } break; case NO_SHOW_SCREEN: reverse = 1; /* fall through to next case */ case SHOW_SCREEN: if (win->desknum == globals.desknum) { /* win and screen intersect if they are not disjoint in x and y */ flag = fvwmrect_do_rectangles_intersect(&g, &manager->managed_g); } break; } flag ^= reverse; return flag; } static int iconmanager_show (WinManager *man, char *tname, char *iname, char *rname, char *cname) { StringEl *string; int in_showlist = 0, in_dontshowlist = 0; assert (man); #ifdef FVWM_DEBUG_MSGS ConsoleDebug (WINLIST, "In iconmanager_show: %s:%s : %s %s\n", tname, iname, rname, cname); ConsoleDebug (WINLIST, "dontshow:\n"); print_stringlist (&man->dontshow); ConsoleDebug (WINLIST, "show:\n"); print_stringlist (&man->show); #endif /* FVWM_DEBUG_MSGS */ for (string = man->dontshow.list; string; string = string->next) { ConsoleDebug (WINLIST, "Matching: %s\n", string->string); if (matches_string (string->type, string->string, tname, iname, rname, cname)) { ConsoleDebug (WINLIST, "Dont show\n"); in_dontshowlist = 1; break; } } if (!in_dontshowlist) { if (man->show.list == NULL) { in_showlist = 1; } else { for (string = man->show.list; string; string = string->next) { ConsoleDebug (WINLIST, "Matching: %s\n", string->string); if (matches_string (string->type, string->string, tname, iname, rname, cname)) { ConsoleDebug (WINLIST, "Show\n"); in_showlist = 1; break; } } } } ConsoleDebug (WINLIST, "returning: %d %d %d\n", in_dontshowlist, in_showlist, !in_dontshowlist && in_showlist); return (!in_dontshowlist && in_showlist); } WinData *new_windata (void) { WinData *new = (WinData *)safemalloc (sizeof (WinData)); memset(new, 0, sizeof(WinData)); new->desknum = ULONG_MAX; new->x = ULONG_MAX; new->y = ULONG_MAX; new->app_id = ULONG_MAX; return new; } void free_windata (WinData *p) { if (globals.select_win == p) { ConsoleMessage ("Internal error in free_windata\n"); globals.select_win = NULL; abort(); } Free (p->resname); Free (p->classname); Free (p->iconname); Free (p->titlename); Free (p->display_string); Free (p); } /* This ALWAYS gets called when one of the name strings changes */ WinManager *figure_win_manager (WinData *win, Uchar name_mask) { int i; char *tname = win->titlename; char *iname = win->iconname; char *rname = win->resname; char *cname = win->classname; WinManager *man; assert (tname || iname || rname || cname); ConsoleDebug (WINLIST, "set_win_manager: %s %s %s %s\n", tname, iname, rname, cname); for (i = 0, man = &globals.managers[0]; i < globals.num_managers; i++, man++) { if (iconmanager_show (man, tname, iname, rname, cname) && check_resolution(man, win)) { if (man != win->manager) { assert (man->magic == 0x12344321); } return man; } } /* No manager wants this window */ return NULL; } int check_win_complete (WinData *p) { if (p->complete) return 1; ConsoleDebug (WINLIST, "Checking completeness:\n"); ConsoleDebug (WINLIST, "\ttitlename: %s\n", (p->titlename ? p->titlename : "No Title name")); ConsoleDebug (WINLIST, "\ticonname: %s\n", (p->iconname ? p->iconname : "No Icon name")); ConsoleDebug (WINLIST, "\tres: %s\n", (p->resname ? p->resname : "No p->resname")); ConsoleDebug (WINLIST, "\tclass: %s\n", (p->classname ? p->classname : "No p->classname")); ConsoleDebug (WINLIST, "\tdisplaystring: %s\n", (p->display_string ? p->display_string : "No p->display_string")); ConsoleDebug (WINLIST, "\t(x, y): (%ld, %ld)\n", p->x, p->y); ConsoleDebug (WINLIST, "\tapp_id: 0x%lx %d\n", p->app_id, p->app_id_set); ConsoleDebug (WINLIST, "\tdesknum: %ld\n", p->desknum); ConsoleDebug (WINLIST, "\tmanager: 0x%lx\n", (unsigned long)p->manager); if (p->geometry_set && p->resname && p->classname && p->iconname && p->titlename && p->app_id_set) { p->complete = 1; ConsoleDebug (WINLIST, "\tcomplete: 1\n\n"); return 1; } ConsoleDebug (WINLIST, "\tcomplete: 0\n\n"); return 0; } void init_winlists (void) { int i; for (i = 0; i < HASHTAB_SIZE; i++) { hash_tab[i].n = 0; hash_tab[i].head = NULL; hash_tab[i].tail = NULL; } } void delete_win_hashtab (WinData *win) { int entry; WinList *list; entry = win->app_id & 0xff; list = &hash_tab[entry]; if (win->win_prev) win->win_prev->win_next = win->win_next; else list->head = win->win_next; if (win->win_next) win->win_next->win_prev = win->win_prev; else list->tail = win->win_prev; list->n--; } void insert_win_hashtab (WinData *win) { int entry; WinList *list; WinData *p; entry = win->app_id & 0xff; list = &hash_tab[entry]; for (p = list->head; p && win->app_id > p->app_id; p = p->win_next); if (p) { /* insert win before p */ win->win_next = p; win->win_prev = p->win_prev; if (p->win_prev) p->win_prev->win_next = win; else list->head = win; p->win_prev = win; } else { /* put win at end of list */ win->win_next = NULL; win->win_prev = list->tail; if (list->tail) list->tail->win_next = win; else list->head = win; list->tail = win; } list->n++; } WinData *find_win_hashtab (Ulong id) { WinList *list; int entry = id & 0xff; WinData *p; list = &hash_tab[entry]; for (p = list->head; p && p->app_id != id; p = p->win_next); return p; } void walk_hashtab (void (*func)(void *)) { int i; WinData *p; for (i = 0; i < HASHTAB_SIZE; i++) { for (p = hash_tab[i].head; p; p = p->win_next) func (p); } } int accumulate_walk_hashtab (int (*func)(void *)) { int i, ret = 0; WinData *p; for (i = 0; i < HASHTAB_SIZE; i++) { for (p = hash_tab[i].head; p; p = p->win_next) ret += func (p); } return ret; }