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_11, CS_ISO_8859_11},
461 {C_ISO_8859_13, CS_ISO_8859_13},
462 {C_ISO_8859_15, CS_ISO_8859_15},
463 {C_BALTIC, CS_BALTIC},
464 {C_CP1251, CS_CP1251},
465 {C_WINDOWS_1251, CS_WINDOWS_1251},
466 {C_KOI8_R, CS_KOI8_R},
467 {C_KOI8_U, CS_KOI8_U},
468 {C_ISO_2022_JP, CS_ISO_2022_JP},
469 {C_ISO_2022_JP_2, CS_ISO_2022_JP_2},
470 {C_EUC_JP, CS_EUC_JP},
471 {C_EUC_JP, CS_EUCJP},
472 {C_SHIFT_JIS, CS_SHIFT_JIS},
473 {C_ISO_2022_KR, CS_ISO_2022_KR},
474 {C_EUC_KR, CS_EUC_KR},
475 {C_ISO_2022_CN, CS_ISO_2022_CN},
476 {C_EUC_CN, CS_EUC_CN},
477 {C_GB2312, CS_GB2312},
478 {C_EUC_TW, CS_EUC_TW},
480 {C_TIS_620, CS_TIS_620},
481 {C_WINDOWS_874, CS_WINDOWS_874},
485 static const struct {
489 {"ja_JP.eucJP" , C_EUC_JP},
490 {"ja_JP.ujis" , C_EUC_JP},
491 {"ja_JP.EUC" , C_EUC_JP},
492 {"ja_JP.SJIS" , C_SHIFT_JIS},
493 {"ja_JP.JIS" , C_ISO_2022_JP},
494 {"ja_JP" , C_EUC_JP},
495 {"ko_KR" , C_EUC_KR},
496 {"zh_CN.GB2312" , C_GB2312},
497 {"zh_CN" , C_GB2312},
498 {"zh_TW.eucTW" , C_EUC_TW},
499 {"zh_TW.Big5" , C_BIG5},
502 {"ru_RU.KOI8-R" , C_KOI8_R},
503 {"ru_RU.CP1251" , C_CP1251},
505 {"en_US" , C_ISO_8859_1},
506 {"ca_ES" , C_ISO_8859_1},
507 {"da_DK" , C_ISO_8859_1},
508 {"de_DE" , C_ISO_8859_1},
509 {"nl_NL" , C_ISO_8859_1},
510 {"et_EE" , C_ISO_8859_1},
511 {"fi_FI" , C_ISO_8859_1},
512 {"fr_FR" , C_ISO_8859_1},
513 {"is_IS" , C_ISO_8859_1},
514 {"it_IT" , C_ISO_8859_1},
515 {"no_NO" , C_ISO_8859_1},
516 {"pt_PT" , C_ISO_8859_1},
517 {"pt_BR" , C_ISO_8859_1},
518 {"es_ES" , C_ISO_8859_1},
519 {"sv_SE" , C_ISO_8859_1},
521 {"hr_HR" , C_ISO_8859_2},
522 {"hu_HU" , C_ISO_8859_2},
523 {"pl_PL" , C_ISO_8859_2},
524 {"ro_RO" , C_ISO_8859_2},
525 {"sk_SK" , C_ISO_8859_2},
526 {"sl_SI" , C_ISO_8859_2},
527 {"ru_RU" , C_ISO_8859_5},
528 {"el_GR" , C_ISO_8859_7},
529 {"iw_IL" , C_ISO_8859_8},
530 {"tr_TR" , C_ISO_8859_9},
531 {"th_TH" , C_ISO_8859_11},
533 {"lt_LT.iso88594" , C_ISO_8859_4},
534 {"lt_LT.ISO8859-4" , C_ISO_8859_4},
535 {"lt_LT.ISO_8859-4" , C_ISO_8859_4},
536 {"lt_LT" , C_ISO_8859_13},
537 {"lv_LV" , C_ISO_8859_13},
540 {"POSIX" , C_US_ASCII},
541 {"ANSI_X3.4-1968" , C_US_ASCII},
543 #endif /* !HAVE_LIBJCONV */
545 const gchar *conv_get_charset_str(CharSet charset)
549 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
550 if (charsets[i].charset == charset)
551 return charsets[i].name;
557 CharSet conv_get_charset_from_str(const gchar *charset)
561 if (!charset) return C_AUTO;
563 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
564 if (!strcasecmp(charsets[i].name, charset))
565 return charsets[i].charset;
571 CharSet conv_get_current_charset(void)
573 static CharSet cur_charset = -1;
577 const gchar *cur_codeset;
579 const gchar *cur_locale;
582 if (cur_charset != -1)
586 cur_codeset = jconv_info_get_current_codeset();
587 for (i = 0; i < sizeof(charsets) / sizeof(charsets[0]); i++) {
588 if (!strcasecmp(cur_codeset, charsets[i].name)) {
589 cur_charset = charsets[i].charset;
594 cur_locale = g_getenv("LC_ALL");
595 if (!cur_locale) cur_locale = g_getenv("LC_CTYPE");
596 if (!cur_locale) cur_locale = g_getenv("LANG");
597 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
599 debug_print("current locale: %s\n",
600 cur_locale ? cur_locale : "(none)");
603 cur_charset = C_US_ASCII;
607 if (strcasestr(cur_locale, "UTF-8")) {
608 cur_charset = C_UTF_8;
612 for (i = 0; i < sizeof(locale_table) / sizeof(locale_table[0]); i++) {
615 /* "ja_JP.EUC" matches with "ja_JP.eucJP" and "ja_JP.EUC" */
616 /* "ja_JP" matches with "ja_JP.xxxx" and "ja" */
617 if (!strncasecmp(cur_locale, locale_table[i].locale,
618 strlen(locale_table[i].locale))) {
619 cur_charset = locale_table[i].charset;
621 } else if ((p = strchr(locale_table[i].locale, '_')) &&
622 !strchr(p + 1, '.')) {
623 if (strlen(cur_locale) == 2 &&
624 !strncasecmp(cur_locale, locale_table[i].locale, 2)) {
625 cur_charset = locale_table[i].charset;
632 cur_charset = C_AUTO;
636 const gchar *conv_get_current_charset_str(void)
638 static const gchar *codeset = NULL;
641 codeset = conv_get_charset_str(conv_get_current_charset());
643 return codeset ? codeset : "US-ASCII";
646 CharSet conv_get_outgoing_charset(void)
648 static CharSet out_charset = -1;
651 gint i, j, n_pref_codesets;
652 const gchar *const *pref_codesets;
657 if (out_charset != -1)
661 /* skip US-ASCII and UTF-8 */
662 pref_codesets = jconv_info_get_pref_codesets(&n_pref_codesets);
663 for (i = 0; i < n_pref_codesets; i++) {
664 for (j = 3; j < sizeof(charsets) / sizeof(charsets[0]); j++) {
665 if (!strcasecmp(pref_codesets[i], charsets[j].name)) {
666 out_charset = charsets[j].charset;
672 for (i = 0; i < n_pref_codesets; i++) {
673 if (!strcasecmp(pref_codesets[i], "UTF-8")) {
674 out_charset = C_UTF_8;
679 out_charset = C_AUTO;
681 cur_charset = conv_get_current_charset();
682 switch (cur_charset) {
685 out_charset = C_ISO_2022_JP;
688 out_charset = cur_charset;
695 const gchar *conv_get_outgoing_charset_str(void)
700 if (prefs_common.outgoing_charset) {
701 if (!isalpha(prefs_common.outgoing_charset[0])) {
702 g_free(prefs_common.outgoing_charset);
703 prefs_common.outgoing_charset = g_strdup(CS_AUTO);
704 } else if (strcmp(prefs_common.outgoing_charset, CS_AUTO) != 0)
705 return prefs_common.outgoing_charset;
708 out_charset = conv_get_outgoing_charset();
709 str = conv_get_charset_str(out_charset);
711 return str ? str : "US-ASCII";
714 const gchar *conv_get_current_locale(void)
718 cur_locale = g_getenv("LC_ALL");
719 if (!cur_locale) cur_locale = g_getenv("LANG");
720 if (!cur_locale) cur_locale = setlocale(LC_CTYPE, NULL);
722 debug_print("current locale: %s\n",
723 cur_locale ? cur_locale : "(none)");
728 void conv_unmime_header_overwrite(gchar *str)
734 cur_charset = conv_get_current_charset();
737 Xstrdup_a(buf, str, return);
738 outlen = strlen(str) + 1;
739 UnMimeHeaderConv(buf, str, outlen);
740 if (cur_charset == C_EUC_JP) {
744 len = strlen(str) * 2 + 1;
745 Xalloca(tmp, len, return);
746 conv_jistodisp(tmp, len, str);
747 strncpy2(str, tmp, outlen);
750 if (cur_charset == C_EUC_JP) {
754 Xstrdup_a(buf, str, return);
755 outlen = strlen(str) + 1;
757 len = strlen(buf) * 2 + 1;
758 Xalloca(tmp, len, {strncpy2(str, buf, outlen); return;});
759 conv_jistodisp(tmp, len, buf);
760 strncpy2(str, tmp, outlen);
766 void conv_unmime_header(gchar *outbuf, gint outlen, const gchar *str,
767 const gchar *charset)
772 cur_charset = conv_get_current_charset();
773 Xstrdup_a(buf, str, return);
776 UnMimeHeaderConv(buf, outbuf, outlen);
779 strncpy2(outbuf, buf, outlen);
781 if (cur_charset == C_EUC_JP) {
784 len = strlen(outbuf) * 2 + 1;
785 Xalloca(buf, len, return);
786 conv_jistodisp(buf, len, outbuf);
787 strncpy2(outbuf, buf, outlen);
791 #define MAX_ENCLEN 75
792 #define MAX_LINELEN 76
794 #define B64LEN(len) ((len) / 3 * 4 + ((len) % 3 ? 4 : 0))
797 void conv_encode_header(gchar *dest, gint len, const gchar *src,
803 size_t line_len, mimehdr_len, mimehdr_begin_len;
804 gchar *mimehdr_init = "=?";
805 gchar *mimehdr_end = "?=";
806 gchar *mimehdr_enctype = "?B?";
807 const gchar *mimehdr_charset;
809 /* g_print("src = %s\n", src); */
810 mimehdr_charset = conv_get_outgoing_charset_str();
812 /* convert to wide-character string */
813 wsrcp = wsrc = strdup_mbstowcs(src);
815 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
816 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
817 mimehdr_begin_len = strlen(mimehdr_init) +
818 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
819 line_len = header_len;
823 g_return_if_fail(wsrc != NULL);
826 wchar_t *wp, *wtmp, *wtmpp;
829 /* irresponsible buffer overrun check */
830 if ((len - (destp - dest)) < (MAX_LINELEN + 1) * 2) break;
832 /* encode string including space
833 if non-ASCII string follows */
834 if (is_next_nonascii(wsrcp)) {
836 while ((wp = find_wspace(wp)) != NULL)
837 if (!is_next_nonascii(wp)) break;
839 wp = find_wspace(wsrcp);
842 wtmp = wcsndup(wsrcp, wp - wsrcp);
844 while (iswspace(wsrcp[nspc])) nspc++;
846 wtmp = wcsdup(wsrcp);
847 wsrcp += wcslen(wsrcp);
853 gint tlen = 0, str_ascii = 1;
854 gchar *tmp; /* internal codeset */
855 gchar *raw; /* converted, but not base64 encoded */
856 register gchar *tmpp;
859 tmpp = tmp = g_malloc(wcslen(wtmpp) * MB_CUR_MAX + 1);
864 while (*wtmpp != (wchar_t)0) {
867 gchar *raw_new = NULL;
869 const gchar *src_codeset;
871 if (*wtmpp < 32 || *wtmpp >= 127)
873 mbl = wctomb(tmpp, *wtmpp);
875 g_warning("invalid wide character\n");
880 src_codeset = conv_get_current_charset_str();
881 /* printf ("tmp = %s, tlen = %d, mbl\n",
883 if (jconv_alloc_conv(tmp, tlen + mbl,
884 &raw_new, &raw_new_len,
886 &dummy, mimehdr_charset)
888 g_warning("can't convert\n");
894 gint dlen = mimehdr_len +
896 if ((line_len + dlen +
897 (*(wtmpp + 1) ? 0 : nspc) +
898 (line_len > 1 ? 1 : 0))
912 } else if ((line_len + tlen + mbl +
913 (*(wtmpp + 1) ? 0 : nspc) +
914 (line_len > 1 ? 1 : 0))
918 (*(wtmpp + 1) ? 0 : nspc)
936 raw_len = raw_new_len;
940 /* g_print("tmp = %s, tlen = %d, mb_seqlen = %d\n",
941 tmp, tlen, mb_seqlen); */
943 if (tlen == 0 || raw_len == 0) {
949 if (line_len > 1 && destp > dest) {
956 g_snprintf(destp, len - strlen(dest), "%s%s%s",
957 mimehdr_init, mimehdr_charset,
959 destp += mimehdr_begin_len;
960 line_len += mimehdr_begin_len;
962 to64frombits(destp, raw, raw_len);
963 line_len += strlen(destp);
964 destp += strlen(destp);
966 strcpy(destp, mimehdr_end);
967 destp += strlen(mimehdr_end);
968 line_len += strlen(mimehdr_end);
971 line_len += strlen(destp);
972 destp += strlen(destp);
977 /* g_print("line_len = %d\n\n", line_len); */
978 } while (*wtmpp != (wchar_t)0);
980 while (iswspace(*wsrcp)) {
983 mbl = wctomb(destp, *wsrcp++);
996 /* g_print("dest = %s\n", dest); */
998 #else /* !HAVE_LIBJCONV */
1000 #define JIS_SEQLEN 3
1002 void conv_encode_header(gchar *dest, gint len, const gchar *src,
1008 size_t line_len, mimehdr_len, mimehdr_begin_len;
1009 gchar *mimehdr_init = "=?";
1010 gchar *mimehdr_end = "?=";
1011 gchar *mimehdr_enctype = "?B?";
1012 const gchar *mimehdr_charset;
1014 /* g_print("src = %s\n", src); */
1015 mimehdr_charset = conv_get_outgoing_charset_str();
1016 if (strcmp(mimehdr_charset, "ISO-2022-JP") != 0) {
1017 /* currently only supports Japanese */
1018 strncpy2(dest, src, len);
1022 /* convert to wide-character string */
1023 wsrcp = wsrc = strdup_mbstowcs(src);
1025 mimehdr_len = strlen(mimehdr_init) + strlen(mimehdr_end) +
1026 strlen(mimehdr_charset) + strlen(mimehdr_enctype);
1027 mimehdr_begin_len = strlen(mimehdr_init) +
1028 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); */
1135 if (line_len > 1 && destp > dest) {
1144 tmp_jis = g_new(gchar, tlen + mb_seqlen + 1);
1145 conv_euctojis(tmp_jis,
1146 tlen + mb_seqlen + 1, tmp);
1147 g_snprintf(destp, len - strlen(dest), "%s%s%s",
1148 mimehdr_init, mimehdr_charset,
1150 destp += mimehdr_begin_len;
1151 line_len += mimehdr_begin_len;
1153 to64frombits(destp, tmp_jis, strlen(tmp_jis));
1154 line_len += strlen(destp);
1155 destp += strlen(destp);
1157 strcpy(destp, mimehdr_end);
1158 destp += strlen(mimehdr_end);
1159 line_len += strlen(mimehdr_end);
1164 line_len += strlen(destp);
1165 destp += strlen(destp);
1169 /* g_print("line_len = %d\n\n", line_len); */
1170 } while (*wtmpp != (wchar_t)0);
1172 while (iswspace(*wsrcp)) {
1175 mbl = wctomb(destp, *wsrcp++);
1188 /* g_print("dest = %s\n", dest); */
1190 #endif /* HAVE_LIBJCONV */