]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/string.cpp
Better markup.
[wxWidgets.git] / src / common / string.cpp
index 76a89a88a32411a27e15adebda85d8da600d8360..f27e32da9bae78dc157b4698beb7eef9cb23b3b9 100644 (file)
@@ -100,6 +100,8 @@ extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = &g_strEmpty.dummy;
 //
 // ATTN: you can _not_ use both of these in the same program!
 
+#include <iostream>
+
 wxSTD istream& operator>>(wxSTD istream& is, wxString& WXUNUSED(str))
 {
 #if 0
@@ -168,6 +170,8 @@ wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str)
   #define STATISTICS_ADD(av, val)
 #endif // WXSTRING_STATISTICS
 
+#if !wxUSE_STL
+
 // ===========================================================================
 // wxStringData class deallocation
 // ===========================================================================
@@ -180,8 +184,6 @@ void wxStringData::Free()
 }
 #endif
 
-#if !wxUSE_STL
-
 // ===========================================================================
 // wxStringBase
 // ===========================================================================
@@ -248,7 +250,7 @@ bool wxStringBase::AllocBuffer(size_t nLen)
 
   if ( pData == NULL ) {
     // allocation failures are handled by the caller
-    return FALSE;
+    return false;
   }
 
   pData->nRefs        = 1;
@@ -256,7 +258,7 @@ bool wxStringBase::AllocBuffer(size_t nLen)
   pData->nAllocLength = nLen + EXTRA_ALLOC;
   m_pchData           = pData->data();  // data starts after wxStringData
   m_pchData[nLen]     = wxT('\0');
-  return TRUE;
+  return true;
 }
 
 // must be called before changing this string
@@ -269,14 +271,14 @@ bool wxStringBase::CopyBeforeWrite()
     size_t nLen = pData->nDataLength;
     if ( !AllocBuffer(nLen) ) {
       // allocation failures are handled by the caller
-      return FALSE;
+      return false;
     }
     memcpy(m_pchData, pData->data(), nLen*sizeof(wxChar));
   }
 
   wxASSERT( !GetStringData()->IsShared() );  // we must be the only owner
 
-  return TRUE;
+  return true;
 }
 
 // must be called before replacing contents of this string
@@ -291,7 +293,7 @@ bool wxStringBase::AllocBeforeWrite(size_t nLen)
     pData->Unlock();
     if ( !AllocBuffer(nLen) ) {
       // allocation failures are handled by the caller
-      return FALSE;
+      return false;
     }
   }
   else {
@@ -308,7 +310,7 @@ bool wxStringBase::AllocBeforeWrite(size_t nLen)
       if ( pData == NULL ) {
         // allocation failures are handled by the caller
         // keep previous data since reallocation failed
-        return FALSE;
+        return false;
       }
 
       pData->nAllocLength = nLen;
@@ -321,7 +323,7 @@ bool wxStringBase::AllocBeforeWrite(size_t nLen)
 
   wxASSERT( !GetStringData()->IsShared() );  // we must be the only owner
 
-  return TRUE;
+  return true;
 }
 
 wxStringBase& wxStringBase::append(size_t n, wxChar ch)
@@ -366,7 +368,7 @@ bool wxStringBase::Alloc(size_t nLen)
 
       if ( pData == NULL ) {
         // allocation failure handled by caller
-        return FALSE;
+        return false;
       }
 
       pData->nRefs = 1;
@@ -380,7 +382,7 @@ bool wxStringBase::Alloc(size_t nLen)
       size_t nOldLen = pData->nDataLength;
       if ( !AllocBuffer(nLen) ) {
         // allocation failure handled by caller
-        return FALSE;
+        return false;
       }
       memcpy(m_pchData, pData->data(), nOldLen*sizeof(wxChar));
     }
@@ -393,7 +395,7 @@ bool wxStringBase::Alloc(size_t nLen)
       if ( pData == NULL ) {
         // allocation failure handled by caller
         // keep previous data since reallocation failed
-        return FALSE;
+        return false;
       }
 
       // it's not important if the pointer changed or not (the check for this
