]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/strconv.cpp
Applied patch [ 709618 ] fixes drawing position in wxPrinterDC::DoBlit()
[wxWidgets.git] / src / common / strconv.cpp
index fb2d4e0023ec180a5d83cfc230f7ad8a607501f0..bbd8ce8369d4035e7524af5406b0f42adac52eb6 100644 (file)
@@ -6,7 +6,7 @@
 // Created:     29/01/98
 // RCS-ID:      $Id$
 // Copyright:   (c) 1999 Ove Kaaven, Robert Roebling, Vadim Zeitlin, Vaclav Slavik
 // Created:     29/01/98
 // RCS-ID:      $Id$
 // Copyright:   (c) 1999 Ove Kaaven, Robert Roebling, Vadim Zeitlin, Vaclav Slavik
-// Licence:     wxWindows license
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 #if wxUSE_WCHAR_T
     WXDLLEXPORT_DATA(wxMBConv) wxConvLibc;
     WXDLLEXPORT_DATA(wxCSConv) wxConvLocal((const wxChar *)NULL);
 #if wxUSE_WCHAR_T
     WXDLLEXPORT_DATA(wxMBConv) wxConvLibc;
     WXDLLEXPORT_DATA(wxCSConv) wxConvLocal((const wxChar *)NULL);
+    WXDLLEXPORT_DATA(wxCSConv) wxConvISO8859_1(_T("iso-8859-1"));
 #else
     // stand-ins in absence of wchar_t
 #else
     // stand-ins in absence of wchar_t
-    WXDLLEXPORT_DATA(wxMBConv) wxConvLibc, wxConvFile;
+    WXDLLEXPORT_DATA(wxMBConv) wxConvLibc,
+                               wxConvFile,
+                               wxConvISO8859_1,
+                               wxConvLocal,
+                               wxConvUTF8;
 #endif // wxUSE_WCHAR_T
 
 WXDLLEXPORT_DATA(wxMBConv *) wxConvCurrent = &wxConvLibc;
 #endif // wxUSE_WCHAR_T
 
 WXDLLEXPORT_DATA(wxMBConv *) wxConvCurrent = &wxConvLibc;
@@ -67,7 +72,8 @@ public:
     virtual void OnExit()
     {
 #if wxUSE_WCHAR_T
     virtual void OnExit()
     {
 #if wxUSE_WCHAR_T
-        wxConvLocal.Clear();
+         wxConvLocal.Clear();
+         wxConvISO8859_1.Clear();
 #endif
     }
 
 #endif
     }
 
@@ -186,61 +192,87 @@ static size_t decode_utf16(const wchar_t* input, wxUint32& output)
 // wxMBConv
 // ----------------------------------------------------------------------------
 
 // wxMBConv
 // ----------------------------------------------------------------------------
 
-size_t wxMBConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
-{
-    return wxMB2WC(buf, psz, n)+1;
-}
+#define IGNORE_LIBC 0
 
 
-size_t wxMBConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const
+wxMBConv::~wxMBConv()
 {
 {
-    return wxWC2MB(buf, psz, n)+1;
+    // nothing to do here
 }
 
 }
 
-const wxWCharBuffer wxMBConv::cMB2WC(const char *psz) const
+size_t wxMBConv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
 {
 {
-    if (psz)
+#if IGNORE_LIBC
+    if (buf)
     {
     {
-        size_t nLen = MB2WC((wchar_t *) NULL, psz, 0);
-        if (nLen == (size_t)-1)
-            return wxWCharBuffer((wchar_t *) NULL);
-        wxWCharBuffer buf(nLen);
-        MB2WC((wchar_t *)(const wchar_t *) buf, psz, nLen);
-        return buf;
+        for (size_t i = 0; i < strlen( psz )+1; i++)
+            buf[i] = (wchar_t) psz[i];
+        return strlen( psz );
     }
     else
     }
     else
-        return wxWCharBuffer((wchar_t *) NULL);
+    {
+        return strlen( psz );
+    }
+#else
+    return wxMB2WC(buf, psz, n);
+#endif
 }
 
 }
 
-const wxCharBuffer wxMBConv::cWC2MB(const wchar_t *psz) const
+size_t wxMBConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const
 {
 {
-    if (psz)
+#if IGNORE_LIBC
+    if (buf)
     {
     {
-        size_t nLen = WC2MB((char *) NULL, psz, 0);
-        if (nLen == (size_t)-1)
-            return wxCharBuffer((char *) NULL);
-        wxCharBuffer buf(nLen);
-        WC2MB((char *)(const char *) buf, psz, nLen);
-        return buf;
+        for (size_t i = 0; i < wxStrlen( psz )+1; i++)
+            buf[i] = (char) psz[i];
+        return wxStrlen( psz );
     }
     else
     }
     else
-        return wxCharBuffer((char *) NULL);
+    {
+        return wxStrlen( psz );
+    }
+#else
+    return wxWC2MB(buf, psz, n);
+#endif
 }
 
 }
 
-// ----------------------------------------------------------------------------
-// standard file conversion
-// ----------------------------------------------------------------------------
+const wxWCharBuffer wxMBConv::cMB2WC(const char *psz) const
+{
+    if ( psz )
+    {
+        // calculate the length of the buffer needed first
+        size_t nLen = MB2WC(NULL, psz, 0);
+        if ( nLen != (size_t)-1 )
+        {
+            // now do the actual conversion
+            wxWCharBuffer buf(nLen);
+            MB2WC(buf.data(), psz, nLen + 1); // with the trailing NUL
 
 
-WXDLLEXPORT_DATA(wxMBConvFile) wxConvFile;
+            return buf;
+        }
+    }
 
 
-// just use the libc conversion for now
-size_t wxMBConvFile::MB2WC(wchar_t *buf, const char *psz, size_t n) const
-{
-    return wxMB2WC(buf, psz, n);
+    wxWCharBuffer buf((wchar_t *)NULL);
+
+    return buf;
 }
 
 }
 
-size_t wxMBConvFile::WC2MB(char *buf, const wchar_t *psz, size_t n) const
+const wxCharBuffer wxMBConv::cWC2MB(const wchar_t *pwz) const
 {
 {
-    return wxWC2MB(buf, psz, n);
+    if ( pwz )
+    {
+        size_t nLen = WC2MB(NULL, pwz, 0);
+        if ( nLen != (size_t)-1 )
+        {
+            wxCharBuffer buf(nLen);
+            WC2MB(buf.data(), pwz, nLen + 1);
+
+            return buf;
+        }
+    }
+
+    wxCharBuffer buf((char *)NULL);
+
+    return buf;
 }
 
 // ----------------------------------------------------------------------------
 }
 
 // ----------------------------------------------------------------------------
@@ -425,6 +457,7 @@ size_t wxMBConvUTF8::WC2MB(char *buf, const wchar_t *psz, size_t n) const
     }
 
     if (buf && (len<n)) *buf = 0;
     }
 
     if (buf && (len<n)) *buf = 0;
+
     return len;
 }
 
     return len;
 }
 
@@ -531,6 +564,11 @@ bool IC_CharSet::ms_wcNeedsSwap = FALSE;
 IC_CharSet::IC_CharSet(const wxChar *name)
           : wxCharacterSet(name)
 {
 IC_CharSet::IC_CharSet(const wxChar *name)
           : wxCharacterSet(name)
 {
+    // Do it the hard way
+    char cname[100];
+    for (size_t i = 0; i < wxStrlen(name)+1; i++)
+        cname[i] = (char) name[i];
+
     // check for charset that represents wchar_t:
     if (ms_wcCharsetName == NULL)
     {
     // check for charset that represents wchar_t:
     if (ms_wcCharsetName == NULL)
     {
@@ -538,20 +576,20 @@ IC_CharSet::IC_CharSet(const wxChar *name)
 
         // try charset with explicit bytesex info (e.g. "UCS-4LE"):
         ms_wcCharsetName = WC_NAME_BEST;
 
         // try charset with explicit bytesex info (e.g. "UCS-4LE"):
         ms_wcCharsetName = WC_NAME_BEST;
-        m2w = iconv_open(ms_wcCharsetName, wxConvLibc.cWX2MB(name));
+        m2w = iconv_open(ms_wcCharsetName, cname);
 
         if (m2w == (iconv_t)-1)
         {
             // try charset w/o bytesex info (e.g. "UCS4")
             // and check for bytesex ourselves:
             ms_wcCharsetName = WC_NAME;
 
         if (m2w == (iconv_t)-1)
         {
             // try charset w/o bytesex info (e.g. "UCS4")
             // and check for bytesex ourselves:
             ms_wcCharsetName = WC_NAME;
-            m2w = iconv_open(ms_wcCharsetName, wxConvLibc.cWX2MB(name));
+            m2w = iconv_open(ms_wcCharsetName, cname);
 
             // last bet, try if it knows WCHAR_T pseudo-charset
             if (m2w == (iconv_t)-1)
             {
                 ms_wcCharsetName = "WCHAR_T";
 
             // last bet, try if it knows WCHAR_T pseudo-charset
             if (m2w == (iconv_t)-1)
             {
                 ms_wcCharsetName = "WCHAR_T";
-                m2w = iconv_open(ms_wcCharsetName, wxConvLibc.cWX2MB(name));
+                m2w = iconv_open(ms_wcCharsetName, cname);
             }
 
             if (m2w != (iconv_t)-1)
             }
 
             if (m2w != (iconv_t)-1)
@@ -576,7 +614,7 @@ IC_CharSet::IC_CharSet(const wxChar *name)
                 {
                     ms_wcCharsetName = NULL;
                     wxLogLastError(wxT("iconv"));
                 {
                     ms_wcCharsetName = NULL;
                     wxLogLastError(wxT("iconv"));
-                    wxLogError(_("Convertion to charset '%s' doesn't work."), name);
+                    wxLogError(_("Conversion to charset '%s' doesn't work."), name);
                 }
                 else
                 {
                 }
                 else
                 {
@@ -597,13 +635,13 @@ IC_CharSet::IC_CharSet(const wxChar *name)
     }
     else // we already have ms_wcCharsetName
     {
     }
     else // we already have ms_wcCharsetName
     {
-        m2w = iconv_open(ms_wcCharsetName, wxConvLibc.cWX2MB(name));
+        m2w = iconv_open(ms_wcCharsetName, cname);
     }
 
     // NB: don't ever pass NULL to iconv_open(), it may crash!
     if ( ms_wcCharsetName )
     {
     }
 
     // NB: don't ever pass NULL to iconv_open(), it may crash!
     if ( ms_wcCharsetName )
     {
-        w2m = iconv_open(wxConvLibc.cWX2MB(name), ms_wcCharsetName);
+        w2m = iconv_open( cname, ms_wcCharsetName);
     }
     else
     {
     }
     else
     {
@@ -641,6 +679,12 @@ size_t IC_CharSet::MB2WC(wchar_t *buf, const char *psz, size_t n)
             // convert to native endianness
             WC_BSWAP(buf /* _not_ bufPtr */, res)
         }
             // convert to native endianness
             WC_BSWAP(buf /* _not_ bufPtr */, res)
         }
+
+        // NB: iconv was given only strlen(psz) characters on input, and so
+        //     it couldn't convert the trailing zero. Let's do it ourselves
+        //     if there's some room left for it in the output buffer.
+        if (res < n)
+            buf[res] = 0;
     }
     else
     {
     }
     else
     {
@@ -672,11 +716,7 @@ size_t IC_CharSet::MB2WC(wchar_t *buf, const char *psz, size_t n)
 
 size_t IC_CharSet::WC2MB(char *buf, const wchar_t *psz, size_t n)
 {
 
 size_t IC_CharSet::WC2MB(char *buf, const wchar_t *psz, size_t n)
 {
-#if defined(__BORLANDC__) && (__BORLANDC__ > 0x530)
-    size_t inbuf = std::wcslen(psz) * SIZEOF_WCHAR_T;
-#else
-    size_t inbuf = ::wcslen(psz) * SIZEOF_WCHAR_T;
-#endif
+    size_t inbuf = wxWcslen(psz) * SIZEOF_WCHAR_T;
     size_t outbuf = n;
     size_t res, cres;
 
     size_t outbuf = n;
     size_t res, cres;
 
@@ -700,6 +740,12 @@ size_t IC_CharSet::WC2MB(char *buf, const wchar_t *psz, size_t n)
         cres = iconv( w2m, ICONV_CHAR_CAST(&psz), &inbuf, &buf, &outbuf );
 
         res = n-outbuf;
         cres = iconv( w2m, ICONV_CHAR_CAST(&psz), &inbuf, &buf, &outbuf );
 
         res = n-outbuf;
+
+        // NB: iconv was given only wcslen(psz) characters on input, and so
+        //     it couldn't convert the trailing zero. Let's do it ourselves
+        //     if there's some room left for it in the output buffer.
+        if (res < n)
+            buf[0] = 0;
     }
     else
     {
     }
     else
     {
@@ -737,7 +783,7 @@ size_t IC_CharSet::WC2MB(char *buf, const wchar_t *psz, size_t n)
 // Win32 conversion classes
 // ============================================================================
 
 // Win32 conversion classes
 // ============================================================================
 
-#if defined(__WIN32__) && !defined(__WXMICROWIN__)
+#if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXUNIVERSAL__)
 
 extern long wxCharsetToCodepage(const wxChar *charset); // from utils.cpp
 
 
 extern long wxCharsetToCodepage(const wxChar *charset); // from utils.cpp
 
@@ -752,20 +798,37 @@ public:
 
     size_t MB2WC(wchar_t *buf, const char *psz, size_t n)
     {
 
     size_t MB2WC(wchar_t *buf, const char *psz, size_t n)
     {
-        size_t len =
-            MultiByteToWideChar(m_CodePage, 0, psz, -1, buf, buf ? n : 0);
-        //VS: returns # of written chars for buf!=NULL and *size*
-        //    needed buffer for buf==NULL
-        return len ? (buf ? len : len-1) : (size_t)-1;
+        const size_t len = ::MultiByteToWideChar
+                             (
+                                m_CodePage,     // code page
+                                0,              // flags (none)
+                                psz,            // input string
+                                -1,             // its length (NUL-terminated)
+                                buf,            // output string
+                                buf ? n : 0     // size of output buffer
+                             );
+
+        // note that it returns # of written chars for buf != NULL and *size*
+        // of the needed buffer for buf == NULL
+        return len ? (buf ? len : len - 1) : (size_t)-1;
     }
 
     size_t WC2MB(char *buf, const wchar_t *psz, size_t n)
     {
     }
 
     size_t WC2MB(char *buf, const wchar_t *psz, size_t n)
     {
-        size_t len = WideCharToMultiByte(m_CodePage, 0, psz, -1, buf,
-                                         buf ? n : 0, NULL, NULL);
-        //VS: returns # of written chars for buf!=NULL and *size*
-        //    needed buffer for buf==NULL
-        return len ? (buf ? len : len-1) : (size_t)-1;
+        const size_t len = ::WideCharToMultiByte
+                             (
+                                m_CodePage,     // code page
+                                0,              // flags (none)
+                                psz,            // 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?
+                             );
+
+        // see the comment above!
+        return len ? (buf ? len : len - 1) : (size_t)-1;
     }
 
     bool usable() const
     }
 
     bool usable() const
@@ -774,7 +837,7 @@ public:
 public:
     long m_CodePage;
 };
 public:
     long m_CodePage;
 };
-#endif // __WIN32__
+#endif // defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXUNIVERSAL__)
 
 // ============================================================================
 // wxEncodingConverter based conversion classes
 
 // ============================================================================
 // wxEncodingConverter based conversion classes
@@ -807,12 +870,7 @@ public:
 
     size_t WC2MB(char *buf, const wchar_t *psz, size_t WXUNUSED(n))
     {
 
     size_t WC2MB(char *buf, const wchar_t *psz, size_t WXUNUSED(n))
     {
-#if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) ) \
-    || ( defined(__MWERKS__) && defined(__WXMSW__) )
-        size_t inbuf = std::wcslen(psz);
-#else
-        size_t inbuf = ::wcslen(psz);
-#endif
+        const size_t inbuf = wxWcslen(psz);
         if (buf)
             w2m.Convert(psz,buf);
 
         if (buf)
             w2m.Convert(psz,buf);
 
@@ -879,14 +937,14 @@ static wxCharacterSet *wxGetCharacterSet(const wxChar *name)
         cset = NULL;
     }
 
         cset = NULL;
     }
 
-#if defined(__WIN32__) && !defined(__WXMICROWIN__)
+#if defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXUNIVERSAL__)
     cset = new CP_CharSet(name);
     if ( cset->usable() )
         return cset;
 
     delete cset;
     cset = NULL;
     cset = new CP_CharSet(name);
     if ( cset->usable() )
         return cset;
 
     delete cset;
     cset = NULL;
-#endif // __WIN32__
+#endif // defined(__WIN32__) && !defined(__WXMICROWIN__) && !defined(__WXUNIVERSAL__)
 
 #if wxUSE_FONTMAP
     cset = new EC_CharSet(name);
 
 #if wxUSE_FONTMAP
     cset = new EC_CharSet(name);
@@ -955,14 +1013,20 @@ void wxCSConv::SetName(const wxChar *charset)
 
 void wxCSConv::LoadNow()
 {
 
 void wxCSConv::LoadNow()
 {
-    if (m_deferred)
+    if ( m_deferred )
     {
     {
+        // it would probably be better to make GetSystemEncodingName() always
+        // available (i.e. even when wxUSE_INTL == 0)?
+#if wxUSE_INTL
         if ( !m_name )
         {
             wxString name = wxLocale::GetSystemEncodingName();
             if ( !name.empty() )
         if ( !m_name )
         {
             wxString name = wxLocale::GetSystemEncodingName();
             if ( !name.empty() )
+            {
                 SetName(name);
                 SetName(name);
+            }
         }
         }
+#endif // wxUSE_INTL
 
         // wxGetCharacterSet() complains about NULL name
         m_cset = m_name ? wxGetCharacterSet(m_name) : NULL;
 
         // wxGetCharacterSet() complains about NULL name
         m_cset = m_name ? wxGetCharacterSet(m_name) : NULL;
@@ -997,12 +1061,7 @@ size_t wxCSConv::WC2MB(char *buf, const wchar_t *psz, size_t n) const
         return m_cset->WC2MB(buf, psz, n);
 
     // latin-1 (direct)
         return m_cset->WC2MB(buf, psz, n);
 
     // latin-1 (direct)
-#if ( defined(__BORLANDC__) && (__BORLANDC__ > 0x530) ) \
-    || ( defined(__MWERKS__) && defined(__WXMSW__) )
-    size_t len=std::wcslen(psz);
-#else
-    size_t len=::wcslen(psz);
-#endif
+    const size_t len = wxWcslen(psz);
     if (buf)
     {
         for (size_t c = 0; c <= len; c++)
     if (buf)
     {
         for (size_t c = 0; c <= len; c++)