13 typedef struct W_UserDefaults
{
16 WMPropList
*appDomain
;
18 WMPropList
*searchListArray
;
19 WMPropList
**searchList
; /* cache for searchListArray */
25 char *path
; /* where is db located */
27 time_t timestamp
; /* last modification time */
29 struct W_UserDefaults
*next
;
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()
45 static char *path
= NULL
;
50 gspath
= getenv("GNUSTEP_USER_ROOT");
52 gspath
= wexpandpath(gspath
);
53 pathlen
= strlen(gspath
) + 4;
54 path
= wmalloc(pathlen
);
58 pathlen
= strlen(wgethomedir()) + 10;
59 path
= wmalloc(pathlen
);
60 strcpy(path
, wgethomedir());
61 strcat(path
, "/GNUstep");
68 char *wdefaultspathfordomain(char *domain
)
73 gspath
= wusergnusteppath();
74 path
= wmalloc(strlen(gspath
) + strlen(DEFAULTS_DIR
) + strlen(domain
) + 4);
76 strcat(path
, DEFAULTS_DIR
);
85 saveDefaultsChanges(void)
87 saveDefaultsChanges(int foo
, void *bar
)
90 /* save the user defaults databases */
91 synchronizeUserDefaults(NULL
);
94 /* set to save changes in defaults when program is exited */
95 static void registerSaveOnExit(void)
97 static Bool registeredSaveOnExit
= False
;
99 if (!registeredSaveOnExit
) {
101 atexit(saveDefaultsChanges
);
103 on_exit(saveDefaultsChanges
, (void *)NULL
);
105 registeredSaveOnExit
= True
;
109 static void synchronizeUserDefaults(void *foo
)
111 UserDefaults
*database
= sharedUserDefaults
;
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
;
132 if (!database
->path
) {
133 path
= wdefaultspathfordomain(WMGetApplicationName());
136 path
= database
->path
;
139 if (stat(path
, &stbuf
) >= 0 && stbuf
.st_mtime
> database
->timestamp
)
142 if (database
->appDomain
&& (database
->dirty
|| fileIsNewer
)) {
143 if (database
->dirty
&& fileIsNewer
) {
144 plF
= WMReadPropListFromFile(path
);
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
);
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
);
162 WMReleasePropList(database
->appDomain
);
163 database
->appDomain
= plF
;
164 key
= database
->searchList
[0];
165 WMPutInPLDictionary(database
->defaults
, key
, plF
);
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
);
176 if (stat(path
, &stbuf
) >= 0)
177 database
->timestamp
= stbuf
.st_mtime
;
180 WMPostNotificationName(WMUserDefaultsDidChangeNotification
, database
, NULL
);
189 void WMSaveUserDefaults(WMUserDefaults
* database
)
191 if (database
->appDomain
) {
194 Bool release
= False
;
196 if (!database
->path
) {
197 path
= wdefaultspathfordomain(WMGetApplicationName());
200 path
= database
->path
;
202 WMWritePropListToFile(database
->appDomain
, path
, True
);
204 if (stat(path
, &stbuf
) >= 0)
205 database
->timestamp
= stbuf
.st_mtime
;
211 WMUserDefaults
*WMGetStandardUserDefaults(void)
213 WMUserDefaults
*defaults
;
220 if (sharedUserDefaults
) {
221 defaults
= sharedUserDefaults
;
223 /* path == NULL only for StandardUserDefaults db */
224 if (defaults
->path
== NULL
)
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
);
255 domain
= WMCreatePLDictionary(NULL
, NULL
);
260 defaults
->appDomain
= domain
;
263 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
266 key
= WMCreatePLString("WMGLOBAL");
267 defaults
->searchList
[1] = key
;
269 path
= wdefaultspathfordomain(WMGetFromPLString(key
));
271 domain
= WMReadPropListFromFile(path
);
276 domain
= WMCreatePLDictionary(NULL
, NULL
);
279 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
282 defaults
->searchList
[2] = NULL
;
284 defaults
->searchListArray
= WMCreatePLArray(NULL
, NULL
);
287 while (defaults
->searchList
[i
]) {
288 WMAddToPLArray(defaults
->searchListArray
, defaults
->searchList
[i
]);
292 if (sharedUserDefaults
)
293 defaults
->next
= sharedUserDefaults
;
294 sharedUserDefaults
= defaults
;
296 registerSaveOnExit();
301 WMUserDefaults
*WMGetDefaultsFromPath(char *path
)
303 WMUserDefaults
*defaults
;
310 assert(path
!= NULL
);
312 if (sharedUserDefaults
) {
313 defaults
= sharedUserDefaults
;
315 if (defaults
->path
&& strcmp(defaults
->path
, path
) == 0)
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
, '/');
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
);
345 domain
= WMCreatePLDictionary(NULL
, NULL
);
347 defaults
->path
= wstrdup(path
);
349 defaults
->appDomain
= domain
;
352 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
355 defaults
->searchList
[1] = NULL
;
357 defaults
->searchListArray
= WMCreatePLArray(NULL
, NULL
);
360 while (defaults
->searchList
[i
]) {
361 WMAddToPLArray(defaults
->searchListArray
, defaults
->searchList
[i
]);
365 if (sharedUserDefaults
)
366 defaults
->next
= sharedUserDefaults
;
367 sharedUserDefaults
= defaults
;
369 registerSaveOnExit();
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
);
389 while (database
->searchList
[i
] && !object
) {
390 domainName
= database
->searchList
[i
];
391 domain
= WMGetFromPLDictionary(database
->defaults
, domainName
);
393 object
= WMGetFromPLDictionary(domain
, key
);
397 WMReleasePropList(key
);
402 void WMSetUDObjectForKey(WMUserDefaults
* database
, WMPropList
* object
, char *defaultName
)
404 WMPropList
*key
= WMCreatePLString(defaultName
);
408 WMPutInPLDictionary(database
->appDomain
, key
, object
);
409 WMReleasePropList(key
);
412 void WMRemoveUDObjectForKey(WMUserDefaults
* database
, char *defaultName
)
414 WMPropList
*key
= WMCreatePLString(defaultName
);
418 WMRemoveFromPLDictionary(database
->appDomain
, key
);
420 WMReleasePropList(key
);
423 char *WMGetUDStringForKey(WMUserDefaults
* database
, char *defaultName
)
427 val
= WMGetUDObjectForKey(database
, defaultName
);
432 if (!WMIsPLString(val
))
435 return WMGetFromPLString(val
);
438 int WMGetUDIntegerForKey(WMUserDefaults
* database
, char *defaultName
)
444 val
= WMGetUDObjectForKey(database
, defaultName
);
449 if (!WMIsPLString(val
))
452 str
= WMGetFromPLString(val
);
456 if (sscanf(str
, "%i", &value
) != 1)
462 float WMGetUDFloatForKey(WMUserDefaults
* database
, char *defaultName
)
468 val
= WMGetUDObjectForKey(database
, defaultName
);
470 if (!val
|| !WMIsPLString(val
))
473 if (!(str
= WMGetFromPLString(val
)))
476 if (sscanf(str
, "%f", &value
) != 1)
482 Bool
WMGetUDBoolForKey(WMUserDefaults
* database
, char *defaultName
)
488 val
= WMGetUDObjectForKey(database
, defaultName
);
493 if (!WMIsPLString(val
))
496 str
= WMGetFromPLString(val
);
500 if (sscanf(str
, "%i", &value
) == 1 && value
!= 0)
503 if (strcasecmp(str
, "YES") == 0)
506 if (strcasecmp(str
, "Y") == 0)
512 void WMSetUDIntegerForKey(WMUserDefaults
* database
, int value
, char *defaultName
)
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
)
528 object
= WMCreatePLString(value
);
530 WMSetUDObjectForKey(database
, object
, defaultName
);
531 WMReleasePropList(object
);
534 void WMSetUDFloatForKey(WMUserDefaults
* database
, float value
, char *defaultName
)
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
;
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
)
567 if (database
->searchList
) {
569 while (database
->searchList
[i
]) {
570 WMReleasePropList(database
->searchList
[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
);