SOme fixes, and added WMGetDefaultsFromPath().
[wmaker-crm.git] / WINGs / userdefaults.c
blob1d0a5bc4a21e3443021928b70522d6f2afe33a9c
2 #include <stdlib.h>
3 #include <strings.h>
4 #include <stdio.h>
5 #include <assert.h>
8 #include "../src/config.h"
10 #include "WUtil.h"
12 #include <proplist.h>
15 typedef struct W_UserDefaults {
16 proplist_t defaults;
18 proplist_t appDomain;
20 proplist_t searchListArray;
21 proplist_t *searchList; /* cache for searchListArray */
23 char dirty;
25 char *path; /* where is db located */
27 struct W_UserDefaults *next;
29 } UserDefaults;
32 static UserDefaults *sharedUserDefaults = NULL;
33 static UserDefaults **sharedDefaultsList = NULL;
34 static Bool registeredSaveOnExit = False;
37 extern char *WMGetApplicationName();
39 #define DEFAULTS_DIR "/Defaults"
42 char*
43 wusergnusteppath()
45 static char *path = NULL;
46 char *gspath;
47 int pathlen;
49 if (!path) {
50 gspath = getenv("GNUSTEP_USER_ROOT");
51 if (gspath) {
52 gspath = wexpandpath(gspath);
53 pathlen = strlen(gspath) + 4;
54 path = wmalloc(pathlen);
55 strcpy(path, gspath);
56 free(gspath);
57 } else {
58 pathlen = strlen(wgethomedir()) + 10;
59 path = wmalloc(pathlen);
60 strcpy(path, wgethomedir());
61 strcat(path, "/GNUstep");
65 return path;
69 char*
70 wdefaultspathfordomain(char *domain)
72 char *path;
73 char *gspath;
75 gspath = wusergnusteppath();
76 path = wmalloc(strlen(gspath)+strlen(DEFAULTS_DIR)+strlen(domain)+4);
77 strcpy(path, gspath);
78 strcat(path, DEFAULTS_DIR);
79 strcat(path, "/");
80 strcat(path, domain);
82 return path;
86 static void
87 #ifndef HAVE_ATEXIT
88 saveDefaultsChanges(int foo, void *bar)
89 #else
90 saveDefaultsChanges(void)
91 #endif
93 /* save the user defaults database */
94 if (sharedUserDefaults && sharedUserDefaults->dirty) {
95 PLSave(sharedUserDefaults->appDomain, YES);
98 /* now save the extra defaults databases we may have */
99 if (sharedDefaultsList) {
100 UserDefaults *tmp = *sharedDefaultsList;
102 while (tmp) {
103 if (tmp->dirty)
104 PLSave(tmp->appDomain, YES);
105 tmp = tmp->next;
111 /* set to save changes in defaults when program is exited */
112 static void
113 registerSaveOnExit(void)
115 if (!registeredSaveOnExit) {
116 #ifndef HAVE_ATEXIT
117 on_exit(saveDefaultsChanges, (void*)NULL);
118 #else
119 atexit(saveDefaultsChanges);
120 #endif
121 registeredSaveOnExit = True;
126 void
127 WMSynchronizeUserDefaults(WMUserDefaults *database)
129 /* TODO: check what it should really do */
130 PLSave(database->appDomain, YES);
134 WMUserDefaults*
135 WMGetStandardUserDefaults(void)
137 if (!sharedUserDefaults) {
138 WMUserDefaults *defaults;
140 proplist_t domain;
141 proplist_t key;
142 char *path;
143 int i;
145 defaults = wmalloc(sizeof(WMUserDefaults));
146 memset(defaults, 0, sizeof(WMUserDefaults));
148 defaults->defaults = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
150 defaults->searchList = wmalloc(sizeof(proplist_t)*3);
152 /* application domain */
153 key = PLMakeString(WMGetApplicationName());
154 defaults->searchList[0] = key;
156 /* temporary kluge */
157 if (strcmp(WMGetApplicationName(), "WindowMaker")==0) {
158 domain = NULL;
159 path = NULL;
160 } else {
161 path = wdefaultspathfordomain(PLGetString(key));
163 domain = PLGetProplistWithPath(path);
165 if (!domain) {
166 proplist_t p;
168 domain = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
169 if (path) {
170 p = PLMakeString(path);
171 PLSetFilename(domain, p);
172 PLRelease(p);
175 if (path)
176 free(path);
178 defaults->appDomain = domain;
180 if (domain)
181 PLInsertDictionaryEntry(defaults->defaults, key, domain);
183 PLRelease(key);
185 /* global domain */
186 key = PLMakeString("WMGLOBAL");
187 defaults->searchList[1] = key;
189 path = wdefaultspathfordomain(PLGetString(key));
191 domain = PLGetProplistWithPath(path);
193 free(path);
195 if (!domain)
196 domain = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
198 if (domain)
199 PLInsertDictionaryEntry(defaults->defaults, key, domain);
201 PLRelease(key);
203 /* terminate list */
204 defaults->searchList[2] = NULL;
206 defaults->searchListArray=PLMakeArrayFromElements(NULL,NULL);
209 i = 0;
210 while (defaults->searchList[i]) {
211 PLAppendArrayElement(defaults->searchListArray,
212 defaults->searchList[i]);
213 i++;
216 sharedUserDefaults = defaults;
218 registerSaveOnExit();
222 return sharedUserDefaults;
226 WMUserDefaults*
227 WMGetDefaultsFromPath(char *path)
229 WMUserDefaults *defaults;
230 proplist_t domain;
231 proplist_t key;
232 char *name;
233 int i;
235 assert(path != NULL);
237 if (sharedDefaultsList) {
238 defaults = *sharedDefaultsList;
239 while (defaults) {
240 if (strcmp(defaults->path, path) == 0)
241 return defaults;
242 defaults = defaults->next;
246 /* we didn't found the database we are looking for. Go read it. */
247 defaults = wmalloc(sizeof(WMUserDefaults));
248 memset(defaults, 0, sizeof(WMUserDefaults));
250 defaults->defaults = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
252 defaults->searchList = wmalloc(sizeof(proplist_t)*2);
254 /* the domain we want go first */
255 name = strrchr(path, '/');
256 if (!name)
257 name = path;
258 else
259 name++;
260 key = PLMakeString(name);
261 defaults->searchList[0] = key;
263 domain = PLGetProplistWithPath(path);
265 if (!domain) {
266 proplist_t p;
268 domain = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
269 p = PLMakeString(path);
270 PLSetFilename(domain, p);
271 PLRelease(p);
274 defaults->path = wstrdup(path);
276 defaults->appDomain = domain;
278 if (domain)
279 PLInsertDictionaryEntry(defaults->defaults, key, domain);
281 PLRelease(key);
283 /* terminate list */
284 defaults->searchList[1] = NULL;
286 defaults->searchListArray=PLMakeArrayFromElements(NULL,NULL);
288 i = 0;
289 while (defaults->searchList[i]) {
290 PLAppendArrayElement(defaults->searchListArray,
291 defaults->searchList[i]);
292 i++;
295 if (sharedDefaultsList)
296 defaults->next = *sharedDefaultsList;
297 sharedDefaultsList = &defaults;
299 registerSaveOnExit();
301 name = PLGetDescriptionIndent(defaults->defaults, 0);
302 puts(name);
303 free(name);
305 return defaults;
309 proplist_t
310 WMGetUDObjectForKey(WMUserDefaults *database, char *defaultName)
312 proplist_t domainName, domain;
313 proplist_t object = NULL;
314 proplist_t key = PLMakeString(defaultName);
315 int i = 0;
317 while (database->searchList[i] && !object) {
318 domainName = database->searchList[i];
319 domain = PLGetDictionaryEntry(database->defaults, domainName);
320 if (domain) {
321 object = PLGetDictionaryEntry(domain, key);
323 i++;
325 PLRelease(key);
327 return object;
331 void
332 WMSetUDObjectForKey(WMUserDefaults *database, proplist_t object,
333 char *defaultName)
335 proplist_t key = PLMakeString(defaultName);
337 database->dirty = 1;
339 PLInsertDictionaryEntry(database->appDomain, key, object);
340 PLRelease(key);
344 void
345 WMRemoveUDObjectForKey(WMUserDefaults *database, char *defaultName)
347 proplist_t key = PLMakeString(defaultName);
349 database->dirty = 1;
351 PLRemoveDictionaryEntry(database->appDomain, key);
353 PLRelease(key);
357 char*
358 WMGetUDStringForKey(WMUserDefaults *database, char *defaultName)
360 proplist_t val;
362 val = WMGetUDObjectForKey(database, defaultName);
364 if (!val)
365 return NULL;
367 if (!PLIsString(val))
368 return NULL;
370 return wstrdup(PLGetString(val));
375 WMGetUDIntegerForKey(WMUserDefaults *database, char *defaultName)
377 proplist_t val;
378 char *str;
379 int value;
381 val = WMGetUDObjectForKey(database, defaultName);
383 if (!val)
384 return 0;
386 if (!PLIsString(val))
387 return 0;
389 str = PLGetString(val);
390 if (!str)
391 return 0;
393 if (sscanf(str, "%i", &value)!=1)
394 return 0;
396 return value;
401 float
402 WMGetUDFloatForKey(WMUserDefaults *database, char *defaultName)
404 proplist_t val;
405 char *str;
406 float value;
408 val = WMGetUDObjectForKey(database, defaultName);
410 if (!val || !PLIsString(val))
411 return 0.0;
413 if (!(str = PLGetString(val)))
414 return 0.0;
416 if (sscanf(str, "%f", &value)!=1)
417 return 0.0;
419 return value;
424 Bool
425 WMGetUDBoolForKey(WMUserDefaults *database, char *defaultName)
427 proplist_t val;
428 int value;
429 char *str;
431 val = WMGetUDObjectForKey(database, defaultName);
433 if (!val)
434 return False;
436 if (!PLIsString(val))
437 return False;
439 str = PLGetString(val);
440 if (!str)
441 return False;
443 if (sscanf(str, "%i", &value)==1 && value!=0)
444 return True;
446 if (strcasecmp(str, "YES")==0)
447 return True;
449 if (strcasecmp(str, "Y")==0)
450 return True;
452 return False;
456 void
457 WMSetUDIntegerForKey(WMUserDefaults *database, int value, char *defaultName)
459 proplist_t object;
460 char buffer[128];
462 sprintf(buffer, "%i", value);
463 object = PLMakeString(buffer);
465 WMSetUDObjectForKey(database, object, defaultName);
466 PLRelease(object);
472 void
473 WMSetUDStringForKey(WMUserDefaults *database, char *value, char *defaultName)
475 proplist_t object;
477 object = PLMakeString(value);
479 WMSetUDObjectForKey(database, object, defaultName);
480 PLRelease(object);
485 void
486 WMSetUDFloatForKey(WMUserDefaults *database, float value, char *defaultName)
488 proplist_t object;
489 char buffer[128];
491 sprintf(buffer, "%f", value);
492 object = PLMakeString(buffer);
494 WMSetUDObjectForKey(database, object, defaultName);
495 PLRelease(object);
500 void
501 WMSetUDBoolForKey(WMUserDefaults *database, Bool value, char *defaultName)
503 static proplist_t yes = NULL, no = NULL;
505 if (!yes) {
506 yes = PLMakeString("YES");
507 no = PLMakeString("NO");
510 WMSetUDObjectForKey(database, value ? yes : no, defaultName);
514 proplist_t
515 WMGetUDSearchList(WMUserDefaults *database)
517 return database->searchListArray;
521 void
522 WMSetUDSearchList(WMUserDefaults *database, proplist_t list)
524 int i, c;
526 if (database->searchList) {
527 i = 0;
528 while (database->searchList[i]) {
529 PLRelease(database->searchList[i]);
530 i++;
532 free(database->searchList);
534 if (database->searchListArray) {
535 PLRelease(database->searchListArray);
538 c = PLGetNumberOfElements(list);
539 database->searchList = wmalloc(sizeof(proplist_t)*(c+1));
541 for (i=0; i<c; i++) {
542 database->searchList[i] = PLGetArrayElement(list, i);
545 database->searchListArray = PLDeepCopy(list);