X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/739cb14a31adcd3af2cf3ef14677e5ea32af24ca..8168167976dc3cc5f5223a21e1a62ba91a4f77b3:/src/common/strconv.cpp diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 33a2e7a161..95ef424042 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -16,6 +16,9 @@ #include "wx/wxprec.h" #ifndef WX_PRECOMP + #ifdef __WXMSW__ + #include "wx/msw/missing.h" + #endif #include "wx/intl.h" #include "wx/log.h" #include "wx/utils.h" @@ -28,7 +31,6 @@ #ifdef __WINDOWS__ #include "wx/msw/private.h" - #include "wx/msw/missing.h" #endif #ifndef __WXWINCE__ @@ -1668,7 +1670,7 @@ wxMBConv_iconv::wxMBConv_iconv(const wxChar *name) #if wxUSE_FONTMAP const wxChar **names = wxFontMapperBase::GetAllEncodingNames(WC_ENC); #else // !wxUSE_FONTMAP - static const wxChar *names[] = + static const wxChar *names_static[] = { #if SIZEOF_WCHAR_T == 4 _T("UCS-4"), @@ -1677,6 +1679,7 @@ wxMBConv_iconv::wxMBConv_iconv(const wxChar *name) #endif NULL }; + const wxChar **names = names_static; #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP for ( ; *names && ms_wcCharsetName.empty(); ++names ) @@ -1806,8 +1809,8 @@ size_t wxMBConv_iconv::MB2WC(wchar_t *buf, const char *psz, size_t n) const } #if wxUSE_THREADS - // NB: iconv() is MT-safe, but each thread must use it's own iconv_t handle. - // Unfortunately there is a couple of global wxCSConv objects such as + // NB: iconv() is MT-safe, but each thread must use its own iconv_t handle. + // Unfortunately there are a couple of global wxCSConv objects such as // wxConvLocal that are used all over wx code, so we have to make sure // the handle is used by at most one thread at the time. Otherwise // only a few wx classes would be safe to use from non-main threads @@ -2228,11 +2231,11 @@ private: int verMaj, verMin; switch ( wxGetOsVersion(&verMaj, &verMin) ) { - case wxWIN95: + case wxOS_WINDOWS_9X: s_isWin98Or2k = verMaj >= 4 && verMin >= 10; break; - case wxWINDOWS_NT: + case wxOS_WINDOWS_NT: s_isWin98Or2k = verMaj >= 5; break; @@ -2584,7 +2587,7 @@ public: Init( wxCFStringEncFromFontEnc(encoding) ); } - ~wxMBConv_cocoa() + virtual ~wxMBConv_cocoa() { } @@ -2739,7 +2742,7 @@ public: Init( wxMacGetSystemEncFromFontEnc(encoding) ); } - ~wxMBConv_mac() + virtual ~wxMBConv_mac() { OSStatus status = noErr ; if (m_MB2WC_converter) @@ -2772,7 +2775,7 @@ public: wxASSERT_MSG( status == noErr , _("Unable to create TextEncodingConverter")) ; } } - + size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const { CreateIfNeeded() ; @@ -2887,9 +2890,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 : @@ -2905,17 +2908,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() { - DisposeUnicodeToTextInfo(&m_uni); + 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() ; @@ -2945,15 +2952,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( @@ -2978,7 +2985,69 @@ public : return res ; } - + + size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const + { + CreateIfNeeded() ; + OSStatus status = noErr ; + ByteCount byteOutLen ; + ByteCount byteInLen = strlen(psz) + 1; + 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 ) ; + + status = TECConvertText( + m_MB2WC_converter, (ConstTextPtr) psz, byteInLen, &byteInLen, + (TextPtr) dcubuf, dcubuflen, &byteOutLen); + // 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 , + 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 ) ; + free( ubuf ) ; +#else + res = byteOutLen / sizeof( UniChar ) ; +#endif + + if ( buf == NULL ) + free(tbuf) ; + + if ( buf && res < n) + buf[res] = 0; + + return res ; + } + virtual void CreateIfNeeded() const { wxMBConv_mac::CreateIfNeeded() ; @@ -2989,15 +3058,24 @@ 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); wxASSERT_MSG( err == noErr , _(" Couldn't create the UnicodeConverter")) ; } } protected : mutable UnicodeToTextInfo m_uni; + mutable UnicodeToTextInfo m_uniBack; mutable UnicodeMapping m_map; -}; +}; #endif // defined(__WXMAC__) && defined(TARGET_CARBON) // ============================================================================ @@ -3230,7 +3308,9 @@ wxMBConv *wxCSConv::DoCreate() const #endif // !wxUSE_FONTMAP { wxString name(m_name); +#if wxUSE_FONTMAP wxFontEncoding encoding(m_encoding); +#endif if ( !name.empty() ) { @@ -3261,20 +3341,26 @@ wxMBConv *wxCSConv::DoCreate() const } const wxChar** names = wxFontMapperBase::GetAllEncodingNames(encoding); - - for ( ; *names; ++names ) + // 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 ) { - wxMBConv_iconv *conv = new wxMBConv_iconv(*names); - if ( conv->IsOk() ) + for ( ; *names; ++names ) { - gs_nameCache[encoding] = *names; - return conv; + wxMBConv_iconv *conv = new wxMBConv_iconv(*names); + if ( conv->IsOk() ) + { + gs_nameCache[encoding] = *names; + return conv; + } + + delete conv; } - delete conv; + gs_nameCache[encoding] = _T(""); // cache the failure } - - gs_nameCache[encoding] = _T(""); // cache the failure } #endif // wxUSE_FONTMAP } @@ -3385,10 +3471,10 @@ wxMBConv *wxCSConv::DoCreate() const // NB: This is a hack to prevent deadlock. What could otherwise happen // in Unicode build: wxConvLocal creation ends up being here // because of some failure and logs the error. But wxLog will try to - // attach timestamp, for which it will need wxConvLocal (to convert - // time to char* and then wchar_t*), but that fails, tries to log - // error, but wxLog has a (already locked) critical section that - // guards static buffer. + // attach a timestamp, for which it will need wxConvLocal (to convert + // time to char* and then wchar_t*), but that fails, tries to log the + // error, but wxLog has an (already locked) critical section that + // guards the static buffer. static bool alreadyLoggingError = false; if (!alreadyLoggingError) { @@ -3399,7 +3485,7 @@ wxMBConv *wxCSConv::DoCreate() const #if wxUSE_FONTMAP wxFontMapperBase::GetEncodingDescription(m_encoding).c_str() #else // !wxUSE_FONTMAP - wxString::Format(_("encoding %s"), m_encoding).c_str() + wxString::Format(_("encoding %i"), m_encoding).c_str() #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP ); @@ -3415,14 +3501,17 @@ 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 ) { +#if wxUSE_INTL self->m_name = wxStrdup(wxLocale::GetSystemEncodingName()); - } +#else + // fallback to some reasonable default: + self->m_encoding = wxFONTENCODING_ISO8859_1; #endif // wxUSE_INTL + } self->m_convReal = DoCreate(); self->m_deferred = false; @@ -3507,7 +3596,7 @@ static wxCSConv wxConvLocalObj(wxFONTENCODING_SYSTEM); static wxCSConv wxConvISO8859_1Obj(wxFONTENCODING_ISO8859_1); static wxMBConvUTF7 wxConvUTF7Obj; static wxMBConvUTF8 wxConvUTF8Obj; -#ifdef __WXOSX__ +#if defined(__WXMAC__) && defined(TARGET_CARBON) static wxMBConv_macUTF8D wxConvMacUTF8DObj; #endif WXDLLIMPEXP_DATA_BASE(wxMBConv&) wxConvLibc = wxConvLibcObj; @@ -3519,7 +3608,11 @@ WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvCurrent = &wxConvLibcObj; WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvUI = &wxConvLocal; WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvFileName = & #ifdef __WXOSX__ +#if defined(__WXMAC__) && defined(TARGET_CARBON) wxConvMacUTF8DObj; +#else + wxConvUTF8Obj; +#endif #else wxConvLibcObj; #endif