Change to the linux kernel coding style
[wmaker-crm.git] / WINGs / userdefaults.c
blob2942745306562cbea5bc8b6a101a86dc3df70eb4
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdio.h>
5 #include <assert.h>
6 #include <unistd.h>
7 #include <sys/stat.h>
9 #include "wconfig.h"
11 #include "WINGs.h"
13 typedef struct W_UserDefaults {
14 WMPropList *defaults;
16 WMPropList *appDomain;
18 WMPropList *searchListArray;
19 WMPropList **searchList; /* cache for searchListArray */
21 char dirty;
23 char dontSync;
25 char *path; /* where is db located */
27 time_t timestamp; /* last modification time */
29 struct W_UserDefaults *next;
31 } UserDefaults;
33 static UserDefaults *sharedUserDefaults = NULL;
35 char *WMUserDefaultsDidChangeNotification = "WMUserDefaultsDidChangeNotification";
37 static void synchronizeUserDefaults(void *foo);
39 extern char *WMGetApplicationName();
41 #define DEFAULTS_DIR "/Defaults"
43 char *wusergnusteppath()
44 {
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 wfree(gspath);
57 } else {
58 pathlen = strlen(wgethomedir()) + 10;
59 path = wmalloc(pathlen);
60 strcpy(path, wgethomedir());
61 strcat(path, "/GNUstep");
62 }
63 }
65 return path;
66 }
68 char *wdefaultspathfordomain(char *domain)
69 {
70 char *path;
71 char *gspath;
73 gspath = wusergnusteppath();
74 path = wmalloc(strlen(gspath) + strlen(DEFAULTS_DIR) + strlen(domain) + 4);
75 strcpy(path, gspath);
76 strcat(path, DEFAULTS_DIR);
77 strcat(path, "/");
78 strcat(path, domain);
80 return path;
81 }
83 static void
84 #ifdef HAVE_ATEXIT
85 saveDefaultsChanges(void)
86 #else
87 saveDefaultsChanges(int foo, void *bar)
88 #endif
89 {
90 /* save the user defaults databases */
91 synchronizeUserDefaults(NULL);
92 }
94 /* set to save changes in defaults when program is exited */
95 static void registerSaveOnExit(void)
96 {
97 static Bool registeredSaveOnExit = False;
99 if (!registeredSaveOnExit) {
100 #ifdef HAVE_ATEXIT
101 atexit(saveDefaultsChanges);
102 #else
103 on_exit(saveDefaultsChanges, (void *)NULL);
104 #endif
105 registeredSaveOnExit = True;
109 static void synchronizeUserDefaults(void *foo)
111 UserDefaults *database = sharedUserDefaults;
113 while (database) {
114 if (!database->dontSync)
115 WMSynchronizeUserDefaults(database);
116 database = database->next;
120 void WMEnableUDPeriodicSynchronization(WMUserDefaults * database, Bool enable)
122 database->dontSync = !enable;
125 void WMSynchronizeUserDefaults(WMUserDefaults * database)
127 Bool fileIsNewer = False, release = False, notify = False;
128 WMPropList *plF, *key;
129 char *path;
130 struct stat stbuf;
132 if (!database->path) {
133 path = wdefaultspathfordomain(WMGetApplicationName());
134 release = True;
135 } else {
136 path = database->path;
139 if (stat(path, &stbuf) >= 0 && stbuf.st_mtime > database->timestamp)
140 fileIsNewer = True;
142 if (database->appDomain && (database->dirty || fileIsNewer)) {
143 if (database->dirty && fileIsNewer) {
144 plF = WMReadPropListFromFile(path);
145 if (plF) {
146 plF = WMMergePLDictionaries(plF, database->appDomain, False);
147 WMReleasePropList(database->appDomain);
148 database->appDomain = plF;
149 key = database->searchList[0];
150 WMPutInPLDictionary(database->defaults, key, plF);
151 notify = True;
152 } else {
153 /* something happened with the file. just overwrite it */
154 wwarning(_("cannot read domain from file '%s' when syncing"), path);
155 WMWritePropListToFile(database->appDomain, path, True);
157 } else if (database->dirty) {
158 WMWritePropListToFile(database->appDomain, path, True);
159 } else if (fileIsNewer) {
160 plF = WMReadPropListFromFile(path);
161 if (plF) {
162 WMReleasePropList(database->appDomain);
163 database->appDomain = plF;
164 key = database->searchList[0];
165 WMPutInPLDictionary(database->defaults, key, plF);
166 notify = True;
167 } else {
168 /* something happened with the file. just overwrite it */
169 wwarning(_("cannot read domain from file '%s' when syncing"), path);
170 WMWritePropListToFile(database->appDomain, path, True);
174 database->dirty = 0;
176 if (stat(path, &stbuf) >= 0)
177 database->timestamp = stbuf.st_mtime;
179 if (notify) {
180 WMPostNotificationName(WMUserDefaultsDidChangeNotification, database, NULL);
184 if (release)
185 wfree(path);
189 void WMSaveUserDefaults(WMUserDefaults * database)
191 if (database->appDomain) {
192 struct stat stbuf;
193 char *path;
194 Bool release = False;
196 if (!database->path) {
197 path = wdefaultspathfordomain(WMGetApplicationName());
198 release = True;
199 } else {
200 path = database->path;
202 WMWritePropListToFile(database->appDomain, path, True);
203 database->dirty = 0;
204 if (stat(path, &stbuf) >= 0)
205 database->timestamp = stbuf.st_mtime;
206 if (release)
207 wfree(path);
211 WMUserDefaults *WMGetStandardUserDefaults(void)
213 WMUserDefaults *defaults;
214 WMPropList *domain;
215 WMPropList *key;
216 struct stat stbuf;
217 char *path;
218 int i;
220 if (sharedUserDefaults) {
221 defaults = sharedUserDefaults;
222 while (defaults) {
223 /* path == NULL only for StandardUserDefaults db */
224 if (defaults->path == NULL)
225 return defaults;
226 defaults = defaults->next;
230 /* we didn't found the database we are looking for. Go read it. */
231 defaults = wmalloc(sizeof(WMUserDefaults));
232 memset(defaults, 0, sizeof(WMUserDefaults));
234 defaults->defaults = WMCreatePLDictionary(NULL, NULL);
236 defaults->searchList = wmalloc(sizeof(WMPropList *) * 3);
238 /* application domain */
239 key = WMCreatePLString(WMGetApplicationName());
240 defaults->searchList[0] = key;
242 /* temporary kluge. wmaker handles synchronization itself */
243 if (strcmp(WMGetApplicationName(), "WindowMaker") == 0) {
244 defaults->dontSync = 1;
247 path = wdefaultspathfordomain(WMGetFromPLString(key));
249 if (stat(path, &stbuf) >= 0)
250 defaults->timestamp = stbuf.st_mtime;
252 domain = WMReadPropListFromFile(path);
254 if (!domain)
255 domain = WMCreatePLDictionary(NULL, NULL);
257 if (path)
258 wfree(path);
260 defaults->appDomain = domain;
262 if (domain)
263 WMPutInPLDictionary(defaults->defaults, key, domain);
265 /* global domain */
266 key = WMCreatePLString("WMGLOBAL");
267 defaults->searchList[1] = key;
269 path = wdefaultspathfordomain(WMGetFromPLString(key));
271 domain = WMReadPropListFromFile(path);
273 wfree(path);
275 if (!domain)
276 domain = WMCreatePLDictionary(NULL, NULL);
278 if (domain)
279 WMPutInPLDictionary(defaults->defaults, key, domain);
281 /* terminate list */
282 defaults->searchList[2] = NULL;
284 defaults->searchListArray = WMCreatePLArray(NULL, NULL);
286 i = 0;
287 while (defaults->searchList[i]) {
288 WMAddToPLArray(defaults->searchListArray, defaults->searchList[i]);
289 i++;
292 if (sharedUserDefaults)
293 defaults->next = sharedUserDefaults;
294 sharedUserDefaults = defaults;
296 registerSaveOnExit();
298 return defaults;
301 WMUserDefaults *WMGetDefaultsFromPath(char *path)
303 WMUserDefaults *defaults;
304 WMPropList *domain;
305 WMPropList *key;
306 struct stat stbuf;
307 char *name;
308 int i;
310 assert(path != NULL);
312 if (sharedUserDefaults) {
313 defaults = sharedUserDefaults;
314 while (defaults) {
315 if (defaults->path && strcmp(defaults->path, path) == 0)
316 return defaults;
317 defaults = defaults->next;
321 /* we didn't found the database we are looking for. Go read it. */
322 defaults = wmalloc(sizeof(WMUserDefaults));
323 memset(defaults, 0, sizeof(WMUserDefaults));
325 defaults->defaults = WMCreatePLDictionary(NULL, NULL);
327 defaults->searchList = wmalloc(sizeof(WMPropList *) * 2);
329 /* the domain we want, go in the first position */
330 name = strrchr(path, '/');
331 if (!name)
332 name = path;
333 else
334 name++;
336 key = WMCreatePLString(name);
337 defaults->searchList[0] = key;
339 if (stat(path, &stbuf) >= 0)
340 defaults->timestamp = stbuf.st_mtime;
342 domain = WMReadPropListFromFile(path);
344 if (!domain)
345 domain = WMCreatePLDictionary(NULL, NULL);
347 defaults->path = wstrdup(path);
349 defaults->appDomain = domain;
351 if (domain)
352 WMPutInPLDictionary(defaults->defaults, key, domain);
354 /* terminate list */
355 defaults->searchList[1] = NULL;
357 defaults->searchListArray = WMCreatePLArray(NULL, NULL);
359 i = 0;
360 while (defaults->searchList[i]) {
361 WMAddToPLArray(defaults->searchListArray, defaults->searchList[i]);
362 i++;
365 if (sharedUserDefaults)
366 defaults->next = sharedUserDefaults;
367 sharedUserDefaults = defaults;
369 registerSaveOnExit();
371 return defaults;
374 /* Returns a WMPropList array with all keys in the user defaults database.
375 * Free the array with WMReleasePropList() when no longer needed,
376 * but do not free the elements of the array! They're just references. */
377 WMPropList *WMGetUDKeys(WMUserDefaults * database)
379 return WMGetPLDictionaryKeys(database->appDomain);
382 WMPropList *WMGetUDObjectForKey(WMUserDefaults * database, char *defaultName)
384 WMPropList *domainName, *domain;
385 WMPropList *object = NULL;
386 WMPropList *key = WMCreatePLString(defaultName);
387 int i = 0;
389 while (database->searchList[i] && !object) {
390 domainName = database->searchList[i];
391 domain = WMGetFromPLDictionary(database->defaults, domainName);
392 if (domain) {
393 object = WMGetFromPLDictionary(domain, key);
395 i++;
397 WMReleasePropList(key);
399 return object;
402 void WMSetUDObjectForKey(WMUserDefaults * database, WMPropList * object, char *defaultName)
404 WMPropList *key = WMCreatePLString(defaultName);
406 database->dirty = 1;
408 WMPutInPLDictionary(database->appDomain, key, object);
409 WMReleasePropList(key);
412 void WMRemoveUDObjectForKey(WMUserDefaults * database, char *defaultName)
414 WMPropList *key = WMCreatePLString(defaultName);
416 database->dirty = 1;
418 WMRemoveFromPLDictionary(database->appDomain, key);
420 WMReleasePropList(key);
423 char *WMGetUDStringForKey(WMUserDefaults * database, char *defaultName)
425 WMPropList *val;
427 val = WMGetUDObjectForKey(database, defaultName);
429 if (!val)
430 return NULL;
432 if (!WMIsPLString(val))
433 return NULL;
435 return WMGetFromPLString(val);
438 int WMGetUDIntegerForKey(WMUserDefaults * database, char *defaultName)
440 WMPropList *val;
441 char *str;
442 int value;
444 val = WMGetUDObjectForKey(database, defaultName);
446 if (!val)
447 return 0;
449 if (!WMIsPLString(val))
450 return 0;
452 str = WMGetFromPLString(val);
453 if (!str)
454 return 0;
456 if (sscanf(str, "%i", &value) != 1)
457 return 0;
459 return value;
462 float WMGetUDFloatForKey(WMUserDefaults * database, char *defaultName)
464 WMPropList *val;
465 char *str;
466 float value;
468 val = WMGetUDObjectForKey(database, defaultName);
470 if (!val || !WMIsPLString(val))
471 return 0.0;
473 if (!(str = WMGetFromPLString(val)))
474 return 0.0;
476 if (sscanf(str, "%f", &value) != 1)
477 return 0.0;
479 return value;
482 Bool WMGetUDBoolForKey(WMUserDefaults * database, char *defaultName)
484 WMPropList *val;
485 int value;
486 char *str;
488 val = WMGetUDObjectForKey(database, defaultName);
490 if (!val)
491 return False;
493 if (!WMIsPLString(val))
494 return False;
496 str = WMGetFromPLString(val);
497 if (!str)
498 return False;
500 if (sscanf(str, "%i", &value) == 1 && value != 0)
501 return True;
503 if (strcasecmp(str, "YES") == 0)
504 return True;
506 if (strcasecmp(str, "Y") == 0)
507 return True;
509 return False;
512 void WMSetUDIntegerForKey(WMUserDefaults * database, int value, char *defaultName)
514 WMPropList *object;
515 char buffer[128];
517 sprintf(buffer, "%i", value);
518 object = WMCreatePLString(buffer);
520 WMSetUDObjectForKey(database, object, defaultName);
521 WMReleasePropList(object);
524 void WMSetUDStringForKey(WMUserDefaults * database, char *value, char *defaultName)
526 WMPropList *object;
528 object = WMCreatePLString(value);
530 WMSetUDObjectForKey(database, object, defaultName);
531 WMReleasePropList(object);
534 void WMSetUDFloatForKey(WMUserDefaults * database, float value, char *defaultName)
536 WMPropList *object;
537 char buffer[128];
539 sprintf(buffer, "%f", value);
540 object = WMCreatePLString(buffer);
542 WMSetUDObjectForKey(database, object, defaultName);
543 WMReleasePropList(object);
546 void WMSetUDBoolForKey(WMUserDefaults * database, Bool value, char *defaultName)
548 static WMPropList *yes = NULL, *no = NULL;
550 if (!yes) {
551 yes = WMCreatePLString("YES");
552 no = WMCreatePLString("NO");
555 WMSetUDObjectForKey(database, value ? yes : no, defaultName);
558 WMPropList *WMGetUDSearchList(WMUserDefaults * database)
560 return database->searchListArray;
563 void WMSetUDSearchList(WMUserDefaults * database, WMPropList * list)
565 int i, c;
567 if (database->searchList) {
568 i = 0;
569 while (database->searchList[i]) {
570 WMReleasePropList(database->searchList[i]);
571 i++;
573 wfree(database->searchList);
575 if (database->searchListArray) {
576 WMReleasePropList(database->searchListArray);
579 c = WMGetPropListItemCount(list);
580 database->searchList = wmalloc(sizeof(WMPropList *) * (c + 1));
582 for (i = 0; i < c; i++) {
583 database->searchList[i] = WMGetFromPLArray(list, i);
585 database->searchList[c] = NULL;
587 database->searchListArray = WMDeepCopyPropList(list);