2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2001 Hiroyuki Yamamoto
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #if (HAVE_WCTYPE_H && HAVE_WCHAR_H)
49 #include "prefs_common.h"
52 (((c) & 0xff) >= 0xa1 && ((c) & 0xff) <= 0xfe)
54 (((c) & 0xff) == 0x8e || ((c) & 0xff) == 0x8f)
55 #define isunprintablekanji(c) \
56 (((c) & 0xff) >= 0xa9 && ((c) & 0xff) <= 0xaf)
58 void conv_jistoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
60 KCC_filter(outbuf, "EUC", (gchar *)inbuf, "JISBB", 0, 0, 0);
63 void conv_euctojis(gchar *outbuf, gint outlen, const gchar *inbuf)
67 inlen = strlen(inbuf);
68 if (iskanji(inbuf[inlen - 1]) || iseucss(inbuf[inlen - 1])) {
69 /* if tail end of the string is not ended with ascii,
70 add dummy return code. */
71 gchar *tmpin, *tmpout;
73 /* length of original string + '\n' + '\0' */
74 tmpin = alloca(inlen + 2);
76 g_warning(_("can't allocate memory\n"));
77 KCC_filter(outbuf, "JISBB", (gchar *)inbuf, "EUC",
83 tmpin[inlen + 1] = '\0';
85 tmpout = alloca(outlen + 1);
87 g_warning(_("can't allocate memory\n"));
88 KCC_filter(outbuf, "JISBB", (gchar *)inbuf, "EUC",
93 KCC_filter(tmpout, "JISBB", tmpin, "EUC", 0, 0, 0);
95 if (tmpout[len - 1] == '\n')
96 tmpout[len - 1] = '\0';
97 strncpy2(outbuf, tmpout, outlen);
99 KCC_filter(outbuf, "JISBB", (gchar *)inbuf, "EUC", 0, 0, 0);
102 void conv_sjistoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
104 KCC_filter(outbuf, "EUC", (gchar *)inbuf, "SJIS", 0, 0, 0);
107 void conv_anytoeuc(gchar *outbuf, gint outlen, const gchar *inbuf)
109 KCC_filter(outbuf, "EUC", (gchar *)inbuf, "AUTO", 0, 0, 0);
112 void conv_anytojis(gchar *outbuf, gint outlen, const gchar *inbuf)
114 KCC_filter(outbuf, "JISBB", (gchar *)inbuf, "AUTO", 0, 0, 0);
117 #define SUBST_CHAR '_'
119 void conv_unreadable_eucjp(gchar *str)
121 register guchar *p = str;
125 /* convert CR+LF -> LF */
126 if (*p == '\r' && *(p + 1) == '\n')
127 memmove(p, p + 1, strlen(p));
128 /* printable 7 bit code */
130 } else if (iskanji(*p)) {
131 if (iskanji(*(p + 1)) && !isunprintablekanji(*p))
132 /* printable euc-jp code */
135 /* substitute unprintable code */
144 } else if (iseucss(*p)) {
145 if ((*(p + 1) & 0x80) != 0)
146 /* euc-jp hankaku kana */
151 /* substitute unprintable 1 byte code */
156 void conv_unreadable_8bit(gchar *str)
158 register guchar *p = str;
161 /* convert CR+LF -> LF */
162 if (*p == '\r' && *(p + 1) == '\n')
163 memmove(p, p + 1, strlen(p));
164 else if (!isascii(*p)) *p = SUBST_CHAR;
169 void conv_unreadable_latin(gchar *str)
171 register guchar *p = str;
174 /* convert CR+LF -> LF */
175 if (*p == '\r' && *(p + 1) == '\n')
176 memmove(p, p + 1, strlen(p));
177 else if ((*p & 0xff) >= 0x80 && (*p & 0xff) <= 0x9f)
185 void conv_mb_alnum(gchar *str)
187 static guchar char_tbl[] = {
189 NCV, ' ', NCV, NCV, ',', '.', NCV, ':',
190 ';', '?', '!', NCV, NCV, NCV, NCV, NCV,
192 NCV, NCV, NCV, NCV, NCV, NCV, NCV, NCV,
193 NCV, NCV, NCV, NCV, NCV, NCV, NCV, NCV,
195 NCV, NCV, NCV, NCV, NCV, NCV, NCV, NCV,
196 NCV, NCV, '(', ')', NCV, NCV, '[', ']',
198 '{', '}', NCV, NCV, NCV, NCV, NCV, NCV,
199 NCV, NCV, NCV, NCV, '+', '-', NCV, NCV,
201 NCV, '=', NCV, '<', '>', NCV, NCV, NCV,
202 NCV, NCV, NCV, NCV, NCV, NCV, NCV, NCV
205 register guchar *p = str;
212 register guchar ch = *(p + 1);
214 if (ch >= 0xb0 && ch <= 0xfa) {
219 memmove(p, p + 1, len);
225 } else if (*p == 0xa1) {
226 register guchar ch = *(p + 1);
228 if (ch >= 0xa0 && ch <= 0xef &&
229 NCV != char_tbl[ch - 0xa0]) {
230 *p = char_tbl[ch - 0xa0];
233 memmove(p, p + 1, len);
239 } else if (iskanji(*p)) {
249 void conv_jistodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
251 conv_jistoeuc(outbuf, outlen, inbuf);
252 conv_unreadable_eucjp(outbuf);
255 void conv_sjistodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
257 conv_sjistoeuc(outbuf, outlen, inbuf);
258 conv_unreadable_eucjp(outbuf);
261 void conv_euctodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
263 strncpy2(outbuf, inbuf, outlen);
264 conv_unreadable_eucjp(outbuf);
267 void conv_ustodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
269 strncpy2(outbuf, inbuf, outlen);
270 conv_unreadable_8bit(outbuf);
273 void conv_latintodisp(gchar *outbuf, gint outlen, const gchar *inbuf)
275 strncpy2(outbuf, inbuf, outlen);
276 conv_unreadable_latin(outbuf);
279 void conv_noconv(gchar *outbuf, gint outlen, const gchar *inbuf)
281 strncpy2(outbuf, inbuf, outlen);
284 CodeConverter *conv_code_converter_new(const gchar *charset)
288 conv = g_new0(CodeConverter, 1);
290 conv->code_conv_func = conv_get_code_conv_func(charset);
292 conv->charset_str = g_strdup(charset);
293 conv->charset = conv_get_charset_from_str(charset);
298 void conv_code_converter_destroy(CodeConverter *conv)
300 g_free(conv->charset_str);
304 gint conv_convert(CodeConverter *conv, gchar *outbuf, gint outlen,
310 str = conv_codeset_strdup(inbuf, conv->charset_str, NULL);
314 strncpy2(outbuf, str, outlen);
317 #else /* !HAVE_LIBJCONV */
318 conv->code_conv_func(outbuf, outlen, inbuf);
324 gchar *conv_codeset_strdup(const gchar *inbuf,
325 const gchar *src_codeset, const gchar *dest_codeset)
331 const gchar *const *codesets;
333 #else /* !HAVE_LIBJCONV */
334 CharSet src_charset = C_AUTO, dest_charset = C_AUTO;
340 func = conv_get_code_conv_func(src_codeset);
341 if (func != conv_noconv) {
342 if (func == conv_jistodisp || func == conv_sjistodisp)
343 len = strlen(inbuf) * 2 + 1;
345 len = strlen(inbuf) + 1;
347 if (!buf) return NULL;
348 func(buf, len, inbuf);
349 buf = g_realloc(buf, strlen(buf) + 1);
354 /* don't convert if src and dest codeset are identical */
355 if (src_codeset && dest_codeset &&
356 !strcasecmp(src_codeset, dest_codeset))
357 return g_strdup(inbuf);
361 codesets = &src_codeset;
364 codesets = jconv_info_get_pref_codesets(&n_codesets);
366 dest_codeset = conv_get_current_charset_str();
367 /* don't convert if current codeset is US-ASCII */
368 if (!strcasecmp(dest_codeset, CS_US_ASCII))
369 return g_strdup(inbuf);
372 if (jconv_alloc_conv(inbuf, strlen(inbuf), &buf, &len,
373 codesets, n_codesets,
374 &actual_codeset, dest_codeset)
379 #else /* !HAVE_LIBJCONV */
381 if (!strcasecmp(src_codeset, CS_EUC_JP) ||
382 !strcasecmp(src_codeset, CS_EUCJP))
383 src_charset = C_EUC_JP;
384 else if (!strcasecmp(src_codeset, CS_SHIFT_JIS) ||
385 !strcasecmp(src_codeset, "SHIFT-JIS") ||
386 !strcasecmp(src_codeset, "SJIS"))
387 src_charset = C_SHIFT_JIS;
388 if (dest_codeset && !strcasecmp(dest_codeset, CS_ISO_2022_JP))
389 dest_charset = C_ISO_2022_JP;
392 if ((src_charset == C_EUC_JP || src_charset == C_SHIFT_JIS) &&
393 dest_charset == C_ISO_2022_JP) {
394 len = (strlen(inbuf) + 1) * 3;
397 if (src_charset == C_EUC_JP)
398 conv_euctojis(buf, len, inbuf);
400 conv_anytojis(buf, len, inbuf);
401 buf = g_realloc(buf, strlen(buf) + 1);
404 buf = g_strdup(inbuf);
407 #endif /* !HAVE_LIBJCONV */
410 CodeConvFunc conv_get_code_conv_func(const gchar *charset)
412 CodeConvFunc code_conv;
415 if (conv_get_outgoing_charset() == C_ISO_2022_JP)
416 return conv_jistodisp;
421 if (!strcasecmp(charset, CS_ISO_2022_JP) ||
422 !strcasecmp(charset, CS_ISO_2022_JP_2))
423 code_conv = conv_jistodisp;
424 else if (!strcasecmp(charset, CS_US_ASCII))
425 code_conv = conv_ustodisp;
426 else if (!strncasecmp(charset, CS_ISO_8859_1, 10))
427 code_conv = conv_latintodisp;
429 else if (!strncasecmp(charset, "ISO-8859-", 9))
430 code_conv = conv_latintodisp;
432 else if (!strcasecmp(charset, CS_SHIFT_JIS) ||
433 !strcasecmp(charset, "SHIFT-JIS") ||
434 !strcasecmp(charset, "SJIS") ||
435 !strcasecmp(charset, "X-SJIS"))
436 code_conv = conv_sjistodisp;
437 else if (!strcasecmp(charset, CS_EUC_JP) ||
438 !strcasecmp(charset, CS_EUCJP))
439 code_conv = conv_euctodisp;
441 code_conv = conv_noconv;
446 static const struct {
450 {C_US_ASCII, CS_US_ASCII},
451 {C_US_ASCII, CS_ANSI_X3_4_1968},
453 {C_ISO_8859_1, CS_ISO_8859_1},
454 {C_ISO_8859_2, CS_ISO_8859_2},
455 {C_ISO_8859_4, CS_ISO_8859_4},
456 {C_ISO_8859_5, CS_ISO_8859_5},
457 {C_ISO_8859_7, CS_ISO_8859_7},
458 {C_ISO_8859_8, CS_ISO_8859_8},
459 {C_ISO_8859_9, CS_ISO_8859_9},
460 {C_ISO_8859_11, CS_ISO_8859_11},
461 {C_ISO_8859_13, CS_ISO_8859_13},
462 {C_ISO_8859_15, CS_ISO_8859_15},
463 {C_BALTIC, CS_BALTIC},
464 {C_CP1251, CS_CP1251},
465 {C_WINDOWS_1251, CS_WINDOWS_1251},
466 {C_KOI8_R, CS_KOI8_R},
467 {C_KOI8_U, CS_KOI8_U},
468 {C_ISO_2022_JP, CS_ISO_2022_JP},
469 {C_ISO_2022_JP_2, CS_ISO_2022_JP_2},
470 {C_EUC_JP, CS_EUC_JP},
471 {C_EUC_JP, CS_EUCJP},
472 {C_SHIFT_JIS, CS_SHIFT_JIS},
473 {C_ISO_2022_KR, CS_ISO_2022_KR},
474 {C_EUC_KR, CS_EUC_KR},
475 {C_ISO_2022_CN, CS_ISO_2022_CN},
476 {C_EUC_CN, CS_EUC_CN},
477 {C_GB2312, CS_GB2312},
478 {C_EUC_TW, CS_EUC_TW},
480 {C_TIS_620, CS_TIS_620},
481 {C_WINDOWS_874, CS_WINDOWS_874},
485 static const struct {
489 {"ja_JP.eucJP" , C_EUC_JP},
490 {"ja_JP.ujis" , C_EUC_JP},
491 {"ja_JP.EUC" , C_EUC_JP},
492 {"ja_JP.SJIS" , C_SHIFT_JIS},
493 {"ja_JP.JIS" , C_ISO_2022_JP},
494 {"ja_JP" , C_EUC_JP},
495 {"ko_KR" , C_EUC_KR},
496 {"zh_CN.GB2312" , C_GB2312},
497 {"zh_CN" , C_GB2312},
498 {"zh_TW.eucTW" , C_EUC_TW},
499 {"zh_TW.Big5" , C_BIG5},
502 {"ru_RU.KOI8-R" , C_KOI8_R},
503 {"ru_RU.CP1251" , C_CP1251},
505 {"en_US" , C_ISO_8859_1},
506 {"ca_ES" , C_ISO_8859_1},
507 {"da_DK" , C_ISO_8859_1},
508 {"de_DE" , C_ISO_8859_1},
509 {"nl_NL" , C_ISO_8859_1},
510 {"et_EE" , C_ISO_8859_1},
511 {"fi_FI" , C_ISO_8859_1},
512 {"fr_FR" , C_ISO_8859_1},
513 {"is_IS" , C_ISO_8859_1},
514 {"it_IT" , C_ISO_8859_1},
515 {"no_NO" , C_ISO_8859_1},
516 {"pt_PT" , C_ISO_8859_1},
517 {"pt_BR" , C_ISO_8859_1},
518 {"es_ES" , C_ISO_8859_1},
519 {"sv_SE" , C_ISO_8859_1},
521 {"hr_HR" , C_ISO_8859_2},
522 {"hu_HU" , C_ISO_8859_2},
523 {"pl_PL" , C_ISO_8859_2},
524 {"ro_RO" , C_ISO_8859_2},
525 {"sk_SK" , C_ISO_8859_2},
526 {"sl_SI" , C_ISO_8859_2},
527 {"ru_RU" , C_ISO_8859_5},
528 {"el_GR" , C_ISO_8859_7},
529 {"iw_IL" , C_ISO_8859_8},
530 {"tr_TR" , C_ISO_8859_9},
532 {"th_TH" , C_TIS_620},
533 /* {"th_TH" , C_WINDOWS_874}, */
534 /* {"th_TH" , C_ISO_8859_11}, */
536 {"lt_LT.iso88594" , C_ISO_8859_4},
537 {"lt_LT.ISO8859-4" , C_ISO_8859_4},
538 {"lt_LT.ISO_8859-4" , C_ISO_8859_4},
539 {"lt_LT" , C_ISO_8859_13},
540 {"lv_LV" , C_ISO_8859_13},
543 {"POSIX" , C_US_ASCII},
544 {"ANSI_X3.4-1968" , C_US_ASCII},
546 #endif /* !HAVE_LIBJCONV */
548 const gchar *conv_get_charset_str(CharSet charset)
552 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
553 if (charsets[i].charset == charset)
554 return charsets[i].name;
560 CharSet conv_get_charset_from_str(const gchar *charset)
564 if (!charset) return C_AUTO;
566 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
567 if (!strcasecmp(charsets[i].name, charset))
568 return charsets[i].charset;
574 CharSet conv_get_current_charset(void)
576 static CharSet cur_charset = -1;
580 const gchar *cur_codeset;
582 const gchar *cur_locale;
585 if (cur_charset != -1)
589 cur_codeset = jconv_info_get_current_codeset();
590 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
591 if (!strcasecmp(cur_codeset, charsets[i].name)) {
592 cur_charset = charsets[i].charset;
597 cur_locale = g_getenv("LC_ALL");
598 if (!cur_locale) cur_locale = g_getenv("LC_CTYPE");
599 if (!cur_locale) cur_locale = g_getenv("LANG");
600 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
602 debug_print("current locale: %s\n",
603 cur_locale ? cur_locale : "(none)");
606 cur_charset = C_US_ASCII;
610 if (strcasestr(cur_locale, "UTF-8")) {
611 cur_charset = C_UTF_8;
615 for (i = 0; i < sizeof(locale_table) / sizeof(locale_table[0]); i++) {
618 /* "ja_JP.EUC" matches with "ja_JP.eucJP" and "ja_JP.EUC" */
619 /* "ja_JP" matches with "ja_JP.xxxx" and "ja" */
620 if (!strncasecmp(cur_locale, locale_table[i].locale,
621 strlen(locale_table[i].locale))) {
622 cur_charset = locale_table[i].charset;
624 } else if ((p = strchr(locale_table[i].locale, '_')) &&
625 !strchr(p + 1, '.')) {
626 if (strlen(cur_locale) == 2 &&
627 !strncasecmp(cur_locale, locale_table[i].locale, 2)) {
628 cur_charset = locale_table[i].charset;
635 cur_charset = C_AUTO;
639 const gchar *conv_get_current_charset_str(void)
641 static const gchar *codeset = NULL;
644 codeset = conv_get_charset_str(conv_get_current_charset());
646 return codeset ? codeset : "US-ASCII";
649 CharSet conv_get_outgoing_charset(void)
651 static CharSet out_charset = -1;
654 gint i, j, n_pref_codesets;
655 const gchar *const *pref_codesets;
660 if (out_charset != -1)
664 /* skip US-ASCII and UTF-8 */
665 pref_codesets = jconv_info_get_pref_codesets(&n_pref_codesets);
666 for (i = 0; i < n_pref_codesets; i++) {
667 for (j = 3; j < sizeof(charsets) / sizeof(charsets[0]); j++) {
668 if (!strcasecmp(pref_codesets[i], charsets[j].name)) {
669 out_charset = charsets[j].charset;
675 for (i = 0; i < n_pref_codesets; i++) {
676 if (!strcasecmp(pref_codesets[i], "UTF-8")) {
677 out_charset = C_UTF_8;
682 out_charset = C_AUTO;
684 cur_charset = conv_get_current_charset();
685 switch (cur_charset) {
688 out_charset = C_ISO_2022_JP;
691 out_charset = cur_charset;
698 const gchar *conv_get_outgoing_charset_str(void)
703 if (prefs_common.outgoing_charset) {
704 if (!isalpha(prefs_common.outgoing_charset[0])) {
705 g_free(prefs_common.outgoing_charset);
706 prefs_common.outgoing_charset = g_strdup(CS_AUTO);
707 } else if (strcmp(prefs_common.outgoing_charset, CS_AUTO) != 0)
708 return prefs_common.outgoing_charset;
711 out_charset = conv_get_outgoing_charset();
712 str = conv_get_charset_str(out_charset);
714 return str ? str : "US-ASCII";
717 const gchar *conv_get_current_locale(void)
721 cur_locale = g_getenv("LC_ALL");
722 if (!cur_locale) cur_locale = g_getenv("LANG");
723 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
725 debug_print("current locale: %s\n",
726 cur_locale ? cur_locale : "(none)");
731 void conv_unmime_header_overwrite(gchar *str)
737 cur_charset = conv_get_current_charset();
740 Xstrdup_a(buf, str, return);
741 outlen = strlen(str) + 1;
742 UnMimeHeaderConv(buf, str, outlen);
743 if (cur_charset == C_EUC_JP) {
747 len = strlen(str) * 2 + 1;
748 Xalloca(tmp, len, return);
749 conv_jistodisp(tmp, len, str);
750 strncpy2(str, tmp, outlen);
753 if (cur_charset == C_EUC_JP) {
757 Xstrdup_a(buf, str, return);
758 outlen = strlen(str) + 1;
760 len = strlen(buf) * 2 + 1;
761 Xalloca(tmp, len, {strncpy2(str, buf, outlen); return;});
762 conv_jistodisp(tmp, len, buf);
763 strncpy2(str, tmp, outlen);
769 void conv_unmime_header(gchar *outbuf, gint outlen, const gchar *str,
770 const gchar *charset)
775 cur_charset = conv_get_current_charset();
776 Xstrdup_a(buf, str, return);
779 UnMimeHeaderConv(buf, outbuf, outlen);
782 strncpy2(outbuf, buf, outlen);
784 if (cur_charset == C_EUC_JP) {
787 len = strlen(outbuf) * 2 + 1;
788 Xalloca(buf, len, return);
789 conv_jistodisp(buf, len, outbuf);
790 strncpy2(outbuf, buf, outlen);
794 #define MAX_ENCLEN 75
795 #define MAX_LINELEN 76
797 #define B64LEN(len) ((len) / 3 * 4 + ((len) % 3 ? 4 : 0))
800 void conv_encode_header(gchar *dest, gint len, const gchar *src,
806 size_t line_len, mimehdr_len, mimehdr_begin_len;
807 gchar *mimehdr_init = "=?";
808 gchar *mimehdr_end = "?=";
809 gchar *mimehdr_enctype = "?B?";
810 const gchar *mimehdr_charset;
812 /* g_print("src = %s\n", src); */
813 mimehdr_charset = conv_get_outgoing_charset_str();
815 /* convert to wide-character string */
816 wsrcp = wsrc = strdup_mbstowcs(src);
818 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
819 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
820 mimehdr_begin_len = strlen(mimehdr_init) +
821 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
822 line_len = header_len;
826 g_return_if_fail(wsrc != NULL);
829 wchar_t *wp, *wtmp, *wtmpp;
832 /* irresponsible buffer overrun check */
833 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
835 /* encode string including space
836 if non-ASCII string follows */
837 if (is_next_nonascii(wsrcp)) {
839 while ((wp = find_wspace(wp)) != NULL)
840 if (!is_next_nonascii(wp)) break;
842 wp = find_wspace(wsrcp);
845 wtmp = wcsndup(wsrcp, wp - wsrcp);
847 while (iswspace(wsrcp[nspc])) nspc++;
849 wtmp = wcsdup(wsrcp);
850 wsrcp += wcslen(wsrcp);
856 gint tlen = 0, str_ascii = 1;
857 gchar *tmp; /* internal codeset */
858 gchar *raw; /* converted, but not base64 encoded */
859 register gchar *tmpp;
862 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
867 while (*wtmpp != (wchar_t)0) {
870 gchar *raw_new = NULL;
872 const gchar *src_codeset;
874 if (*wtmpp < 32 || *wtmpp >= 127)
876 mbl = wctomb(tmpp, *wtmpp);
878 g_warning("invalid wide character\n");
883 src_codeset = conv_get_current_charset_str();
884 /* printf ("tmp = %s, tlen = %d, mbl\n",
886 if (jconv_alloc_conv(tmp, tlen + mbl,
887 &raw_new, &raw_new_len,
889 &dummy, mimehdr_charset)
891 g_warning("can't convert\n");
897 gint dlen = mimehdr_len +
899 if ((line_len + dlen +
900 (*(wtmpp + 1) ? 0 : nspc) +
901 (line_len > 1 ? 1 : 0))
915 } else if ((line_len + tlen + mbl +
916 (*(wtmpp + 1) ? 0 : nspc) +
917 (line_len > 1 ? 1 : 0))
921 (*(wtmpp + 1) ? 0 : nspc)
939 raw_len = raw_new_len;
943 /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
944 tmp, tlen, mb_seqlen); */
946 if (tlen == 0 || raw_len == 0) {
952 if (line_len > 1 && destp > dest) {
959 g_snprintf(destp, len - strlen(dest), "%s%s%s",
960 mimehdr_init, mimehdr_charset,
962 destp += mimehdr_begin_len;
963 line_len += mimehdr_begin_len;
965 to64frombits(destp, raw, raw_len);
966 line_len += strlen(destp);
967 destp += strlen(destp);
969 strcpy(destp, mimehdr_end);
970 destp += strlen(mimehdr_end);
971 line_len += strlen(mimehdr_end);
974 line_len += strlen(destp);
975 destp += strlen(destp);
980 /* g_print("line_len = %d\n\n", line_len); */
981 } while (*wtmpp != (wchar_t)0);
983 while (iswspace(*wsrcp)) {
986 mbl = wctomb(destp, *wsrcp++);
999 /* g_print("dest = %s\n", dest); */
1001 #else /* !HAVE_LIBJCONV */
1003 #define JIS_SEQLEN 3
1005 void conv_encode_header(gchar *dest, gint len, const gchar *src,
1011 size_t line_len, mimehdr_len, mimehdr_begin_len;
1012 gchar *mimehdr_init = "=?";
1013 gchar *mimehdr_end = "?=";
1014 gchar *mimehdr_enctype = "?B?";
1015 const gchar *mimehdr_charset;
1017 /* g_print("src = %s\n", src); */
1018 mimehdr_charset = conv_get_outgoing_charset_str();
1019 if (strcmp(mimehdr_charset, "ISO-2022-JP") != 0) {
1020 /* currently only supports Japanese */
1021 strncpy2(dest, src, len);
1025 /* convert to wide-character string */
1026 wsrcp = wsrc = strdup_mbstowcs(src);
1028 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
1029 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1030 mimehdr_begin_len = strlen(mimehdr_init) +
1031 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1032 line_len = header_len;
1036 g_return_if_fail(wsrc != NULL);
1039 wchar_t *wp, *wtmp, *wtmpp;
1042 /* irresponsible buffer overrun check */
1043 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
1045 /* encode string including space
1046 if non-ASCII string follows */
1047 if (is_next_nonascii(wsrcp)) {
1049 while ((wp = find_wspace(wp)) != NULL)
1050 if (!is_next_nonascii(wp)) break;
1052 wp = find_wspace(wsrcp);
1055 wtmp = wcsndup(wsrcp, wp - wsrcp);
1057 while (iswspace(wsrcp[nspc])) nspc++;
1059 wtmp = wcsdup(wsrcp);
1060 wsrcp += wcslen(wsrcp);
1066 gint prev_mbl = 1, tlen = 0, mb_seqlen = 0;
1068 register gchar *tmpp;
1070 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
1073 while (*wtmpp != (wchar_t)0) {
1076 mbl = wctomb(tmpp, *wtmpp);
1078 g_warning("invalid wide character\n");
1083 /* length of KI + KO */
1084 if (prev_mbl == 1 && mbl == 2)
1085 mb_seqlen += JIS_SEQLEN * 2;
1088 gint dlen = mimehdr_len +
1089 B64LEN(tlen + mb_seqlen + mbl);
1091 if ((line_len + dlen +
1092 (*(wtmpp + 1) ? 0 : nspc) +
1093 (line_len > 1 ? 1 : 0))
1106 } else if ((line_len + tlen + mbl +
1107 (*(wtmpp + 1) ? 0 : nspc) +
1108 (line_len > 1 ? 1 : 0))
1110 if (1 + tlen + mbl +
1111 (*(wtmpp + 1) ? 0 : nspc)
1130 /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
1131 tmp, tlen, mb_seqlen); */
1138 if (line_len > 1 && destp > dest) {
1147 tmp_jis = g_new(gchar, tlen + mb_seqlen + 1);
1148 conv_euctojis(tmp_jis,
1149 tlen + mb_seqlen + 1, tmp);
1150 g_snprintf(destp, len - strlen(dest), "%s%s%s",
1151 mimehdr_init, mimehdr_charset,
1153 destp += mimehdr_begin_len;
1154 line_len += mimehdr_begin_len;
1156 to64frombits(destp, tmp_jis, strlen(tmp_jis));
1157 line_len += strlen(destp);
1158 destp += strlen(destp);
1160 strcpy(destp, mimehdr_end);
1161 destp += strlen(mimehdr_end);
1162 line_len += strlen(mimehdr_end);
1167 line_len += strlen(destp);
1168 destp += strlen(destp);
1172 /* g_print("line_len = %d\n\n", line_len); */
1173 } while (*wtmpp != (wchar_t)0);
1175 while (iswspace(*wsrcp)) {
1178 mbl = wctomb(destp, *wsrcp++);
1191 /* g_print("dest = %s\n", dest); */
1193 #endif /* HAVE_LIBJCONV */