@@ -403,7 +405,21 @@ bool wxStringBase::Alloc(size_t nLen)
     }
   }
   //else: we've already got enough
-  return TRUE;
+  return true;
+}
+
+wxStringBase::iterator wxStringBase::begin()
+{
+    if (length() > 0)
+        CopyBeforeWrite();
+    return m_pchData;
+}
+
+wxStringBase::iterator wxStringBase::end()
+{
+    if (length() > 0)
+        CopyBeforeWrite();
+    return m_pchData + length();
 }
 
 wxStringBase::iterator wxStringBase::erase(iterator it)
@@ -458,9 +474,27 @@ size_t wxStringBase::find(const wxStringBase& str, size_t nStart) const
   wxASSERT( str.GetStringData()->IsValid() );
   wxASSERT( nStart <= length() );
 
-  const wxChar *p = wxStrstr(c_str() + nStart, str.c_str());
+  //anchor
+  const wxChar* p = (const wxChar*)wxMemchr(c_str() + nStart, 
+                                            str.c_str()[0], 
+                                            length() - nStart);
+  if(!p)
+      return npos;
 
-  return p == NULL ? npos : p - c_str();
+  while(p - c_str() + str.length() <= length() &&
+        wxMemcmp(p, str.c_str(), str.length()) )
+  {
+      //anchor again
+      p = (const wxChar*)wxMemchr(++p, 
+                                  str.c_str()[0], 
+                                  length() - (p - c_str()));
+
+      if(!p)
+          return npos;
+  }
+       
+   return (p - c_str() + str.length() <= length()) ? p - c_str() : npos;
 }
 
 size_t wxStringBase::find(const wxChar* sz, size_t nStart, size_t n) const
@@ -472,7 +506,7 @@ size_t wxStringBase::find(wxChar ch, size_t nStart) const
 {
   wxASSERT( nStart <= length() );
 
-  const wxChar *p = wxStrchr(c_str() + nStart, ch);
+  const wxChar *p = (const wxChar*)wxMemchr(c_str() + nStart, ch, length() - nStart);
 
   return p == NULL ? npos : p - c_str();
 }
@@ -499,15 +533,14 @@ size_t wxStringBase::rfind(const wxStringBase& str, size_t nStart) const
         const wxChar *cursor = c_str() + top;
         do
         {
-            if ( memcmp(cursor, str.c_str(),
-                        str.length() * sizeof(wxChar)) == 0 )
+            if ( wxMemcmp(cursor, str.c_str(),
+                        str.length()) == 0 )
             {
                 return cursor - c_str();
             }
-            --cursor;
-        } while ( cursor > c_str() );
+        } while ( cursor-- > c_str() );
     }
-    
+
     return npos;
 }
 
@@ -540,12 +573,21 @@ size_t wxStringBase::rfind(wxChar ch, size_t nStart) const
 
 size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart) const
 {
-    const wxChar *start = c_str() + nStart;
-    const wxChar *firstOf = wxStrpbrk(start, sz);
-    if ( firstOf )
-        return firstOf - c_str();
-    else
+    wxASSERT(nStart <= length());
+
+    size_t len = wxStrlen(sz);
+
+    size_t i;
+    for(i = nStart; i < this->length(); ++i)
+    {
+        if (wxMemchr(sz, *(c_str() + i), len))
+            break;
+    }
+
+    if(i == this->length())
         return npos;
+    else
+        return i;
 }
 
 size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart,
@@ -566,9 +608,11 @@ size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart) const
                         _T("invalid index in find_last_of()") );
     }
 
+    size_t len = wxStrlen(sz);
+    
     for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
     {
-        if ( wxStrchr(sz, *p) )
+        if ( wxMemchr(sz, *p, len) )
             return p - c_str();
     }
 
@@ -592,11 +636,19 @@ size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart) const
         wxASSERT( nStart <= length() );
     }
 
