]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/strconv.cpp
Implemented the same simple API for creating customized
[wxWidgets.git] / src / common / strconv.cpp
index a603d02f18eeaee87abec04920ce164955230fe9..9d093143fe7f60cade95290da2010884826be7fc 100644 (file)
 // For compilers that support precompilation, includes "wx.h".
 #include "wx/wxprec.h"
 
 // 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"
 #ifndef WX_PRECOMP
     #include "wx/intl.h"
     #include "wx/log.h"
 
 #if wxUSE_WCHAR_T
 
 
 #if wxUSE_WCHAR_T
 
-#ifdef __WINDOWS__
-    #include "wx/msw/private.h"
-    #include "wx/msw/missing.h"
-#endif
-
 #ifndef __WXWINCE__
 #include <errno.h>
 #endif
 #ifndef __WXWINCE__
 #include <errno.h>
 #endif
@@ -40,6 +39,8 @@
 #include <stdlib.h>
 
 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
 #include <stdlib.h>
 
 #if defined(__WIN32__) && !defined(__WXMICROWIN__)
+    #include "wx/msw/private.h"
+    #include "wx/msw/missing.h"
     #define wxHAVE_WIN32_MB2WC
 #endif
 
     #define wxHAVE_WIN32_MB2WC
 #endif
 
@@ -1668,7 +1669,7 @@ wxMBConv_iconv::wxMBConv_iconv(const wxChar *name)
 #if wxUSE_FONTMAP
         const wxChar **names = wxFontMapperBase::GetAllEncodingNames(WC_ENC);
 #else // !wxUSE_FONTMAP
 #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"),
         {
 #if SIZEOF_WCHAR_T == 4
             _T("UCS-4"),
@@ -1677,6 +1678,7 @@ wxMBConv_iconv::wxMBConv_iconv(const wxChar *name)
 #endif
             NULL
         };
 #endif
             NULL
         };
+        const wxChar **names = names_static;
 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
 
         for ( ; *names && ms_wcCharsetName.empty(); ++names )
 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
 
         for ( ; *names && ms_wcCharsetName.empty(); ++names )
@@ -2228,11 +2230,11 @@ private:
             int verMaj, verMin;
             switch ( wxGetOsVersion(&verMaj, &verMin) )
             {
             int verMaj, verMin;
             switch ( wxGetOsVersion(&verMaj, &verMin) )
             {
-                case wxWIN95:
+                case wxOS_WINDOWS_9X:
                     s_isWin98Or2k = verMaj >= 4 && verMin >= 10;
                     break;
 
                     s_isWin98Or2k = verMaj >= 4 && verMin >= 10;
                     break;
 
-                case wxWINDOWS_NT:
+                case wxOS_WINDOWS_NT:
                     s_isWin98Or2k = verMaj >= 5;
                     break;
 
                     s_isWin98Or2k = verMaj >= 5;
                     break;
 
@@ -2584,7 +2586,7 @@ public:
         Init( wxCFStringEncFromFontEnc(encoding) );
     }
 
         Init( wxCFStringEncFromFontEnc(encoding) );
     }
 
-    ~wxMBConv_cocoa()
+    virtual ~wxMBConv_cocoa()
     {
     }
 
     {
     }
 
@@ -2739,7 +2741,7 @@ public:
         Init( wxMacGetSystemEncFromFontEnc(encoding) );
     }
 
         Init( wxMacGetSystemEncFromFontEnc(encoding) );
     }
 
-    ~wxMBConv_mac()
+    virtual ~wxMBConv_mac()
     {
         OSStatus status = noErr ;
         if (m_MB2WC_converter)
     {
         OSStatus status = noErr ;
         if (m_MB2WC_converter)
@@ -2772,7 +2774,7 @@ public:
             wxASSERT_MSG( status == noErr , _("Unable to create TextEncodingConverter")) ;
         }
     }
             wxASSERT_MSG( status == noErr , _("Unable to create TextEncodingConverter")) ;
         }
     }
