]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/strconv.cpp
reverted rev 1.26, workarounds for memchecking code no longer needed
[wxWidgets.git] / src / common / strconv.cpp
index fc2ad991771e0e2e63d9c2ba5110e46c2c8532f5..c10d2e211b0c70ee887b4536d656362c18d18d4f 100644 (file)
@@ -40,6 +40,7 @@
 
 #ifdef __WXMSW__
     #include "wx/msw/private.h"
+    #include "wx/msw/missing.h"
 #endif
 
 #ifndef __WXWINCE__
@@ -1151,28 +1152,118 @@ public:
         return len ? len - 1 : (size_t)-1;
     }
 
-    size_t WC2MB(char *buf, const wchar_t *psz, size_t n) const
-    {
+    size_t WC2MB(char *buf, const wchar_t *pwz, size_t n) const
+    {
+        /*
+            we have a problem here: by default, WideCharToMultiByte() may
+            replace characters unrepresentable in the target code page with bad
+            quality approximations such as turning "1/2" symbol (U+00BD) into
+            "1" for the code pages which don't have it and we, obviously, want
+            to avoid this at any price
+        
+            the trouble is that this function does it _silently_, i.e. it won't
+            even tell us whether it did or not... Win98/2000 and higher provide
+            WC_NO_BEST_FIT_CHARS but it doesn't work for the older systems and
+            we have to resort to a round trip, i.e. check that converting back
+            results in the same string -- this is, of course, expensive but
+            otherwise we simply can't be sure to not garble the data.
+         */
+
+        // determine if we can rely on WC_NO_BEST_FIT_CHARS: according to MSDN
+        // it doesn't work with CJK encodings (which we test for rather roughly
+        // here...) nor with UTF-7/8 nor, of course, with Windows versions not
+        // supporting it
+        BOOL usedDef wxDUMMY_INITIALIZE(false),
+             *pUsedDef;
+        int flags;
+        if ( CanUseNoBestFit() && m_CodePage < 50000 )
+        {
+            // it's our lucky day
+            flags = WC_NO_BEST_FIT_CHARS;
+            pUsedDef = &usedDef;
+        }
+        else // old system or unsupported encoding
+        {
+            flags = 0;
+            pUsedDef = NULL;
+        }
+
         const size_t len = ::WideCharToMultiByte
                              (
                                 m_CodePage,     // code page
-                                0,              // flags (none)
-                                psz,            // input string
+                                flags,          // either none or no best fit
+                                pwz,            // 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?
+                                pUsedDef        // [out] was it used?
                              );
 
+        if ( !len )
+        {
+            // function totally failed
+            return (size_t)-1;
+        }
+
+        // if we were really converting, check if we succeeded
+        if ( buf )
+        {
+            if ( flags )
+            {
+                // check if the conversion failed, i.e. if any replacements
+                // were done
+                if ( usedDef )
+                    return (size_t)-1;
+            }
+            else // we must resort to double tripping...
+            {
+                wxWCharBuffer wcBuf(n);
+                if ( MB2WC(wcBuf.data(), buf, n) == (size_t)-1 ||
+                        wcscmp(wcBuf, pwz) != 0 )
+                {
+                    // we didn't obtain the same thing we started from, hence
+                    // the conversion was lossy and we consider that it failed
+                    return (size_t)-1;
+                }
+            }
+        }
+
         // see the comment above for the reason of "len - 1"
-        return len ? len - 1 : (size_t)-1;
+        return len 1;
     }
 
-    bool IsOk() const
-        { return m_CodePage != -1; }
+    bool IsOk() const { return m_CodePage != -1; }
+
+private:
+    static bool CanUseNoBestFit()
+    {
+        static int s_isWin98Or2k = -1;
+
+        if ( s_isWin98Or2k == -1 )
+        {
+            int verMaj, verMin;
+            switch ( wxGetOsVersion(&verMaj, &verMin) )
+            {
+                case wxWIN95:
+                    s_isWin98Or2k = verMaj >= 4 && verMin >= 10;
+                    break;
+
+                case wxWINDOWS_NT:
+                    s_isWin98Or2k = verMaj >= 5;
+                    break;
+
+                default:
+                    // unknown, be conseravtive by default
+                    s_isWin98Or2k = 0;
+            }
+
+            wxASSERT_MSG( s_isWin98Or2k != -1, _T("should be set above") );
+        }
+
+        return s_isWin98Or2k == 1;
+    }
 
-public:
     long m_CodePage;
 };
 
