summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO1
-rw-r--r--configure.in2
-rw-r--r--docs/help/in/network.in5
-rw-r--r--docs/help/in/recode.in34
-rw-r--r--docs/special_vars.txt2
-rw-r--r--src/core/commands.h3
-rw-r--r--src/core/recode.c88
-rw-r--r--src/core/recode.h1
-rw-r--r--src/core/settings.c35
-rw-r--r--src/fe-common/core/Makefile.am2
-rw-r--r--src/fe-common/core/fe-common-core.c10
-rw-r--r--src/fe-common/core/fe-core-commands.c3
-rw-r--r--src/fe-common/core/fe-messages.c16
-rw-r--r--src/fe-common/core/fe-recode.c122
-rw-r--r--src/fe-common/core/formats.c181
-rw-r--r--src/fe-common/core/module-formats.c4
-rw-r--r--src/fe-common/core/module-formats.h2
-rw-r--r--src/fe-common/core/module.h1
-rw-r--r--src/fe-common/core/printtext.c10
-rw-r--r--src/fe-common/core/utf8.c251
-rw-r--r--src/fe-common/core/utf8.h31
-rw-r--r--src/fe-common/irc/fe-events-numeric.c7
-rw-r--r--src/fe-common/irc/fe-events.c41
-rw-r--r--src/fe-text/Makefile.am2
-rw-r--r--src/fe-text/statusbar.c9
-rw-r--r--src/fe-text/term.c1
26 files changed, 662 insertions, 202 deletions
diff --git a/TODO b/TODO
index 3307b9b2..6654d7e0 100644
--- a/TODO
+++ b/TODO
@@ -46,7 +46,6 @@
20:47 <@Juerd> cras: for some reason irssi doesn't know this happens in a
query, and displays "< Juerd:> foo" in the status window
- set TOS field for all connections (DCC especially)
- - /PROXY CTCP ON doesn't work well with multiple servers
22:51 [IRCNet] [zhafte] irssi muuten taitaa bugaa jos
pistää ACT oikeaan reunaan, vai onkohan se vain mun terminaali?
22:52 [IRCNet] [zhafte] menevät välillä päällekkäin
diff --git a/configure.in b/configure.in
index 122ff9d9..e6c8ecc9 100644
--- a/configure.in
+++ b/configure.in
@@ -7,7 +7,7 @@ if test -n "`grep '^#undef VERSION' config.h.in`"; then
fi
AM_CONFIG_HEADER(config.h)
-AM_INIT_AUTOMAKE(irssi, 0.8.10-rc4)
+AM_INIT_AUTOMAKE(irssi, 0.8.10-rc5)
AM_MAINTAINER_MODE
diff --git a/docs/help/in/network.in b/docs/help/in/network.in
index dce4abf2..abeadb32 100644
--- a/docs/help/in/network.in
+++ b/docs/help/in/network.in
@@ -5,11 +5,12 @@
-msgs: Maximum number of nicks in one /MSG command
-modes: Maximum number of mode changes in one /MODE command
-whois: Maximum number of nicks in one /WHOIS command
- -cmdspeed: Same as /SET cmd_queue_speed, see section 3.1
+ -cmdspeed: Same as /SET cmd_queue_speed, see section 3.1
-cmdmax: Same as /SET cmd_max_at_once, see section 3.1
-nick, -user, -realname: Specify what nick/user/name to use
-host: Specify what host name to use, if you have multiple
- -autosendcmd: Command to send after connecting to a server
+ -usermode: Specify what usermode to use on this network
+ -autosendcmd: Command to send after connecting to a server
With -autosendcmd argument you can automatically run any commands
after connecting to network. This is useful for automatically
diff --git a/docs/help/in/recode.in b/docs/help/in/recode.in
index 4f9781df..2b452d82 100644
--- a/docs/help/in/recode.in
+++ b/docs/help/in/recode.in
@@ -12,3 +12,37 @@ RECODE REMOVE %|[<target>]
%|Remove an entry from the conversion database (if target is
omitted, the current channel or query will be used)
+To specify your local charset you have to set term_charset
+
+Example:
+
+/SET term_charset <charset>
+
+To see the recode settings: /SET recode
+
+You can change them with /SET
+
+Examples:
+
+/SET recode_fallback <charset>
+to set the fallback charset for incoming events
+
+This charset will be used if a conversion with
+the defined charset(/recode add) fails, and if no
+charset for the target(query or channel) is defined at all.
+
+/SET recode_out_default_charset <charset>
+to set the global outgoing charset
+
+When it's set to a charset it will be used instead
+of the charset you have defined with /recode add
+
+/SET recode_transliterate ON
+to enable the global transliteration.
+
+The transliteration is based on your locale settings,
+if it doesn't work properly your locale settings may be wrong.
+You can enable it per target by adding //TRANSLIT to the <charset>
+
+Hint: <charset> can be almost everything listed by 'iconv -l'
+
diff --git a/docs/special_vars.txt b/docs/special_vars.txt
index 2008931f..f19b2bb2 100644
--- a/docs/special_vars.txt
+++ b/docs/special_vars.txt
@@ -80,7 +80,7 @@ $A .. $Z is important.
$Z time of day (hh:mm, can be changed with /SET timestamp_format)
$$ a literal '$'
- $versiontim prints time of the irssi version in HHMM format
+ $versiontime prints time of the irssi version in HHMM format
$sysname system name (eg. Linux)
$sysrelease system release (eg. 2.2.18)
$sysarch system architecture (eg. i686)
diff --git a/src/core/commands.h b/src/core/commands.h
index bdc8755d..b4f4ea0e 100644
--- a/src/core/commands.h
+++ b/src/core/commands.h
@@ -38,7 +38,8 @@ enum {
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_INVALID_TIME /* invalid time specification */
+ CMDERR_INVALID_TIME, /* invalid time specification */
+ CMDERR_INVALID_CHARSET /* invalid charset specification */
};
/* Return the full command for `alias' */
diff --git a/src/core/recode.c b/src/core/recode.c
index aa9f8315..8237e056 100644
--- a/src/core/recode.c
+++ b/src/core/recode.c
@@ -20,7 +20,10 @@
#include "module.h"
#include "settings.h"
+#include "servers.h"
+#include "signals.h"
#include "lib-config/iconfig.h"
+#include "misc.h"
#ifdef HAVE_GLIB2
static gboolean recode_get_charset(const char **charset)
@@ -29,39 +32,65 @@ static gboolean recode_get_charset(const char **charset)
if (**charset)
/* we use the same test as in src/fe-text/term.c:123 */
return !g_strcasecmp(*charset, "utf-8");
-
+
return g_get_charset(charset);
}
#endif
+gboolean is_valid_charset(const char *charset)
+{
+#ifdef HAVE_GLIB2
+ const char *from="UTF-8";
+ const char *str="irssi";
+ char *recoded;
+ gboolean valid;
+
+ if (!charset || *charset == '\0')
+ return FALSE;
+ recoded = g_convert(str, strlen(str), charset, from, NULL, NULL, NULL);
+ valid = (recoded != NULL);
+ g_free(recoded);
+ return valid;
+#else
+ if (!charset || *charset =='\0')
+ return FALSE;
+ return TRUE;
+#endif
+}
+
+static gboolean is_translit(const char *charset)
+{
+ char *pos;
+ pos = stristr(charset, "//translit");
+ return (pos != NULL);
+}
+
char *recode_in(const char *str, const char *target)
{
#ifdef HAVE_GLIB2
const char *from = NULL;
const char *to = NULL;
+ char *translit_to = NULL;
char *recoded = NULL;
- gboolean term_is_utf8;
- gboolean str_is_utf8;
- gboolean translit;
+ gboolean term_is_utf8, str_is_utf8, translit;
int len;
-
+
if (!str)
return g_strdup(str);
-
+
len = strlen(str);
str_is_utf8 = g_utf8_validate(str, len, NULL);
-
translit = settings_get_bool("recode_transliterate");
-
- if (target != NULL)
+
+ if (target != NULL && from == NULL)
from = iconfig_get_str("conversions", target, NULL);
term_is_utf8 = recode_get_charset(&to);
-
- if (translit)
- to = g_strdup_printf("%s//TRANSLIT", to);
-
+
+ if (translit && !is_translit(to))
+ to = translit_to = g_strconcat(to, "//TRANSLIT", NULL);
+
if (from)
recoded = g_convert(str, len, to, from, NULL, NULL, NULL);
@@ -69,10 +98,10 @@ char *recode_in(const char *str, const char *target)
if (term_is_utf8) {
if (!str_is_utf8)
from = settings_get_str("recode_fallback");
-
+
} else if (str_is_utf8)
from = "UTF-8";
-
+
if (from)
recoded = g_convert(str, len, to, from, NULL, NULL, NULL);
@@ -93,31 +122,34 @@ char *recode_out(const char *str, const char *target)
gboolean translit;
gboolean term_is_utf8;
int len;
-
+
if (!str)
return g_strdup(str);
-
+
len = strlen(str);
-
+
translit = settings_get_bool("recode_transliterate");
+
if (target) {
const char *to = NULL;
+ char *translit_to = NULL;
+
+ /* default outgoing charset if set */
+ to = settings_get_str("recode_out_default_charset");
+ if (to == NULL || *to == '\0')
+ to = iconfig_get_str("conversions", target, NULL);
+ if (to && *to != '\0') {
+ if (translit && !is_translit(to))
+ to = translit_to = g_strconcat(to ,"//TRANSLIT", NULL);
- to = iconfig_get_str("conversions", target, NULL);
- if (!to)
- /* default outgoing charset if no conversion is set */
- to = settings_get_str("recode_out_default_charset");
- if (to) {
- if (translit)
- to = g_strdup_printf("%s//TRANSLIT", to);
-
term_is_utf8 = recode_get_charset(&from);
recoded = g_convert(str, len, to, from, NULL, NULL, NULL);
}
+ g_free(translit_to);
}
if (!recoded)
recoded = g_strdup(str);
-
+
return recoded;
#else
return g_strdup(str);
@@ -128,7 +160,7 @@ void recode_init(void)
{
settings_add_str("misc", "recode_fallback", "ISO8859-1");
settings_add_str("misc", "recode_out_default_charset", "");
- settings_add_bool("misc", "recode_transliterate", TRUE);
+ settings_add_bool("misc", "recode_transliterate", FALSE);
}
void recode_deinit(void)
diff --git a/src/core/recode.h b/src/core/recode.h
index 47a11f09..2a50da9e 100644
--- a/src/core/recode.h
+++ b/src/core/recode.h
@@ -3,6 +3,7 @@
char *recode_in (const char *str, const char *target);
char *recode_out (const char *str, const char *target);
+gboolean is_valid_charset(const char *charset);
void recode_init (void);
void recode_deinit (void);
diff --git a/src/core/settings.c b/src/core/settings.c
index ba37ddb1..ce230f8a 100644
--- a/src/core/settings.c
+++ b/src/core/settings.c
@@ -25,6 +25,7 @@
#include "misc.h"
#include "lib-config/iconfig.h"
+#include "recode.h"
#include "settings.h"
#include "default-config.h"
@@ -393,8 +394,8 @@ static void sig_init_finished(void)
if (config_changed) {
/* some backwards compatibility changes were made to
config file, reload it */
- g_warning("Some time and size related settings were "
- "automatically changed to new format, please /SAVE");
+ g_warning("Some settings were automatically "
+ "updated, please /SAVE");
signal_emit("setup changed", 0);
}
}
@@ -439,15 +440,41 @@ void settings_clean_invalid(void)
static int backwards_compatibility(const char *module, CONFIG_NODE *node,
CONFIG_NODE *parent)
{
- const char *new_key;
+ const char *new_key, *new_module;
+ CONFIG_NODE *new_node;
char *new_value;
int old_value;
+ new_value = NULL; new_key = NULL; new_module = NULL;
+
+ /* fe-text term_type -> fe-common/core term_charset - for 0.8.10-> */
+ if (strcmp(module, "fe-text") == 0) {
+ if (strcasecmp(node->key, "term_type") == 0 ||
+ /* kludge for cvs-version where term_charset was in fe-text */
+ strcasecmp(node->key, "term_charset") == 0) {
+ new_module = "fe-common/core";
+ new_key = "term_charset";
+ new_value = !is_valid_charset(node->value) ? NULL :
+ g_strdup(node->value);
+ new_node = iconfig_node_traverse("settings", FALSE);
+ new_node = new_node == NULL ? NULL :
+ config_node_section(new_node, new_module, -1);
+
+ config_node_set_str(mainconfig, new_node,
+ new_key, new_value);
+ /* remove old */
+ config_node_set_str(mainconfig, parent,
+ node->key, NULL);
+ g_free(new_value);
+ config_changed = TRUE;
+ return new_key != NULL;
+ }
+ }
+ new_value = NULL, new_key = NULL;
/* FIXME: remove later - for 0.8.6 -> */
if (node->value == NULL || !is_numeric(node->value, '\0'))
return FALSE;
- new_value = NULL; new_key = NULL;
old_value = atoi(node->value);
if (strcmp(module, "fe-text") == 0) {
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)
diff --git a/src/fe-text/Makefile.am b/src/fe-text/Makefile.am
index 68bf7169..39d7a3a3 100644
--- a/src/fe-text/Makefile.am
+++ b/src/fe-text/Makefile.am
@@ -64,7 +64,6 @@ irssi_SOURCES = \
textbuffer-commands.c \
textbuffer-reformat.c \
textbuffer-view.c \
- utf8.c \
irssi.c \
module-formats.c
@@ -81,7 +80,6 @@ noinst_HEADERS = \
textbuffer.h \
textbuffer-view.h \
textbuffer-reformat.h \
- utf8.h \
module.h \
module-formats.h
diff --git a/src/fe-text/statusbar.c b/src/fe-text/statusbar.c
index 0de19e00..5eba9557 100644
--- a/src/fe-text/statusbar.c
+++ b/src/fe-text/statusbar.c
@@ -21,7 +21,6 @@
#include "module.h"
#include "signals.h"
#include "expandos.h"
-#include "recode.h"
#include "special-vars.h"
#include "themes.h"
@@ -687,8 +686,6 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
SERVER_REC *server;
WI_ITEM_REC *wiitem;
char *tmpstr, *tmpstr2;
- const char *target;
- char *recoded;
int len;
if (str == NULL)
@@ -727,11 +724,7 @@ void statusbar_item_default_handler(SBAR_ITEM_REC *item, int get_size_only,
tmpstr2 = reverse_controls(tmpstr);
g_free(tmpstr);
- target = wiitem ? window_item_get_target(wiitem) : NULL;
- recoded = recode_in(tmpstr2, target);
- g_free(tmpstr2);
-
- tmpstr = recoded;
+ tmpstr = tmpstr2;
if (get_size_only) {
item->min_size = item->max_size = format_get_length(tmpstr);
} else {
diff --git a/src/fe-text/term.c b/src/fe-text/term.c
index 5e62ce5d..59c3fe4d 100644
--- a/src/fe-text/term.c
+++ b/src/fe-text/term.c
@@ -152,7 +152,6 @@ void term_common_init(void)
settings_add_bool("lookandfeel", "term_force_colors", FALSE);
settings_add_bool("lookandfeel", "term_auto_detach", FALSE);
settings_add_bool("lookandfeel", "mirc_blink_fix", FALSE);
- settings_add_str("lookandfeel", "term_charset", "ISO8859-1");
force_colors = FALSE;
term_use_colors = term_has_colors() && settings_get_bool("colors");