X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4bc6e5c51af44eb04313ae14f390f3780dfea346..af34705c34c719d9532faedd4c715da94764e76b:/src/common/strconv.cpp?ds=sidebyside diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index b4eaa65148..cdbaabf73e 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -6,7 +6,7 @@ // Created: 29/01/98 // RCS-ID: $Id$ // Copyright: (c) 1999 Ove Kaaven, Robert Roebling, Vadim Zeitlin, Vaclav Slavik -// Licence: wxWindows license +// Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// // ============================================================================ @@ -17,7 +17,7 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "strconv.h" #endif @@ -37,7 +37,10 @@ #include "wx/msw/private.h" #endif +#ifndef __WXWINCE__ #include +#endif + #include #include #include @@ -50,14 +53,19 @@ // ---------------------------------------------------------------------------- #if wxUSE_WCHAR_T - WXDLLEXPORT_DATA(wxMBConv) wxConvLibc; - WXDLLEXPORT_DATA(wxCSConv) wxConvLocal((const wxChar *)NULL); + WXDLLIMPEXP_DATA_BASE(wxMBConv) wxConvLibc; + WXDLLIMPEXP_DATA_BASE(wxCSConv) wxConvLocal((const wxChar *)NULL); + WXDLLIMPEXP_DATA_BASE(wxCSConv) wxConvISO8859_1(_T("iso-8859-1")); #else // stand-ins in absence of wchar_t - WXDLLEXPORT_DATA(wxMBConv) wxConvLibc, wxConvFile; + WXDLLIMPEXP_DATA_BASE(wxMBConv) wxConvLibc, + wxConvFile, + wxConvISO8859_1, + wxConvLocal, + wxConvUTF8; #endif // wxUSE_WCHAR_T -WXDLLEXPORT_DATA(wxMBConv *) wxConvCurrent = &wxConvLibc; +WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvCurrent = &wxConvLibc; class wxStrConvModule: public wxModule { @@ -67,7 +75,8 @@ public: virtual void OnExit() { #if wxUSE_WCHAR_T - wxConvLocal.Clear(); + wxConvLocal.Clear(); + wxConvISO8859_1.Clear(); #endif } @@ -188,6 +197,11 @@ static size_t decode_utf16(const wchar_t* input, wxUint32& output) #define IGNORE_LIBC 0 +wxMBConv::~wxMBConv() +{ + // nothing to do here +} + size_t wxMBConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const { #if IGNORE_LIBC @@ -195,7 +209,6 @@ size_t wxMBConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const { for (size_t i = 0; i < strlen( psz )+1; i++) buf[i] = (wchar_t) psz[i]; - // printf( "libc %s\n", buf ); return strlen( psz ); } else @@ -214,7 +227,6 @@ size_t wxMBConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const { for (size_t i = 0; i < wxStrlen( psz )+1; i++) buf[i] = (char) psz[i]; - // printf( "libc %s\n", buf ); return wxStrlen( psz ); } else @@ -228,82 +240,49 @@ size_t wxMBConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const const wxWCharBuffer wxMBConv::cMB2WC(const char *psz) const { - if (psz) + if ( psz ) { - size_t nLen = MB2WC((wchar_t *) NULL, psz, 0); // return value excludes /0 - if (nLen == (size_t)-1) - return wxWCharBuffer((wchar_t *) NULL); - wxWCharBuffer buf(nLen); // this allocates nLen1+ - MB2WC((wchar_t *)(const wchar_t *) buf, psz, nLen+1); - return buf; - } - else - return wxWCharBuffer((wchar_t *) NULL); -} + // calculate the length of the buffer needed first + size_t nLen = MB2WC(NULL, psz, 0); + if ( nLen != (size_t)-1 ) + { + // now do the actual conversion + wxWCharBuffer buf(nLen); + MB2WC(buf.data(), psz, nLen + 1); // with the trailing NUL -const wxCharBuffer wxMBConv::cWC2MB(const wchar_t *psz) const -{ - if (psz) - { - size_t nLen = WC2MB((char *) NULL, psz, 0); // return value excludes /0 - if (nLen == (size_t)-1) - return wxCharBuffer((char *) NULL); - wxCharBuffer buf(nLen); // this allocates nLen+1 - WC2MB((char *)(const char *) buf, psz, nLen+1); - // printf( "str %s\n", (const char*) buf ); - return buf; + return buf; + } } - else - return wxCharBuffer((char *) NULL); -} - -// ---------------------------------------------------------------------------- -// standard gdk conversion -// ---------------------------------------------------------------------------- -#ifdef __WXGTK12__ + wxWCharBuffer buf((wchar_t *)NULL); -WXDLLEXPORT_DATA(wxMBConvGdk) wxConvGdk; - -#include - -size_t wxMBConvGdk::MB2WC(wchar_t *buf, const char *psz, size_t n) const -{ - if (buf) - { - return gdk_mbstowcs((GdkWChar *)buf, psz, n); - } - else - { - GdkWChar *nbuf = new GdkWChar[n=strlen(psz)]; - size_t len = gdk_mbstowcs(nbuf, psz, n); - delete[] nbuf; - return len; - } + return buf; } -size_t wxMBConvGdk::WC2MB(char *buf, const wchar_t *psz, size_t n) const +const wxCharBuffer wxMBConv::cWC2MB(const wchar_t *pwz) const { - char *mbstr = gdk_wcstombs((GdkWChar *)psz); - size_t len = mbstr ? strlen(mbstr) : 0; - if (buf) + if ( pwz ) { - if (len > n) - len = n; - memcpy(buf, psz, len); - if (len < n) - buf[len] = 0; + size_t nLen = WC2MB(NULL, pwz, 0); + if ( nLen != (size_t)-1 ) + { + wxCharBuffer buf(nLen); + WC2MB(buf.data(), pwz, nLen + 1); + + return buf; + } } - return len; -} -#endif // GTK > 1.0 + wxCharBuffer buf((char *)NULL); + + return buf; +} // ---------------------------------------------------------------------------- // UTF-7 // ---------------------------------------------------------------------------- -WXDLLEXPORT_DATA(wxMBConvUTF7) wxConvUTF7; +WXDLLIMPEXP_DATA_BASE(wxMBConvUTF7) wxConvUTF7; #if 0 static char utf7_setD[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -334,7 +313,7 @@ size_t wxMBConvUTF7::WC2MB(char * WXUNUSED(buf), // UTF-8 // ---------------------------------------------------------------------------- -WXDLLEXPORT_DATA(wxMBConvUTF8) wxConvUTF8; +WXDLLIMPEXP_DATA_BASE(wxMBConvUTF8) wxConvUTF8; static wxUint32 utf8_max[]= { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff, 0xffffffff }; @@ -439,7 +418,7 @@ size_t wxMBConvUTF8::WC2MB(char *buf, const wchar_t *psz, size_t n) const } if (buf && (lenMB2WC(buf,psz,n) : (size_t)-1; } @@ -544,7 +521,6 @@ const char *IC_CharSet::ms_wcCharsetName = NULL; bool IC_CharSet::ms_wcNeedsSwap = FALSE; IC_CharSet::IC_CharSet(const wxChar *name) - : wxCharacterSet(name) { // Do it the hard way char cname[100]; @@ -596,7 +572,7 @@ IC_CharSet::IC_CharSet(const wxChar *name) { ms_wcCharsetName = NULL; wxLogLastError(wxT("iconv")); - wxLogError(_("Convertion to charset '%s' doesn't work."), name); + wxLogError(_("Conversion to charset '%s' doesn't work."), name); } else { @@ -661,9 +637,12 @@ size_t IC_CharSet::MB2WC(wchar_t *buf, const char *psz, size_t n) // convert to native endianness WC_BSWAP(buf /* _not_ bufPtr */, res) } - - // iconv doesn't seem to set the trailing 0 - buf[res] = 0; + + // NB: iconv was given only strlen(psz) characters on input, and so + // it couldn't convert the trailing zero. Let's do it ourselves + // if there's some room left for it in the output buffer. + if (res < n) + buf[res] = 0; } else { @@ -695,11 +674,7 @@ size_t IC_CharSet::MB2WC(wchar_t *buf, const char *psz, size_t n) size_t IC_CharSet::WC2MB(char *buf, const wchar_t *psz, size_t n) { -#if defined(__BORLANDC__) && (__BORLANDC__ > 0x530) - size_t inbuf = std::wcslen(psz) * SIZEOF_WCHAR_T; -#else - size_t inbuf = ::wcslen(psz) * SIZEOF_WCHAR_T; -#endif + size_t inbuf = wxWcslen(psz) * SIZEOF_WCHAR_T; size_t outbuf = n; size_t res, cres; @@ -723,6 +698,12 @@ size_t IC_CharSet::WC2MB(char *buf, const wchar_t *psz, size_t n) cres = iconv( w2m, ICONV_CHAR_CAST(&psz), &inbuf, &buf, &outbuf ); res = n-outbuf; + + // NB: iconv was given only wcslen(psz) characters on input, and so + // it couldn't convert the trailing zero. Let's do it ourselves + // if there's some room left for it in the output buffer. + if (res < n) + buf[0] = 0; } else { @@ -760,35 +741,58 @@ size_t IC_CharSet::WC2MB(char *buf, const wchar_t *psz, size_t n) // Win32 conversion classes // ============================================================================ -#if defined(__WIN32__) && !defined(__WXMICROWIN__) +#if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXUNIVERSAL__) -extern long wxCharsetToCodepage(const wxChar *charset); // from utils.cpp +// from utils.cpp +extern WXDLLIMPEXP_BASE long wxCharsetToCodepage(const wxChar *charset); +extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding); class CP_CharSet : public wxCharacterSet { public: CP_CharSet(const wxChar* name) - : wxCharacterSet(name) { m_CodePage = wxCharsetToCodepage(name); } + CP_CharSet(wxFontEncoding encoding) + { + m_CodePage = wxEncodingToCodepage(encoding); + } + size_t MB2WC(wchar_t *buf, const char *psz, size_t n) { - size_t len = - MultiByteToWideChar(m_CodePage, 0, psz, -1, buf, buf ? n : 0); - //VS: returns # of written chars for buf!=NULL and *size* - // needed buffer for buf==NULL - return len ? (buf ? len : len-1) : (size_t)-1; + const size_t len = ::MultiByteToWideChar + ( + m_CodePage, // code page + 0, // flags (none) + psz, // input string + -1, // its length (NUL-terminated) + buf, // output string + buf ? n : 0 // size of output buffer + ); + + // note that it returns # of written chars for buf != NULL and *size* + // of the needed buffer for buf == NULL + return len ? (buf ? len : len - 1) : (size_t)-1; } size_t WC2MB(char *buf, const wchar_t *psz, size_t n) { - size_t len = WideCharToMultiByte(m_CodePage, 0, psz, -1, buf, - buf ? n : 0, NULL, NULL); - //VS: returns # of written chars for buf!=NULL and *size* - // needed buffer for buf==NULL - return len ? (buf ? len : len-1) : (size_t)-1; + const size_t len = ::WideCharToMultiByte + ( + m_CodePage, // code page + 0, // flags (none) + psz, // input string + -1, // it is (wide) NUL-terminated + buf, // output buffer + buf ? n : 0, // and its size + NULL, // default "replacement" char + NULL // [out] was it used? + ); + + // see the comment above! + return len ? (buf ? len : len - 1) : (size_t)-1; } bool usable() const @@ -797,7 +801,7 @@ public: public: long m_CodePage; }; -#endif // __WIN32__ +#endif // defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXUNIVERSAL__) // ============================================================================ // wxEncodingConverter based conversion classes @@ -807,17 +811,31 @@ public: class EC_CharSet : public wxCharacterSet { +private: + void Init() + { + m_ok = m2w.Init(m_enc, wxFONTENCODING_UNICODE) && + w2m.Init(wxFONTENCODING_UNICODE, m_enc); + } + public: // temporarily just use wxEncodingConverter stuff, // so that it works while a better implementation is built - EC_CharSet(const wxChar* name) : wxCharacterSet(name), - enc(wxFONTENCODING_SYSTEM) + EC_CharSet(const wxChar* name) { if (name) - enc = wxFontMapper::Get()->CharsetToEncoding(name, FALSE); + m_enc = wxFontMapper::Get()->CharsetToEncoding(name, FALSE); + else + m_enc = wxFONTENCODING_SYSTEM; - m_ok = m2w.Init(enc, wxFONTENCODING_UNICODE) && - w2m.Init(wxFONTENCODING_UNICODE, enc); + Init(); + } + + EC_CharSet(wxFontEncoding enc) + { + m_enc = enc; + + Init(); } size_t MB2WC(wchar_t *buf, const char *psz, size_t WXUNUSED(n)) @@ -830,12 +848,7 @@ public: size_t WC2MB(char *buf, const wchar_t *psz, size_t WXUNUSED(n)) { -#if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) ) \ - || ( defined(__MWERKS__) && defined(__WXMSW__) ) - size_t inbuf = std::wcslen(psz); -#else - size_t inbuf = ::wcslen(psz); -#endif + const size_t inbuf = wxWcslen(psz); if (buf) w2m.Convert(psz,buf); @@ -845,11 +858,13 @@ public: bool usable() const { return m_ok; } public: - wxFontEncoding enc; + wxFontEncoding m_enc; wxEncodingConverter m2w, w2m; // were we initialized successfully? bool m_ok; + + DECLARE_NO_COPY_CLASS(EC_CharSet) }; #endif // wxUSE_FONTMAP @@ -857,37 +872,46 @@ public: // ---------------------------------------------------------------------------- // the function creating the wxCharacterSet for the specified charset on the // current system, trying all possibilities +// +// it uses the name if it is given or encoding if name == NULL // ---------------------------------------------------------------------------- -static wxCharacterSet *wxGetCharacterSet(const wxChar *name) +static wxCharacterSet * +wxGetCharacterSet(const wxChar *name, wxFontEncoding encoding) { // check for the special case of ASCII charset + if ( (!name && encoding == wxFONTENCODING_DEFAULT) #if wxUSE_FONTMAP - if ( wxFontMapper::Get()->CharsetToEncoding(name) == wxFONTENCODING_DEFAULT ) -#else // wxUSE_FONTMAP - if ( !name ) -#endif // wxUSE_FONTMAP/!wxUSE_FONTMAP + || (name && wxFontMapper::Get()-> + CharsetToEncoding(name) == wxFONTENCODING_DEFAULT) +#endif // wxUSE_FONTMAP + ) { // don't convert at all return NULL; } - // the test above must have taken care of this case - wxCHECK_MSG( name, NULL, _T("NULL name must be wxFONTENCODING_DEFAULT") ); - wxCharacterSet *cset; - if ( wxStricmp(name, wxT("UTF8")) == 0 || wxStricmp(name, wxT("UTF-8")) == 0) + if ( (name && + (wxStricmp(name, wxT("UTF8")) == 0 || + wxStricmp(name, wxT("UTF-8")) == 0)) || + encoding == wxFONTENCODING_UTF8 ) { - cset = new ID_CharSet(name, &wxConvUTF8); + cset = new ID_CharSet(&wxConvUTF8); } - else + else // !UTF-8 { #ifdef HAVE_ICONV - cset = new IC_CharSet(name); -#else // !HAVE_ICONV - cset = NULL; -#endif // HAVE_ICONV/!HAVE_ICONV + if ( name ) + { + cset = new IC_CharSet(name); + } + else +#endif // HAVE_ICONV + { + cset = NULL; + } } // it can only be NULL in this case @@ -902,17 +926,17 @@ static wxCharacterSet *wxGetCharacterSet(const wxChar *name) cset = NULL; } -#if defined(__WIN32__) && !defined(__WXMICROWIN__) - cset = new CP_CharSet(name); +#if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXUNIVERSAL__) + cset = name ? new CP_CharSet(name) : new CP_CharSet(encoding); if ( cset->usable() ) return cset; delete cset; cset = NULL; -#endif // __WIN32__ +#endif // defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXUNIVERSAL__) #if wxUSE_FONTMAP - cset = new EC_CharSet(name); + cset = name ? new EC_CharSet(name) : new EC_CharSet(encoding); if ( cset->usable() ) return cset; @@ -920,7 +944,15 @@ static wxCharacterSet *wxGetCharacterSet(const wxChar *name) cset = NULL; #endif // wxUSE_FONTMAP - wxLogError(_("Cannot convert from encoding '%s'!"), name); + wxLogError(_("Cannot convert from encoding '%s'!"), + name ? name + : +#if wxUSE_FONTMAP + wxFontMapper::GetEncodingDescription(encoding).c_str() +#else // !wxUSE_FONTMAP + wxString::Format(_T("%s"), encoding).c_str() +#endif // wxUSE_FONTMAP/!wxUSE_FONTMAP + ); return NULL; } @@ -929,40 +961,57 @@ static wxCharacterSet *wxGetCharacterSet(const wxChar *name) // wxCSConv implementation // ============================================================================ -wxCSConv::wxCSConv(const wxChar *charset) +void wxCSConv::Init() { m_name = (wxChar *)NULL; m_cset = (wxCharacterSet *) NULL; m_deferred = TRUE; +} + +wxCSConv::wxCSConv(const wxChar *charset) +{ + Init(); + m_encoding = wxFONTENCODING_DEFAULT; SetName(charset); } +wxCSConv::wxCSConv(wxFontEncoding encoding) +{ + Init(); + + m_encoding = encoding; +} + wxCSConv::~wxCSConv() { Clear(); } wxCSConv::wxCSConv(const wxCSConv& conv) - : wxMBConv() + : wxMBConv() { - Clear(); + Init(); + SetName(conv.m_name); + m_encoding = conv.m_encoding; } wxCSConv& wxCSConv::operator=(const wxCSConv& conv) { Clear(); + SetName(conv.m_name); + m_encoding = conv.m_encoding; + return *this; } void wxCSConv::Clear() { - if (m_name) - free(m_name); - if (m_cset) - delete m_cset; + free(m_name); + delete m_cset; + m_name = NULL; m_cset = NULL; } @@ -978,9 +1027,12 @@ void wxCSConv::SetName(const wxChar *charset) void wxCSConv::LoadNow() { - if (m_deferred) + if ( m_deferred ) { - if ( !m_name ) + // it would probably be better to make GetSystemEncodingName() always + // available (i.e. even when wxUSE_INTL == 0)? +#if wxUSE_INTL + if ( !m_name && m_encoding == wxFONTENCODING_DEFAULT ) { wxString name = wxLocale::GetSystemEncodingName(); if ( !name.empty() ) @@ -988,9 +1040,10 @@ void wxCSConv::LoadNow() SetName(name); } } +#endif // wxUSE_INTL // wxGetCharacterSet() complains about NULL name - m_cset = m_name ? wxGetCharacterSet(m_name) : NULL; + m_cset = wxGetCharacterSet(m_name, m_encoding); m_deferred = FALSE; } } @@ -1022,12 +1075,7 @@ size_t wxCSConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const return m_cset->WC2MB(buf, psz, n); // latin-1 (direct) -#if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) ) \ - || ( defined(__MWERKS__) && defined(__WXMSW__) ) - size_t len=std::wcslen(psz); -#else - size_t len=::wcslen(psz); -#endif + const size_t len = wxWcslen(psz); if (buf) { for (size_t c = 0; c <= len; c++)