1
0
mirror of https://github.com/gryf/wmaker.git synced 2025-12-19 12:28:22 +01:00
Files
wmaker/WINGs/userdefaults.c
dan 33cc542e85 - Finished moving to the new proplist handling code in WINGs.
- Also tested the backward compatibility ability of the WINGs proplist code
  which seems to work quite well.

Starting with this moment, Window Maker no longer needs libPropList and is
now using the better and much more robust proplist code from WINGs. Also the
WINGs based proplist code is actively maintained while the old libPropList
code is practically dead and flawed by the fact that it borrowed concepts
from the UserDefaults which conflicted with the retain/release mechanism,
making some problems that libPropList had, practically unsolvable without a
complete redesign (which can be found in the more robust WINGs code).
2001-10-04 03:07:34 +00:00

679 lines
14 KiB
C

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <unistd.h>
#include <sys/stat.h>
#include "../src/config.h"
#include "wconfig.h"
#include "WINGs.h"
typedef struct W_UserDefaults {
WMPropList *defaults;
WMPropList *appDomain;
WMPropList *searchListArray;
WMPropList **searchList; /* cache for searchListArray */
char dirty;
char dontSync;
char *path; /* where is db located */
time_t timestamp; /* last modification time */
struct W_UserDefaults *next;
} UserDefaults;
static UserDefaults *sharedUserDefaults = NULL;
char *WMUserDefaultsDidChangeNotification = "WMUserDefaultsDidChangeNotification";
extern char *WMGetApplicationName();
#define DEFAULTS_DIR "/Defaults"
#define UD_SYNC_INTERVAL 2000
char*
wusergnusteppath()
{
static char *path = NULL;
char *gspath;
int pathlen;
if (!path) {
gspath = getenv("GNUSTEP_USER_ROOT");
if (gspath) {
gspath = wexpandpath(gspath);
pathlen = strlen(gspath) + 4;
path = wmalloc(pathlen);
strcpy(path, gspath);
wfree(gspath);
} else {
pathlen = strlen(wgethomedir()) + 10;
path = wmalloc(pathlen);
strcpy(path, wgethomedir());
strcat(path, "/GNUstep");
}
}
return path;
}
char*
wdefaultspathfordomain(char *domain)
{
char *path;
char *gspath;
gspath = wusergnusteppath();
path = wmalloc(strlen(gspath)+strlen(DEFAULTS_DIR)+strlen(domain)+4);
strcpy(path, gspath);
strcat(path, DEFAULTS_DIR);
strcat(path, "/");
strcat(path, domain);
return path;
}
static void
#ifndef HAVE_ATEXIT
saveDefaultsChanges(int foo, void *bar)
#else
saveDefaultsChanges(void)
#endif
{
/* save the user defaults databases */
UserDefaults *tmp = sharedUserDefaults;
while (tmp) {
WMSynchronizeUserDefaults(tmp);
tmp = tmp->next;
}
}
/* set to save changes in defaults when program is exited */
static void
registerSaveOnExit(void)
{
static Bool registeredSaveOnExit = False;
if (!registeredSaveOnExit) {
#ifndef HAVE_ATEXIT
on_exit(saveDefaultsChanges, (void*)NULL);
#else
atexit(saveDefaultsChanges);
#endif
registeredSaveOnExit = True;
}
}
static void
synchronizeUserDefaults(void *foo)
{
UserDefaults *database = sharedUserDefaults;
while (database) {
if (!database->dontSync)
WMSynchronizeUserDefaults(database);
database = database->next;
}
WMAddTimerHandler(UD_SYNC_INTERVAL, synchronizeUserDefaults, NULL);
}
static void
addSynchronizeTimerHandler(void)
{
static Bool initialized = False;
if (!initialized) {
WMAddTimerHandler(UD_SYNC_INTERVAL, synchronizeUserDefaults, NULL);
initialized = True;
}
}
void
WMEnableUDPeriodicSynchronization(WMUserDefaults *database, Bool enable)
{
database->dontSync = !enable;
}
void
WMSynchronizeUserDefaults(WMUserDefaults *database)
{
Bool fileIsNewer = False, release = False, notify = False;
WMPropList *plF, *key;
char *path;
struct stat stbuf;
if (!database->path) {
path = wdefaultspathfordomain(WMGetApplicationName());
release = True;
} else {
path = database->path;
}
if (stat(path, &stbuf) >= 0 && stbuf.st_mtime > database->timestamp)
fileIsNewer = True;
if (database->appDomain && (database->dirty || fileIsNewer)) {
if (database->dirty && fileIsNewer) {
plF = WMReadPropListFromFile(path);
if (plF) {
plF = WMMergePLDictionaries(plF, database->appDomain);
WMReleasePropList(database->appDomain);
database->appDomain = plF;
key = database->searchList[0];
WMPutInPLDictionary(database->defaults, key, plF);
notify = True;
} else {
/* something happened with the file. just overwrite it */
wwarning(_("cannot read domain from file '%s' when syncing"),
path);
WMWritePropListToFile(database->appDomain, path, True);
}
} else if (database->dirty) {
WMWritePropListToFile(database->appDomain, path, True);
} else if (fileIsNewer) {
plF = WMReadPropListFromFile(path);
if (plF) {
WMReleasePropList(database->appDomain);
database->appDomain = plF;
key = database->searchList[0];
WMPutInPLDictionary(database->defaults, key, plF);
notify = True;
} else {
/* something happened with the file. just overwrite it */
wwarning(_("cannot read domain from file '%s' when syncing"),
path);
WMWritePropListToFile(database->appDomain, path, True);
}
}
database->dirty = 0;
if (stat(path, &stbuf) >= 0)
database->timestamp = stbuf.st_mtime;
if (notify) {
WMPostNotificationName(WMUserDefaultsDidChangeNotification,
database, NULL);
}
}
if (release)
wfree(path);
}
void
WMSaveUserDefaults(WMUserDefaults *database)
{
if (database->appDomain) {
struct stat stbuf;
char *path;
Bool release = False;
if (!database->path) {
path = wdefaultspathfordomain(WMGetApplicationName());
release = True;
} else {
path = database->path;
}
WMWritePropListToFile(database->appDomain, path, True);
database->dirty = 0;
if (stat(path, &stbuf) >= 0)
database->timestamp = stbuf.st_mtime;
if (release)
wfree(path);
}
}
WMUserDefaults*
WMGetStandardUserDefaults(void)
{
WMUserDefaults *defaults;
WMPropList *domain;
WMPropList *key;
struct stat stbuf;
char *path;
int i;
if (sharedUserDefaults) {
defaults = sharedUserDefaults;
while (defaults) {
/* Trick, path == NULL only for StandardUserDefaults db */
if (defaults->path == NULL)
return defaults;
defaults = defaults->next;
}
}
/* we didn't found the database we are looking for. Go read it. */
defaults = wmalloc(sizeof(WMUserDefaults));
memset(defaults, 0, sizeof(WMUserDefaults));
defaults->defaults = WMCreatePLDictionary(NULL, NULL, NULL);
defaults->searchList = wmalloc(sizeof(WMPropList*)*3);
/* application domain */
key = WMCreatePLString(WMGetApplicationName());
defaults->searchList[0] = key;
/* temporary kluge */
if (strcmp(WMGetApplicationName(), "WindowMaker")==0) {
domain = NULL;
path = NULL;
} else {
path = wdefaultspathfordomain(WMGetFromPLString(key));
if (stat(path, &stbuf) >= 0)
defaults->timestamp = stbuf.st_mtime;
domain = WMReadPropListFromFile(path);
}
if (!domain)
domain = WMCreatePLDictionary(NULL, NULL, NULL);
if (path)
wfree(path);
defaults->appDomain = domain;
if (domain)
WMPutInPLDictionary(defaults->defaults, key, domain);
/* global domain */
key = WMCreatePLString("WMGLOBAL");
defaults->searchList[1] = key;
path = wdefaultspathfordomain(WMGetFromPLString(key));
domain = WMReadPropListFromFile(path);
wfree(path);
if (!domain)
domain = WMCreatePLDictionary(NULL, NULL, NULL);
if (domain)
WMPutInPLDictionary(defaults->defaults, key, domain);
/* terminate list */
defaults->searchList[2] = NULL;
defaults->searchListArray = WMCreatePLArray(NULL,NULL);
i = 0;
while (defaults->searchList[i]) {
WMAddToPLArray(defaults->searchListArray,
defaults->searchList[i]);
i++;
}
if (sharedUserDefaults)
defaults->next = sharedUserDefaults;
sharedUserDefaults = defaults;
addSynchronizeTimerHandler();
registerSaveOnExit();
return defaults;
}
WMUserDefaults*
WMGetDefaultsFromPath(char *path)
{
WMUserDefaults *defaults;
WMPropList *domain;
WMPropList *key;
struct stat stbuf;
char *name;
int i;
assert(path != NULL);
if (sharedUserDefaults) {
defaults = sharedUserDefaults;
while (defaults) {
if (defaults->path && strcmp(defaults->path, path) == 0)
return defaults;
defaults = defaults->next;
}
}
/* we didn't found the database we are looking for. Go read it. */
defaults = wmalloc(sizeof(WMUserDefaults));
memset(defaults, 0, sizeof(WMUserDefaults));
defaults->defaults = WMCreatePLDictionary(NULL, NULL, NULL);
defaults->searchList = wmalloc(sizeof(WMPropList*)*2);
/* the domain we want, go in the first position */
name = strrchr(path, '/');
if (!name)
name = path;
else
name++;
key = WMCreatePLString(name);
defaults->searchList[0] = key;
if (stat(path, &stbuf) >= 0)
defaults->timestamp = stbuf.st_mtime;
domain = WMReadPropListFromFile(path);
if (!domain)
domain = WMCreatePLDictionary(NULL, NULL, NULL);
defaults->path = wstrdup(path);
defaults->appDomain = domain;
if (domain)
WMPutInPLDictionary(defaults->defaults, key, domain);
/* terminate list */
defaults->searchList[1] = NULL;
defaults->searchListArray = WMCreatePLArray(NULL,NULL);
i = 0;
while (defaults->searchList[i]) {
WMAddToPLArray(defaults->searchListArray,
defaults->searchList[i]);
i++;
}
if (sharedUserDefaults)
defaults->next = sharedUserDefaults;
sharedUserDefaults = defaults;
addSynchronizeTimerHandler();
registerSaveOnExit();
return defaults;
}
/* Returns a WMPropList array with all keys in the user defaults database.
* Free the array with WMReleasePropList() when no longer needed,
* but do not free the elements of the array! They're just references. */
WMPropList*
WMGetUDKeys(WMUserDefaults *database)
{
return WMGetPLDictionaryKeys(database->appDomain);
}
WMPropList*
WMGetUDObjectForKey(WMUserDefaults *database, char *defaultName)
{
WMPropList *domainName, *domain;
WMPropList *object = NULL;
WMPropList *key = WMCreatePLString(defaultName);
int i = 0;
while (database->searchList[i] && !object) {
domainName = database->searchList[i];
domain = WMGetFromPLDictionary(database->defaults, domainName);
if (domain) {
object = WMGetFromPLDictionary(domain, key);
}
i++;
}
WMReleasePropList(key);
return object;
}
void
WMSetUDObjectForKey(WMUserDefaults *database, WMPropList *object,
char *defaultName)
{
WMPropList *key = WMCreatePLString(defaultName);
database->dirty = 1;
WMPutInPLDictionary(database->appDomain, key, object);
WMReleasePropList(key);
}
void
WMRemoveUDObjectForKey(WMUserDefaults *database, char *defaultName)
{
WMPropList *key = WMCreatePLString(defaultName);
database->dirty = 1;
WMRemoveFromPLDictionary(database->appDomain, key);
WMReleasePropList(key);
}
char*
WMGetUDStringForKey(WMUserDefaults *database, char *defaultName)
{
WMPropList *val;
val = WMGetUDObjectForKey(database, defaultName);
if (!val)
return NULL;
if (!WMIsPLString(val))
return NULL;
return WMGetFromPLString(val);
}
int
WMGetUDIntegerForKey(WMUserDefaults *database, char *defaultName)
{
WMPropList *val;
char *str;
int value;
val = WMGetUDObjectForKey(database, defaultName);
if (!val)
return 0;
if (!WMIsPLString(val))
return 0;
str = WMGetFromPLString(val);
if (!str)
return 0;
if (sscanf(str, "%i", &value)!=1)
return 0;
return value;
}
float
WMGetUDFloatForKey(WMUserDefaults *database, char *defaultName)
{
WMPropList *val;
char *str;
float value;
val = WMGetUDObjectForKey(database, defaultName);
if (!val || !WMIsPLString(val))
return 0.0;
if (!(str = WMGetFromPLString(val)))
return 0.0;
if (sscanf(str, "%f", &value)!=1)
return 0.0;
return value;
}
Bool
WMGetUDBoolForKey(WMUserDefaults *database, char *defaultName)
{
WMPropList *val;
int value;
char *str;
val = WMGetUDObjectForKey(database, defaultName);
if (!val)
return False;
if (!WMIsPLString(val))
return False;
str = WMGetFromPLString(val);
if (!str)
return False;
if (sscanf(str, "%i", &value)==1 && value!=0)
return True;
if (strcasecmp(str, "YES")==0)
return True;
if (strcasecmp(str, "Y")==0)
return True;
return False;
}
void
WMSetUDIntegerForKey(WMUserDefaults *database, int value, char *defaultName)
{
WMPropList *object;
char buffer[128];
sprintf(buffer, "%i", value);
object = WMCreatePLString(buffer);
WMSetUDObjectForKey(database, object, defaultName);
WMReleasePropList(object);
}
void
WMSetUDStringForKey(WMUserDefaults *database, char *value, char *defaultName)
{
WMPropList *object;
object = WMCreatePLString(value);
WMSetUDObjectForKey(database, object, defaultName);
WMReleasePropList(object);
}
void
WMSetUDFloatForKey(WMUserDefaults *database, float value, char *defaultName)
{
WMPropList *object;
char buffer[128];
sprintf(buffer, "%f", value);
object = WMCreatePLString(buffer);
WMSetUDObjectForKey(database, object, defaultName);
WMReleasePropList(object);
}
void
WMSetUDBoolForKey(WMUserDefaults *database, Bool value, char *defaultName)
{
static WMPropList *yes = NULL, *no = NULL;
if (!yes) {
yes = WMCreatePLString("YES");
no = WMCreatePLString("NO");
}
WMSetUDObjectForKey(database, value ? yes : no, defaultName);
}
WMPropList*
WMGetUDSearchList(WMUserDefaults *database)
{
return database->searchListArray;
}
void
WMSetUDSearchList(WMUserDefaults *database, WMPropList *list)
{
int i, c;
if (database->searchList) {
i = 0;
while (database->searchList[i]) {
WMReleasePropList(database->searchList[i]);
i++;
}
wfree(database->searchList);
}
if (database->searchListArray) {
WMReleasePropList(database->searchListArray);
}
c = WMGetPropListItemCount(list);
database->searchList = wmalloc(sizeof(WMPropList*)*(c+1));
for (i=0; i<c; i++) {
database->searchList[i] = WMGetFromPLArray(list, i);
}
database->searchListArray = WMDeepCopyPropList(list);
}