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)
715 conv_unreadable_eucjp(str);
717 if (cur_charset == C_EUC_JP) {
721 Xstrdup_a(buf, str, {return;});
722 outlen = strlen(str) + 1;
724 len = strlen(buf) * 2 + 1;
725 Xalloca(tmp, len, {strncpy2(str, buf, outlen); return;});
726 conv_jistodisp(tmp, len, buf);
727 strncpy2(str, tmp, outlen);
733 void conv_unmime_header(gchar *outbuf, gint outlen, const gchar *str,
734 const gchar *charset)
739 Xstrdup_a(buf, str, {return;});
740 cur_charset = conv_get_current_charset();
743 UnMimeHeaderConv(buf, outbuf, outlen);
744 if (cur_charset == C_EUC_JP)
745 conv_unreadable_eucjp(outbuf);
748 if (cur_charset == C_EUC_JP) {
752 len = strlen(buf) * 2 + 1;
753 Xalloca(tmp, len, {strncpy2(outbuf, buf, outlen); return;});
754 conv_jistodisp(tmp, len, buf);
755 strncpy2(outbuf, tmp, outlen);
757 strncpy2(outbuf, buf, outlen);
761 #define MAX_ENCLEN 75
762 #define MAX_LINELEN 76
764 #define B64LEN(len) ((len) / 3 * 4 + ((len) % 3 ? 4 : 0))
767 void conv_encode_header(gchar *dest, gint len, const gchar *src,
773 size_t line_len, mimehdr_len, mimehdr_begin_len;
774 gchar *mimehdr_init = "=?";
775 gchar *mimehdr_end = "?=";
776 gchar *mimehdr_enctype = "?B?";
777 const gchar *mimehdr_charset;
779 /* g_print("src = %s\n", src); */
780 mimehdr_charset = conv_get_outgoing_charset_str();
782 /* convert to wide-character string */
783 wsrcp = wsrc = strdup_mbstowcs(src);
785 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
786 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
787 mimehdr_begin_len = strlen(mimehdr_init) +
788 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
790 line_len = header_len;
794 g_return_if_fail(wsrc != NULL);
797 wchar_t *wp, *wtmp, *wtmpp;
800 /* irresponsible buffer overrun check */
801 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
803 /* encode string including space
804 if non-ASCII string follows */
805 if (is_next_nonascii(wsrcp)) {
807 while ((wp = find_wspace(wp)) != NULL)
808 if (!is_next_nonascii(wp)) break;
810 wp = find_wspace(wsrcp);
813 wtmp = wcsndup(wsrcp, wp - wsrcp);
815 while (iswspace(wsrcp[nspc])) nspc++;
817 wtmp = wcsdup(wsrcp);
818 wsrcp += wcslen(wsrcp);
824 gint tlen = 0, str_ascii = 1;
825 gchar *tmp; /* internal codeset */
826 gchar *raw; /* converted, but not base64 encoded */
827 register gchar *tmpp;
830 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
835 while (*wtmpp != (wchar_t)0) {
838 gchar *raw_new = NULL;
840 const gchar *src_codeset;
842 if (*wtmpp < 32 || *wtmpp >= 127)
844 mbl = wctomb(tmpp, *wtmpp);
846 g_warning("invalid wide character\n");
851 src_codeset = conv_get_current_charset_str();
852 /* printf ("tmp = %s, tlen = %d, mbl\n",
854 if (jconv_alloc_conv(tmp, tlen + mbl,
855 &raw_new, &raw_new_len,
857 &dummy, mimehdr_charset)
859 g_warning("can't convert\n");
864 gint dlen = mimehdr_len +
866 if ((line_len + dlen +
867 (*(wtmpp + 1) ? 0 : nspc) +
868 (line_len > 1 ? 1 : 0))
882 } else if ((line_len + tlen + mbl +
883 (*(wtmpp + 1) ? 0 : nspc) +
884 (line_len > 1 ? 1 : 0))
888 (*(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))
1076 } else if ((line_len + tlen + mbl +
1077 (*(wtmpp + 1) ? 0 : nspc) +
1078 (line_len > 1 ? 1 : 0))
1080 if (1 + tlen + mbl +
1081 (*(wtmpp + 1) ? 0 : nspc)
1100 /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
1101 tmp, tlen, mb_seqlen);
1109 if (line_len > 1 && destp > dest) {
1118 tmp_jis = g_new(gchar, tlen + mb_seqlen + 1);
1119 conv_euctojis(tmp_jis,
1120 tlen + mb_seqlen + 1, tmp);
1121 g_snprintf(destp, len - strlen(dest), "%s%s%s",
1122 mimehdr_init, mimehdr_charset,
1124 destp += mimehdr_begin_len;
1125 line_len += mimehdr_begin_len;
1127 to64frombits(destp, tmp_jis, strlen(tmp_jis));
1128 line_len += strlen(destp);
1129 destp += strlen(destp);
1131 strcpy(destp, mimehdr_end);
1132 destp += strlen(mimehdr_end);
1133 line_len += strlen(mimehdr_end);
1138 line_len += strlen(destp);
1139 destp += strlen(destp);
1143 /* g_print("line_len = %d\n\n", line_len); */
1144 } while (*wtmpp != (wchar_t)0);
1146 while (iswspace(*wsrcp)) {
1149 mbl = wctomb(destp, *wsrcp++);
1162 /* g_print("dest = %s\n", dest); */
1164 #endif /* HAVE_LIBJCONV */