-WX_DECLARE_OBJARRAY(wxCharacterSet, wxCSArray);
-#include "wx/arrimpl.cpp"
-WX_DEFINE_OBJARRAY(wxCSArray);
-
-static wxCSArray wxCharsets;
-
-static void wxLoadCharacterSets(void)
-{
- static bool already_loaded = FALSE;
-
- if (already_loaded) return;
-
- already_loaded = TRUE;
-#if defined(__UNIX__) && wxUSE_TEXTFILE
- // search through files in /usr/share/i18n/charmaps
- wxString fname;
- for (fname = ::wxFindFirstFile(T("/usr/share/i18n/charmaps/*"));
- !fname.IsEmpty();
- fname = ::wxFindNextFile()) {
- wxTextFile cmap(fname);
- if (cmap.Open()) {
- wxCharacterSet *cset = new wxCharacterSet;
- wxString comchar,escchar;
- bool in_charset = FALSE;
-
- // wxFprintf(stderr,T("Loaded: %s\n"),fname.c_str());
-
- wxString line;
- for (line = cmap.GetFirstLine();
- !cmap.Eof();
- line = cmap.GetNextLine()) {
- // wxFprintf(stderr,T("line contents: %s\n"),line.c_str());
- wxStringTokenizer token(line);
- wxString cmd = token.GetNextToken();
- if (cmd == comchar) {
- if (token.GetNextToken() == T("alias"))
- cset->names.Add(token.GetNextToken());
+const char *IC_CharSet::ms_wcCharsetName = NULL;
+bool IC_CharSet::ms_wcNeedsSwap = FALSE;
+
+IC_CharSet::IC_CharSet(const wxChar *name)
+{
+ // Do it the hard way
+ char cname[100];
+ for (size_t i = 0; i < wxStrlen(name)+1; i++)
+ cname[i] = (char) name[i];
+
+ // check for charset that represents wchar_t:
+ if (ms_wcCharsetName == NULL)
+ {
+ ms_wcNeedsSwap = FALSE;
+
+ // try charset with explicit bytesex info (e.g. "UCS-4LE"):
+ ms_wcCharsetName = WC_NAME_BEST;
+ m2w = iconv_open(ms_wcCharsetName, cname);
+
+ if (m2w == (iconv_t)-1)
+ {
+ // try charset w/o bytesex info (e.g. "UCS4")
+ // and check for bytesex ourselves:
+ ms_wcCharsetName = WC_NAME;
+ m2w = iconv_open(ms_wcCharsetName, cname);
+
+ // last bet, try if it knows WCHAR_T pseudo-charset
+ if (m2w == (iconv_t)-1)
+ {
+ ms_wcCharsetName = "WCHAR_T";
+ m2w = iconv_open(ms_wcCharsetName, cname);
+ }
+
+ if (m2w != (iconv_t)-1)
+ {
+ char buf[2], *bufPtr;
+ wchar_t wbuf[2], *wbufPtr;
+ size_t insz, outsz;
+ size_t res;
+
+ buf[0] = 'A';
+ buf[1] = 0;
+ wbuf[0] = 0;
+ insz = 2;
+ outsz = SIZEOF_WCHAR_T * 2;
+ wbufPtr = wbuf;
+ bufPtr = buf;
+
+ res = iconv(m2w, ICONV_CHAR_CAST(&bufPtr), &insz,
+ (char**)&wbufPtr, &outsz);
+
+ if (ICONV_FAILED(res, insz))
+ {
+ ms_wcCharsetName = NULL;
+ wxLogLastError(wxT("iconv"));
+ wxLogError(_("Conversion to charset '%s' doesn't work."), name);
+ }
+ else
+ {
+ ms_wcNeedsSwap = wbuf[0] != (wchar_t)buf[0];
+ }
+ }
+ else
+ {
+ ms_wcCharsetName = NULL;
+
+ // VS: we must not output an error here, since wxWindows will safely
+ // fall back to using wxEncodingConverter.
+ wxLogTrace(wxT("strconv"), wxT("Impossible to convert to/from charset '%s' with iconv, falling back to wxEncodingConverter."), name);
+ //wxLogError(
+ }
+ }
+ wxLogTrace(wxT("strconv"), wxT("wchar_t charset is '%s', needs swap: %i"), ms_wcCharsetName, ms_wcNeedsSwap);
+ }
+ else // we already have ms_wcCharsetName
+ {
+ m2w = iconv_open(ms_wcCharsetName, cname);
+ }
+
+ // NB: don't ever pass NULL to iconv_open(), it may crash!
+ if ( ms_wcCharsetName )
+ {
+ w2m = iconv_open( cname, ms_wcCharsetName);
+ }
+ else
+ {
+ w2m = (iconv_t)-1;
+ }
+}
+
+IC_CharSet::~IC_CharSet()
+{
+ if ( m2w != (iconv_t)-1 )
+ iconv_close(m2w);
+ if ( w2m != (iconv_t)-1 )
+ iconv_close(w2m);
+}
+
+size_t IC_CharSet::MB2WC(wchar_t *buf, const char *psz, size_t n)
+{
+ size_t inbuf = strlen(psz);
+ size_t outbuf = n * SIZEOF_WCHAR_T;
+ size_t res, cres;
+ // VS: Use these instead of psz, buf because iconv() modifies its arguments:
+ wchar_t *bufPtr = buf;
+ const char *pszPtr = psz;
+
+ if (buf)
+ {
+ // have destination buffer, convert there
+ cres = iconv(m2w,
+ ICONV_CHAR_CAST(&pszPtr), &inbuf,
+ (char**)&bufPtr, &outbuf);
+ res = n - (outbuf / SIZEOF_WCHAR_T);
+
+ if (ms_wcNeedsSwap)
+ {
+ // convert to native endianness
+ WC_BSWAP(buf /* _not_ bufPtr */, res)