+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.length()) ) {
+ 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.length()) ) {
+ 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
+
+// extract string of length nCount starting at nFirst
+wxString wxString::Mid(size_t nFirst, size_t nCount) const