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 /*printf("syncing: %s %d %d\n", path, database->dirty, fileIsNewer);*/
182 if (database
->appDomain
&& (database
->dirty
|| fileIsNewer
)) {
183 PLShallowSynchronize(database
->appDomain
);
185 if (stat(path
, &stbuf
) >= 0)
186 database
->timestamp
= stbuf
.st_mtime
;
188 WMPostNotificationName(WMUserDefaultsDidChangeNotification
,
200 WMSaveUserDefaults(WMUserDefaults
*database
)
202 if (database
->appDomain
) {
205 Bool release
= False
;
207 PLSave(database
->appDomain
, YES
);
209 if (!database
->path
) {
210 path
= wdefaultspathfordomain(WMGetApplicationName());
213 path
= database
->path
;
215 if (stat(path
, &stbuf
) >= 0)
216 database
->timestamp
= stbuf
.st_mtime
;
224 WMGetStandardUserDefaults(void)
226 WMUserDefaults
*defaults
;
233 if (sharedUserDefaults
) {
234 defaults
= sharedUserDefaults
;
236 /* Trick, path == NULL only for StandardUserDefaults db */
237 if (defaults
->path
== NULL
)
239 defaults
= defaults
->next
;
243 /* we didn't found the database we are looking for. Go read it. */
244 defaults
= wmalloc(sizeof(WMUserDefaults
));
245 memset(defaults
, 0, sizeof(WMUserDefaults
));
247 defaults
->defaults
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
249 defaults
->searchList
= wmalloc(sizeof(proplist_t
)*3);
251 /* application domain */
252 key
= PLMakeString(WMGetApplicationName());
253 defaults
->searchList
[0] = key
;
255 /* temporary kluge */
256 if (strcmp(WMGetApplicationName(), "WindowMaker")==0) {
260 path
= wdefaultspathfordomain(PLGetString(key
));
262 if (stat(path
, &stbuf
) >= 0)
263 defaults
->timestamp
= stbuf
.st_mtime
;
265 domain
= PLGetProplistWithPath(path
);
270 domain
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
272 p
= PLMakeString(path
);
273 PLSetFilename(domain
, p
);
280 defaults
->appDomain
= domain
;
283 PLInsertDictionaryEntry(defaults
->defaults
, key
, domain
);
288 key
= PLMakeString("WMGLOBAL");
289 defaults
->searchList
[1] = key
;
291 path
= wdefaultspathfordomain(PLGetString(key
));
293 domain
= PLGetProplistWithPath(path
);
298 domain
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
301 PLInsertDictionaryEntry(defaults
->defaults
, key
, domain
);
306 defaults
->searchList
[2] = NULL
;
308 defaults
->searchListArray
= PLMakeArrayFromElements(NULL
,NULL
);
311 while (defaults
->searchList
[i
]) {
312 PLAppendArrayElement(defaults
->searchListArray
,
313 defaults
->searchList
[i
]);
317 if (sharedUserDefaults
)
318 defaults
->next
= sharedUserDefaults
;
319 sharedUserDefaults
= defaults
;
321 addSynchronizeTimerHandler();
322 registerSaveOnExit();
329 WMGetDefaultsFromPath(char *path
)
331 WMUserDefaults
*defaults
;
338 assert(path
!= NULL
);
340 if (sharedUserDefaults
) {
341 defaults
= sharedUserDefaults
;
343 if (defaults
->path
&& strcmp(defaults
->path
, path
) == 0)
345 defaults
= defaults
->next
;
349 /* we didn't found the database we are looking for. Go read it. */
350 defaults
= wmalloc(sizeof(WMUserDefaults
));
351 memset(defaults
, 0, sizeof(WMUserDefaults
));
353 defaults
->defaults
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
355 defaults
->searchList
= wmalloc(sizeof(proplist_t
)*2);
357 /* the domain we want, go in the first position */
358 name
= strrchr(path
, '/');
364 key
= PLMakeString(name
);
365 defaults
->searchList
[0] = key
;
367 if (stat(path
, &stbuf
) >= 0)
368 defaults
->timestamp
= stbuf
.st_mtime
;
370 domain
= PLGetProplistWithPath(path
);
375 domain
= PLMakeDictionaryFromEntries(NULL
, NULL
, NULL
);
376 p
= PLMakeString(path
);
377 PLSetFilename(domain
, p
);
381 defaults
->path
= wstrdup(path
);
383 defaults
->appDomain
= domain
;
386 PLInsertDictionaryEntry(defaults
->defaults
, key
, domain
);
391 defaults
->searchList
[1] = NULL
;
393 defaults
->searchListArray
= PLMakeArrayFromElements(NULL
,NULL
);
396 while (defaults
->searchList
[i
]) {
397 PLAppendArrayElement(defaults
->searchListArray
,
398 defaults
->searchList
[i
]);
402 if (sharedUserDefaults
)
403 defaults
->next
= sharedUserDefaults
;
404 sharedUserDefaults
= defaults
;
406 addSynchronizeTimerHandler();
407 registerSaveOnExit();
414 WMGetUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
416 proplist_t domainName
, domain
;
417 proplist_t object
= NULL
;
418 proplist_t key
= PLMakeString(defaultName
);
421 while (database
->searchList
[i
] && !object
) {
422 domainName
= database
->searchList
[i
];
423 domain
= PLGetDictionaryEntry(database
->defaults
, domainName
);
425 object
= PLGetDictionaryEntry(domain
, key
);
436 WMSetUDObjectForKey(WMUserDefaults
*database
, proplist_t object
,
439 proplist_t key
= PLMakeString(defaultName
);
443 PLInsertDictionaryEntry(database
->appDomain
, key
, object
);
449 WMRemoveUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
451 proplist_t key
= PLMakeString(defaultName
);
455 PLRemoveDictionaryEntry(database
->appDomain
, key
);
462 WMGetUDStringForKey(WMUserDefaults
*database
, char *defaultName
)
466 val
= WMGetUDObjectForKey(database
, defaultName
);
471 if (!PLIsString(val
))
474 return PLGetString(val
);
479 WMGetUDIntegerForKey(WMUserDefaults
*database
, char *defaultName
)
485 val
= WMGetUDObjectForKey(database
, defaultName
);
490 if (!PLIsString(val
))
493 str
= PLGetString(val
);
497 if (sscanf(str
, "%i", &value
)!=1)
506 WMGetUDFloatForKey(WMUserDefaults
*database
, char *defaultName
)
512 val
= WMGetUDObjectForKey(database
, defaultName
);
514 if (!val
|| !PLIsString(val
))
517 if (!(str
= PLGetString(val
)))
520 if (sscanf(str
, "%f", &value
)!=1)
529 WMGetUDBoolForKey(WMUserDefaults
*database
, char *defaultName
)
535 val
= WMGetUDObjectForKey(database
, defaultName
);
540 if (!PLIsString(val
))
543 str
= PLGetString(val
);
547 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
550 if (strcasecmp(str
, "YES")==0)
553 if (strcasecmp(str
, "Y")==0)
561 WMSetUDIntegerForKey(WMUserDefaults
*database
, int value
, char *defaultName
)
566 sprintf(buffer
, "%i", value
);
567 object
= PLMakeString(buffer
);
569 WMSetUDObjectForKey(database
, object
, defaultName
);
577 WMSetUDStringForKey(WMUserDefaults
*database
, char *value
, char *defaultName
)
581 object
= PLMakeString(value
);
583 WMSetUDObjectForKey(database
, object
, defaultName
);
590 WMSetUDFloatForKey(WMUserDefaults
*database
, float value
, char *defaultName
)
595 sprintf(buffer
, "%f", value
);
596 object
= PLMakeString(buffer
);
598 WMSetUDObjectForKey(database
, object
, defaultName
);
605 WMSetUDBoolForKey(WMUserDefaults
*database
, Bool value
, char *defaultName
)
607 static proplist_t yes
= NULL
, no
= NULL
;
610 yes
= PLMakeString("YES");
611 no
= PLMakeString("NO");
614 WMSetUDObjectForKey(database
, value
? yes
: no
, defaultName
);
619 WMGetUDSearchList(WMUserDefaults
*database
)
621 return database
->searchListArray
;
626 WMSetUDSearchList(WMUserDefaults
*database
, proplist_t list
)
630 if (database
->searchList
) {
632 while (database
->searchList
[i
]) {
633 PLRelease(database
->searchList
[i
]);
636 wfree(database
->searchList
);
638 if (database
->searchListArray
) {
639 PLRelease(database
->searchListArray
);
642 c
= PLGetNumberOfElements(list
);
643 database
->searchList
= wmalloc(sizeof(proplist_t
)*(c
+1));
645 for (i
=0; i
<c
; i
++) {
646 database
->searchList
[i
] = PLGetArrayElement(list
, i
);
649 database
->searchListArray
= PLDeepCopy(list
);