-    size_t nAccept = wxStrspn(c_str() + nStart, sz);
-    if ( nAccept >= length() - nStart )
-        return npos;
-    else
-        return nStart + nAccept;
+    size_t len = wxStrlen(sz);
+
+    size_t i;
+    for(i = nStart; i < this->length(); ++i)
+    {
+        if (!wxMemchr(sz, *(c_str() + i), len))
+            break;
+    }
+
+    if(i == this->length())
+         return npos;
+     else
+        return i;
 }
 
 size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart,
@@ -629,10 +681,12 @@ size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart) const
         wxASSERT( nStart <= length() );
     }
 
+    size_t len = wxStrlen(sz);
+
     for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
     {
-        if ( !wxStrchr(sz, *p) )
-            return p - c_str();
+        if ( !wxMemchr(sz, *p,len) )
+             return p - c_str();
     }
 
     return npos;
@@ -758,13 +812,13 @@ bool wxStringBase::AssignCopy(size_t nSrcLen, const wxChar *pszSrcData)
   else {
     if ( !AllocBeforeWrite(nSrcLen) ) {
       // allocation failure handled by caller
-      return FALSE;
+      return false;
     }
     memcpy(m_pchData, pszSrcData, nSrcLen*sizeof(wxChar));
     GetStringData()->nDataLength = nSrcLen;
     m_pchData[nSrcLen] = wxT('\0');
   }
-  return TRUE;
+  return true;
 }
 
 // ---------------------------------------------------------------------------
@@ -793,7 +847,7 @@ bool wxStringBase::ConcatSelf(size_t nSrcLen, const wxChar *pszSrcData,
       wxStringData* pOldData = GetStringData();
       if ( !AllocBuffer(nNewLen) ) {
           // allocation failure handled by caller
-          return FALSE;
+          return false;
       }
       memcpy(m_pchData, pOldData->data(), nLen*sizeof(wxChar));
       pOldData->Unlock();
@@ -805,7 +859,7 @@ bool wxStringBase::ConcatSelf(size_t nSrcLen, const wxChar *pszSrcData,
       // we have to grow the buffer
       if ( capacity() < nNewLen ) {
           // allocation failure handled by caller
-          return FALSE;
+          return false;
       }
     }
     else {
@@ -824,7 +878,7 @@ bool wxStringBase::ConcatSelf(size_t nSrcLen, const wxChar *pszSrcData,
     GetStringData()->nDataLength = nNewLen; // and fix the length
   }
   //else: the string to append was empty
-  return TRUE;
+  return true;
 }
 
 // ---------------------------------------------------------------------------
@@ -840,11 +894,11 @@ bool wxStringBase::AllocCopy(wxString& dest, int nCopyLen, int nCopyIndex) const
   else {
     if ( !dest.AllocBuffer(nCopyLen) ) {
       // allocation failure handled by caller
-      return FALSE;
+      return false;
     }
     memcpy(dest.m_pchData, m_pchData + nCopyIndex, nCopyLen*sizeof(wxChar));
   }
-  return TRUE;
+  return true;
 }
 
 #endif // !wxUSE_STL
