2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999,2000 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);
356 codesets = &src_codeset;
359 codesets = jconv_info_get_pref_codesets(&n_codesets);
361 dest_codeset = conv_get_current_charset_str();
363 if (jconv_alloc_conv(inbuf, strlen(inbuf), &buf, &len,
364 codesets, n_codesets,
365 &actual_codeset, dest_codeset)
370 #else /* !HAVE_LIBJCONV */
372 if (!strcasecmp(src_codeset, CS_EUC_JP) ||
373 !strcasecmp(src_codeset, "EUCJP"))
374 src_charset = C_EUC_JP;
375 else if (!strcasecmp(src_codeset, CS_SHIFT_JIS) ||
376 !strcasecmp(src_codeset, "SHIFT-JIS") ||
377 !strcasecmp(src_codeset, "SJIS"))
378 src_charset = C_SHIFT_JIS;
379 if (dest_codeset && !strcasecmp(dest_codeset, CS_ISO_2022_JP))
380 dest_charset = C_ISO_2022_JP;
383 if ((src_charset == C_EUC_JP || src_charset == C_SHIFT_JIS) &&
384 dest_charset == C_ISO_2022_JP) {
385 len = (strlen(inbuf) + 1) * 3;
388 if (src_charset == C_EUC_JP)
389 conv_euctojis(buf, len, inbuf);
391 conv_anytojis(buf, len, inbuf);
392 buf = g_realloc(buf, strlen(buf) + 1);
395 buf = g_strdup(inbuf);
398 #endif /* !HAVE_LIBJCONV */
401 CodeConvFunc conv_get_code_conv_func(const gchar *charset)
403 CodeConvFunc code_conv;
406 if (conv_get_outgoing_charset() == C_ISO_2022_JP)
407 return conv_jistodisp;
412 if (!strcasecmp(charset, CS_ISO_2022_JP) ||
413 !strcasecmp(charset, CS_ISO_2022_JP_2))
414 code_conv = conv_jistodisp;
415 else if (!strcasecmp(charset, CS_US_ASCII))
416 code_conv = conv_ustodisp;
418 else if (!strncasecmp(charset, "ISO-8859-", 9))
419 code_conv = conv_latintodisp;
420 #endif /* !HAVE_LIBJCONV */
421 else if (!strcasecmp(charset, CS_SHIFT_JIS) ||
422 !strcasecmp(charset, "SHIFT-JIS") ||
423 !strcasecmp(charset, "SJIS") ||
424 !strcasecmp(charset, "X-SJIS"))
425 code_conv = conv_sjistodisp;
426 else if (!strcasecmp(charset, CS_EUC_JP) ||
427 !strcasecmp(charset, "EUCJP"))
428 code_conv = conv_euctodisp;
430 code_conv = conv_noconv;
435 static const struct {
439 {C_US_ASCII, CS_US_ASCII},
441 {C_ISO_8859_1, CS_ISO_8859_1},
442 {C_ISO_8859_2, CS_ISO_8859_2},
443 {C_ISO_8859_4, CS_ISO_8859_4},
444 {C_ISO_8859_5, CS_ISO_8859_5},
445 {C_ISO_8859_7, CS_ISO_8859_7},
446 {C_ISO_8859_8, CS_ISO_8859_8},
447 {C_ISO_8859_9, CS_ISO_8859_9},
448 {C_ISO_8859_13, CS_ISO_8859_13},
449 {C_ISO_8859_15, CS_ISO_8859_15},
450 {C_BALTIC, CS_BALTIC},
451 {C_CP1251, CS_CP1251},
452 {C_WINDOWS_1251, CS_WINDOWS_1251},
453 {C_KOI8_R, CS_KOI8_R},
454 {C_KOI8_U, CS_KOI8_U},
455 {C_ISO_2022_JP, CS_ISO_2022_JP},
456 {C_ISO_2022_JP_2, CS_ISO_2022_JP_2},
457 {C_EUC_JP, CS_EUC_JP},
458 {C_SHIFT_JIS, CS_SHIFT_JIS},
459 {C_ISO_2022_KR, CS_ISO_2022_KR},
460 {C_EUC_KR, CS_EUC_KR},
461 {C_ISO_2022_CN, CS_ISO_2022_CN},
462 {C_EUC_CN, CS_EUC_CN},
463 {C_GB2312, CS_GB2312},
464 {C_EUC_TW, CS_EUC_TW},
469 static const struct {
473 {"ja_JP.eucJP" , C_EUC_JP},
474 {"ja_JP.ujis" , C_EUC_JP},
475 {"ja_JP.EUC" , C_EUC_JP},
476 {"ja_JP.SJIS" , C_SHIFT_JIS},
477 {"ja_JP.JIS" , C_ISO_2022_JP},
478 {"ja_JP" , C_EUC_JP},
479 {"ko_KR" , C_EUC_KR},
480 {"zh_CN.GB2312" , C_GB2312},
481 {"zh_CN" , C_GB2312},
482 {"zh_TW.eucTW" , C_EUC_TW},
483 {"zh_TW.Big5" , C_BIG5},
486 {"ru_RU.KOI8-R" , C_KOI8_R},
487 {"ru_RU.CP1251" , C_CP1251},
489 {"en_US" , C_ISO_8859_1},
490 {"ca_ES" , C_ISO_8859_1},
491 {"da_DK" , C_ISO_8859_1},
492 {"de_DE" , C_ISO_8859_1},
493 {"nl_NL" , C_ISO_8859_1},
494 {"et_EE" , C_ISO_8859_1},
495 {"fi_FI" , C_ISO_8859_1},
496 {"fr_FR" , C_ISO_8859_1},
497 {"is_IS" , C_ISO_8859_1},
498 {"it_IT" , C_ISO_8859_1},
499 {"no_NO" , C_ISO_8859_1},
500 {"pt_PT" , C_ISO_8859_1},
501 {"pt_BR" , C_ISO_8859_1},
502 {"es_ES" , C_ISO_8859_1},
503 {"sv_SE" , C_ISO_8859_1},
505 {"hr_HR" , C_ISO_8859_2},
506 {"hu_HU" , C_ISO_8859_2},
507 {"pl_PL" , C_ISO_8859_2},
508 {"ro_RO" , C_ISO_8859_2},
509 {"sk_SK" , C_ISO_8859_2},
510 {"sl_SI" , C_ISO_8859_2},
511 {"ru_RU" , C_ISO_8859_5},
512 {"el_GR" , C_ISO_8859_7},
513 {"iw_IL" , C_ISO_8859_8},
514 {"tr_TR" , C_ISO_8859_9},
516 {"lt_LT.iso88594" , C_ISO_8859_4},
517 {"lt_LT.ISO8859-4" , C_ISO_8859_4},
518 {"lt_LT.ISO_8859-4" , C_ISO_8859_4},
519 {"lt_LT" , C_ISO_8859_13},
520 {"lv_LV" , C_ISO_8859_13},
523 {"POSIX" , C_US_ASCII},
525 #endif /* !HAVE_LIBJCONV */
527 const gchar *conv_get_charset_str(CharSet charset)
531 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
532 if (charsets[i].charset == charset)
533 return charsets[i].name;
539 CharSet conv_get_charset_from_str(const gchar *charset)
543 if (!charset) return C_AUTO;
545 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
546 if (!strcasecmp(charsets[i].name, charset))
547 return charsets[i].charset;
553 CharSet conv_get_current_charset(void)
555 static CharSet cur_charset = -1;
559 const gchar *cur_codeset;
561 const gchar *cur_locale;
564 if (cur_charset != -1)
568 cur_codeset = jconv_info_get_current_codeset();
569 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
570 if (!strcasecmp(cur_codeset, charsets[i].name)) {
571 cur_charset = charsets[i].charset;
576 cur_locale = g_getenv("LC_ALL");
577 if (!cur_locale) cur_locale = g_getenv("LC_CTYPE");
578 if (!cur_locale) cur_locale = g_getenv("LANG");
579 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
581 debug_print("current locale: %s\n",
582 cur_locale ? cur_locale : "(none)");
585 cur_charset = C_US_ASCII;
589 if (strcasestr(cur_locale, "UTF-8")) {
590 cur_charset = C_UTF_8;
594 for (i = 0; i < sizeof(locale_table) / sizeof(locale_table[0]); i++) {
597 /* "ja_JP.EUC" matches with "ja_JP.eucJP" and "ja_JP.EUC" */
598 /* "ja_JP" matches with "ja_JP.xxxx" and "ja" */
599 if (!strncasecmp(cur_locale, locale_table[i].locale,
600 strlen(locale_table[i].locale))) {
601 cur_charset = locale_table[i].charset;
603 } else if ((p = strchr(locale_table[i].locale, '_')) &&
604 !strchr(p + 1, '.')) {
605 if (strlen(cur_locale) == 2 &&
606 !strncasecmp(cur_locale, locale_table[i].locale, 2)) {
607 cur_charset = locale_table[i].charset;
614 cur_charset = C_AUTO;
618 const gchar *conv_get_current_charset_str(void)
621 return jconv_info_get_current_codeset();
623 static const gchar *codeset = NULL;
626 codeset = conv_get_charset_str(conv_get_current_charset());
628 return codeset ? codeset : "US-ASCII";
632 CharSet conv_get_outgoing_charset(void)
634 static CharSet out_charset = -1;
637 gint i, j, n_pref_codesets;
638 const gchar *const *pref_codesets;
643 if (out_charset != -1)
647 /* skip US-ASCII and UTF-8 */
648 pref_codesets = jconv_info_get_pref_codesets(&n_pref_codesets);
649 for (i = 0; i < n_pref_codesets; i++) {
650 for (j = 2; j < sizeof(charsets) / sizeof(charsets[0]); j++) {
651 if (!strcasecmp(pref_codesets[i], charsets[j].name)) {
652 out_charset = charsets[j].charset;
658 for (i = 0; i < n_pref_codesets; i++) {
659 if (!strcasecmp(pref_codesets[i], "UTF-8")) {
660 out_charset = C_UTF_8;
665 out_charset = C_AUTO;
667 cur_charset = conv_get_current_charset();
668 switch (cur_charset) {
671 out_charset = C_ISO_2022_JP;
674 out_charset = cur_charset;
681 const gchar *conv_get_outgoing_charset_str(void)
686 if (prefs_common.outgoing_charset) {
687 if (!isalpha(prefs_common.outgoing_charset[0])) {
688 g_free(prefs_common.outgoing_charset);
689 prefs_common.outgoing_charset = g_strdup(CS_AUTO);
690 } else if (strcmp(prefs_common.outgoing_charset, CS_AUTO) != 0)
691 return prefs_common.outgoing_charset;
694 out_charset = conv_get_outgoing_charset();
695 str = conv_get_charset_str(out_charset);
697 return str ? str : "US-ASCII";
700 void conv_unmime_header_overwrite(gchar *str)
706 cur_charset = conv_get_current_charset();
709 Xstrdup_a(buf, str, {return;});
710 outlen = strlen(str) + 1;
711 UnMimeHeaderConv(buf, str, outlen);
712 if (cur_charset == C_EUC_JP)
713 conv_unreadable_eucjp(str);
715 if (cur_charset == C_EUC_JP) {
719 Xstrdup_a(buf, str, {return;});
720 outlen = strlen(str) + 1;
722 len = strlen(buf) * 2 + 1;
723 Xalloca(tmp, len, {strncpy2(str, buf, outlen); return;});
724 conv_jistodisp(tmp, len, buf);
725 strncpy2(str, tmp, outlen);
731 void conv_unmime_header(gchar *outbuf, gint outlen, const gchar *str,
732 const gchar *charset)
737 Xstrdup_a(buf, str, {return;});
738 cur_charset = conv_get_current_charset();
741 UnMimeHeaderConv(buf, outbuf, outlen);
742 if (cur_charset == C_EUC_JP)
743 conv_unreadable_eucjp(outbuf);
746 if (cur_charset == C_EUC_JP) {
750 len = strlen(buf) * 2 + 1;
751 Xalloca(tmp, len, {strncpy2(outbuf, buf, outlen); return;});
752 conv_jistodisp(tmp, len, buf);
753 strncpy2(outbuf, tmp, outlen);
755 strncpy2(outbuf, buf, outlen);
759 #define MAX_ENCLEN 75
760 #define MAX_LINELEN 76
762 #define B64LEN(len) ((len) / 3 * 4 + ((len) % 3 ? 4 : 0))
765 void conv_encode_header(gchar *dest, gint len, const gchar *src,
771 size_t line_len, mimehdr_len, mimehdr_begin_len;
772 gchar *mimehdr_init = "=?";
773 gchar *mimehdr_end = "?=";
774 gchar *mimehdr_enctype = "?B?";
775 const gchar *mimehdr_charset;
777 //g_print("src = %s\n", src);
778 mimehdr_charset = conv_get_outgoing_charset_str();
780 /* convert to wide-character string */
781 wsrcp = wsrc = strdup_mbstowcs(src);
783 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
784 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
785 mimehdr_begin_len = strlen(mimehdr_init) +
786 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
788 line_len = header_len;
792 g_return_if_fail(wsrc != NULL);
795 wchar_t *wp, *wtmp, *wtmpp;
798 /* irresponsible buffer overrun check */
799 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
801 /* encode string including space
802 if non-ASCII string follows */
803 if (is_next_nonascii(wsrcp)) {
805 while ((wp = find_wspace(wp)) != NULL)
806 if (!is_next_nonascii(wp)) break;
808 wp = find_wspace(wsrcp);
811 wtmp = wcsndup(wsrcp, wp - wsrcp);
813 while (iswspace(wsrcp[nspc])) nspc++;
815 wtmp = wcsdup(wsrcp);
816 wsrcp += wcslen(wsrcp);
822 gint tlen = 0, str_ascii = 1;
823 gchar *tmp; /* internal codeset */
824 gchar *raw; /* converted, but not base64 encoded */
825 register gchar *tmpp;
828 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
833 while (*wtmpp != (wchar_t)0) {
836 gchar *raw_new = NULL;
838 const gchar *src_codeset;
840 if (*wtmpp < 32 || *wtmpp >= 127)
842 mbl = wctomb(tmpp, *wtmpp);
844 g_warning("invalid wide character\n");
849 src_codeset = conv_get_current_charset_str();
850 //printf ("tmp = %s, tlen = %d, mbl\n",
852 if (jconv_alloc_conv(tmp, tlen + mbl,
853 &raw_new, &raw_new_len,
855 &dummy, mimehdr_charset)
857 g_warning("can't convert\n");
862 gint dlen = mimehdr_len +
864 if ((line_len + dlen +
865 (*(wtmpp + 1) ? 0 : nspc) +
866 (line_len > 1 ? 1 : 0))
881 if ((line_len + tlen + mbl +
882 (*(wtmpp + 1) ? 0 : nspc) +
883 (line_len > 1 ? 1 : 0))
887 (*(wtmpp + 1) ? 0 : nspc)
906 raw_len = raw_new_len;
910 //g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
911 // tmp, tlen, mb_seqlen);
913 if (tlen == 0 || raw_len == 0) {
919 if (line_len > 1 && destp > dest) {
926 g_snprintf(destp, len - strlen(dest), "%s%s%s",
927 mimehdr_init, mimehdr_charset,
929 destp += mimehdr_begin_len;
930 line_len += mimehdr_begin_len;
932 to64frombits(destp, raw, raw_len);
933 line_len += strlen(destp);
934 destp += strlen(destp);
936 strcpy(destp, mimehdr_end);
937 destp += strlen(mimehdr_end);
938 line_len += strlen(mimehdr_end);
941 line_len += strlen(destp);
942 destp += strlen(destp);
947 //g_print("line_len = %d\n\n", line_len);
948 } while (*wtmpp != (wchar_t)0);
950 while (iswspace(*wsrcp)) {
953 mbl = wctomb(destp, *wsrcp++);
966 //g_print("dest = %s\n", dest);
968 #else /* !HAVE_LIBJCONV */
972 void conv_encode_header(gchar *dest, gint len, const gchar *src,
978 size_t line_len, mimehdr_len, mimehdr_begin_len;
979 gchar *mimehdr_init = "=?";
980 gchar *mimehdr_end = "?=";
981 gchar *mimehdr_enctype = "?B?";
982 const gchar *mimehdr_charset;
984 //g_print("src = %s\n", src);
985 mimehdr_charset = conv_get_outgoing_charset_str();
986 if (strcmp(mimehdr_charset, "ISO-2022-JP") != 0) {
987 /* currently only supports Japanese */
988 strncpy2(dest, src, len);
992 /* convert to wide-character string */
993 wsrcp = wsrc = strdup_mbstowcs(src);
995 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
996 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
997 mimehdr_begin_len = strlen(mimehdr_init) +
998 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1000 line_len = header_len;
1004 g_return_if_fail(wsrc != NULL);
1007 wchar_t *wp, *wtmp, *wtmpp;
1010 /* irresponsible buffer overrun check */
1011 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
1013 /* encode string including space
1014 if non-ASCII string follows */
1015 if (is_next_nonascii(wsrcp)) {
1017 while ((wp = find_wspace(wp)) != NULL)
1018 if (!is_next_nonascii(wp)) break;
1020 wp = find_wspace(wsrcp);
1023 wtmp = wcsndup(wsrcp, wp - wsrcp);
1025 while (iswspace(wsrcp[nspc])) nspc++;
1027 wtmp = wcsdup(wsrcp);
1028 wsrcp += wcslen(wsrcp);
1034 gint prev_mbl = 1, tlen = 0, mb_seqlen = 0;
1036 register gchar *tmpp;
1038 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
1041 while (*wtmpp != (wchar_t)0) {
1044 mbl = wctomb(tmpp, *wtmpp);
1046 g_warning("invalid wide character\n");
1051 /* length of KI + KO */
1052 if (prev_mbl == 1 && mbl == 2)
1053 mb_seqlen += JIS_SEQLEN * 2;
1056 gint dlen = mimehdr_len +
1057 B64LEN(tlen + mb_seqlen + mbl);
1059 if ((line_len + dlen +
1060 (*(wtmpp + 1) ? 0 : nspc) +
1061 (line_len > 1 ? 1 : 0))
1075 if ((line_len + tlen + mbl +
1076 (*(wtmpp + 1) ? 0 : nspc) +
1077 (line_len > 1 ? 1 : 0))
1079 if (1 + tlen + mbl +
1080 (*(wtmpp + 1) ? 0 : nspc)
1100 //g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
1101 // tmp, tlen, mb_seqlen);
1108 if (line_len > 1 && destp > dest) {
1117 tmp_jis = g_new(gchar, tlen + mb_seqlen + 1);
1118 conv_euctojis(tmp_jis,
1119 tlen + mb_seqlen + 1, tmp);
1120 g_snprintf(destp, len - strlen(dest), "%s%s%s",
1121 mimehdr_init, mimehdr_charset,
1123 destp += mimehdr_begin_len;
1124 line_len += mimehdr_begin_len;
1126 to64frombits(destp, tmp_jis, strlen(tmp_jis));
1127 line_len += strlen(destp);
1128 destp += strlen(destp);
1130 strcpy(destp, mimehdr_end);
1131 destp += strlen(mimehdr_end);
1132 line_len += strlen(mimehdr_end);
1137 line_len += strlen(destp);
1138 destp += strlen(destp);
1142 //g_print("line_len = %d\n\n", line_len);
1143 } while (*wtmpp != (wchar_t)0);
1145 while (iswspace(*wsrcp)) {
1148 mbl = wctomb(destp, *wsrcp++);
1161 //g_print("dest = %s\n", dest);
1163 #endif /* HAVE_LIBJCONV */