Fixed some problems with WMGetDefaultsFromPath().
[wmaker-crm.git] / WINGs / userdefaults.c
blob1f892eb67b879c3f4b5bf6c795e678f9b5a9d411
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;
34 static Bool registeredSaveOnExit = False;
38 extern char *WMGetApplicationName();
40 #define DEFAULTS_DIR "/Defaults"
43 char*
44 wusergnusteppath()
46 static char *path = NULL;
47 char *gspath;
48 int pathlen;
50 if (!path) {
51 gspath = getenv("GNUSTEP_USER_ROOT");
52 if (gspath) {
53 gspath = wexpandpath(gspath);
54 pathlen = strlen(gspath) + 4;
55 path = wmalloc(pathlen);
56 strcpy(path, gspath);
57 free(gspath);
58 } else {
59 pathlen = strlen(wgethomedir()) + 10;
60 path = wmalloc(pathlen);
61 strcpy(path, wgethomedir());
62 strcat(path, "/GNUstep");
66 return path;
70 char*
71 wdefaultspathfordomain(char *domain)
73 char *path;
74 char *gspath;
76 gspath = wusergnusteppath();
77 path = wmalloc(strlen(gspath)+strlen(DEFAULTS_DIR)+strlen(domain)+4);
78 strcpy(path, gspath);
79 strcat(path, DEFAULTS_DIR);
80 strcat(path, "/");
81 strcat(path, domain);
83 return path;
87 static void
88 #ifndef HAVE_ATEXIT
89 saveDefaultsChanges(int foo, void *bar)
90 #else
91 saveDefaultsChanges(void)
92 #endif
94 /* save the user defaults databases */
95 if (sharedUserDefaults) {
96 UserDefaults *tmp = sharedUserDefaults;
98 while (tmp) {
99 if (tmp->appDomain && tmp->dirty)
100 PLSave(tmp->appDomain, YES);
101 tmp = tmp->next;
107 /* set to save changes in defaults when program is exited */
108 static void
109 registerSaveOnExit(void)
111 if (!registeredSaveOnExit) {
112 #ifndef HAVE_ATEXIT
113 on_exit(saveDefaultsChanges, (void*)NULL);
114 #else
115 atexit(saveDefaultsChanges);
116 #endif
117 registeredSaveOnExit = True;
122 void
123 WMSynchronizeUserDefaults(WMUserDefaults *database)
125 /* TODO: check what it should really do */
126 PLSave(database->appDomain, YES);
130 WMUserDefaults*
131 WMGetStandardUserDefaults(void)
133 WMUserDefaults *defaults;
134 proplist_t domain;
135 proplist_t key;
136 char *path;
137 int i;
139 if (sharedUserDefaults) {
140 defaults = sharedUserDefaults;
141 while (defaults) {
142 /* Trick, path == NULL only for StandardUserDefaults db */
143 if (defaults->path == NULL)
144 return defaults;
145 defaults = defaults->next;
149 /* we didn't found the database we are looking for. Go read it. */
150 defaults = wmalloc(sizeof(WMUserDefaults));
151 memset(defaults, 0, sizeof(WMUserDefaults));
153 defaults->defaults = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
155 defaults->searchList = wmalloc(sizeof(proplist_t)*3);
157 /* application domain */
158 key = PLMakeString(WMGetApplicationName());
159 defaults->searchList[0] = key;
161 /* temporary kluge */
162 if (strcmp(WMGetApplicationName(), "WindowMaker")==0) {
163 domain = NULL;
164 path = NULL;
165 } else {
166 path = wdefaultspathfordomain(PLGetString(key));
168 domain = PLGetProplistWithPath(path);
170 if (!domain) {
171 proplist_t p;
173 domain = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
174 if (path) {
175 p = PLMakeString(path);
176 PLSetFilename(domain, p);
177 PLRelease(p);
180 if (path)
181 free(path);
183 defaults->appDomain = domain;
185 if (domain)
186 PLInsertDictionaryEntry(defaults->defaults, key, domain);
188 PLRelease(key);
190 /* global domain */
191 key = PLMakeString("WMGLOBAL");
192 defaults->searchList[1] = key;
194 path = wdefaultspathfordomain(PLGetString(key));
196 domain = PLGetProplistWithPath(path);
198 free(path);
200 if (!domain)
201 domain = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
203 if (domain)
204 PLInsertDictionaryEntry(defaults->defaults, key, domain);
206 PLRelease(key);
208 /* terminate list */
209 defaults->searchList[2] = NULL;
211 defaults->searchListArray=PLMakeArrayFromElements(NULL,NULL);
214 i = 0;
215 while (defaults->searchList[i]) {
216 PLAppendArrayElement(defaults->searchListArray,
217 defaults->searchList[i]);
218 i++;
221 if (sharedUserDefaults)
222 defaults->next = sharedUserDefaults;
223 sharedUserDefaults = defaults;
225 registerSaveOnExit();
227 return defaults;
231 WMUserDefaults*
232 WMGetDefaultsFromPath(char *path)
234 WMUserDefaults *defaults;
235 proplist_t domain;
236 proplist_t key;
237 char *name;
238 int i;
240 assert(path != NULL);
242 if (sharedUserDefaults) {
243 defaults = sharedUserDefaults;
244 while (defaults) {
245 if (defaults->path && strcmp(defaults->path, path) == 0)
246 return defaults;
247 defaults = defaults->next;
251 /* we didn't found the database we are looking for. Go read it. */
252 defaults = wmalloc(sizeof(WMUserDefaults));
253 memset(defaults, 0, sizeof(WMUserDefaults));
255 defaults->defaults = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
257 defaults->searchList = wmalloc(sizeof(proplist_t)*2);
259 /* the domain we want, go in the first position */
260 name = strrchr(path, '/');
261 if (!name)
262 name = path;
263 else
264 name++;
266 key = PLMakeString(name);
267 defaults->searchList[0] = key;
269 domain = PLGetProplistWithPath(path);
271 if (!domain) {
272 proplist_t p;
274 domain = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
275 p = PLMakeString(path);
276 PLSetFilename(domain, p);
277 PLRelease(p);
280 defaults->path = wstrdup(path);
282 defaults->appDomain = domain;
284 if (domain)
285 PLInsertDictionaryEntry(defaults->defaults, key, domain);
287 PLRelease(key);
289 /* terminate list */
290 defaults->searchList[1] = NULL;
292 defaults->searchListArray=PLMakeArrayFromElements(NULL,NULL);
294 i = 0;
295 while (defaults->searchList[i]) {
296 PLAppendArrayElement(defaults->searchListArray,
297 defaults->searchList[i]);
298 i++;
301 if (sharedUserDefaults)
302 defaults->next = sharedUserDefaults;
303 sharedUserDefaults = defaults;
305 registerSaveOnExit();
307 return defaults;
311 proplist_t
312 WMGetUDObjectForKey(WMUserDefaults *database, char *defaultName)
314 proplist_t domainName, domain;
315 proplist_t object = NULL;
316 proplist_t key = PLMakeString(defaultName);
317 int i = 0;
319 while (database->searchList[i] && !object) {
320 domainName = database->searchList[i];
321 domain = PLGetDictionaryEntry(database->defaults, domainName);
322 if (domain) {
323 object = PLGetDictionaryEntry(domain, key);
325 i++;
327 PLRelease(key);
329 return object;
333 void
334 WMSetUDObjectForKey(WMUserDefaults *database, proplist_t object,
335 char *defaultName)
337 proplist_t key = PLMakeString(defaultName);
339 database->dirty = 1;
341 PLInsertDictionaryEntry(database->appDomain, key, object);
342 PLRelease(key);
346 void
347 WMRemoveUDObjectForKey(WMUserDefaults *database, char *defaultName)
349 proplist_t key = PLMakeString(defaultName);
351 database->dirty = 1;
353 PLRemoveDictionaryEntry(database->appDomain, key);
355 PLRelease(key);
359 char*
360 WMGetUDStringForKey(WMUserDefaults *database, char *defaultName)
362 proplist_t val;
364 val = WMGetUDObjectForKey(database, defaultName);
366 if (!val)
367 return NULL;
369 if (!PLIsString(val))
370 return NULL;
372 return wstrdup(PLGetString(val));
377 WMGetUDIntegerForKey(WMUserDefaults *database, char *defaultName)
379 proplist_t val;
380 char *str;
381 int value;
383 val = WMGetUDObjectForKey(database, defaultName);
385 if (!val)
386 return 0;
388 if (!PLIsString(val))
389 return 0;
391 str = PLGetString(val);
392 if (!str)
393 return 0;
395 if (sscanf(str, "%i", &value)!=1)
396 return 0;
398 return value;
403 float
404 WMGetUDFloatForKey(WMUserDefaults *database, char *defaultName)
406 proplist_t val;
407 char *str;
408 float value;
410 val = WMGetUDObjectForKey(database, defaultName);
412 if (!val || !PLIsString(val))
413 return 0.0;
415 if (!(str = PLGetString(val)))
416 return 0.0;
418 if (sscanf(str, "%f", &value)!=1)
419 return 0.0;
421 return value;
426 Bool
427 WMGetUDBoolForKey(WMUserDefaults *database, char *defaultName)
429 proplist_t val;
430 int value;
431 char *str;
433 val = WMGetUDObjectForKey(database, defaultName);
435 if (!val)
436 return False;
438 if (!PLIsString(val))
439 return False;
441 str = PLGetString(val);
442 if (!str)
443 return False;
445 if (sscanf(str, "%i", &value)==1 && value!=0)
446 return True;
448 if (strcasecmp(str, "YES")==0)
449 return True;
451 if (strcasecmp(str, "Y")==0)
452 return True;
454 return False;
458 void
459 WMSetUDIntegerForKey(WMUserDefaults *database, int value, char *defaultName)
461 proplist_t object;
462 char buffer[128];
464 sprintf(buffer, "%i", value);
465 object = PLMakeString(buffer);
467 WMSetUDObjectForKey(database, object, defaultName);
468 PLRelease(object);
474 void
475 WMSetUDStringForKey(WMUserDefaults *database, char *value, char *defaultName)
477 proplist_t object;
479 object = PLMakeString(value);
481 WMSetUDObjectForKey(database, object, defaultName);
482 PLRelease(object);
487 void
488 WMSetUDFloatForKey(WMUserDefaults *database, float value, char *defaultName)
490 proplist_t object;
491 char buffer[128];
493 sprintf(buffer, "%f", value);
494 object = PLMakeString(buffer);
496 WMSetUDObjectForKey(database, object, defaultName);
497 PLRelease(object);
502 void
503 WMSetUDBoolForKey(WMUserDefaults *database, Bool value, char *defaultName)
505 static proplist_t yes = NULL, no = NULL;
507 if (!yes) {
508 yes = PLMakeString("YES");
509 no = PLMakeString("NO");
512 WMSetUDObjectForKey(database, value ? yes : no, defaultName);
516 proplist_t
517 WMGetUDSearchList(WMUserDefaults *database)
519 return database->searchListArray;
523 void
524 WMSetUDSearchList(WMUserDefaults *database, proplist_t list)
526 int i, c;
528 if (database->searchList) {
529 i = 0;
530 while (database->searchList[i]) {
531 PLRelease(database->searchList[i]);
532 i++;
534 free(database->searchList);
536 if (database->searchListArray) {
537 PLRelease(database->searchListArray);
540 c = PLGetNumberOfElements(list);
541 database->searchList = wmalloc(sizeof(proplist_t)*(c+1));
543 for (i=0; i<c; i++) {
544 database->searchList[i] = PLGetArrayElement(list, i);
547 database->searchListArray = PLDeepCopy(list);