@@ -861,15 +915,15 @@ static inline int wxDoCmp(const wxChar* s1, size_t l1,
                           const wxChar* s2, size_t l2)
 {
     if( l1 == l2 )
-        return wxStrncmp(s1, s2, l1);
+        return wxMemcmp(s1, s2, l1);
     else if( l1 < l2 )
     {
-        int ret = wxStrncmp(s1, s2, l1);
+        int ret = wxMemcmp(s1, s2, l1);
         return ret == 0 ? -1 : ret;
     }
     else if( l1 > l2 )
     {
-        int ret = wxStrncmp(s1, s2, l2);
+        int ret = wxMemcmp(s1, s2, l2);
         return ret == 0 ? +1 : ret;
     }
 
@@ -877,15 +931,11 @@ static inline int wxDoCmp(const wxChar* s1, size_t l1,
     return 0; // quiet compilers
 }
 
-#if wxUSE_STL
-
 int STRINGCLASS::compare(const wxStringBase& str) const
 {
     return ::wxDoCmp(data(), length(), str.data(), str.length());
 }
 
-#endif
-
 int STRINGCLASS::compare(size_t nStart, size_t nLen,
                          const wxStringBase& str) const
 {
@@ -908,16 +958,12 @@ int STRINGCLASS::compare(size_t nStart, size_t nLen,
     return ::wxDoCmp(data() + nStart, nLen, str.data() + nStart2, nLen2);
 }
 
-#if wxUSE_STL
-
 int STRINGCLASS::compare(const wxChar* sz) const
 {
     size_t nLen = wxStrlen(sz);
     return ::wxDoCmp(data(), length(), sz, nLen);
 }
 
-#endif
-
 int STRINGCLASS::compare(size_t nStart, size_t nLen,
                          const wxChar* sz, size_t nCount) const
 {
@@ -947,12 +993,26 @@ int STRINGCLASS::compare(size_t nStart, size_t nLen,
 // 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 = nLength == npos ? conv.MB2WC(NULL, psz, 0) : nLength;
+        nLen = conv.MB2WC(NULL, psz, 0);
     }
     else
     {
@@ -969,7 +1029,7 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
         }
         else
         {
-            wxWCharBuffer buf(nLen + 1);
+            wxWCharBuffer buf(nLen);
             // MB2WC wants the buffer size, not the string length hence +1
             nLen = conv.MB2WC(buf.data(), psz, nLen + 1);
 
@@ -983,6 +1043,36 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
             //else: the conversion failed -- leave the string empty (what else?)
         }
     }
+}        
+
+const wxCharBuffer wxString::mb_str(wxMBConv& conv) const
+{
+    const wxChar* szEnd = (*this).c_str() + length() + 1;
+    const wxChar* szPos = (*this).c_str();
+    const wxChar* szStart = szPos;
+    
+    wxCharBuffer buffer(length() + 1);
+    
+    //Convert the string until the length() is reached, continuing the
+    //loop every time a null character is reached
+    while(szPos != szEnd)
+    {
+        size_t nLen = conv.WC2MB(NULL, szPos, 0);
+        
+        wxASSERT(nLen != (size_t)-1); //should not be true!  If it is system wctomb could be bad
+
+        if ( conv.WC2MB(&buffer.data()[szPos - szStart], szPos, nLen + 1) == (size_t)-1 )
+        {
+            //error - return empty buffer
+            wxFAIL_MSG(wxT("Error converting wide-character string to a multi-byte string"));
+            buffer.data()[0] = '\0';
+            return buffer;
+        }        
+        
+        szPos += nLen + 1;
+    }
+    
+    return buffer;
 }
 
 #else // ANSI
@@ -991,12 +1081,26 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
 // 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 = nLength == npos ? conv.WC2MB(NULL, pwz, 0) : nLength;
+        nLen = conv.WC2MB(NULL, pwz, 0);
     }
     else
     {
@@ -1027,6 +1131,37 @@ wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength)
 
     // leave empty
 }
+
+const wxWCharBuffer wxString::wc_str(wxMBConv& conv) const
+{
+    const wxChar* szEnd = (*this).c_str() + length() + 1;
+    const wxChar* szPos = (*this).c_str();
+    const wxChar* szStart = szPos;
+    
+    wxWCharBuffer buffer(length() + 1);
+    
+    //Convert the string until the length() is reached, continuing the
+    //loop every time a null character is reached
+    while(szPos != szEnd)
+    {
+        size_t nLen = conv.MB2WC(NULL, szPos, 0);
+        
+        wxASSERT(nLen != (size_t)-1); //should not be true!  If it is system mbtowc could be bad
+        
+        if ( conv.MB2WC(&buffer.data()[szPos - szStart], szPos, nLen + 1) == (size_t)-1 )
+        {
+            //error - return empty buffer
+            wxFAIL_MSG(wxT("Error converting multi-byte string to a wide-character string"));
+            buffer.data()[0] = '\0';
+            return buffer;
+        }        
+        
+        szPos += nLen + 1;
+    }
+    
+    return buffer;
+}
+    
 #endif // wxUSE_WCHAR_T
 
 #endif // Unicode/ANSI
