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();
414 /* Returns a PLArray with all keys in the user defaults database.
415 * Free the returned array with PLRelease() when no longer needed,
416 * but do not free the elements of the array! They're just references. */
418 WMGetUDAllKeys(WMUserDefaults
*database
)
420 return PLGetAllDictionaryKeys(database
->appDomain
);
425 WMGetUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
427 proplist_t domainName
, domain
;
428 proplist_t object
= NULL
;
429 proplist_t key
= PLMakeString(defaultName
);
432 while (database
->searchList
[i
] && !object
) {
433 domainName
= database
->searchList
[i
];
434 domain
= PLGetDictionaryEntry(database
->defaults
, domainName
);
436 object
= PLGetDictionaryEntry(domain
, key
);
447 WMSetUDObjectForKey(WMUserDefaults
*database
, proplist_t object
,
450 proplist_t key
= PLMakeString(defaultName
);
454 PLInsertDictionaryEntry(database
->appDomain
, key
, object
);
460 WMRemoveUDObjectForKey(WMUserDefaults
*database
, char *defaultName
)
462 proplist_t key
= PLMakeString(defaultName
);
466 PLRemoveDictionaryEntry(database
->appDomain
, key
);
473 WMGetUDStringForKey(WMUserDefaults
*database
, char *defaultName
)
477 val
= WMGetUDObjectForKey(database
, defaultName
);
482 if (!PLIsString(val
))
485 return PLGetString(val
);
490 WMGetUDIntegerForKey(WMUserDefaults
*database
, char *defaultName
)
496 val
= WMGetUDObjectForKey(database
, defaultName
);
501 if (!PLIsString(val
))
504 str
= PLGetString(val
);
508 if (sscanf(str
, "%i", &value
)!=1)
517 WMGetUDFloatForKey(WMUserDefaults
*database
, char *defaultName
)
523 val
= WMGetUDObjectForKey(database
, defaultName
);
525 if (!val
|| !PLIsString(val
))
528 if (!(str
= PLGetString(val
)))
531 if (sscanf(str
, "%f", &value
)!=1)
540 WMGetUDBoolForKey(WMUserDefaults
*database
, char *defaultName
)
546 val
= WMGetUDObjectForKey(database
, defaultName
);
551 if (!PLIsString(val
))
554 str
= PLGetString(val
);
558 if (sscanf(str
, "%i", &value
)==1 && value
!=0)
561 if (strcasecmp(str
, "YES")==0)
564 if (strcasecmp(str
, "Y")==0)
572 WMSetUDIntegerForKey(WMUserDefaults
*database
, int value
, char *defaultName
)
577 sprintf(buffer
, "%i", value
);
578 object
= PLMakeString(buffer
);
580 WMSetUDObjectForKey(database
, object
, defaultName
);
588 WMSetUDStringForKey(WMUserDefaults
*database
, char *value
, char *defaultName
)
592 object
= PLMakeString(value
);
594 WMSetUDObjectForKey(database
, object
, defaultName
);
601 WMSetUDFloatForKey(WMUserDefaults
*database
, float value
, char *defaultName
)
606 sprintf(buffer
, "%f", value
);
607 object
= PLMakeString(buffer
);
609 WMSetUDObjectForKey(database
, object
, defaultName
);
616 WMSetUDBoolForKey(WMUserDefaults
*database
, Bool value
, char *defaultName
)
618 static proplist_t yes
= NULL
, no
= NULL
;
621 yes
= PLMakeString("YES");
622 no
= PLMakeString("NO");
625 WMSetUDObjectForKey(database
, value
? yes
: no
, defaultName
);
630 WMGetUDSearchList(WMUserDefaults
*database
)
632 return database
->searchListArray
;
637 WMSetUDSearchList(WMUserDefaults
*database
, proplist_t list
)
641 if (database
->searchList
) {
643 while (database
->searchList
[i
]) {
644 PLRelease(database
->searchList
[i
]);
647 wfree(database
->searchList
);
649 if (database
->searchListArray
) {
650 PLRelease(database
->searchListArray
);
653 c
= PLGetNumberOfElements(list
);
654 database
->searchList
= wmalloc(sizeof(proplist_t
)*(c
+1));
656 for (i
=0; i
<c
; i
++) {
657 database
->searchList
[i
] = PLGetArrayElement(list
, i
);
660 database
->searchListArray
= PLDeepCopy(list
);