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"
48 #define UD_SYNC_INTERVAL 2000
55 static char *path
= NULL
;
60 gspath
= getenv("GNUSTEP_USER_ROOT");
62 gspath
= wexpandpath(gspath
);
63 pathlen
= strlen(gspath
) + 4;
64 path
= wmalloc(pathlen
);
68 pathlen
= strlen(wgethomedir()) + 10;
69 path
= wmalloc(pathlen
);
70 strcpy(path
, wgethomedir());
71 strcat(path
, "/GNUstep");
80 wdefaultspathfordomain(char *domain
)
85 gspath
= wusergnusteppath();
86 path
= wmalloc(strlen(gspath
)+strlen(DEFAULTS_DIR
)+strlen(domain
)+4);
88 strcat(path
, DEFAULTS_DIR
);
98 saveDefaultsChanges(void)
100 saveDefaultsChanges(int foo
, void *bar
)
103 /* save the user defaults databases */
104 synchronizeUserDefaults(NULL
);
108 /* set to save changes in defaults when program is exited */
110 registerSaveOnExit(void)
112 static Bool registeredSaveOnExit
= False
;
114 if (!registeredSaveOnExit
) {
116 atexit(saveDefaultsChanges
);
118 on_exit(saveDefaultsChanges
, (void*)NULL
);
120 registeredSaveOnExit
= True
;
126 synchronizeUserDefaults(void *foo
)
128 UserDefaults
*database
= sharedUserDefaults
;
131 if (!database
->dontSync
)
132 WMSynchronizeUserDefaults(database
);
133 database
= database
->next
;
139 addSynchronizeTimerHandler(void)
141 static Bool initialized
= False
;
144 WMAddPersistentTimerHandler(UD_SYNC_INTERVAL
, synchronizeUserDefaults
,
152 WMEnableUDPeriodicSynchronization(WMUserDefaults
*database
, Bool enable
)
154 database
->dontSync
= !enable
;
159 WMSynchronizeUserDefaults(WMUserDefaults
*database
)
161 Bool fileIsNewer
= False
, release
= False
, notify
= False
;
162 WMPropList
*plF
, *key
;
166 if (!database
->path
) {
167 path
= wdefaultspathfordomain(WMGetApplicationName());
170 path
= database
->path
;
173 if (stat(path
, &stbuf
) >= 0 && stbuf
.st_mtime
> database
->timestamp
)
176 if (database
->appDomain
&& (database
->dirty
|| fileIsNewer
)) {
177 if (database
->dirty
&& fileIsNewer
) {
178 plF
= WMReadPropListFromFile(path
);
180 plF
= WMMergePLDictionaries(plF
, database
->appDomain
, False
);
181 WMReleasePropList(database
->appDomain
);
182 database
->appDomain
= plF
;
183 key
= database
->searchList
[0];
184 WMPutInPLDictionary(database
->defaults
, key
, plF
);
187 /* something happened with the file. just overwrite it */
188 wwarning(_("cannot read domain from file '%s' when syncing"),
190 WMWritePropListToFile(database
->appDomain
, path
, True
);
192 } else if (database
->dirty
) {
193 WMWritePropListToFile(database
->appDomain
, path
, True
);
194 } else if (fileIsNewer
) {
195 plF
= WMReadPropListFromFile(path
);
197 WMReleasePropList(database
->appDomain
);
198 database
->appDomain
= plF
;
199 key
= database
->searchList
[0];
200 WMPutInPLDictionary(database
->defaults
, key
, plF
);
203 /* something happened with the file. just overwrite it */
204 wwarning(_("cannot read domain from file '%s' when syncing"),
206 WMWritePropListToFile(database
->appDomain
, path
, True
);
212 if (stat(path
, &stbuf
) >= 0)
213 database
->timestamp
= stbuf
.st_mtime
;
216 WMPostNotificationName(WMUserDefaultsDidChangeNotification
,
228 WMSaveUserDefaults(WMUserDefaults
*database
)
230 if (database
->appDomain
) {
233 Bool release
= False
;
235 if (!database
->path
) {
236 path
= wdefaultspathfordomain(WMGetApplicationName());
239 path
= database
->path
;
241 WMWritePropListToFile(database
->appDomain
, path
, True
);
243 if (stat(path
, &stbuf
) >= 0)
244 database
->timestamp
= stbuf
.st_mtime
;
252 WMGetStandardUserDefaults(void)
254 WMUserDefaults
*defaults
;
261 if (sharedUserDefaults
) {
262 defaults
= sharedUserDefaults
;
264 /* path == NULL only for StandardUserDefaults db */
265 if (defaults
->path
== NULL
)
267 defaults
= defaults
->next
;
271 /* we didn't found the database we are looking for. Go read it. */
272 defaults
= wmalloc(sizeof(WMUserDefaults
));
273 memset(defaults
, 0, sizeof(WMUserDefaults
));
275 defaults
->defaults
= WMCreatePLDictionary(NULL
, NULL
);
277 defaults
->searchList
= wmalloc(sizeof(WMPropList
*)*3);
279 /* application domain */
280 key
= WMCreatePLString(WMGetApplicationName());
281 defaults
->searchList
[0] = key
;
283 /* temporary kluge. wmaker handles synchronization itself */
284 if (strcmp(WMGetApplicationName(), "WindowMaker")==0) {
285 defaults
->dontSync
= 1;
288 path
= wdefaultspathfordomain(WMGetFromPLString(key
));
290 if (stat(path
, &stbuf
) >= 0)
291 defaults
->timestamp
= stbuf
.st_mtime
;
293 domain
= WMReadPropListFromFile(path
);
296 domain
= WMCreatePLDictionary(NULL
, NULL
);
301 defaults
->appDomain
= domain
;
304 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
307 key
= WMCreatePLString("WMGLOBAL");
308 defaults
->searchList
[1] = key
;
310 path
= wdefaultspathfordomain(WMGetFromPLString(key
));
312 domain
= WMReadPropListFromFile(path
);
317 domain
= WMCreatePLDictionary(NULL
, NULL
);
320 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
323 defaults
->searchList
[2] = NULL
;
325 defaults
->searchListArray
= WMCreatePLArray(NULL
,NULL
);
328 while (defaults
->searchList
[i
]) {
329 WMAddToPLArray(defaults
->searchListArray
,
330 defaults
->searchList
[i
]);
334 if (sharedUserDefaults
)
335 defaults
->next
= sharedUserDefaults
;
336 sharedUserDefaults
= defaults
;
338 addSynchronizeTimerHandler();
339 registerSaveOnExit();
346 WMGetDefaultsFromPath(char *path
)
348 WMUserDefaults
*defaults
;
355 assert(path
!= NULL
);
357 if (sharedUserDefaults
) {
358 defaults
= sharedUserDefaults
;
360 if (defaults
->path
&& strcmp(defaults
->path
, path
) == 0)
362 defaults
= defaults
->next
;
366 /* we didn't found the database we are looking for. Go read it. */
367 defaults
= wmalloc(sizeof(WMUserDefaults
));
368 memset(defaults
, 0, sizeof(WMUserDefaults
));
370 defaults
->defaults
= WMCreatePLDictionary(NULL
, NULL
);
372 defaults
->searchList
= wmalloc(sizeof(WMPropList
*)*2);
374 /* the domain we want, go in the first position */
375 name
= strrchr(path
, '/');
381 key
= WMCreatePLString(name
);
382 defaults
->searchList
[0] = key
;
384 if (stat(path
, &stbuf
) >= 0)
385 defaults
->timestamp
= stbuf
.st_mtime
;
387 domain
= WMReadPropListFromFile(path
);
390 domain
= WMCreatePLDictionary(NULL
, NULL
);
392 defaults
->path
= wstrdup(path
);
394 defaults
->appDomain
= domain
;
397 WMPutInPLDictionary(defaults
->defaults
, key
, domain
);
400 defaults
->searchList
[1] = NULL
;
402 defaults
->searchListArray
= WMCreatePLArray(NULL
,NULL
);
405 while (defaults
->searchList
[i
]) {
406 WMAddToPLArray(defaults
->searchListArray
,
407 defaults
->searchList
[i
]);
411 if (sharedUserDefaults
)
412 defaults
->next
= sharedUserDefaults
;
413 sharedUserDefaults
= defaults
;
415 addSynchronizeTimerHandler();
416 registerSaveOnExit();
422 /* Returns a WMPropList array with all keys in the user defaults database.
423 * Free the array with WMReleasePropList() when no longer needed,
424 * but do not free the elements of the array! They're just references. */
426 WMGetUDKeys(WMUserDefaults
*database
)
428 return WMGetPLDictionaryKeys(database
->appDomain
);
433 WMGetUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
435 WMPropList
*domainName
, *domain
;
436 WMPropList
*object
= NULL
;
437 WMPropList
*key
= WMCreatePLString(defaultName
);
440 while (database
->searchList
[i
] && !object
) {
441 domainName
= database
->searchList
[i
];
442 domain
= WMGetFromPLDictionary(database
->defaults
, domainName
);
444 object
= WMGetFromPLDictionary(domain
, key
);
448 WMReleasePropList(key
);
455 WMSetUDObjectForKey(WMUserDefaults
*database
, WMPropList
*object
,
458 WMPropList
*key
= WMCreatePLString(defaultName
);
462 WMPutInPLDictionary(database
->appDomain
, key
, object
);
463 WMReleasePropList(key
);
468 WMRemoveUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
470 WMPropList
*key
= WMCreatePLString(defaultName
);
474 WMRemoveFromPLDictionary(database
->appDomain
, key
);
476 WMReleasePropList(key
);
481 WMGetUDStringForKey(WMUserDefaults
*database
, char *defaultName
)
485 val
= WMGetUDObjectForKey(database
, defaultName
);
490 if (!WMIsPLString(val
))
493 return WMGetFromPLString(val
);
498 WMGetUDIntegerForKey(WMUserDefaults
*database
, char *defaultName
)
504 val
= WMGetUDObjectForKey(database
, defaultName
);
509 if (!WMIsPLString(val
))
512 str
= WMGetFromPLString(val
);
516 if (sscanf(str
, "%i", &value
)!=1)
525 WMGetUDFloatForKey(WMUserDefaults
*database
, char *defaultName
)
531 val
= WMGetUDObjectForKey(database
, defaultName
);
533 if (!val
|| !WMIsPLString(val
))
536 if (!(str
= WMGetFromPLString(val
)))
539 if (sscanf(str
, "%f", &value
)!=1)
548 WMGetUDBoolForKey(WMUserDefaults
*database
, char *defaultName
)
554 val
= WMGetUDObjectForKey(database
, defaultName
);
559 if (!WMIsPLString(val
))
562 str
= WMGetFromPLString(val
);
566 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
569 if (strcasecmp(str
, "YES")==0)
572 if (strcasecmp(str
, "Y")==0)
580 WMSetUDIntegerForKey(WMUserDefaults
*database
, int value
, char *defaultName
)
585 sprintf(buffer
, "%i", value
);
586 object
= WMCreatePLString(buffer
);
588 WMSetUDObjectForKey(database
, object
, defaultName
);
589 WMReleasePropList(object
);
596 WMSetUDStringForKey(WMUserDefaults
*database
, char *value
, char *defaultName
)
600 object
= WMCreatePLString(value
);
602 WMSetUDObjectForKey(database
, object
, defaultName
);
603 WMReleasePropList(object
);
609 WMSetUDFloatForKey(WMUserDefaults
*database
, float value
, char *defaultName
)
614 sprintf(buffer
, "%f", value
);
615 object
= WMCreatePLString(buffer
);
617 WMSetUDObjectForKey(database
, object
, defaultName
);
618 WMReleasePropList(object
);
624 WMSetUDBoolForKey(WMUserDefaults
*database
, Bool value
, char *defaultName
)
626 static WMPropList
*yes
= NULL
, *no
= NULL
;
629 yes
= WMCreatePLString("YES");
630 no
= WMCreatePLString("NO");
633 WMSetUDObjectForKey(database
, value
? yes
: no
, defaultName
);
638 WMGetUDSearchList(WMUserDefaults
*database
)
640 return database
->searchListArray
;
645 WMSetUDSearchList(WMUserDefaults
*database
, WMPropList
*list
)
649 if (database
->searchList
) {
651 while (database
->searchList
[i
]) {
652 WMReleasePropList(database
->searchList
[i
]);
655 wfree(database
->searchList
);
657 if (database
->searchListArray
) {
658 WMReleasePropList(database
->searchListArray
);
661 c
= WMGetPropListItemCount(list
);
662 database
->searchList
= wmalloc(sizeof(WMPropList
*)*(c
+1));
664 for (i
=0; i
<c
; i
++) {
665 database
->searchList
[i
] = WMGetFromPLArray(list
, i
);
667 database
->searchList
[c
] = NULL
;
669 database
->searchListArray
= WMDeepCopyPropList(list
);