@@ -1049,7 +1184,7 @@ wxChar *wxString::GetWriteBuf(size_t nLen)
   }
 
   wxASSERT( GetStringData()->nRefs == 1 );
-  GetStringData()->Validate(FALSE);
+  GetStringData()->Validate(false);
 
   return m_pchData;
 }
@@ -1058,13 +1193,13 @@ wxChar *wxString::GetWriteBuf(size_t nLen)
 void wxString::UngetWriteBuf()
 {
   GetStringData()->nDataLength = wxStrlen(m_pchData);
-  GetStringData()->Validate(TRUE);
+  GetStringData()->Validate(true);
 }
 
 void wxString::UngetWriteBuf(size_t nLen)
 {
   GetStringData()->nDataLength = nLen;
-  GetStringData()->Validate(TRUE);
+  GetStringData()->Validate(true);
 }
 #endif
 
@@ -1178,8 +1313,74 @@ wxString operator+(const wxChar *psz, const wxString& str)
 // 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 : s1[i] < 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 : s1[i] < s2[i] ? -1 : 1;
+    }
+    else if( l1 > l2 )
+    {
+        for(i = 0; i < l2; ++i)
+        {
+            if(wxTolower(s1[i]) != wxTolower(s2[i]))
+                break;
+        }
+        return i == l2 ? 1 : s1[i] < s2[i] ? -1 : 1;
+    }
+
+    wxFAIL;   // must never get there
+    return 0; // quiet compilers
+}
+
+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)
@@ -1269,7 +1470,7 @@ wxString wxString::Mid(size_t nFirst, size_t nCount) const
 }
 
 // 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
+// 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") );
@@ -1284,7 +1485,7 @@ bool wxString::StartsWith(const wxChar *prefix, wxString *rest) const
         if ( *prefix++ != *p++ )
         {
             // no match
-            return FALSE;
+            return false;
         }
     }
 
@@ -1294,7 +1495,7 @@ bool wxString::StartsWith(const wxChar *prefix, wxString *rest) const
         *rest = p;
     }
 
-    return TRUE;
+    return true;
 }
 
 // extract nCount last (rightmost) characters
