diff --git a/src/core/commands.h b/src/core/commands.h index 0b599f54..bdc8755d 100644 --- a/src/core/commands.h +++ b/src/core/commands.h @@ -37,7 +37,8 @@ enum { CMDERR_CHAN_NOT_FOUND, /* channel not found */ CMDERR_CHAN_NOT_SYNCED, /* channel not fully synchronized yet */ CMDERR_ILLEGAL_PROTO, /* requires different chat protocol than the active server */ - CMDERR_NOT_GOOD_IDEA /* not good idea to do, -yes overrides this */ + CMDERR_NOT_GOOD_IDEA, /* not good idea to do, -yes overrides this */ + CMDERR_INVALID_TIME /* invalid time specification */ }; /* Return the full command for `alias' */ diff --git a/src/core/log-away.c b/src/core/log-away.c index 724e4b4a..586d17d4 100644 --- a/src/core/log-away.c +++ b/src/core/log-away.c @@ -38,16 +38,13 @@ static void sig_log_written(LOG_REC *log) static void awaylog_open(void) { - const char *fname, *levelstr; + const char *fname; LOG_REC *log; int level; fname = settings_get_str("awaylog_file"); - levelstr = settings_get_str("awaylog_level"); - if (*fname == '\0' || *levelstr == '\0') return; - - level = level2bits(levelstr); - if (level == 0) return; + level = settings_get_level("awaylog_level"); + if (*fname == '\0' || level == 0) return; log = log_find(fname); if (log != NULL && log->handle != -1) @@ -106,7 +103,7 @@ void log_away_init(void) away_msgs = 0; settings_add_str("log", "awaylog_file", IRSSI_DIR_SHORT"/away.log"); - settings_add_str("log", "awaylog_level", "msgs hilight"); + settings_add_level("log", "awaylog_level", "msgs hilight"); signal_add("log written", (SIGNAL_FUNC) sig_log_written); signal_add("away mode changed", (SIGNAL_FUNC) sig_away_changed); diff --git a/src/core/misc.c b/src/core/misc.c index 89f564d3..46720d62 100644 --- a/src/core/misc.c +++ b/src/core/misc.c @@ -816,3 +816,117 @@ int nearest_power(int num) while (n < num) n <<= 1; return n; } + +int parse_time_interval(const char *time, int *msecs) +{ + const char *desc; + int number, len; + + *msecs = 0; + + /* max. return value is about 1.6 years */ + number = 0; + for (;;) { + if (i_isdigit(*time)) { + number = number*10 + (*time - '0'); + time++; + continue; + } + + /* skip punctuation */ + while (*time != '\0' && i_ispunct(*time)) + time++; + + /* get description */ + for (len = 0, desc = time; i_isalpha(*time); time++) + len++; + + if (len == 0) { + if (number == 0) { + /* "0" - allow it */ + return TRUE; + } + + *msecs += number; /* assume seconds */ + return FALSE; + } + + if (g_strncasecmp(desc, "weeks", len) == 0) + *msecs += number * 1000*3600*7; + if (g_strncasecmp(desc, "days", len) == 0) + *msecs += number * 1000*3600; + else if (g_strncasecmp(desc, "minutes", len) == 0 || + g_strncasecmp(desc, "mins", len) == 0) + *msecs += number * 1000*60; + else if (g_strncasecmp(desc, "seconds", len) == 0 || + g_strncasecmp(desc, "secs", len) == 0) + *msecs += number * 1000; + else if (g_strncasecmp(desc, "milliseconds", len) == 0 || + g_strncasecmp(desc, "millisecs", len) == 0 || + g_strncasecmp(desc, "mseconds", len) == 0 || + g_strncasecmp(desc, "msecs", len) == 0) + *msecs += number; + + /* skip punctuation */ + while (*time != '\0' && i_ispunct(*time)) + time++; + + if (*time == '\0') + break; + + number = 0; + } + + return TRUE; +} + +int parse_size(const char *size, int *bytes) +{ + const char *desc; + int number, len; + + *bytes = 0; + + /* max. return value is about 1.6 years */ + number = 0; + while (*size != '\0') { + if (i_isdigit(*size)) { + number = number*10 + (*size - '0'); + size++; + continue; + } + + /* skip punctuation */ + while (*size != '\0' && i_ispunct(*size)) + size++; + + /* get description */ + for (len = 0, desc = size; i_isalpha(*size); size++) + len++; + + if (len == 0) { + if (number == 0) { + /* "0" - allow it */ + return TRUE; + } + + *bytes += number*1024; /* assume kilobytes */ + return FALSE; + } + + if (g_strncasecmp(desc, "gbytes", len) == 0) + *bytes += number * 1024*1024*1024; + if (g_strncasecmp(desc, "mbytes", len) == 0) + *bytes += number * 1024*1024; + if (g_strncasecmp(desc, "kbytes", len) == 0) + *bytes += number * 1024; + if (g_strncasecmp(desc, "bytes", len) == 0) + *bytes += number; + + /* skip punctuation */ + while (*size != '\0' && i_ispunct(*size)) + size++; + } + + return TRUE; +} diff --git a/src/core/misc.h b/src/core/misc.h index 46f91bb8..7eee01a2 100644 --- a/src/core/misc.h +++ b/src/core/misc.h @@ -105,4 +105,8 @@ char *escape_string(const char *str); int nearest_power(int num); +/* Returns TRUE / FALSE */ +int parse_time_interval(const char *time, int *msecs); +int parse_size(const char *size, int *bytes); + #endif diff --git a/src/core/servers-reconnect.c b/src/core/servers-reconnect.c index c7b5dd45..beeddc94 100644 --- a/src/core/servers-reconnect.c +++ b/src/core/servers-reconnect.c @@ -461,14 +461,14 @@ static void sig_chat_protocol_deinit(CHAT_PROTOCOL_REC *proto) static void read_settings(void) { - reconnect_time = settings_get_int("server_reconnect_time"); - connect_timeout = settings_get_int("server_connect_timeout"); + reconnect_time = settings_get_time("server_reconnect_time")/1000; + connect_timeout = settings_get_time("server_connect_timeout")/1000; } void servers_reconnect_init(void) { - settings_add_int("server", "server_reconnect_time", 300); - settings_add_int("server", "server_connect_timeout", 300); + settings_add_time("server", "server_reconnect_time", "5min"); + settings_add_time("server", "server_connect_timeout", "5min"); reconnects = NULL; last_reconnect_tag = 0; diff --git a/src/core/settings.c b/src/core/settings.c index d99757e0..c93a11d6 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -21,6 +21,7 @@ #include "module.h" #include "signals.h" #include "commands.h" +#include "levels.h" #include "misc.h" #include "lib-config/iconfig.h" @@ -29,6 +30,8 @@ #include +#define SETTINGS_AUTOSAVE_TIMEOUT (1000*60*60) /* 1 hour */ + CONFIG_REC *mainconfig; static GString *last_errors; @@ -60,133 +63,214 @@ 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; rec = settings_find(key); - g_return_val_if_fail(rec != NULL, NULL); + if (rec == NULL) { + g_warning("settings_get(%s) : not found", key); + return 0; + } + if (type != -1 && rec->type != type) { + g_warning("settings_get(%s) : invalid type", key); + return 0; + } - setnode = iconfig_node_traverse("settings", FALSE); - if (setnode == NULL) - return rec->def; + return rec; +} - node = config_node_section(setnode, rec->module, -1); - return node == NULL ? rec->def : - config_node_get_str(node, key, rec->def); +static const char * +settings_get_str_type(const char *key, SettingType type) +{ + SETTINGS_REC *rec; + CONFIG_NODE *node; + + 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); +} + +int settings_get_time(const char *key) +{ + const char *str; + int msecs; + + str = settings_get_str_type(key, SETTING_TYPE_TIME); + if (str != NULL && !parse_time_interval(str, &msecs)) + g_warning("settings_get_size(%s) : Invalid time '%s'", key, str); + return str == NULL ? 0 : msecs; +} + +int settings_get_level(const char *key) +{ + const char *str; + + 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; + + 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; +} + +static void settings_add(const char *module, const char *section, + const char *key, SettingType type, + SettingValue *default_value) +{ + SETTINGS_REC *rec; + + g_return_if_fail(key != NULL); + g_return_if_fail(section != NULL); + + rec = g_hash_table_lookup(settings, key); + 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; + if (type != SETTING_TYPE_INT && + type != SETTING_TYPE_BOOLEAN) { + rec->default_value.v_string = + g_strdup(default_value->v_string); + } + + g_hash_table_insert(settings, rec->key, rec); + } + + rec->refcount++; } void settings_add_str_module(const char *module, const char *section, const char *key, const char *def) { - SETTINGS_REC *rec; + SettingValue default_value; - g_return_if_fail(key != NULL); - g_return_if_fail(section != NULL); - - rec = g_hash_table_lookup(settings, key); - g_return_if_fail(rec == NULL); - - 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); - - g_hash_table_insert(settings, rec->key, rec); + default_value.v_string = (char *) def; + settings_add(module, section, key, SETTING_TYPE_STRING, &default_value); } void settings_add_int_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); - - rec = g_hash_table_lookup(settings, key); - g_return_if_fail(rec == NULL); - - 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); - - g_hash_table_insert(settings, rec->key, rec); + 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); + 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; - 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); + default_value.v_string = (char *) def; + settings_add(module, section, key, SETTING_TYPE_TIME, &default_value); +} - g_hash_table_insert(settings, rec->key, rec); +void settings_add_level_module(const char *module, const char *section, + const char *key, const char *def) +{ + SettingValue default_value; + + default_value.v_string = (char *) 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; + + default_value.v_string = (char *) 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); + 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) +{ + if (--rec->refcount == 0) { + g_hash_table_remove(settings, rec->key); + settings_destroy(rec); + } +} + void settings_remove(const char *key) { SETTINGS_REC *rec; @@ -194,17 +278,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); } 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); return TRUE; } @@ -226,7 +308,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 +332,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; @@ -621,7 +734,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); } diff --git a/src/core/settings.h b/src/core/settings.h index fdff3801..df4a95ab 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -1,18 +1,30 @@ #ifndef __SETTINGS_H #define __SETTINGS_H -enum { +typedef enum { SETTING_TYPE_STRING, SETTING_TYPE_INT, - SETTING_TYPE_BOOLEAN -}; + SETTING_TYPE_BOOLEAN, + SETTING_TYPE_TIME, + SETTING_TYPE_LEVEL, + SETTING_TYPE_SIZE +} SettingType; + +typedef union { + char *v_string; + int v_int; + unsigned int v_bool:1; +} SettingValue; typedef struct { - char *module; - int type; + int refcount; + + char *module; char *key; char *section; - void *def; + + SettingType type; + SettingValue default_value; } SETTINGS_REC; /* macros for handling the default Irssi configuration */ @@ -40,6 +52,9 @@ extern const char *default_config; const char *settings_get_str(const char *key); int settings_get_int(const char *key); int settings_get_bool(const char *key); +int settings_get_time(const char *key); /* as milliseconds */ +int settings_get_level(const char *key); +int settings_get_size(const char *key); /* as bytes */ /* Functions to add/remove settings */ void settings_add_str_module(const char *module, const char *section, @@ -48,6 +63,12 @@ void settings_add_int_module(const char *module, const char *section, const char *key, int def); void settings_add_bool_module(const char *module, const char *section, const char *key, int def); +void settings_add_time_module(const char *module, const char *section, + const char *key, const char *def); +void settings_add_level_module(const char *module, const char *section, + const char *key, const char *def); +void settings_add_size_module(const char *module, const char *section, + const char *key, const char *def); void settings_remove(const char *key); void settings_remove_module(const char *module); @@ -57,13 +78,22 @@ void settings_remove_module(const char *module); settings_add_int_module(MODULE_NAME, section, key, def) #define settings_add_bool(section, key, def) \ settings_add_bool_module(MODULE_NAME, section, key, def) +#define settings_add_time(section, key, def) \ + settings_add_time_module(MODULE_NAME, section, key, def) +#define settings_add_level(section, key, def) \ + settings_add_level_module(MODULE_NAME, section, key, def) +#define settings_add_size(section, key, def) \ + settings_add_size_module(MODULE_NAME, section, key, def) void settings_set_str(const char *key, const char *value); void settings_set_int(const char *key, int value); void settings_set_bool(const char *key, int value); +int settings_set_time(const char *key, const char *value); +int settings_set_level(const char *key, const char *value); +int settings_set_size(const char *key, const char *value); /* Get the type (SETTING_TYPE_xxx) of `key' */ -int settings_get_type(const char *key); +SettingType settings_get_type(const char *key); /* Get all settings sorted by section. Free the result with g_slist_free() */ GSList *settings_get_sorted(void); /* Get the record of the setting */ diff --git a/src/core/write-buffer.c b/src/core/write-buffer.c index 1c3eef82..eec306ae 100644 --- a/src/core/write-buffer.c +++ b/src/core/write-buffer.c @@ -134,17 +134,14 @@ static int flush_timeout(void) static void read_settings(void) { - int msecs; - write_buffer_flush(); - write_buffer_max_blocks = settings_get_int("write_buffer_kb") * - 1024/BUFFER_BLOCK_SIZE; + write_buffer_max_blocks = + settings_get_size("write_buffer_size") / BUFFER_BLOCK_SIZE; - if (settings_get_int("write_buffer_mins") > 0) { - msecs = settings_get_int("write_buffer_mins")*60*1000; + if (settings_get_time("write_buffer_timeout") > 0) { if (timeout_tag == -1) { - timeout_tag = g_timeout_add(msecs, + timeout_tag = g_timeout_add(settings_get_time("write_buffer_timeout"), (GSourceFunc) flush_timeout, NULL); } @@ -161,8 +158,8 @@ static void cmd_flushbuffer(void) void write_buffer_init(void) { - settings_add_int("misc", "write_buffer_mins", 0); - settings_add_int("misc", "write_buffer_kb", 0); + settings_add_time("misc", "write_buffer_timeout", "0"); + settings_add_size("misc", "write_buffer_size", "0"); buffers = g_hash_table_new((GHashFunc) g_direct_hash, (GCompareFunc) g_direct_equal); diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index 49c8db87..e6fdb6fe 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -153,11 +153,11 @@ void fe_common_core_init(void) args_register(options); settings_add_bool("lookandfeel", "timestamps", TRUE); - settings_add_str("lookandfeel", "timestamp_level", "ALL"); - settings_add_int("lookandfeel", "timestamp_timeout", 0); + settings_add_level("lookandfeel", "timestamp_level", "ALL"); + settings_add_time("lookandfeel", "timestamp_timeout", 0); settings_add_bool("lookandfeel", "bell_beeps", FALSE); - settings_add_str("lookandfeel", "beep_msg_level", ""); + settings_add_level("lookandfeel", "beep_msg_level", ""); settings_add_bool("lookandfeel", "beep_when_window_active", TRUE); settings_add_bool("lookandfeel", "beep_when_away", TRUE); diff --git a/src/fe-common/core/fe-core-commands.c b/src/fe-common/core/fe-core-commands.c index b599c810..56c2dac3 100644 --- a/src/fe-common/core/fe-core-commands.c +++ b/src/fe-common/core/fe-core-commands.c @@ -47,7 +47,8 @@ static int ret_texts[] = { TXT_CHAN_NOT_FOUND, TXT_CHAN_NOT_SYNCED, TXT_ILLEGAL_PROTO, - TXT_NOT_GOOD_IDEA + TXT_NOT_GOOD_IDEA, + CMDERR_INVALID_TIME }; int command_hide_output; diff --git a/src/fe-common/core/fe-ignore.c b/src/fe-common/core/fe-ignore.c index 4621ab26..83bc1584 100644 --- a/src/fe-common/core/fe-ignore.c +++ b/src/fe-common/core/fe-ignore.c @@ -115,7 +115,7 @@ static void cmd_ignore(const char *data) char *patternarg, *chanarg, *mask, *levels, *timestr; char **channels; void *free_arg; - int new_ignore; + int new_ignore, msecs; if (*data == '\0') { cmd_ignore_show(); @@ -132,6 +132,13 @@ static void cmd_ignore(const char *data) if (*mask == '\0') cmd_param_error(CMDERR_NOT_ENOUGH_PARAMS); if (*levels == '\0') levels = "ALL"; + msecs = 0; + timestr = g_hash_table_lookup(optlist, "time"); + if (timestr != NULL) { + if (!parse_time_interval(timestr, &msecs)) + cmd_return_error(CMDERR_INVALID_TIME); + } + if (active_win->active_server != NULL && server_ischannel(active_win->active_server, mask)) { chanarg = mask; @@ -173,9 +180,8 @@ static void cmd_ignore(const char *data) rec->regexp = g_hash_table_lookup(optlist, "regexp") != NULL; rec->fullword = g_hash_table_lookup(optlist, "full") != NULL; rec->replies = g_hash_table_lookup(optlist, "replies") != NULL; - timestr = g_hash_table_lookup(optlist, "time"); - if (timestr != NULL) - rec->unignore_time = time(NULL)+atoi(timestr); + if (msecs != 0) + rec->unignore_time = time(NULL)+msecs/1000; if (new_ignore) ignore_add_rec(rec); diff --git a/src/fe-common/core/fe-log.c b/src/fe-common/core/fe-log.c index 1db74fe1..1b88364e 100644 --- a/src/fe-common/core/fe-log.c +++ b/src/fe-common/core/fe-log.c @@ -671,7 +671,7 @@ static void read_settings(void) autolog_path = settings_get_str("autolog_path"); autolog_level = !settings_get_bool("autolog") ? 0 : - level2bits(settings_get_str("autolog_level")); + settings_get_level("autolog_level"); if (old_autolog && !autolog_level) autologs_close_all(); @@ -704,7 +704,7 @@ void fe_log_init(void) settings_add_bool("log", "autolog", FALSE); settings_add_bool("log", "autolog_colors", FALSE); settings_add_str("log", "autolog_path", "~/irclogs/$tag/$0.log"); - settings_add_str("log", "autolog_level", "all -crap -clientcrap -ctcps"); + settings_add_level("log", "autolog_level", "all -crap -clientcrap -ctcps"); settings_add_str("log", "log_theme", ""); autolog_level = 0; diff --git a/src/fe-common/core/fe-queries.c b/src/fe-common/core/fe-queries.c index 8345d52f..f48e37e9 100644 --- a/src/fe-common/core/fe-queries.c +++ b/src/fe-common/core/fe-queries.c @@ -340,8 +340,8 @@ static void sig_message_private(SERVER_REC *server, const char *msg, static void read_settings(void) { - querycreate_level = level2bits(settings_get_str("autocreate_query_level")); - query_auto_close = settings_get_int("autoclose_query"); + querycreate_level = settings_get_level("autocreate_query_level"); + query_auto_close = settings_get_time("autoclose_query")/1000; if (query_auto_close > 0 && queryclose_tag == -1) queryclose_tag = g_timeout_add(5000, (GSourceFunc) sig_query_autoclose, NULL); else if (query_auto_close <= 0 && queryclose_tag != -1) { @@ -352,9 +352,9 @@ static void read_settings(void) void fe_queries_init(void) { - settings_add_str("lookandfeel", "autocreate_query_level", "MSGS DCCMSGS"); + settings_add_level("lookandfeel", "autocreate_query_level", "MSGS DCCMSGS"); settings_add_bool("lookandfeel", "autocreate_own_query", TRUE); - settings_add_int("lookandfeel", "autoclose_query", 0); + settings_add_time("lookandfeel", "autoclose_query", "0"); queryclose_tag = -1; read_settings(); diff --git a/src/fe-common/core/fe-settings.c b/src/fe-common/core/fe-settings.c index 7fb512e8..8dba8f73 100644 --- a/src/fe-common/core/fe-settings.c +++ b/src/fe-common/core/fe-settings.c @@ -45,6 +45,9 @@ static void set_print(SETTINGS_REC *rec) value = value_int; break; case SETTING_TYPE_STRING: + case SETTING_TYPE_TIME: + case SETTING_TYPE_LEVEL: + case SETTING_TYPE_SIZE: value = settings_get_str(rec->key); break; default: @@ -106,20 +109,38 @@ static void cmd_set(char *data) if (clear) settings_set_bool(key, FALSE); else if (set_default) - settings_set_bool(key, GPOINTER_TO_INT(rec->def)); + settings_set_bool(key, rec->default_value.v_bool); else set_boolean(key, value); break; case SETTING_TYPE_INT: settings_set_int(key, clear ? 0 : - set_default ? GPOINTER_TO_INT(rec->def) : + set_default ? rec->default_value.v_int : atoi(value)); break; case SETTING_TYPE_STRING: settings_set_str(key, clear ? "" : - set_default ? rec->def : + set_default ? rec->default_value.v_string : value); break; + case SETTING_TYPE_TIME: + if (!settings_set_time(key, clear ? "0" : + set_default ? rec->default_value.v_string : value)) + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, + TXT_INVALID_TIME); + break; + case SETTING_TYPE_LEVEL: + if (!settings_set_level(key, clear ? "" : + set_default ? rec->default_value.v_string : value)) + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, + TXT_INVALID_LEVEL); + break; + case SETTING_TYPE_SIZE: + if (!settings_set_size(key, clear ? "0" : + set_default ? rec->default_value.v_string : value)) + printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, + TXT_INVALID_SIZE); + break; } signal_emit("setup changed", 0); } diff --git a/src/fe-common/core/fe-windows.c b/src/fe-common/core/fe-windows.c index dc264d65..6eb4707a 100644 --- a/src/fe-common/core/fe-windows.c +++ b/src/fe-common/core/fe-windows.c @@ -70,7 +70,7 @@ WINDOW_REC *window_create(WI_ITEM_REC *item, int automatic) rec = g_new0(WINDOW_REC, 1); rec->refnum = window_get_new_refnum(); - rec->level = level2bits(settings_get_str("window_default_level")); + rec->level = settings_get_level("window_default_level"); windows = g_slist_prepend(windows, rec); signal_emit("window created", 2, rec, GINT_TO_POINTER(automatic)); @@ -646,7 +646,7 @@ void windows_init(void) settings_add_bool("lookandfeel", "window_auto_change", FALSE); settings_add_bool("lookandfeel", "windows_auto_renumber", TRUE); settings_add_bool("lookandfeel", "window_check_level_first", FALSE); - settings_add_str("lookandfeel", "window_default_level", "NONE"); + settings_add_level("lookandfeel", "window_default_level", "NONE"); read_settings(); signal_add("server looking", (SIGNAL_FUNC) sig_server_connected); diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index 06464894..c6bc72a3 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -1091,11 +1091,9 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text) static void read_settings(void) { timestamp_level = settings_get_bool("timestamps") ? MSGLEVEL_ALL : 0; - if (timestamp_level > 0) { - timestamp_level = - level2bits(settings_get_str("timestamp_level")); - } - timestamp_timeout = settings_get_int("timestamp_timeout"); + if (timestamp_level > 0) + timestamp_level = settings_get_level("timestamp_level"); + timestamp_timeout = settings_get_time("timestamp_timeout")/1000; hide_server_tags = settings_get_bool("hide_server_tags"); hide_text_style = settings_get_bool("hide_text_style"); diff --git a/src/fe-common/core/hilight-text.c b/src/fe-common/core/hilight-text.c index 9749504b..54cb12a1 100644 --- a/src/fe-common/core/hilight-text.c +++ b/src/fe-common/core/hilight-text.c @@ -676,14 +676,14 @@ static void hilight_nick_cache(GHashTable *list, CHANNEL_REC *channel, static void read_settings(void) { - default_hilight_level = level2bits(settings_get_str("hilight_level")); + default_hilight_level = settings_get_level("hilight_level"); } void hilight_text_init(void) { settings_add_str("lookandfeel", "hilight_color", "%Y"); settings_add_str("lookandfeel", "hilight_act_color", "%M"); - settings_add_str("lookandfeel", "hilight_level", "PUBLIC DCCMSGS"); + settings_add_level("lookandfeel", "hilight_level", "PUBLIC DCCMSGS"); read_settings(); diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c index 2d4f02e1..c70f1e04 100644 --- a/src/fe-common/core/module-formats.c +++ b/src/fe-common/core/module-formats.c @@ -214,6 +214,9 @@ FORMAT_REC fecommon_core_formats[] = { { "chan_not_synced", "Channel not fully synchronized yet, try again after a while", 0 }, { "illegal_proto", "Command isn't designed for the chat protocol of the active server", 0 }, { "not_good_idea", "Doing this is not a good idea. Add -YES option to command if you really mean it", 0 }, + { "invalid_time", "Invalid timestamp", 0 }, + { "invalid_level", "Invalid message level", 0 }, + { "invalid_size", "Invalid size", 0 }, /* ---- */ { NULL, "Themes", 0 }, diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h index 7cd46bab..5f28f0e1 100644 --- a/src/fe-common/core/module-formats.h +++ b/src/fe-common/core/module-formats.h @@ -183,6 +183,9 @@ enum { TXT_CHAN_NOT_SYNCED, TXT_ILLEGAL_PROTO, TXT_NOT_GOOD_IDEA, + TXT_INVALID_TIME, + TXT_INVALID_LEVEL, + TXT_INVALID_SIZE, TXT_FILL_11, diff --git a/src/fe-common/core/printtext.c b/src/fe-common/core/printtext.c index e32b5943..6cc64081 100644 --- a/src/fe-common/core/printtext.c +++ b/src/fe-common/core/printtext.c @@ -474,7 +474,7 @@ static void sig_gui_dialog(const char *type, const char *text) static void read_settings(void) { - beep_msg_level = level2bits(settings_get_str("beep_msg_level")); + beep_msg_level = settings_get_level("beep_msg_level"); beep_when_away = settings_get_bool("beep_when_away"); beep_when_window_active = settings_get_bool("beep_when_window_active"); } diff --git a/src/fe-common/core/window-activity.c b/src/fe-common/core/window-activity.c index 883821f0..64b0aad3 100644 --- a/src/fe-common/core/window-activity.c +++ b/src/fe-common/core/window-activity.c @@ -138,18 +138,18 @@ static void read_settings(void) g_strsplit(targets, " ", -1); hide_level = MSGLEVEL_NEVER | MSGLEVEL_NO_ACT | - level2bits(settings_get_str("activity_hide_level")); - msg_level = level2bits(settings_get_str("activity_msg_level")); + settings_get_level("activity_hide_level"); + msg_level = settings_get_level("activity_msg_level"); hilight_level = MSGLEVEL_HILIGHT | - level2bits(settings_get_str("activity_hilight_level")); + settings_get_level("activity_hilight_level"); } void window_activity_init(void) { settings_add_str("lookandfeel", "activity_hide_targets", ""); - settings_add_str("lookandfeel", "activity_hide_level", ""); - settings_add_str("lookandfeel", "activity_msg_level", "PUBLIC"); - settings_add_str("lookandfeel", "activity_hilight_level", "MSGS DCCMSGS"); + settings_add_level("lookandfeel", "activity_hide_level", ""); + settings_add_level("lookandfeel", "activity_msg_level", "PUBLIC"); + settings_add_level("lookandfeel", "activity_hilight_level", "MSGS DCCMSGS"); read_settings(); signal_add("print text", (SIGNAL_FUNC) sig_hilight_text); diff --git a/src/fe-common/irc/dcc/fe-dcc-chat.c b/src/fe-common/irc/dcc/fe-dcc-chat.c index 3095fcfd..d2723c96 100644 --- a/src/fe-common/irc/dcc/fe-dcc-chat.c +++ b/src/fe-common/irc/dcc/fe-dcc-chat.c @@ -340,7 +340,7 @@ static void read_settings(void) { int level; - level = level2bits(settings_get_str("autocreate_query_level")); + level = settings_get_level("autocreate_query_level"); autocreate_dccquery = (level & MSGLEVEL_DCCMSGS) != 0; } diff --git a/src/fe-text/gui-printtext.c b/src/fe-text/gui-printtext.c index 2d8a8cde..b4d223e9 100644 --- a/src/fe-text/gui-printtext.c +++ b/src/fe-text/gui-printtext.c @@ -30,7 +30,7 @@ #include "gui-windows.h" int mirc_colors[] = { 15, 0, 1, 2, 12, 4, 5, 6, 14, 10, 3, 11, 9, 13, 8, 7 }; -static int scrollback_lines, scrollback_hours, scrollback_burst_remove; +static int scrollback_lines, scrollback_time, scrollback_burst_remove; static int last_fg, last_bg, last_flags; static int next_xpos, next_ypos; @@ -120,7 +120,7 @@ static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view) LINE_REC *line; time_t old_time; - old_time = time(NULL)-(scrollback_hours*3600)+1; + old_time = time(NULL)-scrollback_time+1; if (view->buffer->lines_count >= scrollback_lines+scrollback_burst_remove) { /* remove lines by line count */ @@ -130,7 +130,7 @@ static void remove_old_lines(TEXT_BUFFER_VIEW_REC *view) scrollback_lines == 0) { /* too new line, don't remove yet - also if scrollback_lines is 0, we want to check - only scrollback_hours setting. */ + only scrollback_time setting. */ break; } textbuffer_view_remove_line(view, line); @@ -302,7 +302,7 @@ static void sig_gui_printtext_finished(WINDOW_REC *window) static void read_settings(void) { scrollback_lines = settings_get_int("scrollback_lines"); - scrollback_hours = settings_get_int("scrollback_hours"); + scrollback_time = settings_get_time("scrollback_time")/1000; scrollback_burst_remove = settings_get_int("scrollback_burst_remove"); } @@ -314,7 +314,7 @@ void gui_printtext_init(void) (GCompareFunc) g_str_equal); settings_add_int("history", "scrollback_lines", 500); - settings_add_int("history", "scrollback_hours", 24); + settings_add_time("history", "scrollback_time", "day"); settings_add_int("history", "scrollback_burst_remove", 10); signal_add("gui print text", (SIGNAL_FUNC) sig_gui_print_text); diff --git a/src/fe-text/statusbar-items.c b/src/fe-text/statusbar-items.c index fe74a748..fe9ca0e2 100644 --- a/src/fe-text/statusbar-items.c +++ b/src/fe-text/statusbar-items.c @@ -290,15 +290,16 @@ static void item_lag(SBAR_ITEM_REC *item, int get_size_only) int lag, lag_unknown; server = active_win == NULL ? NULL : active_win->active_server; - lag = get_lag(server, &lag_unknown)/10; + lag = get_lag(server, &lag_unknown); - if (lag <= 0 || lag < settings_get_int("lag_min_show")) { + if (lag <= 0 || lag < settings_get_time("lag_min_show")) { /* don't print the lag item */ if (get_size_only) item->min_size = item->max_size = 0; return; } + lag /= 10; last_lag = lag; last_lag_unknown = lag_unknown; @@ -321,8 +322,10 @@ static void lag_check_update(void) server = active_win == NULL ? NULL : active_win->active_server; lag = get_lag(server, &lag_unknown)/10; - if (lag < settings_get_int("lag_min_show")) - lag = 0; + if (lag < settings_get_time("lag_min_show")) + lag = 0; + else + lag /= 10; if (lag != last_lag || (lag > 0 && lag_unknown != last_lag_unknown)) statusbar_items_redraw("lag"); @@ -372,7 +375,7 @@ static void read_settings(void) void statusbar_items_init(void) { - settings_add_int("misc", "lag_min_show", 100); + settings_add_time("misc", "lag_min_show", "100msec"); settings_add_bool("lookandfeel", "actlist_moves", FALSE); statusbar_item_register("window", NULL, item_window_active); diff --git a/src/fe-text/textbuffer.c b/src/fe-text/textbuffer.c index e989b8fd..5a8d256d 100644 --- a/src/fe-text/textbuffer.c +++ b/src/fe-text/textbuffer.c @@ -137,6 +137,8 @@ static void text_chunk_line_free(TEXT_BUFFER_REC *buffer, LINE_REC *line) break; text = tmp-1; + } else if (*text == LINE_CMD_INDENT_FUNC) { + text += sizeof(int (*) ()); } } } diff --git a/src/irc/core/irc-commands.c b/src/irc/core/irc-commands.c index d7512de2..8c888ffe 100644 --- a/src/irc/core/irc-commands.c +++ b/src/irc/core/irc-commands.c @@ -736,7 +736,7 @@ static int knockout_timeout(void) return 1; } -/* SYNTAX: KNOCKOUT [] */ +/* SYNTAX: KNOCKOUT [