mirror of
https://github.com/irssi/irssi.git
synced 2026-08-10 12:23:37 +02:00
Lots of changes again. Biggest ones:
- window's text buffer should work better - themes are almost working, you can change the text formats with /format - automatically try to rejoin the channel after 5 minutes if the join there failed because it was "temporarily unavailable" (netsplits) - generally cleaning code.. git-svn-id: http://svn.irssi.org/repos/irssi/trunk@216 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
parent
969cfe8abc
commit
cbdaf7d06d
63 changed files with 2471 additions and 1912 deletions
|
|
@ -20,6 +20,8 @@
|
|||
|
||||
#include "module.h"
|
||||
#include "signals.h"
|
||||
#include "commands.h"
|
||||
#include "levels.h"
|
||||
#include "misc.h"
|
||||
#include "lib-config/iconfig.h"
|
||||
#include "settings.h"
|
||||
|
|
@ -29,6 +31,7 @@
|
|||
|
||||
GSList *themes;
|
||||
THEME_REC *current_theme;
|
||||
GHashTable *default_formats;
|
||||
|
||||
THEME_REC *theme_create(const char *path, const char *name)
|
||||
{
|
||||
|
|
@ -46,17 +49,15 @@ THEME_REC *theme_create(const char *path, const char *name)
|
|||
return rec;
|
||||
}
|
||||
|
||||
static void theme_destroy_hash(const char *key, MODULE_THEME_REC *rec)
|
||||
static void theme_module_destroy(const char *key, MODULE_THEME_REC *rec)
|
||||
{
|
||||
int n, max;
|
||||
int n;
|
||||
|
||||
max = strarray_length(rec->formatlist);
|
||||
for (n = 0; n < max; n++)
|
||||
if (rec->format[n] != NULL)
|
||||
g_free(rec->format[n]);
|
||||
g_free(rec->format);
|
||||
for (n = 0; n < rec->count; n++)
|
||||
if (rec->formats[n] != NULL)
|
||||
g_free(rec->formats[n]);
|
||||
g_free(rec->formats);
|
||||
|
||||
g_strfreev(rec->formatlist);
|
||||
g_free(rec->name);
|
||||
g_free(rec);
|
||||
}
|
||||
|
|
@ -64,7 +65,7 @@ static void theme_destroy_hash(const char *key, MODULE_THEME_REC *rec)
|
|||
void theme_destroy(THEME_REC *rec)
|
||||
{
|
||||
signal_emit("theme destroyed", 1, rec);
|
||||
g_hash_table_foreach(rec->modules, (GHFunc) theme_destroy_hash, NULL);
|
||||
g_hash_table_foreach(rec->modules, (GHFunc) theme_module_destroy, NULL);
|
||||
g_hash_table_destroy(rec->modules);
|
||||
|
||||
if (rec->bg_pixmap != NULL) g_free(rec->bg_pixmap);
|
||||
|
|
@ -74,6 +75,119 @@ void theme_destroy(THEME_REC *rec)
|
|||
g_free(rec);
|
||||
}
|
||||
|
||||
static MODULE_THEME_REC *theme_module_create(THEME_REC *theme, const char *module)
|
||||
{
|
||||
MODULE_THEME_REC *rec;
|
||||
FORMAT_REC *formats;
|
||||
|
||||
rec = g_hash_table_lookup(theme->modules, module);
|
||||
if (rec != NULL) return rec;
|
||||
|
||||
formats = g_hash_table_lookup(default_formats, module);
|
||||
g_return_val_if_fail(formats != NULL, NULL);
|
||||
|
||||
rec = g_new0(MODULE_THEME_REC, 1);
|
||||
rec->name = g_strdup(module);
|
||||
|
||||
for (rec->count = 0; formats[rec->count].def != NULL; rec->count++) ;
|
||||
rec->formats = g_new0(char *, rec->count);
|
||||
|
||||
g_hash_table_insert(theme->modules, rec->name, rec);
|
||||
return rec;
|
||||
}
|
||||
|
||||
static void theme_read_formats(CONFIG_REC *config, THEME_REC *theme, const char *module)
|
||||
{
|
||||
MODULE_THEME_REC *rec;
|
||||
FORMAT_REC *formats;
|
||||
CONFIG_NODE *node;
|
||||
GSList *tmp;
|
||||
int n;
|
||||
|
||||
formats = g_hash_table_lookup(default_formats, module);
|
||||
if (formats == NULL) return;
|
||||
|
||||
node = config_node_traverse(config, "formats", FALSE);
|
||||
if (node == NULL) return;
|
||||
node = config_node_section(node, module, -1);
|
||||
if (node == NULL) return;
|
||||
|
||||
rec = theme_module_create(theme, module);
|
||||
|
||||
for (tmp = node->value; tmp != NULL; tmp = tmp->next) {
|
||||
node = tmp->data;
|
||||
|
||||
if (node->key == NULL || node->value == NULL)
|
||||
continue;
|
||||
|
||||
for (n = 0; formats[n].def != NULL; n++) {
|
||||
if (formats[n].tag != NULL &&
|
||||
g_strcasecmp(formats[n].tag, node->key) == 0) {
|
||||
rec->formats[n] = g_strdup(node->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void theme_read_module(THEME_REC *theme, const char *module)
|
||||
{
|
||||
CONFIG_REC *config;
|
||||
char *msg;
|
||||
|
||||
config = config_open(theme->path, -1);
|
||||
if (config == NULL) return;
|
||||
|
||||
config_parse(config);
|
||||
|
||||
if (config_last_error(mainconfig) != NULL) {
|
||||
msg = g_strdup_printf(_("Ignored errors in theme:\n%s"),
|
||||
config_last_error(mainconfig));
|
||||
signal_emit("gui dialog", 2, "error", msg);
|
||||
g_free(msg);
|
||||
}
|
||||
|
||||
theme_read_formats(config, theme, module);
|
||||
|
||||
config_close(config);
|
||||
}
|
||||
|
||||
static void theme_remove_module(THEME_REC *theme, const char *module)
|
||||
{
|
||||
MODULE_THEME_REC *rec;
|
||||
|
||||
rec = g_hash_table_lookup(theme->modules, module);
|
||||
if (rec == NULL) return;
|
||||
|
||||
g_hash_table_remove(theme->modules, module);
|
||||
theme_module_destroy(module, rec);
|
||||
}
|
||||
|
||||
void theme_register_module(const char *module, FORMAT_REC *formats)
|
||||
{
|
||||
if (g_hash_table_lookup(default_formats, module) != NULL)
|
||||
return;
|
||||
|
||||
g_hash_table_insert(default_formats, g_strdup(module), formats);
|
||||
|
||||
if (current_theme != NULL)
|
||||
theme_read_module(current_theme, module);
|
||||
}
|
||||
|
||||
void theme_unregister_module(const char *module)
|
||||
{
|
||||
gpointer key, value;
|
||||
|
||||
if (!g_hash_table_lookup_extended(default_formats, module, &key, &value))
|
||||
return;
|
||||
|
||||
g_hash_table_remove(default_formats, key);
|
||||
g_free(key);
|
||||
|
||||
if (current_theme != NULL)
|
||||
theme_remove_module(current_theme, module);
|
||||
}
|
||||
|
||||
static THEME_REC *theme_find(const char *name)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
|
@ -115,49 +229,19 @@ static void find_themes(gchar *path)
|
|||
closedir(dirp);
|
||||
}
|
||||
|
||||
/* Read module texts into theme */
|
||||
static void theme_read_module_texts(const char *hashkey, MODULE_THEME_REC *rec, CONFIG_REC *config)
|
||||
static void theme_read(THEME_REC *theme, const char *path)
|
||||
{
|
||||
CONFIG_NODE *formats;
|
||||
GSList *tmp;
|
||||
char **flist;
|
||||
int n;
|
||||
|
||||
formats = config_node_traverse(config, "moduleformats", FALSE);
|
||||
if (formats == NULL) return;
|
||||
|
||||
for (tmp = formats->value; tmp != NULL; tmp = tmp->next) {
|
||||
CONFIG_NODE *node = tmp->data;
|
||||
|
||||
if (node->key == NULL || node->value == NULL)
|
||||
continue;
|
||||
|
||||
for (n = 0, flist = rec->formatlist; *flist != NULL; flist++, n++) {
|
||||
if (g_strcasecmp(*flist, node->key) == 0) {
|
||||
rec->format[n] = g_strdup(node->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int theme_read(THEME_REC *theme, const char *path)
|
||||
{
|
||||
MODULE_THEME_REC *mrec;
|
||||
CONFIG_REC *config;
|
||||
CONFIG_NODE *formats;
|
||||
GSList *tmp;
|
||||
char *value;
|
||||
int errors;
|
||||
|
||||
config = config_open(path, -1);
|
||||
if (config == NULL) {
|
||||
/* didn't exist or no access? */
|
||||
theme->default_color = 15;
|
||||
return FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
errors = config_parse(config) == -1;
|
||||
config_parse(config);
|
||||
|
||||
/* default color */
|
||||
theme->default_color = config_get_int(config, NULL, "default_color", 15);
|
||||
|
|
@ -175,58 +259,172 @@ static int theme_read(THEME_REC *theme, const char *path)
|
|||
theme->flags |= THEME_FLAG_BG_SCALED;
|
||||
if (config_get_bool(config, NULL, "bg_shaded", FALSE))
|
||||
theme->flags |= THEME_FLAG_BG_SHADED;
|
||||
|
||||
/* Read modules that are defined in this theme. */
|
||||
formats = config_node_traverse(config, "modules", FALSE);
|
||||
if (formats != NULL) {
|
||||
for (tmp = formats->value; tmp != NULL; tmp = tmp->next) {
|
||||
CONFIG_NODE *node = tmp->data;
|
||||
|
||||
if (node->key == NULL || node->value == NULL)
|
||||
continue;
|
||||
|
||||
mrec = g_new0(MODULE_THEME_REC, 1);
|
||||
mrec->name = g_strdup(node->key);
|
||||
mrec->formatlist = g_strsplit(node->value, " ", -1);
|
||||
mrec->format = g_new0(char*, strarray_length(mrec->formatlist));
|
||||
g_hash_table_insert(theme->modules, mrec->name, mrec);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read the texts inside the plugin */
|
||||
g_hash_table_foreach(theme->modules, (GHFunc) theme_read_module_texts, config);
|
||||
|
||||
if (errors) {
|
||||
/* errors fixed - save the theme */
|
||||
if (config_write(config, NULL, 0660) == -1) {
|
||||
/* we probably tried to save to global directory
|
||||
where we didn't have access.. try saving it to
|
||||
home dir instead. */
|
||||
char *str;
|
||||
|
||||
/* check that we really didn't try to save
|
||||
it to home dir.. */
|
||||
str = g_strdup_printf("%s/.irssi/", g_get_home_dir());
|
||||
if (strncmp(path, str, strlen(str)) != 0) {
|
||||
g_free(str);
|
||||
str = g_strdup_printf("%s/.irssi/%s", g_get_home_dir(), g_basename(path));
|
||||
|
||||
config_write(config, str, 0660);
|
||||
}
|
||||
g_free(str);
|
||||
}
|
||||
}
|
||||
config_close(config);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
static void sig_formats_error(void)
|
||||
typedef struct {
|
||||
char *name;
|
||||
char *short_name;
|
||||
} THEME_SEARCH_REC;
|
||||
|
||||
static int theme_search_equal(THEME_SEARCH_REC *r1, THEME_SEARCH_REC *r2)
|
||||
{
|
||||
signal_emit("gui dialog", 2, "warning",
|
||||
"Your theme(s) had some old format strings, "
|
||||
"these have been changed back to their default values.");
|
||||
signal_remove("irssi init finished", (SIGNAL_FUNC) sig_formats_error);
|
||||
return g_strcasecmp(r1->short_name, r2->short_name);
|
||||
}
|
||||
|
||||
static void theme_get_modules(char *module, FORMAT_REC *formats, GSList **list)
|
||||
{
|
||||
THEME_SEARCH_REC *rec;
|
||||
|
||||
rec = g_new(THEME_SEARCH_REC, 1);
|
||||
rec->name = module;
|
||||
rec->short_name = strrchr(module, '/');
|
||||
if (rec->short_name != NULL)
|
||||
rec->short_name++; else rec->short_name = module;
|
||||
*list = g_slist_insert_sorted(*list, rec, (GCompareFunc) theme_search_equal);
|
||||
}
|
||||
|
||||
static GSList *get_sorted_modules(void)
|
||||
{
|
||||
GSList *list;
|
||||
|
||||
list = NULL;
|
||||
g_hash_table_foreach(default_formats, (GHFunc) theme_get_modules, &list);
|
||||
return list;
|
||||
}
|
||||
|
||||
static THEME_SEARCH_REC *theme_search(GSList *list, const char *module)
|
||||
{
|
||||
THEME_SEARCH_REC *rec;
|
||||
|
||||
while (list != NULL) {
|
||||
rec = list->data;
|
||||
|
||||
if (g_strcasecmp(rec->short_name, module) == 0)
|
||||
return rec;
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void theme_show(THEME_SEARCH_REC *rec, const char *key, const char *value)
|
||||
{
|
||||
MODULE_THEME_REC *theme;
|
||||
FORMAT_REC *formats;
|
||||
const char *text, *last_title;
|
||||
int n, first;
|
||||
|
||||
formats = g_hash_table_lookup(default_formats, rec->name);
|
||||
theme = g_hash_table_lookup(current_theme->modules, rec->name);
|
||||
|
||||
last_title = NULL; first = TRUE;
|
||||
for (n = 1; formats[n].def != NULL; n++) {
|
||||
text = theme != NULL && theme->formats[n] != NULL ?
|
||||
theme->formats[n] : formats[n].def;
|
||||
|
||||
if (formats[n].tag == NULL)
|
||||
last_title = text;
|
||||
else if ((value != NULL && key != NULL && g_strcasecmp(formats[n].tag, key) == 0) ||
|
||||
(value == NULL && (key == NULL || stristr(formats[n].tag, key) != NULL))) {
|
||||
if (first) {
|
||||
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "");
|
||||
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%K[%W%s%K] - [%W%s%K]", rec->short_name, formats[0].def);
|
||||
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "");
|
||||
first = FALSE;
|
||||
}
|
||||
if (last_title != NULL)
|
||||
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%K[%W%s%K]", last_title);
|
||||
if (value != NULL) {
|
||||
theme = theme_module_create(current_theme, rec->name);
|
||||
theme->formats[n] = g_strdup(value);
|
||||
text = value;
|
||||
}
|
||||
printtext(NULL, NULL, MSGLEVEL_CLIENTCRAP, "%s %K=%n %s", formats[n].tag, text);
|
||||
last_title = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cmd_format(const char *data)
|
||||
{
|
||||
char *params, *module, *key, *value;
|
||||
GSList *tmp, *modules;
|
||||
|
||||
/* /FORMAT [<module>] [<key> [<value>]] */
|
||||
params = cmd_get_params(data, 3 | PARAM_FLAG_GETREST, &module, &key, &value);
|
||||
|
||||
modules = get_sorted_modules();
|
||||
if (*module != '\0' && theme_search(modules, module) == NULL) {
|
||||
/* first argument isn't module.. */
|
||||
g_free(params);
|
||||
params = cmd_get_params(data, 2 | PARAM_FLAG_GETREST, &key, &value);
|
||||
module = "";
|
||||
}
|
||||
|
||||
if (*key == '\0') key = NULL;
|
||||
if (*value == '\0') value = NULL;
|
||||
|
||||
for (tmp = modules; tmp != NULL; tmp = tmp->next) {
|
||||
THEME_SEARCH_REC *rec = tmp->data;
|
||||
|
||||
if (*module == '\0' || g_strcasecmp(rec->short_name, module) == 0)
|
||||
theme_show(rec, key, value);
|
||||
}
|
||||
g_slist_foreach(modules, (GFunc) g_free, NULL);
|
||||
g_slist_free(modules);
|
||||
|
||||
g_free(params);
|
||||
}
|
||||
|
||||
static void module_save(const char *module, MODULE_THEME_REC *rec, CONFIG_NODE *fnode)
|
||||
{
|
||||
CONFIG_NODE *node;
|
||||
FORMAT_REC *formats;
|
||||
int n;
|
||||
|
||||
formats = g_hash_table_lookup(default_formats, rec->name);
|
||||
if (formats == NULL) return;
|
||||
|
||||
node = config_node_section(fnode, rec->name, NODE_TYPE_BLOCK);
|
||||
for (n = 0; formats[n].def != NULL; n++) {
|
||||
if (rec->formats[n] != NULL)
|
||||
iconfig_node_set_str(node, formats[n].tag, rec->formats[n]);
|
||||
}
|
||||
}
|
||||
|
||||
/* save changed formats */
|
||||
static void cmd_save(void)
|
||||
{
|
||||
CONFIG_REC *config;
|
||||
CONFIG_NODE *fnode;
|
||||
|
||||
config = config_open(current_theme->path, 0660);
|
||||
if (config == NULL) return;
|
||||
|
||||
config_parse(config);
|
||||
|
||||
fnode = config_node_traverse(config, "formats", TRUE);
|
||||
g_hash_table_foreach(current_theme->modules, (GHFunc) module_save, fnode);
|
||||
|
||||
if (config_write(config, NULL, 0660) == -1) {
|
||||
/* we probably tried to save to global directory
|
||||
where we didn't have access.. try saving it to
|
||||
home dir instead. */
|
||||
char *str;
|
||||
|
||||
/* check that we really didn't try to save
|
||||
it to home dir.. */
|
||||
str = g_strdup_printf("%s/.irssi/", g_get_home_dir());
|
||||
if (strncmp(current_theme->path, str, strlen(str)) != 0) {
|
||||
g_free(str);
|
||||
str = g_strdup_printf("%s/.irssi/%s", g_get_home_dir(), g_basename(current_theme->path));
|
||||
|
||||
config_write(config, str, 0660);
|
||||
}
|
||||
g_free(str);
|
||||
}
|
||||
config_close(config);
|
||||
}
|
||||
|
||||
void themes_init(void)
|
||||
|
|
@ -235,7 +433,8 @@ void themes_init(void)
|
|||
GSList *tmp;
|
||||
const char *value;
|
||||
char *str;
|
||||
int errors;
|
||||
|
||||
default_formats = g_hash_table_new((GHashFunc) g_str_hash, (GCompareFunc) g_str_equal);
|
||||
|
||||
/* first there's default theme.. */
|
||||
str = g_strdup_printf("%s/.irssi/default.theme", g_get_home_dir());
|
||||
|
|
@ -251,22 +450,20 @@ void themes_init(void)
|
|||
find_themes(SYSCONFDIR"/irssi");
|
||||
|
||||
/* read formats for all themes */
|
||||
errors = FALSE;
|
||||
for (tmp = themes; tmp != NULL; tmp = tmp->next) {
|
||||
rec = tmp->data;
|
||||
|
||||
if (theme_read(rec, rec->path))
|
||||
errors = TRUE;
|
||||
theme_read(rec, rec->path);
|
||||
}
|
||||
|
||||
if (errors)
|
||||
signal_add("irssi init finished", (SIGNAL_FUNC) sig_formats_error);
|
||||
|
||||
/* find the current theme to use */
|
||||
value = settings_get_str("current_theme");
|
||||
|
||||
rec = theme_find(value);
|
||||
if (rec != NULL) current_theme = rec;
|
||||
|
||||
command_bind("format", NULL, (SIGNAL_FUNC) cmd_format);
|
||||
command_bind("save", NULL, (SIGNAL_FUNC) cmd_save);
|
||||
}
|
||||
|
||||
void themes_deinit(void)
|
||||
|
|
@ -275,4 +472,9 @@ void themes_deinit(void)
|
|||
g_slist_foreach(themes, (GFunc) theme_destroy, NULL);
|
||||
g_slist_free(themes);
|
||||
themes = NULL;
|
||||
|
||||
g_hash_table_destroy(default_formats);
|
||||
|
||||
command_unbind("format", (SIGNAL_FUNC) cmd_format);
|
||||
command_unbind("save", (SIGNAL_FUNC) cmd_save);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue