]> git.saurik.com Git - wxWidgets.git/blobdiff - include/wx/string.h
* Renamed fstream.h in wfstream.h
[wxWidgets.git] / include / wx / string.h
index 62a5730f58bf8448c5cadd493dde66ff61ff137d..1db45300c411696570a98fc3a3b1ab58c8f82747 100644 (file)
@@ -6,11 +6,11 @@
 // Created:     29/01/98
 // RCS-ID:      $Id$
 // Copyright:   (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
-// Licence:    wxWindows license
+// Licence:     wxWindows license
 /////////////////////////////////////////////////////////////////////////////
 
-#ifndef __WXSTRINGH__
-#define __WXSTRINGH__
+#ifndef _WX_WXSTRINGH__
+#define _WX_WXSTRINGH__
 
 #ifdef __GNUG__
 #pragma interface "string.h"
 #include <stdio.h>
 #include <stdarg.h>
 #include <limits.h>
+#include <stdlib.h>
+
+#ifndef  WX_PRECOMP
+  #include "wx/defs.h"     // Robert Roebling
+  #ifdef    WXSTRING_IS_WXOBJECT
+    #include "wx/object.h"
+  #endif
+#endif
 
-#include "wx/defs.h"     // Robert Roebling
-#include "wx/object.h"
 #include "wx/debug.h"
 
 /** @name wxString library
     @memo Efficient wxString class [more or less] compatible with MFC CString,
-          wxWindows wxString and std::string and some handy functions 
+          wxWindows wxString and std::string and some handy functions
           missing from string.h.
   */
 //@{
@@ -42,7 +48,7 @@
 // macros
 // ---------------------------------------------------------------------------
 
-/** @name Macros 
+/** @name Macros
     @memo You can switch off wxString/std::string compatibility if desired
  */
 /// compile the std::string compatibility functions
@@ -62,7 +68,7 @@
 #define   ASSERT_VALID_INDEX(i) wxASSERT( (unsigned)(i) < Len() )
 
 // ---------------------------------------------------------------------------
-/** @name Global functions complementing standard C string library 
+/** @name Global functions complementing standard C string library
     @memo replacements for strlen() and portable strcasecmp()
  */
 // ---------------------------------------------------------------------------
@@ -75,10 +81,45 @@ inline size_t  WXDLLEXPORT Strlen(const char *psz)
   { return psz ? strlen(psz) : 0; }
 
 /// portable strcasecmp/_stricmp
-int WXDLLEXPORT Stricmp(const char *, const char *);
+inline int WXDLLEXPORT Stricmp(const char *psz1, const char *psz2)
+{
+#if     defined(_MSC_VER)
+  return _stricmp(psz1, psz2);
+#elif defined(__BORLANDC__)
+  return stricmp(psz1, psz2);
+#elif   defined(__UNIX__) || defined(__GNUWIN32__)
+  return strcasecmp(psz1, psz2);
+#else
+  // almost all compilers/libraries provide this function (unfortunately under
+  // different names), that's why we don't implement our own which will surely
+  // be more efficient than this code (uncomment to use):
+  /*
+    register char c1, c2;
+    do {
+      c1 = tolower(*psz1++);
+      c2 = tolower(*psz2++);
+    } while ( c1 && (c1 == c2) );
+
+    return c1 - c2;
+  */
+
+  #error  "Please define string case-insensitive compare for your OS/compiler"
+#endif  // OS/compiler
+}
+
+// ----------------------------------------------------------------------------
+// global data
+// ----------------------------------------------------------------------------
+
+// global pointer to empty string
+WXDLLEXPORT_DATA(extern const char*) g_szNul;
+
+// return an empty wxString
+class WXDLLEXPORT wxString; // not yet defined
+inline const wxString& wxGetEmptyString() { return *(wxString *)&g_szNul; }
 
 // ---------------------------------------------------------------------------
-// string data prepended with some housekeeping info (used by String class),
+// string data prepended with some housekeeping info (used by wxString class),
 // is never used directly (but had to be put here to allow inlining)
 // ---------------------------------------------------------------------------
 struct WXDLLEXPORT wxStringData
@@ -88,19 +129,21 @@ struct WXDLLEXPORT wxStringData
           nAllocLength; // allocated memory size
 
   // mimics declaration 'char data[nAllocLength]'
