diff --git a/src/common/server.c b/src/common/server.c index cdd67cda..53e877e3 100644 --- a/src/common/server.c +++ b/src/common/server.c @@ -310,6 +310,11 @@ server_inline (server *serv, char *line, int len) { char *utf_line_allocated = NULL; +#ifdef WIN32 + char *cleaned_line; + int cleaned_len; +#endif + /* Checks whether we're set to use UTF-8 charset */ if (serv->using_irc || /* 1. using CP1252/UTF-8 Hybrid */ (serv->encoding == NULL && prefs.utf8_locale) || /* OR 2. using system default->UTF-8 */ @@ -396,12 +401,24 @@ server_inline (server *serv, char *line, int len) } } +#ifdef WIN32 + cleaned_line = text_replace_non_bmp (line, len, &cleaned_len); + if (cleaned_line != NULL ) { + line = cleaned_line; + len = cleaned_len; + } +#endif + fe_add_rawlog (serv, line, len, FALSE); url_check_line (line, len); /* let proto-irc.c handle it */ serv->p_inline (serv, line, len); +#ifdef WIN32 + g_free (cleaned_line); +#endif + if (utf_line_allocated != NULL) /* only if a special copy was allocated */ g_free (utf_line_allocated); } diff --git a/src/common/text.c b/src/common/text.c index 9aa1bc85..93392d1a 100644 --- a/src/common/text.c +++ b/src/common/text.c @@ -275,7 +275,10 @@ scrollback_load (session *sess) time_t stamp; int lines; -#ifndef WIN32 +#ifdef WIN32 + char *cleaned_text; + int cleaned_len; +#else char *map, *end_map; struct stat statbuf; const char *begin, *eol; @@ -371,6 +374,12 @@ scrollback_load (session *sess) if (text) { text = strip_color (text + 1, -1, STRIP_COLOR); + cleaned_text = text_replace_non_bmp (text, -1, &cleaned_len); + if (cleaned_text != NULL) + { + g_free (text); + text = cleaned_text; + } fe_print_text (sess, text, stamp); g_free (text); } @@ -852,6 +861,46 @@ iso_8859_1_to_utf8 (unsigned char *text, int len, gsize *bytes_written) return res; } +#ifdef WIN32 +/* replace characters outside of the Basic Multilingual Plane with + * replacement characters (0xFFFD) */ +char * +text_replace_non_bmp (char *utf8_input, int input_length, glong *output_length) +{ + gunichar *ucs4_text; + gunichar suspect; + gchar *utf8_text; + glong ucs4_length; + glong index; + + ucs4_text = g_utf8_to_ucs4_fast (utf8_input, input_length, &ucs4_length); + + /* replace anything not in the Basic Multilingual Plane + * (code points above 0xFFFF) with the replacement + * character */ + for (index = 0; index < ucs4_length; index++) + { + suspect = ucs4_text[index]; + if ((suspect >= 0x1D173 && suspect <= 0x1D17A) + || (suspect >= 0xE0001 && suspect <= 0xE007F)) + { + ucs4_text[index] = 0xFFFD; /* replacement character */ + } + } + + utf8_text = g_ucs4_to_utf8 ( + ucs4_text, + ucs4_length, + NULL, + output_length, + NULL + ); + g_free (ucs4_text); + + return utf8_text; +} +#endif + char * text_validate (char **text, int *len) { diff --git a/src/common/text.h b/src/common/text.h index 150821ae..6d5ac03e 100644 --- a/src/common/text.h +++ b/src/common/text.h @@ -28,6 +28,9 @@ int pevent_load (char *filename); void pevent_make_pntevts (void); void text_emit (int index, session *sess, char *a, char *b, char *c, char *d); int text_emit_by_name (char *name, session *sess, char *a, char *b, char *c, char *d); +#ifdef WIN32 +char *text_replace_non_bmp (char *utf8_input, int input_length, glong *output_length); +#endif char *text_validate (char **text, int *len); int get_stamp_str (char *fmt, time_t tim, char **ret); void format_event (session *sess, int index, char **args, char *o, int sizeofo, unsigned int stripcolor_args);