+ 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
+{
+ size_t nLen = length();
+
+ // default value of nCount is npos and means "till the end"
+ if ( nCount == npos )
+ {
+ nCount = nLen - nFirst;
+ }
+
+ // out-of-bounds requests return sensible things
+ if ( nFirst + nCount > nLen )
+ {
+ nCount = nLen - nFirst;
+ }
+
+ if ( nFirst > nLen )
+ {
+ // AllocCopy() will return empty string
+ return wxEmptyString;
+ }
+
+ wxString dest(*this, nFirst, nCount);
+ if ( dest.length() != nCount )
+ {
+ wxFAIL_MSG( _T("out of memory in wxString::Mid") );
+ }
+
+ return dest;
+}
+
+// check that the string starts with prefix and return the rest of the string
+// in the provided pointer if it is not NULL, otherwise return false
+bool wxString::StartsWith(const wxChar *prefix, wxString *rest) const
+{
+ wxASSERT_MSG( prefix, _T("invalid parameter in wxString::StartsWith") );
+
+ // first check if the beginning of the string matches the prefix: note
+ // that we don't have to check that we don't run out of this string as
+ // when we reach the terminating NUL, either prefix string ends too (and
+ // then it's ok) or we break out of the loop because there is no match
+ const wxChar *p = c_str();
+ while ( *prefix )
+ {
+ if ( *prefix++ != *p++ )
+ {
+ // no match
+ return false;
+ }
+ }
+
+ if ( rest )
+ {
+ // put the rest of the string into provided pointer
+ *rest = p;
+ }
+
+ return true;
+}
+
+
+// check that the string ends with suffix and return the rest of it in the
+// provided pointer if it is not NULL, otherwise return false
+bool wxString::EndsWith(const wxChar *suffix, wxString *rest) const
+{
+ wxASSERT_MSG( suffix, _T("invalid parameter in wxString::EndssWith") );
+
+ int start = length() - wxStrlen(suffix);
+ if ( start < 0 || wxStrcmp(c_str() + start, suffix) != 0 )
+ return false;
+
+ if ( rest )
+ {
+ // put the rest of the string into provided pointer
+ rest->assign(*this, 0, start);
+ }
+
+ return true;
+}
+
+
+// extract nCount last (rightmost) characters
+wxString wxString::Right(size_t nCount) const
+{
+ if ( nCount > length() )
+ nCount = length();
+
+ wxString dest(*this, length() - nCount, nCount);
+ if ( dest.length() != nCount ) {
+ wxFAIL_MSG( _T("out of memory in wxString::Right") );
+ }
+ return dest;
+}
+
+// get all characters after the last occurence of ch
+// (returns the whole string if ch not found)
+wxString wxString::AfterLast(wxChar ch) const
+{
+ wxString str;
+ int iPos = Find(ch, true);
+ if ( iPos == wxNOT_FOUND )
+ str = *this;
+ else
+ str = c_str() + iPos + 1;
+
+ return str;
+}
+
+// extract nCount first (leftmost) characters
+wxString wxString::Left(size_t nCount) const
+{
+ if ( nCount > length() )
+ nCount = length();
+
+ wxString dest(*this, 0, nCount);
+ if ( dest.length() != nCount ) {
+ wxFAIL_MSG( _T("out of memory in wxString::Left") );
+ }
+ return dest;
+}
+
+// get all characters before the first occurence of ch
+// (returns the whole string if ch not found)
+wxString wxString::BeforeFirst(wxChar ch) const
+{
+ int iPos = Find(ch);
+ if ( iPos == wxNOT_FOUND ) iPos = length();
+ return wxString(*this, 0, iPos);
+}
+
+/// get all characters before the last occurence of ch
+/// (returns empty string if ch not found)
+wxString wxString::BeforeLast(wxChar ch) const
+{
+ wxString str;
+ int iPos = Find(ch, true);
+ if ( iPos != wxNOT_FOUND && iPos != 0 )
+ str = wxString(c_str(), iPos);
+
+ return str;
+}
+
+/// get all characters after the first occurence of ch
+/// (returns empty string if ch not found)
+wxString wxString::AfterFirst(wxChar ch) const
+{
+ wxString str;
+ int iPos = Find(ch);
+ if ( iPos != wxNOT_FOUND )
+ str = c_str() + iPos + 1;
+
+ return str;
+}
+
+// replace first (or all) occurences of some substring with another one
+size_t wxString::Replace(const wxChar *szOld,
+ const wxChar *szNew, bool bReplaceAll)
+{
+ // if we tried to replace an empty string we'd enter an infinite loop below
+ wxCHECK_MSG( szOld && *szOld && szNew, 0,
+ _T("wxString::Replace(): invalid parameter") );
+
+ size_t uiCount = 0; // count of replacements made
+
+ size_t uiOldLen = wxStrlen(szOld);
+ size_t uiNewLen = wxStrlen(szNew);
+
+ size_t dwPos = 0;
+
+ while ( this->c_str()[dwPos] != wxT('\0') )
+ {
+ //DO NOT USE STRSTR HERE
+ //this string can contain embedded null characters,
+ //so strstr will function incorrectly
+ dwPos = find(szOld, dwPos);
+ if ( dwPos == npos )
+ break; // exit the loop
+ else
+ {
+ //replace this occurance of the old string with the new one
+ replace(dwPos, uiOldLen, szNew, uiNewLen);
+
+ //move up pos past the string that was replaced
+ dwPos += uiNewLen;
+
+ //increase replace count
+ ++uiCount;
+
+ // stop now?
+ if ( !bReplaceAll )
+ break; // exit the loop
+ }
+ }
+
+ return uiCount;
+}
+
+bool wxString::IsAscii() const
+{
+ const wxChar *s = (const wxChar*) *this;
+ while(*s){
+ if(!isascii(*s)) return(false);
+ s++;
+ }
+ return(true);
+}
+
+bool wxString::IsWord() const
+{
+ const wxChar *s = (const wxChar*) *this;
+ while(*s){
+ if(!wxIsalpha(*s)) return(false);
+ s++;
+ }
+ return(true);
+}
+
+bool wxString::IsNumber() const
+{
+ const wxChar *s = (const wxChar*) *this;
+ if (wxStrlen(s))
+ if ((s[0] == wxT('-')) || (s[0] == wxT('+'))) s++;
+ while(*s){
+ if(!wxIsdigit(*s)) return(false);
+ s++;
+ }
+ return(true);
+}
+
+wxString wxString::Strip(stripType w) const
+{
+ wxString s = *this;
+ if ( w & leading ) s.Trim(false);
+ if ( w & trailing ) s.Trim(true);
+ return s;
+}
+
+// ---------------------------------------------------------------------------
+// case conversion
+// ---------------------------------------------------------------------------
+
+wxString& wxString::MakeUpper()
+{
+ for ( iterator it = begin(), en = end(); it != en; ++it )
+ *it = (wxChar)wxToupper(*it);
+
+ return *this;
+}
+
+wxString& wxString::MakeLower()
+{
+ for ( iterator it = begin(), en = end(); it != en; ++it )
+ *it = (wxChar)wxTolower(*it);
+
+ return *this;
+}
+
+// ---------------------------------------------------------------------------
+// trimming and padding
+// ---------------------------------------------------------------------------
+
+// some compilers (VC++ 6.0 not to name them) return true for a call to
+// isspace('ê') in the C locale which seems to be broken to me, but we have to
+// live with this by checking that the character is a 7 bit one - even if this
+// may fail to detect some spaces (I don't know if Unicode doesn't have
+// space-like symbols somewhere except in the first 128 chars), it is arguably
+// still better than trimming away accented letters
+inline int wxSafeIsspace(wxChar ch) { return (ch < 127) && wxIsspace(ch); }
+
+// trims spaces (in the sense of isspace) from left or right side
+wxString& wxString::Trim(bool bFromRight)
+{
+ // first check if we're going to modify the string at all
+ if ( !empty() &&
+ (
+ (bFromRight && wxSafeIsspace(GetChar(length() - 1))) ||
+ (!bFromRight && wxSafeIsspace(GetChar(0u)))
+ )
+ )
+ {
+ if ( bFromRight )
+ {
+ // find last non-space character
+ reverse_iterator psz = rbegin();
+ while ( (psz != rend()) && wxSafeIsspace(*psz) )
+ psz++;
+
+ // truncate at trailing space start
+ erase(psz.base(), end());
+ }
+ else
+ {
+ // find first non-space character
+ iterator psz = begin();
+ while ( (psz != end()) && wxSafeIsspace(*psz) )
+ psz++;
+
+ // fix up data and length
+ erase(begin(), psz);
+ }
+ }
+
+ return *this;
+}
+
+// adds nCount characters chPad to the string from either side
+wxString& wxString::Pad(size_t nCount, wxChar chPad, bool bFromRight)
+{
+ wxString s(chPad, nCount);
+
+ if ( bFromRight )
+ *this += s;
+ else
+ {
+ s += *this;
+ swap(s);
+ }
+
+ return *this;
+}
+
+// truncate the string
+wxString& wxString::Truncate(size_t uiLen)
+{
+ if ( uiLen < length() )
+ {
+ erase(begin() + uiLen, end());