+int STRINGCLASS::compare(const wxStringBase& str) const
+{
+    return ::wxDoCmp(data(), length(), str.data(), str.length());
+}
+
+int STRINGCLASS::compare(size_t nStart, size_t nLen,
+                         const wxStringBase& str) const
+{
+    wxASSERT(nStart <= length());
+    size_type strLen = length() - nStart;
+    nLen = strLen < nLen ? strLen : nLen;
+    return ::wxDoCmp(data() + nStart, nLen, str.data(), str.length());
+}
+
+int STRINGCLASS::compare(size_t nStart, size_t nLen,
+                         const wxStringBase& str,
+                         size_t nStart2, size_t nLen2) const
+{
+    wxASSERT(nStart <= length());
+    wxASSERT(nStart2 <= str.length());
+    size_type strLen  =     length() - nStart,
+              strLen2 = str.length() - nStart2;
+    nLen  = strLen  < nLen  ? strLen  : nLen;
+    nLen2 = strLen2 < nLen2 ? strLen2 : nLen2;
+    return ::wxDoCmp(data() + nStart, nLen, str.data() + nStart2, nLen2);
+}
+
+int STRINGCLASS::compare(const wxChar* sz) const
+{
+    size_t nLen = wxStrlen(sz);
+    return ::wxDoCmp(data(), length(), sz, nLen);
+}
+
+int STRINGCLASS::compare(size_t nStart, size_t nLen,
+                         const wxChar* sz, size_t nCount) const
+{
+    wxASSERT(nStart <= length());
+    size_type strLen = length() - nStart;
+    nLen = strLen < nLen ? strLen : nLen;
+    if( nCount == npos )
+        nCount = wxStrlen(sz);
+
+    return ::wxDoCmp(data() + nStart, nLen, sz, nCount);
+}
+
+#undef STRINGCLASS
+
+#endif // !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)
+
+// ===========================================================================
+// wxString class core
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// construction and conversion
+// ---------------------------------------------------------------------------
+
+#if wxUSE_UNICODE
+
+// from multibyte string
+wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
+{
+    // if nLength != npos, then we have to make a NULL-terminated copy
+    // of first nLength bytes of psz first because the input buffer to MB2WC
+    // must always be NULL-terminated:
+    wxCharBuffer inBuf((const char *)NULL);
+    if (nLength != npos)
+    {
+        wxASSERT( psz != NULL );
+        wxCharBuffer tmp(nLength);
+        memcpy(tmp.data(), psz, nLength);
+        tmp.data()[nLength] = '\0';
+        inBuf = tmp;
+        psz = inBuf.data();
+    }
+
+    // first get the size of the buffer we need
+    size_t nLen;
+    if ( psz )
+    {
+        // calculate the needed size ourselves or use the provided one
+        if (nLength == npos)
+            nLen = strlen(psz);
+        else
+            nLen = nLength;
+    }
+    else
+    {
+        // nothing to convert
+        nLen = 0;
+    }
+
+
+    // anything to do?
+    if ( (nLen != 0) && (nLen != (size_t)-1) )
+    {
+        //Convert string
+        size_t nRealSize;
+        wxWCharBuffer theBuffer = conv.cMB2WC(psz, nLen, &nRealSize);
+
+        //Copy
+        if (nRealSize)
+            assign( theBuffer.data() , nRealSize - 1 );
+    }
+}
+
+//Convert wxString in Unicode mode to a multi-byte string
+const wxCharBuffer wxString::mb_str(wxMBConv& conv) const
+{
+    size_t dwOutSize;
+    return conv.cWC2MB(c_str(), length(), &dwOutSize);
+}
+
+#else // ANSI
+
+#if wxUSE_WCHAR_T
+// from wide string
+wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength)
+{
+    // if nLength != npos, then we have to make a NULL-terminated copy
+    // of first nLength chars of psz first because the input buffer to WC2MB
+    // must always be NULL-terminated:
+    wxWCharBuffer inBuf((const wchar_t *)NULL);
+    if (nLength != npos)
+    {
+        wxASSERT( pwz != NULL );
+        wxWCharBuffer tmp(nLength);
+        memcpy(tmp.data(), pwz, nLength * sizeof(wchar_t));
+        tmp.data()[nLength] = '\0';
+        inBuf = tmp;
+        pwz = inBuf.data();
+    }
+
+    // first get the size of the buffer we need
+    size_t nLen;
+    if ( pwz )
+    {
+        // calculate the needed size ourselves or use the provided one
+        if (nLength == npos)
+            nLen = wxWcslen(pwz);
+        else
+            nLen = nLength;
+    }
+    else
+    {
+        // nothing to convert
+        nLen = 0;
+    }
+
+    // anything to do?
+    if ( (nLen != 0) && (nLen != (size_t)-1) )
+    {
+        //Convert string
+        size_t nRealSize;
+        wxCharBuffer theBuffer = conv.cWC2MB(pwz, nLen, &nRealSize);
+
+        //Copy
+        if (nRealSize)
+            assign( theBuffer.data() , nRealSize - 1 );
+    }
+}
+
+//Converts this string to a wide character string if unicode
+//mode is not enabled and wxUSE_WCHAR_T is enabled
+const wxWCharBuffer wxString::wc_str(wxMBConv& conv) const
+{
+    size_t dwOutSize;
+    return conv.cMB2WC(c_str(), length(), &dwOutSize);
+}
+
+#endif // wxUSE_WCHAR_T
+
+#endif // Unicode/ANSI
+
+// shrink to minimal size (releasing extra memory)
+bool wxString::Shrink()
+{
+  wxString tmp(begin(), end());
+  swap(tmp);
+  return tmp.length() == length();
+}
+
+#if !wxUSE_STL
+// get the pointer to writable buffer of (at least) nLen bytes
+wxChar *wxString::GetWriteBuf(size_t nLen)
+{
+  if ( !AllocBeforeWrite(nLen) ) {
+    // allocation failure handled by caller
+    return NULL;
+  }
+
+  wxASSERT( GetStringData()->nRefs == 1 );
+  GetStringData()->Validate(false);
+
+  return m_pchData;
+}
+
+// put string back in a reasonable state after GetWriteBuf
+void wxString::UngetWriteBuf()
+{
+  GetStringData()->nDataLength = wxStrlen(m_pchData);
+  GetStringData()->Validate(true);
+}
+
+void wxString::UngetWriteBuf(size_t nLen)
+{
+  GetStringData()->nDataLength = nLen;
+  GetStringData()->Validate(true);
+}
+#endif
+
+// ---------------------------------------------------------------------------
+// data access
+// ---------------------------------------------------------------------------
+
+// all functions are inline in string.h
+
+// ---------------------------------------------------------------------------
+// assignment operators
+// ---------------------------------------------------------------------------
+
+#if !wxUSE_UNICODE
+
+// same as 'signed char' variant
+wxString& wxString::operator=(const unsigned char* psz)
+{
+  *this = (const char *)psz;
+  return *this;
+}
+
+#if wxUSE_WCHAR_T
+wxString& wxString::operator=(const wchar_t *pwz)
+{
+  wxString str(pwz);
+  swap(str);
+  return *this;
+}
+#endif
+
+#endif
+
+/*
+ * concatenation functions come in 5 flavours:
+ *  string + string
+ *  char   + string      and      string + char
+ *  C str  + string      and      string + C str
+ */
+
+wxString operator+(const wxString& str1, const wxString& str2)
+{
+#if !wxUSE_STL
+  wxASSERT( str1.GetStringData()->IsValid() );
+  wxASSERT( str2.GetStringData()->IsValid() );
+#endif
+
+  wxString s = str1;
+  s += str2;
+
+  return s;
+}
+
+wxString operator+(const wxString& str, wxChar ch)
+{
+#if !wxUSE_STL
+  wxASSERT( str.GetStringData()->IsValid() );
+#endif
+
+  wxString s = str;
+  s += ch;
+
+  return s;
+}
+
+wxString operator+(wxChar ch, const wxString& str)
+{
+#if !wxUSE_STL
+  wxASSERT( str.GetStringData()->IsValid() );
+#endif
+
+  wxString s = ch;
+  s += str;
+
+  return s;
+}
+
+wxString operator+(const wxString& str, const wxChar *psz)
+{
+#if !wxUSE_STL
+  wxASSERT( str.GetStringData()->IsValid() );
+#endif
+
+  wxString s;
+  if ( !s.Alloc(wxStrlen(psz) + str.Len()) ) {
+    wxFAIL_MSG( _T("out of memory in wxString::operator+") );
+  }
+  s += str;
+  s += psz;
+
+  return s;
+}
+
+wxString operator+(const wxChar *psz, const wxString& str)
+{
+#if !wxUSE_STL
+  wxASSERT( str.GetStringData()->IsValid() );
+#endif
+
+  wxString s;
+  if ( !s.Alloc(wxStrlen(psz) + str.Len()) ) {
+    wxFAIL_MSG( _T("out of memory in wxString::operator+") );
+  }
+  s = psz;
+  s += str;
+
+  return s;
+}
+
+// ===========================================================================
+// other common string functions
+// ===========================================================================
+
+int wxString::Cmp(const wxString& s) const
+{
+    return compare(s);
+}
+
+int wxString::Cmp(const wxChar* psz) const
+{
+    return compare(psz);
+}
+
+static inline int wxDoCmpNoCase(const wxChar* s1, size_t l1,
+                                const wxChar* s2, size_t l2)
+{
+    size_t i;
+
+    if( l1 == l2 )
+    {
+        for(i = 0; i < l1; ++i)
+        {
+            if(wxTolower(s1[i]) != wxTolower(s2[i]))
+                break;
+        }
+        return i == l1 ? 0 : wxTolower(s1[i]) < wxTolower(s2[i]) ? -1 : 1;
+    }
+    else if( l1 < l2 )
+    {
+        for(i = 0; i < l1; ++i)
+        {
+            if(wxTolower(s1[i]) != wxTolower(s2[i]))
+                break;
+        }
+        return i == l1 ? -1 : wxTolower(s1[i]) < wxTolower(s2[i]) ? -1 : 1;
+    }
+    else
+    {
+        for(i = 0; i < l2; ++i)
+        {
+            if(wxTolower(s1[i]) != wxTolower(s2[i]))
+                break;
+        }
+        return i == l2 ? 1 : wxTolower(s1[i]) < wxTolower(s2[i]) ? -1 : 1;
+    }
+}
+
+int wxString::CmpNoCase(const wxString& s) const
+{
+    return wxDoCmpNoCase(data(), length(), s.data(), s.length());
+}
+
+int wxString::CmpNoCase(const wxChar* psz) const
+{
+    int nLen = wxStrlen(psz);
+
+    return wxDoCmpNoCase(data(), length(), psz, nLen);
+}
+
+
+#if wxUSE_UNICODE
+
+#ifdef __MWERKS__
+#ifndef __SCHAR_MAX__
+#define __SCHAR_MAX__ 127
+#endif
+#endif
+
+wxString wxString::FromAscii(const char *ascii)
+{
+    if (!ascii)
+       return wxEmptyString;
+
+    size_t len = strlen( ascii );
+    wxString res;
+
+    if ( len )
+    {
+        wxStringBuffer buf(res, len);
+
+        wchar_t *dest = buf;
+
+        for ( ;; )
+        {
+           if ( (*dest++ = (wchar_t)(unsigned char)*ascii++) == L'\0' )
+               break;
+        }
+    }
+
+    return res;
+}
+
+wxString wxString::FromAscii(const char ascii)
+{
+    // What do we do with '\0' ?
+
+    wxString res;
+    res += (wchar_t)(unsigned char) ascii;
+
+    return res;
+}
+
+const wxCharBuffer wxString::ToAscii() const
+{
+    // this will allocate enough space for the terminating NUL too
+    wxCharBuffer buffer(length());
+
+
+    char *dest = buffer.data();
+
+    const wchar_t *pwc = c_str();
+    for ( ;; )
+    {
+        *dest++ = (char)(*pwc > SCHAR_MAX ? wxT('_') : *pwc);
+
+        // the output string can't have embedded NULs anyhow, so we can safely
+        // stop at first of them even if we do have any
+        if ( !*pwc++ )
+            break;
+    }
+
+    return buffer;
+}
+
+#endif // Unicode
+