+ return npos;
+}
+
+
+size_t wxString::find_last_of(const wxChar* sz, size_t nStart) const
+{
+ return find_last_of(sz, nStart, wxStrlen(sz));
+}
+
+size_t wxString::find_last_not_of(const wxChar* sz, size_t nStart) const
+{
+ return find_last_not_of(sz, nStart, wxStrlen(sz));
+}
+
+size_t wxString::find_last_of(const wxChar* sz, size_t nStart, size_t n) const
+{
+ size_t len = length();
+
+ if ( nStart == npos )
+ {
+ nStart = len - 1;
+ }
+ else
+ {
+ wxASSERT_MSG( nStart <= len, _T("invalid index") );
+ }
+
+ size_t idx = nStart;
+ for ( const_reverse_iterator i = rbegin() + (len - nStart - 1);
+ i != rend(); --idx, ++i )
+ {
+ if ( wxTmemchr(sz, *i, n) )
+ return idx;
+ }
+
+ return npos;
+}
+
+size_t wxString::find_last_not_of(const wxChar* sz, size_t nStart, size_t n) const
+{
+ size_t len = length();
+
+ if ( nStart == npos )
+ {
+ nStart = len - 1;
+ }
+ else
+ {
+ wxASSERT_MSG( nStart <= len, _T("invalid index") );
+ }
+
+ size_t idx = nStart;
+ for ( const_reverse_iterator i = rbegin() + (len - nStart - 1);
+ i != rend(); --idx, ++i )
+ {
+ if ( !wxTmemchr(sz, *i, n) )
+ return idx;
+ }
+
+ return npos;
+}
+
+size_t wxString::find_first_not_of(wxUniChar ch, size_t nStart) const
+{
+ wxASSERT_MSG( nStart <= length(), _T("invalid index") );
+
+ size_t idx = nStart;
+ for ( const_iterator i = begin() + nStart; i != end(); ++idx, ++i )
+ {
+ if ( *i != ch )
+ return idx;
+ }
+
+ return npos;
+}
+
+size_t wxString::find_last_not_of(wxUniChar ch, size_t nStart) const
+{
+ size_t len = length();
+
+ if ( nStart == npos )
+ {
+ nStart = len - 1;
+ }
+ else
+ {
+ wxASSERT_MSG( nStart <= len, _T("invalid index") );
+ }
+
+ size_t idx = nStart;
+ for ( const_reverse_iterator i = rbegin() + (len - nStart - 1);
+ i != rend(); --idx, ++i )
+ {
+ if ( *i != ch )
+ return idx;
+ }
+
+ return npos;
+}
+
+// the functions above were implemented for wchar_t* arguments in Unicode
+// build and char* in ANSI build; below are implementations for the other
+// version:
+#if wxUSE_UNICODE
+ #define wxOtherCharType char
+ #define STRCONV (const wxChar*)wxConvLibc.cMB2WC
+#else
+ #define wxOtherCharType wchar_t
+ #define STRCONV (const wxChar*)wxConvLibc.cWC2MB
+#endif
+
+size_t wxString::find_first_of(const wxOtherCharType* sz, size_t nStart) const
+ { return find_first_of(STRCONV(sz), nStart); }
+
+size_t wxString::find_first_of(const wxOtherCharType* sz, size_t nStart,
+ size_t n) const
+ { return find_first_of(STRCONV(sz, n, NULL), nStart, n); }
+size_t wxString::find_last_of(const wxOtherCharType* sz, size_t nStart) const
+ { return find_last_of(STRCONV(sz), nStart); }
+size_t wxString::find_last_of(const wxOtherCharType* sz, size_t nStart,
+ size_t n) const
+ { return find_last_of(STRCONV(sz, n, NULL), nStart, n); }
+size_t wxString::find_first_not_of(const wxOtherCharType* sz, size_t nStart) const
+ { return find_first_not_of(STRCONV(sz), nStart); }
+size_t wxString::find_first_not_of(const wxOtherCharType* sz, size_t nStart,
+ size_t n) const
+ { return find_first_not_of(STRCONV(sz, n, NULL), nStart, n); }
+size_t wxString::find_last_not_of(const wxOtherCharType* sz, size_t nStart) const
+ { return find_last_not_of(STRCONV(sz), nStart); }
+size_t wxString::find_last_not_of(const wxOtherCharType* sz, size_t nStart,
+ size_t n) const
+ { return find_last_not_of(STRCONV(sz, n, NULL), nStart, n); }
+
+#undef wxOtherCharType
+#undef STRCONV
+
+#endif // !wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
+
+// ===========================================================================
+// other common string functions
+// ===========================================================================
+
+int wxString::CmpNoCase(const wxString& s) const
+{
+ // FIXME-UTF8: use wxUniChar::ToLower/ToUpper once added
+
+ const_iterator i1 = begin();
+ const_iterator end1 = end();
+ const_iterator i2 = s.begin();
+ const_iterator end2 = s.end();
+
+ for ( ; i1 != end1 && i2 != end2; ++i1, ++i2 )
+ {
+ wxUniChar lower1 = (wxChar)wxTolower(*i1);
+ wxUniChar lower2 = (wxChar)wxTolower(*i2);
+ if ( lower1 != lower2 )
+ return lower1 < lower2 ? -1 : 1;
+ }
+
+ size_t len1 = length();
+ size_t len2 = s.length();
+
+ if ( len1 < len2 )
+ return -1;
+ else if ( len1 > len2 )
+ return 1;
+ return 0;
+}
+
+
+#if wxUSE_UNICODE
+
+#ifdef __MWERKS__
+#ifndef __SCHAR_MAX__
+#define __SCHAR_MAX__ 127
+#endif
+#endif
+
+wxString wxString::FromAscii(const char *ascii, size_t len)
+{
+ if (!ascii || len == 0)
+ return wxEmptyString;
+
+ wxString res;
+
+ {
+ wxStringInternalBuffer buf(res, len);
+ wxStringCharType *dest = buf;
+
+ for ( ; len > 0; --len )
+ {
+ unsigned char c = (unsigned char)*ascii++;
+ wxASSERT_MSG( c < 0x80,
+ _T("Non-ASCII value passed to FromAscii().") );
+
+ *dest++ = (wchar_t)c;
+ }
+ }
+
+ return res;
+}
+
+wxString wxString::FromAscii(const char *ascii)
+{
+ return FromAscii(ascii, wxStrlen(ascii));
+}
+
+wxString wxString::FromAscii(char ascii)
+{
+ // What do we do with '\0' ?
+
+ unsigned char c = (unsigned char)ascii;
+
+ wxASSERT_MSG( c < 0x80, _T("Non-ASCII value passed to FromAscii().") );
+
+ // NB: the cast to wchar_t causes interpretation of 'ascii' as Latin1 value
+ return wxString(wxUniChar((wchar_t)c));
+}
+
+const wxCharBuffer wxString::ToAscii() const
+{
+ // this will allocate enough space for the terminating NUL too
+ wxCharBuffer buffer(length());
+ char *dest = buffer.data();
+
+ for ( const_iterator i = begin(); i != end(); ++i )
+ {
+ wxUniChar c(*i);
+ // FIXME-UTF8: unify substituted char ('_') with wxUniChar ('?')
+ *dest++ = c.IsAscii() ? (char)c : '_';
+
+ // 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 ( !c )
+ break;
+ }
+
+ return buffer;