-  char* data() const { return (char*)(this + 1); }  
+  char* data() const { return (char*)(this + 1); }
 
   // empty string has a special ref count so it's never deleted
   bool  IsEmpty()   const { return nRefs == -1; }
   bool  IsShared()  const { return nRefs > 1;   }
-  bool  IsValid()   const { return nRefs != 0;  }
 
   // lock/unlock
-  void  Lock()   { if ( !IsEmpty() ) nRefs++;                             }
-  void  Unlock() { if ( !IsEmpty() && --nRefs == 0) delete (char *)this;  }
-};
+  void  Lock()   { if ( !IsEmpty() ) nRefs++;                    }
+  void  Unlock() { if ( !IsEmpty() && --nRefs == 0) free(this);  }
 
-extern const char *g_szNul; // global pointer to empty string
+  // if we had taken control over string memory (GetWriteBuf), it's
+  // intentionally put in invalid state
+  void  Validate(bool b)  { nRefs = b ? 1 : 0; }
+  bool  IsValid() const   { return nRefs != 0; }
+};
 
 // ---------------------------------------------------------------------------
 /**
@@ -113,9 +156,9 @@ extern const char *g_szNul; // global pointer to empty string
     This class aims to be as compatible as possible with the new standard
     std::string class, but adds some additional functions and should be
     at least as efficient than the standard implementation.
-    
-    Performance note: it's more efficient to write functions which take 
-    "const String&" arguments than "const char *" if you assign the argument 
+
+    Performance note: it's more efficient to write functions which take
+    "const String&" arguments than "const char *" if you assign the argument
     to another string.
 
     It was compiled and tested under Win32, Linux (libc 5 & 6), Solaris 5.5.
@@ -124,7 +167,7 @@ extern const char *g_szNul; // global pointer to empty string
       - ressource support (string tables in ressources)
       - more wide character (UNICODE) support
       - regular expressions support
-    
+
 @memo     A non-template portable wxString class implementing copy-on-write.
 @author   VZ
 @version  1.3
@@ -139,25 +182,73 @@ extern const char *g_szNul; // global pointer to empty string
   {
 #endif  //WXSTRING_IS_WXOBJECT
 
-friend class wxArrayString;
+friend class WXDLLEXPORT wxArrayString;
+
+  // NB: special care was taken in arrangin the member functions in such order
+  //     that all inline functions can be effectively inlined
+private:
+  // points to data preceded by wxStringData structure with ref count info
+  char *m_pchData;
+
+  // accessor to string data
+  wxStringData* GetStringData() const { return (wxStringData*)m_pchData - 1; }
+
+  // string (re)initialization functions
+    // initializes the string to the empty value (must be called only from
+    // ctors, use Reinit() otherwise)
+  void Init() { m_pchData = (char *)g_szNul; }
+    // initializaes the string with (a part of) C-string
+  void InitWith(const char *psz, size_t nPos = 0, size_t nLen = STRING_MAXLEN);
+    // as Init, but also frees old data
+  void Reinit() { GetStringData()->Unlock(); Init(); }
+
+  // memory allocation
+    // allocates memory for string of lenght nLen
+  void AllocBuffer(size_t nLen);
+    // copies data to another string
+  void AllocCopy(wxString&, int, int) const;
+    // effectively copies data to string
+  void AssignCopy(size_t, const char *);
+
+  // append a (sub)string
+  void ConcatSelf(int nLen, const char *src);
+
+  // functions called before writing to the string: they copy it if there
+  // are other references to our data (should be the only owner when writing)
+  void CopyBeforeWrite();
+  void AllocBeforeWrite(size_t);
 
 public:
   /** @name constructors & dtor */
   //@{
     /// ctor for an empty string
-  wxString();
+  wxString() { Init(); }
     /// copy ctor
-  wxString(const wxString& stringSrc);        
+  wxString(const wxString& stringSrc)
+  {
+    wxASSERT( stringSrc.GetStringData()->IsValid() );
+
+    if ( stringSrc.IsEmpty() ) {
+      // nothing to do for an empty string
+      Init();
+    }
+    else {
+      m_pchData = stringSrc.m_pchData;            // share same data
+      GetStringData()->Lock();                    // => one more copy
+    }
+  }
     /// string containing nRepeat copies of ch
