10 #include "../src/config.h"
17 typedef struct W_UserDefaults
{
22 proplist_t searchListArray
;
23 proplist_t
*searchList
; /* cache for searchListArray */
29 char *path
; /* where is db located */
31 time_t timestamp
; /* last modification time */
33 struct W_UserDefaults
*next
;
38 static UserDefaults
*sharedUserDefaults
= NULL
;
40 char *WMUserDefaultsDidChangeNotification
= "WMUserDefaultsDidChangeNotification";
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(int foo
, void *bar
)
100 saveDefaultsChanges(void)
103 /* save the user defaults databases */
104 UserDefaults
*tmp
= sharedUserDefaults
;
107 WMSynchronizeUserDefaults(tmp
);
113 /* set to save changes in defaults when program is exited */
115 registerSaveOnExit(void)
117 static Bool registeredSaveOnExit
= False
;
119 if (!registeredSaveOnExit
) {
121 on_exit(saveDefaultsChanges
, (void*)NULL
);
123 atexit(saveDefaultsChanges
);
125 registeredSaveOnExit
= True
;
131 synchronizeUserDefaults(void *foo
)
133 UserDefaults
*database
= sharedUserDefaults
;
136 if (!database
->dontSync
)
137 WMSynchronizeUserDefaults(database
);
138 database
= database
->next
;
140 WMAddTimerHandler(UD_SYNC_INTERVAL
, synchronizeUserDefaults
, NULL
);
145 addSynchronizeTimerHandler(void)
147 static Bool initialized
= False
;
150 WMAddTimerHandler(UD_SYNC_INTERVAL
, synchronizeUserDefaults
, NULL
);
157 WMEnableUDPeriodicSynchronization(WMUserDefaults
*database
, Bool enable
)
159 database
->dontSync
= !enable
;
164 WMSynchronizeUserDefaults(WMUserDefaults
*database
)
166 Bool fileIsNewer
= False
, release
= False
;
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
)) {
182 /*fprintf(stderr, "syncing: %s %d %d\n", path, database->dirty, fileIsNewer);*/
184 PLShallowSynchronize(database
->appDomain
);
186 if (stat(path
, &stbuf
) >= 0)
187 database
->timestamp
= stbuf
.st_mtime
;
189 WMPostNotificationName(WMUserDefaultsDidChangeNotification
,
201 WMSaveUserDefaults(WMUserDefaults
*database
)
203 if (database
->appDomain
) {
206 Bool release
= False
;
208 PLSave(database
->appDomain
, YES
);
210 if (!database
->path
) {
211 path
= wdefaultspathfordomain(WMGetApplicationName());
214 path
= database
->path
;
216 if (stat(path
, &stbuf
) >= 0)
217 database
->timestamp
= stbuf
.st_mtime
;
225 WMGetStandardUserDefaults(void)
227 WMUserDefaults
*defaults
;
234 if (sharedUserDefaults
) {
235 defaults
= sharedUserDefaults
;
237 /* Trick, path == NULL only for StandardUserDefaults db */
238 if (defaults
->path
== NULL
)
240 defaults
= defaults
->next
;
244 /* we didn't found the database we are looking for. Go read it. */
245 defaults
= wmalloc(sizeof(WMUserDefaults
));
246 memset(defaults
, 0, sizeof(WMUserDefaults
));
248 defaults
->defaults
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
250 defaults
->searchList
= wmalloc(sizeof(proplist_t
)*3);
252 /* application domain */
253 key
= PLMakeString(WMGetApplicationName());
254 defaults
->searchList
[0] = key
;
256 /* temporary kluge */
257 if (strcmp(WMGetApplicationName(), "WindowMaker")==0) {
261 path
= wdefaultspathfordomain(PLGetString(key
));
263 if (stat(path
, &stbuf
) >= 0)
264 defaults
->timestamp
= stbuf
.st_mtime
;
266 domain
= PLGetProplistWithPath(path
);
271 domain
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
273 p
= PLMakeString(path
);
274 PLSetFilename(domain
, p
);
281 defaults
->appDomain
= domain
;
284 PLInsertDictionaryEntry(defaults
->defaults
, key
, domain
);
289 key
= PLMakeString("WMGLOBAL");
290 defaults
->searchList
[1] = key
;
292 path
= wdefaultspathfordomain(PLGetString(key
));
294 domain
= PLGetProplistWithPath(path
);
299 domain
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
302 PLInsertDictionaryEntry(defaults
->defaults
, key
, domain
);
307 defaults
->searchList
[2] = NULL
;
309 defaults
->searchListArray
= PLMakeArrayFromElements(NULL
,NULL
);
312 while (defaults
->searchList
[i
]) {
313 PLAppendArrayElement(defaults
->searchListArray
,
314 defaults
->searchList
[i
]);
318 if (sharedUserDefaults
)
319 defaults
->next
= sharedUserDefaults
;
320 sharedUserDefaults
= defaults
;
322 addSynchronizeTimerHandler();
323 registerSaveOnExit();
330 WMGetDefaultsFromPath(char *path
)
332 WMUserDefaults
*defaults
;
339 assert(path
!= NULL
);
341 if (sharedUserDefaults
) {
342 defaults
= sharedUserDefaults
;
344 if (defaults
->path
&& strcmp(defaults
->path
, path
) == 0)
346 defaults
= defaults
->next
;
350 /* we didn't found the database we are looking for. Go read it. */
351 defaults
= wmalloc(sizeof(WMUserDefaults
));
352 memset(defaults
, 0, sizeof(WMUserDefaults
));
354 defaults
->defaults
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
356 defaults
->searchList
= wmalloc(sizeof(proplist_t
)*2);
358 /* the domain we want, go in the first position */
359 name
= strrchr(path
, '/');
365 key
= PLMakeString(name
);
366 defaults
->searchList
[0] = key
;
368 if (stat(path
, &stbuf
) >= 0)
369 defaults
->timestamp
= stbuf
.st_mtime
;
371 domain
= PLGetProplistWithPath(path
);
376 domain
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
377 p
= PLMakeString(path
);
378 PLSetFilename(domain
, p
);
382 defaults
->path
= wstrdup(path
);
384 defaults
->appDomain
= domain
;
387 PLInsertDictionaryEntry(defaults
->defaults
, key
, domain
);
392 defaults
->searchList
[1] = NULL
;
394 defaults
->searchListArray
= PLMakeArrayFromElements(NULL
,NULL
);
397 while (defaults
->searchList
[i
]) {
398 PLAppendArrayElement(defaults
->searchListArray
,
399 defaults
->searchList
[i
]);
403 if (sharedUserDefaults
)
404 defaults
->next
= sharedUserDefaults
;
405 sharedUserDefaults
= defaults
;
407 addSynchronizeTimerHandler();
408 registerSaveOnExit();
415 WMGetUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
417 proplist_t domainName
, domain
;
418 proplist_t object
= NULL
;
419 proplist_t key
= PLMakeString(defaultName
);
422 while (database
->searchList
[i
] && !object
) {
423 domainName
= database
->searchList
[i
];
424 domain
= PLGetDictionaryEntry(database
->defaults
, domainName
);
426 object
= PLGetDictionaryEntry(domain
, key
);
437 WMSetUDObjectForKey(WMUserDefaults
*database
, proplist_t object
,
440 proplist_t key
= PLMakeString(defaultName
);
444 PLInsertDictionaryEntry(database
->appDomain
, key
, object
);
450 WMRemoveUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
452 proplist_t key
= PLMakeString(defaultName
);
456 PLRemoveDictionaryEntry(database
->appDomain
, key
);
463 WMGetUDStringForKey(WMUserDefaults
*database
, char *defaultName
)
467 val
= WMGetUDObjectForKey(database
, defaultName
);
472 if (!PLIsString(val
))
475 return PLGetString(val
);
480 WMGetUDIntegerForKey(WMUserDefaults
*database
, char *defaultName
)
486 val
= WMGetUDObjectForKey(database
, defaultName
);
491 if (!PLIsString(val
))
494 str
= PLGetString(val
);
498 if (sscanf(str
, "%i", &value
)!=1)
507 WMGetUDFloatForKey(WMUserDefaults
*database
, char *defaultName
)
513 val
= WMGetUDObjectForKey(database
, defaultName
);
515 if (!val
|| !PLIsString(val
))
518 if (!(str
= PLGetString(val
)))
521 if (sscanf(str
, "%f", &value
)!=1)
530 WMGetUDBoolForKey(WMUserDefaults
*database
, char *defaultName
)
536 val
= WMGetUDObjectForKey(database
, defaultName
);
541 if (!PLIsString(val
))
544 str
= PLGetString(val
);
548 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
551 if (strcasecmp(str
, "YES")==0)
554 if (strcasecmp(str
, "Y")==0)
562 WMSetUDIntegerForKey(WMUserDefaults
*database
, int value
, char *defaultName
)
567 sprintf(buffer
, "%i", value
);
568 object
= PLMakeString(buffer
);
570 WMSetUDObjectForKey(database
, object
, defaultName
);
578 WMSetUDStringForKey(WMUserDefaults
*database
, char *value
, char *defaultName
)
582 object
= PLMakeString(value
);
584 WMSetUDObjectForKey(database
, object
, defaultName
);
591 WMSetUDFloatForKey(WMUserDefaults
*database
, float value
, char *defaultName
)
596 sprintf(buffer
, "%f", value
);
597 object
= PLMakeString(buffer
);
599 WMSetUDObjectForKey(database
, object
, defaultName
);
606 WMSetUDBoolForKey(WMUserDefaults
*database
, Bool value
, char *defaultName
)
608 static proplist_t yes
= NULL
, no
= NULL
;
611 yes
= PLMakeString("YES");
612 no
= PLMakeString("NO");
615 WMSetUDObjectForKey(database
, value
? yes
: no
, defaultName
);
620 WMGetUDSearchList(WMUserDefaults
*database
)
622 return database
->searchListArray
;
627 WMSetUDSearchList(WMUserDefaults
*database
, proplist_t list
)
631 if (database
->searchList
) {
633 while (database
->searchList
[i
]) {
634 PLRelease(database
->searchList
[i
]);
637 wfree(database
->searchList
);
639 if (database
->searchListArray
) {
640 PLRelease(database
->searchListArray
);
643 c
= PLGetNumberOfElements(list
);
644 database
->searchList
= wmalloc(sizeof(proplist_t
)*(c
+1));
646 for (i
=0; i
<c
; i
++) {
647 database
->searchList
[i
] = PLGetArrayElement(list
, i
);
650 database
->searchListArray
= PLDeepCopy(list
);