+#undef STRINGCLASS
+
+#endif // !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)
+
+// ===========================================================================
+// wxString class core
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// construction
+// ---------------------------------------------------------------------------
+
+#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
+ nLen = conv.MB2WC(NULL, psz, 0);
+ }
+ else
+ {
+ // nothing to convert
+ nLen = 0;
+ }
+
+ // anything to do?
+ if ( (nLen != 0) && (nLen != (size_t)-1) )
+ {
+ if ( !Alloc(nLen) )
+ {
+ wxFAIL_MSG( _T("out of memory in wxString::wxString") );
+ }
+ else
+ {
+ wxWCharBuffer buf(nLen);
+ // MB2WC wants the buffer size, not the string length hence +1
+ nLen = conv.MB2WC(buf.data(), psz, nLen + 1);
+
+ if ( nLen != (size_t)-1 )
+ {
+ // initialized ok, set the real length as nLength specified by
+ // the caller could be greater than the real string length
+ assign(buf.data(), nLen);
+ return;
+ }
+ //else: the conversion failed -- leave the string empty (what else?)
+ }
+ }
+}
+
+#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
+ nLen = conv.WC2MB(NULL, pwz, 0);
+ }
+ else
+ {
+ // nothing to convert
+ nLen = 0;
+ }
+
+ // anything to do?
+ if ( (nLen != 0) && (nLen != (size_t)-1) )
+ {
+ if ( !Alloc(nLen) )
+ {
+ wxFAIL_MSG( _T("out of memory in wxString::wxString") );
+ }
+ else
+ {
+ wxCharBuffer buf(nLen);
+ // WC2MB wants the buffer size, not the string length
+ if ( conv.WC2MB(buf.data(), pwz, nLen + 1) != (size_t)-1 )
+ {
+ // initialized ok
+ assign(buf.data(), nLen);
+ return;
+ }
+ //else: the conversion failed -- leave the string empty (what else?)
+ }
+ }
+
+ // leave empty
+}
+#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
+// ===========================================================================
+
+#if wxUSE_UNICODE
+
+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());
+
+ signed char *dest = (signed char *)buffer.data();
+
+ const wchar_t *pwc = c_str();
+ for ( ;; )
+ {
+ *dest++ = *pwc > SCHAR_MAX ? '_' : *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
+