-  wxString(char ch, size_t nRepeat = 1);       
+  wxString(char ch, size_t nRepeat = 1);
     /// ctor takes first nLength characters from C string
-  wxString(const char *psz, size_t nLength = STRING_MAXLEN);
+    // (default value of STRING_MAXLEN means take all the string)
+  wxString(const char *psz, size_t nLength = STRING_MAXLEN)
+    { InitWith(psz, 0, nLength); }
     /// from C string (for compilers using unsigned char)
   wxString(const unsigned char* psz, size_t nLength = STRING_MAXLEN);
     /// from wide (UNICODE) string
   wxString(const wchar_t *pwz);
     /// dtor is not virtual, this class must not be inherited from!
- ~wxString();
+ ~wxString() { GetStringData()->Unlock(); }
   //@}
 
   /** @name generic attributes & operations */
@@ -165,9 +256,17 @@ public:
     /// as standard strlen()
   size_t Len() const { return GetStringData()->nDataLength; }
     /// string contains any characters?
-  bool IsEmpty() const;
-    /// reinitialize string (and free data!)
-  void Empty();
+  bool IsEmpty() const { return Len() == 0; }
+    /// reinitialize string (and free memory)
+  void Empty()
+  {
+    if ( !IsEmpty() )
+      Reinit();
+
+    wxASSERT( GetStringData()->nDataLength == 0 );
+    wxASSERT( GetStringData()->nAllocLength == 0 );
+  }
+
     /// Is an ascii value
   bool IsAscii() const;
     /// Is a number
@@ -180,10 +279,10 @@ public:
   //@{
     /// read access
     char  GetChar(size_t n) const
-         { ASSERT_VALID_INDEX( n );  return m_pchData[n]; }
+      { ASSERT_VALID_INDEX( n );  return m_pchData[n]; }
     /// read/write access
     char& GetWritableChar(size_t n)
-         { ASSERT_VALID_INDEX( n ); CopyBeforeWrite(); return m_pchData[n]; }
+      { ASSERT_VALID_INDEX( n ); CopyBeforeWrite(); return m_pchData[n]; }
     /// write access
     void  SetChar(size_t n, char ch)
       { ASSERT_VALID_INDEX( n ); CopyBeforeWrite(); m_pchData[n] = ch; }
@@ -192,7 +291,7 @@ public:
     char  Last() const
       { wxASSERT( !IsEmpty() ); return m_pchData[Len() - 1]; }
     /// get writable last character
-    char& Last() 
+    char& Last()
       { wxASSERT( !IsEmpty() ); CopyBeforeWrite(); return m_pchData[Len()-1]; }
 
     /// operator version of GetChar
@@ -206,7 +305,7 @@ public:
       { ASSERT_VALID_INDEX( n ); CopyBeforeWrite(); return m_pchData[n]; }
 
     /// implicit conversion to C string
-    operator const char*() const { return m_pchData; } 
+    operator const char*() const { return m_pchData; }
     /// explicit conversion to C string (use this with printf()!)
     const char* c_str()   const { return m_pchData; }
     ///
@@ -226,55 +325,63 @@ public:
     ///
   wxString& operator=(const wchar_t *pwz);
   //@}
-  
+
   /** @name string concatenation */
   //@{
     /** @name in place concatenation */
-    //@{
-      /// string += string
-  void operator+=(const wxString& string);
-      /// string += C string
-  void operator+=(const char *psz);
-      /// string += char
-  void operator+=(char ch);
-    //@}
     /** @name concatenate and return the result
-        left to right associativity of << allows to write 
+        left to right associativity of << allows to write
         things like "str << str1 << str2 << ..."          */
     //@{
       /// as +=
-  wxString& operator<<(const wxString& string);
+  wxString& operator<<(const wxString& s)
+  {
+    wxASSERT( s.GetStringData()->IsValid() );
+
+    ConcatSelf(s.Len(), s);
+    return *this;
+  }
       /// as +=
-  wxString& operator<<(char ch);
+  wxString& operator<<(const char *psz)
+    { ConcatSelf(Strlen(psz), psz); return *this; }
       /// as +=
