/*
* iconv implementation using Win32 API to convert.
*
* This file is placed in the public domain.
*/
/* for WC_NO_BEST_FIT_CHARS */
#ifndef WINVER
# define WINVER 0x0500
#endif
#define STRICT
#include <windows.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
/* WORKAROUND: */
#ifndef UNDER_CE
#define GetProcAddressA GetProcAddress
#endif
#if 0
# define MAKE_EXE
# define MAKE_DLL
# define USE_LIBICONV_DLL
#endif
#if !defined(DEFAULT_LIBICONV_DLL)
# define DEFAULT_LIBICONV_DLL ""
#endif
#define MB_CHAR_MAX 16
#define UNICODE_MODE_BOM_DONE 1
#define UNICODE_MODE_SWAPPED 2
#define FLAG_USE_BOM 1
#define FLAG_TRANSLIT 2 /* //TRANSLIT */
#define FLAG_IGNORE 4 /* //IGNORE */
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef void* iconv_t;
iconv_t iconv_open(const char *tocode, const char *fromcode);
int iconv_close(iconv_t cd);
size_t iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
/* libiconv interface for vim */
#if defined(MAKE_DLL)
int
iconvctl (iconv_t cd, int request, void* argument)
{
/* not supported */
return 0;
}
#endif
typedef struct compat_t compat_t;
typedef struct csconv_t csconv_t;
typedef struct rec_iconv_t rec_iconv_t;
typedef iconv_t (*f_iconv_open)(const char *tocode, const char *fromcode);
typedef int (*f_iconv_close)(iconv_t cd);
typedef size_t (*f_iconv)(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
typedef int* (*f_errno)(void);
typedef int (*f_mbtowc)(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
typedef int (*f_wctomb)(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
typedef int (*f_mblen)(csconv_t *cv, const uchar *buf, int bufsize);
typedef int (*f_flush)(csconv_t *cv, uchar *buf, int bufsize);
#define COMPAT_IN 1
#define COMPAT_OUT 2
/* unicode mapping for compatibility with other conversion table. */
struct compat_t {
uint in;
uint out;
uint flag;
};
struct csconv_t {
int codepage;
int flags;
f_mbtowc mbtowc;
f_wctomb wctomb;
f_mblen mblen;
f_flush flush;
DWORD mode;
compat_t *compat;
};
struct rec_iconv_t {
iconv_t cd;
f_iconv_close iconv_close;
f_iconv iconv;
f_errno _errno;
csconv_t from;
csconv_t to;
#if defined(USE_LIBICONV_DLL)
HMODULE hlibiconv;
#endif
};
static int win_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode);
static int win_iconv_close(iconv_t cd);
static size_t win_iconv(iconv_t cd, char **inbuf, size_t *inbytesleft, char **outbuf, size_t *outbytesleft);
static int load_mlang();
static int make_csconv(const char *name, csconv_t *cv);
static int name_to_codepage(const char *name);
static uint utf16_to_ucs4(const ushort *wbuf);
static void ucs4_to_utf16(uint wc, ushort *wbuf, int *wbufsize);
static int mbtowc_flags(int codepage);
static int must_use_null_useddefaultchar(int codepage);
static char *strrstr(const char *str, const char *token);
static char *xstrndup(const char *s, size_t n);
static int seterror(int err);
#if defined(USE_LIBICONV_DLL)
static int libiconv_iconv_open(rec_iconv_t *cd, const char *tocode, const char *fromcode);
static PVOID MyImageDirectoryEntryToData(LPVOID Base, BOOLEAN MappedAsImage, USHORT DirectoryEntry, PULONG Size);
static HMODULE find_imported_module_by_funcname(HMODULE hModule, const char *funcname);
static HMODULE hwiniconv;
#endif
static int sbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize);
static int dbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize);
static int mbcs_mblen(csconv_t *cv, const uchar *buf, int bufsize);
static int utf8_mblen(csconv_t *cv, const uchar *buf, int bufsize);
static int eucjp_mblen(csconv_t *cv, const uchar *buf, int bufsize);
static int kernel_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
static int kernel_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
static int mlang_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
static int mlang_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
static int utf16_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
static int utf16_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
static int utf32_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
static int utf32_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
static int iso2022jp_mbtowc(csconv_t *cv, const uchar *buf, int bufsize, ushort *wbuf, int *wbufsize);
static int iso2022jp_wctomb(csconv_t *cv, ushort *wbuf, int wbufsize, uchar *buf, int bufsize);
static int iso2022jp_flush(csconv_t *cv, uchar *buf, int bufsize);
static struct {
int codepage;
const char *name;
} codepage_alias[] = {
{65001, "CP65001"},
{65001, "UTF8"},
{65001, "UTF-8"},
{1200, "CP1200"},
{1200, "UTF16LE"},
{1200, "UTF-16LE"},
{1200, "UCS2LE"},
{1200, "UCS-2LE"},
{1201, "CP1201"},
{1201, "UTF16BE"},
{1201, "UTF-16BE"},
{1201, "UCS2BE"},
{1201, "UCS-2BE"},
{1201, "unicodeFFFE"},
{12000, "CP12000"},
{12000, "UTF32LE"},
{12000, "UTF-32LE"},
{12000, "UCS4LE"},
{12000, "UCS-4LE"},
{12001, "CP12001"},
{12001, "UTF32BE"},
{12001, "UTF-32BE"},
{12001, "UCS4BE"},
{12001, "UCS-4BE"},
#ifndef GLIB_COMPILATION
/*
* Default is big endian.
* See rfc2781 4.3 Interpreting text labelled as UTF-16.
*/
{1201, "UTF16"},
{1201, "UTF-16"},
{1201, "UCS2"},
{1201, "UCS-2"},
{12001, "UTF32"},
{12001, "UTF-32"},
{12001, "UCS-4"},
{12001, "UCS4"},
#else
/* Default is little endian, because the platform is */
{1200, "UTF16"},
{1200, "UTF-16"},
{1200, "UCS2"},
{1200, "UCS-2"},
{12000, "UTF32"},
{12000, "UTF-32"},
{12000, "UCS4"},
{12000, "UCS-4"},
#endif
/* copy from libiconv `iconv -l` */
/* !IsValidCodePage(367) */
{20127, "ANSI_X3.4-1968"},
{20127, "ANSI_X3.4-1986"},
{20127, "ASCII"},
{20127, "CP367"},
{20127, "IBM367"},
{20127, "ISO-IR-6"},
{20127, "ISO646-US"},
{20127, "ISO_646.IRV:1991"},
{20127, "US"},
{20127, "US-ASCII"},
{20127, "CSASCII"},
/* !IsValidCodePage(819) */
{1252, "CP819"},
{1252, "IBM819"},
{28591, "ISO-8859-1"},
{28591, "ISO-IR-100"},
{28591, "ISO8859-1"},
{28591, "ISO_8859-1"},
{28591, "ISO_8859-1:1987"},
{28591, "L1"},
{28591, "LATIN1"},
{28591, "CSISOLATIN1"},
{1250, "CP1250"},
{1250, "MS-EE"},
{1250, "WINDOWS-1250"},
{1251, "CP1251"},
{1251, "MS-CYRL"},
{1251, "WINDOWS-1251"},
{1252, "CP1252"},
{1252, "MS-ANSI"},
{1252, "WINDOWS-1252"},
{1253, "CP1253"},
{1253, "MS-GREEK"},
{1253, "WINDOWS-1253"},
{1254, "CP1254"},
{1254, "MS-TURK"},
{1254, "WINDOWS-1254"},
{1255, "CP1255"},
{1255, "MS-HEBR"},
{1255, "WINDOWS-1255"},
{1256, "CP1256"},
{1256, "MS-ARAB"},
{1256, "WINDOWS-1256"},
{1257, "CP1257"},
{1257, "WINBALTRIM"},
{1257, "WINDOWS-1257"},
{1258, "CP1258"},
{1258, "WINDOWS-1258"},
{850, "850"},
{850, "CP850"},
{850, "IBM850"},
{850, "CSPC850MULTILINGUAL"},
/* !IsValidCodePage(862) */
{862, "862"},
{862, "CP862"},
{862, "IBM862"},
{862, "CSPC862LATINHEBREW"},
{866, "866"},
{866, "CP866"},
{866, "IBM866"},
{866, "CSIBM866"},
/* !IsValidCodePage(154) */
{154