size_t Len() const { return GetStringData()->nDataLength; }
     /// string contains any characters?
   bool IsEmpty() const { return Len() == 0; }
-    /// reinitialize string (and free memory)
+    /// empty string contents
   void Empty()
   {
     if ( !IsEmpty() )
       Reinit();
 
+    // should be empty
     wxASSERT( GetStringData()->nDataLength == 0 );
-    wxASSERT( GetStringData()->nAllocLength == 0 );
+  }
+    /// empty the string and free memory
+  void Clear()
+  {
+    if ( !GetStringData()->IsEmpty() )
+      Reinit();
+
+    wxASSERT( GetStringData()->nDataLength == 0 );  // should be empty
+    wxASSERT( GetStringData()->nAllocLength == 0 ); // and not own any memory
   }
 
     /// Is an ascii value
     //@}
   //@}
 
+  /** @name stream-like functions */
+  //@{
+        /// insert an int into string
+    wxString& operator<<(int i);
+        /// insert a float into string
+    wxString& operator<<(float f);
+        /// insert a double into string
+    wxString& operator<<(double d);
+  //@}
+  
   /** @name string comparison */
   //@{
     /**
 
   return (psz == NULL) ? NOT_FOUND : psz - m_pchData;
 }
 
+// ---------------------------------------------------------------------------
+// stream-like operators
+// ---------------------------------------------------------------------------
+wxString& wxString::operator<<(int i)
+{
+    wxString res;
+    res.Printf("%d", i);
+
+    return (*this) << res;
+}
+
+wxString& wxString::operator<<(float f)
+{
+    wxString res;
+    res.Printf("%f", f);
+
+    return (*this) << res;
+}
+
+wxString& wxString::operator<<(double d)
+{
+    wxString res;
+    res.Printf("%g", d);
+
+    return (*this) << res;
+}
+
 // ---------------------------------------------------------------------------
 // formatted output
 // ---------------------------------------------------------------------------
 
 int wxString::PrintfV(const char* pszFormat, va_list argptr)
 {
+#ifdef __WXMSW__
+  #ifdef _MSC_VER
+    #define wxVsprintf     _vsnprintf
+  #endif
+#else // guess that any Unix has snprintf() - feel free to insert additional
+      // platform/compiler tests here if this is not the case for you
+  #define wxVsprintf       vsnprintf
+#endif
+  
+#ifndef wxVsprintf
+  #pragma message("Using sprintf() because no snprintf()-like function defined")
+  #define wxVsprintf vsprintf
+#endif
+
+  // static buffer to avoid dynamic memory allocation each time
   static char s_szScratch[1024];
 
-  int iLen = vsprintf(s_szScratch, pszFormat, argptr);
+  int iLen = wxVsprintf(s_szScratch, WXSIZEOF(s_szScratch), pszFormat, argptr);
+  char *buffer;
+  if ( (size_t)iLen < WXSIZEOF(s_szScratch) ) {
+    buffer = s_szScratch;
+  }
+  else {
+      int size = WXSIZEOF(s_szScratch) * 2;
+      buffer = (char *)malloc(size);
+      while ( buffer != NULL ) {
+          iLen = wxVsprintf(buffer, WXSIZEOF(s_szScratch), pszFormat, argptr);
+          if ( iLen < size ) {
+              // ok, there was enough space
+              break;
+          }
+
+          // still not enough, double it again
+          buffer = (char *)realloc(buffer, size *= 2);
+      }
+
+      if ( !buffer ) {
+          // out of memory
+          return -1;
+      }
+  }
+
   AllocBeforeWrite(iLen);
-  strcpy(m_pchData, s_szScratch);
+  strcpy(m_pchData, buffer);
+
+  if ( buffer != s_szScratch )
+      free(buffer);
 
   return iLen;
 }