-  wxString& operator<<(const char *psz);
+  wxString& operator<<(char ch) { ConcatSelf(1, &ch); return *this; }
+    //@}
+
+    //@{
+      /// string += string
+  void operator+=(const wxString& s) { (void)operator<<(s); }
+      /// string += C string
+  void operator+=(const char *psz) { (void)operator<<(psz); }
+      /// string += char
+  void operator+=(char ch) { (void)operator<<(ch); }
     //@}
-    
+
     /** @name return resulting string */
     //@{
       ///
-  friend wxString operator+(const wxString& string1,  const wxString& string2);
+  friend wxString WXDLLEXPORT operator+(const wxString& string1,  const wxString& string2);
       ///
-  friend wxString operator+(const wxString& string, char ch);
+  friend wxString WXDLLEXPORT operator+(const wxString& string, char ch);
       ///
-  friend wxString operator+(char ch, const wxString& string);
+  friend wxString WXDLLEXPORT operator+(char ch, const wxString& string);
       ///
-  friend wxString operator+(const wxString& string, const char *psz);
+  friend wxString WXDLLEXPORT operator+(const wxString& string, const char *psz);
       ///
-  friend wxString operator+(const char *psz, const wxString& string);
+  friend wxString WXDLLEXPORT operator+(const char *psz, const wxString& string);
     //@}
   //@}
-  
+
   /** @name string comparison */
   //@{
-    /** 
-    case-sensitive comparaison
+    /**
+    case-sensitive comparison
     @return 0 if equal, +1 if greater or -1 if less
     @see CmpNoCase, IsSameAs
     */
   int  Cmp(const char *psz) const { return strcmp(c_str(), psz); }
     /**
-    case-insensitive comparaison, return code as for wxString::Cmp()
+    case-insensitive comparison, return code as for wxString::Cmp()
     @see: Cmp, IsSameAs
     */
   int  CmpNoCase(const char *psz) const { return Stricmp(c_str(), psz); }
@@ -284,20 +391,20 @@ public:
     @return  TRUE if strings are equal, FALSE otherwise
     @see     Cmp, CmpNoCase
     */
-  bool IsSameAs(const char *psz, bool bCase = TRUE) const 
+  bool IsSameAs(const char *psz, bool bCase = TRUE) const
     { return !(bCase ? Cmp(psz) : CmpNoCase(psz)); }
   //@}
-  
+
   /** @name other standard string operations */
   //@{
     /** @name simple sub-string extraction
      */
     //@{
-      /** 
-      return substring starting at nFirst of length 
+      /**
+      return substring starting at nFirst of length
       nCount (or till the end if nCount = default value)
       */
-  wxString Mid(size_t nFirst, size_t nCount = STRING_MAXLEN) const;  
+  wxString Mid(size_t nFirst, size_t nCount = STRING_MAXLEN) const;
       /// get first nCount characters
   wxString Left(size_t nCount) const;
       /// get all characters before the first occurence of ch
@@ -315,9 +422,9 @@ public:
       /// (returns the whole string if ch not found)
   wxString Right(char ch) const;
     //@}
-    
+
     /** @name case conversion */
-    //@{ 
+    //@{
       ///
   wxString& MakeUpper();
       ///
@@ -333,7 +440,7 @@ public:
       /// truncate string to given length
   wxString& Truncate(size_t uiLen);
     //@}
-    
+
     /** @name searching and replacing */
     //@{
       /// searching (return starting index, or -1 if not found)
@@ -345,8 +452,11 @@ public:
       @param  bReplaceAll: global replace (default) or only the first occurence
       @return the number of replacements made
       */
-  uint Replace(const char *szOld, const char *szNew, bool bReplaceAll = TRUE);
+  size_t Replace(const char *szOld, const char *szNew, bool bReplaceAll = TRUE);
     //@}
+
+    /// check if the string contents matches a mask containing '*' and '?'
+  bool Matches(const char *szMask) const;
   //@}
 
   /** @name formated input/output */
@@ -356,9 +466,24 @@ public:
     /// as vprintf(), returns the number of characters written or < 0 on error
   int PrintfV(const char* pszFormat, va_list argptr);
   //@}
