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;
911 g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
912 tmp, tlen, mb_seqlen);
915 if (tlen == 0 || raw_len == 0) {
921 if (line_len > 1 && destp > dest) {
928 g_snprintf(destp, len - strlen(dest), "%s%s%s",
929 mimehdr_init, mimehdr_charset,
931 destp += mimehdr_begin_len;
932 line_len += mimehdr_begin_len;
934 to64frombits(destp, raw, raw_len);
935 line_len += strlen(destp);
936 destp += strlen(destp);
938 strcpy(destp, mimehdr_end);
939 destp += strlen(mimehdr_end);
940 line_len += strlen(mimehdr_end);
943 line_len += strlen(destp);
944 destp += strlen(destp);
949 /* g_print("line_len = %d\n\n", line_len); */
950 } while (*wtmpp != (wchar_t)0);
952 while (iswspace(*wsrcp)) {
955 mbl = wctomb(destp, *wsrcp++);
968 /g_print("dest = %s\n", dest);
970 #else /* !HAVE_LIBJCONV */
974 void conv_encode_header(gchar *dest, gint len, const gchar *src,
980 size_t line_len, mimehdr_len, mimehdr_begin_len;
981 gchar *mimehdr_init = "=?";
982 gchar *mimehdr_end = "?=";
983 gchar *mimehdr_enctype = "?B?";
984 const gchar *mimehdr_charset;
986 /* g_print("src = %s\n", src); */
987 mimehdr_charset = conv_get_outgoing_charset_str();
988 if (strcmp(mimehdr_charset, "ISO-2022-JP") != 0) {
989 /* currently only supports Japanese */
990 strncpy2(dest, src, len);
994 /* convert to wide-character string */
995 wsrcp = wsrc = strdup_mbstowcs(src);
997 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
998 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
999 mimehdr_begin_len = strlen(mimehdr_init) +
1000 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1002 line_len = header_len;
1006 g_return_if_fail(wsrc != NULL);
1009 wchar_t *wp, *wtmp, *wtmpp;
1012 /* irresponsible buffer overrun check */
1013 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
1015 /* encode string including space
1016 if non-ASCII string follows */
1017 if (is_next_nonascii(wsrcp)) {
1019 while ((wp = find_wspace(wp)) != NULL)
1020 if (!is_next_nonascii(wp)) break;
1022 wp = find_wspace(wsrcp);
1025 wtmp = wcsndup(wsrcp, wp - wsrcp);
1027 while (iswspace(wsrcp[nspc])) nspc++;
1029 wtmp = wcsdup(wsrcp);
1030 wsrcp += wcslen(wsrcp);
1036 gint prev_mbl = 1, tlen = 0, mb_seqlen = 0;
1038 register gchar *tmpp;
1040 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
1043 while (*wtmpp != (wchar_t)0) {
1046 mbl = wctomb(tmpp, *wtmpp);
1048 g_warning("invalid wide character\n");
1053 /* length of KI + KO */
1054 if (prev_mbl == 1 && mbl == 2)
1055 mb_seqlen += JIS_SEQLEN * 2;
1058 gint dlen = mimehdr_len +
1059 B64LEN(tlen + mb_seqlen + mbl);
1061 if ((line_len + dlen +
1062 (*(wtmpp + 1) ? 0 : nspc) +
1063 (line_len > 1 ? 1 : 0))
1077 if ((line_len + tlen + mbl +
1078 (*(wtmpp + 1) ? 0 : nspc) +
1079 (line_len > 1 ? 1 : 0))
1081 if (1 + tlen + mbl +
1082 (*(wtmpp + 1) ? 0 : nspc)
1102 /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
1103 tmp, tlen, mb_seqlen);
1111 if (line_len > 1 && destp > dest) {
1120 tmp_jis = g_new(gchar, tlen + mb_seqlen + 1);
1121 conv_euctojis(tmp_jis,
1122 tlen + mb_seqlen + 1, tmp);
1123 g_snprintf(destp, len - strlen(dest), "%s%s%s",
1124 mimehdr_init, mimehdr_charset,
1126 destp += mimehdr_begin_len;
1127 line_len += mimehdr_begin_len;
1129 to64frombits(destp, tmp_jis, strlen(tmp_jis));
1130 line_len += strlen(destp);
1131 destp += strlen(destp);
1133 strcpy(destp, mimehdr_end);
1134 destp += strlen(mimehdr_end);
1135 line_len += strlen(mimehdr_end);
1140 line_len += strlen(destp);
1141 destp += strlen(destp);
1145 /* g_print("line_len = %d\n\n", line_len); */
1146 } while (*wtmpp != (wchar_t)0);
1148 while (iswspace(*wsrcp)) {
1151 mbl = wctomb(destp, *wsrcp++);
1164 /* g_print("dest = %s\n", dest); */
1166 #endif /* HAVE_LIBJCONV */