Coding style cleanup in dock.c
[wmaker-crm.git] / WINGs / userdefaults.c
blob6de410e06a8ee1c6cdf3ba558566c89a3419f8a2
2 #include <stdlib.h>
3 #include <string.h>
4 #include <strings.h>
5 #include <stdio.h>
6 #include <assert.h>
7 #include <unistd.h>
8 #include <sys/stat.h>
10 #include "wconfig.h"
12 #include "WINGs.h"
14 typedef struct W_UserDefaults {
15 WMPropList *defaults;
17 WMPropList *appDomain;
19 WMPropList *searchListArray;
20 WMPropList **searchList; /* cache for searchListArray */
22 char dirty;
24 char dontSync;
26 char *path; /* where is db located */
28 time_t timestamp; /* last modification time */
30 struct W_UserDefaults *next;
32 } UserDefaults;
34 static UserDefaults *sharedUserDefaults = NULL;
36 char *WMUserDefaultsDidChangeNotification = "WMUserDefaultsDidChangeNotification";
38 static void synchronizeUserDefaults(void *foo);
40 extern char *WMGetApplicationName();
42 #define DEFAULTS_DIR "/Defaults"
43 #ifndef HAVE_INOTIFY
44 /* Check defaults database for changes every this many milliseconds */
45 /* XXX: this is shared with src/ stuff, put it in some common header */
46 #define UD_SYNC_INTERVAL 2000
47 #endif
49 char *wusergnusteppath()
51 static char *path = NULL;
52 char *gspath;
53 int pathlen;
55 gspath = getenv("GNUSTEP_USER_ROOT");
56 if (gspath) {
57 gspath = wexpandpath(gspath);
58 if (gspath) {
59 pathlen = strlen(gspath) + 4;
60 path = wmalloc(pathlen);
61 if (wstrlcpy(path, gspath, pathlen) >= pathlen) {
62 wfree(gspath);
63 return NULL;
65 wfree(gspath);
67 } else {
68 char *h = wgethomedir();
69 if (!h)
70 return NULL;
71 pathlen = strlen(h) + 8 /* /GNUstep */ + 1;
72 path = wmalloc(pathlen);
73 if (wstrlcpy(path, h, pathlen) >= pathlen ||
74 wstrlcat(path, "/GNUstep", pathlen) >= pathlen) {
75 wfree(path);
76 return NULL;
80 return path;
83 char *wdefaultspathfordomain(char *domain)
85 char *path;
86 char *gspath;
87 size_t slen;
89 gspath = wusergnusteppath();
90 slen = strlen(gspath) + strlen(DEFAULTS_DIR) + strlen(domain) + 4;
91 path = wmalloc(slen);
93 if (wstrlcpy(path, gspath, slen) >= slen ||
94 wstrlcat(path, DEFAULTS_DIR, slen) >= slen ||
95 wstrlcat(path, "/", slen) >= slen ||
96 wstrlcat(path, domain, slen) >= slen) {
97 wfree(path);
98 return NULL;
101 return path;
104 /* XXX: doesn't quite belong to *user*defaults.c */
105 #ifndef GLOBAL_DEFAULTS_SUBDIR
106 #define GLOBAL_DEFAULTS_SUBDIR "WindowMaker"
107 #endif
108 char *wglobaldefaultspathfordomain(const char *domain)
110 char *t = NULL;
111 size_t len;
113 len = strlen( SYSCONFDIR ) + strlen( GLOBAL_DEFAULTS_SUBDIR ) + strlen(domain) + 3;
114 t = wmalloc(len);
115 snprintf(t, len, "%s/%s/%s", SYSCONFDIR, GLOBAL_DEFAULTS_SUBDIR, domain);
117 return t;
120 static void
121 saveDefaultsChanges(void)
123 /* save the user defaults databases */
124 synchronizeUserDefaults(NULL);
127 /* set to save changes in defaults when program is exited */
128 static void registerSaveOnExit(void)
130 static Bool registeredSaveOnExit = False;
132 if (!registeredSaveOnExit) {
133 atexit(saveDefaultsChanges);
134 registeredSaveOnExit = True;
138 static void synchronizeUserDefaults(void *foo)
140 UserDefaults *database = sharedUserDefaults;
142 while (database) {
143 if (!database->dontSync)
144 WMSynchronizeUserDefaults(database);
145 database = database->next;
149 #ifndef HAVE_INOTIFY
150 static void addSynchronizeTimerHandler(void)
152 static Bool initialized = False;
154 if (!initialized) {
155 WMAddPersistentTimerHandler(UD_SYNC_INTERVAL,
156 synchronizeUserDefaults, NULL);
157 initialized = True;
160 #endif
162 void WMEnableUDPeriodicSynchronization(WMUserDefaults * database, Bool enable)
164 database->dontSync = !enable;
167 void WMSynchronizeUserDefaults(WMUserDefaults * database)
169 Bool fileIsNewer = False, release = False, notify = False;
170 WMPropList *plF, *key;
171 char *path;
172 struct stat stbuf;
174 if (!database->path) {
175 path = wdefaultspathfordomain(WMGetApplicationName());
176 release = True;
177 } else {
178 path = database->path;
181 if (stat(path, &stbuf) >= 0 && stbuf.st_mtime > database->timestamp)
182 fileIsNewer = True;
184 if (database->appDomain && (database->dirty || fileIsNewer)) {
185 if (database->dirty && fileIsNewer) {
186 plF = WMReadPropListFromFile(path);
187 if (plF) {
188 plF = WMMergePLDictionaries(plF, database->appDomain, False);
189 WMReleasePropList(database->appDomain);
190 database->appDomain = plF;
191 key = database->searchList[0];
192 WMPutInPLDictionary(database->defaults, key, plF);
193 notify = True;
194 } else {
195 /* something happened with the file. just overwrite it */
196 wwarning(_("cannot read domain from file '%s' when syncing"), path);
197 WMWritePropListToFile(database->appDomain, path);
199 } else if (database->dirty) {
200 WMWritePropListToFile(database->appDomain, path);
201 } else if (fileIsNewer) {
202 plF = WMReadPropListFromFile(path);
203 if (plF) {
204 WMReleasePropList(database->appDomain);
205 database->appDomain = plF;
206 key = database->searchList[0];
207 WMPutInPLDictionary(database->defaults, key, plF);
208 notify = True;
209 } else {
210 /* something happened with the file. just overwrite it */
211 wwarning(_("cannot read domain from file '%s' when syncing"), path);
212 WMWritePropListToFile(database->appDomain, path);
216 database->dirty = 0;
218 if (stat(path, &stbuf) >= 0)
219 database->timestamp = stbuf.st_mtime;
221 if (notify) {
222 WMPostNotificationName(WMUserDefaultsDidChangeNotification, database, NULL);
226 if (release)
227 wfree(path);
231 void WMSaveUserDefaults(WMUserDefaults * database)
233 if (database->appDomain) {
234 struct stat stbuf;
235 char *path;
236 Bool release = False;
238 if (!database->path) {
239 path = wdefaultspathfordomain(WMGetApplicationName());
240 release = True;
241 } else {
242 path = database->path;
244 WMWritePropListToFile(database->appDomain, path);
245 database->dirty = 0;
246 if (stat(path, &stbuf) >= 0)
247 database->timestamp = stbuf.st_mtime;
248 if (release)
249 wfree(path);
253 WMUserDefaults *WMGetStandardUserDefaults(void)
255 WMUserDefaults *defaults;
256 WMPropList *domain;
257 WMPropList *key;
258 struct stat stbuf;
259 char *path;
260 int i;
262 if (sharedUserDefaults) {
263 defaults = sharedUserDefaults;
264 while (defaults) {
265 /* path == NULL only for StandardUserDefaults db */
266 if (defaults->path == NULL)
267 return defaults;
268 defaults = defaults->next;
272 /* we didn't found the database we are looking for. Go read it. XXX: wtf? */
273 defaults = wmalloc(sizeof(WMUserDefaults));
274 defaults->defaults = WMCreatePLDictionary(NULL, NULL);
275 defaults->searchList = wmalloc(sizeof(WMPropList *) * 3);
277 /* application domain */
278 key = WMCreatePLString(WMGetApplicationName());
279 defaults->searchList[0] = key;
281 /* temporary kluge. wmaker handles synchronization itself */
282 if (strcmp(WMGetApplicationName(), "WindowMaker") == 0) {
283 defaults->dontSync = 1;
286 path = wdefaultspathfordomain(WMGetFromPLString(key));
288 if (stat(path, &stbuf) >= 0)
289 defaults->timestamp = stbuf.st_mtime;
291 domain = WMReadPropListFromFile(path);
293 if (!domain)
294 domain = WMCreatePLDictionary(NULL, NULL);
296 if (path)
297 wfree(path);
299 defaults->appDomain = domain;
301 if (domain)
302 WMPutInPLDictionary(defaults->defaults, key, domain);
304 /* global domain */
305 key = WMCreatePLString("WMGLOBAL");
306 defaults->searchList[1] = key;
308 path = wdefaultspathfordomain(WMGetFromPLString(key));
310 domain = WMReadPropListFromFile(path);
312 wfree(path);
314 if (!domain)
315 domain = WMCreatePLDictionary(NULL, NULL);
317 if (domain)
318 WMPutInPLDictionary(defaults->defaults, key, domain);
320 /* terminate list */
321 defaults->searchList[2] = NULL;
323 defaults->searchListArray = WMCreatePLArray(NULL, NULL);
325 i = 0;
326 while (defaults->searchList[i]) {
327 WMAddToPLArray(defaults->searchListArray, defaults->searchList[i]);
328 i++;
331 if (sharedUserDefaults)
332 defaults->next = sharedUserDefaults;
333 sharedUserDefaults = defaults;
335 #ifndef HAVE_INOTIFY
336 addSynchronizeTimerHandler();
337 #endif
338 registerSaveOnExit();
340 return defaults;
343 WMUserDefaults *WMGetDefaultsFromPath(char *path)
345 WMUserDefaults *defaults;
346 WMPropList *domain;
347 WMPropList *key;
348 struct stat stbuf;
349 char *name;
350 int i;
352 assert(path != NULL);
354 if (sharedUserDefaults) {
355 defaults = sharedUserDefaults;
356 while (defaults) {
357 if (defaults->path && strcmp(defaults->path, path) == 0)
358 return defaults;
359 defaults = defaults->next;
363 /* we didn't found the database we are looking for. Go read it. XXX wtf? */
364 defaults = wmalloc(sizeof(WMUserDefaults));
365 defaults->defaults = WMCreatePLDictionary(NULL, NULL);
366 defaults->searchList = wmalloc(sizeof(WMPropList *) * 2);
368 /* the domain we want, go in the first position */
369 name = strrchr(path, '/');
370 if (!name)
371 name = path;
372 else
373 name++;
375 key = WMCreatePLString(name);
376 defaults->searchList[0] = key;
378 if (stat(path, &stbuf) >= 0)
379 defaults->timestamp = stbuf.st_mtime;
381 domain = WMReadPropListFromFile(path);
383 if (!domain)
384 domain = WMCreatePLDictionary(NULL, NULL);
386 defaults->path = wstrdup(path);
388 defaults->appDomain = domain;
390 if (domain)
391 WMPutInPLDictionary(defaults->defaults, key, domain);
393 /* terminate list */
394 defaults->searchList[1] = NULL;
396 defaults->searchListArray = WMCreatePLArray(NULL, NULL);
398 i = 0;
399 while (defaults->searchList[i]) {
400 WMAddToPLArray(defaults->searchListArray, defaults->searchList[i]);
401 i++;
404 if (sharedUserDefaults)
405 defaults->next = sharedUserDefaults;
406 sharedUserDefaults = defaults;
408 #ifndef HAVE_INOTIFY
409 addSynchronizeTimerHandler();
410 #endif
411 registerSaveOnExit();
413 return defaults;
416 /* Returns a WMPropList array with all keys in the user defaults database.
417 * Free the array with WMReleasePropList() when no longer needed,
418 * but do not free the elements of the array! They're just references. */
419 WMPropList *WMGetUDKeys(WMUserDefaults * database)
421 return WMGetPLDictionaryKeys(database->appDomain);
424 WMPropList *WMGetUDObjectForKey(WMUserDefaults * database, char *defaultName)
426 WMPropList *domainName, *domain;
427 WMPropList *object = NULL;
428 WMPropList *key = WMCreatePLString(defaultName);
429 int i = 0;
431 while (database->searchList[i] && !object) {
432 domainName = database->searchList[i];
433 domain = WMGetFromPLDictionary(database->defaults, domainName);
434 if (domain) {
435 object = WMGetFromPLDictionary(domain, key);
437 i++;
439 WMReleasePropList(key);
441 return object;
444 void WMSetUDObjectForKey(WMUserDefaults * database, WMPropList * object, char *defaultName)
446 WMPropList *key = WMCreatePLString(defaultName);
448 database->dirty = 1;
450 WMPutInPLDictionary(database->appDomain, key, object);
451 WMReleasePropList(key);
454 void WMRemoveUDObjectForKey(WMUserDefaults * database, char *defaultName)
456 WMPropList *key = WMCreatePLString(defaultName);
458 database->dirty = 1;
460 WMRemoveFromPLDictionary(database->appDomain, key);
462 WMReleasePropList(key);
465 char *WMGetUDStringForKey(WMUserDefaults * database, char *defaultName)
467 WMPropList *val;
469 val = WMGetUDObjectForKey(database, defaultName);
471 if (!val)
472 return NULL;
474 if (!WMIsPLString(val))
475 return NULL;
477 return WMGetFromPLString(val);
480 int WMGetUDIntegerForKey(WMUserDefaults * database, char *defaultName)
482 WMPropList *val;
483 char *str;
484 int value;
486 val = WMGetUDObjectForKey(database, defaultName);
488 if (!val)
489 return 0;
491 if (!WMIsPLString(val))
492 return 0;
494 str = WMGetFromPLString(val);
495 if (!str)
496 return 0;
498 if (sscanf(str, "%i", &value) != 1)
499 return 0;
501 return value;
504 float WMGetUDFloatForKey(WMUserDefaults * database, char *defaultName)
506 WMPropList *val;
507 char *str;
508 float value;
510 val = WMGetUDObjectForKey(database, defaultName);
512 if (!val || !WMIsPLString(val))
513 return 0.0;
515 if (!(str = WMGetFromPLString(val)))
516 return 0.0;
518 if (sscanf(str, "%f", &value) != 1)
519 return 0.0;
521 return value;
524 Bool WMGetUDBoolForKey(WMUserDefaults * database, char *defaultName)
526 WMPropList *val;
527 int value;
528 char *str;
530 val = WMGetUDObjectForKey(database, defaultName);
532 if (!val)
533 return False;
535 if (!WMIsPLString(val))
536 return False;
538 str = WMGetFromPLString(val);
539 if (!str)
540 return False;
542 if (sscanf(str, "%i", &value) == 1 && value != 0)
543 return True;
545 if (strcasecmp(str, "YES") == 0)
546 return True;
548 if (strcasecmp(str, "Y") == 0)
549 return True;
551 return False;
554 void WMSetUDIntegerForKey(WMUserDefaults * database, int value, char *defaultName)
556 WMPropList *object;
557 char buffer[128];
559 sprintf(buffer, "%i", value);
560 object = WMCreatePLString(buffer);
562 WMSetUDObjectForKey(database, object, defaultName);
563 WMReleasePropList(object);
566 void WMSetUDStringForKey(WMUserDefaults * database, char *value, char *defaultName)
568 WMPropList *object;
570 object = WMCreatePLString(value);
572 WMSetUDObjectForKey(database, object, defaultName);
573 WMReleasePropList(object);
576 void WMSetUDFloatForKey(WMUserDefaults * database, float value, char *defaultName)
578 WMPropList *object;
579 char buffer[128];
581 sprintf(buffer, "%f", value);
582 object = WMCreatePLString(buffer);
584 WMSetUDObjectForKey(database, object, defaultName);
585 WMReleasePropList(object);
588 void WMSetUDBoolForKey(WMUserDefaults * database, Bool value, char *defaultName)
590 static WMPropList *yes = NULL, *no = NULL;
592 if (!yes) {
593 yes = WMCreatePLString("YES");
594 no = WMCreatePLString("NO");
597 WMSetUDObjectForKey(database, value ? yes : no, defaultName);
600 WMPropList *WMGetUDSearchList(WMUserDefaults * database)
602 return database->searchListArray;
605 void WMSetUDSearchList(WMUserDefaults * database, WMPropList * list)
607 int i, c;
609 if (database->searchList) {
610 i = 0;
611 while (database->searchList[i]) {
612 WMReleasePropList(database->searchList[i]);
613 i++;
615 wfree(database->searchList);
617 if (database->searchListArray) {
618 WMReleasePropList(database->searchListArray);
621 c = WMGetPropListItemCount(list);
622 database->searchList = wmalloc(sizeof(WMPropList *) * (c + 1));
624 for (i = 0; i < c; i++) {
625 database->searchList[i] = WMGetFromPLArray(list, i);
627 database->searchList[c] = NULL;
629 database->searchListArray = WMDeepCopyPropList(list);