X-Git-Url: http://git.silcnet.org/gitweb/?a=blobdiff_plain;f=apps%2Firssi%2Fsrc%2Fcore%2Fsettings.c;h=be49d800e2684f961cddbbf176b647d3fd4deeb8;hb=63ca577177f9f5db8e553372a9793b0c85f10715;hp=d99757e0a6f0c69ede91359e87b040b0fff1a110;hpb=60c165f23f8d5553bd8b4fd43366fbf5f24c2832;p=silc.git diff --git a/apps/irssi/src/core/settings.c b/apps/irssi/src/core/settings.c index d99757e0..be49d800 100644 --- a/apps/irssi/src/core/settings.c +++ b/apps/irssi/src/core/settings.c @@ -21,14 +21,18 @@ #include "module.h" #include "signals.h" #include "commands.h" +#include "levels.h" #include "misc.h" #include "lib-config/iconfig.h" +#include "recode.h" #include "settings.h" #include "default-config.h" #include +#define SETTINGS_AUTOSAVE_TIMEOUT (1000*60*60) /* 1 hour */ + CONFIG_REC *mainconfig; static GString *last_errors; @@ -60,83 +64,109 @@ static SETTINGS_REC *settings_find(const char *key) return rec; } -const char *settings_get_str(const char *key) +static SETTINGS_REC *settings_get(const char *key, SettingType type) { SETTINGS_REC *rec; - CONFIG_NODE *setnode, *node; + + g_return_val_if_fail(key != NULL, NULL); rec = settings_find(key); - g_return_val_if_fail(rec != NULL, NULL); + if (rec == NULL) { + g_warning("settings_get(%s) : not found", key); + return NULL; + } + if (type != -1 && rec->type != type) { + g_warning("settings_get(%s) : invalid type", key); + return NULL; + } + + return rec; +} - setnode = iconfig_node_traverse("settings", FALSE); - if (setnode == NULL) - return rec->def; +static const char * +settings_get_str_type(const char *key, SettingType type) +{ + SETTINGS_REC *rec; + CONFIG_NODE *node; - node = config_node_section(setnode, rec->module, -1); - return node == NULL ? rec->def : - config_node_get_str(node, key, rec->def); + rec = settings_get(key, type); + if (rec == NULL) return NULL; + + node = iconfig_node_traverse("settings", FALSE); + node = node == NULL ? NULL : config_node_section(node, rec->module, -1); + + return node == NULL ? rec->default_value.v_string : + config_node_get_str(node, key, rec->default_value.v_string); +} + +const char *settings_get_str(const char *key) +{ + return settings_get_str_type(key, -1); } int settings_get_int(const char *key) { SETTINGS_REC *rec; - CONFIG_NODE *setnode, *node; - int def; + CONFIG_NODE *node; - rec = settings_find(key); - g_return_val_if_fail(rec != NULL, 0); - def = GPOINTER_TO_INT(rec->def); + rec = settings_get(key, SETTING_TYPE_INT); + if (rec == NULL) return 0; - setnode = iconfig_node_traverse("settings", FALSE); - if (setnode == NULL) - return def; + node = iconfig_node_traverse("settings", FALSE); + node = node == NULL ? NULL : config_node_section(node, rec->module, -1); - node = config_node_section(setnode, rec->module, -1); - return node == NULL ? def : - config_node_get_int(node, key, def); + return node == NULL ? rec->default_value.v_int : + config_node_get_int(node, key, rec->default_value.v_int); } int settings_get_bool(const char *key) { SETTINGS_REC *rec; - CONFIG_NODE *setnode, *node; - int def; + CONFIG_NODE *node; - rec = settings_find(key); - g_return_val_if_fail(rec != NULL, 0); - def = GPOINTER_TO_INT(rec->def); + rec = settings_get(key, SETTING_TYPE_BOOLEAN); + if (rec == NULL) return FALSE; - setnode = iconfig_node_traverse("settings", FALSE); - if (setnode == NULL) - return def; + node = iconfig_node_traverse("settings", FALSE); + node = node == NULL ? NULL : config_node_section(node, rec->module, -1); - node = config_node_section(setnode, rec->module, -1); - return node == NULL ? def : - config_node_get_bool(node, key, def); + return node == NULL ? rec->default_value.v_bool : + config_node_get_bool(node, key, rec->default_value.v_bool); } -void settings_add_str_module(const char *module, const char *section, - const char *key, const char *def) +int settings_get_time(const char *key) { - SETTINGS_REC *rec; + const char *str; + int msecs; - g_return_if_fail(key != NULL); - g_return_if_fail(section != NULL); + str = settings_get_str_type(key, SETTING_TYPE_TIME); + if (str != NULL && !parse_time_interval(str, &msecs)) + g_warning("settings_get_time(%s) : Invalid time '%s'", key, str); + return str == NULL ? 0 : msecs; +} - rec = g_hash_table_lookup(settings, key); - g_return_if_fail(rec == NULL); +int settings_get_level(const char *key) +{ + const char *str; - rec = g_new0(SETTINGS_REC, 1); - rec->module = g_strdup(module); - rec->key = g_strdup(key); - rec->section = g_strdup(section); - rec->def = def == NULL ? NULL : g_strdup(def); + str = settings_get_str_type(key, SETTING_TYPE_LEVEL); + return str == NULL ? 0 : level2bits(str); +} + +int settings_get_size(const char *key) +{ + const char *str; + int bytes; - g_hash_table_insert(settings, rec->key, rec); + str = settings_get_str_type(key, SETTING_TYPE_SIZE); + if (str != NULL && !parse_size(str, &bytes)) + g_warning("settings_get_size(%s) : Invalid size '%s'", key, str); + return str == NULL ? 0 : bytes; } -void settings_add_int_module(const char *module, const char *section, - const char *key, int def) +static void settings_add(const char *module, const char *section, + const char *key, SettingType type, + const SettingValue *default_value) { SETTINGS_REC *rec; @@ -144,49 +174,108 @@ void settings_add_int_module(const char *module, const char *section, g_return_if_fail(section != NULL); rec = g_hash_table_lookup(settings, key); - g_return_if_fail(rec == NULL); + if (rec != NULL) { + /* Already exists, make sure it's correct type */ + if (rec->type != type) { + g_warning("Trying to add already existing " + "setting '%s' with different type.", key); + return; + } + } else { + rec = g_new(SETTINGS_REC, 1); + rec->module = g_strdup(module); + rec->key = g_strdup(key); + rec->section = g_strdup(section); + rec->type = type; + + rec->default_value = *default_value; + g_hash_table_insert(settings, rec->key, rec); + } - rec = g_new0(SETTINGS_REC, 1); - rec->module = g_strdup(module); - rec->type = SETTING_TYPE_INT; - rec->key = g_strdup(key); - rec->section = g_strdup(section); - rec->def = GINT_TO_POINTER(def); + rec->refcount++; +} + +void settings_add_str_module(const char *module, const char *section, + const char *key, const char *def) +{ + SettingValue default_value; + + memset(&default_value, 0, sizeof(default_value)); + default_value.v_string = g_strdup(def); + settings_add(module, section, key, SETTING_TYPE_STRING, &default_value); +} - g_hash_table_insert(settings, rec->key, rec); +void settings_add_int_module(const char *module, const char *section, + const char *key, int def) +{ + SettingValue default_value; + + memset(&default_value, 0, sizeof(default_value)); + default_value.v_int = def; + settings_add(module, section, key, SETTING_TYPE_INT, &default_value); } void settings_add_bool_module(const char *module, const char *section, const char *key, int def) { - SETTINGS_REC *rec; + SettingValue default_value; - g_return_if_fail(key != NULL); - g_return_if_fail(section != NULL); + memset(&default_value, 0, sizeof(default_value)); + default_value.v_bool = def; + settings_add(module, section, key, SETTING_TYPE_BOOLEAN, + &default_value); +} - rec = g_hash_table_lookup(settings, key); - g_return_if_fail(rec == NULL); +void settings_add_time_module(const char *module, const char *section, + const char *key, const char *def) +{ + SettingValue default_value; + + memset(&default_value, 0, sizeof(default_value)); + default_value.v_string = g_strdup(def); + settings_add(module, section, key, SETTING_TYPE_TIME, &default_value); +} + +void settings_add_level_module(const char *module, const char *section, + const char *key, const char *def) +{ + SettingValue default_value; - rec = g_new0(SETTINGS_REC, 1); - rec->module = g_strdup(module); - rec->type = SETTING_TYPE_BOOLEAN; - rec->key = g_strdup(key); - rec->section = g_strdup(section); - rec->def = GINT_TO_POINTER(def); + memset(&default_value, 0, sizeof(default_value)); + default_value.v_string = g_strdup(def); + settings_add(module, section, key, SETTING_TYPE_LEVEL, &default_value); +} + +void settings_add_size_module(const char *module, const char *section, + const char *key, const char *def) +{ + SettingValue default_value; - g_hash_table_insert(settings, rec->key, rec); + memset(&default_value, 0, sizeof(default_value)); + default_value.v_string = g_strdup(def); + settings_add(module, section, key, SETTING_TYPE_SIZE, &default_value); } static void settings_destroy(SETTINGS_REC *rec) { - if (rec->type == SETTING_TYPE_STRING) - g_free_not_null(rec->def); + if (rec->type != SETTING_TYPE_INT && + rec->type != SETTING_TYPE_BOOLEAN) + g_free(rec->default_value.v_string); g_free(rec->module); g_free(rec->section); g_free(rec->key); g_free(rec); } +static void settings_unref(SETTINGS_REC *rec, int remove_hash) +{ + if (--rec->refcount == 0) { + if (remove_hash) + g_hash_table_remove(settings, rec->key); + settings_destroy(rec); + } +} + void settings_remove(const char *key) { SETTINGS_REC *rec; @@ -194,17 +283,15 @@ void settings_remove(const char *key) g_return_if_fail(key != NULL); rec = g_hash_table_lookup(settings, key); - if (rec == NULL) return; - - g_hash_table_remove(settings, key); - settings_destroy(rec); + if (rec != NULL) + settings_unref(rec, TRUE); } static int settings_remove_hash(const char *key, SETTINGS_REC *rec, const char *module) { if (strcmp(rec->module, module) == 0) { - settings_destroy(rec); + settings_unref(rec, FALSE); return TRUE; } @@ -226,7 +313,10 @@ static CONFIG_NODE *settings_get_node(const char *key) g_return_val_if_fail(key != NULL, NULL); rec = g_hash_table_lookup(settings, key); - g_return_val_if_fail(rec != NULL, NULL); + if (rec == NULL) { + g_warning("Changing unknown setting '%s'", key); + return NULL; + } node = iconfig_node_traverse("settings", TRUE); return config_node_section(node, rec->module, NODE_TYPE_BLOCK); @@ -247,7 +337,35 @@ void settings_set_bool(const char *key, int value) iconfig_node_set_bool(settings_get_node(key), key, value); } -int settings_get_type(const char *key) +int settings_set_time(const char *key, const char *value) +{ + int msecs; + + if (!parse_time_interval(value, &msecs)) + return FALSE; + + iconfig_node_set_str(settings_get_node(key), key, value); + return TRUE; +} + +int settings_set_level(const char *key, const char *value) +{ + iconfig_node_set_str(settings_get_node(key), key, value); + return TRUE; +} + +int settings_set_size(const char *key, const char *value) +{ + int size; + + if (!parse_size(value, &size)) + return FALSE; + + iconfig_node_set_str(settings_get_node(key), key, value); + return TRUE; +} + +SettingType settings_get_type(const char *key) { SETTINGS_REC *rec; @@ -276,6 +394,8 @@ static void sig_init_finished(void) if (config_changed) { /* some backwards compatibility changes were made to config file, reload it */ + g_warning("Some settings were automatically " + "updated, please /SAVE"); signal_emit("setup changed", 0); } } @@ -311,10 +431,92 @@ void settings_clean_invalid(void) settings_clean_invalid_module(module); - g_free(module); last_invalid_modules = g_slist_remove(last_invalid_modules, module); + g_free(module); + } +} + +static int backwards_compatibility(const char *module, CONFIG_NODE *node, + CONFIG_NODE *parent) +{ + const char *new_key, *new_module; + CONFIG_NODE *new_node; + char *new_value; + int old_value; + + new_value = NULL; new_key = NULL; new_module = NULL; + + /* fe-text term_type -> fe-common/core term_charset - for 0.8.10-> */ + if (strcmp(module, "fe-text") == 0) { + if (strcasecmp(node->key, "term_type") == 0 || + /* kludge for cvs-version where term_charset was in fe-text */ + strcasecmp(node->key, "term_charset") == 0) { + new_module = "fe-common/core"; + new_key = "term_charset"; + new_value = !is_valid_charset(node->value) ? NULL : + g_strdup(node->value); + new_node = iconfig_node_traverse("settings", FALSE); + new_node = new_node == NULL ? NULL : + config_node_section(new_node, new_module, -1); + + config_node_set_str(mainconfig, new_node, + new_key, new_value); + /* remove old */ + config_node_set_str(mainconfig, parent, + node->key, NULL); + g_free(new_value); + config_changed = TRUE; + return new_key != NULL; + } + } + new_value = NULL, new_key = NULL; + /* FIXME: remove later - for 0.8.6 -> */ + if (node->value == NULL || !is_numeric(node->value, '\0')) + return FALSE; + + old_value = atoi(node->value); + + if (strcmp(module, "fe-text") == 0) { + if (strcasecmp(node->key, "lag_min_show") == 0) + new_value = g_strdup_printf("%dms", old_value*10); + else if (strcasecmp(node->key, "scrollback_hours") == 0) { + new_value = g_strdup_printf("%dh", old_value); + new_key = "scrollback_time"; + } + } else if (strcmp(module, "irc/core") == 0) { + if (strcasecmp(node->key, "cmd_queue_speed") == 0) + new_value = g_strdup_printf("%dms", old_value); + } else if (strcmp(module, "irc/dcc") == 0) { + if (strcasecmp(node->key, "dcc_autoget_max_size") == 0) + new_value = g_strdup_printf("%dk", old_value); + } else if (strcmp(module, "irc/notify") == 0) { + if (strcasecmp(node->key, "notify_idle_time") == 0) + new_value = g_strdup_printf("%dmin", old_value); + } else if (strcmp(module, "core") == 0) { + if (strcasecmp(node->key, "write_buffer_mins") == 0) { + new_value = g_strdup_printf("%dmin", old_value); + new_key = "write_buffer_timeout"; + } else if (strcasecmp(node->key, "write_buffer_kb") == 0) { + new_value = g_strdup_printf("%dk", old_value); + new_key = "write_buffer_size"; + } + } + + if (new_key != NULL || new_value != NULL) { + config_node_set_str(mainconfig, parent, + new_key != NULL ? new_key : node->key, + new_value != NULL ? + new_value : node->value); + if (new_key != NULL) { + /* remove old */ + config_node_set_str(mainconfig, parent, + node->key, NULL); + } + config_changed = TRUE; + g_free(new_value); } + return new_key != NULL; } /* verify that all settings in config file for `module' are actually found @@ -322,9 +524,9 @@ void settings_clean_invalid(void) void settings_check_module(const char *module) { SETTINGS_REC *set; - CONFIG_NODE *node; + CONFIG_NODE *node, *parent; GString *errors; - GSList *tmp; + GSList *tmp, *next; int count; g_return_if_fail(module != NULL); @@ -338,11 +540,16 @@ void settings_check_module(const char *module) "file for module %s:", module); count = 0; + parent = node; tmp = config_node_first(node->value); - for (; tmp != NULL; tmp = config_node_next(tmp)) { + for (; tmp != NULL; tmp = next) { node = tmp->data; + next = config_node_next(tmp); set = g_hash_table_lookup(settings, node->key); + if (backwards_compatibility(module, node, parent)) + continue; + if (set == NULL || strcmp(set->module, module) != 0) { g_string_sprintfa(errors, " %s", node->key); count++; @@ -485,7 +692,7 @@ static CONFIG_REC *parse_configfile(const char *fname) config = config_open(NULL, -1); } - if (path != NULL) + if (config->fname != NULL) config_parse(config); else config_parse_data(config, default_config, "internal"); @@ -621,7 +828,8 @@ void settings_init(void) init_configfile(); settings_add_bool("misc", "settings_autosave", TRUE); - timeout_tag = g_timeout_add(1000*60*60, (GSourceFunc) sig_autosave, NULL); + timeout_tag = g_timeout_add(SETTINGS_AUTOSAVE_TIMEOUT, + (GSourceFunc) sig_autosave, NULL); signal_add("irssi init finished", (SIGNAL_FUNC) sig_init_finished); signal_add("gui exit", (SIGNAL_FUNC) sig_autosave); }