-  
-  // get writable buffer of at least nLen characters
+
+  /** @name raw access to string memory */
+  //@{
+    /// ensure that string has space for at least nLen characters
+    // only works if the data of this string is not shared
+  void Alloc(size_t nLen);
+    /// minimize the string's memory
+    // only works if the data of this string is not shared
+  void Shrink();
+    /**
+        get writable buffer of at least nLen bytes.
+        Unget() *must* be called a.s.a.p. to put string back in a reasonable
+        state!
+     */
   char *GetWriteBuf(size_t nLen);
+    /// call this immediately after GetWriteBuf() has been used
+  void UngetWriteBuf();
+  //@}
 
   /** @name wxWindows compatibility functions */
   //@{
@@ -378,17 +503,20 @@ public:
 
     /// same as Cmp
   inline int CompareTo(const char* psz, caseCompare cmp = exact) const
-  { return cmp == exact ? Cmp(psz) : CmpNoCase(psz); }
+    { return cmp == exact ? Cmp(psz) : CmpNoCase(psz); }
 
     /// same as Mid (substring extraction)
-  inline wxString  operator()(size_t start, size_t len) const { return Mid(start, len); }
+  inline wxString  operator()(size_t start, size_t len) const
+    { return Mid(start, len); }
 
     /// same as += or <<
   inline wxString& Append(const char* psz) { return *this << psz; }
-  inline wxString& Append(char ch, int count = 1) { wxString str(ch, count); (*this) += str; return *this; }
+  inline wxString& Append(char ch, int count = 1)
+    { wxString str(ch, count); (*this) += str; return *this; }
 
     ///
-  wxString& Prepend(const wxString& str) { *this = str + *this; return *this; }
+  wxString& Prepend(const wxString& str)
+    { *this = str + *this; return *this; }
     /// same as Len
   size_t Length() const { return Len(); }
     /// same as MakeLower
@@ -405,17 +533,13 @@ public:
   wxString& Remove(size_t pos) { return Truncate(pos); }
   wxString& RemoveLast() { return Truncate(Len() - 1); }
 
-  // Robert Roebling
-  
   wxString& Remove(size_t nStart, size_t nLen) { return erase( nStart, nLen ); }
-  
-  size_t First( const char ch ) const { return find(ch); }
-  size_t First( const char* psz ) const { return find(psz); }
-  size_t First( const wxString &str ) const { return find(str); }
 
-  size_t Last( const char ch ) const { return rfind(ch,0); }
-  size_t Last( const char* psz ) const { return rfind(psz,0); }
-  size_t Last( const wxString &str ) const { return rfind(str,0); }
+  int First( const char ch ) const { return Find(ch); }
+  int First( const char* psz ) const { return Find(psz); }
+  int First( const wxString &str ) const { return Find(str); }
+
+  int Last( const char ch ) const { return Find(ch, TRUE); }
 
     /// same as IsEmpty
   bool IsNull() const { return IsEmpty(); }
@@ -423,15 +547,19 @@ public:
 
 #ifdef  STD_STRING_COMPATIBILITY
   /** @name std::string compatibility functions */
-  
+
   /// an 'invalid' value for string index
   static const size_t npos;
-        
+
   //@{
     /** @name constructors */
     //@{
       /// take nLen chars starting at nPos
-      wxString(const wxString& s, size_t nPos, size_t nLen = npos);
+      wxString(const wxString& str, size_t nPos, size_t nLen = npos)
+      {
+        wxASSERT( str.GetStringData()->IsValid() );
+        InitWith(str.c_str(), nPos, nLen == npos ? 0 : nLen);
+      }
       /// take all characters from pStart to pEnd
       wxString(const void *pStart, const void *pEnd);
     //@}
@@ -442,7 +570,7 @@ public:
       /// return the length of the string
       size_t length() const { return Len(); }
       /// return the maximum size of the string
-      size_t max_size() const { return STRING_MAXLEN; } 
+      size_t max_size() const { return STRING_MAXLEN; }
       /// resize the string, filling the space with c if c != 0
       void resize(size_t nSize, char ch = '\0');
       /// delete the contents of the string
@@ -462,58 +590,58 @@ public:
       /** @name append something to the end of this one */
       //@{
         /// append a string
-        wxString& append(const wxString& str) 
+        wxString& append(const wxString& str)
           { *this += str; return *this; }
         /// append elements str[pos], ..., str[pos+n]
