16 typedef struct W_UserDefaults
{
19 WMPropList
*appDomain
;
21 WMPropList
*searchListArray
;
22 WMPropList
**searchList
; /* cache for searchListArray */
28 char *path
; /* where is db located */
30 time_t timestamp
; /* last modification time */
32 struct W_UserDefaults
*next
;
37 static UserDefaults
*sharedUserDefaults
= NULL
;
39 char *WMUserDefaultsDidChangeNotification
= "WMUserDefaultsDidChangeNotification";
43 extern char *WMGetApplicationName();
45 #define DEFAULTS_DIR "/Defaults"
47 #define UD_SYNC_INTERVAL 2000
54 static char *path
= NULL
;
59 gspath
= getenv("GNUSTEP_USER_ROOT");
61 gspath
= wexpandpath(gspath
);
62 pathlen
= strlen(gspath
) + 4;
63 path
= wmalloc(pathlen
);
67 pathlen
= strlen(wgethomedir()) + 10;
68 path
= wmalloc(pathlen
);
69 strcpy(path
, wgethomedir());
70 strcat(path
, "/GNUstep");
79 wdefaultspathfordomain(char *domain
)
84 gspath
= wusergnusteppath();
85 path
= wmalloc(strlen(gspath
)+strlen(DEFAULTS_DIR
)+strlen(domain
)+4);
87 strcat(path
, DEFAULTS_DIR
);
97 saveDefaultsChanges(int foo
, void *bar
)
99 saveDefaultsChanges(void)
102 /* save the user defaults databases */
103 UserDefaults
*tmp
= sharedUserDefaults
;
106 WMSynchronizeUserDefaults(tmp
);
112 /* set to save changes in defaults when program is exited */
114 registerSaveOnExit(void)
116 static Bool registeredSaveOnExit
= False
;
118 if (!registeredSaveOnExit
) {
120 on_exit(saveDefaultsChanges
, (void*)NULL
);
122 atexit(saveDefaultsChanges
);
124 registeredSaveOnExit
= True
;
130 synchronizeUserDefaults(void *foo
)
132 UserDefaults
*database
= sharedUserDefaults
;
135 if (!database
->dontSync
)
136 WMSynchronizeUserDefaults(database
);
137 database
= database
->next
;
139 WMAddTimerHandler(UD_SYNC_INTERVAL
, synchronizeUserDefaults
, NULL
);
144 addSynchronizeTimerHandler(void)
146 static Bool initialized
= False
;
149 WMAddTimerHandler(UD_SYNC_INTERVAL
, synchronizeUserDefaults
, NULL
);
156 WMEnableUDPeriodicSynchronization(WMUserDefaults
*database
, Bool enable
)
158 database
->dontSync
= !enable
;
163 WMSynchronizeUserDefaults(WMUserDefaults
*database
)
165 Bool fileIsNewer
= False
, release
= False
, notify
= False
;
166 WMPropList
*plF
, *key
;
170 if (!database
->path
) {
171 path
= wdefaultspathfordomain(WMGetApplicationName());
174 path
= database
->path
;
177 if (stat(path
, &stbuf
) >= 0 && stbuf
.st_mtime
> database
->timestamp
)
180 if (database
->appDomain
&& (database
->dirty
|| fileIsNewer
)) {
181 if (database
->dirty
&& fileIsNewer
) {
182 plF
= WMReadPropListFromFile(path
);
184 plF
= WMMergePLDictionaries(plF
, database
->appDomain
);
185 WMReleasePropList(database
->appDomain
);
186 database
->appDomain
= plF
;
187 key
= database
->searchList
[0];
188 WMPutInPLDictionary(database
->defaults
, key
, plF
);
191 /* something happened with the file. just overwrite it */
192 wwarning(_("cannot read domain from file '%s' when syncing"),
194 WMWritePropListToFile(database
->appDomain
, path
, True
);
196 } else if (database
->dirty
) {
197 WMWritePropListToFile(database
->appDomain
, path
, True
);
198 } else if (fileIsNewer
) {
199 plF
= WMReadPropListFromFile(path
);
201 WMReleasePropList(database
->appDomain
);
202 database
->appDomain
= plF
;
203 key
= database
->searchList
[0];
204 WMPutInPLDictionary(database
->defaults
, key
, plF
);
207 /* something happened with the file. just overwrite it */
208 wwarning(_("cannot read domain from file '%s' when syncing"),
210 WMWritePropListToFile(database
->appDomain
, path
, True
);
216 if (stat(path
, &stbuf
) >= 0)
217 database
->timestamp
= stbuf
.st_mtime
;
220 WMPostNotificationName(WMUserDefaultsDidChangeNotification
,
232 WMSaveUserDefaults(WMUserDefaults
*database
)
234 if (database
->appDomain
) {
237 Bool release
= False
;
239 if (!database
->path
) {
240 path
= wdefaultspathfordomain(WMGetApplicationName());
243 path
= database
->path
;
245 WMWritePropListToFile(database
->appDomain
, path
, True
);
247 if (stat(path
, &stbuf
) >= 0)
248 database
->timestamp
= stbuf
.st_mtime
;
256 WMGetStandardUserDefaults(void)
258 WMUserDefaults
*defaults
;
265 if (sharedUserDefaults
) {
266 defaults
= sharedUserDefaults
;
268 /* Trick, path == NULL only for StandardUserDefaults db */
269 if (defaults
->path
== NULL
)
271 defaults
= defaults
->next
;
275 /* we didn't found the database we are looking for. Go read it. */
276 defaults
= wmalloc(sizeof(WMUserDefaults
));
277 memset(defaults
, 0, sizeof(WMUserDefaults
));
279 defaults
->defaults
= WMCreatePLDictionary(NULL
, NULL
, NULL
);
281 defaults
->searchList
= wmalloc(sizeof(WMPropList
*)*3);
283 /* application domain */
284 key
= WMCreatePLString(WMGetApplicationName());
285 defaults
->searchList
[0] = key
;
287 /* temporary kluge */
288 if (strcmp(WMGetApplicationName(), "WindowMaker")==0) {
292 path
= wdefaultspathfordomain(WMGetFromPLString(key
));
294 if (stat(path
, &stbuf
) >= 0)
295 defaults
->timestamp
= stbuf
.st_mtime
;
297 domain
= WMReadPropListFromFile(path
);
301 domain
= WMCreatePLDictionary(NULL
, NULL
, NULL
);
306 defaults
->appDomain
= domain
;
309 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
312 key
= WMCreatePLString("WMGLOBAL");
313 defaults
->searchList
[1] = key
;
315 path
= wdefaultspathfordomain(WMGetFromPLString(key
));
317 domain
= WMReadPropListFromFile(path
);
322 domain
= WMCreatePLDictionary(NULL
, NULL
, NULL
);
325 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
328 defaults
->searchList
[2] = NULL
;
330 defaults
->searchListArray
= WMCreatePLArray(NULL
,NULL
);
333 while (defaults
->searchList
[i
]) {
334 WMAddToPLArray(defaults
->searchListArray
,
335 defaults
->searchList
[i
]);
339 if (sharedUserDefaults
)
340 defaults
->next
= sharedUserDefaults
;
341 sharedUserDefaults
= defaults
;
343 addSynchronizeTimerHandler();
344 registerSaveOnExit();
351 WMGetDefaultsFromPath(char *path
)
353 WMUserDefaults
*defaults
;
360 assert(path
!= NULL
);
362 if (sharedUserDefaults
) {
363 defaults
= sharedUserDefaults
;
365 if (defaults
->path
&& strcmp(defaults
->path
, path
) == 0)
367 defaults
= defaults
->next
;
371 /* we didn't found the database we are looking for. Go read it. */
372 defaults
= wmalloc(sizeof(WMUserDefaults
));
373 memset(defaults
, 0, sizeof(WMUserDefaults
));
375 defaults
->defaults
= WMCreatePLDictionary(NULL
, NULL
, NULL
);
377 defaults
->searchList
= wmalloc(sizeof(WMPropList
*)*2);
379 /* the domain we want, go in the first position */
380 name
= strrchr(path
, '/');
386 key
= WMCreatePLString(name
);
387 defaults
->searchList
[0] = key
;
389 if (stat(path
, &stbuf
) >= 0)
390 defaults
->timestamp
= stbuf
.st_mtime
;
392 domain
= WMReadPropListFromFile(path
);
395 domain
= WMCreatePLDictionary(NULL
, NULL
, NULL
);
397 defaults
->path
= wstrdup(path
);
399 defaults
->appDomain
= domain
;
402 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
405 defaults
->searchList
[1] = NULL
;
407 defaults
->searchListArray
= WMCreatePLArray(NULL
,NULL
);
410 while (defaults
->searchList
[i
]) {
411 WMAddToPLArray(defaults
->searchListArray
,
412 defaults
->searchList
[i
]);
416 if (sharedUserDefaults
)
417 defaults
->next
= sharedUserDefaults
;
418 sharedUserDefaults
= defaults
;
420 addSynchronizeTimerHandler();
421 registerSaveOnExit();
427 /* Returns a WMPropList array with all keys in the user defaults database.
428 * Free the array with WMReleasePropList() when no longer needed,
429 * but do not free the elements of the array! They're just references. */
431 WMGetUDKeys(WMUserDefaults
*database
)
433 return WMGetPLDictionaryKeys(database
->appDomain
);
438 WMGetUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
440 WMPropList
*domainName
, *domain
;
441 WMPropList
*object
= NULL
;
442 WMPropList
*key
= WMCreatePLString(defaultName
);
445 while (database
->searchList
[i
] && !object
) {
446 domainName
= database
->searchList
[i
];
447 domain
= WMGetFromPLDictionary(database
->defaults
, domainName
);
449 object
= WMGetFromPLDictionary(domain
, key
);
453 WMReleasePropList(key
);
460 WMSetUDObjectForKey(WMUserDefaults
*database
, WMPropList
*object
,
463 WMPropList
*key
= WMCreatePLString(defaultName
);
467 WMPutInPLDictionary(database
->appDomain
, key
, object
);
468 WMReleasePropList(key
);
473 WMRemoveUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
475 WMPropList
*key
= WMCreatePLString(defaultName
);
479 WMRemoveFromPLDictionary(database
->appDomain
, key
);
481 WMReleasePropList(key
);
486 WMGetUDStringForKey(WMUserDefaults
*database
, char *defaultName
)
490 val
= WMGetUDObjectForKey(database
, defaultName
);
495 if (!WMIsPLString(val
))
498 return WMGetFromPLString(val
);
503 WMGetUDIntegerForKey(WMUserDefaults
*database
, char *defaultName
)
509 val
= WMGetUDObjectForKey(database
, defaultName
);
514 if (!WMIsPLString(val
))
517 str
= WMGetFromPLString(val
);
521 if (sscanf(str
, "%i", &value
)!=1)
530 WMGetUDFloatForKey(WMUserDefaults
*database
, char *defaultName
)
536 val
= WMGetUDObjectForKey(database
, defaultName
);
538 if (!val
|| !WMIsPLString(val
))
541 if (!(str
= WMGetFromPLString(val
)))
544 if (sscanf(str
, "%f", &value
)!=1)
553 WMGetUDBoolForKey(WMUserDefaults
*database
, char *defaultName
)
559 val
= WMGetUDObjectForKey(database
, defaultName
);
564 if (!WMIsPLString(val
))
567 str
= WMGetFromPLString(val
);
571 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
574 if (strcasecmp(str
, "YES")==0)
577 if (strcasecmp(str
, "Y")==0)
585 WMSetUDIntegerForKey(WMUserDefaults
*database
, int value
, char *defaultName
)
590 sprintf(buffer
, "%i", value
);
591 object
= WMCreatePLString(buffer
);
593 WMSetUDObjectForKey(database
, object
, defaultName
);
594 WMReleasePropList(object
);
601 WMSetUDStringForKey(WMUserDefaults
*database
, char *value
, char *defaultName
)
605 object
= WMCreatePLString(value
);
607 WMSetUDObjectForKey(database
, object
, defaultName
);
608 WMReleasePropList(object
);
614 WMSetUDFloatForKey(WMUserDefaults
*database
, float value
, char *defaultName
)
619 sprintf(buffer
, "%f", value
);
620 object
= WMCreatePLString(buffer
);
622 WMSetUDObjectForKey(database
, object
, defaultName
);
623 WMReleasePropList(object
);
629 WMSetUDBoolForKey(WMUserDefaults
*database
, Bool value
, char *defaultName
)
631 static WMPropList
*yes
= NULL
, *no
= NULL
;
634 yes
= WMCreatePLString("YES");
635 no
= WMCreatePLString("NO");
638 WMSetUDObjectForKey(database
, value
? yes
: no
, defaultName
);
643 WMGetUDSearchList(WMUserDefaults
*database
)
645 return database
->searchListArray
;
650 WMSetUDSearchList(WMUserDefaults
*database
, WMPropList
*list
)
654 if (database
->searchList
) {
656 while (database
->searchList
[i
]) {
657 WMReleasePropList(database
->searchList
[i
]);
660 wfree(database
->searchList
);
662 if (database
->searchListArray
) {
663 WMReleasePropList(database
->searchListArray
);
666 c
= WMGetPropListItemCount(list
);
667 database
->searchList
= wmalloc(sizeof(WMPropList
*)*(c
+1));
669 for (i
=0; i
<c
; i
++) {
670 database
->searchList
[i
] = WMGetFromPLArray(list
, i
);
673 database
->searchListArray
= WMDeepCopyPropList(list
);