fixed memory leaks and crash with deminiaturization
[wmaker-crm.git] / src / wdefaults.c
blob047aa7343a30f0a2388457b089101c6e73f87414
1 /* wdefaults.c - window specific defaults
2 *
3 * Window Maker window manager
4 *
5 * Copyright (c) 1997, 1998 Alfredo K. Kojima
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20 * USA.
23 #include "wconfig.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <ctype.h>
31 #include <X11/Xlib.h>
32 #include <X11/Xutil.h>
33 #include <X11/keysym.h>
35 #include <wraster.h>
38 #include "WindowMaker.h"
39 #include "window.h"
40 #include "screen.h"
41 #include "funcs.h"
42 #include "workspace.h"
43 #include "defaults.h"
44 #include "icon.h"
47 /* Global stuff */
49 extern WPreferences wPreferences;
51 extern proplist_t wAttributeDomainName;
53 extern WDDomain *WDWindowAttributes;
56 /* Local stuff */
59 /* type converters */
60 static int getBool(proplist_t, proplist_t);
62 static char* getString(proplist_t, proplist_t);
65 static proplist_t ANoTitlebar = NULL;
66 static proplist_t ANoResizebar;
67 static proplist_t ANoMiniaturizeButton;
68 static proplist_t ANoCloseButton;
69 static proplist_t ANoBorder;
70 static proplist_t ANoHideOthers;
71 static proplist_t ANoMouseBindings;
72 static proplist_t ANoKeyBindings;
73 static proplist_t ANoAppIcon; /* app */
74 static proplist_t AKeepOnTop;
75 static proplist_t AKeepOnBottom;
76 static proplist_t AOmnipresent;
77 static proplist_t ASkipWindowList;
78 static proplist_t AKeepInsideScreen;
79 static proplist_t AUnfocusable;
80 static proplist_t AAlwaysUserIcon;
81 static proplist_t AStartMiniaturized;
82 static proplist_t AStartMaximized;
83 static proplist_t AStartHidden; /* app */
84 static proplist_t ADontSaveSession; /* app */
85 static proplist_t AEmulateAppIcon;
86 static proplist_t AFullMaximize;
87 #ifdef XKB_BUTTON_HINT
88 static proplist_t ANoLanguageButton;
89 #endif
91 static proplist_t AStartWorkspace;
93 static proplist_t AIcon;
96 static proplist_t AnyWindow;
97 static proplist_t No;
100 static void
101 init_wdefaults(WScreen *scr)
103 AIcon = PLMakeString("Icon");
105 ANoTitlebar = PLMakeString("NoTitlebar");
106 ANoResizebar = PLMakeString("NoResizebar");
107 ANoMiniaturizeButton = PLMakeString("NoMiniaturizeButton");
108 ANoCloseButton = PLMakeString("NoCloseButton");
109 ANoBorder = PLMakeString("NoBorder");
110 ANoHideOthers = PLMakeString("NoHideOthers");
111 ANoMouseBindings = PLMakeString("NoMouseBindings");
112 ANoKeyBindings = PLMakeString("NoKeyBindings");
113 ANoAppIcon = PLMakeString("NoAppIcon");
114 AKeepOnTop = PLMakeString("KeepOnTop");
115 AKeepOnBottom = PLMakeString("KeepOnBottom");
116 AOmnipresent = PLMakeString("Omnipresent");
117 ASkipWindowList = PLMakeString("SkipWindowList");
118 AKeepInsideScreen = PLMakeString("KeepInsideScreen");
119 AUnfocusable = PLMakeString("Unfocusable");
120 AAlwaysUserIcon = PLMakeString("AlwaysUserIcon");
121 AStartMiniaturized = PLMakeString("StartMiniaturized");
122 AStartHidden = PLMakeString("StartHidden");
123 AStartMaximized = PLMakeString("StartMaximized");
124 ADontSaveSession = PLMakeString("DontSaveSession");
125 AEmulateAppIcon = PLMakeString("EmulateAppIcon");
126 AFullMaximize = PLMakeString("FullMaximize");
127 #ifdef XKB_BUTTON_HINT
128 ANoLanguageButton = PLMakeString("NoLanguageButton");
129 #endif
131 AStartWorkspace = PLMakeString("StartWorkspace");
133 AnyWindow = PLMakeString("*");
134 No = PLMakeString("No");
136 if (!scr->wattribs) {
137 scr->wattribs = PLGetDomain(wAttributeDomainName);
143 static proplist_t
144 get_value(proplist_t dict_win, proplist_t dict_class, proplist_t dict_name,
145 proplist_t dict_any, proplist_t option, proplist_t default_value,
146 Bool useGlobalDefault)
148 proplist_t value;
151 if (dict_win) {
152 value = PLGetDictionaryEntry(dict_win, option);
153 if (value)
154 return value;
157 if (dict_name) {
158 value = PLGetDictionaryEntry(dict_name, option);
159 if (value)
160 return value;
163 if (dict_class) {
164 value = PLGetDictionaryEntry(dict_class, option);
165 if (value)
166 return value;
169 if (!useGlobalDefault)
170 return NULL;
172 if (dict_any) {
173 value = PLGetDictionaryEntry(dict_any, option);
174 if (value)
175 return value;
178 return default_value;
183 *----------------------------------------------------------------------
184 * wDefaultFillAttributes--
185 * Retrieves attributes for the specified instance/class and
186 * fills attr with it. Values that are actually defined are also
187 * set in mask. If useGlobalDefault is True, the default for
188 * all windows ("*") will be used for when no values are found
189 * for that instance/class.
191 *----------------------------------------------------------------------
193 void
194 wDefaultFillAttributes(WScreen *scr, char *instance, char *class,
195 WWindowAttributes *attr,
196 WWindowAttributes *mask,
197 Bool useGlobalDefault)
199 proplist_t value;
200 proplist_t key1, key2, key3;
201 proplist_t dw, dc, dn, da;
204 if (class && instance) {
205 char *buffer = NULL;
206 buffer = wmalloc(strlen(class)+strlen(instance)+4);
207 key1 = PLMakeString(strcat(strcat(strcpy(buffer,instance),"."),class));
208 free(buffer);
209 } else
210 key1 = NULL;
212 if (instance)
213 key2 = PLMakeString(instance);
214 else
215 key2 = NULL;
217 if (class)
218 key3 = PLMakeString(class);
219 else
220 key3 = NULL;
222 if (!ANoTitlebar) {
223 init_wdefaults(scr);
226 PLSetStringCmpHook(NULL);
228 if (WDWindowAttributes->dictionary) {
229 dw = key1 ? PLGetDictionaryEntry(WDWindowAttributes->dictionary, key1) : NULL;
230 dn = key2 ? PLGetDictionaryEntry(WDWindowAttributes->dictionary, key2) : NULL;
231 dc = key3 ? PLGetDictionaryEntry(WDWindowAttributes->dictionary, key3) : NULL;
232 if (useGlobalDefault)
233 da = PLGetDictionaryEntry(WDWindowAttributes->dictionary, AnyWindow);
234 else
235 da = NULL;
236 } else {
237 dw = NULL;
238 dn = NULL;
239 dc = NULL;
240 da = NULL;
242 if (key1)
243 PLRelease(key1);
244 if (key2)
245 PLRelease(key2);
246 if (key3)
247 PLRelease(key3);
249 #define APPLY_VAL(value, flag, attrib) \
250 if (value) {attr->flag = getBool(attrib, value); \
251 if (mask) mask->flag = 1;}
253 /* get the data */
254 value = get_value(dw, dc, dn, da, ANoTitlebar, No, useGlobalDefault);
255 APPLY_VAL(value, no_titlebar, ANoTitlebar);
257 value = get_value(dw, dc, dn, da, ANoResizebar, No, useGlobalDefault);
258 APPLY_VAL(value, no_resizebar, ANoResizebar);
260 value = get_value(dw, dc, dn, da, ANoMiniaturizeButton, No, useGlobalDefault);
261 APPLY_VAL(value, no_miniaturize_button, ANoMiniaturizeButton);
263 value = get_value(dw, dc, dn, da, ANoCloseButton, No, useGlobalDefault);
264 APPLY_VAL(value, no_close_button, ANoCloseButton);
266 value = get_value(dw, dc, dn, da, ANoBorder, No, useGlobalDefault);
267 APPLY_VAL(value, no_border, ANoBorder);
269 value = get_value(dw, dc, dn, da, ANoHideOthers, No, useGlobalDefault);
270 APPLY_VAL(value, no_hide_others, ANoHideOthers);
272 value = get_value(dw, dc, dn, da, ANoMouseBindings, No, useGlobalDefault);
273 APPLY_VAL(value, no_bind_mouse, ANoMouseBindings);
275 value = get_value(dw, dc, dn, da, ANoKeyBindings, No, useGlobalDefault);
276 APPLY_VAL(value, no_bind_keys, ANoKeyBindings);
278 value = get_value(dw, dc, dn, da, ANoAppIcon, No, useGlobalDefault);
279 APPLY_VAL(value, no_appicon, ANoAppIcon);
281 value = get_value(dw, dc, dn, da, AKeepOnTop, No, useGlobalDefault);
282 APPLY_VAL(value, floating, AKeepOnTop);
284 value = get_value(dw, dc, dn, da, AKeepOnBottom, No, useGlobalDefault);
285 APPLY_VAL(value, sunken, AKeepOnBottom);
287 value = get_value(dw, dc, dn, da, AOmnipresent, No, useGlobalDefault);
288 APPLY_VAL(value, omnipresent, AOmnipresent);
290 value = get_value(dw, dc, dn, da, ASkipWindowList, No, useGlobalDefault);
291 APPLY_VAL(value, skip_window_list, ASkipWindowList);
293 value = get_value(dw, dc, dn, da, AKeepInsideScreen, No, useGlobalDefault);
294 APPLY_VAL(value, dont_move_off, AKeepInsideScreen);
296 value = get_value(dw, dc, dn, da, AUnfocusable, No, useGlobalDefault);
297 APPLY_VAL(value, no_focusable, AUnfocusable);
299 value = get_value(dw, dc, dn, da, AAlwaysUserIcon, No, useGlobalDefault);
300 APPLY_VAL(value, always_user_icon, AAlwaysUserIcon);
302 value = get_value(dw, dc, dn, da, AStartMiniaturized, No, useGlobalDefault);
303 APPLY_VAL(value, start_miniaturized, AStartMiniaturized);
305 value = get_value(dw, dc, dn, da, AStartHidden, No, useGlobalDefault);
306 APPLY_VAL(value, start_hidden, AStartHidden);
308 value = get_value(dw, dc, dn, da, AStartMaximized, No, useGlobalDefault);
309 APPLY_VAL(value, start_maximized, AStartMaximized);
311 value = get_value(dw, dc, dn, da, ADontSaveSession, No, useGlobalDefault);
312 APPLY_VAL(value, dont_save_session, ADontSaveSession);
314 value = get_value(dw, dc, dn, da, AEmulateAppIcon, No, useGlobalDefault);
315 APPLY_VAL(value, emulate_appicon, AEmulateAppIcon);
317 value = get_value(dw, dc, dn, da, AFullMaximize, No, useGlobalDefault);
318 APPLY_VAL(value, full_maximize, AFullMaximize);
320 #ifdef XKB_BUTTON_HINT
321 value = get_value(dw, dc, dn, da, ANoLanguageButton, No, useGlobalDefault);
322 APPLY_VAL(value, no_language_button, ANoLanguageButton);
323 #endif
325 /* clean up */
326 PLSetStringCmpHook(StringCompareHook);
331 proplist_t
332 get_generic_value(WScreen *scr, char *instance, char *class, proplist_t option,
333 Bool noDefault)
335 proplist_t value, key, dict;
337 value = NULL;
339 PLSetStringCmpHook(NULL);
341 if (class && instance) {
342 char *buffer = NULL;
343 buffer = wmalloc(strlen(class)+strlen(instance)+4);
344 key = PLMakeString(strcat(strcat(strcpy(buffer,instance),"."),class));
346 dict = PLGetDictionaryEntry(WDWindowAttributes->dictionary, key);
347 PLRelease(key);
348 free(buffer);
350 if (dict) {
351 value = PLGetDictionaryEntry(dict, option);
355 if (!value && instance) {
356 key = PLMakeString(instance);
358 dict = PLGetDictionaryEntry(WDWindowAttributes->dictionary, key);
359 PLRelease(key);
360 if (dict) {
361 value = PLGetDictionaryEntry(dict, option);
365 if (!value && class) {
366 key = PLMakeString(class);
368 dict = PLGetDictionaryEntry(WDWindowAttributes->dictionary, key);
369 PLRelease(key);
371 if (dict) {
372 value = PLGetDictionaryEntry(dict, option);
376 if (!value && !noDefault) {
377 dict = PLGetDictionaryEntry(WDWindowAttributes->dictionary, AnyWindow);
379 if (dict) {
380 value = PLGetDictionaryEntry(dict, option);
384 PLSetStringCmpHook(StringCompareHook);
386 return value;
390 char*
391 wDefaultGetIconFile(WScreen *scr, char *instance, char *class,
392 Bool noDefault)
394 proplist_t value;
395 char *tmp;
397 if (!ANoTitlebar) {
398 init_wdefaults(scr);
401 if (!WDWindowAttributes->dictionary)
402 return NULL;
404 value = get_generic_value(scr, instance, class, AIcon, noDefault);
406 if (!value)
407 return NULL;
409 tmp = getString(AIcon, value);
411 return tmp;
415 RImage*
416 wDefaultGetImage(WScreen *scr, char *winstance, char *wclass)
418 char *file_name;
419 char *path;
420 RImage *image;
422 file_name = wDefaultGetIconFile(scr, winstance, wclass, False);
423 if (!file_name)
424 return NULL;
426 path = FindImage(wPreferences.icon_path, file_name);
428 if (!path) {
429 wwarning(_("could not find icon file \"%s\""), file_name);
430 return NULL;
433 image = RLoadImage(scr->rcontext, path, 0);
434 if (!image) {
435 wwarning(_("error loading image file \"%s\""), path, RMessageForError(RErrorCode));
437 free(path);
439 image = wIconValidateIconSize(scr, image);
441 return image;
446 wDefaultGetStartWorkspace(WScreen *scr, char *instance, char *class)
448 proplist_t value;
449 int w, i;
450 char *tmp;
452 if (!ANoTitlebar) {
453 init_wdefaults(scr);
456 if (!WDWindowAttributes->dictionary)
457 return -1;
459 value = get_generic_value(scr, instance, class, AStartWorkspace,
460 False);
462 if (!value)
463 return -1;
465 tmp = getString(AStartWorkspace, value);
467 if (!tmp || strlen(tmp)==0)
468 return -1;
470 if (sscanf(tmp, "%i", &w)!=1) {
471 w = -1;
472 for (i=0; i < scr->workspace_count; i++) {
473 if (strcmp(scr->workspaces[i]->name, tmp)==0) {
474 w = i;
475 break;
478 } else {
479 w--;
482 return w;
486 void
487 wDefaultChangeIcon(WScreen *scr, char *instance, char* class, char *file)
489 WDDomain *db = WDWindowAttributes;
490 proplist_t icon_value=NULL, value, attr, key, def_win, def_icon=NULL;
491 proplist_t dict = db->dictionary;
492 int same = 0;
494 if (!dict) {
495 dict = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
496 if (dict) {
497 db->dictionary = dict;
498 value = PLMakeString(db->path);
499 PLSetFilename(dict, value);
500 PLRelease(value);
502 else
503 return;
506 PLSetStringCmpHook(NULL);
508 if (instance && class) {
509 char *buffer;
510 buffer = wmalloc(strlen(instance) + strlen(class) + 2);
511 strcat(strcat(strcpy(buffer, instance), "."), class);
512 key = PLMakeString(buffer);
513 free(buffer);
514 } else if (instance) {
515 key = PLMakeString(instance);
516 } else if (class) {
517 key = PLMakeString(class);
518 } else {
519 key = PLRetain(AnyWindow);
522 if (file) {
523 value = PLMakeString(file);
524 icon_value = PLMakeDictionaryFromEntries(AIcon, value, NULL);
525 PLRelease(value);
527 if ((def_win = PLGetDictionaryEntry(dict, AnyWindow)) != NULL) {
528 def_icon = PLGetDictionaryEntry(def_win, AIcon);
531 if (def_icon && !strcmp(PLGetString(def_icon), file))
532 same = 1;
535 if ((attr = PLGetDictionaryEntry(dict, key)) != NULL) {
536 if (PLIsDictionary(attr)) {
537 if (icon_value!=NULL && !same)
538 PLMergeDictionaries(attr, icon_value);
539 else
540 PLRemoveDictionaryEntry(attr, AIcon);
542 } else if (icon_value!=NULL && !same) {
543 PLInsertDictionaryEntry(dict, key, icon_value);
545 if (!wPreferences.flags.noupdates)
546 PLSave(dict, YES);
548 PLRelease(key);
549 if(icon_value)
550 PLRelease(icon_value);
552 PLSetStringCmpHook(StringCompareHook);
557 /* --------------------------- Local ----------------------- */
559 static int
560 getBool(proplist_t key, proplist_t value)
562 char *val;
564 if (!PLIsString(value)) {
565 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
566 PLGetString(key), "Boolean");
567 return 0;
569 val = PLGetString(value);
571 if ((val[1]=='\0' && (val[0]=='y' || val[0]=='Y' || val[0]=='T'
572 || val[0]=='t' || val[0]=='1'))
573 || (strcasecmp(val, "YES")==0 || strcasecmp(val, "TRUE")==0)) {
575 return 1;
576 } else if ((val[1]=='\0'
577 && (val[0]=='n' || val[0]=='N' || val[0]=='F'
578 || val[0]=='f' || val[0]=='0'))
579 || (strcasecmp(val, "NO")==0 || strcasecmp(val, "FALSE")==0)) {
581 return 0;
582 } else {
583 wwarning(_("can't convert \"%s\" to boolean"), val);
584 /* We return False if we can't convert to BOOLEAN.
585 * This is because all options defaults to False.
586 * -1 is not checked and thus is interpreted as True,
587 * which is not good.*/
588 return 0;
595 * WARNING: Do not free value returned by this!!
597 static char*
598 getString(proplist_t key, proplist_t value)
600 if (!PLIsString(value)) {
601 wwarning(_("Wrong option format for key \"%s\". Should be %s."),
602 PLGetString(key), "String");
603 return NULL;
606 return PLGetString(value);