X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/57bd4c6031d438f11af0ec540136f49a928b923c..1a1f3e4b53fd5d1515b16905edf4250dfb2fc676:/src/common/strconv.cpp diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 95ef424042..843c84e046 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -15,10 +15,11 @@ // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" +#ifdef __BORLANDC__ + #pragma hdrstop +#endif //__BORLANDC__ + #ifndef WX_PRECOMP - #ifdef __WXMSW__ - #include "wx/msw/missing.h" - #endif #include "wx/intl.h" #include "wx/log.h" #include "wx/utils.h" @@ -29,10 +30,6 @@ #if wxUSE_WCHAR_T -#ifdef __WINDOWS__ - #include "wx/msw/private.h" -#endif - #ifndef __WXWINCE__ #include #endif @@ -42,6 +39,8 @@ #include #if defined(__WIN32__) && !defined(__WXMICROWIN__) + #include "wx/msw/private.h" + #include "wx/msw/missing.h" #define wxHAVE_WIN32_MB2WC #endif @@ -477,11 +476,11 @@ size_t wxMBConvLibc::WC2MB(char *buf, const wchar_t *psz, size_t n) const #ifdef __UNIX__ -wxConvBrokenFileNames::wxConvBrokenFileNames(const wxChar *charset) +wxConvBrokenFileNames::wxConvBrokenFileNames(const wxString& charset) { - if ( !charset || wxStricmp(charset, _T("UTF-8")) == 0 - || wxStricmp(charset, _T("UTF8")) == 0 ) - m_conv = new wxMBConvUTF8(wxMBConvUTF8::MAP_INVALID_UTF8_TO_OCTAL); + if ( wxStricmp(charset, _T("UTF-8")) == 0 || + wxStricmp(charset, _T("UTF8")) == 0 ) + m_conv = new wxMBConvUTF8(wxMBConvUTF8::MAP_INVALID_UTF8_TO_PUA); else m_conv = new wxCSConv(charset); } @@ -1589,7 +1588,7 @@ wxMBConvUTF32swap::FromWChar(char *dst, size_t dstLen, class wxMBConv_iconv : public wxMBConv { public: - wxMBConv_iconv(const wxChar *name); + wxMBConv_iconv(const char *name); virtual ~wxMBConv_iconv(); virtual size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const; @@ -1598,9 +1597,13 @@ public: // classify this encoding as explained in wxMBConv::GetMBNulLen() comment virtual size_t GetMBNulLen() const; +#if wxUSE_UNICODE_UTF8 + virtual bool IsUTF8() const; +#endif + virtual wxMBConv *Clone() const { - wxMBConv_iconv *p = new wxMBConv_iconv(m_name); + wxMBConv_iconv *p = new wxMBConv_iconv(m_name.ToAscii()); p->m_minMBCharWidth = m_minMBCharWidth; return p; } @@ -1638,7 +1641,7 @@ private: }; // make the constructor available for unit testing -WXDLLIMPEXP_BASE wxMBConv* new_wxMBConv_iconv( const wxChar* name ) +WXDLLIMPEXP_BASE wxMBConv* new_wxMBConv_iconv( const char* name ) { wxMBConv_iconv* result = new wxMBConv_iconv( name ); if ( !result->IsOk() ) @@ -1653,15 +1656,11 @@ WXDLLIMPEXP_BASE wxMBConv* new_wxMBConv_iconv( const wxChar* name ) wxString wxMBConv_iconv::ms_wcCharsetName; bool wxMBConv_iconv::ms_wcNeedsSwap = false; -wxMBConv_iconv::wxMBConv_iconv(const wxChar *name) +wxMBConv_iconv::wxMBConv_iconv(const char *name) : m_name(name) { m_minMBCharWidth = 0; - // iconv operates with chars, not wxChars, but luckily it uses only ASCII - // names for the charsets - const wxCharBuffer cname(wxString(name).ToAscii()); - // check for charset that represents wchar_t: if ( ms_wcCharsetName.empty() ) { @@ -1698,13 +1697,13 @@ wxMBConv_iconv::wxMBConv_iconv(const wxChar *name) wxLogTrace(TRACE_STRCONV, _T(" trying charset \"%s\""), nameXE.c_str()); - m2w = iconv_open(nameXE.ToAscii(), cname); + m2w = iconv_open(nameXE.ToAscii(), name); if ( m2w == ICONV_T_INVALID ) { // try charset w/o bytesex info (e.g. "UCS4") wxLogTrace(TRACE_STRCONV, _T(" trying charset \"%s\""), nameCS.c_str()); - m2w = iconv_open(nameCS.ToAscii(), cname); + m2w = iconv_open(nameCS.ToAscii(), name); // and check for bytesex ourselves: if ( m2w != ICONV_T_INVALID ) @@ -1747,14 +1746,14 @@ wxMBConv_iconv::wxMBConv_iconv(const wxChar *name) wxLogTrace(TRACE_STRCONV, wxT("iconv wchar_t charset is \"%s\"%s"), - ms_wcCharsetName.empty() ? _T("") - : ms_wcCharsetName.c_str(), + ms_wcCharsetName.empty() ? wxString("") + : ms_wcCharsetName, ms_wcNeedsSwap ? _T(" (needs swap)") : _T("")); } else // we already have ms_wcCharsetName { - m2w = iconv_open(ms_wcCharsetName.ToAscii(), cname); + m2w = iconv_open(ms_wcCharsetName.ToAscii(), name); } if ( ms_wcCharsetName.empty() ) @@ -1763,12 +1762,12 @@ wxMBConv_iconv::wxMBConv_iconv(const wxChar *name) } else { - w2m = iconv_open(cname, ms_wcCharsetName.ToAscii()); + w2m = iconv_open(name, ms_wcCharsetName.ToAscii()); if ( w2m == ICONV_T_INVALID ) { wxLogTrace(TRACE_STRCONV, wxT("\"%s\" -> \"%s\" works but not the converse!?"), - ms_wcCharsetName.c_str(), cname.data()); + ms_wcCharsetName.c_str(), name); } } } @@ -1957,7 +1956,7 @@ size_t wxMBConv_iconv::GetMBNulLen() const wxMutexLocker lock(self->m_iconvMutex); #endif - wchar_t *wnul = L""; + const wchar_t *wnul = L""; char buf[8]; // should be enough for NUL in any encoding size_t inLen = sizeof(wchar_t), outLen = WXSIZEOF(buf); @@ -1976,6 +1975,14 @@ size_t wxMBConv_iconv::GetMBNulLen() const return m_minMBCharWidth; } +#if wxUSE_UNICODE_UTF8 +bool wxMBConv_iconv::IsUTF8() const +{ + return wxStricmp(m_name, "UTF-8") == 0 || + wxStricmp(m_name, "UTF8") == 0; +} +#endif + #endif // HAVE_ICONV @@ -1987,7 +1994,7 @@ size_t wxMBConv_iconv::GetMBNulLen() const // from utils.cpp #if wxUSE_FONTMAP -extern WXDLLIMPEXP_BASE long wxCharsetToCodepage(const wxChar *charset); +extern WXDLLIMPEXP_BASE long wxCharsetToCodepage(const char *charset); extern WXDLLIMPEXP_BASE long wxEncodingToCodepage(wxFontEncoding encoding); #endif @@ -2008,7 +2015,7 @@ public: } #if wxUSE_FONTMAP - wxMBConv_win32(const wxChar* name) + wxMBConv_win32(const char* name) { m_CodePage = wxCharsetToCodepage(name); m_minMBCharWidth = 0; @@ -2036,12 +2043,12 @@ public: // http://msdn.microsoft.com/library/en-us/intl/unicode_17si.asp if ( m_CodePage == CP_UTF8 ) { - return wxConvUTF8.MB2WC(buf, psz, n); + return wxMBConvUTF8().MB2WC(buf, psz, n); } if ( m_CodePage == CP_UTF7 ) { - return wxConvUTF7.MB2WC(buf, psz, n); + return wxMBConvUTF7().MB2WC(buf, psz, n); } int flags = 0; @@ -2731,7 +2738,7 @@ public: } #if wxUSE_FONTMAP - wxMBConv_mac(const wxChar* name) + wxMBConv_mac(const char* name) { Init( wxMacGetSystemEncFromFontEnc( wxFontMapperBase::Get()->CharsetToEncoding(name, false) ) ); } @@ -3096,7 +3103,7 @@ private: public: // temporarily just use wxEncodingConverter stuff, // so that it works while a better implementation is built - wxMBConv_wxwin(const wxChar* name) + wxMBConv_wxwin(const char* name) { if (name) m_enc = wxFontMapperBase::Get()->CharsetToEncoding(name, false); @@ -3169,7 +3176,7 @@ private: }; // make the constructors available for unit testing -WXDLLIMPEXP_BASE wxMBConv* new_wxMBConv_wxwin( const wxChar* name ) +WXDLLIMPEXP_BASE wxMBConv* new_wxMBConv_wxwin( const char* name ) { wxMBConv_wxwin* result = new wxMBConv_wxwin( name ); if ( !result->IsOk() ) @@ -3194,13 +3201,13 @@ void wxCSConv::Init() m_deferred = true; } -wxCSConv::wxCSConv(const wxChar *charset) +wxCSConv::wxCSConv(const wxString& charset) { Init(); - if ( charset ) + if ( !charset.empty() ) { - SetName(charset); + SetName(charset.ToAscii()); } #if wxUSE_FONTMAP @@ -3257,11 +3264,11 @@ void wxCSConv::Clear() m_convReal = NULL; } -void wxCSConv::SetName(const wxChar *charset) +void wxCSConv::SetName(const char *charset) { if (charset) { - m_name = wxStrdup(charset); + m_name = strdup(charset); m_deferred = true; } } @@ -3280,7 +3287,7 @@ wxMBConv *wxCSConv::DoCreate() const wxLogTrace(TRACE_STRCONV, wxT("creating conversion for %s"), (m_name ? m_name - : wxFontMapperBase::GetEncodingName(m_encoding).c_str())); + : (const char*)wxFontMapperBase::GetEncodingName(m_encoding).mb_str())); #endif // wxUSE_FONTMAP // check for the special case of ASCII or ISO8859-1 charset: as we have @@ -3307,14 +3314,13 @@ wxMBConv *wxCSConv::DoCreate() const if ( m_name ) #endif // !wxUSE_FONTMAP { - wxString name(m_name); #if wxUSE_FONTMAP wxFontEncoding encoding(m_encoding); #endif - if ( !name.empty() ) + if ( m_name ) { - wxMBConv_iconv *conv = new wxMBConv_iconv(name); + wxMBConv_iconv *conv = new wxMBConv_iconv(m_name); if ( conv->IsOk() ) return conv; @@ -3322,7 +3328,7 @@ wxMBConv *wxCSConv::DoCreate() const #if wxUSE_FONTMAP encoding = - wxFontMapperBase::Get()->CharsetToEncoding(name, false); + wxFontMapperBase::Get()->CharsetToEncoding(m_name, false); #endif // wxUSE_FONTMAP } #if wxUSE_FONTMAP @@ -3333,7 +3339,7 @@ wxMBConv *wxCSConv::DoCreate() const if ( it->second.empty() ) return NULL; - wxMBConv_iconv *conv = new wxMBConv_iconv(it->second); + wxMBConv_iconv *conv = new wxMBConv_iconv(it->second.ToAscii()); if ( conv->IsOk() ) return conv; @@ -3341,15 +3347,19 @@ wxMBConv *wxCSConv::DoCreate() const } const wxChar** names = wxFontMapperBase::GetAllEncodingNames(encoding); - // CS : in case this does not return valid names (eg for MacRoman) encoding - // got a 'failure' entry in the cache all the same, although it just has to - // be created using a different method, so only store failed iconv creation - // attempts (or perhaps we shoulnd't do this at all ?) + // CS : in case this does not return valid names (eg for MacRoman) + // encoding got a 'failure' entry in the cache all the same, + // although it just has to be created using a different method, so + // only store failed iconv creation attempts (or perhaps we + // shoulnd't do this at all ?) if ( names[0] != NULL ) { for ( ; *names; ++names ) { - wxMBConv_iconv *conv = new wxMBConv_iconv(*names); + // FIXME-UTF8: wxFontMapperBase::GetAllEncodingNames() + // will need changes that will obsolete this + wxString name(*names); + wxMBConv_iconv *conv = new wxMBConv_iconv(name.ToAscii()); if ( conv->IsOk() ) { gs_nameCache[encoding] = *names; @@ -3483,9 +3493,9 @@ wxMBConv *wxCSConv::DoCreate() const m_name ? m_name : #if wxUSE_FONTMAP - wxFontMapperBase::GetEncodingDescription(m_encoding).c_str() + (const char*)wxFontMapperBase::GetEncodingDescription(m_encoding).ToAscii() #else // !wxUSE_FONTMAP - wxString::Format(_("encoding %i"), m_encoding).c_str() + (const char*)wxString::Format(_("encoding %i"), m_encoding).ToAscii() #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP ); @@ -3506,7 +3516,7 @@ void wxCSConv::CreateConvIfNeeded() const if ( !m_name && m_encoding == wxFONTENCODING_SYSTEM ) { #if wxUSE_INTL - self->m_name = wxStrdup(wxLocale::GetSystemEncodingName()); + self->m_encoding = wxLocale::GetSystemEncoding(); #else // fallback to some reasonable default: self->m_encoding = wxFONTENCODING_ISO8859_1; @@ -3518,6 +3528,43 @@ void wxCSConv::CreateConvIfNeeded() const } } +bool wxCSConv::IsOk() const +{ + CreateConvIfNeeded(); + + // special case: no convReal created for wxFONTENCODING_ISO8859_1 + if ( m_encoding == wxFONTENCODING_ISO8859_1 ) + return true; // always ok as we do it ourselves + + // m_convReal->IsOk() is called at its own creation, so we know it must + // be ok if m_convReal is non-NULL + return m_convReal != NULL; +} + +size_t wxCSConv::ToWChar(wchar_t *dst, size_t dstLen, + const char *src, size_t srcLen) const +{ + CreateConvIfNeeded(); + + if (m_convReal) + return m_convReal->ToWChar(dst, dstLen, src, srcLen); + + // latin-1 (direct) + return wxMBConv::ToWChar(dst, dstLen, src, srcLen); +} + +size_t wxCSConv::FromWChar(char *dst, size_t dstLen, + const wchar_t *src, size_t srcLen) const +{ + CreateConvIfNeeded(); + + if (m_convReal) + return m_convReal->FromWChar(dst, dstLen, src, srcLen); + + // latin-1 (direct) + return wxMBConv::FromWChar(dst, dstLen, src, srcLen); +} + size_t wxCSConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const { CreateConvIfNeeded(); @@ -3577,48 +3624,122 @@ size_t wxCSConv::GetMBNulLen() const return m_convReal->GetMBNulLen(); } + // otherwise, we are ISO-8859-1 return 1; } +#if wxUSE_UNICODE_UTF8 +bool wxCSConv::IsUTF8() const +{ + CreateConvIfNeeded(); + + if ( m_convReal ) + { + return m_convReal->IsUTF8(); + } + + // otherwise, we are ISO-8859-1 + return false; +} +#endif + + +#if wxUSE_UNICODE + +wxWCharBuffer wxSafeConvertMB2WX(const char *s) +{ + if ( !s ) + return wxWCharBuffer(); + + wxWCharBuffer wbuf(wxConvLibc.cMB2WX(s)); + if ( !wbuf ) + wbuf = wxMBConvUTF8().cMB2WX(s); + if ( !wbuf ) + wbuf = wxConvISO8859_1.cMB2WX(s); + + return wbuf; +} + +wxCharBuffer wxSafeConvertWX2MB(const wchar_t *ws) +{ + if ( !ws ) + return wxCharBuffer(); + + wxCharBuffer buf(wxConvLibc.cWX2MB(ws)); + if ( !buf ) + buf = wxMBConvUTF8(wxMBConvUTF8::MAP_INVALID_UTF8_TO_OCTAL).cWX2MB(ws); + + return buf; +} + +#endif // wxUSE_UNICODE + // ---------------------------------------------------------------------------- // globals // ---------------------------------------------------------------------------- +// NB: The reason why we create converted objects in this convoluted way, +// using a factory function instead of global variable, is that they +// may be used at static initialization time (some of them are used by +// wxString ctors and there may be a global wxString object). In other +// words, possibly _before_ the converter global object would be +// initialized. + +#undef wxConvLibc +#undef wxConvUTF8 +#undef wxConvUTF7 +#undef wxConvLocal +#undef wxConvISO8859_1 + +#define WX_DEFINE_GLOBAL_CONV2(klass, impl_klass, name, ctor_args) \ + WXDLLIMPEXP_DATA_BASE(klass*) name##Ptr = NULL; \ + WXDLLIMPEXP_BASE klass* wxGet_##name##Ptr() \ + { \ + static impl_klass name##Obj ctor_args; \ + return &name##Obj; \ + } \ + /* this ensures that all global converter objects are created */ \ + /* by the time static initialization is done, i.e. before any */ \ + /* thread is launched: */ \ + static klass* gs_##name##instance = wxGet_##name##Ptr() + +#define WX_DEFINE_GLOBAL_CONV(klass, name, ctor_args) \ + WX_DEFINE_GLOBAL_CONV2(klass, klass, name, ctor_args) + #ifdef __WINDOWS__ - static wxMBConv_win32 wxConvLibcObj; + WX_DEFINE_GLOBAL_CONV2(wxMBConv, wxMBConv_win32, wxConvLibc, wxEMPTY_PARAMETER_VALUE); #elif defined(__WXMAC__) && !defined(__MACH__) - static wxMBConv_mac wxConvLibcObj ; + WX_DEFINE_GLOBAL_CONV2(wxMBConv, wxMBConv_mac, wxConvLibc, wxEMPTY_PARAMETER_VALUE); #else - static wxMBConvLibc wxConvLibcObj; + WX_DEFINE_GLOBAL_CONV2(wxMBConv, wxMBConvLibc, wxConvLibc, wxEMPTY_PARAMETER_VALUE); #endif -static wxCSConv wxConvLocalObj(wxFONTENCODING_SYSTEM); -static wxCSConv wxConvISO8859_1Obj(wxFONTENCODING_ISO8859_1); -static wxMBConvUTF7 wxConvUTF7Obj; -static wxMBConvUTF8 wxConvUTF8Obj; +WX_DEFINE_GLOBAL_CONV(wxMBConvUTF8, wxConvUTF8, wxEMPTY_PARAMETER_VALUE); +WX_DEFINE_GLOBAL_CONV(wxMBConvUTF7, wxConvUTF7, wxEMPTY_PARAMETER_VALUE); + +WX_DEFINE_GLOBAL_CONV(wxCSConv, wxConvLocal, (wxFONTENCODING_SYSTEM)); +WX_DEFINE_GLOBAL_CONV(wxCSConv, wxConvISO8859_1, (wxFONTENCODING_ISO8859_1)); + +WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvCurrent = wxGet_wxConvLibcPtr(); +WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvUI = wxGet_wxConvLocalPtr(); + #if defined(__WXMAC__) && defined(TARGET_CARBON) static wxMBConv_macUTF8D wxConvMacUTF8DObj; #endif -WXDLLIMPEXP_DATA_BASE(wxMBConv&) wxConvLibc = wxConvLibcObj; -WXDLLIMPEXP_DATA_BASE(wxCSConv&) wxConvLocal = wxConvLocalObj; -WXDLLIMPEXP_DATA_BASE(wxCSConv&) wxConvISO8859_1 = wxConvISO8859_1Obj; -WXDLLIMPEXP_DATA_BASE(wxMBConvUTF7&) wxConvUTF7 = wxConvUTF7Obj; -WXDLLIMPEXP_DATA_BASE(wxMBConvUTF8&) wxConvUTF8 = wxConvUTF8Obj; -WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvCurrent = &wxConvLibcObj; -WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvUI = &wxConvLocal; -WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvFileName = & +WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvFileName = #ifdef __WXOSX__ #if defined(__WXMAC__) && defined(TARGET_CARBON) - wxConvMacUTF8DObj; -#else - wxConvUTF8Obj; -#endif + &wxConvMacUTF8DObj; #else - wxConvLibcObj; + wxGet_wxConvUTF8Ptr(); #endif +#else // !__WXOSX__ + wxGet_wxConvLibcPtr(); +#endif // __WXOSX__/!__WXOSX__ #else // !wxUSE_WCHAR_T +// FIXME-UTF8: remove this, wxUSE_WCHAR_T is required now // stand-ins in absence of wchar_t WXDLLIMPEXP_DATA_BASE(wxMBConv) wxConvLibc, wxConvISO8859_1,