@@ -1315,7 +1516,7 @@ wxString wxString::Right(size_t nCount) const
 wxString wxString::AfterLast(wxChar ch) const
 {
   wxString str;
-  int iPos = Find(ch, TRUE);
+  int iPos = Find(ch, true);
   if ( iPos == wxNOT_FOUND )
     str = *this;
   else
@@ -1351,7 +1552,7 @@ wxString wxString::BeforeFirst(wxChar ch) const
 wxString wxString::BeforeLast(wxChar ch) const
 {
   wxString str;
-  int iPos = Find(ch, TRUE);
+  int iPos = Find(ch, true);
   if ( iPos != wxNOT_FOUND && iPos != 0 )
     str = wxString(c_str(), iPos);
 
@@ -1426,20 +1627,20 @@ bool wxString::IsAscii() const
 {
   const wxChar *s = (const wxChar*) *this;
   while(*s){
-    if(!isascii(*s)) return(FALSE);
+    if(!isascii(*s)) return(false);
     s++;
   }
-  return(TRUE);
+  return(true);
 }
 
 bool wxString::IsWord() const
 {
   const wxChar *s = (const wxChar*) *this;
   while(*s){
-    if(!wxIsalpha(*s)) return(FALSE);
+    if(!wxIsalpha(*s)) return(false);
     s++;
   }
-  return(TRUE);
+  return(true);
 }
 
 bool wxString::IsNumber() const
@@ -1448,17 +1649,17 @@ bool wxString::IsNumber() const
   if (wxStrlen(s))
      if ((s[0] == '-') || (s[0] == '+')) s++;
   while(*s){
-    if(!wxIsdigit(*s)) return(FALSE);
+    if(!wxIsdigit(*s)) return(false);
     s++;
   }
-  return(TRUE);
+  return(true);
 }
 
 wxString wxString::Strip(stripType w) const
 {
     wxString s = *this;
-    if ( w & leading ) s.Trim(FALSE);
-    if ( w & trailing ) s.Trim(TRUE);
+    if ( w & leading ) s.Trim(false);
+    if ( w & trailing ) s.Trim(true);
     return s;
 }
 
@@ -1486,7 +1687,7 @@ wxString& wxString::MakeLower()
 // trimming and padding
 // ---------------------------------------------------------------------------
 
-// some compilers (VC++ 6.0 not to name them) return TRUE for a call to
+// 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
@@ -1584,41 +1785,41 @@ int wxString::Find(const wxChar *pszSub) const
 
 bool wxString::ToLong(long *val, int base) const
 {
-    wxCHECK_MSG( val, FALSE, _T("NULL pointer in wxString::ToLong") );
+    wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToLong") );
     wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
 
     const wxChar *start = c_str();
     wxChar *end;
     *val = wxStrtol(start, &end, base);
 
-    // return TRUE only if scan was stopped by the terminating NUL and if the
+    // return true only if scan was stopped by the terminating NUL and if the
     // string was not empty to start with
     return !*end && (end != start);
 }
 
 bool wxString::ToULong(unsigned long *val, int base) const
 {
-    wxCHECK_MSG( val, FALSE, _T("NULL pointer in wxString::ToULong") );
+    wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToULong") );
     wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
 
     const wxChar *start = c_str();
     wxChar *end;
     *val = wxStrtoul(start, &end, base);
 
-    // return TRUE only if scan was stopped by the terminating NUL and if the
+    // return true only if scan was stopped by the terminating NUL and if the
     // string was not empty to start with
     return !*end && (end != start);
 }
 
 bool wxString::ToDouble(double *val) const
 {
-    wxCHECK_MSG( val, FALSE, _T("NULL pointer in wxString::ToDouble") );
+    wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToDouble") );
 
     const wxChar *start = c_str();
     wxChar *end;
     *val = wxStrtod(start, &end);
 
-    // return TRUE only if scan was stopped by the terminating NUL and if the
+    // return true only if scan was stopped by the terminating NUL and if the
     // string was not empty to start with
     return !*end && (end != start);
 }
@@ -1678,7 +1879,12 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr)
                 return -1;
             }
 
-            len = wxVsnprintf(buf, size, pszFormat, argptr);
+            // wxVsnprintf() may modify the original arg pointer, so pass it
+            // only a copy
+            va_list argptrcopy;
+            wxVaCopy(argptrcopy, argptr);
+            len = wxVsnprintf(buf, size, pszFormat, argptrcopy);
+            va_end(argptrcopy);
 
             // some implementations of vsnprintf() don't NUL terminate
             // the string if there is not enough space for it so
@@ -1686,7 +1892,10 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr)
             buf[size] = _T('\0');
         }
 
-        if ( len >= 0 )
+        // vsnprintf() may return either -1 (traditional Unix behaviour) or the
+        // total number of characters which would have been written if the
+        // buffer were large enough
+        if ( len >= 0 && len <= size )
         {
             // ok, there was enough space
             break;
@@ -1706,7 +1915,7 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr)
 // misc other operations
 // ----------------------------------------------------------------------------
 
-// returns TRUE if the string matches the pattern which may contain '*' and
+// returns true if the string matches the pattern which may contain '*' and
 // '?' metacharacters (as usual, '?' matches any character and '*' any number
 // of them)
 bool wxString::Matches(const wxChar *pszMask) const
