express/src/bin/config.c

293 lines
7.6 KiB
C

#include "private.h"
#include "config.h"
#include "utils.h"
#include "window.h"
# define EX_CONFIG_LIMIT(v, min, max) \
if (v > max) v = max; else if (v < min) v = min;
# define EX_CONFIG_DD_NEW(str, typ) \
_config_descriptor_new(str, sizeof(typ))
# define EX_CONFIG_DD_FREE(eed) \
if (eed) { eet_data_descriptor_free(eed); (eed) = NULL; }
# define EX_CONFIG_VAL(edd, type, member, dtype) \
EET_DATA_DESCRIPTOR_ADD_BASIC(edd, type, #member, member, dtype)
# define EX_CONFIG_SUB(edd, type, member, eddtype) \
EET_DATA_DESCRIPTOR_ADD_SUB(edd, type, #member, member, eddtype)
# define EX_CONFIG_LIST(edd, type, member, eddtype) \
EET_DATA_DESCRIPTOR_ADD_LIST(edd, type, #member, member, eddtype)
# define EX_CONFIG_HASH(edd, type, member, eddtype) \
EET_DATA_DESCRIPTOR_ADD_HASH(edd, type, #member, member, eddtype)
# define EX_CONFIG_FILE_EPOCH 0x0001
# define EX_CONFIG_FILE_GENERATION 0x008d
# define EX_CONFIG_FILE_VERSION \
((EX_CONFIG_FILE_EPOCH << 16) | EX_CONFIG_FILE_GENERATION)
typedef Eet_Data_Descriptor Ex_Config_DD;
/* local variables */
static Ex_Config_DD *_ex_cfg_edd = NULL;
static Ex_Config_DD *_ex_cfg_srv_edd = NULL;
static Ex_Config_DD *_ex_cfg_net_edd = NULL;
static Ex_Config_DD *_ex_cfg_chl_edd = NULL;
/* external variables */
Config *_ex_cfg = NULL;
/* local functions */
static Ex_Config_DD *
_config_descriptor_new(const char *name, int size)
{
Eet_Data_Descriptor_Class eddc;
if (!eet_eina_stream_data_descriptor_class_set(&eddc, sizeof(eddc),
name, size))
return NULL;
return (Ex_Config_DD *)eet_data_descriptor_stream_new(&eddc);
}
static void
_config_cb_free(void)
{
Config_Network *net;
EINA_LIST_FREE(_ex_cfg->networks, net)
{
Config_Server *srv;
Config_Channel *chl;
EINA_LIST_FREE(net->servers, srv)
{
if (srv->name) eina_stringshare_del(srv->name);
free(srv);
}
EINA_LIST_FREE(net->channels, chl)
{
if (chl->name) eina_stringshare_del(chl->name);
free(chl);
}
if (net->name) eina_stringshare_del(net->name);
if (net->nick_passwd) eina_stringshare_del(net->nick_passwd);
if (net->server_passwd) eina_stringshare_del(net->server_passwd);
free(net);
}
if (_ex_cfg->font.name) eina_stringshare_del(_ex_cfg->font.name);
if (_ex_cfg->nick) eina_stringshare_del(_ex_cfg->nick);
if (_ex_cfg->name) eina_stringshare_del(_ex_cfg->name);
free(_ex_cfg);
_ex_cfg = NULL;
}
static void *
_config_domain_load(const char *domain, Ex_Config_DD *edd)
{
Eet_File *ef;
char buff[PATH_MAX];
if (!domain) return NULL;
snprintf(buff, sizeof(buff),
"%s/%s.cfg", _util_user_dir_get(), domain);
ef = eet_open(buff, EET_FILE_MODE_READ);
if (ef)
{
void *data;
data = eet_data_read(ef, edd, "config");
eet_close(ef);
if (data) return data;
}
return NULL;
}
static Eina_Bool
_config_domain_save(const char *domain, Ex_Config_DD *edd, const void *data)
{
Eet_File *ef;
char buff[PATH_MAX];
const char *userdir;
if (!domain) return 0;
userdir = _util_user_dir_get();
snprintf(buff, sizeof(buff), "%s/", userdir);
if (!ecore_file_exists(buff)) ecore_file_mkpath(buff);
snprintf(buff, sizeof(buff), "%s/%s.tmp", userdir, domain);
ef = eet_open(buff, EET_FILE_MODE_WRITE);
if (ef)
{
char buff2[PATH_MAX];
snprintf(buff2, sizeof(buff2), "%s/%s.cfg", userdir, domain);
if (!eet_data_write(ef, edd, "config", data, 1))
{
eet_close(ef);
return EINA_FALSE;
}
if (eet_close(ef) > 0) return EINA_FALSE;
if (!ecore_file_mv(buff, buff2)) return EINA_FALSE;
return EINA_TRUE;
}
return EINA_FALSE;
}
/* external functions */
Eina_Bool
_config_init(void)
{
elm_need_efreet();
if (!efreet_init()) return EINA_FALSE;
_ex_cfg_chl_edd = EX_CONFIG_DD_NEW("Config_Channel", Config_Channel);
#undef T
#undef D
#define T Config_Channel
#define D _ex_cfg_chl_edd
EX_CONFIG_VAL(D, T, name, EET_T_STRING);
_ex_cfg_srv_edd = EX_CONFIG_DD_NEW("Config_Server", Config_Server);
#undef T
#undef D
#define T Config_Server
#define D _ex_cfg_srv_edd
EX_CONFIG_VAL(D, T, name, EET_T_STRING);
EX_CONFIG_VAL(D, T, port, EET_T_INT);
_ex_cfg_net_edd = EX_CONFIG_DD_NEW("Config_Network", Config_Network);
#undef T
#undef D
#define T Config_Network
#define D _ex_cfg_net_edd
EX_CONFIG_VAL(D, T, name, EET_T_STRING);
EX_CONFIG_VAL(D, T, nick_passwd, EET_T_STRING);
EX_CONFIG_VAL(D, T, server_passwd, EET_T_STRING);
EX_CONFIG_VAL(D, T, autoconnect, EET_T_UCHAR);
EX_CONFIG_VAL(D, T, bypass_proxy, EET_T_UCHAR);
EX_CONFIG_VAL(D, T, use_ssl, EET_T_UCHAR);
EX_CONFIG_LIST(D, T, servers, _ex_cfg_srv_edd);
EX_CONFIG_LIST(D, T, channels, _ex_cfg_chl_edd);
_ex_cfg_edd = EX_CONFIG_DD_NEW("Config", Config);
#undef T
#undef D
#define T Config
#define D _ex_cfg_edd
EX_CONFIG_VAL(D, T, version, EET_T_INT);
EX_CONFIG_VAL(D, T, nick, EET_T_STRING);
EX_CONFIG_VAL(D, T, name, EET_T_STRING);
EX_CONFIG_VAL(D, T, font.name, EET_T_STRING);
EX_CONFIG_VAL(D, T, font.size, EET_T_INT);
EX_CONFIG_VAL(D, T, font.bitmap, EET_T_UCHAR);
EX_CONFIG_VAL(D, T, gui.translucent, EET_T_UCHAR);
EX_CONFIG_VAL(D, T, gui.zoom, EET_T_DOUBLE);
EX_CONFIG_VAL(D, T, gui.scrollback, EET_T_INT);
EX_CONFIG_LIST(D, T, networks, _ex_cfg_net_edd);
_config_load();
return EINA_TRUE;
}
Eina_Bool
_config_shutdown(void)
{
_config_cb_free();
EX_CONFIG_DD_FREE(_ex_cfg_chl_edd);
EX_CONFIG_DD_FREE(_ex_cfg_srv_edd);
EX_CONFIG_DD_FREE(_ex_cfg_net_edd);
EX_CONFIG_DD_FREE(_ex_cfg_edd);
efreet_shutdown();
return EINA_TRUE;
}
void
_config_load(void)
{
Eina_Bool save = EINA_FALSE;
_ex_cfg = _config_domain_load(PACKAGE_NAME, _ex_cfg_edd);
if (_ex_cfg)
{
Eina_Bool reload = EINA_FALSE;
if ((_ex_cfg->version >> 16) < EX_CONFIG_FILE_EPOCH)
{
/* config too old */
reload = EINA_TRUE;
}
else if (_ex_cfg->version > EX_CONFIG_FILE_VERSION)
{
/* config too new, WTF ? */
reload = EINA_TRUE;
}
/* if too old or too new, clear it so we can create new */
if (reload) _config_cb_free();
}
if (!_ex_cfg)
{
_ex_cfg = malloc(sizeof(Config));
save = EINA_TRUE;
}
/* define some convenient macros */
#define IFCFG(v) if ((_ex_cfg->version & 0xffff) < (v)) {
#define IFCFGELSE } else {
#define IFCFGEND }
/* setup defaults */
IFCFG(0x008d);
char *usr;
if ((usr = _util_user_name_get()))
_ex_cfg->nick = eina_stringshare_add(usr);
else
_ex_cfg->nick = NULL;
if ((usr = _util_user_fullname_get()))
_ex_cfg->name = eina_stringshare_add(usr);
else
_ex_cfg->name = NULL;
_ex_cfg->font.size = 10;
_ex_cfg->font.bitmap = EINA_TRUE;
_ex_cfg->font.name = eina_stringshare_add("nexus.pcf");
_ex_cfg->gui.translucent = EINA_TRUE;
_ex_cfg->gui.zoom = 0.5;
_ex_cfg->gui.scrollback = 2000;
_ex_cfg->networks = NULL;
IFCFGEND;
/* limit config values so they are sane */
EX_CONFIG_LIMIT(_ex_cfg->font.size, 3, 400);
EX_CONFIG_LIMIT(_ex_cfg->gui.zoom, 0.1, 1.0);
EX_CONFIG_LIMIT(_ex_cfg->gui.scrollback, 0, 200000);
_ex_cfg->version = EX_CONFIG_FILE_VERSION;
if (save) _config_save();
}
void
_config_save(void)
{
if (_config_domain_save(PACKAGE_NAME, _ex_cfg_edd, _ex_cfg))
{
/* update window, channels, etc */
_window_update();
}
}