2005-04-20 [paul] 1.9.6cvs43
[claws.git] / src / codeconv.c
index d36bf87627739f0de0b99ea2dd1998856641ba34..71f8804b8c70fd077d2bc5f7dfaeacc50f12763b 100644 (file)
@@ -21,6 +21,8 @@
 #  include "config.h"
 #endif
 
+#include "defs.h"
+
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <string.h>
@@ -655,7 +657,7 @@ static void conv_unreadable_latin(gchar *str)
                /* convert CR+LF -> LF */
                if (*p == '\r' && *(p + 1) == '\n')
                        memmove(p, p + 1, strlen(p));
-               else if ((*p & 0xff) >= 0x7f)
+               else if ((*p & 0xff) >= 0x7f && (*p & 0xff) <= 0x9f)
                        *p = SUBST_CHAR;
                p++;
        }
@@ -795,6 +797,8 @@ void conv_utf8todisp(gchar *outbuf, gint outlen, const gchar *inbuf)
 static void conv_anytodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
 {
        conv_anytoutf8(outbuf, outlen, inbuf);
+       if (g_utf8_validate(outbuf, -1, NULL) != TRUE)
+               conv_unreadable_8bit(outbuf);
 }
 
 static void conv_ustodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
@@ -813,7 +817,7 @@ void conv_localetodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
                strncpy2(outbuf, tmpstr, outlen);
                g_free(tmpstr);
        } else
-               strncpy2(outbuf, inbuf, outlen);
+               conv_utf8todisp(outbuf, outlen, inbuf);
 }
 
 static void conv_noconv(gchar *outbuf, gint outlen, const gchar *inbuf)
@@ -821,10 +825,24 @@ static void conv_noconv(gchar *outbuf, gint outlen, const gchar *inbuf)
        strncpy2(outbuf, inbuf, outlen);
 }
 
+static const gchar *
+conv_get_fallback_for_private_encoding(const gchar *encoding)
+{
+       if (encoding && (encoding[0] == 'X' || encoding[0] == 'x') &&
+           encoding[1] == '-') {
+               if (!g_ascii_strcasecmp(encoding, CS_X_GBK))
+                       return CS_GBK;
+       }
+
+       return encoding;
+}
+
 CodeConverter *conv_code_converter_new(const gchar *src_charset)
 {
        CodeConverter *conv;
 
+       src_charset = conv_get_fallback_for_private_encoding(src_charset);
+
        conv = g_new0(CodeConverter, 1);
        conv->code_conv_func = conv_get_code_conv_func(src_charset, NULL);
        conv->charset_str = g_strdup(src_charset);
@@ -866,6 +884,7 @@ gchar *conv_codeset_strdup(const gchar *inbuf,
        size_t len;
        CodeConvFunc conv_func;
 
+       src_code = conv_get_fallback_for_private_encoding(src_code);
        conv_func = conv_get_code_conv_func(src_code, dest_code);
        if (conv_func != conv_noconv) {
                len = (strlen(inbuf) + 1) * 3;
@@ -1148,7 +1167,7 @@ static const struct {
        {"ko_KR.EUC-KR" , C_EUC_KR      , C_EUC_KR},
        {"ko_KR"        , C_EUC_KR      , C_EUC_KR},
        {"zh_CN.GB2312" , C_GB2312      , C_GB2312},
-       {"zh_CN.GBK"    , C_GBK         , C_GB2312},
+       {"zh_CN.GBK"    , C_GBK         , C_GBK},
        {"zh_CN"        , C_GB2312      , C_GB2312},
        {"zh_HK"        , C_BIG5_HKSCS  , C_BIG5_HKSCS},
        {"zh_TW.eucTW"  , C_EUC_TW      , C_BIG5},
@@ -1515,6 +1534,7 @@ gboolean conv_is_multibyte_encoding(CharSet encoding)
        case C_ISO_2022_CN:
        case C_SHIFT_JIS:
        case C_GB2312:
+       case C_GBK:
        case C_BIG5:
        case C_UTF_8:
        case C_UTF_7:
@@ -1539,61 +1559,33 @@ const gchar *conv_get_current_locale(void)
        return cur_locale;
 }
 
-void conv_unmime_header_overwrite(gchar *str)
+gchar *conv_unmime_header(const gchar *str, const gchar *default_encoding)
 {
-       gchar *buf;
-       gint buflen;
-       CharSet cur_charset;
-
-       cur_charset = conv_get_locale_charset();
-
-       if (cur_charset == C_EUC_JP) {
-               buflen = strlen(str) * 2 + 1;
-               Xalloca(buf, buflen, return);
-               conv_anytodisp(buf, buflen, str);
-               unmime_header(str, buf);
-       } else {
-               buflen = strlen(str) + 1;
-               Xalloca(buf, buflen, return);
-               unmime_header(buf, str);
-               strncpy2(str, buf, buflen);
-       }
-}
+       gchar buf[BUFFSIZE];
 
-void conv_unmime_header(gchar *outbuf, gint outlen, const gchar *str,
-                       const gchar *charset)
-{
-       CharSet cur_charset;
+       if (is_ascii_str(str))
+               return unmime_header(str);
 
-       cur_charset = conv_get_locale_charset();
+       if (default_encoding) {
+               gchar *utf8_buf;
 
-       if (cur_charset == C_EUC_JP) {
-               gchar *buf;
-               gint buflen;
+               utf8_buf = conv_codeset_strdup
+                       (str, default_encoding, CS_INTERNAL);
+               if (utf8_buf) {
+                       gchar *decoded_str;
 
-               buflen = strlen(str) * 2 + 1;
-               Xalloca(buf, buflen, return);
-               conv_anytodisp(buf, buflen, str);
-               unmime_header(outbuf, buf);
-       } else {
-               gchar *tmp = NULL;
-               unmime_header(outbuf, str);
-
-               if (outbuf && !g_utf8_validate(outbuf, -1, NULL)) {
-                       if (conv_get_locale_charset() != C_INTERNAL)
-                               tmp = conv_codeset_strdup(outbuf,
-                                       conv_get_locale_charset_str(),
-                                       CS_INTERNAL);
-
-                       if (tmp) {
-                               strncpy(outbuf, tmp, outlen-1);
-                               g_free(tmp);
-                       } else {
-                               conv_unreadable_8bit(outbuf);
-                       }
+                       decoded_str = unmime_header(utf8_buf);
+                       g_free(utf8_buf);
+                       return decoded_str;
                }
        }
 
+       if (conv_get_locale_charset() == C_EUC_JP)
+               conv_anytodisp(buf, sizeof(buf), str);
+       else
+               conv_localetodisp(buf, sizeof(buf), str);
+
+       return unmime_header(buf);
 }
 
 #define MAX_LINELEN            76
@@ -1805,7 +1797,7 @@ gchar *conv_filename_from_utf8(const gchar *utf8_file)
 
 gchar *conv_filename_to_utf8(const gchar *fs_file)
 {
-       gchar *utf8_file;
+       gchar *utf8_file = NULL;
        GError *error = NULL;
 
        utf8_file = g_filename_to_utf8(fs_file, -1, NULL, NULL, &error);
@@ -1814,8 +1806,12 @@ gchar *conv_filename_to_utf8(const gchar *fs_file)
                          error->message);
                g_error_free(error);
        }
-       if (!utf8_file)
+
+       if (!utf8_file || !g_utf8_validate(utf8_file, -1, NULL)) {
+               g_free(utf8_file);
                utf8_file = g_strdup(fs_file);
+               conv_unreadable_8bit(utf8_file);
+       }
 
        return utf8_file;
 }