10 #include "../src/config.h"
18 typedef struct W_UserDefaults
{
21 WMPropList
*appDomain
;
23 WMPropList
*searchListArray
;
24 WMPropList
**searchList
; /* cache for searchListArray */
30 char *path
; /* where is db located */
32 time_t timestamp
; /* last modification time */
34 struct W_UserDefaults
*next
;
39 static UserDefaults
*sharedUserDefaults
= NULL
;
41 char *WMUserDefaultsDidChangeNotification
= "WMUserDefaultsDidChangeNotification";
45 extern char *WMGetApplicationName();
47 #define DEFAULTS_DIR "/Defaults"
49 #define UD_SYNC_INTERVAL 2000
56 static char *path
= NULL
;
61 gspath
= getenv("GNUSTEP_USER_ROOT");
63 gspath
= wexpandpath(gspath
);
64 pathlen
= strlen(gspath
) + 4;
65 path
= wmalloc(pathlen
);
69 pathlen
= strlen(wgethomedir()) + 10;
70 path
= wmalloc(pathlen
);
71 strcpy(path
, wgethomedir());
72 strcat(path
, "/GNUstep");
81 wdefaultspathfordomain(char *domain
)
86 gspath
= wusergnusteppath();
87 path
= wmalloc(strlen(gspath
)+strlen(DEFAULTS_DIR
)+strlen(domain
)+4);
89 strcat(path
, DEFAULTS_DIR
);
99 saveDefaultsChanges(int foo
, void *bar
)
101 saveDefaultsChanges(void)
104 /* save the user defaults databases */
105 UserDefaults
*tmp
= sharedUserDefaults
;
108 WMSynchronizeUserDefaults(tmp
);
114 /* set to save changes in defaults when program is exited */
116 registerSaveOnExit(void)
118 static Bool registeredSaveOnExit
= False
;
120 if (!registeredSaveOnExit
) {
122 on_exit(saveDefaultsChanges
, (void*)NULL
);
124 atexit(saveDefaultsChanges
);
126 registeredSaveOnExit
= True
;
132 synchronizeUserDefaults(void *foo
)
134 UserDefaults
*database
= sharedUserDefaults
;
137 if (!database
->dontSync
)
138 WMSynchronizeUserDefaults(database
);
139 database
= database
->next
;
141 WMAddTimerHandler(UD_SYNC_INTERVAL
, synchronizeUserDefaults
, NULL
);
146 addSynchronizeTimerHandler(void)
148 static Bool initialized
= False
;
151 WMAddTimerHandler(UD_SYNC_INTERVAL
, synchronizeUserDefaults
, NULL
);
158 WMEnableUDPeriodicSynchronization(WMUserDefaults
*database
, Bool enable
)
160 database
->dontSync
= !enable
;
165 WMSynchronizeUserDefaults(WMUserDefaults
*database
)
167 Bool fileIsNewer
= False
, release
= False
, notify
= False
;
168 WMPropList
*plF
, *key
;
172 if (!database
->path
) {
173 path
= wdefaultspathfordomain(WMGetApplicationName());
176 path
= database
->path
;
179 if (stat(path
, &stbuf
) >= 0 && stbuf
.st_mtime
> database
->timestamp
)
182 if (database
->appDomain
&& (database
->dirty
|| fileIsNewer
)) {
183 if (database
->dirty
&& fileIsNewer
) {
184 plF
= WMReadPropListFromFile(path
);
186 plF
= WMMergePLDictionaries(plF
, database
->appDomain
);
187 WMReleasePropList(database
->appDomain
);
188 database
->appDomain
= plF
;
189 key
= database
->searchList
[0];
190 WMPutInPLDictionary(database
->defaults
, key
, plF
);
193 /* something happened with the file. just overwrite it */
194 wwarning(_("cannot read domain from file '%s' when syncing"),
196 WMWritePropListToFile(database
->appDomain
, path
, True
);
198 } else if (database
->dirty
) {
199 WMWritePropListToFile(database
->appDomain
, path
, True
);
200 } else if (fileIsNewer
) {
201 plF
= WMReadPropListFromFile(path
);
203 WMReleasePropList(database
->appDomain
);
204 database
->appDomain
= plF
;
205 key
= database
->searchList
[0];
206 WMPutInPLDictionary(database
->defaults
, key
, plF
);
209 /* something happened with the file. just overwrite it */
210 wwarning(_("cannot read domain from file '%s' when syncing"),
212 WMWritePropListToFile(database
->appDomain
, path
, True
);
218 if (stat(path
, &stbuf
) >= 0)
219 database
->timestamp
= stbuf
.st_mtime
;
222 WMPostNotificationName(WMUserDefaultsDidChangeNotification
,
234 WMSaveUserDefaults(WMUserDefaults
*database
)
236 if (database
->appDomain
) {
239 Bool release
= False
;
241 if (!database
->path
) {
242 path
= wdefaultspathfordomain(WMGetApplicationName());
245 path
= database
->path
;
247 WMWritePropListToFile(database
->appDomain
, path
, True
);
249 if (stat(path
, &stbuf
) >= 0)
250 database
->timestamp
= stbuf
.st_mtime
;
258 WMGetStandardUserDefaults(void)
260 WMUserDefaults
*defaults
;
267 if (sharedUserDefaults
) {
268 defaults
= sharedUserDefaults
;
270 /* Trick, path == NULL only for StandardUserDefaults db */
271 if (defaults
->path
== NULL
)
273 defaults
= defaults
->next
;
277 /* we didn't found the database we are looking for. Go read it. */
278 defaults
= wmalloc(sizeof(WMUserDefaults
));
279 memset(defaults
, 0, sizeof(WMUserDefaults
));
281 defaults
->defaults
= WMCreatePLDictionary(NULL
, NULL
, NULL
);
283 defaults
->searchList
= wmalloc(sizeof(WMPropList
*)*3);
285 /* application domain */
286 key
= WMCreatePLString(WMGetApplicationName());
287 defaults
->searchList
[0] = key
;
289 /* temporary kluge */
290 if (strcmp(WMGetApplicationName(), "WindowMaker")==0) {
294 path
= wdefaultspathfordomain(WMGetFromPLString(key
));
296 if (stat(path
, &stbuf
) >= 0)
297 defaults
->timestamp
= stbuf
.st_mtime
;
299 domain
= WMReadPropListFromFile(path
);
303 domain
= WMCreatePLDictionary(NULL
, NULL
, NULL
);
308 defaults
->appDomain
= domain
;
311 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
314 key
= WMCreatePLString("WMGLOBAL");
315 defaults
->searchList
[1] = key
;
317 path
= wdefaultspathfordomain(WMGetFromPLString(key
));
319 domain
= WMReadPropListFromFile(path
);
324 domain
= WMCreatePLDictionary(NULL
, NULL
, NULL
);
327 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
330 defaults
->searchList
[2] = NULL
;
332 defaults
->searchListArray
= WMCreatePLArray(NULL
,NULL
);
335 while (defaults
->searchList
[i
]) {
336 WMAddToPLArray(defaults
->searchListArray
,
337 defaults
->searchList
[i
]);
341 if (sharedUserDefaults
)
342 defaults
->next
= sharedUserDefaults
;
343 sharedUserDefaults
= defaults
;
345 addSynchronizeTimerHandler();
346 registerSaveOnExit();
353 WMGetDefaultsFromPath(char *path
)
355 WMUserDefaults
*defaults
;
362 assert(path
!= NULL
);
364 if (sharedUserDefaults
) {
365 defaults
= sharedUserDefaults
;
367 if (defaults
->path
&& strcmp(defaults
->path
, path
) == 0)
369 defaults
= defaults
->next
;
373 /* we didn't found the database we are looking for. Go read it. */
374 defaults
= wmalloc(sizeof(WMUserDefaults
));
375 memset(defaults
, 0, sizeof(WMUserDefaults
));
377 defaults
->defaults
= WMCreatePLDictionary(NULL
, NULL
, NULL
);
379 defaults
->searchList
= wmalloc(sizeof(WMPropList
*)*2);
381 /* the domain we want, go in the first position */
382 name
= strrchr(path
, '/');
388 key
= WMCreatePLString(name
);
389 defaults
->searchList
[0] = key
;
391 if (stat(path
, &stbuf
) >= 0)
392 defaults
->timestamp
= stbuf
.st_mtime
;
394 domain
= WMReadPropListFromFile(path
);
397 domain
= WMCreatePLDictionary(NULL
, NULL
, NULL
);
399 defaults
->path
= wstrdup(path
);
401 defaults
->appDomain
= domain
;
404 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
407 defaults
->searchList
[1] = NULL
;
409 defaults
->searchListArray
= WMCreatePLArray(NULL
,NULL
);
412 while (defaults
->searchList
[i
]) {
413 WMAddToPLArray(defaults
->searchListArray
,
414 defaults
->searchList
[i
]);
418 if (sharedUserDefaults
)
419 defaults
->next
= sharedUserDefaults
;
420 sharedUserDefaults
= defaults
;
422 addSynchronizeTimerHandler();
423 registerSaveOnExit();
429 /* Returns a WMPropList array with all keys in the user defaults database.
430 * Free the array with WMReleasePropList() when no longer needed,
431 * but do not free the elements of the array! They're just references. */
433 WMGetUDKeys(WMUserDefaults
*database
)
435 return WMGetPLDictionaryKeys(database
->appDomain
);
440 WMGetUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
442 WMPropList
*domainName
, *domain
;
443 WMPropList
*object
= NULL
;
444 WMPropList
*key
= WMCreatePLString(defaultName
);
447 while (database
->searchList
[i
] && !object
) {
448 domainName
= database
->searchList
[i
];
449 domain
= WMGetFromPLDictionary(database
->defaults
, domainName
);
451 object
= WMGetFromPLDictionary(domain
, key
);
455 WMReleasePropList(key
);
462 WMSetUDObjectForKey(WMUserDefaults
*database
, WMPropList
*object
,
465 WMPropList
*key
= WMCreatePLString(defaultName
);
469 WMPutInPLDictionary(database
->appDomain
, key
, object
);
470 WMReleasePropList(key
);
475 WMRemoveUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
477 WMPropList
*key
= WMCreatePLString(defaultName
);
481 WMRemoveFromPLDictionary(database
->appDomain
, key
);
483 WMReleasePropList(key
);
488 WMGetUDStringForKey(WMUserDefaults
*database
, char *defaultName
)
492 val
= WMGetUDObjectForKey(database
, defaultName
);
497 if (!WMIsPLString(val
))
500 return WMGetFromPLString(val
);
505 WMGetUDIntegerForKey(WMUserDefaults
*database
, char *defaultName
)
511 val
= WMGetUDObjectForKey(database
, defaultName
);
516 if (!WMIsPLString(val
))
519 str
= WMGetFromPLString(val
);
523 if (sscanf(str
, "%i", &value
)!=1)
532 WMGetUDFloatForKey(WMUserDefaults
*database
, char *defaultName
)
538 val
= WMGetUDObjectForKey(database
, defaultName
);
540 if (!val
|| !WMIsPLString(val
))
543 if (!(str
= WMGetFromPLString(val
)))
546 if (sscanf(str
, "%f", &value
)!=1)
555 WMGetUDBoolForKey(WMUserDefaults
*database
, char *defaultName
)
561 val
= WMGetUDObjectForKey(database
, defaultName
);
566 if (!WMIsPLString(val
))
569 str
= WMGetFromPLString(val
);
573 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
576 if (strcasecmp(str
, "YES")==0)
579 if (strcasecmp(str
, "Y")==0)
587 WMSetUDIntegerForKey(WMUserDefaults
*database
, int value
, char *defaultName
)
592 sprintf(buffer
, "%i", value
);
593 object
= WMCreatePLString(buffer
);
595 WMSetUDObjectForKey(database
, object
, defaultName
);
596 WMReleasePropList(object
);
603 WMSetUDStringForKey(WMUserDefaults
*database
, char *value
, char *defaultName
)
607 object
= WMCreatePLString(value
);
609 WMSetUDObjectForKey(database
, object
, defaultName
);
610 WMReleasePropList(object
);
616 WMSetUDFloatForKey(WMUserDefaults
*database
, float value
, char *defaultName
)
621 sprintf(buffer
, "%f", value
);
622 object
= WMCreatePLString(buffer
);
624 WMSetUDObjectForKey(database
, object
, defaultName
);
625 WMReleasePropList(object
);
631 WMSetUDBoolForKey(WMUserDefaults
*database
, Bool value
, char *defaultName
)
633 static WMPropList
*yes
= NULL
, *no
= NULL
;
636 yes
= WMCreatePLString("YES");
637 no
= WMCreatePLString("NO");
640 WMSetUDObjectForKey(database
, value
? yes
: no
, defaultName
);
645 WMGetUDSearchList(WMUserDefaults
*database
)
647 return database
->searchListArray
;
652 WMSetUDSearchList(WMUserDefaults
*database
, WMPropList
*list
)
656 if (database
->searchList
) {
658 while (database
->searchList
[i
]) {
659 WMReleasePropList(database
->searchList
[i
]);
662 wfree(database
->searchList
);
664 if (database
->searchListArray
) {
665 WMReleasePropList(database
->searchListArray
);
668 c
= WMGetPropListItemCount(list
);
669 database
->searchList
= wmalloc(sizeof(WMPropList
*)*(c
+1));
671 for (i
=0; i
<c
; i
++) {
672 database
->searchList
[i
] = WMGetFromPLArray(list
, i
);
675 database
->searchListArray
= WMDeepCopyPropList(list
);