Added WMSaveUserDefaults()
[wmaker-crm.git] / WINGs / userdefaults.c
blobbe279c224085966423da4284f07083854849fa9f
2 #include <stdlib.h>
3 #include <string.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 PLShallowSynchronize(tmp->appDomain);
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 PLShallowSynchronize(database->appDomain);
130 void
131 WMSaveUserDefaults(WMUserDefaults *database)
133 PLSave(database->appDomain, YES);
137 WMUserDefaults*
138 WMGetStandardUserDefaults(void)
140 WMUserDefaults *defaults;
141 proplist_t domain;
142 proplist_t key;
143 char *path;
144 int i;
146 if (sharedUserDefaults) {
147 defaults = sharedUserDefaults;
148 while (defaults) {
149 /* Trick, path == NULL only for StandardUserDefaults db */
150 if (defaults->path == NULL)
151 return defaults;
152 defaults = defaults->next;
156 /* we didn't found the database we are looking for. Go read it. */
157 defaults = wmalloc(sizeof(WMUserDefaults));
158 memset(defaults, 0, sizeof(WMUserDefaults));
160 defaults->defaults = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
162 defaults->searchList = wmalloc(sizeof(proplist_t)*3);
164 /* application domain */
165 key = PLMakeString(WMGetApplicationName());
166 defaults->searchList[0] = key;
168 /* temporary kluge */
169 if (strcmp(WMGetApplicationName(), "WindowMaker")==0) {
170 domain = NULL;
171 path = NULL;
172 } else {
173 path = wdefaultspathfordomain(PLGetString(key));
175 domain = PLGetProplistWithPath(path);
177 if (!domain) {
178 proplist_t p;
180 domain = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
181 if (path) {
182 p = PLMakeString(path);
183 PLSetFilename(domain, p);
184 PLRelease(p);
187 if (path)
188 free(path);
190 defaults->appDomain = domain;
192 if (domain)
193 PLInsertDictionaryEntry(defaults->defaults, key, domain);
195 PLRelease(key);
197 /* global domain */
198 key = PLMakeString("WMGLOBAL");
199 defaults->searchList[1] = key;
201 path = wdefaultspathfordomain(PLGetString(key));
203 domain = PLGetProplistWithPath(path);
205 free(path);
207 if (!domain)
208 domain = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
210 if (domain)
211 PLInsertDictionaryEntry(defaults->defaults, key, domain);
213 PLRelease(key);
215 /* terminate list */
216 defaults->searchList[2] = NULL;
218 defaults->searchListArray=PLMakeArrayFromElements(NULL,NULL);
221 i = 0;
222 while (defaults->searchList[i]) {
223 PLAppendArrayElement(defaults->searchListArray,
224 defaults->searchList[i]);
225 i++;
228 if (sharedUserDefaults)
229 defaults->next = sharedUserDefaults;
230 sharedUserDefaults = defaults;
232 registerSaveOnExit();
234 return defaults;
238 WMUserDefaults*
239 WMGetDefaultsFromPath(char *path)
241 WMUserDefaults *defaults;
242 proplist_t domain;
243 proplist_t key;
244 char *name;
245 int i;
247 assert(path != NULL);
249 if (sharedUserDefaults) {
250 defaults = sharedUserDefaults;
251 while (defaults) {
252 if (defaults->path && strcmp(defaults->path, path) == 0)
253 return defaults;
254 defaults = defaults->next;
258 /* we didn't found the database we are looking for. Go read it. */
259 defaults = wmalloc(sizeof(WMUserDefaults));
260 memset(defaults, 0, sizeof(WMUserDefaults));
262 defaults->defaults = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
264 defaults->searchList = wmalloc(sizeof(proplist_t)*2);
266 /* the domain we want, go in the first position */
267 name = strrchr(path, '/');
268 if (!name)
269 name = path;
270 else
271 name++;
273 key = PLMakeString(name);
274 defaults->searchList[0] = key;
276 domain = PLGetProplistWithPath(path);
278 if (!domain) {
279 proplist_t p;
281 domain = PLMakeDictionaryFromEntries(NULL, NULL, NULL);
282 p = PLMakeString(path);
283 PLSetFilename(domain, p);
284 PLRelease(p);
287 defaults->path = wstrdup(path);
289 defaults->appDomain = domain;
291 if (domain)
292 PLInsertDictionaryEntry(defaults->defaults, key, domain);
294 PLRelease(key);
296 /* terminate list */
297 defaults->searchList[1] = NULL;
299 defaults->searchListArray=PLMakeArrayFromElements(NULL,NULL);
301 i = 0;
302 while (defaults->searchList[i]) {
303 PLAppendArrayElement(defaults->searchListArray,
304 defaults->searchList[i]);
305 i++;
308 if (sharedUserDefaults)
309 defaults->next = sharedUserDefaults;
310 sharedUserDefaults = defaults;
312 registerSaveOnExit();
314 return defaults;
318 proplist_t
319 WMGetUDObjectForKey(WMUserDefaults *database, char *defaultName)
321 proplist_t domainName, domain;
322 proplist_t object = NULL;
323 proplist_t key = PLMakeString(defaultName);
324 int i = 0;
326 while (database->searchList[i] && !object) {
327 domainName = database->searchList[i];
328 domain = PLGetDictionaryEntry(database->defaults, domainName);
329 if (domain) {
330 object = PLGetDictionaryEntry(domain, key);
332 i++;
334 PLRelease(key);
336 return object;
340 void
341 WMSetUDObjectForKey(WMUserDefaults *database, proplist_t object,
342 char *defaultName)
344 proplist_t key = PLMakeString(defaultName);
346 database->dirty = 1;
348 PLInsertDictionaryEntry(database->appDomain, key, object);
349 PLRelease(key);
353 void
354 WMRemoveUDObjectForKey(WMUserDefaults *database, char *defaultName)
356 proplist_t key = PLMakeString(defaultName);
358 database->dirty = 1;
360 PLRemoveDictionaryEntry(database->appDomain, key);
362 PLRelease(key);
366 char*
367 WMGetUDStringForKey(WMUserDefaults *database, char *defaultName)
369 proplist_t val;
371 val = WMGetUDObjectForKey(database, defaultName);
373 if (!val)
374 return NULL;
376 if (!PLIsString(val))
377 return NULL;
379 return PLGetString(val);
384 WMGetUDIntegerForKey(WMUserDefaults *database, char *defaultName)
386 proplist_t val;
387 char *str;
388 int value;
390 val = WMGetUDObjectForKey(database, defaultName);
392 if (!val)
393 return 0;
395 if (!PLIsString(val))
396 return 0;
398 str = PLGetString(val);
399 if (!str)
400 return 0;
402 if (sscanf(str, "%i", &value)!=1)
403 return 0;
405 return value;
410 float
411 WMGetUDFloatForKey(WMUserDefaults *database, char *defaultName)
413 proplist_t val;
414 char *str;
415 float value;
417 val = WMGetUDObjectForKey(database, defaultName);
419 if (!val || !PLIsString(val))
420 return 0.0;
422 if (!(str = PLGetString(val)))
423 return 0.0;
425 if (sscanf(str, "%f", &value)!=1)
426 return 0.0;
428 return value;
433 Bool
434 WMGetUDBoolForKey(WMUserDefaults *database, char *defaultName)
436 proplist_t val;
437 int value;
438 char *str;
440 val = WMGetUDObjectForKey(database, defaultName);
442 if (!val)
443 return False;
445 if (!PLIsString(val))
446 return False;
448 str = PLGetString(val);
449 if (!str)
450 return False;
452 if (sscanf(str, "%i", &value)==1 && value!=0)
453 return True;
455 if (strcasecmp(str, "YES")==0)
456 return True;
458 if (strcasecmp(str, "Y")==0)
459 return True;
461 return False;
465 void
466 WMSetUDIntegerForKey(WMUserDefaults *database, int value, char *defaultName)
468 proplist_t object;
469 char buffer[128];
471 sprintf(buffer, "%i", value);
472 object = PLMakeString(buffer);
474 WMSetUDObjectForKey(database, object, defaultName);
475 PLRelease(object);
481 void
482 WMSetUDStringForKey(WMUserDefaults *database, char *value, char *defaultName)
484 proplist_t object;
486 object = PLMakeString(value);
488 WMSetUDObjectForKey(database, object, defaultName);
489 PLRelease(object);
494 void
495 WMSetUDFloatForKey(WMUserDefaults *database, float value, char *defaultName)
497 proplist_t object;
498 char buffer[128];
500 sprintf(buffer, "%f", value);
501 object = PLMakeString(buffer);
503 WMSetUDObjectForKey(database, object, defaultName);
504 PLRelease(object);
509 void
510 WMSetUDBoolForKey(WMUserDefaults *database, Bool value, char *defaultName)
512 static proplist_t yes = NULL, no = NULL;
514 if (!yes) {
515 yes = PLMakeString("YES");
516 no = PLMakeString("NO");
519 WMSetUDObjectForKey(database, value ? yes : no, defaultName);
523 proplist_t
524 WMGetUDSearchList(WMUserDefaults *database)
526 return database->searchListArray;
530 void
531 WMSetUDSearchList(WMUserDefaults *database, proplist_t list)
533 int i, c;
535 if (database->searchList) {
536 i = 0;
537 while (database->searchList[i]) {
538 PLRelease(database->searchList[i]);
539 i++;
541 free(database->searchList);
543 if (database->searchListArray) {
544 PLRelease(database->searchListArray);
547 c = PLGetNumberOfElements(list);
548 database->searchList = wmalloc(sizeof(proplist_t)*(c+1));
550 for (i=0; i<c; i++) {
551 database->searchList[i] = PLGetArrayElement(list, i);
554 database->searchListArray = PLDeepCopy(list);