diff options
author | Valentin Batz <senneth@irssi.org> | 2004-09-15 12:11:43 +0000 |
---|---|---|
committer | senneth <senneth@dbcabf3a-b0e7-0310-adc4-f8d773084564> | 2004-09-15 12:11:43 +0000 |
commit | 8ea717b67609a7ddaa6481e49fc638a4b40e84e8 (patch) | |
tree | 10e28c5a7f6ade72b86ad7fd8c680320ecafa36b /src/fe-common | |
parent | 55bcc420a713d5bfac3813f7bc002de0b0c13538 (diff) | |
download | irssi-8ea717b67609a7ddaa6481e49fc638a4b40e84e8.zip |
Fixed memleak in recode.c, fixed typo in special_vars.txt, fixed bug 105, fixed bug 106
git-svn-id: http://svn.irssi.org/repos/irssi/trunk@3295 dbcabf3a-b0e7-0310-adc4-f8d773084564
Diffstat (limited to 'src/fe-common')
-rw-r--r-- | src/fe-common/core/Makefile.am | 2 | ||||
-rw-r--r-- | src/fe-common/core/fe-common-core.c | 10 | ||||
-rw-r--r-- | src/fe-common/core/fe-core-commands.c | 3 | ||||
-rw-r--r-- | src/fe-common/core/fe-messages.c | 16 | ||||
-rw-r--r-- | src/fe-common/core/fe-recode.c | 122 | ||||
-rw-r--r-- | src/fe-common/core/formats.c | 181 | ||||
-rw-r--r-- | src/fe-common/core/module-formats.c | 4 | ||||
-rw-r--r-- | src/fe-common/core/module-formats.h | 2 | ||||
-rw-r--r-- | src/fe-common/core/module.h | 1 | ||||
-rw-r--r-- | src/fe-common/core/printtext.c | 10 | ||||
-rw-r--r-- | src/fe-common/core/utf8.c | 251 | ||||
-rw-r--r-- | src/fe-common/core/utf8.h | 31 | ||||
-rw-r--r-- | src/fe-common/irc/fe-events-numeric.c | 7 | ||||
-rw-r--r-- | src/fe-common/irc/fe-events.c | 41 |
14 files changed, 528 insertions, 153 deletions
diff --git a/src/fe-common/core/Makefile.am b/src/fe-common/core/Makefile.am index 75ff7a9a..c0b53177 100644 --- a/src/fe-common/core/Makefile.am +++ b/src/fe-common/core/Makefile.am @@ -25,6 +25,7 @@ libfe_common_core_a_SOURCES = \ fe-queries.c \ fe-server.c \ fe-settings.c \ + utf8.c \ formats.c \ hilight-text.c \ keyboard.c \ @@ -51,6 +52,7 @@ pkginc_fe_common_core_HEADERS = \ fe-exec.h \ fe-messages.h \ fe-queries.h \ + utf8.h \ formats.h \ hilight-text.h \ keyboard.h \ diff --git a/src/fe-common/core/fe-common-core.c b/src/fe-common/core/fe-common-core.c index 147d5448..443204cb 100644 --- a/src/fe-common/core/fe-common-core.c +++ b/src/fe-common/core/fe-common-core.c @@ -25,10 +25,14 @@ #include "levels.h" #include "settings.h" #include "irssi-version.h" +#ifdef HAVE_NL_LANGINFO +# include <langinfo.h> +#endif #include "servers.h" #include "channels.h" #include "servers-setup.h" +#include "recode.h" #include "autorun.h" #include "fe-core-commands.h" @@ -170,7 +174,11 @@ void fe_common_core_init(void) settings_add_bool("lookandfeel", "use_status_window", TRUE); settings_add_bool("lookandfeel", "use_msgs_window", FALSE); - +#if defined (HAVE_NL_LANGINFO) && defined(CODESET) + settings_add_str("lookandfeel", "term_charset", nl_langinfo(CODESET)); +#else + settings_add_str("lookandfeel", "term_charset", "ISO8859-1"); +#endif themes_init(); theme_register(fecommon_core_formats); diff --git a/src/fe-common/core/fe-core-commands.c b/src/fe-common/core/fe-core-commands.c index cc1f587c..13ddc8ac 100644 --- a/src/fe-common/core/fe-core-commands.c +++ b/src/fe-common/core/fe-core-commands.c @@ -48,7 +48,8 @@ static int ret_texts[] = { TXT_CHAN_NOT_SYNCED, TXT_ILLEGAL_PROTO, TXT_NOT_GOOD_IDEA, - TXT_INVALID_TIME + TXT_INVALID_TIME, + TXT_INVALID_CHARSET }; int command_hide_output; diff --git a/src/fe-common/core/fe-messages.c b/src/fe-common/core/fe-messages.c index f0015f20..d5b011c5 100644 --- a/src/fe-common/core/fe-messages.c +++ b/src/fe-common/core/fe-messages.c @@ -31,6 +31,7 @@ #include "channels.h" #include "nicklist.h" #include "ignore.h" +#include "recode.h" #include "window-items.h" #include "fe-queries.h" @@ -330,7 +331,7 @@ static void sig_message_quit(SERVER_REC *server, const char *nick, WINDOW_REC *window; GString *chans; GSList *tmp, *windows; - char *print_channel; + char *print_channel, *recoded; int once, count; if (ignore_check(server, nick, address, NULL, reason, MSGLEVEL_QUITS)) @@ -363,10 +364,12 @@ static void sig_message_quit(SERVER_REC *server, const char *nick, window = window_item_window((WI_ITEM_REC *) rec); if (g_slist_find(windows, window) == NULL) { windows = g_slist_append(windows, window); + recoded = recode_in(reason, rec->visible_name); printformat(server, rec->visible_name, MSGLEVEL_QUITS, - TXT_QUIT, nick, address, reason, + TXT_QUIT, nick, address, recoded, rec->visible_name); + g_free(recoded); } } count++; @@ -378,17 +381,22 @@ static void sig_message_quit(SERVER_REC *server, const char *nick, display the quit there too */ QUERY_REC *query = query_find(server, nick); if (query != NULL) { + recoded = recode_in(reason, nick); printformat(server, nick, MSGLEVEL_QUITS, - TXT_QUIT, nick, address, reason, ""); + TXT_QUIT, nick, address, recoded, ""); + g_free(recoded); } } if (once || count == 0) { if (chans->len > 0) g_string_truncate(chans, chans->len-1); + /* at least recode_fallback will be used */ + recoded = recode_in(reason, NULL); printformat(server, print_channel, MSGLEVEL_QUITS, count <= 1 ? TXT_QUIT : TXT_QUIT_ONCE, - nick, address, reason, chans->str); + nick, address, recoded, chans->str); + g_free(recoded); } g_string_free(chans, TRUE); } diff --git a/src/fe-common/core/fe-recode.c b/src/fe-common/core/fe-recode.c index a693b5ec..a46e3547 100644 --- a/src/fe-common/core/fe-recode.c +++ b/src/fe-common/core/fe-recode.c @@ -27,26 +27,21 @@ #include "settings.h" #include "printtext.h" #include "formats.h" +#include "recode.h" + +#ifdef HAVE_NL_LANGINFO +# include <langinfo.h> +#endif + #define SLIST_FOREACH(var, head) \ for ((var) = (head); \ (var); \ (var) = g_slist_next((var))) #ifdef HAVE_GLIB2 -static gboolean is_valid_charset(const char *charset) -{ - const char *from="UTF-8"; - const char *str="irssi"; - char *recoded; - if (!charset) - return FALSE; - recoded = g_convert(str, strlen(str), charset, from, NULL, NULL, NULL); - if (recoded) { - g_free(recoded); - return TRUE; - } else - return FALSE; -} +const char *recode_fallback = NULL; +const char *recode_out_default = NULL; +const char *term_charset = NULL; static const char *fe_recode_get_target (WI_ITEM_REC *witem) { @@ -123,7 +118,7 @@ static void fe_recode_add_cmd (const char *data, SERVER_REC *server, WI_ITEM_REC iconfig_set_str("conversions", target, charset); printformat(NULL, NULL, MSGLEVEL_CLIENTNOTICE, TXT_CONVERSION_ADDED, target, charset); } else - printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_CONVERSION_NOT_SUPPORTED, charset); + signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_INVALID_CHARSET), charset); end: cmd_params_free(free_arg); } @@ -156,23 +151,76 @@ static void fe_recode_remove_cmd (const char *data, SERVER_REC *server, WI_ITEM_ static void read_settings(void) { - const char *charset; - - charset = settings_get_str("recode_fallback"); - if (!is_valid_charset(charset)){ - printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_CONVERSION_NOT_SUPPORTED, charset); - settings_set_str("recode_fallback", "ISO8859-1"); - } - charset = settings_get_str("term_charset"); - if (charset && !is_valid_charset(charset)) { - printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_CONVERSION_NOT_SUPPORTED, charset); - settings_set_str("term_charset", "ISO8859-1"); - } - charset = settings_get_str("recode_out_default_charset"); - if (charset && !is_valid_charset(charset)) { - printformat(NULL, NULL, MSGLEVEL_CLIENTERROR, TXT_CONVERSION_NOT_SUPPORTED, charset); - settings_set_str("recode_out_default_charset", ""); - } + const char *old_term_charset = g_strdup (term_charset); + const char *old_recode_fallback = g_strdup (recode_fallback); + const char *old_recode_out_default = g_strdup (recode_out_default); + + recode_fallback = settings_get_str("recode_fallback"); + if (!is_valid_charset(recode_fallback)) { + signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_INVALID_CHARSET), recode_fallback); + settings_set_str("recode_fallback", old_recode_fallback != NULL ? old_recode_fallback : "ISO8859-1"); + } + recode_fallback = g_strdup(settings_get_str("recode_fallback")); + + term_charset = settings_get_str("term_charset"); + if (!is_valid_charset(term_charset)) { +#if defined (HAVE_NL_LANGINFO) && defined(CODESET) + settings_set_str("term_charset", is_valid_charset(old_term_charset) ? old_term_charset : nl_langinfo(CODESET)); +#else + settings_set_str("term_charset", is_valid_charset(old_term_charset) ? old_term_charset : "ISO8859-1"); +#endif + /* FIXME: move the check of term_charset into fe-text/term.c + it breaks the proper term_input_type + setup and reemitting of the signal is kludgy */ + if (g_strcasecmp(term_charset, old_term_charset) != 0); + signal_emit("setup changed", 0); + } + term_charset = g_strdup(settings_get_str("term_charset")); + + recode_out_default = settings_get_str("recode_out_default_charset"); + if (recode_out_default != NULL && *recode_out_default != '\0') + if( !is_valid_charset(recode_out_default)) { + signal_emit("error command", 2, GINT_TO_POINTER(CMDERR_INVALID_CHARSET), recode_out_default); + settings_set_str("recode_out_default_charset", old_recode_out_default); + } + recode_out_default = g_strdup(settings_get_str("recode_out_default_charset")); +} + +static void message_own_public(const SERVER_REC *server, const char *msg, + const char *target) +{ + char *recoded; + recoded = recode_in(msg, target); + signal_continue(3, server, recoded, target); + g_free(recoded); +} + +static void message_own_private(const SERVER_REC *server, const char *msg, + const char *target, const char *orig_target) +{ + char *recoded; + recoded = recode_in(msg, target); + signal_continue(4, server, recoded, target, orig_target); + g_free(recoded); +} + +static void message_irc_own_action(const SERVER_REC *server, const char *msg, + const char *nick, const char *addr, + const char *target) +{ + char *recoded; + recoded = recode_in(msg, target); + signal_continue(5, server, recoded, nick, addr, target); + g_free(recoded); +} + +static void message_irc_own_notice(const SERVER_REC *server, const char *msg, + const char *channel) +{ + char *recoded; + recoded = recode_in(msg, channel); + signal_continue(3, server, recoded, channel); + g_free(recoded); } #endif @@ -184,6 +232,11 @@ void fe_recode_init (void) command_bind("recode add", NULL, (SIGNAL_FUNC) fe_recode_add_cmd); command_bind("recode remove", NULL, (SIGNAL_FUNC) fe_recode_remove_cmd); signal_add("setup changed", (SIGNAL_FUNC) read_settings); + signal_add("message own_public", (SIGNAL_FUNC) message_own_public); + signal_add("message own_private", (SIGNAL_FUNC) message_own_private); + signal_add("message irc own_action", (SIGNAL_FUNC) message_irc_own_action); + signal_add("message irc own_notice", (SIGNAL_FUNC) message_irc_own_notice); + read_settings(); #endif } @@ -195,5 +248,10 @@ void fe_recode_deinit (void) command_unbind("recode add", (SIGNAL_FUNC) fe_recode_add_cmd); command_unbind("recode remove", (SIGNAL_FUNC) fe_recode_remove_cmd); signal_remove("setup changed", (SIGNAL_FUNC) read_settings); + signal_remove("message own_public", (SIGNAL_FUNC) message_own_public); + signal_remove("message own_private", (SIGNAL_FUNC) message_own_private); + signal_remove("message irc own_action", (SIGNAL_FUNC) message_irc_own_action); + signal_remove("message irc own_notice", (SIGNAL_FUNC) message_irc_own_notice); #endif } + diff --git a/src/fe-common/core/formats.c b/src/fe-common/core/formats.c index 2470ba26..3fcb8066 100644 --- a/src/fe-common/core/formats.c +++ b/src/fe-common/core/formats.c @@ -32,6 +32,9 @@ #include "formats.h" #include "themes.h" #include "translation.h" +#ifdef HAVE_GLIB2 +#include "utf8.h" +#endif static const char *format_backs = "04261537"; static const char *format_fores = "kbgcrmyw"; @@ -66,13 +69,13 @@ static void format_expand_code(const char **format, GString *out, int *flags) int set; if (flags == NULL) { - /* flags are being ignored - skip the code */ + /* flags are being ignored - skip the code */ while (**format != ']') (*format)++; - return; + return; } - set = TRUE; + set = TRUE; (*format)++; while (**format != ']' && **format != '\0') { if (**format == '+') @@ -94,7 +97,7 @@ static void format_expand_code(const char **format, GString *out, int *flags) (*format)++; } g_string_append_c(out, ','); - (*format)--; + (*format)--; break; case 's': case 'S': @@ -104,12 +107,12 @@ static void format_expand_code(const char **format, GString *out, int *flags) break; case 't': *flags |= set ? PRINT_FLAG_SET_TIMESTAMP : - PRINT_FLAG_UNSET_TIMESTAMP; - break; + PRINT_FLAG_UNSET_TIMESTAMP; + break; case 'T': *flags |= set ? PRINT_FLAG_SET_SERVERTAG : - PRINT_FLAG_UNSET_SERVERTAG; - break; + PRINT_FLAG_UNSET_SERVERTAG; + break; } (*format)++; @@ -120,12 +123,12 @@ int format_expand_styles(GString *out, const char **format, int *flags) { char *p, fmt; - fmt = **format; + fmt = **format; switch (fmt) { case '{': case '}': case '%': - /* escaped char */ + /* escaped char */ g_string_append_c(out, fmt); break; case 'U': @@ -165,7 +168,7 @@ int format_expand_styles(GString *out, const char **format, int *flags) g_string_append_c(out, FORMAT_STYLE_DEFAULTS); break; case '>': - /* clear to end of line */ + /* clear to end of line */ g_string_append_c(out, 4); g_string_append_c(out, FORMAT_STYLE_CLRTOEOL); break; @@ -175,7 +178,7 @@ int format_expand_styles(GString *out, const char **format, int *flags) break; case '[': /* code */ - format_expand_code(format, out, flags); + format_expand_code(format, out, flags); break; default: /* check if it's a background color */ @@ -219,10 +222,10 @@ void format_read_arglist(va_list va, FORMAT_REC *format, { int num, len, bufpos; - g_return_if_fail(format->params < arglist_size); + g_return_if_fail(format->params < arglist_size); bufpos = 0; - arglist[format->params] = NULL; + arglist[format->params] = NULL; for (num = 0; num < format->params; num++) { switch (format->paramtypes[num]) { case FORMAT_STRING: @@ -255,7 +258,7 @@ void format_read_arglist(va_list va, FORMAT_REC *format, arglist[num] = buffer+bufpos; len = g_snprintf(buffer+bufpos, buffer_size-bufpos, "%ld", l); - bufpos += len+1; + bufpos += len+1; break; } case FORMAT_FLOAT: { @@ -279,14 +282,14 @@ void format_create_dest(TEXT_DEST_REC *dest, void *server, const char *target, int level, WINDOW_REC *window) { - format_create_dest_tag(dest, server, NULL, target, level, window); + format_create_dest_tag(dest, server, NULL, target, level, window); } void format_create_dest_tag(TEXT_DEST_REC *dest, void *server, const char *server_tag, const char *target, int level, WINDOW_REC *window) { - memset(dest, 0, sizeof(TEXT_DEST_REC)); + memset(dest, 0, sizeof(TEXT_DEST_REC)); dest->server = server; dest->server_tag = server != NULL ? SERVER(server)->tag : server_tag; @@ -345,7 +348,7 @@ int format_get_length(const char *str) str++; if (*str != '%' && format_expand_styles(tmp, &str, NULL)) { - str++; + str++; continue; } @@ -356,13 +359,13 @@ int format_get_length(const char *str) #ifdef HAVE_GLIB2 len += advance(&str, utf8); #else - len++; + len++; str++; #endif } g_string_free(tmp, TRUE); - return len; + return len; } /* Return how many characters in `str' must be skipped before `len' @@ -389,27 +392,27 @@ int format_real_length(const char *str, int len) str++; if (*str != '%' && format_expand_styles(tmp, &str, NULL)) { - str++; + str++; continue; } /* %% or unknown %code, written as-is */ if (*str != '%') { if (--len == 0) - break; + break; } } #ifdef HAVE_GLIB2 len -= advance(&str, utf8); #else - len--; + len--; str++; #endif } g_string_free(tmp, TRUE); - return (int) (str-start); + return (int) (str-start); } char *format_string_expand(const char *text, int *flags) @@ -417,7 +420,7 @@ char *format_string_expand(const char *text, int *flags) GString *out; char code, *ret; - g_return_val_if_fail(text != NULL, NULL); + g_return_val_if_fail(text != NULL, NULL); out = g_string_new(NULL); @@ -478,7 +481,7 @@ static char *format_get_text_args(TEXT_DEST_REC *dest, if (ret != NULL) { /* string shouldn't end with \003 or it could mess up the next one or two characters */ - int diff; + int diff; int len = strlen(ret); while (len > 0 && ret[len-1] == 3) len--; diff = strlen(ret)-len; @@ -548,7 +551,7 @@ char *format_get_text_theme_charargs(THEME_REC *theme, const char *module, if (module_theme == NULL) return NULL; - text = module_theme->expanded_formats[formatnum]; + text = module_theme->expanded_formats[formatnum]; return format_get_text_args(dest, text, args); } @@ -594,7 +597,7 @@ char *format_add_linestart(const char *text, const char *linestart) ret = str->str; g_string_free(str, FALSE); - return ret; + return ret; } char *format_add_lineend(const char *text, const char *linestart) @@ -619,7 +622,7 @@ char *format_add_lineend(const char *text, const char *linestart) ret = str->str; g_string_free(str, FALSE); - return ret; + return ret; } #define LINE_START_IRSSI_LEVEL \ @@ -635,16 +638,16 @@ char *format_get_level_tag(THEME_REC *theme, TEXT_DEST_REC *dest) { int format; - /* check for flags if we want to override defaults */ + /* check for flags if we want to override defaults */ if (dest->flags & PRINT_FLAG_UNSET_LINE_START) return NULL; if (dest->flags & PRINT_FLAG_SET_LINE_START) format = TXT_LINE_START; - else if (dest->flags & PRINT_FLAG_SET_LINE_START_IRSSI) + else if (dest->flags & PRINT_FLAG_SET_LINE_START_IRSSI) format = TXT_LINE_START_IRSSI; else { - /* use defaults */ + /* use defaults */ if (dest->level & LINE_START_IRSSI_LEVEL) format = TXT_LINE_START_IRSSI; else if ((dest->level & NOT_LINE_START_LEVEL) == 0) @@ -658,20 +661,20 @@ char *format_get_level_tag(THEME_REC *theme, TEXT_DEST_REC *dest) static char *get_timestamp(THEME_REC *theme, TEXT_DEST_REC *dest, time_t t) { - char *format, str[256]; + char *format, str[256]; struct tm *tm; int diff; if ((timestamp_level & dest->level) == 0) return NULL; - /* check for flags if we want to override defaults */ + /* check for flags if we want to override defaults */ if (dest->flags & PRINT_FLAG_UNSET_TIMESTAMP) return NULL; if ((dest->flags & PRINT_FLAG_SET_TIMESTAMP) == 0 && (dest->level & (MSGLEVEL_NEVER|MSGLEVEL_LASTLOG)) != 0) - return NULL; + return NULL; if (timestamp_timeout > 0) { @@ -685,7 +688,7 @@ static char *get_timestamp(THEME_REC *theme, TEXT_DEST_REC *dest, time_t t) format = format_get_text_theme(theme, MODULE_NAME, dest, TXT_TIMESTAMP); if (strftime(str, sizeof(str), format, tm) <= 0) - str[0] = '\0'; + str[0] = '\0'; g_free(format); return g_strdup(str); } @@ -695,9 +698,9 @@ static char *get_server_tag(THEME_REC *theme, TEXT_DEST_REC *dest) int count = 0; if (dest->server_tag == NULL || hide_server_tags) - return NULL; + return NULL; - /* check for flags if we want to override defaults */ + /* check for flags if we want to override defaults */ if (dest->flags & PRINT_FLAG_UNSET_SERVERTAG) return NULL; @@ -718,7 +721,7 @@ static char *get_server_tag(THEME_REC *theme, TEXT_DEST_REC *dest) } if (count < 2) - return NULL; + return NULL; } return format_get_text_theme(theme, MODULE_NAME, dest, @@ -842,7 +845,7 @@ static void get_mirc_color(const char **str, int *fg_ret, int *bg_ret) /* foreground color */ if (**str != ',') { fg = **str-'0'; - (*str)++; + (*str)++; if (i_isdigit(**str)) { fg = fg*10 + (**str-'0'); (*str)++; @@ -879,7 +882,7 @@ int strip_real_length(const char *str, int len, { const char *start = str; - if (last_color_pos != NULL) + if (last_color_pos != NULL) *last_color_pos = -1; if (last_color_len != NULL) *last_color_len = -1; @@ -890,25 +893,25 @@ int strip_real_length(const char *str, int len, if (last_color_pos != NULL) *last_color_pos = (int) (str-start); - str++; + str++; get_mirc_color(&str, NULL, NULL); - if (last_color_len != NULL) + if (last_color_len != NULL) *last_color_len = (int) (str-mircstart); } else if (*str == 4 && str[1] != '\0') { if (str[1] < FORMAT_STYLE_SPECIAL && str[2] != '\0') { if (last_color_pos != NULL) *last_color_pos = (int) (str-start); - if (last_color_len != NULL) - *last_color_len = 3; + if (last_color_len != NULL) + *last_color_len = 3; str++; } else if (str[1] == FORMAT_STYLE_DEFAULTS) { if (last_color_pos != NULL) *last_color_pos = (int) (str-start); - if (last_color_len != NULL) - *last_color_len = 2; + if (last_color_len != NULL) + *last_color_len = 2; } - str += 2; + str += 2; } else { if (!IS_COLOR_CODE(*str)) { if (len-- == 0) @@ -923,61 +926,61 @@ int strip_real_length(const char *str, int len, char *strip_codes(const char *input) { - const char *p; - char *str, *out; - - out = str = g_strdup(input); - for (p = input; *p != '\0'; p++) { - if (*p == 3) { - p++; - - /* mirc color */ - get_mirc_color(&p, NULL, NULL); - p--; - continue; - } - - if (*p == 4 && p[1] != '\0') { - if (p[1] >= FORMAT_STYLE_SPECIAL) { - p++; - continue; - } - - /* irssi color */ - if (p[2] != '\0') { - p += 2; - continue; - } + const char *p; + char *str, *out; + + out = str = g_strdup(input); + for (p = input; *p != '\0'; p++) { + if (*p == 3) { + p++; + + /* mirc color */ + get_mirc_color(&p, NULL, NULL); + p--; + continue; + } + + if (*p == 4 && p[1] != '\0') { + if (p[1] >= FORMAT_STYLE_SPECIAL) { + p++; + continue; + } + + /* irssi color */ + if (p[2] != '\0') { + p += 2; + continue; + } } if (*p == 27 && p[1] != '\0') { - p++; + p++; p = get_ansi_color(current_theme, p, NULL, NULL, NULL); p--; } else if (!IS_COLOR_CODE(*p)) - *out++ = *p; - } + *out++ = *p; + } - *out = '\0'; - return str; + *out = '\0'; + return str; } /* send a fully parsed text string for GUI to print */ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text) { - THEME_REC *theme; + THEME_REC *theme; char *dup, *str, *ptr, type; int fgcolor, bgcolor; int flags; - theme = dest->window != NULL && dest->window->theme != NULL ? + theme = dest->window != NULL && dest->window->theme != NULL ? dest->window->theme : current_theme; dup = str = g_strdup(text); flags = 0; fgcolor = theme->default_color; bgcolor = -1; while (*str != '\0') { - type = '\0'; + type = '\0'; for (ptr = str; *ptr != '\0'; ptr++) { if (IS_COLOR_CODE(*ptr) || *ptr == '\n') { type = *ptr; @@ -991,14 +994,14 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text) if (type == 7) { /* bell */ if (settings_get_bool("bell_beeps")) - signal_emit("beep", 0); + signal_emit("beep", 0); } else if (type == 4 && *ptr == FORMAT_STYLE_CLRTOEOL) { - /* clear to end of line */ + /* clear to end of line */ flags |= GUI_PRINT_FLAG_CLRTOEOL; } if (*str != '\0' || (flags & GUI_PRINT_FLAG_CLRTOEOL)) { - /* send the text to gui handler */ + /* send the text to gui handler */ signal_emit_id(signal_gui_print_text, 6, dest->window, GINT_TO_POINTER(fgcolor), GINT_TO_POINTER(bgcolor), @@ -1055,7 +1058,7 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text) while (*ptr != ',' && *ptr != '\0') ptr++; if (*ptr != '\0') *ptr++ = '\0'; - ptr--; + ptr--; signal_emit_id(signal_gui_print_text, 6, dest->window, NULL, NULL, GINT_TO_POINTER(GUI_PRINT_FLAG_INDENT_FUNC), @@ -1063,12 +1066,12 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text) break; } case FORMAT_STYLE_DEFAULTS: - fgcolor = theme->default_color; + fgcolor = theme->default_color; bgcolor = -1; flags &= GUI_PRINT_FLAG_INDENT|GUI_PRINT_FLAG_MONOSPACE; break; case FORMAT_STYLE_CLRTOEOL: - break; + break; default: if (*ptr != FORMAT_COLOR_NOCHANGE) { fgcolor = (unsigned char) *ptr-'0'; @@ -1090,8 +1093,8 @@ void format_send_to_gui(TEXT_DEST_REC *dest, const char *text) flags &= ~GUI_PRINT_FLAG_BLINK; else { /* blink */ - bgcolor -= 8; - flags |= GUI_PRINT_FLAG_BLINK; + bgcolor -= 8; + flags |= GUI_PRINT_FLAG_BLINK; } } } diff --git a/src/fe-common/core/module-formats.c b/src/fe-common/core/module-formats.c index 2bd4c23d..6d13ed08 100644 --- a/src/fe-common/core/module-formats.c +++ b/src/fe-common/core/module-formats.c @@ -218,6 +218,7 @@ FORMAT_REC fecommon_core_formats[] = { { "invalid_time", "Invalid timestamp", 0 }, { "invalid_level", "Invalid message level", 0 }, { "invalid_size", "Invalid size", 0 }, + { "invalid_charset", "Invalid charset: $0", 1, { 0 } }, /* ---- */ { NULL, "Themes", 0 }, @@ -253,7 +254,6 @@ FORMAT_REC fecommon_core_formats[] = { { "conversion_added", "Added {hilight $0}/{hilight $1} to conversion database", 2, { FORMAT_STRING, FORMAT_STRING } }, { "conversion_removed", "Removed {hilight $0} from conversion database", 1, { FORMAT_STRING } }, { "conversion_not_found", "{hilight $0} not found in conversion database", 1, { FORMAT_STRING } }, - { "conversion_not_supported", "Conversion to the character set {hilight $0} is not supported",1, { FORMAT_STRING } }, { "recode_header", "%#Target Character set", 0 }, { "recode_line", "%#%|$[!30]0 $1", 2, { FORMAT_STRING, FORMAT_STRING } }, @@ -261,7 +261,7 @@ FORMAT_REC fecommon_core_formats[] = { { NULL, "Misc", 0 }, { "unknown_chat_protocol", "Unknown chat protocol: $0", 1, { 0 } }, - { "unknown_chatnet", "Unknown chat network: $0 (create it with /IRCNET ADD)", 1, { 0 } }, + { "unknown_chatnet", "Unknown chat network: $0 (create it with /NETWORK ADD)", 1, { 0 } }, { "not_toggle", "Value must be either ON, OFF or TOGGLE", 0 }, { "perl_error", "Perl error: $0", 1, { 0 } }, { "bind_header", "%#Key Action", 0 }, diff --git a/src/fe-common/core/module-formats.h b/src/fe-common/core/module-formats.h index 95465c33..ea9af5d2 100644 --- a/src/fe-common/core/module-formats.h +++ b/src/fe-common/core/module-formats.h @@ -187,6 +187,7 @@ enum { TXT_INVALID_TIME, TXT_INVALID_LEVEL, TXT_INVALID_SIZE, + TXT_INVALID_CHARSET, TXT_FILL_11, @@ -219,7 +220,6 @@ enum { TXT_CONVERSION_ADDED, TXT_CONVERSION_REMOVED, TXT_CONVERSION_NOT_FOUND, - TXT_CONVERSION_NOT_SUPPORTED, TXT_RECODE_HEADER, TXT_RECODE_LINE, diff --git a/src/fe-common/core/module.h b/src/fe-common/core/module.h index 203e3a30..51b61b3e 100644 --- a/src/fe-common/core/module.h +++ b/src/fe-common/core/module.h @@ -2,6 +2,7 @@ #define MODULE_NAME "fe-common/core" +typedef guint32 unichar; typedef struct { time_t time; char *nick; diff --git a/src/fe-common/core/printtext.c b/src/fe-common/core/printtext.c index e51da230..a3d34a22 100644 --- a/src/fe-common/core/printtext.c +++ b/src/fe-common/core/printtext.c @@ -23,7 +23,6 @@ #include "modules.h" #include "signals.h" #include "commands.h" -#include "recode.h" #include "settings.h" #include "levels.h" @@ -160,7 +159,7 @@ void printformat_module_gui(const char *module, int formatnum, ...) static void print_line(TEXT_DEST_REC *dest, const char *text) { THEME_REC *theme; - char *str, *recoded, *tmp, *stripped; + char *str, *tmp, *stripped; g_return_if_fail(dest != NULL); g_return_if_fail(text != NULL); @@ -171,15 +170,12 @@ static void print_line(TEXT_DEST_REC *dest, const char *text) format_add_lineend(text, tmp); g_free_not_null(tmp); - recoded = recode_in(str, dest->target); - /* send both the formatted + stripped (for logging etc.) */ - stripped = strip_codes(recoded); - signal_emit_id(signal_print_text, 3, dest, recoded, stripped); + stripped = strip_codes(str); + signal_emit_id(signal_print_text, 3, dest, str, stripped); g_free_and_null(dest->hilight_color); g_free(str); - g_free(recoded); g_free(stripped); } diff --git a/src/fe-common/core/utf8.c b/src/fe-common/core/utf8.c new file mode 100644 index 00000000..4049991d --- /dev/null +++ b/src/fe-common/core/utf8.c @@ -0,0 +1,251 @@ +/* utf8.c - Operations on UTF-8 strings. + * + * Copyright (C) 2002 Timo Sirainen + * + * Based on GLib code by + * + * Copyright (C) 1999 Tom Tromey + * Copyright (C) 2000 Red Hat, Inc. + * + * UTF-8 width tables based on locale data from GNU libc by + * + * Copyright (C) 1991-2002 Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "module.h" + +#define UTF8_COMPUTE(Char, Mask, Len) \ + if (Char < 128) \ + { \ + Len = 1; \ + Mask = 0x7f; \ + } \ + else if ((Char & 0xe0) == 0xc0) \ + { \ + Len = 2; \ + Mask = 0x1f; \ + } \ + else if ((Char & 0xf0) == 0xe0) \ + { \ + Len = 3; \ + Mask = 0x0f; \ + } \ + else if ((Char & 0xf8) == 0xf0) \ + { \ + Len = 4; \ + Mask = 0x07; \ + } \ + else if ((Char & 0xfc) == 0xf8) \ + { \ + Len = 5; \ + Mask = 0x03; \ + } \ + else if ((Char & 0xfe) == 0xfc) \ + { \ + Len = 6; \ + Mask = 0x01; \ + } \ + else \ + Len = -1; + +#define UTF8_GET(Result, Chars, Count, Mask, Len) \ + (Result) = (Chars)[0] & (Mask); \ + for ((Count) = 1; (Count) < (Len); ++(Count)) \ + { \ + if (((Chars)[(Count)] & 0xc0) != 0x80) \ + { \ + (Result) = -1; \ + break; \ + } \ + (Result) <<= 6; \ + (Result) |= ((Chars)[(Count)] & 0x3f); \ + } + +unichar get_utf8_char(const unsigned char **ptr, int len) +{ + int i, result, mask, chrlen; + + mask = 0; + UTF8_COMPUTE(**ptr, mask, chrlen); + if (chrlen == -1) + return (unichar) -2; + + if (chrlen > len) + return (unichar) -1; + + UTF8_GET(result, *ptr, i, mask, chrlen); + if (result == -1) + return (unichar) -2; + + *ptr += chrlen-1; + return result; +} + +int strlen_utf8(const char *str) +{ + const unsigned char *p = (const unsigned char *) str; + int len; + + len = 0; + while (*p != '\0' && get_utf8_char(&p, 6) > 0) { + len++; + p++; + } + return len; +} + +int utf16_char_to_utf8(unichar c, char *outbuf) +{ + int len, i, first; + + len = 0; + if (c < 0x80) { + first = 0; + len = 1; + } else if (c < 0x800) { + first = 0xc0; + len = 2; + } else if (c < 0x10000) { + first = 0xe0; + len = 3; + } else if (c < 0x200000) { + first = 0xf0; + len = 4; + } else if (c < 0x4000000) { + first = 0xf8; + len = 5; + } else { + first = 0xfc; + len = 6; + } + + if (outbuf) { + for (i = len - 1; i > 0; --i) { + outbuf[i] = (c & 0x3f) | 0x80; + c >>= 6; + } + outbuf[0] = c | first; + } + + return len; +} + +void utf8_to_utf16(const char *str, unichar *out) +{ + const unsigned char *p = (const unsigned char *) str; + int i, result, mask, len; + + while (*p != '\0') { + mask = 0; + UTF8_COMPUTE(*p, mask, len); + if (len == -1) + break; + + UTF8_GET(result, p, i, mask, len); + if (result == -1) + break; + + p += len; + *out++ = result; + } + + *out = '\0'; +} + +void utf16_to_utf8(const unichar *str, char *out) +{ + int len; + + while (*str != '\0') { + len = utf16_char_to_utf8(*str, out); + out += len; + + str++; + } + *out = '\0'; +} + +static const unichar wcc[] = { + 0x0, 0x300, 0x34F, 0x360, 0x363, 0x483, 0x487, 0x488, 0x48A, 0x591, + 0x5A2, 0x5A3, 0x5BA, 0x5BB, 0x5BE, 0x5BF, 0x5C0, 0x5C1, 0x5C3, 0x5C4, + 0x5C5, 0x64B, 0x656, 0x670, 0x671, 0x6D6, 0x6E5, 0x6E7, 0x6E9, 0x6EA, + 0x6EE, 0x70F, 0x710, 0x711, 0x712, 0x730, 0x74B, 0x7A6, 0x7B1, 0x901, + 0x903, 0x93C, 0x93D, 0x941, 0x949, 0x94D, 0x94E, 0x951, 0x955, 0x962, + 0x964, 0x981, 0x982, 0x9BC, 0x9BD, 0x9C1, 0x9C5, 0x9CD, 0x9CE, 0x9E2, + 0x9E4, 0xA02, 0xA03, 0xA3C, 0xA3D, 0xA41, 0xA43, 0xA47, 0xA49, 0xA4B, + 0xA4E, 0xA70, 0xA72, 0xA81, 0xA83, 0xABC, 0xABD, 0xAC1, 0xAC6, 0xAC7, + 0xAC9, 0xACD, 0xACE, 0xB01, 0xB02, 0xB3C, 0xB3D, 0xB3F, 0xB40, 0xB41, + 0xB44, 0xB4D, 0xB4E, 0xB56, 0xB57, 0xB82, 0xB83, 0xBC0, 0xBC1, 0xBCD, + 0xBCE, 0xC3E, 0xC41, 0xC46, 0xC49, 0xC4A, 0xC4E, 0xC55, 0xC57, 0xCBF, + 0xCC0, 0xCC6, 0xCC7, 0xCCC, 0xCCE, 0xD41, 0xD44, 0xD4D, 0xD4E, 0xDCA, + 0xDCB, 0xDD2, 0xDD5, 0xDD6, 0xDD7, 0xE31, 0xE32, 0xE34, 0xE3B, 0xE47, + 0xE4F, 0xEB1, 0xEB2, 0xEB4, 0xEBA, 0xEBB, 0xEBD, 0xEC8, 0xECE, 0xF18, + 0xF1A, 0xF35, 0xF36, 0xF37, 0xF38, 0xF39, 0xF3A, 0xF71, 0xF7F, 0xF80, + 0xF85, 0xF86, 0xF88, 0xF90, 0xF98, 0xF99, 0xFBD, 0xFC6, 0xFC7, 0x102D, + 0x1031, 0x1032, 0x1033, 0x1036, 0x1038, 0x1039, 0x103A, 0x1058, 0x105A, + 0x1100, 0x1160, 0x17B7, 0x17BE, 0x17C6, 0x17C7, 0x17C9, 0x17D4, 0x180B, + 0x180F, 0x18A9, 0x18AA, 0x200B, 0x2010, 0x202A, 0x202F, 0x206A, 0x2070, + 0x20D0, 0x20E4, 0x2E80, 0x3008, 0x300C, 0x3014, 0x3016, 0x3018, 0x301C, + 0x302A, 0x3030, 0x303F, 0x3041, 0x3095, 0x3099, 0x309B, 0xA4C7, 0xAC00, + 0xD7A4, 0xF8F0, 0xF900, 0xFA2E, 0xFB1E, 0xFB1F, 0xFE20, 0xFE24, 0xFE30, + 0xFE6C, 0xFEFF, 0xFF00, 0xFF01, 0xFF5F, 0xFFE0, 0xFFE7, 0xFFF9, 0xFFFC, +#if 1 + 0x1D167, 0x1D16A, 0x1D173, 0x1D183, 0x1D185, 0x1D18C, 0x1D1AA, 0x1D1AE, + 0x20000, 0x2A6D7, 0x2F800, 0x2FA1E, 0xE0001, 0xE0002, 0xE0020, 0xE0080 +#endif +}; + +static const int wccnum = sizeof(wcc) / sizeof(wcc[0]) - 1; + +static const char wws[] = { + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, + 1, 2, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, + 1, 2, 1, 2, 0, 2, 1, 2, 1, 0, 2, 1, 2, 1, 0, 2, 1, 0, 1, 0, 1, 2, 1, 0, + 1, 2, 1, 2, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 2, 1, 2, 1, 0, 1, 0, 1, -1 +}; + +int utf8_width(unichar c) +{ + int p, q, r; + unichar d; + + if (c < wcc[1]) + return 1; + + p = 0; + q = wccnum; + + while (p < q - 1) { + r = (p + q)/2; + d = wcc[r]; + if (d < c) + p = r; + else if (d > c) + q = r; + else + return wws[r]; + } + + return wws[p]; +} diff --git a/src/fe-common/core/utf8.h b/src/fe-common/core/utf8.h new file mode 100644 index 00000000..456c6bf8 --- /dev/null +++ b/src/fe-common/core/utf8.h @@ -0,0 +1,31 @@ +#ifndef __UTF8_H +#define __UTF8_H + +/* Returns -2 = invalid, -1 = need more data, otherwise unichar. */ +unichar get_utf8_char(const unsigned char **ptr, int len); + +/* Returns length of UTF8 string */ +int strlen_utf8(const char *str); + +/* UTF-8 -> unichar string. The NUL is copied as well. */ +void utf8_to_utf16(const char *str, unichar *out); + +/* unichar -> UTF-8 string. outbuf must be at least 6 chars long. + Returns outbuf string length. */ +int utf16_char_to_utf8(unichar c, char *outbuf); + +/* unichar -> UTF-8 string. The NUL is copied as well. + Make sure out is at least 6 x length of str. */ +void utf16_to_utf8(const unichar *str, char *out); + +/* XXX I didn't check the encoding range of big5+. This is standard big5. */ +#define is_big5_los(lo) (0x40 <= (lo) && (lo) <= 0x7E) /* standard */ +#define is_big5_lox(lo) (0x80 <= (lo) && (lo) <= 0xFE) /* extended */ +#define is_big5_lo(lo) ((is_big5_los(lo) || is_big5_lox(lo))) +#define is_big5_hi(hi) (0x81 <= (hi) && (hi) <= 0xFE) +#define is_big5(hi,lo) (is_big5_hi(hi) && is_big5_lo(lo)) + +/* Returns width for character (0-2). */ +int utf8_width(unichar c); + +#endif diff --git a/src/fe-common/irc/fe-events-numeric.c b/src/fe-common/irc/fe-events-numeric.c index 6dcf8eee..f67cd844 100644 --- a/src/fe-common/irc/fe-events-numeric.c +++ b/src/fe-common/irc/fe-events-numeric.c @@ -24,6 +24,7 @@ #include "misc.h" #include "settings.h" #include "levels.h" +#include "recode.h" #include "irc-servers.h" #include "irc-channels.h" @@ -228,15 +229,17 @@ static void event_nick_in_use(IRC_SERVER_REC *server, const char *data) static void event_topic_get(IRC_SERVER_REC *server, const char *data) { const char *channel; - char *params, *topic; + char *params, *topic, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 3, NULL, &channel, &topic); + recoded = recode_in(topic, channel); channel = get_visible_target(server, channel); printformat(server, channel, MSGLEVEL_CRAP, - IRCTXT_TOPIC, channel, topic); + IRCTXT_TOPIC, channel, recoded); g_free(params); + g_free(recoded); } static void event_topic_info(IRC_SERVER_REC *server, const char *data) diff --git a/src/fe-common/irc/fe-events.c b/src/fe-common/irc/fe-events.c index 90be755e..6e157caa 100644 --- a/src/fe-common/irc/fe-events.c +++ b/src/fe-common/irc/fe-events.c @@ -30,6 +30,7 @@ #include "servers-reconnect.h" #include "queries.h" #include "ignore.h" +#include "recode.h" #include "irc-servers.h" #include "irc-channels.h" @@ -44,57 +45,63 @@ static void event_privmsg(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr) { - char *params, *target, *msg; + char *params, *target, *msg, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); if (nick == NULL) nick = server->real_address; if (addr == NULL) addr = ""; - + recoded = recode_in(msg, target); if (*target == '@' && ischannel(target[1])) { /* Hybrid 6 feature, send msg to all ops in channel */ signal_emit("message irc op_public", 5, - server, msg, nick, addr, + server, recoded, nick, addr, get_visible_target(server, target+1)); } else { signal_emit(ischannel(*target) ? "message public" : "message private", 5, - server, msg, nick, addr, + server, recoded, nick, addr, get_visible_target(server, target)); } g_free(params); + g_free(recoded); } static void ctcp_action(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr, const char *target) { - g_return_if_fail(data != NULL); + char *recoded; + g_return_if_fail(data != NULL); + recoded = recode_in(data, target); signal_emit("message irc action", 5, - server, data, nick, addr, + server, recoded, nick, addr, get_visible_target(server, target)); + g_free(recoded); } static void event_notice(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr) { - char *params, *target, *msg; + char *params, *target, *msg, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &target, &msg); + recoded = recode_in(msg, target); if (nick == NULL) { nick = server->real_address == NULL ? server->connrec->address : server->real_address; } - signal_emit("message irc notice", 5, server, msg, nick, addr, + signal_emit("message irc notice", 5, server, recoded, nick, addr, get_visible_target(server, target)); g_free(params); + g_free(recoded); } static void event_join(IRC_SERVER_REC *server, const char *data, @@ -116,15 +123,17 @@ static void event_join(IRC_SERVER_REC *server, const char *data, static void event_part(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr) { - char *params, *channel, *reason; + char *params, *channel, *reason, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &reason); + recoded = recode_in(reason, channel); signal_emit("message part", 5, server, - get_visible_target(server, channel), nick, addr, reason); + get_visible_target(server, channel), nick, addr, recoded); g_free(params); + g_free(recoded); } static void event_quit(IRC_SERVER_REC *server, const char *data, @@ -139,16 +148,18 @@ static void event_quit(IRC_SERVER_REC *server, const char *data, static void event_kick(IRC_SERVER_REC *server, const char *data, const char *kicker, const char *addr) { - char *params, *channel, *nick, *reason; + char *params, *channel, *nick, *reason, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 3 | PARAM_FLAG_GETREST, &channel, &nick, &reason); + recoded = recode_in(reason, channel); signal_emit("message kick", 6, server, get_visible_target(server, channel), - nick, kicker, addr, reason); + nick, kicker, addr, recoded); g_free(params); + g_free(recoded); } static void event_kill(IRC_SERVER_REC *server, const char *data, @@ -244,15 +255,17 @@ static void event_invite(IRC_SERVER_REC *server, const char *data, static void event_topic(IRC_SERVER_REC *server, const char *data, const char *nick, const char *addr) { - char *params, *channel, *topic; + char *params, *channel, *topic, *recoded; g_return_if_fail(data != NULL); params = event_get_params(data, 2 | PARAM_FLAG_GETREST, &channel, &topic); + recoded = recode_in(topic, channel); signal_emit("message topic", 5, server, - get_visible_target(server, channel), topic, nick, addr); + get_visible_target(server, channel), recoded, nick, addr); g_free(params); + g_free(recoded); } static void event_error(IRC_SERVER_REC *server, const char *data) |