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
This commit is contained in:
Valentin Batz 2004-09-15 12:11:43 +00:00 committed by senneth
commit 8ea717b676
26 changed files with 662 additions and 202 deletions

View file

@ -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 \

View file

@ -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);

View file

@ -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;

View file

@ -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);
}

View file

@ -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;
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);
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", "");
}
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
}

View file

@ -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;
const char *p;
char *str, *out;
out = str = g_strdup(input);
for (p = input; *p != '\0'; p++) {
if (*p == 3) {
p++;
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;
}
/* mirc color */
get_mirc_color(&p, NULL, NULL);
p--;
continue;
}
if (*p == 4 && p[1] != '\0') {
if (p[1] >= FORMAT_STYLE_SPECIAL) {
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;
}
/* 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;
}
}
}

View file

@ -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 },

View file

@ -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,

View file

@ -2,6 +2,7 @@
#define MODULE_NAME "fe-common/core"
typedef guint32 unichar;
typedef struct {
time_t time;
char *nick;

View file

@ -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);
}

251
src/fe-common/core/utf8.c Normal file
View file

@ -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];
}

31
src/fe-common/core/utf8.h Normal file
View file

@ -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