X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/406d283a6409838d72d1490ca5d20fa067b7723b..8bd37efca7eb0de7cdf72167e138f9cabd9b6750:/src/common/strconv.cpp diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 97b58b2497..f2947edfd3 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -15,6 +15,10 @@ // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" +#ifdef __BORLANDC__ + #pragma hdrstop +#endif //__BORLANDC__ + #ifndef WX_PRECOMP #include "wx/intl.h" #include "wx/log.h" @@ -26,11 +30,6 @@ #if wxUSE_WCHAR_T -#ifdef __WINDOWS__ - #include "wx/msw/private.h" - #include "wx/msw/missing.h" -#endif - #ifndef __WXWINCE__ #include #endif @@ -40,6 +39,8 @@ #include #if defined(__WIN32__) && !defined(__WXMICROWIN__) + #include "wx/msw/private.h" + #include "wx/msw/missing.h" #define wxHAVE_WIN32_MB2WC #endif @@ -479,7 +480,7 @@ wxConvBrokenFileNames::wxConvBrokenFileNames(const wxChar *charset) { if ( !charset || wxStricmp(charset, _T("UTF-8")) == 0 || wxStricmp(charset, _T("UTF8")) == 0 ) - m_conv = new wxMBConvUTF8(wxMBConvUTF8::MAP_INVALID_UTF8_TO_OCTAL); + m_conv = new wxMBConvUTF8(wxMBConvUTF8::MAP_INVALID_UTF8_TO_PUA); else m_conv = new wxCSConv(charset); } @@ -2585,7 +2586,7 @@ public: Init( wxCFStringEncFromFontEnc(encoding) ); } - ~wxMBConv_cocoa() + virtual ~wxMBConv_cocoa() { } @@ -2740,7 +2741,7 @@ public: Init( wxMacGetSystemEncFromFontEnc(encoding) ); } - ~wxMBConv_mac() + virtual ~wxMBConv_mac() { OSStatus status = noErr ; if (m_MB2WC_converter) @@ -2773,7 +2774,7 @@ public: wxASSERT_MSG( status == noErr , _("Unable to create TextEncodingConverter")) ; } } - + size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const { CreateIfNeeded() ; @@ -2888,9 +2889,9 @@ public: virtual wxMBConv *Clone() const { return new wxMBConv_mac(*this); } bool IsOk() const - { + { CreateIfNeeded() ; - return m_MB2WC_converter != NULL && m_WC2MB_converter != NULL; + return m_MB2WC_converter != NULL && m_WC2MB_converter != NULL; } protected : @@ -2906,21 +2907,21 @@ protected : class wxMBConv_macUTF8D : public wxMBConv_mac { public : - wxMBConv_macUTF8D() + wxMBConv_macUTF8D() { Init( kTextEncodingUnicodeDefault , kUnicodeNoSubset , kUnicodeUTF8Format ) ; m_uni = NULL; m_uniBack = NULL ; } - - ~wxMBConv_macUTF8D() + + virtual ~wxMBConv_macUTF8D() { if (m_uni!=NULL) DisposeUnicodeToTextInfo(&m_uni); if (m_uniBack!=NULL) DisposeUnicodeToTextInfo(&m_uniBack); } - + size_t WC2MB(char *buf, const wchar_t *psz, size_t n) const { CreateIfNeeded() ; @@ -2950,15 +2951,15 @@ public : ubuf = (UniChar*) psz ; #endif - // ubuf is a non-decomposed UniChar buffer - + // ubuf is a non-decomposed UniChar buffer + ByteCount dcubuflen = byteInLen * 2 + 2 ; ByteCount dcubufread , dcubufwritten ; - UniChar *dcubuf = (UniChar*) malloc( dcubuflen ) ; - - ConvertFromUnicodeToText( m_uni , byteInLen , ubuf , + UniChar *dcubuf = (UniChar*) malloc( dcubuflen ) ; + + ConvertFromUnicodeToText( m_uni , byteInLen , ubuf , kUnicodeDefaultDirectionMask, 0, NULL, NULL, NULL, dcubuflen , &dcubufread , &dcubufwritten , dcubuf ) ; - + // we now convert that decomposed buffer into UTF8 status = TECConvertText( @@ -2983,7 +2984,7 @@ public : return res ; } - + size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const { CreateIfNeeded() ; @@ -2993,25 +2994,25 @@ public : wchar_t *tbuf = NULL ; UniChar* ubuf = NULL ; size_t res = 0 ; - + if (buf == NULL) { // Apple specs say at least 32 n = wxMax( 32, byteInLen ) ; tbuf = (wchar_t*) malloc( n * SIZEOF_WCHAR_T ) ; } - + ByteCount byteBufferLen = n * sizeof( UniChar ) ; - + #if SIZEOF_WCHAR_T == 4 ubuf = (UniChar*) malloc( byteBufferLen + 2 ) ; #else ubuf = (UniChar*) (buf ? buf : tbuf) ; #endif - + ByteCount dcubuflen = byteBufferLen * 2 + 2 ; ByteCount dcubufread , dcubufwritten ; - UniChar *dcubuf = (UniChar*) malloc( dcubuflen ) ; + UniChar *dcubuf = (UniChar*) malloc( dcubuflen ) ; status = TECConvertText( m_MB2WC_converter, (ConstTextPtr) psz, byteInLen, &byteInLen, @@ -3019,16 +3020,16 @@ public : // we have to terminate here, because n might be larger for the trailing zero, and if UniChar // is not properly terminated we get random characters at the end dcubuf[byteOutLen / sizeof( UniChar ) ] = 0 ; - + // now from the decomposed UniChar to properly composed uniChar - ConvertFromUnicodeToText( m_uniBack , byteOutLen , dcubuf , + ConvertFromUnicodeToText( m_uniBack , byteOutLen , dcubuf , kUnicodeDefaultDirectionMask, 0, NULL, NULL, NULL, dcubuflen , &dcubufread , &dcubufwritten , ubuf ) ; free( dcubuf ); byteOutLen = dcubufwritten ; ubuf[byteOutLen / sizeof( UniChar ) ] = 0 ; - - + + #if SIZEOF_WCHAR_T == 4 wxMBConvUTF16 converter ; res = converter.MB2WC( (buf ? buf : tbuf), (const char*)ubuf, n ) ; @@ -3036,13 +3037,13 @@ public : #else res = byteOutLen / sizeof( UniChar ) ; #endif - + if ( buf == NULL ) free(tbuf) ; - + if ( buf && res < n) buf[res] = 0; - + return res ; } @@ -3056,16 +3057,16 @@ public : m_map.otherEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault, kUnicodeCanonicalDecompVariant, kTextEncodingDefaultFormat); m_map.mappingVersion = kUnicodeUseLatestMapping; - - OSStatus err = CreateUnicodeToTextInfo(&m_map, &m_uni); + + OSStatus err = CreateUnicodeToTextInfo(&m_map, &m_uni); wxASSERT_MSG( err == noErr , _(" Couldn't create the UnicodeConverter")) ; - + m_map.unicodeEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault, kUnicodeNoSubset, kTextEncodingDefaultFormat); m_map.otherEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault, kUnicodeCanonicalCompVariant, kTextEncodingDefaultFormat); m_map.mappingVersion = kUnicodeUseLatestMapping; - err = CreateUnicodeToTextInfo(&m_map, &m_uniBack); + err = CreateUnicodeToTextInfo(&m_map, &m_uniBack); wxASSERT_MSG( err == noErr , _(" Couldn't create the UnicodeConverter")) ; } } @@ -3073,7 +3074,7 @@ protected : mutable UnicodeToTextInfo m_uni; mutable UnicodeToTextInfo m_uniBack; mutable UnicodeMapping m_map; -}; +}; #endif // defined(__WXMAC__) && defined(TARGET_CARBON) // ============================================================================ @@ -3278,7 +3279,7 @@ wxMBConv *wxCSConv::DoCreate() const wxLogTrace(TRACE_STRCONV, wxT("creating conversion for %s"), (m_name ? m_name - : wxFontMapperBase::GetEncodingName(m_encoding).c_str())); + : (const wxChar*)wxFontMapperBase::GetEncodingName(m_encoding).c_str())); #endif // wxUSE_FONTMAP // check for the special case of ASCII or ISO8859-1 charset: as we have @@ -3340,7 +3341,7 @@ 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 + // 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 ) @@ -3481,9 +3482,9 @@ wxMBConv *wxCSConv::DoCreate() const m_name ? m_name : #if wxUSE_FONTMAP - wxFontMapperBase::GetEncodingDescription(m_encoding).c_str() + (const wxChar*)wxFontMapperBase::GetEncodingDescription(m_encoding).c_str() #else // !wxUSE_FONTMAP - wxString::Format(_("encoding %i"), m_encoding).c_str() + (const wxChar*)wxString::Format(_("encoding %i"), m_encoding).c_str() #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP ); @@ -3499,20 +3500,60 @@ void wxCSConv::CreateConvIfNeeded() const { wxCSConv *self = (wxCSConv *)this; // const_cast -#if wxUSE_INTL // if we don't have neither the name nor the encoding, use the default // encoding for this system if ( !m_name && m_encoding == wxFONTENCODING_SYSTEM ) { - self->m_name = wxStrdup(wxLocale::GetSystemEncodingName()); - } +#if wxUSE_INTL + self->m_encoding = wxLocale::GetSystemEncoding(); +#else + // fallback to some reasonable default: + self->m_encoding = wxFONTENCODING_ISO8859_1; #endif // wxUSE_INTL + } self->m_convReal = DoCreate(); self->m_deferred = false; } } +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(); @@ -3575,45 +3616,103 @@ size_t wxCSConv::GetMBNulLen() const return 1; } + +#if wxUSE_UNICODE + +wxWCharBuffer wxSafeConvertMB2WX(const char *s) +{ + if ( !s ) + return wxWCharBuffer(); + + wxWCharBuffer wbuf(wxConvLibc.cMB2WX(s)); + if ( !wbuf ) + wbuf = wxConvUTF8.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; \ + klass* WXDLLIMPEXP_BASE 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,