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);
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;
417 else if (!strncasecmp(charset, CS_ISO_8859_1, 10))
418 code_conv = conv_latintodisp;
420 else if (!strncasecmp(charset, "ISO-8859-", 9))
421 code_conv = conv_latintodisp;
423 else if (!strcasecmp(charset, CS_SHIFT_JIS) ||
424 !strcasecmp(charset, "SHIFT-JIS") ||
425 !strcasecmp(charset, "SJIS") ||
426 !strcasecmp(charset, "X-SJIS"))
427 code_conv = conv_sjistodisp;
428 else if (!strcasecmp(charset, CS_EUC_JP) ||
429 !strcasecmp(charset, "EUCJP"))
430 code_conv = conv_euctodisp;
432 code_conv = conv_noconv;
437 static const struct {
441 {C_US_ASCII, CS_US_ASCII},
443 {C_ISO_8859_1, CS_ISO_8859_1},
444 {C_ISO_8859_2, CS_ISO_8859_2},
445 {C_ISO_8859_4, CS_ISO_8859_4},
446 {C_ISO_8859_5, CS_ISO_8859_5},
447 {C_ISO_8859_7, CS_ISO_8859_7},
448 {C_ISO_8859_8, CS_ISO_8859_8},
449 {C_ISO_8859_9, CS_ISO_8859_9},
450 {C_ISO_8859_13, CS_ISO_8859_13},
451 {C_ISO_8859_15, CS_ISO_8859_15},
452 {C_BALTIC, CS_BALTIC},
453 {C_CP1251, CS_CP1251},
454 {C_WINDOWS_1251, CS_WINDOWS_1251},
455 {C_KOI8_R, CS_KOI8_R},
456 {C_KOI8_U, CS_KOI8_U},
457 {C_ISO_2022_JP, CS_ISO_2022_JP},
458 {C_ISO_2022_JP_2, CS_ISO_2022_JP_2},
459 {C_EUC_JP, CS_EUC_JP},
460 {C_SHIFT_JIS, CS_SHIFT_JIS},
461 {C_ISO_2022_KR, CS_ISO_2022_KR},
462 {C_EUC_KR, CS_EUC_KR},
463 {C_ISO_2022_CN, CS_ISO_2022_CN},
464 {C_EUC_CN, CS_EUC_CN},
465 {C_GB2312, CS_GB2312},
466 {C_EUC_TW, CS_EUC_TW},
471 static const struct {
475 {"ja_JP.eucJP" , C_EUC_JP},
476 {"ja_JP.ujis" , C_EUC_JP},
477 {"ja_JP.EUC" , C_EUC_JP},
478 {"ja_JP.SJIS" , C_SHIFT_JIS},
479 {"ja_JP.JIS" , C_ISO_2022_JP},
480 {"ja_JP" , C_EUC_JP},
481 {"ko_KR" , C_EUC_KR},
482 {"zh_CN.GB2312" , C_GB2312},
483 {"zh_CN" , C_GB2312},
484 {"zh_TW.eucTW" , C_EUC_TW},
485 {"zh_TW.Big5" , C_BIG5},
488 {"ru_RU.KOI8-R" , C_KOI8_R},
489 {"ru_RU.CP1251" , C_CP1251},
491 {"en_US" , C_ISO_8859_1},
492 {"ca_ES" , C_ISO_8859_1},
493 {"da_DK" , C_ISO_8859_1},
494 {"de_DE" , C_ISO_8859_1},
495 {"nl_NL" , C_ISO_8859_1},
496 {"et_EE" , C_ISO_8859_1},
497 {"fi_FI" , C_ISO_8859_1},
498 {"fr_FR" , C_ISO_8859_1},
499 {"is_IS" , C_ISO_8859_1},
500 {"it_IT" , C_ISO_8859_1},
501 {"no_NO" , C_ISO_8859_1},
502 {"pt_PT" , C_ISO_8859_1},
503 {"pt_BR" , C_ISO_8859_1},
504 {"es_ES" , C_ISO_8859_1},
505 {"sv_SE" , C_ISO_8859_1},
507 {"hr_HR" , C_ISO_8859_2},
508 {"hu_HU" , C_ISO_8859_2},
509 {"pl_PL" , C_ISO_8859_2},
510 {"ro_RO" , C_ISO_8859_2},
511 {"sk_SK" , C_ISO_8859_2},
512 {"sl_SI" , C_ISO_8859_2},
513 {"ru_RU" , C_ISO_8859_5},
514 {"el_GR" , C_ISO_8859_7},
515 {"iw_IL" , C_ISO_8859_8},
516 {"tr_TR" , C_ISO_8859_9},
518 {"lt_LT.iso88594" , C_ISO_8859_4},
519 {"lt_LT.ISO8859-4" , C_ISO_8859_4},
520 {"lt_LT.ISO_8859-4" , C_ISO_8859_4},
521 {"lt_LT" , C_ISO_8859_13},
522 {"lv_LV" , C_ISO_8859_13},
525 {"POSIX" , C_US_ASCII},
527 #endif /* !HAVE_LIBJCONV */
529 const gchar *conv_get_charset_str(CharSet charset)
533 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
534 if (charsets[i].charset == charset)
535 return charsets[i].name;
541 CharSet conv_get_charset_from_str(const gchar *charset)
545 if (!charset) return C_AUTO;
547 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
548 if (!strcasecmp(charsets[i].name, charset))
549 return charsets[i].charset;
555 CharSet conv_get_current_charset(void)
557 static CharSet cur_charset = -1;
561 const gchar *cur_codeset;
563 const gchar *cur_locale;
566 if (cur_charset != -1)
570 cur_codeset = jconv_info_get_current_codeset();
571 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
572 if (!strcasecmp(cur_codeset, charsets[i].name)) {
573 cur_charset = charsets[i].charset;
578 cur_locale = g_getenv("LC_ALL");
579 if (!cur_locale) cur_locale = g_getenv("LC_CTYPE");
580 if (!cur_locale) cur_locale = g_getenv("LANG");
581 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
583 debug_print("current locale: %s\n",
584 cur_locale ? cur_locale : "(none)");
587 cur_charset = C_US_ASCII;
591 if (strcasestr(cur_locale, "UTF-8")) {
592 cur_charset = C_UTF_8;
596 for (i = 0; i < sizeof(locale_table) / sizeof(locale_table[0]); i++) {
599 /* "ja_JP.EUC" matches with "ja_JP.eucJP" and "ja_JP.EUC" */
600 /* "ja_JP" matches with "ja_JP.xxxx" and "ja" */
601 if (!strncasecmp(cur_locale, locale_table[i].locale,
602 strlen(locale_table[i].locale))) {
603 cur_charset = locale_table[i].charset;
605 } else if ((p = strchr(locale_table[i].locale, '_')) &&
606 !strchr(p + 1, '.')) {
607 if (strlen(cur_locale) == 2 &&
608 !strncasecmp(cur_locale, locale_table[i].locale, 2)) {
609 cur_charset = locale_table[i].charset;
616 cur_charset = C_AUTO;
620 const gchar *conv_get_current_charset_str(void)
623 return jconv_info_get_current_codeset();
625 static const gchar *codeset = NULL;
628 codeset = conv_get_charset_str(conv_get_current_charset());
630 return codeset ? codeset : "US-ASCII";
634 CharSet conv_get_outgoing_charset(void)
636 static CharSet out_charset = -1;
639 gint i, j, n_pref_codesets;
640 const gchar *const *pref_codesets;
645 if (out_charset != -1)
649 /* skip US-ASCII and UTF-8 */
650 pref_codesets = jconv_info_get_pref_codesets(&n_pref_codesets);
651 for (i = 0; i < n_pref_codesets; i++) {
652 for (j = 2; j < sizeof(charsets) / sizeof(charsets[0]); j++) {
653 if (!strcasecmp(pref_codesets[i], charsets[j].name)) {
654 out_charset = charsets[j].charset;
660 for (i = 0; i < n_pref_codesets; i++) {
661 if (!strcasecmp(pref_codesets[i], "UTF-8")) {
662 out_charset = C_UTF_8;
667 out_charset = C_AUTO;
669 cur_charset = conv_get_current_charset();
670 switch (cur_charset) {
673 out_charset = C_ISO_2022_JP;
676 out_charset = cur_charset;
683 const gchar *conv_get_outgoing_charset_str(void)
688 if (prefs_common.outgoing_charset) {
689 if (!isalpha(prefs_common.outgoing_charset[0])) {
690 g_free(prefs_common.outgoing_charset);
691 prefs_common.outgoing_charset = g_strdup(CS_AUTO);
692 } else if (strcmp(prefs_common.outgoing_charset, CS_AUTO) != 0)
693 return prefs_common.outgoing_charset;
696 out_charset = conv_get_outgoing_charset();
697 str = conv_get_charset_str(out_charset);
699 return str ? str : "US-ASCII";
702 void conv_unmime_header_overwrite(gchar *str)
708 cur_charset = conv_get_current_charset();
711 Xstrdup_a(buf, str, return);
712 outlen = strlen(str) + 1;
713 UnMimeHeaderConv(buf, str, outlen);
714 if (cur_charset == C_EUC_JP) {
718 len = strlen(str) * 2 + 1;
719 Xalloca(tmp, len, return);
720 conv_jistodisp(tmp, len, str);
721 strncpy2(str, tmp, outlen);
724 if (cur_charset == C_EUC_JP) {
728 Xstrdup_a(buf, str, return);
729 outlen = strlen(str) + 1;
731 len = strlen(buf) * 2 + 1;
732 Xalloca(tmp, len, {strncpy2(str, buf, outlen); return;});
733 conv_jistodisp(tmp, len, buf);
734 strncpy2(str, tmp, outlen);
740 void conv_unmime_header(gchar *outbuf, gint outlen, const gchar *str,
741 const gchar *charset)
746 cur_charset = conv_get_current_charset();
747 Xstrdup_a(buf, str, return);
750 UnMimeHeaderConv(buf, outbuf, outlen);
753 strncpy2(outbuf, buf, outlen);
755 if (cur_charset == C_EUC_JP) {
758 len = strlen(outbuf) * 2 + 1;
759 Xalloca(buf, len, return);
760 conv_jistodisp(buf, len, outbuf);
761 strncpy2(outbuf, buf, outlen);
765 #define MAX_ENCLEN 75
766 #define MAX_LINELEN 76
768 #define B64LEN(len) ((len) / 3 * 4 + ((len) % 3 ? 4 : 0))
771 void conv_encode_header(gchar *dest, gint len, const gchar *src,
777 size_t line_len, mimehdr_len, mimehdr_begin_len;
778 gchar *mimehdr_init = "=?";
779 gchar *mimehdr_end = "?=";
780 gchar *mimehdr_enctype = "?B?";
781 const gchar *mimehdr_charset;
783 /* g_print("src = %s\n", src); */
784 mimehdr_charset = conv_get_outgoing_charset_str();
786 /* convert to wide-character string */
787 wsrcp = wsrc = strdup_mbstowcs(src);
789 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
790 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
791 mimehdr_begin_len = strlen(mimehdr_init) +
792 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
794 line_len = header_len;
798 g_return_if_fail(wsrc != NULL);
801 wchar_t *wp, *wtmp, *wtmpp;
804 /* irresponsible buffer overrun check */
805 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
807 /* encode string including space
808 if non-ASCII string follows */
809 if (is_next_nonascii(wsrcp)) {
811 while ((wp = find_wspace(wp)) != NULL)
812 if (!is_next_nonascii(wp)) break;
814 wp = find_wspace(wsrcp);
817 wtmp = wcsndup(wsrcp, wp - wsrcp);
819 while (iswspace(wsrcp[nspc])) nspc++;
821 wtmp = wcsdup(wsrcp);
822 wsrcp += wcslen(wsrcp);
828 gint tlen = 0, str_ascii = 1;
829 gchar *tmp; /* internal codeset */
830 gchar *raw; /* converted, but not base64 encoded */
831 register gchar *tmpp;
834 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
839 while (*wtmpp != (wchar_t)0) {
842 gchar *raw_new = NULL;
844 const gchar *src_codeset;
846 if (*wtmpp < 32 || *wtmpp >= 127)
848 mbl = wctomb(tmpp, *wtmpp);
850 g_warning("invalid wide character\n");
855 src_codeset = conv_get_current_charset_str();
856 /* printf ("tmp = %s, tlen = %d, mbl\n",
858 if (jconv_alloc_conv(tmp, tlen + mbl,
859 &raw_new, &raw_new_len,
861 &dummy, mimehdr_charset)
863 g_warning("can't convert\n");
868 gint dlen = mimehdr_len +
870 if ((line_len + dlen +
871 (*(wtmpp + 1) ? 0 : nspc) +
872 (line_len > 1 ? 1 : 0))
886 } else if ((line_len + tlen + mbl +
887 (*(wtmpp + 1) ? 0 : nspc) +
888 (line_len > 1 ? 1 : 0))
892 (*(wtmpp + 1) ? 0 : nspc)
910 raw_len = raw_new_len;
915 g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
916 tmp, tlen, mb_seqlen);
919 if (tlen == 0 || raw_len == 0) {
925 if (line_len > 1 && destp > dest) {
932 g_snprintf(destp, len - strlen(dest), "%s%s%s",
933 mimehdr_init, mimehdr_charset,
935 destp += mimehdr_begin_len;
936 line_len += mimehdr_begin_len;
938 to64frombits(destp, raw, raw_len);
939 line_len += strlen(destp);
940 destp += strlen(destp);
942 strcpy(destp, mimehdr_end);
943 destp += strlen(mimehdr_end);
944 line_len += strlen(mimehdr_end);
947 line_len += strlen(destp);
948 destp += strlen(destp);
953 /* g_print("line_len = %d\n\n", line_len); */
954 } while (*wtmpp != (wchar_t)0);
956 while (iswspace(*wsrcp)) {
959 mbl = wctomb(destp, *wsrcp++);
972 /* g_print("dest = %s\n", dest); */
974 #else /* !HAVE_LIBJCONV */
978 void conv_encode_header(gchar *dest, gint len, const gchar *src,
984 size_t line_len, mimehdr_len, mimehdr_begin_len;
985 gchar *mimehdr_init = "=?";
986 gchar *mimehdr_end = "?=";
987 gchar *mimehdr_enctype = "?B?";
988 const gchar *mimehdr_charset;
990 /* g_print("src = %s\n", src); */
991 mimehdr_charset = conv_get_outgoing_charset_str();
992 if (strcmp(mimehdr_charset, "ISO-2022-JP") != 0) {
993 /* currently only supports Japanese */
994 strncpy2(dest, src, len);
998 /* convert to wide-character string */
999 wsrcp = wsrc = strdup_mbstowcs(src);
1001 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
1002 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1003 mimehdr_begin_len = strlen(mimehdr_init) +
1004 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1006 line_len = header_len;
1010 g_return_if_fail(wsrc != NULL);
1013 wchar_t *wp, *wtmp, *wtmpp;
1016 /* irresponsible buffer overrun check */
1017 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
1019 /* encode string including space
1020 if non-ASCII string follows */
1021 if (is_next_nonascii(wsrcp)) {
1023 while ((wp = find_wspace(wp)) != NULL)
1024 if (!is_next_nonascii(wp)) break;
1026 wp = find_wspace(wsrcp);
1029 wtmp = wcsndup(wsrcp, wp - wsrcp);
1031 while (iswspace(wsrcp[nspc])) nspc++;
1033 wtmp = wcsdup(wsrcp);
1034 wsrcp += wcslen(wsrcp);
1040 gint prev_mbl = 1, tlen = 0, mb_seqlen = 0;
1042 register gchar *tmpp;
1044 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
1047 while (*wtmpp != (wchar_t)0) {
1050 mbl = wctomb(tmpp, *wtmpp);
1052 g_warning("invalid wide character\n");
1057 /* length of KI + KO */
1058 if (prev_mbl == 1 && mbl == 2)
1059 mb_seqlen += JIS_SEQLEN * 2;
1062 gint dlen = mimehdr_len +
1063 B64LEN(tlen + mb_seqlen + mbl);
1065 if ((line_len + dlen +
1066 (*(wtmpp + 1) ? 0 : nspc) +
1067 (line_len > 1 ? 1 : 0))
1080 } else if ((line_len + tlen + mbl +
1081 (*(wtmpp + 1) ? 0 : nspc) +
1082 (line_len > 1 ? 1 : 0))
1084 if (1 + tlen + mbl +
1085 (*(wtmpp + 1) ? 0 : nspc)
1104 /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
1105 tmp, tlen, mb_seqlen);
1113 if (line_len > 1 && destp > dest) {
1122 tmp_jis = g_new(gchar, tlen + mb_seqlen + 1);
1123 conv_euctojis(tmp_jis,
1124 tlen + mb_seqlen + 1, tmp);
1125 g_snprintf(destp, len - strlen(dest), "%s%s%s",
1126 mimehdr_init, mimehdr_charset,
1128 destp += mimehdr_begin_len;
1129 line_len += mimehdr_begin_len;
1131 to64frombits(destp, tmp_jis, strlen(tmp_jis));
1132 line_len += strlen(destp);
1133 destp += strlen(destp);
1135 strcpy(destp, mimehdr_end);
1136 destp += strlen(mimehdr_end);
1137 line_len += strlen(mimehdr_end);
1142 line_len += strlen(destp);
1143 destp += strlen(destp);
1147 /* g_print("line_len = %d\n\n", line_len); */
1148 } while (*wtmpp != (wchar_t)0);
1150 while (iswspace(*wsrcp)) {
1153 mbl = wctomb(destp, *wsrcp++);
1166 /* g_print("dest = %s\n", dest); */
1168 #endif /* HAVE_LIBJCONV */