@@ -1772,7 +1981,7 @@ match:
     switch ( *pszMask ) {
       case wxT('?'):
         if ( *pszTxt == wxT('\0') )
-          return FALSE;
+          return false;
 
         // pszTxt and pszMask will be incremented in the loop statement
 
@@ -1791,7 +2000,7 @@ match:
 
           // if there is nothing more, match
           if ( *pszMask == wxT('\0') )
-            return TRUE;
+            return true;
 
           // are there any other metacharacters in the mask?
           size_t uiLenMask;
@@ -1809,7 +2018,7 @@ match:
           wxString strToMatch(pszMask, uiLenMask);
           const wxChar* pMatch = wxStrstr(pszTxt, strToMatch);
           if ( pMatch == NULL )
-            return FALSE;
+            return false;
 
           // -1 to compensate "++" in the loop
           pszTxt = pMatch + uiLenMask - 1;
@@ -1819,14 +2028,14 @@ match:
 
       default:
         if ( *pszMask != *pszTxt )
-          return FALSE;
+          return false;
         break;
     }
   }
 
   // match only if nothing left
   if ( *pszTxt == wxT('\0') )
-    return TRUE;
+    return true;
 
   // if we failed to match, backtrack if we can
   if ( pszLastStarInText ) {
@@ -1840,7 +2049,7 @@ match:
     goto match;
   }
 
-  return FALSE;
+  return false;
 #endif // wxUSE_REGEX/!wxUSE_REGEX
 }
 
@@ -2119,7 +2328,7 @@ size_t wxArrayString::Add(const wxString& str, size_t nInsert)
     while ( lo < hi ) {
       i = (lo + hi)/2;
 
-      res = wxStrcmp(str, m_pItems[i]);
+      res = str.Cmp(m_pItems[i]);
       if ( res < 0 )
         hi = i;
       else if ( res > 0 )
@@ -2177,6 +2386,30 @@ void wxArrayString::Insert(const wxString& str, size_t nIndex, size_t nInsert)
   m_nCount += nInsert;
 }
 
+// range insert (STL 23.2.4.3)
+void
+wxArrayString::insert(iterator it, const_iterator first, const_iterator last)
+{
+    const int idx = it - begin();
+
+    // grow it once
+    Grow(last - first);
+
+    // reset "it" since it can change inside Grow()
+    it = begin() + idx;
+
+    while ( first != last )
+    {
+        it = insert(it, *first);
+
+        // insert returns an iterator to the last element inserted but we need
+        // insert the next after this one, that is before the next one
+        ++it;
+
+        ++first;
+    }
+}
+
 // expand the array
 void wxArrayString::SetCount(size_t count)
 {
@@ -2250,7 +2483,7 @@ static wxArrayString::CompareFunction gs_compareFunction = NULL;
 
 // if we don't use the compare function, this flag tells us if we sort the
 // array in ascending or descending order
-static bool gs_sortAscending = TRUE;
+static bool gs_sortAscending = true;
 
 // function which is called by quick sort
 extern "C" int wxC_CALLING_CONV     // LINKAGEMODE
@@ -2264,7 +2497,7 @@ wxStringCompareFunction(const void *first, const void *second)
   }
   else {
     // maybe we should use wxStrcoll
-    int result = wxStrcmp(strFirst->c_str(), strSecond->c_str());
+    int result = strFirst->Cmp(*strSecond);
 
     return gs_sortAscending ? result : -result;
   }
@@ -2310,25 +2543,25 @@ void wxArrayString::DoSort()
 bool wxArrayString::operator==(const wxArrayString& a) const
 {
     if ( m_nCount != a.m_nCount )
-        return FALSE;
+        return false;
 
     for ( size_t n = 0; n < m_nCount; n++ )
     {
         if ( Item(n) != a[n] )
-            return FALSE;
+            return false;
     }
 
-    return TRUE;
+    return true;
 }
 
 #endif // !wxUSE_STL
 
-int wxStringSortAscending(wxString* s1, wxString* s2)
+int wxCMPFUNC_CONV wxStringSortAscending(wxString* s1, wxString* s2)
 {
-    return wxStrcmp(s1->c_str(), s2->c_str());
+    return  s1->Cmp(*s2);
 }
 
-int wxStringSortDescending(wxString* s1, wxString* s2)
+int wxCMPFUNC_CONV wxStringSortDescending(wxString* s1, wxString* s2)
 {
-    return -wxStrcmp(s1->c_str(), s2->c_str());
+    return -s1->Cmp(*s2);
 }