-    
+
     size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const
     {
         CreateIfNeeded() ;
     size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const
     {
         CreateIfNeeded() ;
@@ -2887,9 +2889,9 @@ public:
     virtual wxMBConv *Clone() const { return new wxMBConv_mac(*this); }
 
     bool IsOk() const
     virtual wxMBConv *Clone() const { return new wxMBConv_mac(*this); }
 
     bool IsOk() const
-    {         
+    {
         CreateIfNeeded() ;
         CreateIfNeeded() ;
-        return m_MB2WC_converter != NULL && m_WC2MB_converter != NULL; 
+        return m_MB2WC_converter != NULL && m_WC2MB_converter != NULL;
     }
 
 protected :
     }
 
 protected :
@@ -2905,21 +2907,21 @@ protected :
 class wxMBConv_macUTF8D : public wxMBConv_mac
 {
 public :
 class wxMBConv_macUTF8D : public wxMBConv_mac
 {
 public :
-    wxMBConv_macUTF8D() 
+    wxMBConv_macUTF8D()
     {
         Init( kTextEncodingUnicodeDefault , kUnicodeNoSubset , kUnicodeUTF8Format ) ;
         m_uni = NULL;
         m_uniBack = NULL ;
     }
     {
         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);
     }
     {
         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() ;
     size_t WC2MB(char *buf, const wchar_t *psz, size_t n) const
     {
         CreateIfNeeded() ;
@@ -2949,15 +2951,15 @@ public :
         ubuf = (UniChar*) psz ;
 #endif
 
         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 ;
         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 ) ;
             kUnicodeDefaultDirectionMask, 0, NULL, NULL, NULL, dcubuflen  , &dcubufread , &dcubufwritten , dcubuf ) ;
-       
+
         // we now convert that decomposed buffer into UTF8
 
         status = TECConvertText(
         // we now convert that decomposed buffer into UTF8
 
         status = TECConvertText(
@@ -2982,7 +2984,7 @@ public :
 
         return res ;
     }
 
         return res ;
     }
-    
+
     size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const
     {
         CreateIfNeeded() ;
     size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const
     {
         CreateIfNeeded() ;
@@ -2992,25 +2994,25 @@ public :
         wchar_t *tbuf = NULL ;
         UniChar* ubuf = NULL ;
         size_t res = 0 ;
         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 ) ;
         }
         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 ) ;
         ByteCount byteBufferLen = n * sizeof( UniChar ) ;
-        
+
 #if SIZEOF_WCHAR_T == 4
         ubuf = (UniChar*) malloc( byteBufferLen + 2 ) ;
 #else
         ubuf = (UniChar*) (buf ? buf : tbuf) ;
 #endif
 #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 ;
         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,
 
         status = TECConvertText(
                                 m_MB2WC_converter, (ConstTextPtr) psz, byteInLen, &byteInLen,
@@ -3018,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 ;
         // 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
         // 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 ;
                                   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 ) ;
 #if SIZEOF_WCHAR_T == 4
         wxMBConvUTF16 converter ;
         res = converter.MB2WC( (buf ? buf : tbuf), (const char*)ubuf, n ) ;
@@ -3035,13 +3037,13 @@ public :
 #else
         res = byteOutLen / sizeof( UniChar ) ;
 #endif
 #else
         res = byteOutLen / sizeof( UniChar ) ;
 #endif
-        
+
         if ( buf == NULL )
             free(tbuf) ;
         if ( buf == NULL )
             free(tbuf) ;
-        
+
         if ( buf  && res < n)
             buf[res] = 0;
         if ( buf  && res < n)
             buf[res] = 0;
-        
+
         return res ;
     }
 
         return res ;
     }
 