-        wxString& append(const wxString& str, size_t pos, size_t n) 
+        wxString& append(const wxString& str, size_t pos, size_t n)
           { ConcatSelf(n, str.c_str() + pos); return *this; }
         /// append first n (or all if n == npos) characters of sz
-        wxString& append(const char *sz, size_t n = npos) 
+        wxString& append(const char *sz, size_t n = npos)
           { ConcatSelf(n == npos ? Strlen(sz) : n, sz); return *this; }
 
         /// append n copies of ch
         wxString& append(size_t n, char ch) { return Pad(n, ch); }
       //@}
-        
+
       /** @name replaces the contents of this string with another one */
       //@{
         /// same as `this_string = str'
         wxString& assign(const wxString& str) { return (*this) = str; }
         /// same as ` = str[pos..pos + n]
-        wxString& assign(const wxString& str, size_t pos, size_t n) 
+        wxString& assign(const wxString& str, size_t pos, size_t n)
           { return *this = wxString((const char *)str + pos, n); }
         /// same as `= first n (or all if n == npos) characters of sz'
-        wxString& assign(const char *sz, size_t n = npos) 
+        wxString& assign(const char *sz, size_t n = npos)
           { return *this = wxString(sz, n); }
         /// same as `= n copies of ch'
-        wxString& assign(size_t n, char ch) 
+        wxString& assign(size_t n, char ch)
           { return *this = wxString(ch, n); }
 
       //@}
-        
-      /** @name inserts something at position nPos into this one */  
+
+      /** @name inserts something at position nPos into this one */
       //@{
         /// insert another string
         wxString& insert(size_t nPos, const wxString& str);
         /// insert n chars of str starting at nStart (in str)
         wxString& insert(size_t nPos, const wxString& str, size_t nStart, size_t n)
-                   { return insert(nPos, wxString((const char *)str + nStart, n)); }
+          { return insert(nPos, wxString((const char *)str + nStart, n)); }
 
         /// insert first n (or all if n == npos) characters of sz
         wxString& insert(size_t nPos, const char *sz, size_t n = npos)
           { return insert(nPos, wxString(sz, n)); }
         /// insert n copies of ch
-        wxString& insert(size_t nPos, size_t n, char ch) 
+        wxString& insert(size_t nPos, size_t n, char ch)
           { return insert(nPos, wxString(ch, n)); }
 
       //@}
-      
+
       /** @name deletes a part of the string */
       //@{
         /// delete characters from nStart to nStart + nLen
         wxString& erase(size_t nStart = 0, size_t nLen = npos);
       //@}
-      
+
       /** @name replaces a substring of this string with another one */
       //@{
          /// replaces the substring of length nLen starting at nStart
@@ -521,14 +649,14 @@ public:
          /// replaces the substring with nCount copies of ch
          wxString& replace(size_t nStart, size_t nLen, size_t nCount, char ch);
          /// replaces a substring with another substring
