]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/strconv.cpp
fix SetValue
[wxWidgets.git] / src / common / strconv.cpp
index f2364b7fc3f59994061dcd95eb97e12a94f8640d..91186b40c69db828d9b9d909546ed28bb6653b15 100644 (file)
@@ -703,7 +703,7 @@ size_t wxMBConvUTF7::WC2MB(char *buf, const wchar_t *psz, size_t n) const
 // UTF-8
 // ----------------------------------------------------------------------------
 
-static wxUint32 utf8_max[]=
+static const wxUint32 utf8_max[]=
     { 0x7f, 0x7ff, 0xffff, 0x1fffff, 0x3ffffff, 0x7fffffff, 0xffffffff };
 
 // boundaries of the private use area we use to (temporarily) remap invalid
@@ -712,7 +712,7 @@ const wxUint32 wxUnicodePUA = 0x100000;
 const wxUint32 wxUnicodePUAEnd = wxUnicodePUA + 256;
 
 // this table gives the length of the UTF-8 encoding from its first character:
-unsigned char tableUtf8Lengths[256] = {
+const unsigned char tableUtf8Lengths[256] = {
     // single-byte sequences (ASCII):
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 00..0F
     1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 10..1F
@@ -778,58 +778,73 @@ wxMBConvStrictUTF8::ToWChar(wchar_t *dst, size_t dstLen,
             return written;
         }
 
-        unsigned char c = *p;
-        unsigned len = tableUtf8Lengths[c];
-        if ( !len )
+        if ( out && !dstLen-- )
             break;
 
-        if ( srcLen < len ) // the test works for wxNO_LEN too
-            break;
+        wxUint32 code;
+        unsigned char c = *p;
 
-        if ( srcLen != wxNO_LEN )
-            srcLen -= len;
+        if ( c < 0x80 )
+        {
+            if ( srcLen == 0 ) // the test works for wxNO_LEN too
+                break;
 
-        if ( out && !dstLen-- )
-            break;
+            if ( srcLen != wxNO_LEN )
+                srcLen--;
 
+            code = c;
+        }
+        else
+        {
+            unsigned len = tableUtf8Lengths[c];
+            if ( !len )
+                break;
 
-        //   Char. number range   |        UTF-8 octet sequence
-        //      (hexadecimal)     |              (binary)
-        //  ----------------------+---------------------------------------------
-        //  0000 0000 - 0000 007F | 0xxxxxxx
-        //  0000 0080 - 0000 07FF | 110xxxxx 10xxxxxx
-        //  0000 0800 - 0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
-        //  0001 0000 - 0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
-        //
-        //  Code point value is stored in bits marked with 'x', lowest-order bit
-        //  of the value on the right side in the diagram above.
-        //                                                       (from RFC 3629)
+            if ( srcLen < len ) // the test works for wxNO_LEN too
+                break;
 
-        // mask to extract lead byte's value ('x' bits above), by sequence length:
-        static const unsigned char leadValueMask[] = { 0x7F, 0x1F, 0x0F, 0x07 };
+            if ( srcLen != wxNO_LEN )
+                srcLen -= len;
 
-        // mask and value of lead byte's most significant bits, by length:
-        static const unsigned char leadMarkerMask[] = { 0x80, 0xE0, 0xF0, 0xF8 };
-        static const unsigned char leadMarkerVal[] = { 0x00, 0xC0, 0xE0, 0xF0 };
+            //   Char. number range   |        UTF-8 octet sequence
+            //      (hexadecimal)     |              (binary)
+            //  ----------------------+----------------------------------------
+            //  0000 0000 - 0000 007F | 0xxxxxxx
+            //  0000 0080 - 0000 07FF | 110xxxxx 10xxxxxx
+            //  0000 0800 - 0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
+            //  0001 0000 - 0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+            //
+            //  Code point value is stored in bits marked with 'x',
+            //  lowest-order bit of the value on the right side in the diagram
+            //  above.                                         (from RFC 3629)
 
-        len--; // it's more convenient to work with 0-based length here
+            // mask to extract lead byte's value ('x' bits above), by sequence
+            // length:
+            static const unsigned char leadValueMask[] = { 0x7F, 0x1F, 0x0F, 0x07 };
 
-        // extract the lead byte's value bits:
-        if ( (c & leadMarkerMask[len]) != leadMarkerVal[len] )
-            break;
+            // mask and value of lead byte's most significant bits, by length:
+            static const unsigned char leadMarkerMask[] = { 0x80, 0xE0, 0xF0, 0xF8 };
+            static const unsigned char leadMarkerVal[] = { 0x00, 0xC0, 0xE0, 0xF0 };
 
-        wxUint32 code = c & leadValueMask[len];
+            len--; // it's more convenient to work with 0-based length here
 
-        // all remaining bytes, if any, are handled in the same way regardless of
-        // sequence's length:
-        for ( ; len; --len )
-        {
-            c = *++p;
-            if ( (c & 0xC0) != 0x80 )
-                return wxCONV_FAILED;
+            // extract the lead byte's value bits:
+            if ( (c & leadMarkerMask[len]) != leadMarkerVal[len] )
+                break;
 
-            code <<= 6;
-            code |= c & 0x3F;
+            code = c & leadValueMask[len];
+
+            // all remaining bytes, if any, are handled in the same way
+            // regardless of sequence's length:
+            for ( ; len; --len )
+            {
+                c = *++p;
+                if ( (c & 0xC0) != 0x80 )
+                    return wxCONV_FAILED;
+
+                code <<= 6;
+                code |= c & 0x3F;
+            }
         }
 
 #ifdef WC_UTF16
@@ -2411,26 +2426,36 @@ public:
             return wxCONV_FAILED;
         }
 
-        // if we were really converting, check if we succeeded
-        if ( buf )
+        // we did something, check if we really succeeded
+        if ( flags )
+        {
+            // check if the conversion failed, i.e. if any replacements
+            // were done
+            if ( usedDef )
+                return wxCONV_FAILED;
+        }
+        else // we must resort to double tripping...
         {
-            if ( flags )
+            // first we need to ensure that we really have the MB data: this is
+            // not the case if we're called with NULL buffer, in which case we
+            // need to do the conversion yet again
+            wxCharBuffer bufDef;
+            if ( !buf )
             {
-                // check if the conversion failed, i.e. if any replacements
-                // were done
-                if ( usedDef )
+                bufDef = wxCharBuffer(len);
+                buf = bufDef.data();
+                if ( !::WideCharToMultiByte(m_CodePage, flags, pwz, -1,
+                                            buf, len, NULL, NULL) )
                     return wxCONV_FAILED;
             }
-            else // we must resort to double tripping...
+
+            wxWCharBuffer wcBuf(n);
+            if ( MB2WC(wcBuf.data(), buf, n) == wxCONV_FAILED ||
+                    wcscmp(wcBuf, pwz) != 0 )
             {
-                wxWCharBuffer wcBuf(n);
-                if ( MB2WC(wcBuf.data(), buf, n) == wxCONV_FAILED ||
-                        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 wxCONV_FAILED;
-                }
+                // we didn't obtain the same thing we started from, hence
+                // the conversion was lossy and we consider that it failed
+                return wxCONV_FAILED;
             }
         }