@@ -1194,12 +1285,12 @@ public:
 
     wxMBConv_mac(const wxChar* name)
     {
-       Init( EncodingToSystem(wxFontMapper::Get()->CharsetToEncoding(name, FALSE) ) ) ;
+       Init( wxMacGetSystemEncFromFontEnc(wxFontMapper::Get()->CharsetToEncoding(name, FALSE) ) ) ;
     }
 
     wxMBConv_mac(wxFontEncoding encoding)
     {
-       Init( EncodingToSystem(encoding) );
+       Init( wxMacGetSystemEncFromFontEnc(encoding) );
     }
     
        ~wxMBConv_mac()
@@ -1209,143 +1300,6 @@ public:
            status = TECDisposeConverter(m_WC2MB_converter);            
        }
        
-    static TextEncodingBase EncodingToSystem(wxFontEncoding encoding)
-    {          
-       TextEncodingBase enc = CFStringGetSystemEncoding() ;
-
-       switch( encoding)
-       {
-               case wxFONTENCODING_ISO8859_1 :
-                       enc = kTextEncodingISOLatin1 ;
-                       break ;
-               case wxFONTENCODING_ISO8859_2 :
-                       enc = kTextEncodingISOLatin2;
-                       break ;
-               case wxFONTENCODING_ISO8859_3 :
-                       enc = kTextEncodingISOLatin3 ;
-                       break ;
-               case wxFONTENCODING_ISO8859_4 :
-                       enc = kTextEncodingISOLatin4;
-                       break ;
-               case wxFONTENCODING_ISO8859_5 :
-                       enc = kTextEncodingISOLatinCyrillic;
-                       break ;
-               case wxFONTENCODING_ISO8859_6 :
-                       enc = kTextEncodingISOLatinArabic;
-                       break ;
-               case wxFONTENCODING_ISO8859_7 :
-                       enc = kTextEncodingISOLatinGreek;
-                       break ;
-               case wxFONTENCODING_ISO8859_8 :
-                       enc = kTextEncodingISOLatinHebrew;
-                       break ;
-               case wxFONTENCODING_ISO8859_9 :
-                       enc = kTextEncodingISOLatin5;
-                       break ;
-               case wxFONTENCODING_ISO8859_10 :
-                       enc = kTextEncodingISOLatin6;
-                       break ;
-               case wxFONTENCODING_ISO8859_13 :
-                       enc = kTextEncodingISOLatin7;
-                       break ;
-               case wxFONTENCODING_ISO8859_14 :
-                       enc = kTextEncodingISOLatin8;
-                       break ;
-               case wxFONTENCODING_ISO8859_15 :
-                       enc = kTextEncodingISOLatin9;
-                       break ;
-
-               case wxFONTENCODING_KOI8 :
-                       enc = kTextEncodingKOI8_R;
-                       break ;
-               case wxFONTENCODING_ALTERNATIVE : // MS-DOS CP866
-                       enc = kTextEncodingDOSRussian;
-                       break ;
-/*
-               case wxFONTENCODING_BULGARIAN : 
-                       enc = ;
-                       break ;
-*/                     
-               case wxFONTENCODING_CP437 : 
-                       enc =kTextEncodingDOSLatinUS ;
-                       break ;
-               case wxFONTENCODING_CP850 :
-                       enc = kTextEncodingDOSLatin1;
-                       break ;
-               case wxFONTENCODING_CP852 : 
-                       enc = kTextEncodingDOSLatin2;
-                       break ;
-               case wxFONTENCODING_CP855 :
-                       enc = kTextEncodingDOSCyrillic;
-                       break ;
-               case wxFONTENCODING_CP866 :
-                       enc =kTextEncodingDOSRussian ;
-                       break ;
-               case wxFONTENCODING_CP874 :
-                       enc = kTextEncodingDOSThai;
-                       break ;
-               case wxFONTENCODING_CP932 : 
-                       enc = kTextEncodingDOSJapanese;
-                       break ;
-               case wxFONTENCODING_CP936 : 
-                       enc =kTextEncodingDOSChineseSimplif ;
-                       break ;
-               case wxFONTENCODING_CP949 : 
-                       enc = kTextEncodingDOSKorean;
-                       break ;
-               case wxFONTENCODING_CP950 : 
-                       enc = kTextEncodingDOSChineseTrad;
-                       break ;
-                       
-               case wxFONTENCODING_CP1250 : 
-                       enc = kTextEncodingWindowsLatin2;
-                       break ;
-               case wxFONTENCODING_CP1251 : 
-                       enc =kTextEncodingWindowsCyrillic ;
-                       break ;
-               case wxFONTENCODING_CP1252 : 
-                       enc =kTextEncodingWindowsLatin1 ;
-                       break ;
-               case wxFONTENCODING_CP1253 : 
-                       enc = kTextEncodingWindowsGreek;
-                       break ;
-               case wxFONTENCODING_CP1254 : 
-                       enc = kTextEncodingWindowsLatin5;
-                       break ;
-               case wxFONTENCODING_CP1255 : 
-                       enc =kTextEncodingWindowsHebrew ;
-                       break ;
-               case wxFONTENCODING_CP1256 : 
-                       enc =kTextEncodingWindowsArabic ;
-                       break ;
-               case wxFONTENCODING_CP1257 : 
-                       enc = kTextEncodingWindowsBalticRim;
-                       break ;
-                       
-               case wxFONTENCODING_UTF7 : 
-                       enc = CreateTextEncoding(kTextEncodingUnicodeDefault,0,kUnicodeUTF7Format) ;
-                       break ;
-               case wxFONTENCODING_UTF8 : 
-                       enc = CreateTextEncoding(kTextEncodingUnicodeDefault,0,kUnicodeUTF8Format) ;
-                       break ;
-               case wxFONTENCODING_EUC_JP : 
-                       enc = kTextEncodingEUC_JP;
-                       break ;
-               case wxFONTENCODING_UTF16BE : 
-                       enc = CreateTextEncoding(kTextEncodingUnicodeDefault,0,kUnicode16BitFormat) ;
-                       break ;
-               case wxFONTENCODING_UTF16LE : 
-                       enc = CreateTextEncoding(kTextEncodingUnicodeDefault,0,kUnicode16BitFormat) ;
-                       break ;
-               case wxFONTENCODING_UTF32BE : 
-                       enc = CreateTextEncoding(kTextEncodingUnicodeDefault,0,kUnicode32BitFormat) ;
-                       break ;
-               case wxFONTENCODING_UTF32LE : 
-                       enc = CreateTextEncoding(kTextEncodingUnicodeDefault,0,kUnicode32BitFormat) ;
-                       break ;
-       } ;
-       return enc ;
-    }
     
        void Init( TextEncodingBase encoding)
        {
@@ -1369,15 +1323,15 @@ public:
            OSStatus status = noErr ;
            ByteCount byteOutLen ;
            ByteCount byteInLen = strlen(psz) ;
-           ByteCount byteBufferLen = n ; 
                wchar_t *tbuf = NULL ;
                
                if (buf == NULL)
                {
-                       n = byteInLen * SIZEOF_WCHAR_T ;
-                       tbuf = (wchar_t*) malloc( n ) ;
+                       n = byteInLen ;
+                       tbuf = (wchar_t*) malloc( n * SIZEOF_WCHAR_T) ;
                }
        
+           ByteCount byteBufferLen = n * SIZEOF_WCHAR_T ; 
            status = TECConvertText(m_MB2WC_converter, (ConstTextPtr) psz , byteInLen, &byteInLen,
              (TextPtr) (buf ? buf : tbuf) , byteBufferLen, &byteOutLen);
 
@@ -1396,16 +1350,17 @@ public:
            OSStatus status = noErr ;
            ByteCount byteOutLen ;
            ByteCount byteInLen = wxWcslen(psz) * SIZEOF_WCHAR_T ;
-           ByteCount byteBufferLen = n ;
 
                char *tbuf = NULL ;
                
                if (buf == NULL)
                {
-                       n = byteInLen ;
+                       // worst case
+                       n = byteInLen * 2 ;
                        tbuf = (char*) malloc( n ) ;
                }
 
+           ByteCount byteBufferLen = n ;
            status = TECConvertText(m_WC2MB_converter, (ConstTextPtr) psz , byteInLen, &byteInLen,
               (TextPtr) ( buf ? buf : tbuf ) , byteBufferLen, &byteOutLen);