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_13, CS_ISO_8859_13},
461 {C_ISO_8859_15, CS_ISO_8859_15},
462 {C_BALTIC, CS_BALTIC},
463 {C_CP1251, CS_CP1251},
464 {C_WINDOWS_1251, CS_WINDOWS_1251},
465 {C_KOI8_R, CS_KOI8_R},
466 {C_KOI8_U, CS_KOI8_U},
467 {C_ISO_2022_JP, CS_ISO_2022_JP},
468 {C_ISO_2022_JP_2, CS_ISO_2022_JP_2},
469 {C_EUC_JP, CS_EUC_JP},
470 {C_EUC_JP, CS_EUCJP},
471 {C_SHIFT_JIS, CS_SHIFT_JIS},
472 {C_ISO_2022_KR, CS_ISO_2022_KR},
473 {C_EUC_KR, CS_EUC_KR},
474 {C_ISO_2022_CN, CS_ISO_2022_CN},
475 {C_EUC_CN, CS_EUC_CN},
476 {C_GB2312, CS_GB2312},
477 {C_EUC_TW, CS_EUC_TW},
482 static const struct {
486 {"ja_JP.eucJP" , C_EUC_JP},
487 {"ja_JP.ujis" , C_EUC_JP},
488 {"ja_JP.EUC" , C_EUC_JP},
489 {"ja_JP.SJIS" , C_SHIFT_JIS},
490 {"ja_JP.JIS" , C_ISO_2022_JP},
491 {"ja_JP" , C_EUC_JP},
492 {"ko_KR" , C_EUC_KR},
493 {"zh_CN.GB2312" , C_GB2312},
494 {"zh_CN" , C_GB2312},
495 {"zh_TW.eucTW" , C_EUC_TW},
496 {"zh_TW.Big5" , C_BIG5},
499 {"ru_RU.KOI8-R" , C_KOI8_R},
500 {"ru_RU.CP1251" , C_CP1251},
502 {"en_US" , C_ISO_8859_1},
503 {"ca_ES" , C_ISO_8859_1},
504 {"da_DK" , C_ISO_8859_1},
505 {"de_DE" , C_ISO_8859_1},
506 {"nl_NL" , C_ISO_8859_1},
507 {"et_EE" , C_ISO_8859_1},
508 {"fi_FI" , C_ISO_8859_1},
509 {"fr_FR" , C_ISO_8859_1},
510 {"is_IS" , C_ISO_8859_1},
511 {"it_IT" , C_ISO_8859_1},
512 {"no_NO" , C_ISO_8859_1},
513 {"pt_PT" , C_ISO_8859_1},
514 {"pt_BR" , C_ISO_8859_1},
515 {"es_ES" , C_ISO_8859_1},
516 {"sv_SE" , C_ISO_8859_1},
518 {"hr_HR" , C_ISO_8859_2},
519 {"hu_HU" , C_ISO_8859_2},
520 {"pl_PL" , C_ISO_8859_2},
521 {"ro_RO" , C_ISO_8859_2},
522 {"sk_SK" , C_ISO_8859_2},
523 {"sl_SI" , C_ISO_8859_2},
524 {"ru_RU" , C_ISO_8859_5},
525 {"el_GR" , C_ISO_8859_7},
526 {"iw_IL" , C_ISO_8859_8},
527 {"tr_TR" , C_ISO_8859_9},
529 {"lt_LT.iso88594" , C_ISO_8859_4},
530 {"lt_LT.ISO8859-4" , C_ISO_8859_4},
531 {"lt_LT.ISO_8859-4" , C_ISO_8859_4},
532 {"lt_LT" , C_ISO_8859_13},
533 {"lv_LV" , C_ISO_8859_13},
536 {"POSIX" , C_US_ASCII},
537 {"ANSI_X3.4-1968" , C_US_ASCII},
539 #endif /* !HAVE_LIBJCONV */
541 const gchar *conv_get_charset_str(CharSet charset)
545 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
546 if (charsets[i].charset == charset)
547 return charsets[i].name;
553 CharSet conv_get_charset_from_str(const gchar *charset)
557 if (!charset) return C_AUTO;
559 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
560 if (!strcasecmp(charsets[i].name, charset))
561 return charsets[i].charset;
567 CharSet conv_get_current_charset(void)
569 static CharSet cur_charset = -1;
573 const gchar *cur_codeset;
575 const gchar *cur_locale;
578 if (cur_charset != -1)
582 cur_codeset = jconv_info_get_current_codeset();
583 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
584 if (!strcasecmp(cur_codeset, charsets[i].name)) {
585 cur_charset = charsets[i].charset;
590 cur_locale = g_getenv("LC_ALL");
591 if (!cur_locale) cur_locale = g_getenv("LC_CTYPE");
592 if (!cur_locale) cur_locale = g_getenv("LANG");
593 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
595 debug_print("current locale: %s\n",
596 cur_locale ? cur_locale : "(none)");
599 cur_charset = C_US_ASCII;
603 if (strcasestr(cur_locale, "UTF-8")) {
604 cur_charset = C_UTF_8;
608 for (i = 0; i < sizeof(locale_table) / sizeof(locale_table[0]); i++) {
611 /* "ja_JP.EUC" matches with "ja_JP.eucJP" and "ja_JP.EUC" */
612 /* "ja_JP" matches with "ja_JP.xxxx" and "ja" */
613 if (!strncasecmp(cur_locale, locale_table[i].locale,
614 strlen(locale_table[i].locale))) {
615 cur_charset = locale_table[i].charset;
617 } else if ((p = strchr(locale_table[i].locale, '_')) &&
618 !strchr(p + 1, '.')) {
619 if (strlen(cur_locale) == 2 &&
620 !strncasecmp(cur_locale, locale_table[i].locale, 2)) {
621 cur_charset = locale_table[i].charset;
628 cur_charset = C_AUTO;
632 const gchar *conv_get_current_charset_str(void)
634 static const gchar *codeset = NULL;
637 codeset = conv_get_charset_str(conv_get_current_charset());
639 return codeset ? codeset : "US-ASCII";
642 CharSet conv_get_outgoing_charset(void)
644 static CharSet out_charset = -1;
647 gint i, j, n_pref_codesets;
648 const gchar *const *pref_codesets;
653 if (out_charset != -1)
657 /* skip US-ASCII and UTF-8 */
658 pref_codesets = jconv_info_get_pref_codesets(&n_pref_codesets);
659 for (i = 0; i < n_pref_codesets; i++) {
660 for (j = 3; j < sizeof(charsets) / sizeof(charsets[0]); j++) {
661 if (!strcasecmp(pref_codesets[i], charsets[j].name)) {
662 out_charset = charsets[j].charset;
668 for (i = 0; i < n_pref_codesets; i++) {
669 if (!strcasecmp(pref_codesets[i], "UTF-8")) {
670 out_charset = C_UTF_8;
675 out_charset = C_AUTO;
677 cur_charset = conv_get_current_charset();
678 switch (cur_charset) {
681 out_charset = C_ISO_2022_JP;
684 out_charset = cur_charset;
691 const gchar *conv_get_outgoing_charset_str(void)
696 if (prefs_common.outgoing_charset) {
697 if (!isalpha(prefs_common.outgoing_charset[0])) {
698 g_free(prefs_common.outgoing_charset);
699 prefs_common.outgoing_charset = g_strdup(CS_AUTO);
700 } else if (strcmp(prefs_common.outgoing_charset, CS_AUTO) != 0)
701 return prefs_common.outgoing_charset;
704 out_charset = conv_get_outgoing_charset();
705 str = conv_get_charset_str(out_charset);
707 return str ? str : "US-ASCII";
710 const gchar *conv_get_current_locale(void)
714 cur_locale = g_getenv("LC_ALL");
715 if (!cur_locale) cur_locale = g_getenv("LANG");
716 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
718 debug_print("current locale: %s\n",
719 cur_locale ? cur_locale : "(none)");
724 void conv_unmime_header_overwrite(gchar *str)
730 cur_charset = conv_get_current_charset();
733 Xstrdup_a(buf, str, return);
734 outlen = strlen(str) + 1;
735 UnMimeHeaderConv(buf, str, outlen);
736 if (cur_charset == C_EUC_JP) {
740 len = strlen(str) * 2 + 1;
741 Xalloca(tmp, len, return);
742 conv_jistodisp(tmp, len, str);
743 strncpy2(str, tmp, outlen);
746 if (cur_charset == C_EUC_JP) {
750 Xstrdup_a(buf, str, return);
751 outlen = strlen(str) + 1;
753 len = strlen(buf) * 2 + 1;
754 Xalloca(tmp, len, {strncpy2(str, buf, outlen); return;});
755 conv_jistodisp(tmp, len, buf);
756 strncpy2(str, tmp, outlen);
762 void conv_unmime_header(gchar *outbuf, gint outlen, const gchar *str,
763 const gchar *charset)
768 cur_charset = conv_get_current_charset();
769 Xstrdup_a(buf, str, return);
772 UnMimeHeaderConv(buf, outbuf, outlen);
775 strncpy2(outbuf, buf, outlen);
777 if (cur_charset == C_EUC_JP) {
780 len = strlen(outbuf) * 2 + 1;
781 Xalloca(buf, len, return);
782 conv_jistodisp(buf, len, outbuf);
783 strncpy2(outbuf, buf, outlen);
787 #define MAX_ENCLEN 75
788 #define MAX_LINELEN 76
790 #define B64LEN(len) ((len) / 3 * 4 + ((len) % 3 ? 4 : 0))
793 void conv_encode_header(gchar *dest, gint len, const gchar *src,
799 size_t line_len, mimehdr_len, mimehdr_begin_len;
800 gchar *mimehdr_init = "=?";
801 gchar *mimehdr_end = "?=";
802 gchar *mimehdr_enctype = "?B?";
803 const gchar *mimehdr_charset;
805 /* g_print("src = %s\n", src); */
806 mimehdr_charset = conv_get_outgoing_charset_str();
808 /* convert to wide-character string */
809 wsrcp = wsrc = strdup_mbstowcs(src);
811 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
812 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
813 mimehdr_begin_len = strlen(mimehdr_init) +
814 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
816 line_len = header_len;
820 g_return_if_fail(wsrc != NULL);
823 wchar_t *wp, *wtmp, *wtmpp;
826 /* irresponsible buffer overrun check */
827 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
829 /* encode string including space
830 if non-ASCII string follows */
831 if (is_next_nonascii(wsrcp)) {
833 while ((wp = find_wspace(wp)) != NULL)
834 if (!is_next_nonascii(wp)) break;
836 wp = find_wspace(wsrcp);
839 wtmp = wcsndup(wsrcp, wp - wsrcp);
841 while (iswspace(wsrcp[nspc])) nspc++;
843 wtmp = wcsdup(wsrcp);
844 wsrcp += wcslen(wsrcp);
850 gint tlen = 0, str_ascii = 1;
851 gchar *tmp; /* internal codeset */
852 gchar *raw; /* converted, but not base64 encoded */
853 register gchar *tmpp;
856 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
861 while (*wtmpp != (wchar_t)0) {
864 gchar *raw_new = NULL;
866 const gchar *src_codeset;
868 if (*wtmpp < 32 || *wtmpp >= 127)
870 mbl = wctomb(tmpp, *wtmpp);
872 g_warning("invalid wide character\n");
877 src_codeset = conv_get_current_charset_str();
878 /* printf ("tmp = %s, tlen = %d, mbl\n",
880 if (jconv_alloc_conv(tmp, tlen + mbl,
881 &raw_new, &raw_new_len,
883 &dummy, mimehdr_charset)
885 g_warning("can't convert\n");
891 gint dlen = mimehdr_len +
893 if ((line_len + dlen +
894 (*(wtmpp + 1) ? 0 : nspc) +
895 (line_len > 1 ? 1 : 0))
909 } else if ((line_len + tlen + mbl +
910 (*(wtmpp + 1) ? 0 : nspc) +
911 (line_len > 1 ? 1 : 0))
915 (*(wtmpp + 1) ? 0 : nspc)
933 raw_len = raw_new_len;
938 g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
939 tmp, tlen, mb_seqlen);
942 if (tlen == 0 || raw_len == 0) {
948 if (line_len > 1 && destp > dest) {
955 g_snprintf(destp, len - strlen(dest), "%s%s%s",
956 mimehdr_init, mimehdr_charset,
958 destp += mimehdr_begin_len;
959 line_len += mimehdr_begin_len;
961 to64frombits(destp, raw, raw_len);
962 line_len += strlen(destp);
963 destp += strlen(destp);
965 strcpy(destp, mimehdr_end);
966 destp += strlen(mimehdr_end);
967 line_len += strlen(mimehdr_end);
970 line_len += strlen(destp);
971 destp += strlen(destp);
976 /* g_print("line_len = %d\n\n", line_len); */
977 } while (*wtmpp != (wchar_t)0);
979 while (iswspace(*wsrcp)) {
982 mbl = wctomb(destp, *wsrcp++);
995 /* g_print("dest = %s\n", dest); */
997 #else /* !HAVE_LIBJCONV */
1001 void conv_encode_header(gchar *dest, gint len, const gchar *src,
1007 size_t line_len, mimehdr_len, mimehdr_begin_len;
1008 gchar *mimehdr_init = "=?";
1009 gchar *mimehdr_end = "?=";
1010 gchar *mimehdr_enctype = "?B?";
1011 const gchar *mimehdr_charset;
1013 /* g_print("src = %s\n", src); */
1014 mimehdr_charset = conv_get_outgoing_charset_str();
1015 if (strcmp(mimehdr_charset, "ISO-2022-JP") != 0) {
1016 /* currently only supports Japanese */
1017 strncpy2(dest, src, len);
1021 /* convert to wide-character string */
1022 wsrcp = wsrc = strdup_mbstowcs(src);
1024 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
1025 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1026 mimehdr_begin_len = strlen(mimehdr_init) +
1027 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1029 line_len = header_len;
1033 g_return_if_fail(wsrc != NULL);
1036 wchar_t *wp, *wtmp, *wtmpp;
1039 /* irresponsible buffer overrun check */
1040 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
1042 /* encode string including space
1043 if non-ASCII string follows */
1044 if (is_next_nonascii(wsrcp)) {
1046 while ((wp = find_wspace(wp)) != NULL)
1047 if (!is_next_nonascii(wp)) break;
1049 wp = find_wspace(wsrcp);
1052 wtmp = wcsndup(wsrcp, wp - wsrcp);
1054 while (iswspace(wsrcp[nspc])) nspc++;
1056 wtmp = wcsdup(wsrcp);
1057 wsrcp += wcslen(wsrcp);
1063 gint prev_mbl = 1, tlen = 0, mb_seqlen = 0;
1065 register gchar *tmpp;
1067 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
1070 while (*wtmpp != (wchar_t)0) {
1073 mbl = wctomb(tmpp, *wtmpp);
1075 g_warning("invalid wide character\n");
1080 /* length of KI + KO */
1081 if (prev_mbl == 1 && mbl == 2)
1082 mb_seqlen += JIS_SEQLEN * 2;
1085 gint dlen = mimehdr_len +
1086 B64LEN(tlen + mb_seqlen + mbl);
1088 if ((line_len + dlen +
1089 (*(wtmpp + 1) ? 0 : nspc) +
1090 (line_len > 1 ? 1 : 0))
1103 } else if ((line_len + tlen + mbl +
1104 (*(wtmpp + 1) ? 0 : nspc) +
1105 (line_len > 1 ? 1 : 0))
1107 if (1 + tlen + mbl +
1108 (*(wtmpp + 1) ? 0 : nspc)
1127 /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
1128 tmp, tlen, mb_seqlen);
1136 if (line_len > 1 && destp > dest) {
1145 tmp_jis = g_new(gchar, tlen + mb_seqlen + 1);
1146 conv_euctojis(tmp_jis,
1147 tlen + mb_seqlen + 1, tmp);
1148 g_snprintf(destp, len - strlen(dest), "%s%s%s",
1149 mimehdr_init, mimehdr_charset,
1151 destp += mimehdr_begin_len;
1152 line_len += mimehdr_begin_len;
1154 to64frombits(destp, tmp_jis, strlen(tmp_jis));
1155 line_len += strlen(destp);
1156 destp += strlen(destp);
1158 strcpy(destp, mimehdr_end);
1159 destp += strlen(mimehdr_end);
1160 line_len += strlen(mimehdr_end);
1165 line_len += strlen(destp);
1166 destp += strlen(destp);
1170 /* g_print("line_len = %d\n\n", line_len); */
1171 } while (*wtmpp != (wchar_t)0);
1173 while (iswspace(*wsrcp)) {
1176 mbl = wctomb(destp, *wsrcp++);
1189 /* g_print("dest = %s\n", dest); */
1191 #endif /* HAVE_LIBJCONV */