AC_SUBST(sharedir)
LIBICONV=
-LIBICONVDEPS=
-need_iconv=no
-AC_ARG_WITH(included-iconv,
- [ --with-included-iconv Use the iconv implementation included here],
- need_iconv=yes,
- AC_CACHE_CHECK(for iconv, mutt_cv_func_iconv,
+AC_CACHE_CHECK(for iconv, mutt_cv_func_iconv,
[ mutt_cv_func_iconv=no
mutt_cv_lib_iconv=no
AC_TRY_LINK([#include <stdlib.h>
LIBS="$mutt_save_LIBS"
fi
])
- if test "$mutt_cv_func_iconv" = no; then
- need_iconv=yes
- fi
- if test "$mutt_cv_lib_iconv" = yes; then
- LIBICONV="-liconv"
- fi
-)
-
-if test "$need_iconv" = yes ; then
- LIBICONV="-Liconv -liconv"
- LIBICONVDEPS="\$(top_srcdir)/iconv/iconv.h iconv/libiconv.a"
+if test "$mutt_cv_func_iconv" = no; then
+ AC_MSG_ERROR(Unable to find iconv library)
+fi
+if test "$mutt_cv_lib_iconv" = yes; then
+ LIBICONV="-liconv"
fi
-AM_CONDITIONAL(BUILD_ICONV, test "$need_iconv" = yes)
AC_SUBST(LIBICONV)
-AC_SUBST(LIBICONVDEPS)
-
-if test "$need_iconv" = yes ; then
-mutt_cv_charmaps=/usr/share/i18n/charmaps
-AC_ARG_WITH(charmaps, [ --with-charmaps=PATH Where to find character set definitions],
- [if test x$withval != x -a $withval != yes ; then
- mutt_cv_charmaps=$withval
- fi])
+AC_CACHE_CHECK([whether iconv is seriously broken], mutt_cv_iconv_broken,
+ mutt_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBICONV"
+ AC_TRY_RUN([
+#include <iconv.h>
+#include <string.h>
+int main()
+{
+ iconv_t cd;
+ const char *ib;
+ char *ob;
+ size_t ibl, obl;
+ const char *s = "\304\211";
+changequote(, )dnl
+ char t[3];
+changequote([, ])dnl
+ ib = s, ibl = 2, ob = t, obl = 3; /* glibc-2.1 needs space for '\0'? */
+ return ((cd = iconv_open("UTF-8", "UTF-8")) == (iconv_t)(-1) ||
+ iconv(cd, &ib, &ibl, &ob, &obl) == (size_t)(-1) ||
+ iconv_close(cd) ||
+ !(ib == s + 2 && ibl == 0 && ob == t + 2 && obl == 1) ||
+ memcmp(s, t, 2));
+}
+ ],
+ mutt_cv_iconv_broken=no,
+ mutt_cv_iconv_broken=yes,
+ mutt_cv_iconv_broken=no)
+ LIBS="$mutt_save_LIBS")
+if test "$mutt_cv_iconv_broken" = yes; then
+ AC_MSG_ERROR(Try using libiconv instead)
+fi
-AC_MSG_CHECKING(whether character set definitions are desired and usable)
-if test ! -f $mutt_cv_charmaps/ISO_10646 ; then
- AC_MSG_RESULT(no)
- mutt_cv_charmaps=$mutt_cv_sharedir/charmaps
- echo "Mutt will expect character map definitions under $mutt_cv_charmaps." >&AC_FD_MSG
- if test \( -d $srcdir/charmaps \) -a \( -d $srcdir/charmaps/maps \) ; then
- echo "We will install the included character set definitions." >&AC_FD_MSG
- mutt_cv_add_subdirs="charmaps"
- else
- mutt_cv_add_subdirs=""
- echo "If you want character set support, read INSTALL". >& AC_FD_MSG
- fi
- need_charmaps=yes
+dnl This is to detect implementations such as the one in glibc-2.1,
+dnl which always convert exactly but return the number of characters
+dnl converted instead of the number converted inexactly.
+AC_CACHE_CHECK([whether iconv is non-transcribing], mutt_cv_iconv_nontrans,
+ mutt_save_LIBS="$LIBS"
+ LIBS="$LIBS $LIBICONV"
+ AC_TRY_RUN([
+#include <iconv.h>
+#include <string.h>
+int main()
+{
+ iconv_t cd;
+ const char *ib;
+ char *ob;
+ size_t ibl, obl;
+ const char *s = "\304\211";
+changequote(, )dnl
+ char t[3];
+changequote([, ])dnl
+ ib = s, ibl = 2, ob = t, obl = 3;
+ return ((cd = iconv_open("UTF-8", "UTF-8")) == (iconv_t)(-1) ||
+ iconv(cd, &ib, &ibl, &ob, &obl));
+}
+ ],
+ mutt_cv_iconv_nontrans=no,
+ mutt_cv_iconv_nontrans=yes,
+ mutt_cv_iconv_nontrans=no)
+ LIBS="$mutt_save_LIBS")
+if test "$mutt_cv_iconv_nontrans" = yes; then
+ AC_DEFINE(ICONV_NONTRANS, 1)
else
- AC_MSG_RESULT(yes)
+ AC_DEFINE(ICONV_NONTRANS, 0)
fi
-AC_DEFINE_UNQUOTED(CHARMAPS_DIR, "$mutt_cv_charmaps")
-charmaps=$mutt_cv_charmaps
-AC_SUBST(charmaps)
-AM_CONDITIONAL(BUILD_CHARMAPS, test x$need_charmaps = xyes)
-
-fi # /* need_iconv */
-
AC_ARG_WITH(docdir, [ --with-docdir=PATH Specify where to put the documentation],
[mutt_cv_docdir=$withval],
[ AC_CACHE_CHECK(where to put the documentation,
AC_OUTPUT(Makefile intl/Makefile m4/Makefile dnl
po/Makefile.in doc/Makefile contrib/Makefile dnl
muttbug.sh dnl
- charmaps/Makefile imap/Makefile iconv/Makefile dnl
+ imap/Makefile dnl
Muttrc.head)
+++ /dev/null
-/*
- * Copyright (C) 1999 Thomas Roessler <roessler@guug.de>
- *
- * This program is free software; you can redistribute it
- * and/or modify it under the terms of the GNU General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be
- * useful, but WITHOUT ANY WARRANTY; without even the implied
- * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public
- * License along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
- * 02139, USA.
- */
-
-/*
- * This module deals with POSIX.2 character set definition files.
- */
-
-
-#include <string.h>
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include <sys/types.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include "mutt.h"
-#include "iconv.h"
-
-#ifndef EILSEQ
-#define EILSEQ EINVAL
-#endif
-
-/* Define this if you want any dprint () statements in this code */
-
-#undef CHARSET_DEBUG
-
-#ifndef CHARSET_DEBUG
-# undef dprint
-# define dprint(a, b) (void) a
-#endif
-
-
-/* Type definitions */
-
-typedef int CHARSET_MAP[256];
-
-typedef struct descr
-{
- char *symbol;
- int repr;
-}
-CHARDESC;
-
-typedef struct
-{
- char *charset;
- char escape_char;
- char comment_char;
- short multbyte;
- LIST *aliases;
-}
-CHARMAP;
-
-typedef struct
-{
- size_t n_symb;
- size_t u_symb;
-
- short multbyte;
- HASH *symb_to_repr;
- CHARDESC **description;
-}
-CHARSET;
-
-/* Module-global variables */
-
-static HASH *Translations = NULL;
-static HASH *Charsets = NULL;
-static HASH *CharsetAliases = NULL;
-
-/* Function Prototypes */
-
-static CHARDESC *chardesc_new (void);
-static CHARDESC *repr2descr (int repr, CHARSET * cs);
-
-static CHARMAP *charmap_new (void);
-static CHARMAP *parse_charmap_header (FILE * fp);
-static CHARSET *charset_new (size_t hash_size);
-
-static CHARSET_MAP *build_translation (CHARSET * from, CHARSET * to);
-
-static char translate_character (CHARSET * to, const char *symbol);
-
-static int load_charset (const char *filename, CHARSET ** csp, short multbyte);
-static int parse_charmap_line (char *line, CHARMAP * m, CHARDESC ** descrp);
-static int _cd_compar (const void *a, const void *b);
-
-static void chardesc_free (CHARDESC ** cdp);
-static void charmap_free (CHARMAP ** cp);
-static void charset_free (CHARSET ** csp);
-static void fix_symbol (char *symbol, CHARMAP * m);
-
-static CHARSET *charset_new (size_t hash_size)
-{
- CHARSET *cp = safe_malloc (sizeof (CHARSET));
- size_t i;
-
- cp->n_symb = 256;
- cp->u_symb = 0;
- cp->multbyte = 1;
- cp->symb_to_repr = hash_create (hash_size);
- cp->description = safe_malloc (cp->n_symb * sizeof (CHARDESC *));
-
- for (i = 0; i < cp->n_symb; i++)
- cp->description[i] = NULL;
-
- return cp;
-}
-
-static void charset_free (CHARSET ** csp)
-{
- CHARSET *cs = *csp;
- size_t i;
-
- for (i = 0; i < cs->n_symb; i++)
- chardesc_free (&cs->description[i]);
-
- safe_free ((void **) &cs->description);
-
- hash_destroy (&cs->symb_to_repr, NULL);
- safe_free ((void **) csp);
-}
-
-static CHARMAP *charmap_new (void)
-{
- CHARMAP *m = safe_malloc (sizeof (CHARMAP));
-
- m->charset = NULL;
- m->escape_char = '\\';
- m->comment_char = '#';
- m->multbyte = 1;
- m->aliases = NULL;
-
- return m;
-}
-
-static void charmap_free (CHARMAP ** cp)
-{
- if (!cp || !*cp)
- return;
-
- mutt_free_list (&(*cp)->aliases);
- safe_free ((void **) &(*cp)->charset);
- safe_free ((void **) cp);
-
- return;
-}
-
-static CHARDESC *chardesc_new (void)
-{
- CHARDESC *p = safe_malloc (sizeof (CHARDESC));
-
- p->symbol = NULL;
- p->repr = -1;
-
- return p;
-}
-
-static void chardesc_free (CHARDESC ** cdp)
-{
- if (!cdp || !*cdp)
- return;
-
-
- safe_free ((void **) &(*cdp)->symbol);
- safe_free ((void **) cdp);
-
- return;
-}
-
-static CHARMAP *parse_charmap_header (FILE * fp)
-{
- char buffer[1024];
- char *t, *u;
- CHARMAP *m = charmap_new ();
-
- while (fgets (buffer, sizeof (buffer), fp))
- {
- if ((t = strchr (buffer, '\n')))
- *t = '\0';
- else
- {
- charmap_free (&m);
- return NULL;
- }
-
- if (!strncmp (buffer, "CHARMAP", 7))
- break;
-
- if (*buffer == m->comment_char)
- {
- if ((t = strtok (buffer + 1, "\t ")) && !strcasecmp (t, "alias"))
- {
- char _tmp[SHORT_STRING];
- while ((t = strtok(NULL, "\t, ")))
- {
- mutt_canonical_charset (_tmp, sizeof (_tmp), t);
- m->aliases = mutt_add_list (m->aliases, _tmp);
- }
- }
- continue;
- }
-
- if (!(t = strtok (buffer, "\t ")))
- continue;
-
- if (!(u = strtok (NULL, "\t ")))
- {
- charmap_free (&m);
- return NULL;
- }
-
- if (!strcmp (t, "<code_set_name>"))
- {
- safe_free ((void **) &m->charset);
- mutt_canonical_charset (u, strlen (u) + 1, u);
- m->charset = safe_strdup (u);
- }
- else if (!strcmp (t, "<comment_char>"))
- {
- m->comment_char = *u;
- }
- else if (!strcmp (t, "<escape_char>"))
- {
- m->escape_char = *u;
- }
- else if (!strcmp (t, "<mb_cur_max>"))
- {
- m->multbyte = strtol (u, NULL, 0);
- }
- }
-
- return m;
-}
-
-/* Properly handle escape characters within a symbol. */
-
-static void fix_symbol (char *symbol, CHARMAP * m)
-{
- char *s, *d;
-
- for (s = symbol, d = symbol; *s; *d++ = *s++)
- {
- if (*s == m->escape_char && !*++s)
- break;
- }
-
- *d = *s;
-}
-
-enum
-{
- CL_DESCR,
- CL_END,
- CL_COMMENT,
- CL_ERROR
-};
-
-static int parse_charmap_line (char *line, CHARMAP * m, CHARDESC ** descrp)
-{
- char *t, *u;
- short n;
- CHARDESC *descr;
-
- if (*line == m->comment_char)
- return CL_COMMENT;
-
- descr = *descrp = chardesc_new ();
-
- if (!strncmp (line, "END CHARMAP", 11))
- {
- chardesc_free (descrp);
- return CL_END;
- }
-
- for (t = line; *t && isspace ((unsigned char) *t); t++)
- ;
-
- if (*t++ != '<')
- {
- chardesc_free (descrp);
- return CL_ERROR;
- }
-
- for (u = t; *u && *u != '>'; u++)
- {
- if (*u == m->escape_char && u[1])
- u++;
- }
-
- if (*u != '>')
- {
- chardesc_free (descrp);
- return CL_ERROR;
- }
-
- *u++ = '\0';
- descr->symbol = safe_strdup (t);
- fix_symbol (descr->symbol, m);
-
- for (t = u; *t && isspace ((unsigned char) *t); t++)
- ;
-
- for (u = t; *u && !isspace ((unsigned char) *u); u++)
- ;
-
- *u++ = 0;
- descr->repr = 0;
-
- for (n = 0; *t == m->escape_char && n < m->multbyte; n++)
- {
- switch (*++t)
- {
- case 'x':
- descr->repr = descr->repr * 256 + strtol (++t, &t, 16);
- break;
- case 'd':
- descr->repr = descr->repr * 256 + strtol (++t, &t, 10);
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- descr->repr = descr->repr * 256 + strtol (t, &t, 8);
- break;
- default:
- chardesc_free (descrp);
- return CL_ERROR;
- }
- }
-
- if (!n)
- {
- chardesc_free (descrp);
- return CL_ERROR;
- }
-
- return CL_DESCR;
-}
-
-static int _cd_compar (const void *a, const void *b)
-{
- const CHARDESC *ap, *bp;
- int i;
-
- ap = * (CHARDESC **) a;
- bp = * (CHARDESC **) b;
-
- i = ap->repr - bp->repr;
-
- dprint (98, (debugfile, "_cd_compar: { %x, %s }, { %x, %s } -> %d\n",
- ap->repr, ap->symbol, bp->repr, bp->symbol, i));
-
- return i;
-}
-
-/*
- * Load a character set description into memory.
- *
- * The multibyte parameter tells us whether we are going
- * to accept multibyte character sets.
- */
-
-static int load_charset (const char *filename, CHARSET ** csp, short multbyte)
-{
- CHARDESC *cd = NULL;
- CHARSET *cs = NULL;
- CHARMAP *m = NULL;
- FILE *fp;
- char buffer[1024];
- int i;
- int rv = -1;
-
- cs = *csp = charset_new (multbyte ? 1031 : 257);
-
- dprint (2, (debugfile, "load_charset: Trying to open: %s\n", filename));
-
- if ((fp = fopen (filename, "r")) == NULL)
- {
- char _filename[_POSIX_PATH_MAX];
-
- snprintf (_filename, sizeof (_filename), "%s/%s", CHARMAPS_DIR, filename);
- dprint (2, (debugfile, "load_charset: Trying to open: %s\n", _filename));
-
- if ((fp = fopen (_filename, "r")) == NULL)
- {
- dprint (2, (debugfile, "load_charset: Failed.\n"));
- goto bail;
- }
- }
-
- if ((m = parse_charmap_header (fp)) == NULL)
- goto bail;
-
- /* Don't handle multibyte character sets unless explicitly requested
- * to do so.
- */
-
- if (m->multbyte > 1 && !multbyte)
- {
- dprint (2, (debugfile, "load_charset: m->multbyte == %d\n",
- (int) m->multbyte));
- goto bail;
- }
-
- cs->multbyte = m->multbyte;
-
- while (fgets (buffer, sizeof (buffer), fp) != NULL)
- {
- i = parse_charmap_line (buffer, m, &cd);
-
- if (i == CL_END)
- break;
- else if (i == CL_DESCR)
- {
- dprint (5, (debugfile, "load_charset: Got character description: <%s> -> %x\n",
- cd->symbol, cd->repr));
-
- if (!multbyte)
- {
- if (0 <= cd->repr && cd->repr < 256)
- {
- hash_delete (cs->symb_to_repr, cd->symbol, NULL, NULL);
- hash_insert (cs->symb_to_repr, cd->symbol, cd, 0);
-
- /* note: we intentionally leak some memory here. */
- if (!cs->description[cd->repr])
- cs->u_symb++;
-
- cs->description[cd->repr] = cd;
- cd = NULL;
- }
- }
- else
- {
- if (cs->u_symb == cs->n_symb)
- {
- size_t new_size = cs->n_symb + 256;
- size_t i;
-
- safe_realloc ((void **) &cs->description, new_size * sizeof (CHARDESC *));
- for (i = cs->u_symb; i < new_size; i++)
- cs->description[i] = NULL;
- cs->n_symb = new_size;
- }
-
- hash_delete (cs->symb_to_repr, cd->symbol, NULL, NULL);
- hash_insert (cs->symb_to_repr, cd->symbol, cd, 0);
-
- cs->description[cs->u_symb++] = cd;
- cd = NULL;
- }
- }
-
- if (cd)
- {
- dprint (5, (debugfile, "load_charset: character description still present: <%s>->%x\n",
- cd->symbol, cd->repr));
- }
- chardesc_free (&cd);
- }
-
- if (multbyte)
- qsort (cs->description, cs->u_symb, sizeof (CHARDESC *), _cd_compar);
-
- rv = 0;
-
-bail:
- charmap_free (&m);
- if (fp)
- fclose (fp);
- if (rv)
- charset_free (csp);
-
- return rv;
-}
-
-static CHARDESC *repr2descr (int repr, CHARSET * cs)
-{
- CHARDESC *key;
- CHARDESC **r;
-
- if (!cs || repr < 0)
- return NULL;
-
- if (cs->multbyte == 1)
- {
- if (repr < 256)
- return cs->description[repr];
- else
- return NULL;
- }
-
- key = safe_malloc (sizeof(CHARDESC));
- key->repr = repr;
- key->symbol = "<unknown>"; /* otherwise, the
- * debug code may
- * segfault. ouch.
- */
-
- r = bsearch (&key, cs->description, cs->u_symb,
- sizeof (CHARDESC *), _cd_compar);
-
- safe_free ((void **) &key);
-
- if (r) return *r;
-
- return NULL;
-}
-
-/* Build a translation table. If a character cannot be
- * translated correctly, we try to find an approximation
- * from the portable charcter set.
- *
- * Note that this implies the assumption that the portable
- * character set can be used without any conversion.
- *
- * Should be safe on POSIX systems.
- */
-
-static char translate_character (CHARSET * to, const char *symbol)
-{
- CHARDESC *cdt;
-
- if ((cdt = hash_find (to->symb_to_repr, symbol)))
- return (char) cdt->repr;
- else
- return *symbol;
-}
-
-static CHARSET_MAP *build_translation (CHARSET * from, CHARSET * to)
-{
- int i;
- CHARSET_MAP *map;
- CHARDESC *cd;
-
- /* This is for 8-bit character sets. */
-
- if (!from || !to || from->multbyte > 1 || to->multbyte > 1)
- return NULL;
-
- map = safe_malloc (sizeof (CHARSET_MAP));
- for (i = 0; i < 256; i++)
- {
- if (!(cd = repr2descr (i, from)))
- (*map)[i] = '?';
- else
- (*map)[i] = translate_character (to, cd->symbol);
- }
-
- return map;
-}
-
-/* Currently, just scan the various charset definition files.
- * On the long run, we should cache this stuff in a file.
- */
-
-static HASH *load_charset_aliases (void)
-{
- HASH *charset_aliases;
- CHARMAP *m;
- DIR *dp;
- FILE *fp;
- struct dirent *de;
-
- if ((dp = opendir (CHARMAPS_DIR)) == NULL)
- return NULL;
-
- charset_aliases = hash_create(127);
-
- while ((de = readdir (dp)))
- {
- char fnbuff[_POSIX_PATH_MAX];
-
- if (*de->d_name == '.')
- continue;
-
- snprintf (fnbuff, sizeof (fnbuff), "%s/%s", CHARMAPS_DIR, de->d_name);
- dprint (2, (debugfile, "load_charset_aliases: Opening %s\n", fnbuff));
- if ((fp = fopen (fnbuff, "r")) == NULL)
- continue;
-
- if ((m = parse_charmap_header (fp)) != NULL)
- {
- LIST *lp;
- char buffer[LONG_STRING];
-
- mutt_canonical_charset (buffer, sizeof (buffer), de->d_name);
- m->aliases = mutt_add_list (m->aliases, buffer);
-
- if (m->charset)
- m->aliases = mutt_add_list (m->aliases, m->charset);
-
- for (lp = m->aliases; lp; lp = lp->next)
- {
- if (lp->data)
- {
- dprint (2, (debugfile, "load_charset_aliases: %s -> %s\n",
- lp->data, de->d_name));
- if (hash_find (charset_aliases, lp->data))
- {
- dprint (2, (debugfile, "load_charset_aliases: %s already mapped.\n",
- lp->data));
- }
- else
- hash_insert (charset_aliases, safe_strdup (lp->data), safe_strdup (de->d_name), 0);
- }
- }
-
- charmap_free (&m);
- }
-
- fclose (fp);
- }
-
- closedir (dp);
- return charset_aliases;
-}
-
-static void init_charsets ()
-{
- if (Charsets) return;
-
- Charsets = hash_create (127);
- Translations = hash_create (127);
- CharsetAliases = load_charset_aliases ();
-}
-
-static CHARSET *mutt_get_charset (const char *name)
-{
- CHARSET *charset;
- char buffer[SHORT_STRING];
- char *real_charset;
-
- if (!name || !*name)
- return (NULL);
-
- init_charsets();
- mutt_canonical_charset (buffer, sizeof(buffer), name);
-
- dprint (2, (debugfile, "mutt_get_charset: Looking for %s\n", buffer));
-
- if(!CharsetAliases || !(real_charset = hash_find(CharsetAliases, buffer)))
- real_charset = buffer;
-
- dprint (2, (debugfile, "mutt_get_charset: maps to: %s\n", real_charset));
-
- if(!(charset = hash_find (Charsets, real_charset)))
- {
- dprint (2, (debugfile, "mutt_get_charset: Need to load.\n"));
- if (load_charset(real_charset, &charset, 0) == 0)
- hash_insert(Charsets, safe_strdup(real_charset), charset, 1);
- else
- charset = NULL;
- }
- return charset;
-}
-
-static CHARSET_MAP *mutt_get_translation(const char *_from, const char *_to)
-{
- char from_canon[SHORT_STRING];
- char to_canon[SHORT_STRING];
- char key[SHORT_STRING];
- char *from, *to;
- CHARSET *from_cs, *to_cs;
- CHARSET_MAP *map;
-
- if(!_from || !_to)
- return NULL;
-
- mutt_canonical_charset(from_canon, sizeof(from_canon), _from);
- mutt_canonical_charset(to_canon, sizeof(to_canon), _to);
-
- /* quick check for some trivial cases. Doing this before
- * we actually call the initialization routine delays character
- * set loading until it's _really_ needed.
- */
-
- if(!strcmp(from_canon, to_canon)
- || (!strcmp (from_canon, "us-ascii") && !strncmp (to_canon, "iso-8859", 8)))
- return NULL;
-
- init_charsets();
-
- if(!CharsetAliases || !(from = hash_find(CharsetAliases, from_canon)))
- from = from_canon;
- if(!CharsetAliases || !(to = hash_find(CharsetAliases, to_canon)))
- to = to_canon;
-
- /* quick check for the identity mapping */
- if((from == to) || !mutt_strcmp(from, to))
- return NULL;
-
- snprintf(key, sizeof(key), "%s %s", from, to);
- if((map = hash_find(Translations, key)) == NULL)
- {
- from_cs = mutt_get_charset(from);
- to_cs = mutt_get_charset(to);
-
- if((map = build_translation(from_cs, to_cs)))
- hash_insert(Translations, safe_strdup(key), map, 1);
- }
- return map;
-}
-
-static unsigned char mutt_display_char (unsigned char ch, CHARSET_MAP *map)
-{
- if (!map || !ch)
- return ch;
-
- return (unsigned char) (*map)[ch];
-}
-
-static CHARSET *Unicode = NULL;
-
-static int unicode_init (void)
-{
- if (!Unicode)
- {
- if (load_charset ("ISO_10646", &Unicode, 1) == -1)
- Unicode = NULL;
- }
-
- return (Unicode == NULL ? -1 : 0);
-}
-
-/*************************************************************/
-/* iconv functions */
-
-struct iconv
-{
- CHARSET_MAP *chm; /* used for 8-bit to 8-bit recoding */
- CHARSET *chs_from; /* used for translation from UTF-8 */
- CHARSET *chs_to; /* used for translation to UTF-8 */
-};
-
-iconv_t iconv_open (const char *tocode, const char *fromcode)
-{
- struct iconv *cd = 0;
- CHARSET_MAP *chm;
- CHARSET *chs;
-
- if (fromcode && tocode)
- {
- if (mutt_is_utf8 (fromcode))
- {
- if (!mutt_is_utf8 (tocode))
- {
- if ((chs = mutt_get_charset (tocode)))
- {
- cd = safe_calloc (sizeof (struct iconv), 1);
- cd->chs_to = chs;
- }
- }
- }
- else if (mutt_is_utf8 (tocode))
- {
- if ((chs = mutt_get_charset (fromcode)))
- {
- cd = safe_calloc (sizeof (struct iconv), 1);
- cd->chs_from = chs;
- }
- }
- else
- {
- if ((chm = mutt_get_translation (fromcode, tocode)))
- {
- cd = safe_calloc (sizeof (struct iconv), 1);
- cd->chm = mutt_get_translation (fromcode, tocode);
- }
- }
- }
- return cd;
-}
-
-size_t iconv (iconv_t _cd, const char **inbuf, size_t *inbytesleft,
- char **outbuf, size_t *outbytesleft)
-{
- struct iconv *cd = (struct iconv *)_cd;
- const char *ib = *inbuf;
- size_t ibl = *inbytesleft;
- char *ob = *outbuf;
- size_t obl = *outbytesleft;
- int n;
-
- if (cd && cd->chm)
- {
- int i;
- n = ibl < obl ? ibl : obl;
- for (i = 0; i < n; i++)
- ob[i] = mutt_display_char (ib[i], cd->chm);
- ib += n, ibl -= n, ob += n, obl -= n;
- }
- else if (cd && cd->chs_from && !unicode_init ())
- {
- n = 0;
- while (ibl && obl)
- {
- CHARDESC *d;
- unsigned long c = 0xfffd; /* replacement char */
- int k;
- if ((d = repr2descr ((unsigned char)*ib, cd->chs_from)) &&
- (d = hash_find (Unicode->symb_to_repr, d->symbol)))
- c = d->repr;
- if (obl < 6 && obl < mutt_wctoutf8 (0, c))
- break;
- k = mutt_wctoutf8 (ob, c);
- ++ib, --ibl;
- ob += k, obl -=k;
- ++n;
- }
- }
- else if (cd && !cd->chs_from && cd->chs_to && !unicode_init ())
- {
- mbstate_t mbstate;
- unsigned int wc;
- int k;
- char c;
- CHARDESC *d;
-
- memset(&mbstate, 0, sizeof(mbstate));
- n = 0;
- while (ibl && obl)
- {
- k = utf8rtowc (&wc, ib, ibl, &mbstate);
- if (k == -1 || k == -2)
- {
- *inbuf = ib, *inbytesleft = ibl;
- *outbuf = ob, *outbytesleft = obl;
- errno = (k == -1) ? EILSEQ : EINVAL;
- return -1;
- }
- k = k ? k : 1;
- c = '?'; /* replacement char */
- if ((d = repr2descr (wc, Unicode)))
- {
- c = d->symbol[0]; /* approximation */
- if ((d = hash_find (cd->chs_to->symb_to_repr, d->symbol)))
- c = d->repr;
- }
- ib += k, ibl -= k;
- *ob++ = c, --obl;
- ++n;
- }
- }
- else
- {
- /* no translation defined - just copy */
- n = ibl < obl ? ibl : obl;
- memcpy (ob, ib, n);
- ib += n, ibl -= n, ob += n, obl -= n;
- }
-
- *inbuf = ib, *inbytesleft = ibl;
- *outbuf = ob, *outbytesleft = obl;
- if (ibl)
- {
- errno = E2BIG;
- return (size_t)-1;
- }
- else
- return n;
-}
-
-int iconv_close (iconv_t cd)
-{
- free (cd);
- return 0;
-}