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";
42 static void synchronizeUserDefaults(void *foo
);
44 extern char *WMGetApplicationName();
46 #define DEFAULTS_DIR "/Defaults"
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(void)
99 saveDefaultsChanges(int foo
, void *bar
)
102 /* save the user defaults databases */
103 synchronizeUserDefaults(NULL
);
107 /* set to save changes in defaults when program is exited */
109 registerSaveOnExit(void)
111 static Bool registeredSaveOnExit
= False
;
113 if (!registeredSaveOnExit
) {
115 atexit(saveDefaultsChanges
);
117 on_exit(saveDefaultsChanges
, (void*)NULL
);
119 registeredSaveOnExit
= True
;
125 synchronizeUserDefaults(void *foo
)
127 UserDefaults
*database
= sharedUserDefaults
;
130 if (!database
->dontSync
)
131 WMSynchronizeUserDefaults(database
);
132 database
= database
->next
;
140 WMEnableUDPeriodicSynchronization(WMUserDefaults
*database
, Bool enable
)
142 database
->dontSync
= !enable
;
147 WMSynchronizeUserDefaults(WMUserDefaults
*database
)
149 Bool fileIsNewer
= False
, release
= False
, notify
= False
;
150 WMPropList
*plF
, *key
;
154 if (!database
->path
) {
155 path
= wdefaultspathfordomain(WMGetApplicationName());
158 path
= database
->path
;
161 if (stat(path
, &stbuf
) >= 0 && stbuf
.st_mtime
> database
->timestamp
)
164 if (database
->appDomain
&& (database
->dirty
|| fileIsNewer
)) {
165 if (database
->dirty
&& fileIsNewer
) {
166 plF
= WMReadPropListFromFile(path
);
168 plF
= WMMergePLDictionaries(plF
, database
->appDomain
, False
);
169 WMReleasePropList(database
->appDomain
);
170 database
->appDomain
= plF
;
171 key
= database
->searchList
[0];
172 WMPutInPLDictionary(database
->defaults
, key
, plF
);
175 /* something happened with the file. just overwrite it */
176 wwarning(_("cannot read domain from file '%s' when syncing"),
178 WMWritePropListToFile(database
->appDomain
, path
, True
);
180 } else if (database
->dirty
) {
181 WMWritePropListToFile(database
->appDomain
, path
, True
);
182 } else if (fileIsNewer
) {
183 plF
= WMReadPropListFromFile(path
);
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
);
200 if (stat(path
, &stbuf
) >= 0)
201 database
->timestamp
= stbuf
.st_mtime
;
204 WMPostNotificationName(WMUserDefaultsDidChangeNotification
,
216 WMSaveUserDefaults(WMUserDefaults
*database
)
218 if (database
->appDomain
) {
221 Bool release
= False
;
223 if (!database
->path
) {
224 path
= wdefaultspathfordomain(WMGetApplicationName());
227 path
= database
->path
;
229 WMWritePropListToFile(database
->appDomain
, path
, True
);
231 if (stat(path
, &stbuf
) >= 0)
232 database
->timestamp
= stbuf
.st_mtime
;
240 WMGetStandardUserDefaults(void)
242 WMUserDefaults
*defaults
;
249 if (sharedUserDefaults
) {
250 defaults
= sharedUserDefaults
;
252 /* path == NULL only for StandardUserDefaults db */
253 if (defaults
->path
== NULL
)
255 defaults
= defaults
->next
;
259 /* we didn't found the database we are looking for. Go read it. */
260 defaults
= wmalloc(sizeof(WMUserDefaults
));
261 memset(defaults
, 0, sizeof(WMUserDefaults
));
263 defaults
->defaults
= WMCreatePLDictionary(NULL
, NULL
);
265 defaults
->searchList
= wmalloc(sizeof(WMPropList
*)*3);
267 /* application domain */
268 key
= WMCreatePLString(WMGetApplicationName());
269 defaults
->searchList
[0] = key
;
271 /* temporary kluge. wmaker handles synchronization itself */
272 if (strcmp(WMGetApplicationName(), "WindowMaker")==0) {
273 defaults
->dontSync
= 1;
276 path
= wdefaultspathfordomain(WMGetFromPLString(key
));
278 if (stat(path
, &stbuf
) >= 0)
279 defaults
->timestamp
= stbuf
.st_mtime
;
281 domain
= WMReadPropListFromFile(path
);
284 domain
= WMCreatePLDictionary(NULL
, NULL
);
289 defaults
->appDomain
= domain
;
292 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
295 key
= WMCreatePLString("WMGLOBAL");
296 defaults
->searchList
[1] = key
;
298 path
= wdefaultspathfordomain(WMGetFromPLString(key
));
300 domain
= WMReadPropListFromFile(path
);
305 domain
= WMCreatePLDictionary(NULL
, NULL
);
308 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
311 defaults
->searchList
[2] = NULL
;
313 defaults
->searchListArray
= WMCreatePLArray(NULL
,NULL
);
316 while (defaults
->searchList
[i
]) {
317 WMAddToPLArray(defaults
->searchListArray
,
318 defaults
->searchList
[i
]);
322 if (sharedUserDefaults
)
323 defaults
->next
= sharedUserDefaults
;
324 sharedUserDefaults
= defaults
;
326 registerSaveOnExit();
333 WMGetDefaultsFromPath(char *path
)
335 WMUserDefaults
*defaults
;
342 assert(path
!= NULL
);
344 if (sharedUserDefaults
) {
345 defaults
= sharedUserDefaults
;
347 if (defaults
->path
&& strcmp(defaults
->path
, path
) == 0)
349 defaults
= defaults
->next
;
353 /* we didn't found the database we are looking for. Go read it. */
354 defaults
= wmalloc(sizeof(WMUserDefaults
));
355 memset(defaults
, 0, sizeof(WMUserDefaults
));
357 defaults
->defaults
= WMCreatePLDictionary(NULL
, NULL
);
359 defaults
->searchList
= wmalloc(sizeof(WMPropList
*)*2);
361 /* the domain we want, go in the first position */
362 name
= strrchr(path
, '/');
368 key
= WMCreatePLString(name
);
369 defaults
->searchList
[0] = key
;
371 if (stat(path
, &stbuf
) >= 0)
372 defaults
->timestamp
= stbuf
.st_mtime
;
374 domain
= WMReadPropListFromFile(path
);
377 domain
= WMCreatePLDictionary(NULL
, NULL
);
379 defaults
->path
= wstrdup(path
);
381 defaults
->appDomain
= domain
;
384 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
387 defaults
->searchList
[1] = NULL
;
389 defaults
->searchListArray
= WMCreatePLArray(NULL
,NULL
);
392 while (defaults
->searchList
[i
]) {
393 WMAddToPLArray(defaults
->searchListArray
,
394 defaults
->searchList
[i
]);
398 if (sharedUserDefaults
)
399 defaults
->next
= sharedUserDefaults
;
400 sharedUserDefaults
= defaults
;
402 registerSaveOnExit();
408 /* Returns a WMPropList array with all keys in the user defaults database.
409 * Free the array with WMReleasePropList() when no longer needed,
410 * but do not free the elements of the array! They're just references. */
412 WMGetUDKeys(WMUserDefaults
*database
)
414 return WMGetPLDictionaryKeys(database
->appDomain
);
419 WMGetUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
421 WMPropList
*domainName
, *domain
;
422 WMPropList
*object
= NULL
;
423 WMPropList
*key
= WMCreatePLString(defaultName
);
426 while (database
->searchList
[i
] && !object
) {
427 domainName
= database
->searchList
[i
];
428 domain
= WMGetFromPLDictionary(database
->defaults
, domainName
);
430 object
= WMGetFromPLDictionary(domain
, key
);
434 WMReleasePropList(key
);
441 WMSetUDObjectForKey(WMUserDefaults
*database
, WMPropList
*object
,
444 WMPropList
*key
= WMCreatePLString(defaultName
);
448 WMPutInPLDictionary(database
->appDomain
, key
, object
);
449 WMReleasePropList(key
);
454 WMRemoveUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
456 WMPropList
*key
= WMCreatePLString(defaultName
);
460 WMRemoveFromPLDictionary(database
->appDomain
, key
);
462 WMReleasePropList(key
);
467 WMGetUDStringForKey(WMUserDefaults
*database
, char *defaultName
)
471 val
= WMGetUDObjectForKey(database
, defaultName
);
476 if (!WMIsPLString(val
))
479 return WMGetFromPLString(val
);
484 WMGetUDIntegerForKey(WMUserDefaults
*database
, char *defaultName
)
490 val
= WMGetUDObjectForKey(database
, defaultName
);
495 if (!WMIsPLString(val
))
498 str
= WMGetFromPLString(val
);
502 if (sscanf(str
, "%i", &value
)!=1)
511 WMGetUDFloatForKey(WMUserDefaults
*database
, char *defaultName
)
517 val
= WMGetUDObjectForKey(database
, defaultName
);
519 if (!val
|| !WMIsPLString(val
))
522 if (!(str
= WMGetFromPLString(val
)))
525 if (sscanf(str
, "%f", &value
)!=1)
534 WMGetUDBoolForKey(WMUserDefaults
*database
, char *defaultName
)
540 val
= WMGetUDObjectForKey(database
, defaultName
);
545 if (!WMIsPLString(val
))
548 str
= WMGetFromPLString(val
);
552 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
555 if (strcasecmp(str
, "YES")==0)
558 if (strcasecmp(str
, "Y")==0)
566 WMSetUDIntegerForKey(WMUserDefaults
*database
, int value
, char *defaultName
)
571 sprintf(buffer
, "%i", value
);
572 object
= WMCreatePLString(buffer
);
574 WMSetUDObjectForKey(database
, object
, defaultName
);
575 WMReleasePropList(object
);
582 WMSetUDStringForKey(WMUserDefaults
*database
, char *value
, char *defaultName
)
586 object
= WMCreatePLString(value
);
588 WMSetUDObjectForKey(database
, object
, defaultName
);
589 WMReleasePropList(object
);
595 WMSetUDFloatForKey(WMUserDefaults
*database
, float value
, char *defaultName
)
600 sprintf(buffer
, "%f", value
);
601 object
= WMCreatePLString(buffer
);
603 WMSetUDObjectForKey(database
, object
, defaultName
);
604 WMReleasePropList(object
);
610 WMSetUDBoolForKey(WMUserDefaults
*database
, Bool value
, char *defaultName
)
612 static WMPropList
*yes
= NULL
, *no
= NULL
;
615 yes
= WMCreatePLString("YES");
616 no
= WMCreatePLString("NO");
619 WMSetUDObjectForKey(database
, value
? yes
: no
, defaultName
);
624 WMGetUDSearchList(WMUserDefaults
*database
)
626 return database
->searchListArray
;
631 WMSetUDSearchList(WMUserDefaults
*database
, WMPropList
*list
)
635 if (database
->searchList
) {
637 while (database
->searchList
[i
]) {
638 WMReleasePropList(database
->searchList
[i
]);
641 wfree(database
->searchList
);
643 if (database
->searchListArray
) {
644 WMReleasePropList(database
->searchListArray
);
647 c
= WMGetPropListItemCount(list
);
648 database
->searchList
= wmalloc(sizeof(WMPropList
*)*(c
+1));
650 for (i
=0; i
<c
; i
++) {
651 database
->searchList
[i
] = WMGetFromPLArray(list
, i
);
653 database
->searchList
[c
] = NULL
;
655 database
->searchListArray
= WMDeepCopyPropList(list
);