@@ -3055,16 +3057,16 @@ public :
             m_map.otherEncoding = CreateTextEncoding(kTextEncodingUnicodeDefault,
                 kUnicodeCanonicalDecompVariant, kTextEncodingDefaultFormat);
             m_map.mappingVersion = kUnicodeUseLatestMapping;
             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")) ;
             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;
             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")) ;
         }
     }
             wxASSERT_MSG( err == noErr , _(" Couldn't create the UnicodeConverter")) ;
         }
     }
@@ -3072,7 +3074,7 @@ protected :
     mutable UnicodeToTextInfo   m_uni;
     mutable UnicodeToTextInfo   m_uniBack;
     mutable UnicodeMapping      m_map;
     mutable UnicodeToTextInfo   m_uni;
     mutable UnicodeToTextInfo   m_uniBack;
     mutable UnicodeMapping      m_map;
-}; 
+};
 #endif // defined(__WXMAC__) && defined(TARGET_CARBON)
 
 // ============================================================================
 #endif // defined(__WXMAC__) && defined(TARGET_CARBON)
 
 // ============================================================================
@@ -3277,7 +3279,7 @@ wxMBConv *wxCSConv::DoCreate() const
     wxLogTrace(TRACE_STRCONV,
                wxT("creating conversion for %s"),
                (m_name ? m_name
     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
 #endif // wxUSE_FONTMAP
 
     // check for the special case of ASCII or ISO8859-1 charset: as we have
@@ -3305,7 +3307,9 @@ wxMBConv *wxCSConv::DoCreate() const
 #endif // !wxUSE_FONTMAP
     {
         wxString name(m_name);
 #endif // !wxUSE_FONTMAP
     {
         wxString name(m_name);
+#if wxUSE_FONTMAP
         wxFontEncoding encoding(m_encoding);
         wxFontEncoding encoding(m_encoding);
+#endif
 
         if ( !name.empty() )
         {
 
         if ( !name.empty() )
         {
@@ -3336,20 +3340,26 @@ wxMBConv *wxCSConv::DoCreate() const
             }
 
             const wxChar** names = wxFontMapperBase::GetAllEncodingNames(encoding);
             }
 
             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
     }
         }
 #endif // wxUSE_FONTMAP
     }
@@ -3472,9 +3482,9 @@ wxMBConv *wxCSConv::DoCreate() const
                    m_name ? m_name
                       :
 #if wxUSE_FONTMAP
                    m_name ? m_name
                       :
 #if wxUSE_FONTMAP
-                         wxFontMapperBase::GetEncodingDescription(m_encoding).c_str()
+                         (const wxChar*)wxFontMapperBase::GetEncodingDescription(m_encoding).c_str()
 #else // !wxUSE_FONTMAP
 #else // !wxUSE_FONTMAP
-                         wxString::Format(_("encoding %s"), m_encoding).c_str()
+                         (const wxChar*)wxString::Format(_("encoding %i"), m_encoding).c_str()
 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
               );
 
 #endif // wxUSE_FONTMAP/!wxUSE_FONTMAP
               );
 
@@ -3490,20 +3500,60 @@ void wxCSConv::CreateConvIfNeeded() const
     {
         wxCSConv *self = (wxCSConv *)this; // const_cast
 
     {
         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 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
 #endif // wxUSE_INTL
+        }
 
         self->m_convReal = DoCreate();
         self->m_deferred = false;
     }
 }
 
 
         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();
 size_t wxCSConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
 {
     CreateConvIfNeeded();
@@ -3599,9 +3649,39 @@ WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvFileName = &
 #else
                                     wxConvUTF8Obj;
 #endif
 #else
                                     wxConvUTF8Obj;
 #endif
-#else
+#else // !__WXOSX__
                                     wxConvLibcObj;
                                     wxConvLibcObj;
-#endif
+#endif // __WXOSX__/!__WXOSX__
+
+#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
 
 #else // !wxUSE_WCHAR_T
 
 
 #else // !wxUSE_WCHAR_T