-         wxString& replace(size_t nStart, size_t nLen, 
+         wxString& replace(size_t nStart, size_t nLen,
                          const wxString& str, size_t nStart2, size_t nLen2);
          /// replaces the substring with first nCount chars of sz
-         wxString& replace(size_t nStart, size_t nLen, 
+         wxString& replace(size_t nStart, size_t nLen,
                          const char* sz, size_t nCount);
       //@}
     //@}
-         
+
     /// swap two strings
     void swap(wxString& str);
 
@@ -536,14 +664,14 @@ public:
     //@{
       /** All find() functions take the nStart argument which specifies
           the position to start the search on, the default value is 0.
-          
+
           All functions return npos if there were no match.
-          
-          @name string search 
+
+          @name string search
       */
       //@{
         /**
-            @name find a match for the string/character in this string 
+            @name find a match for the string/character in this string
         */
         //@{
           /// find a substring
@@ -557,12 +685,12 @@ public:
           /// find the first occurence of character ch after nStart
           size_t find(char ch, size_t nStart = 0) const;
 
-                 // wxWin compatibility
-                 inline bool Contains(const wxString& str) { return (Find(str) != -1); }
+          // wxWin compatibility
+          inline bool Contains(const wxString& str) const { return Find(str) != -1; }
 
         //@}
-        
-        /** 
+
+        /**
           @name rfind() family is exactly like find() but works right to left
         */
         //@{
@@ -571,13 +699,13 @@ public:
         /// as find, but from the end
         // VC++ 1.5 can't cope with this syntax.
 #if ! (defined(_MSC_VER) && !defined(__WIN32__))
-        size_t rfind(const char* sz, size_t nStart = npos, 
+        size_t rfind(const char* sz, size_t nStart = npos,
                      size_t n = npos) const;
         /// as find, but from the end
         size_t rfind(char ch, size_t nStart = npos) const;
 #endif
         //@}
-        
+
         /**
           @name find first/last occurence of any character in the set
         */
@@ -588,7 +716,7 @@ public:
           size_t find_first_of(const char* sz, size_t nStart = 0) const;
           /// same as find(char, size_t)
           size_t find_first_of(char c, size_t nStart = 0) const;
-          
+
           ///
           size_t find_last_of (const wxString& str, size_t nStart = npos) const;
           ///
@@ -596,7 +724,7 @@ public:
           /// same as rfind(char, size_t)
           size_t find_last_of (char c, size_t nStart = npos) const;
         //@}
-        
+
         /**
           @name find first/last occurence of any character not in the set
         */
@@ -607,7 +735,7 @@ public:
           size_t find_first_not_of(const char* s, size_t nStart = 0) const;
           ///
           size_t find_first_not_of(char ch, size_t nStart = 0) const;
-          
+
           ///
           size_t find_last_not_of(const wxString& str, size_t nStart=npos) const;
           ///
@@ -616,63 +744,30 @@ public:
           size_t find_last_not_of(char ch, size_t nStart = npos) const;
         //@}
       //@}
-      
-      /** 
-        All compare functions return -1, 0 or 1 if the [sub]string 
+
+      /**
+        All compare functions return -1, 0 or 1 if the [sub]string
         is less, equal or greater than the compare() argument.
-        
+
         @name comparison
       */
       //@{
         /// just like strcmp()
         int compare(const wxString& str) const { return Cmp(str); }
-        /// comparaison with a substring
+        /// comparison with a substring
         int compare(size_t nStart, size_t nLen, const wxString& str) const;
-        /// comparaison of 2 substrings
+        /// comparison of 2 substrings
         int compare(size_t nStart, size_t nLen,
                     const wxString& str, size_t nStart2, size_t nLen2) const;
         /// just like strcmp()
         int compare(const char* sz) const { return Cmp(sz); }
-        /// substring comparaison with first nCount characters of sz
+        /// substring comparison with first nCount characters of sz
         int compare(size_t nStart, size_t nLen,
                     const char* sz, size_t nCount = npos) const;
       //@}
     wxString substr(size_t nStart = 0, size_t nLen = npos) const;
   //@}
 #endif
-    
-protected:
-  // points to data preceded by wxStringData structure with ref count info
-  char *m_pchData;
-
-  // accessor to string data
-  wxStringData* GetStringData() const { return (wxStringData*)m_pchData - 1; }
-
-  // string (re)initialization functions
-    // initializes the string to the empty value (must be called only from
-    // ctors, use Reinit() otherwise)
-  void Init() { m_pchData = (char *)g_szNul; }
-    // initializaes the string with (a part of) C-string
-  void InitWith(const char *psz, size_t nPos = 0, size_t nLen = STRING_MAXLEN);
-    // as Init, but also frees old data
-  inline void Reinit(); 
-
-  // memory allocation
-    // allocates memory for string of lenght nLen
-  void AllocBuffer(size_t nLen);
-    // copies data to another string
-  void AllocCopy(wxString&, int, int) const;
-    // effectively copies data to string
-  void AssignCopy(size_t, const char *);
-  
-  // append a (sub)string
-  void ConcatCopy(int nLen1, const char *src1, int nLen2, const char *src2);
-  void ConcatSelf(int nLen, const char *src);
-
-  // functions called before writing to the string: they copy it if there 
-  // other references (should be the only owner when writing)
-  void CopyBeforeWrite();
-  void AllocBeforeWrite(size_t);
 };
 
 // ----------------------------------------------------------------------------
@@ -682,7 +777,7 @@ protected:
     sizeof(char *)) we store these pointers instead. The cast to "String *"
     is really all we need to turn such pointer into a string!
 
-    Of course, it can be called a dirty hack, but we use twice less memory 
+    Of course, it can be called a dirty hack, but we use twice less memory
     and this approach is also more speed efficient, so it's probably worth it.
 
     Usage notes: when a string is added/inserted, a new copy of it is created,
@@ -693,7 +788,7 @@ protected:
     @memo probably the most commonly used array type - array of strings
  */
 // ----------------------------------------------------------------------------
-class wxArrayString
+class WXDLLEXPORT wxArrayString
 {
 public:
   /** @name ctors and dtor */
@@ -716,12 +811,14 @@ public:
   void Clear();
     /// preallocates memory for given number of items
   void Alloc(size_t nCount);
+    /// minimzes the memory usage (by freeing all extra memory)
+  void Shrink();
   //@}
 
   /** @name simple accessors */
   //@{
     /// number of elements in the array
-  uint  Count() const   { return m_nCount;      }
+  size_t  Count() const   { return m_nCount;      }
     /// is it empty?
   bool  IsEmpty() const { return m_nCount == 0; }
   //@}
@@ -742,7 +839,7 @@ public:
     /**
       Search the element in the array, starting from the either side
       @param if bFromEnd reverse search direction
-      @param if bCase, comparaison is case sensitive (default)
+      @param if bCase, comparison is case sensitive (default)
       @return index of the first item matched or NOT_FOUND
       @see NOT_FOUND
      */
@@ -750,7 +847,7 @@ public:
     /// add new element at the end
   void Add   (const wxString& str);
     /// add new element at given position
-  void Insert(const wxString& str, uint uiIndex);
+  void Insert(const wxString& str, size_t uiIndex);
     /// remove first item matching this value
   void Remove(const char *sz);
     /// remove item by index
@@ -764,21 +861,15 @@ private:
   void    Grow();     // makes array bigger if needed
   void    Free();     // free the string stored
 
-  size_t  m_nSize,    // current size of the array
+  size_t    m_nSize,    // current size of the array
           m_nCount;   // current number of elements
 
   char  **m_pItems;   // pointer to data
 };
 
 // ---------------------------------------------------------------------------
-// implementation of inline functions
-// ---------------------------------------------------------------------------
-
-// Put back into class, since BC++ can't create precompiled header otherwise
-
-// ---------------------------------------------------------------------------
-/** @name wxString comparaison functions 
-    @memo Comparaisons are case sensitive
+/** @name wxString comparison functions
+    @memo Comparisons are case sensitive
  */
 // ---------------------------------------------------------------------------
 //@{
@@ -818,9 +909,14 @@ inline bool operator>=(const wxString& s1, const char  * s2) { return s1.Cmp(s2)
 ///
 inline bool operator>=(const char  * s1, const wxString& s2) { return s2.Cmp(s1) <= 0; }
 //@}
-    
+wxString WXDLLEXPORT operator+(const wxString& string1,  const wxString& string2);
+wxString WXDLLEXPORT operator+(const wxString& string, char ch);
+wxString WXDLLEXPORT operator+(char ch, const wxString& string);
+wxString WXDLLEXPORT operator+(const wxString& string, const char *psz);
+wxString WXDLLEXPORT operator+(const char *psz, const wxString& string);
+
 // ---------------------------------------------------------------------------
-/** @name Global functions complementing standard C string library 
+/** @name Global functions complementing standard C string library
     @memo replacements for strlen() and portable strcasecmp()
  */
 // ---------------------------------------------------------------------------
@@ -828,12 +924,23 @@ inline bool operator>=(const char  * s1, const wxString& s2) { return s2.Cmp(s1)
 #ifdef  STD_STRING_COMPATIBILITY
 
 // fwd decl
-class WXDLLEXPORT istream;
+// Known not to work with wxUSE_IOSTREAMH set to 0, so
+// replacing with includes (on advice of ungod@pasdex.com.au)
+// class WXDLLEXPORT istream;
+#if wxUSE_IOSTREAMH
+// N.B. BC++ doesn't have istream.h, ostream.h
+#include <iostream.h>
+#else
+#include <istream>
+#  ifdef _MSC_VER
+      using namespace std;
+#  endif
+#endif
 
 istream& WXDLLEXPORT operator>>(istream& is, wxString& str);
 
 #endif  //std::string compatibility
 
-#endif  // __WXSTRINGH__
+#endif  // _WX_WXSTRINGH__
 
 //@}