diff options
| author | George Hazan <george.hazan@gmail.com> | 2013-10-11 12:15:06 +0000 | 
|---|---|---|
| committer | George Hazan <george.hazan@gmail.com> | 2013-10-11 12:15:06 +0000 | 
| commit | 3fc8b6f686262e8a595fc10b2bd947526ca77bdc (patch) | |
| tree | 4175381d8009ec701a731a1611255e0daf3b65dd | |
| parent | e9df5cb26041817f3d06c7887ba534273dd0d99d (diff) | |
CMStringT::Format to return its buffer back
git-svn-id: http://svn.miranda-ng.org/main/trunk@6434 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
| -rw-r--r-- | include/m_string.h | 2033 | ||||
| -rw-r--r-- | protocols/MRA/src/Mra_proto.cpp | 4 | 
2 files changed, 1013 insertions, 1024 deletions
diff --git a/include/m_string.h b/include/m_string.h index fe7cf06edc..ae5e245916 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -1059,1190 +1059,1181 @@ public:  	  {
  	  }
 -	  static void __stdcall Construct(CMStringT* pString)
 -	  {
 -		  new(pString) CMStringT;
 -	  }
 +	static void __stdcall Construct(CMStringT* pString)
 +	{
 +		new(pString) CMStringT;
 +	}
 -	  // Copy constructor
 -	  CMStringT(const CMStringT& strSrc) :
 -	  CThisSimpleString(strSrc)
 -	  {
 -	  }
 +	// Copy constructor
 +	CMStringT(const CMStringT& strSrc) :
 +		CThisSimpleString(strSrc)
 +	{
 +	}
 -	  CMStringT(const XCHAR* pszSrc) :
 -	  CThisSimpleString()
 -	  {
 -		  // nDestLength is in XCHARs
 -		  *this = pszSrc;
 -	  }
 +	CMStringT(const XCHAR* pszSrc) :
 +		CThisSimpleString()
 +	{
 +		// nDestLength is in XCHARs
 +		*this = pszSrc;
 +	}
 -	  CMStringT(const YCHAR* pszSrc) :
 -	  CThisSimpleString()
 -	  {
 -		  *this = pszSrc;
 -	  }
 +	CMStringT(const YCHAR* pszSrc) :
 +		CThisSimpleString()
 +	{
 +		*this = pszSrc;
 +	}
 -	  CMStringT(const unsigned char* pszSrc) :
 -	  CThisSimpleString()
 -	  {
 -		  *this = reinterpret_cast< const char* >(pszSrc);
 -	  }
 +	CMStringT(const unsigned char* pszSrc) :
 +		CThisSimpleString()
 +	{
 +		*this = reinterpret_cast< const char* >(pszSrc);
 +	}
 -	  CMStringT(char ch, int nLength = 1) :
 -	  CThisSimpleString()
 -	  {
 -		  if (nLength > 0)
 -		  {
 -			  PXSTR pszBuffer = this->GetBuffer(nLength);
 -			  StringTraits::FloodCharacters(XCHAR(ch), nLength, pszBuffer);
 -			  this->ReleaseBufferSetLength(nLength);
 -		  }
 -	  }
 +	CMStringT(char ch, int nLength = 1) :
 +		CThisSimpleString()
 +	{
 +		if (nLength > 0)
 +		{
 +			PXSTR pszBuffer = this->GetBuffer(nLength);
 +			StringTraits::FloodCharacters(XCHAR(ch), nLength, pszBuffer);
 +			this->ReleaseBufferSetLength(nLength);
 +		}
 +	}
 -	  CMStringT(wchar_t ch, int nLength = 1) :
 -	  CThisSimpleString()
 -	  {
 -		  if (nLength > 0)
 -		  {			
 -			  //Convert ch to the BaseType
 -			  wchar_t pszCh[2] = { ch , 0 };
 -			  int nBaseTypeCharLen = 1;
 -
 -			  if (ch != L'\0')
 -			  {
 -				  nBaseTypeCharLen = StringTraits::GetBaseTypeLength(pszCh);
 -			  }
 -
 -			  XCHAR *buffBaseTypeChar = new XCHAR[nBaseTypeCharLen+1];
 -			  StringTraits::ConvertToBaseType(buffBaseTypeChar, nBaseTypeCharLen+1, pszCh, 1);
 -			  //allocate enough characters in String and flood (replicate) with the (converted character)*nLength
 -			  PXSTR pszBuffer = this->GetBuffer(nLength*nBaseTypeCharLen);
 -			  if (nBaseTypeCharLen == 1)
 -			  {   //Optimization for a common case - wide char translates to 1 ansi/wide char.
 -				  StringTraits::FloodCharacters(buffBaseTypeChar[0], nLength, pszBuffer);				
 -			  } else
 -			  {
 -				  XCHAR* p=pszBuffer;
 -				  for (int i=0 ; i < nLength ;i++)
 -				  {
 -					  for (int j=0 ; j < nBaseTypeCharLen ;++j)
 -					  {	
 -						  *p=buffBaseTypeChar[j];
 -						  ++p;
 -					  }
 -				  }
 -			  }
 -			  this->ReleaseBufferSetLength(nLength*nBaseTypeCharLen);
 -			  delete [] buffBaseTypeChar;
 -		  }
 -	  }
 +	CMStringT(wchar_t ch, int nLength = 1) :
 +		CThisSimpleString()
 +	{
 +		if (nLength > 0)
 +		{			
 +			//Convert ch to the BaseType
 +			wchar_t pszCh[2] = { ch , 0 };
 +			int nBaseTypeCharLen = 1;
 -	  CMStringT(const XCHAR* pch, int nLength) :
 -	  CThisSimpleString(pch, nLength)
 -	  {
 -	  }
 +			if (ch != L'\0')
 +			{
 +				nBaseTypeCharLen = StringTraits::GetBaseTypeLength(pszCh);
 +			}
 -	  CMStringT(const YCHAR* pch, int nLength) :
 -	  CThisSimpleString()
 -	  {
 -		  if (nLength > 0)
 -		  {
 -			  int nDestLength = StringTraits::GetBaseTypeLength(pch, nLength);
 -			  PXSTR pszBuffer = this->GetBuffer(nDestLength);
 -			  StringTraits::ConvertToBaseType(pszBuffer, nDestLength, pch, nLength);
 -			  this->ReleaseBufferSetLength(nDestLength);
 -		  }
 -	  }
 +			XCHAR *buffBaseTypeChar = new XCHAR[nBaseTypeCharLen+1];
 +			StringTraits::ConvertToBaseType(buffBaseTypeChar, nBaseTypeCharLen+1, pszCh, 1);
 +			//allocate enough characters in String and flood (replicate) with the (converted character)*nLength
 +			PXSTR pszBuffer = this->GetBuffer(nLength*nBaseTypeCharLen);
 +			if (nBaseTypeCharLen == 1)
 +			{   //Optimization for a common case - wide char translates to 1 ansi/wide char.
 +				StringTraits::FloodCharacters(buffBaseTypeChar[0], nLength, pszBuffer);				
 +			} else
 +			{
 +				XCHAR* p=pszBuffer;
 +				for (int i=0 ; i < nLength ;i++)
 +				{
 +					for (int j=0 ; j < nBaseTypeCharLen ;++j)
 +					{	
 +						*p=buffBaseTypeChar[j];
 +						++p;
 +					}
 +				}
 +			}
 +			this->ReleaseBufferSetLength(nLength*nBaseTypeCharLen);
 +			delete [] buffBaseTypeChar;
 +		}
 +	}
 -	  // Destructor
 -	  ~CMStringT()
 -	  {
 -	  }
 +	CMStringT(const XCHAR* pch, int nLength) :
 +		CThisSimpleString(pch, nLength)
 +	{
 +	}
 -	  // Assignment operators
 -	  CMStringT& operator=(const CMStringT& strSrc)
 -	  {
 -		  CThisSimpleString::operator=(strSrc);
 +	CMStringT(const YCHAR* pch, int nLength) :
 +		CThisSimpleString()
 +	{
 +		if (nLength > 0)
 +		{
 +			int nDestLength = StringTraits::GetBaseTypeLength(pch, nLength);
 +			PXSTR pszBuffer = this->GetBuffer(nDestLength);
 +			StringTraits::ConvertToBaseType(pszBuffer, nDestLength, pch, nLength);
 +			this->ReleaseBufferSetLength(nDestLength);
 +		}
 +	}
 -		  return *this;
 -	  }
 +	// Destructor
 +	~CMStringT()
 +	{
 +	}
 -	  CMStringT& operator=(PCXSTR pszSrc)
 -	  {
 -		  CThisSimpleString::operator=(pszSrc);
 +	// Assignment operators
 +	CMStringT& operator=(const CMStringT& strSrc)
 +	{
 +		CThisSimpleString::operator=(strSrc);
 -		  return *this;
 -	  }
 +		return *this;
 +	}
 -	  CMStringT& operator=(PCYSTR pszSrc)
 -	  {
 -		  // nDestLength is in XCHARs
 -		  int nDestLength = (pszSrc != NULL) ? StringTraits::GetBaseTypeLength(pszSrc) : 0;
 -		  if (nDestLength > 0)
 -		  {
 -			  PXSTR pszBuffer = this->GetBuffer(nDestLength);
 -			  StringTraits::ConvertToBaseType(pszBuffer, nDestLength, pszSrc);
 -			  this->ReleaseBufferSetLength(nDestLength);
 -		  }
 -		  else
 -		  {
 -			  this->Empty();
 -		  }
 -
 -		  return *this;
 -	  }
 +	CMStringT& operator=(PCXSTR pszSrc)
 +	{
 +		CThisSimpleString::operator=(pszSrc);
 -	  CMStringT& operator=(const unsigned char* pszSrc)
 -	  {
 -		  return operator=(reinterpret_cast< const char* >(pszSrc));
 -	  }
 +		return *this;
 +	}
 -	  CMStringT& operator=(char ch)
 -	  {
 -		  char ach[2] = { ch, 0 };
 +	CMStringT& operator=(PCYSTR pszSrc)
 +	{
 +		// nDestLength is in XCHARs
 +		int nDestLength = (pszSrc != NULL) ? StringTraits::GetBaseTypeLength(pszSrc) : 0;
 +		if (nDestLength > 0)
 +		{
 +			PXSTR pszBuffer = this->GetBuffer(nDestLength);
 +			StringTraits::ConvertToBaseType(pszBuffer, nDestLength, pszSrc);
 +			this->ReleaseBufferSetLength(nDestLength);
 +		}
 +		else
 +		{
 +			this->Empty();
 +		}
 -		  return operator=(ach);
 -	  }
 +		return *this;
 +	}
 -	  CMStringT& operator=(wchar_t ch)
 -	  {
 -		  wchar_t ach[2] = { ch, 0 };
 +	CMStringT& operator=(const unsigned char* pszSrc)
 +	{
 +		return operator=(reinterpret_cast< const char* >(pszSrc));
 +	}
 -		  return operator=(ach);
 -	  }
 +	CMStringT& operator=(char ch)
 +	{
 +		char ach[2] = { ch, 0 };
 -//	  CMStringT& operator=(const VARIANT& var);
 +		return operator=(ach);
 +	}
 -	  CMStringT& operator+=(const CMStringT& str)
 -	  {
 -		  CThisSimpleString::operator+=(str);
 -		  return *this;
 -	  }
 +	CMStringT& operator=(wchar_t ch)
 +	{
 +		wchar_t ach[2] = { ch, 0 };
 -	  CMStringT& operator+=(const CThisSimpleString& str)
 -	  {
 -		  CThisSimpleString::operator+=(str);
 -		  return *this;
 -	  }
 +		return operator=(ach);
 +	}
 -	  CMStringT& operator+=(PCXSTR pszSrc)
 -	  {
 -		  CThisSimpleString::operator+=(pszSrc);
 -		  return *this;
 -	  }
 -//	  template< int t_nSize >
 -//	  CMStringT& operator+=(const CStaticString< XCHAR, t_nSize >& strSrc)
 -//	  {
 -//		  CThisSimpleString::operator+=(strSrc);
 -//
 -//		  return *this;
 -//	  }
 -	  CMStringT& operator+=(PCYSTR pszSrc)
 -	  {
 -		  CMStringT str(pszSrc);
 +	//	  CMStringT& operator=(const VARIANT& var);
 -		  return operator+=(str);
 -	  }
 +	CMStringT& operator+=(const CMStringT& str)
 +	{
 +		CThisSimpleString::operator+=(str);
 +		return *this;
 +	}
 -	  CMStringT& operator+=(char ch)
 -	  {
 -		  CThisSimpleString::operator+=(ch);
 +	CMStringT& operator+=(const CThisSimpleString& str)
 +	{
 +		CThisSimpleString::operator+=(str);
 +		return *this;
 +	}
 -		  return *this;
 -	  }
 +	CMStringT& operator+=(PCXSTR pszSrc)
 +	{
 +		CThisSimpleString::operator+=(pszSrc);
 +		return *this;
 +	}
 +	//	  template< int t_nSize >
 +	//	  CMStringT& operator+=(const CStaticString< XCHAR, t_nSize >& strSrc)
 +	//	  {
 +	//		  CThisSimpleString::operator+=(strSrc);
 +	//
 +	//		  return *this;
 +	//	  }
 +	CMStringT& operator+=(PCYSTR pszSrc)
 +	{
 +		CMStringT str(pszSrc);
 -	  CMStringT& operator+=(unsigned char ch)
 -	  {
 -		  CThisSimpleString::operator+=(ch);
 +		return operator+=(str);
 +	}
 -		  return *this;
 -	  }
 +	CMStringT& operator+=(char ch)
 +	{
 +		CThisSimpleString::operator+=(ch);
 -	  CMStringT& operator+=(wchar_t ch)
 -	  {
 -		  CThisSimpleString::operator+=(ch);
 +		return *this;
 +	}
 -		  return *this;
 -	  }
 +	CMStringT& operator+=(unsigned char ch)
 +	{
 +		CThisSimpleString::operator+=(ch);
 -	  // Comparison
 +		return *this;
 +	}
 -	  int Compare(PCXSTR psz) const
 -	  {
 -		  return StringTraits::StringCompare(this->GetString(), psz);
 -	  }
 +	CMStringT& operator+=(wchar_t ch)
 +	{
 +		CThisSimpleString::operator+=(ch);
 -	  int CompareNoCase(PCXSTR psz) const
 -	  {
 -		  return StringTraits::StringCompareIgnore(this->GetString(), psz);
 -	  }
 +		return *this;
 +	}
 -	  int Collate(PCXSTR psz) const
 -	  {
 -		  return StringTraits::StringCollate(this->GetString(), psz);
 -	  }
 +	// Comparison
 -	  int CollateNoCase(PCXSTR psz) const
 -	  {
 -		  return StringTraits::StringCollateIgnore(this->GetString(), psz);
 -	  }
 +	int Compare(PCXSTR psz) const
 +	{
 +		return StringTraits::StringCompare(this->GetString(), psz);
 +	}
 -	  // Advanced manipulation
 +	int CompareNoCase(PCXSTR psz) const
 +	{
 +		return StringTraits::StringCompareIgnore(this->GetString(), psz);
 +	}
 -	  // Delete 'nCount' characters, starting at index 'iIndex'
 -	  int Delete(int iIndex, int nCount = 1)
 -	  {
 -		  if (iIndex < 0)
 -			  iIndex = 0;
 -
 -		  if (nCount < 0)
 -			  nCount = 0;
 -
 -		  int nLength = this->GetLength();
 -		  if (nCount + iIndex > nLength)
 -		  {
 -			  nCount = nLength-iIndex;
 -		  }
 -		  if (nCount > 0)
 -		  {
 -			  int nNewLength = nLength-nCount;
 -			  int nXCHARsToCopy = nLength-(iIndex+nCount)+1;
 -			  PXSTR pszBuffer = this->GetBuffer();
 -				#if _MSC_VER >= 1400
 -				  memmove_s(pszBuffer+iIndex, nXCHARsToCopy*sizeof(XCHAR), pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof(XCHAR));
 -				#else
 -				  memmove(pszBuffer+iIndex, pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof(XCHAR));
 -				#endif
 -			  this->ReleaseBufferSetLength(nNewLength);
 -		  }
 -
 -		  return this->GetLength();
 -	  }
 +	int Collate(PCXSTR psz) const
 +	{
 +		return StringTraits::StringCollate(this->GetString(), psz);
 +	}
 -	  // Insert character 'ch' before index 'iIndex'
 -	  int Insert(int iIndex, XCHAR ch)
 -	  {
 -		  if (iIndex < 0)
 -			  iIndex = 0;
 +	int CollateNoCase(PCXSTR psz) const
 +	{
 +		return StringTraits::StringCollateIgnore(this->GetString(), psz);
 +	}
 +
 +	// Advanced manipulation
 +
 +	// Delete 'nCount' characters, starting at index 'iIndex'
 +	int Delete(int iIndex, int nCount = 1)
 +	{
 +		if (iIndex < 0)
 +			iIndex = 0;
 +
 +		if (nCount < 0)
 +			nCount = 0;
 +
 +		int nLength = this->GetLength();
 +		if (nCount + iIndex > nLength)
 +		{
 +			nCount = nLength-iIndex;
 +		}
 +		if (nCount > 0)
 +		{
 +			int nNewLength = nLength-nCount;
 +			int nXCHARsToCopy = nLength-(iIndex+nCount)+1;
 +			PXSTR pszBuffer = this->GetBuffer();
 +#if _MSC_VER >= 1400
 +			memmove_s(pszBuffer+iIndex, nXCHARsToCopy*sizeof(XCHAR), pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof(XCHAR));
 +#else
 +			memmove(pszBuffer+iIndex, pszBuffer+iIndex+nCount, nXCHARsToCopy*sizeof(XCHAR));
 +#endif
 +			this->ReleaseBufferSetLength(nNewLength);
 +		}
 +
 +		return this->GetLength();
 +	}
 +
 +	// Insert character 'ch' before index 'iIndex'
 +	int Insert(int iIndex, XCHAR ch)
 +	{
 +		if (iIndex < 0)
 +			iIndex = 0;
 +
 +		if (iIndex > this->GetLength())
 +			iIndex = this->GetLength();
 +
 +		int nNewLength = this->GetLength()+1;
 +
 +		PXSTR pszBuffer = this->GetBuffer(nNewLength);
 +
 +		// move existing bytes down 
 +#if _MSC_VER >= 1400
 +		memmove_s(pszBuffer+iIndex+1, (nNewLength-iIndex)*sizeof(XCHAR), pszBuffer+iIndex, (nNewLength-iIndex)*sizeof(XCHAR));
 +#else
 +		memmove(pszBuffer+iIndex+1, pszBuffer+iIndex, (nNewLength-iIndex)*sizeof(XCHAR));
 +#endif
 +		pszBuffer[iIndex] = ch;
 +
 +		this->ReleaseBufferSetLength(nNewLength);
 +		return nNewLength;
 +	}
 +
 +	// Insert string 'psz' before index 'iIndex'
 +	int Insert(int iIndex, PCXSTR psz)
 +	{
 +		if (iIndex < 0)
 +			iIndex = 0;
 -			if (iIndex > this->GetLength())
 -				iIndex = this->GetLength();
 +		if (iIndex > this->GetLength())
 +		{
 +			iIndex = this->GetLength();
 +		}
 -			int nNewLength = this->GetLength()+1;
 +		// nInsertLength and nNewLength are in XCHARs
 +		int nInsertLength = StringTraits::SafeStringLen(psz);
 +		int nNewLength = this->GetLength();
 +		if (nInsertLength > 0)
 +		{
 +			nNewLength += nInsertLength;
  			PXSTR pszBuffer = this->GetBuffer(nNewLength);
 +			// move existing bytes down 
 +#if _MSC_VER >= 1400
 +			memmove_s(pszBuffer+iIndex+nInsertLength, (nNewLength-iIndex-nInsertLength+1)*sizeof(XCHAR), pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof(XCHAR));
 +			memcpy_s(pszBuffer+iIndex, nInsertLength*sizeof(XCHAR), psz, nInsertLength*sizeof(XCHAR));
 +#else
 +			memmove(pszBuffer+iIndex+nInsertLength, pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof(XCHAR));
 +			memcpy(pszBuffer+iIndex, psz, nInsertLength*sizeof(XCHAR));
 +#endif
 +			this->ReleaseBufferSetLength(nNewLength);
 +		}
 +
 +		return nNewLength;
 +	}
 +
 +	// Replace all occurrences of character 'chOld' with character 'chNew'
 +	int Replace(XCHAR chOld, XCHAR chNew)
 +	{
 +		int nCount = 0;
 +
 +		// short-circuit the nop case
 +		if (chOld != chNew)
 +		{
 +			// otherwise modify each character that matches in the string
 +			bool bCopied = false;
 +			PXSTR pszBuffer = const_cast< PXSTR >(this->GetString());  // We don't actually write to pszBuffer until we've called GetBuffer().
 +
 +			int nLength = this->GetLength();
 +			int iChar = 0;
 +			while(iChar < nLength)
 +			{
 +				// replace instances of the specified character only
 +				if (pszBuffer[iChar] == chOld)
 +				{
 +					if ( !bCopied)
 +					{
 +						bCopied = true;
 +						pszBuffer = this->GetBuffer(nLength);
 +					}
 +					pszBuffer[iChar] = chNew;
 +					nCount++;
 +				}
 +				iChar = int(StringTraits::CharNext(pszBuffer+iChar)-pszBuffer);
 +			}
 +			if (bCopied)
 +			{
 +				this->ReleaseBufferSetLength(nLength);
 +			}
 +		}
 +
 +		return nCount;
 +	}
 +
 +	// Replace all occurrences of string 'pszOld' with string 'pszNew'
 +	int Replace(PCXSTR pszOld, PCXSTR pszNew)
 +	{
 +		// can't have empty or NULL lpszOld
 -		  // move existing bytes down 
 -			#if _MSC_VER >= 1400
 -				memmove_s(pszBuffer+iIndex+1, (nNewLength-iIndex)*sizeof(XCHAR), pszBuffer+iIndex, (nNewLength-iIndex)*sizeof(XCHAR));
 -			#else
 -				memmove(pszBuffer+iIndex+1, pszBuffer+iIndex, (nNewLength-iIndex)*sizeof(XCHAR));
 -			#endif
 -			pszBuffer[iIndex] = ch;
 +		// nSourceLen is in XCHARs
 +		int nSourceLen = StringTraits::SafeStringLen(pszOld);
 +		if (nSourceLen == 0)
 +			return 0;
 +		// nReplacementLen is in XCHARs
 +		int nReplacementLen = StringTraits::SafeStringLen(pszNew);
 +		// loop once to figure out the size of the result string
 +		int nCount = 0;
 +		{
 +			PCXSTR pszStart = this->GetString();
 +			PCXSTR pszEnd = pszStart+this->GetLength();
 +			while(pszStart < pszEnd)
 +			{
 +				PCXSTR pszTarget;
 +				while((pszTarget = StringTraits::StringFindString(pszStart, pszOld)) != NULL)
 +				{
 +					nCount++;
 +					pszStart = pszTarget+nSourceLen;
 +				}
 +				pszStart += StringTraits::SafeStringLen(pszStart)+1;
 +			}
 +		}
 +
 +		// if any changes were made, make them
 +		if (nCount > 0)
 +		{
 +			// if the buffer is too small, just
 +			//   allocate a new buffer (slow but sure)
 +			int nOldLength = this->GetLength();
 +			int nNewLength = nOldLength+(nReplacementLen-nSourceLen)*nCount;
 +
 +			PXSTR pszBuffer = this->GetBuffer(__max(nNewLength, nOldLength));
 +
 +			PXSTR pszStart = pszBuffer;
 +			PXSTR pszEnd = pszStart+nOldLength;
 +
 +			// loop again to actually do the work
 +			while(pszStart < pszEnd)
 +			{
 +				PXSTR pszTarget;
 +				while((pszTarget = StringTraits::StringFindString(pszStart, pszOld)) != NULL)
 +				{
 +					int nBalance = nOldLength-int(pszTarget-pszBuffer+nSourceLen);
 +					memmove_s(pszTarget+nReplacementLen, nBalance*sizeof(XCHAR), 
 +						pszTarget+nSourceLen, nBalance*sizeof(XCHAR));
 +					memcpy_s(pszTarget, nReplacementLen*sizeof(XCHAR), 
 +						pszNew, nReplacementLen*sizeof(XCHAR));
 +					pszStart = pszTarget+nReplacementLen;
 +					pszTarget[nReplacementLen+nBalance] = 0;
 +					nOldLength += (nReplacementLen-nSourceLen);
 +				}
 +				pszStart += StringTraits::SafeStringLen(pszStart)+1;
 +			}
  			this->ReleaseBufferSetLength(nNewLength);
 -			return nNewLength;
  		}
 -		// Insert string 'psz' before index 'iIndex'
 -		int Insert(int iIndex, PCXSTR psz)
 -	  {
 -		  if (iIndex < 0)
 -			  iIndex = 0;
 -
 -		  if (iIndex > this->GetLength())
 -		  {
 -			  iIndex = this->GetLength();
 -		  }
 -
 -		  // nInsertLength and nNewLength are in XCHARs
 -		  int nInsertLength = StringTraits::SafeStringLen(psz);
 -		  int nNewLength = this->GetLength();
 -		  if (nInsertLength > 0)
 -		  {
 -			  nNewLength += nInsertLength;
 -
 -			  PXSTR pszBuffer = this->GetBuffer(nNewLength);
 -			  // move existing bytes down 
 -				#if _MSC_VER >= 1400
 -					memmove_s(pszBuffer+iIndex+nInsertLength, (nNewLength-iIndex-nInsertLength+1)*sizeof(XCHAR), pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof(XCHAR));
 -					memcpy_s(pszBuffer+iIndex, nInsertLength*sizeof(XCHAR), psz, nInsertLength*sizeof(XCHAR));
 -				#else
 -					memmove(pszBuffer+iIndex+nInsertLength, pszBuffer+iIndex, (nNewLength-iIndex-nInsertLength+1)*sizeof(XCHAR));
 -					memcpy(pszBuffer+iIndex, psz, nInsertLength*sizeof(XCHAR));
 -				#endif
 -			  this->ReleaseBufferSetLength(nNewLength);
 -		  }
 -
 -		  return nNewLength;
 -	  }
 +		return nCount;
 +	}
 -	  // Replace all occurrences of character 'chOld' with character 'chNew'
 -	  int Replace(XCHAR chOld, XCHAR chNew)
 -	  {
 -		  int nCount = 0;
 -
 -		  // short-circuit the nop case
 -		  if (chOld != chNew)
 -		  {
 -			  // otherwise modify each character that matches in the string
 -			  bool bCopied = false;
 -			  PXSTR pszBuffer = const_cast< PXSTR >(this->GetString());  // We don't actually write to pszBuffer until we've called GetBuffer().
 -
 -			  int nLength = this->GetLength();
 -			  int iChar = 0;
 -			  while(iChar < nLength)
 -			  {
 -				  // replace instances of the specified character only
 -				  if (pszBuffer[iChar] == chOld)
 -				  {
 -					  if ( !bCopied)
 -					  {
 -						  bCopied = true;
 -						  pszBuffer = this->GetBuffer(nLength);
 -					  }
 -					  pszBuffer[iChar] = chNew;
 -					  nCount++;
 -				  }
 -				  iChar = int(StringTraits::CharNext(pszBuffer+iChar)-pszBuffer);
 -			  }
 -			  if (bCopied)
 -			  {
 -				  this->ReleaseBufferSetLength(nLength);
 -			  }
 -		  }
 -
 -		  return nCount;
 -	  }
 +	// Remove all occurrences of character 'chRemove'
 +	int Remove(XCHAR chRemove)
 +	{
 +		int nLength = this->GetLength();
 +		PXSTR pszBuffer = this->GetBuffer(nLength);
 -	  // Replace all occurrences of string 'pszOld' with string 'pszNew'
 -	  int Replace(PCXSTR pszOld, PCXSTR pszNew)
 -	  {
 -		  // can't have empty or NULL lpszOld
 -
 -		  // nSourceLen is in XCHARs
 -		  int nSourceLen = StringTraits::SafeStringLen(pszOld);
 -		  if (nSourceLen == 0)
 -			  return 0;
 -		  // nReplacementLen is in XCHARs
 -		  int nReplacementLen = StringTraits::SafeStringLen(pszNew);
 -
 -		  // loop once to figure out the size of the result string
 -		  int nCount = 0;
 -		  {
 -			  PCXSTR pszStart = this->GetString();
 -			  PCXSTR pszEnd = pszStart+this->GetLength();
 -			  while(pszStart < pszEnd)
 -			  {
 -				  PCXSTR pszTarget;
 -				  while((pszTarget = StringTraits::StringFindString(pszStart, pszOld)) != NULL)
 -				  {
 -					  nCount++;
 -					  pszStart = pszTarget+nSourceLen;
 -				  }
 -				  pszStart += StringTraits::SafeStringLen(pszStart)+1;
 -			  }
 -		  }
 -
 -		  // if any changes were made, make them
 -		  if (nCount > 0)
 -		  {
 -			  // if the buffer is too small, just
 -			  //   allocate a new buffer (slow but sure)
 -			  int nOldLength = this->GetLength();
 -			  int nNewLength = nOldLength+(nReplacementLen-nSourceLen)*nCount;
 -
 -			  PXSTR pszBuffer = this->GetBuffer(__max(nNewLength, nOldLength));
 -
 -			  PXSTR pszStart = pszBuffer;
 -			  PXSTR pszEnd = pszStart+nOldLength;
 -
 -			  // loop again to actually do the work
 -			  while(pszStart < pszEnd)
 -			  {
 -				  PXSTR pszTarget;
 -				  while((pszTarget = StringTraits::StringFindString(pszStart, pszOld)) != NULL)
 -				  {
 -					  int nBalance = nOldLength-int(pszTarget-pszBuffer+nSourceLen);
 -					  memmove_s(pszTarget+nReplacementLen, nBalance*sizeof(XCHAR), 
 -						  pszTarget+nSourceLen, nBalance*sizeof(XCHAR));
 -					  memcpy_s(pszTarget, nReplacementLen*sizeof(XCHAR), 
 -						  pszNew, nReplacementLen*sizeof(XCHAR));
 -					  pszStart = pszTarget+nReplacementLen;
 -					  pszTarget[nReplacementLen+nBalance] = 0;
 -					  nOldLength += (nReplacementLen-nSourceLen);
 -				  }
 -				  pszStart += StringTraits::SafeStringLen(pszStart)+1;
 -			  }
 -			  this->ReleaseBufferSetLength(nNewLength);
 -		  }
 -
 -		  return nCount;
 -	  }
 +		PXSTR pszSource = pszBuffer;
 +		PXSTR pszDest = pszBuffer;
 +		PXSTR pszEnd = pszBuffer+nLength;
 -	  // Remove all occurrences of character 'chRemove'
 -	  int Remove(XCHAR chRemove)
 -	  {
 -		  int nLength = this->GetLength();
 -		  PXSTR pszBuffer = this->GetBuffer(nLength);
 -
 -		  PXSTR pszSource = pszBuffer;
 -		  PXSTR pszDest = pszBuffer;
 -		  PXSTR pszEnd = pszBuffer+nLength;
 -
 -		  while(pszSource < pszEnd)
 -		  {
 -			  PXSTR pszNewSource = StringTraits::CharNext(pszSource);
 -			  if (*pszSource != chRemove)
 -			  {
 -				  // Copy the source to the destination.  Remember to copy all bytes of an MBCS character
 -				  // Copy the source to the destination.  Remember to copy all bytes of an MBCS character
 -				  size_t NewSourceGap = (pszNewSource-pszSource);
 -				  PXSTR pszNewDest = pszDest + NewSourceGap;
 -				  size_t i = 0;
 -				  for (i = 0;  pszDest != pszNewDest && i < NewSourceGap; i++)
 -				  {
 -					  *pszDest = *pszSource;
 -					  pszSource++;
 -					  pszDest++;
 -				  }
 -			  }
 -			  pszSource = pszNewSource;
 -		  }
 -		  *pszDest = 0;
 -		  int nCount = int(pszSource-pszDest);
 -		  this->ReleaseBufferSetLength(nLength-nCount);
 -
 -		  return nCount;
 -	  }
 +		while(pszSource < pszEnd)
 +		{
 +			PXSTR pszNewSource = StringTraits::CharNext(pszSource);
 +			if (*pszSource != chRemove)
 +			{
 +				// Copy the source to the destination.  Remember to copy all bytes of an MBCS character
 +				// Copy the source to the destination.  Remember to copy all bytes of an MBCS character
 +				size_t NewSourceGap = (pszNewSource-pszSource);
 +				PXSTR pszNewDest = pszDest + NewSourceGap;
 +				size_t i = 0;
 +				for (i = 0;  pszDest != pszNewDest && i < NewSourceGap; i++)
 +				{
 +					*pszDest = *pszSource;
 +					pszSource++;
 +					pszDest++;
 +				}
 +			}
 +			pszSource = pszNewSource;
 +		}
 +		*pszDest = 0;
 +		int nCount = int(pszSource-pszDest);
 +		this->ReleaseBufferSetLength(nLength-nCount);
 -	  CMStringT Tokenize(PCXSTR pszTokens, int& iStart) const
 -	  {
 -		  if ((pszTokens == NULL) || (*pszTokens == (XCHAR)0))
 -		  {
 -			  if (iStart < this->GetLength())
 -				  return CMStringT(this->GetString()+iStart);
 -		  }
 -		  else
 -		  {
 -			  PCXSTR pszPlace = this->GetString()+iStart;
 -			  PCXSTR pszEnd = this->GetString()+this->GetLength();
 -			  if (pszPlace < pszEnd)
 -			  {
 -				  int nIncluding = StringTraits::StringSpanIncluding(pszPlace, pszTokens);
 -
 -				  if ((pszPlace+nIncluding) < pszEnd)
 -				  {
 -					  pszPlace += nIncluding;
 -					  int nExcluding = StringTraits::StringSpanExcluding(pszPlace, pszTokens);
 -
 -					  int iFrom = iStart+nIncluding;
 -					  int nUntil = nExcluding;
 -					  iStart = iFrom+nUntil+1;
 -
 -					  return Mid(iFrom, nUntil);
 -				  }
 -			  }
 -		  }
 -
 -		  // return empty string, done tokenizing
 -		  iStart = -1;
 -
 -		  return CMStringT();
 -	  }
 +		return nCount;
 +	}
 -	  // find routines
 +	CMStringT Tokenize(PCXSTR pszTokens, int& iStart) const
 +	{
 +		if ((pszTokens == NULL) || (*pszTokens == (XCHAR)0))
 +		{
 +			if (iStart < this->GetLength())
 +				return CMStringT(this->GetString()+iStart);
 +		}
 +		else
 +		{
 +			PCXSTR pszPlace = this->GetString()+iStart;
 +			PCXSTR pszEnd = this->GetString()+this->GetLength();
 +			if (pszPlace < pszEnd)
 +			{
 +				int nIncluding = StringTraits::StringSpanIncluding(pszPlace, pszTokens);
 +
 +				if ((pszPlace+nIncluding) < pszEnd)
 +				{
 +					pszPlace += nIncluding;
 +					int nExcluding = StringTraits::StringSpanExcluding(pszPlace, pszTokens);
 +
 +					int iFrom = iStart+nIncluding;
 +					int nUntil = nExcluding;
 +					iStart = iFrom+nUntil+1;
 +
 +					return Mid(iFrom, nUntil);
 +				}
 +			}
 +		}
 -	  // Find the first occurrence of character 'ch', starting at index 'iStart'
 -	  int Find(XCHAR ch, int iStart = 0) const
 -	  {
 -		  // nLength is in XCHARs
 -		  int nLength = this->GetLength();
 -		  if (iStart < 0 || iStart >= nLength)
 -			  return -1;
 +		// return empty string, done tokenizing
 +		iStart = -1;
 -		  // find first single character
 -		  PCXSTR psz = StringTraits::StringFindChar(this->GetString()+iStart, ch);
 +		return CMStringT();
 +	}
 -		  // return -1 if not found and index otherwise
 -		  return (psz == NULL) ? -1 : int(psz-this->GetString());
 -	  }
 +	// find routines
 -	  // look for a specific sub-string
 +	// Find the first occurrence of character 'ch', starting at index 'iStart'
 +	int Find(XCHAR ch, int iStart = 0) const
 +	{
 +		// nLength is in XCHARs
 +		int nLength = this->GetLength();
 +		if (iStart < 0 || iStart >= nLength)
 +			return -1;
 -	  // Find the first occurrence of string 'pszSub', starting at index 'iStart'
 -	  int Find(PCXSTR pszSub, int iStart = 0) const
 -	  {
 -		  // iStart is in XCHARs
 -		  if (pszSub == NULL)
 -			  return -1;
 +		// find first single character
 +		PCXSTR psz = StringTraits::StringFindChar(this->GetString()+iStart, ch);
 -		  // nLength is in XCHARs
 -		  int nLength = this->GetLength();
 -		  if (iStart < 0 || iStart > nLength)
 -			  return -1;
 +		// return -1 if not found and index otherwise
 +		return (psz == NULL) ? -1 : int(psz-this->GetString());
 +	}
 -		  // find first matching substring
 -		  PCXSTR psz = StringTraits::StringFindString(this->GetString()+iStart, pszSub);
 +	// look for a specific sub-string
 -		  // return -1 for not found, distance from beginning otherwise
 -		  return (psz == NULL) ? -1 : int(psz-this->GetString());
 -	  }
 +	// Find the first occurrence of string 'pszSub', starting at index 'iStart'
 +	int Find(PCXSTR pszSub, int iStart = 0) const
 +	{
 +		// iStart is in XCHARs
 +		if (pszSub == NULL)
 +			return -1;
 -	  // Find the first occurrence of any of the characters in string 'pszCharSet'
 -	  int FindOneOf(PCXSTR pszCharSet) const
 -	  {
 -		  PCXSTR psz = StringTraits::StringScanSet(this->GetString(), pszCharSet);
 -		  return (psz == NULL) ? -1 : int(psz-this->GetString());
 -	  }
 +		// nLength is in XCHARs
 +		int nLength = this->GetLength();
 +		if (iStart < 0 || iStart > nLength)
 +			return -1;
 -	  // Find the last occurrence of character 'ch'
 -	  int ReverseFind(XCHAR ch) const
 -	  {
 -		  // find last single character
 -		  PCXSTR psz = StringTraits::StringFindCharRev(this->GetString(), ch);
 +		// find first matching substring
 +		PCXSTR psz = StringTraits::StringFindString(this->GetString()+iStart, pszSub);
 -		  // return -1 if not found, distance from beginning otherwise
 -		  return (psz == NULL) ? -1 : int(psz-this->GetString());
 -	  }
 +		// return -1 for not found, distance from beginning otherwise
 +		return (psz == NULL) ? -1 : int(psz-this->GetString());
 +	}
 -	  // manipulation
 +	// Find the first occurrence of any of the characters in string 'pszCharSet'
 +	int FindOneOf(PCXSTR pszCharSet) const
 +	{
 +		PCXSTR psz = StringTraits::StringScanSet(this->GetString(), pszCharSet);
 +		return (psz == NULL) ? -1 : int(psz-this->GetString());
 +	}
 -	  // Convert the string to uppercase
 -	  CMStringT& MakeUpper()
 -	  {
 -		  int nLength = this->GetLength();
 -		  PXSTR pszBuffer = this->GetBuffer(nLength);
 -		  StringTraits::StringUppercase(pszBuffer, nLength+1);
 -		  this->ReleaseBufferSetLength(nLength);
 +	// Find the last occurrence of character 'ch'
 +	int ReverseFind(XCHAR ch) const
 +	{
 +		// find last single character
 +		PCXSTR psz = StringTraits::StringFindCharRev(this->GetString(), ch);
 -		  return *this;
 -	  }
 +		// return -1 if not found, distance from beginning otherwise
 +		return (psz == NULL) ? -1 : int(psz-this->GetString());
 +	}
 -	  // Convert the string to lowercase
 -	  CMStringT& MakeLower()
 -	  {
 -		  int nLength = this->GetLength();
 -		  PXSTR pszBuffer = this->GetBuffer(nLength);
 -		  StringTraits::StringLowercase(pszBuffer, nLength+1);
 -		  this->ReleaseBufferSetLength(nLength);
 +	// manipulation
 -		  return *this;
 -	  }
 +	// Convert the string to uppercase
 +	CMStringT& MakeUpper()
 +	{
 +		int nLength = this->GetLength();
 +		PXSTR pszBuffer = this->GetBuffer(nLength);
 +		StringTraits::StringUppercase(pszBuffer, nLength+1);
 +		this->ReleaseBufferSetLength(nLength);
 -	  // Reverse the string
 -	  CMStringT& MakeReverse()
 -	  {
 -		  int nLength = this->GetLength();
 -		  PXSTR pszBuffer = this->GetBuffer(nLength);
 -		  StringTraits::StringReverse(pszBuffer);
 -		  this->ReleaseBufferSetLength(nLength);
 +		return *this;
 +	}
 -		  return *this;
 -	  }
 +	// Convert the string to lowercase
 +	CMStringT& MakeLower()
 +	{
 +		int nLength = this->GetLength();
 +		PXSTR pszBuffer = this->GetBuffer(nLength);
 +		StringTraits::StringLowercase(pszBuffer, nLength+1);
 +		this->ReleaseBufferSetLength(nLength);
 -	  // trimming
 +		return *this;
 +	}
 -	  // Remove all trailing whitespace
 -	  CMStringT& TrimRight()
 -	  {
 -		  // find beginning of trailing spaces by starting
 -		  // at beginning (DBCS aware)
 -
 -		  PCXSTR psz = this->GetString();
 -		  PCXSTR pszLast = NULL;
 -
 -		  while(*psz != 0)
 -		  {
 -			  if (StringTraits::IsSpace(*psz))
 -			  {
 -				  if (pszLast == NULL)
 -					  pszLast = psz;
 -			  }
 -			  else
 -			  {
 -				  pszLast = NULL;
 -			  }
 -			  psz = StringTraits::CharNext(psz);
 -		  }
 -
 -		  if (pszLast != NULL)
 -		  {
 -			  // truncate at trailing space start
 -			  int iLast = int(pszLast-this->GetString());
 -
 -			  this->Truncate(iLast);
 -		  }
 -
 -		  return *this;
 -	  }
 +	// Reverse the string
 +	CMStringT& MakeReverse()
 +	{
 +		int nLength = this->GetLength();
 +		PXSTR pszBuffer = this->GetBuffer(nLength);
 +		StringTraits::StringReverse(pszBuffer);
 +		this->ReleaseBufferSetLength(nLength);
 -	  // Remove all leading whitespace
 -	  CMStringT& TrimLeft()
 -	  {
 -		  // find first non-space character
 -
 -		  PCXSTR psz = this->GetString();
 -
 -		  while(StringTraits::IsSpace(*psz))
 -		  {
 -			  psz = StringTraits::CharNext(psz);
 -		  }
 -
 -		  if (psz != this->GetString())
 -		  {
 -			  // fix up data and length
 -			  int iFirst = int(psz-this->GetString());
 -			  PXSTR pszBuffer = this->GetBuffer(this->GetLength());
 -			  psz = pszBuffer+iFirst;
 -			  int nDataLength = this->GetLength()-iFirst;
 -			  memmove_s(pszBuffer, (this->GetLength()+1)*sizeof(XCHAR), 
 -				  psz, (nDataLength+1)*sizeof(XCHAR));
 -			  this->ReleaseBufferSetLength(nDataLength);
 -		  }
 -
 -		  return *this;
 -	  }
 +		return *this;
 +	}
 -	  // Remove all leading and trailing whitespace
 -	  CMStringT& Trim()
 -	  {
 -		  return TrimRight().TrimLeft();
 -	  }
 +	// trimming
 -	  // Remove all leading and trailing occurrences of character 'chTarget'
 -	  CMStringT& Trim(XCHAR chTarget)
 -	  {
 -		  return TrimRight(chTarget).TrimLeft(chTarget);
 -	  }
 +	// Remove all trailing whitespace
 +	CMStringT& TrimRight()
 +	{
 +		// find beginning of trailing spaces by starting
 +		// at beginning (DBCS aware)
 -	  // Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets'
 -	  CMStringT& Trim(PCXSTR pszTargets)
 -	  {
 -		  return TrimRight(pszTargets).TrimLeft(pszTargets);
 -	  }
 +		PCXSTR psz = this->GetString();
 +		PCXSTR pszLast = NULL;
 -	  // trimming anything (either side)
 +		while(*psz != 0) {
 +			if (StringTraits::IsSpace(*psz)) {
 +				if (pszLast == NULL)
 +					pszLast = psz;
 +			}
 +			else pszLast = NULL;
 -	  // Remove all trailing occurrences of character 'chTarget'
 -	  CMStringT& TrimRight(XCHAR chTarget)
 -	  {
 -		  // find beginning of trailing matches
 -		  // by starting at beginning (DBCS aware)
 -
 -		  PCXSTR psz = this->GetString();
 -		  PCXSTR pszLast = NULL;
 -
 -		  while(*psz != 0)
 -		  {
 -			  if (*psz == chTarget)
 -			  {
 -				  if (pszLast == NULL)
 -				  {
 -					  pszLast = psz;
 -				  }
 -			  }
 -			  else
 -			  {
 -				  pszLast = NULL;
 -			  }
 -			  psz = StringTraits::CharNext(psz);
 -		  }
 -
 -		  if (pszLast != NULL)
 -		  {
 -			  // truncate at left-most matching character  
 -			  int iLast = int(pszLast-this->GetString());
 -			  this->Truncate(iLast);
 -		  }
 -
 -		  return *this;
 -	  }
 +			psz = StringTraits::CharNext(psz);
 +		}
 -	  // Remove all trailing occurrences of any of the characters in string 'pszTargets'
 -	  CMStringT& TrimRight(PCXSTR pszTargets)
 -	  {
 -		  // if we're not trimming anything, we're not doing any work
 -		  if ((pszTargets == NULL) || (*pszTargets == 0))
 -		  {
 -			  return *this;
 -		  }
 -
 -		  // find beginning of trailing matches
 -		  // by starting at beginning (DBCS aware)
 -
 -		  PCXSTR psz = this->GetString();
 -		  PCXSTR pszLast = NULL;
 -
 -		  while(*psz != 0)
 -		  {
 -			  if (StringTraits::StringFindChar(pszTargets, *psz) != NULL)
 -			  {
 -				  if (pszLast == NULL)
 -				  {
 -					  pszLast = psz;
 -				  }
 -			  }
 -			  else
 -			  {
 -				  pszLast = NULL;
 -			  }
 -			  psz = StringTraits::CharNext(psz);
 -		  }
 -
 -		  if (pszLast != NULL)
 -		  {
 -			  // truncate at left-most matching character  
 -			  int iLast = int(pszLast-this->GetString());
 -			  this->Truncate(iLast);
 -		  }
 -
 -		  return *this;
 -	  }
 +		if (pszLast != NULL) {
 +			// truncate at trailing space start
 +			int iLast = int(pszLast-this->GetString());
 -	  // Remove all leading occurrences of character 'chTarget'
 -	  CMStringT& TrimLeft(XCHAR chTarget)
 -	  {
 -		  // find first non-matching character
 -		  PCXSTR psz = this->GetString();
 -
 -		  while(chTarget == *psz)
 -		  {
 -			  psz = StringTraits::CharNext(psz);
 -		  }
 -
 -		  if (psz != this->GetString())
 -		  {
 -			  // fix up data and length
 -			  int iFirst = int(psz-this->GetString());
 -			  PXSTR pszBuffer = this->GetBuffer(this->GetLength());
 -			  psz = pszBuffer+iFirst;
 -			  int nDataLength = this->GetLength()-iFirst;
 -			  memmove_s(pszBuffer, (this->GetLength()+1)*sizeof(XCHAR), 
 -				  psz, (nDataLength+1)*sizeof(XCHAR));
 -			  this->ReleaseBufferSetLength(nDataLength);
 -		  }
 -
 -		  return *this;
 -	  }
 +			this->Truncate(iLast);
 +		}
 -	  // Remove all leading occurrences of any of the characters in string 'pszTargets'
 -	  CMStringT& TrimLeft(PCXSTR pszTargets)
 -	  {
 -		  // if we're not trimming anything, we're not doing any work
 -		  if ((pszTargets == NULL) || (*pszTargets == 0))
 -		  {
 -			  return *this;
 -		  }
 -
 -		  PCXSTR psz = this->GetString();
 -		  while((*psz != 0) && (StringTraits::StringFindChar(pszTargets, *psz) != NULL))
 -		  {
 -			  psz = StringTraits::CharNext(psz);
 -		  }
 -
 -		  if (psz != this->GetString())
 -		  {
 -			  // fix up data and length
 -			  int iFirst = int(psz-this->GetString());
 -			  PXSTR pszBuffer = this->GetBuffer(this->GetLength());
 -			  psz = pszBuffer+iFirst;
 -			  int nDataLength = this->GetLength()-iFirst;
 -			  memmove_s(pszBuffer, (this->GetLength()+1)*sizeof(XCHAR), 
 -				  psz, (nDataLength+1)*sizeof(XCHAR));
 -			  this->ReleaseBufferSetLength(nDataLength);
 -		  }
 -
 -		  return *this;
 -	  }
 +		return *this;
 +	}
 -	  // Convert the string to the OEM character set
 -	  void AnsiToOem()
 -	  {
 -		  int nLength = this->GetLength();
 -		  PXSTR pszBuffer = this->GetBuffer(nLength);
 -		  StringTraits::ConvertToOem(pszBuffer, nLength+1);
 -		  this->ReleaseBufferSetLength(nLength);
 -	  }
 +	// Remove all leading whitespace
 +	CMStringT& TrimLeft()
 +	{
 +		// find first non-space character
 -	  // Convert the string to the ANSI character set
 -	  void OemToAnsi()
 -	  {
 -		  int nLength = this->GetLength();
 -		  PXSTR pszBuffer = this->GetBuffer(nLength);
 -		  StringTraits::ConvertToAnsi(pszBuffer, nLength+1);
 -		  this->ReleaseBufferSetLength(nLength);
 -	  }
 +		PCXSTR psz = this->GetString();
 -	  // Very simple sub-string extraction
 +		while(StringTraits::IsSpace(*psz))
 +		{
 +			psz = StringTraits::CharNext(psz);
 +		}
 -	  // Return the substring starting at index 'iFirst'
 -	  CMStringT Mid(int iFirst) const
 -	  {
 -		  return Mid(iFirst, this->GetLength()-iFirst);
 -	  }
 +		if (psz != this->GetString())
 +		{
 +			// fix up data and length
 +			int iFirst = int(psz-this->GetString());
 +			PXSTR pszBuffer = this->GetBuffer(this->GetLength());
 +			psz = pszBuffer+iFirst;
 +			int nDataLength = this->GetLength()-iFirst;
 +			memmove_s(pszBuffer, (this->GetLength()+1)*sizeof(XCHAR), 
 +				psz, (nDataLength+1)*sizeof(XCHAR));
 +			this->ReleaseBufferSetLength(nDataLength);
 +		}
 -	  // Return the substring starting at index 'iFirst', with length 'nCount'
 -	  CMStringT Mid(int iFirst, int nCount) const
 -	  {
 -		  // nCount is in XCHARs
 +		return *this;
 +	}
 -		  // out-of-bounds requests return sensible things
 -		  if (iFirst < 0)
 -			  iFirst = 0;
 -		  if (nCount < 0)
 -			  nCount = 0;
 +	// Remove all leading and trailing whitespace
 +	CMStringT& Trim()
 +	{
 +		return TrimRight().TrimLeft();
 +	}
 -		  if ((iFirst + nCount) > this->GetLength())
 -			  nCount = this->GetLength()-iFirst;
 +	// Remove all leading and trailing occurrences of character 'chTarget'
 +	CMStringT& Trim(XCHAR chTarget)
 +	{
 +		return TrimRight(chTarget).TrimLeft(chTarget);
 +	}
 -		  if (iFirst > this->GetLength())
 -			  nCount = 0;
 +	// Remove all leading and trailing occurrences of any of the characters in the string 'pszTargets'
 +	CMStringT& Trim(PCXSTR pszTargets)
 +	{
 +		return TrimRight(pszTargets).TrimLeft(pszTargets);
 +	}
 -		  // optimize case of returning entire string
 -		  if ((iFirst == 0) && ((iFirst+nCount) == this->GetLength()))
 -			  return *this;
 +	// trimming anything (either side)
 -		  return CMStringT(this->GetString()+iFirst, nCount);
 -	  }
 +	// Remove all trailing occurrences of character 'chTarget'
 +	CMStringT& TrimRight(XCHAR chTarget)
 +	{
 +		// find beginning of trailing matches
 +		// by starting at beginning (DBCS aware)
 -	  // Return the substring consisting of the rightmost 'nCount' characters
 -	  CMStringT Right(int nCount) const
 -	  {
 -		  // nCount is in XCHARs
 -		  if (nCount < 0)
 -			  nCount = 0;
 +		PCXSTR psz = this->GetString();
 +		PCXSTR pszLast = NULL;
 -		  int nLength = this->GetLength();
 -		  if (nCount >= nLength)
 -		  {
 -			  return *this;
 -		  }
 +		while(*psz != 0)
 +		{
 +			if (*psz == chTarget)
 +			{
 +				if (pszLast == NULL)
 +				{
 +					pszLast = psz;
 +				}
 +			}
 +			else
 +			{
 +				pszLast = NULL;
 +			}
 +			psz = StringTraits::CharNext(psz);
 +		}
 -		  return CMStringT(this->GetString()+nLength-nCount, nCount);
 -	  }
 +		if (pszLast != NULL)
 +		{
 +			// truncate at left-most matching character  
 +			int iLast = int(pszLast-this->GetString());
 +			this->Truncate(iLast);
 +		}
 -	  // Return the substring consisting of the leftmost 'nCount' characters
 -	  CMStringT Left(int nCount) const
 -	  {
 -		  // nCount is in XCHARs
 -		  if (nCount < 0)
 -			  nCount = 0;
 +		return *this;
 +	}
 -		  int nLength = this->GetLength();
 -		  if (nCount >= nLength)
 -			  return *this;
 +	// Remove all trailing occurrences of any of the characters in string 'pszTargets'
 +	CMStringT& TrimRight(PCXSTR pszTargets)
 +	{
 +		// if we're not trimming anything, we're not doing any work
 +		if ((pszTargets == NULL) || (*pszTargets == 0))
 +		{
 +			return *this;
 +		}
 -		  return CMStringT(this->GetString(), nCount);
 -	  }
 +		// find beginning of trailing matches
 +		// by starting at beginning (DBCS aware)
 -	  // Return the substring consisting of the leftmost characters in the set 'pszCharSet'
 -	  CMStringT SpanIncluding(PCXSTR pszCharSet) const
 -	  {
 -		  return Left(StringTraits::StringSpanIncluding(this->GetString(), pszCharSet));
 -	  }
 +		PCXSTR psz = this->GetString();
 +		PCXSTR pszLast = NULL;
 -	  // Return the substring consisting of the leftmost characters not in the set 'pszCharSet'
 -	  CMStringT SpanExcluding(PCXSTR pszCharSet) const
 -	  {
 -		  return Left(StringTraits::StringSpanExcluding(this->GetString(), pszCharSet));
 -	  }
 +		while(*psz != 0)
 +		{
 +			if (StringTraits::StringFindChar(pszTargets, *psz) != NULL)
 +			{
 +				if (pszLast == NULL)
 +				{
 +					pszLast = psz;
 +				}
 +			}
 +			else
 +			{
 +				pszLast = NULL;
 +			}
 +			psz = StringTraits::CharNext(psz);
 +		}
 -	  // Format data using format string 'pszFormat'
 -	  void Format(PCXSTR pszFormat, ...);
 +		if (pszLast != NULL)
 +		{
 +			// truncate at left-most matching character  
 +			int iLast = int(pszLast-this->GetString());
 +			this->Truncate(iLast);
 +		}
 -	  // Append formatted data using format string 'pszFormat'
 -	  void AppendFormat(PCXSTR pszFormat, ...);
 +		return *this;
 +	}
 -	  void AppendFormatV(PCXSTR pszFormat, va_list args)
 -	  {
 -		  int nCurrentLength = this->GetLength();
 -		  int nAppendLength = StringTraits::GetFormattedLength(pszFormat, args);
 -		  PXSTR pszBuffer = this->GetBuffer(nCurrentLength+nAppendLength);
 -		  StringTraits::Format(pszBuffer+nCurrentLength, 
 -			  nAppendLength+1, pszFormat, args);
 -		  this->ReleaseBufferSetLength(nCurrentLength+nAppendLength);
 -	  }
 +	// Remove all leading occurrences of character 'chTarget'
 +	CMStringT& TrimLeft(XCHAR chTarget)
 +	{
 +		// find first non-matching character
 +		PCXSTR psz = this->GetString();
 -	  void FormatV(PCXSTR pszFormat, va_list args)
 -	  {
 -		  int nLength = StringTraits::GetFormattedLength(pszFormat, args);
 -		  PXSTR pszBuffer = this->GetBuffer(nLength);
 -		  StringTraits::Format(pszBuffer, nLength+1, pszFormat, args);
 -		  this->ReleaseBufferSetLength(nLength);
 -	  }
 +		while(chTarget == *psz)
 +		{
 +			psz = StringTraits::CharNext(psz);
 +		}
 -	  // OLE BSTR support
 +		if (psz != this->GetString())
 +		{
 +			// fix up data and length
 +			int iFirst = int(psz-this->GetString());
 +			PXSTR pszBuffer = this->GetBuffer(this->GetLength());
 +			psz = pszBuffer+iFirst;
 +			int nDataLength = this->GetLength()-iFirst;
 +			memmove_s(pszBuffer, (this->GetLength()+1)*sizeof(XCHAR), 
 +				psz, (nDataLength+1)*sizeof(XCHAR));
 +			this->ReleaseBufferSetLength(nDataLength);
 +		}
 -	  // allocate a BSTR containing a copy of the string
 -	  BSTR AllocSysString() const
 -	  {
 -		  BSTR bstrResult = StringTraits::AllocSysString(this->GetString(), this->GetLength());
 -		  return bstrResult;
 -	  }
 +		return *this;
 +	}
 -	  BSTR SetSysString(BSTR* pbstr) const
 -	  {
 -		  StringTraits::ReAllocSysString(this->GetString(), pbstr, this->GetLength());
 -		  return *pbstr;
 -	  }
 +	// Remove all leading occurrences of any of the characters in string 'pszTargets'
 +	CMStringT& TrimLeft(PCXSTR pszTargets)
 +	{
 +		// if we're not trimming anything, we're not doing any work
 +		if ((pszTargets == NULL) || (*pszTargets == 0))
 +		{
 +			return *this;
 +		}
 -	  // Set the string to the value of environment variable 'pszVar'
 -	  BOOL GetEnvironmentVariable(PCXSTR pszVar)
 -	  {
 -		  ULONG nLength = StringTraits::GetEnvironmentVariable(pszVar, NULL, 0);
 -		  BOOL bRetVal = FALSE;
 -
 -		  if (nLength == 0)
 -		  {
 -			  this->Empty();
 -		  }
 -		  else
 -		  {
 -			  PXSTR pszBuffer = this->GetBuffer(nLength);
 -			  StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength);
 -			  this->ReleaseBuffer();
 -			  bRetVal = TRUE;
 -		  }
 -
 -		  return bRetVal;
 -	  }
 +		PCXSTR psz = this->GetString();
 +		while((*psz != 0) && (StringTraits::StringFindChar(pszTargets, *psz) != NULL))
 +		{
 +			psz = StringTraits::CharNext(psz);
 +		}
 -	  // Load the string from resource 'nID'
 -	  BOOL LoadString(UINT nID)
 -	  {
 -		  HINSTANCE hInst = StringTraits::FindStringResourceInstance(nID);
 -		  if (hInst == NULL)
 -			  return FALSE;
 +		if (psz != this->GetString())
 +		{
 +			// fix up data and length
 +			int iFirst = int(psz-this->GetString());
 +			PXSTR pszBuffer = this->GetBuffer(this->GetLength());
 +			psz = pszBuffer+iFirst;
 +			int nDataLength = this->GetLength()-iFirst;
 +			memmove_s(pszBuffer, (this->GetLength()+1)*sizeof(XCHAR), 
 +				psz, (nDataLength+1)*sizeof(XCHAR));
 +			this->ReleaseBufferSetLength(nDataLength);
 +		}
 -		  return LoadString(hInst, nID);
 -	  }
 +		return *this;
 +	}
 -	  friend CMStringT __stdcall operator+(const CMStringT& str1, const CMStringT& str2)
 -	  {
 -		  CMStringT strResult;
 +	// Convert the string to the OEM character set
 +	void AnsiToOem()
 +	{
 +		int nLength = this->GetLength();
 +		PXSTR pszBuffer = this->GetBuffer(nLength);
 +		StringTraits::ConvertToOem(pszBuffer, nLength+1);
 +		this->ReleaseBufferSetLength(nLength);
 +	}
 -		  Concatenate(strResult, str1, str1.GetLength(), str2, str2.GetLength());
 +	// Convert the string to the ANSI character set
 +	void OemToAnsi()
 +	{
 +		int nLength = this->GetLength();
 +		PXSTR pszBuffer = this->GetBuffer(nLength);
 +		StringTraits::ConvertToAnsi(pszBuffer, nLength+1);
 +		this->ReleaseBufferSetLength(nLength);
 +	}
 -		  return strResult;
 -	  }
 +	// Very simple sub-string extraction
 -	  friend CMStringT __stdcall operator+(const CMStringT& str1, PCXSTR psz2)
 -	  {
 -		  CMStringT strResult;
 +	// Return the substring starting at index 'iFirst'
 +	CMStringT Mid(int iFirst) const
 +	{
 +		return Mid(iFirst, this->GetLength()-iFirst);
 +	}
 -		  Concatenate(strResult, str1, str1.GetLength(), psz2, StringLength(psz2));
 +	// Return the substring starting at index 'iFirst', with length 'nCount'
 +	CMStringT Mid(int iFirst, int nCount) const
 +	{
 +		// nCount is in XCHARs
 -		  return strResult;
 -	  }
 +		// out-of-bounds requests return sensible things
 +		if (iFirst < 0)
 +			iFirst = 0;
 +		if (nCount < 0)
 +			nCount = 0;
 -	  friend CMStringT __stdcall operator+(PCXSTR psz1, const CMStringT& str2)
 -	  {
 -		  CMStringT strResult;
 +		if ((iFirst + nCount) > this->GetLength())
 +			nCount = this->GetLength()-iFirst;
 -		  Concatenate(strResult, psz1, StringLength(psz1), str2, str2.GetLength());
 +		if (iFirst > this->GetLength())
 +			nCount = 0;
 -		  return strResult;
 -	  }
 +		// optimize case of returning entire string
 +		if ((iFirst == 0) && ((iFirst+nCount) == this->GetLength()))
 +			return *this;
 -	  friend CMStringT __stdcall operator+(const CMStringT& str1, wchar_t ch2)
 -	  {
 -		  CMStringT strResult;
 -		  XCHAR chTemp = XCHAR(ch2);
 +		return CMStringT(this->GetString()+iFirst, nCount);
 +	}
 -		  Concatenate(strResult, str1, str1.GetLength(), &chTemp, 1);
 +	// Return the substring consisting of the rightmost 'nCount' characters
 +	CMStringT Right(int nCount) const
 +	{
 +		// nCount is in XCHARs
 +		if (nCount < 0)
 +			nCount = 0;
 -		  return strResult;
 -	  }
 +		int nLength = this->GetLength();
 +		if (nCount >= nLength)
 +		{
 +			return *this;
 +		}
 -	  friend CMStringT __stdcall operator+(const CMStringT& str1, char ch2)
 -	  {
 -		  CMStringT strResult;
 -		  XCHAR chTemp = XCHAR(ch2);
 +		return CMStringT(this->GetString()+nLength-nCount, nCount);
 +	}
 -		  Concatenate(strResult, str1, str1.GetLength(), &chTemp, 1);
 +	// Return the substring consisting of the leftmost 'nCount' characters
 +	CMStringT Left(int nCount) const
 +	{
 +		// nCount is in XCHARs
 +		if (nCount < 0)
 +			nCount = 0;
 -		  return strResult;
 -	  }
 +		int nLength = this->GetLength();
 +		if (nCount >= nLength)
 +			return *this;
 -	  friend CMStringT __stdcall operator+(wchar_t ch1, const CMStringT& str2)
 -	  {
 -		  CMStringT strResult;
 -		  XCHAR chTemp = XCHAR(ch1);
 +		return CMStringT(this->GetString(), nCount);
 +	}
 -		  Concatenate(strResult, &chTemp, 1, str2, str2.GetLength());
 +	// Return the substring consisting of the leftmost characters in the set 'pszCharSet'
 +	CMStringT SpanIncluding(PCXSTR pszCharSet) const
 +	{
 +		return Left(StringTraits::StringSpanIncluding(this->GetString(), pszCharSet));
 +	}
 -		  return strResult;
 -	  }
 +	// Return the substring consisting of the leftmost characters not in the set 'pszCharSet'
 +	CMStringT SpanExcluding(PCXSTR pszCharSet) const
 +	{
 +		return Left(StringTraits::StringSpanExcluding(this->GetString(), pszCharSet));
 +	}
 -	  friend CMStringT __stdcall operator+(char ch1, const CMStringT& str2)
 -	  {
 -		  CMStringT strResult;
 -		  XCHAR chTemp = XCHAR(ch1);
 +	// Format data using format string 'pszFormat'
 +	PCXSTR Format(PCXSTR pszFormat, ...)
 +	{
 +		va_list argList;
 +		va_start(argList, pszFormat);
 +		FormatV(pszFormat, argList);
 +		va_end(argList);
 +		return GetString();
 +	}
 -		  Concatenate(strResult, &chTemp, 1, str2, str2.GetLength());
 +	// Append formatted data using format string 'pszFormat'
 +	PCXSTR AppendFormat(PCXSTR pszFormat, ...)
 +	{
 +		va_list argList;
 +		va_start(argList, pszFormat);
 +		AppendFormatV(pszFormat, argList);
 +		va_end(argList);
 +		return GetString();
 +	}
 -		  return strResult;
 -	  }
 +	void AppendFormatV(PCXSTR pszFormat, va_list args)
 +	{
 +		int nCurrentLength = this->GetLength();
 +		int nAppendLength = StringTraits::GetFormattedLength(pszFormat, args);
 +		PXSTR pszBuffer = this->GetBuffer(nCurrentLength+nAppendLength);
 +		StringTraits::Format(pszBuffer+nCurrentLength, 
 +			nAppendLength+1, pszFormat, args);
 +		this->ReleaseBufferSetLength(nCurrentLength+nAppendLength);
 +	}
 -	  friend bool __stdcall operator==(const CMStringT& str1, const CMStringT& str2)
 -	  {
 -		  return str1.Compare(str2) == 0;
 -	  }
 +	void FormatV(PCXSTR pszFormat, va_list args)
 +	{
 +		int nLength = StringTraits::GetFormattedLength(pszFormat, args);
 +		PXSTR pszBuffer = this->GetBuffer(nLength);
 +		StringTraits::Format(pszBuffer, nLength+1, pszFormat, args);
 +		this->ReleaseBufferSetLength(nLength);
 +	}
 -	  friend bool __stdcall operator==(const CMStringT& str1, PCXSTR psz2)
 -	  {
 -		  return str1.Compare(psz2) == 0;
 -	  }
 +	// OLE BSTR support
 -	  friend bool __stdcall operator==(PCXSTR psz1, const CMStringT& str2)
 -	  {
 -		  return str2.Compare(psz1) == 0;
 -	  }
 +	// allocate a BSTR containing a copy of the string
 +	BSTR AllocSysString() const
 +	{
 +		BSTR bstrResult = StringTraits::AllocSysString(this->GetString(), this->GetLength());
 +		return bstrResult;
 +	}
 -	  friend bool __stdcall operator==(const CMStringT& str1, PCYSTR psz2)
 -	  {
 -		  CMStringT str2(psz2);
 +	BSTR SetSysString(BSTR* pbstr) const
 +	{
 +		StringTraits::ReAllocSysString(this->GetString(), pbstr, this->GetLength());
 +		return *pbstr;
 +	}
 -		  return str1 == str2;
 -	  }
 +	// Set the string to the value of environment variable 'pszVar'
 +	BOOL GetEnvironmentVariable(PCXSTR pszVar)
 +	{
 +		ULONG nLength = StringTraits::GetEnvironmentVariable(pszVar, NULL, 0);
 +		BOOL bRetVal = FALSE;
 -	  friend bool __stdcall operator==(PCYSTR psz1, const CMStringT& str2)
 -	  {
 -		  CMStringT str1(psz1);
 +		if (nLength == 0)
 +		{
 +			this->Empty();
 +		}
 +		else
 +		{
 +			PXSTR pszBuffer = this->GetBuffer(nLength);
 +			StringTraits::GetEnvironmentVariable(pszVar, pszBuffer, nLength);
 +			this->ReleaseBuffer();
 +			bRetVal = TRUE;
 +		}
 -		  return str1 == str2;
 -	  }
 +		return bRetVal;
 +	}
 -	  friend bool __stdcall operator!=(const CMStringT& str1, const CMStringT& str2)
 -	  {
 -		  return str1.Compare(str2) != 0;
 -	  }
 +	// Load the string from resource 'nID'
 +	BOOL LoadString(UINT nID)
 +	{
 +		HINSTANCE hInst = StringTraits::FindStringResourceInstance(nID);
 +		if (hInst == NULL)
 +			return FALSE;
 -	  friend bool __stdcall operator!=(const CMStringT& str1, PCXSTR psz2)
 -	  {
 -		  return str1.Compare(psz2) != 0;
 -	  }
 +		return LoadString(hInst, nID);
 +	}
 -	  friend bool __stdcall operator!=(PCXSTR psz1, const CMStringT& str2)
 -	  {
 -		  return str2.Compare(psz1) != 0;
 -	  }
 +	friend CMStringT __stdcall operator+(const CMStringT& str1, const CMStringT& str2)
 +	{
 +		CMStringT strResult;
 -	  friend bool __stdcall operator!=(const CMStringT& str1, PCYSTR psz2)
 -	  {
 -		  CMStringT str2(psz2);
 +		Concatenate(strResult, str1, str1.GetLength(), str2, str2.GetLength());
 -		  return str1 != str2;
 -	  }
 +		return strResult;
 +	}
 -	  friend bool __stdcall operator!=(PCYSTR psz1, const CMStringT& str2)
 -	  {
 -		  CMStringT str1(psz1);
 +	friend CMStringT __stdcall operator+(const CMStringT& str1, PCXSTR psz2)
 +	{
 +		CMStringT strResult;
 -		  return str1 != str2;
 -	  }
 +		Concatenate(strResult, str1, str1.GetLength(), psz2, StringLength(psz2));
 -	  friend bool __stdcall operator<(const CMStringT& str1, const CMStringT& str2)
 -	  {
 -		  return str1.Compare(str2) < 0;
 -	  }
 +		return strResult;
 +	}
 -	  friend bool __stdcall operator<(const CMStringT& str1, PCXSTR psz2)
 -	  {
 -		  return str1.Compare(psz2) < 0;
 -	  }
 +	friend CMStringT __stdcall operator+(PCXSTR psz1, const CMStringT& str2)
 +	{
 +		CMStringT strResult;
 -	  friend bool __stdcall operator<(PCXSTR psz1, const CMStringT& str2)
 -	  {
 -		  return str2.Compare(psz1) > 0;
 -	  }
 +		Concatenate(strResult, psz1, StringLength(psz1), str2, str2.GetLength());
 -	  friend bool __stdcall operator>(const CMStringT& str1, const CMStringT& str2)
 -	  {
 -		  return str1.Compare(str2) > 0;
 -	  }
 +		return strResult;
 +	}
 -	  friend bool __stdcall operator>(const CMStringT& str1, PCXSTR psz2)
 -	  {
 -		  return str1.Compare(psz2) > 0;
 -	  }
 +	friend CMStringT __stdcall operator+(const CMStringT& str1, wchar_t ch2)
 +	{
 +		CMStringT strResult;
 +		XCHAR chTemp = XCHAR(ch2);
 -	  friend bool __stdcall operator>(PCXSTR psz1, const CMStringT& str2)
 -	  {
 -		  return str2.Compare(psz1) < 0;
 -	  }
 +		Concatenate(strResult, str1, str1.GetLength(), &chTemp, 1);
 -	  friend bool __stdcall operator<=(const CMStringT& str1, const CMStringT& str2)
 -	  {
 -		  return str1.Compare(str2) <= 0;
 -	  }
 +		return strResult;
 +	}
 -	  friend bool __stdcall operator<=(const CMStringT& str1, PCXSTR psz2)
 -	  {
 -		  return str1.Compare(psz2) <= 0;
 -	  }
 +	friend CMStringT __stdcall operator+(const CMStringT& str1, char ch2)
 +	{
 +		CMStringT strResult;
 +		XCHAR chTemp = XCHAR(ch2);
 -	  friend bool __stdcall operator<=(PCXSTR psz1, const CMStringT& str2)
 -	  {
 -		  return str2.Compare(psz1) >= 0;
 -	  }
 +		Concatenate(strResult, str1, str1.GetLength(), &chTemp, 1);
 -	  friend bool __stdcall operator>=(const CMStringT& str1, const CMStringT& str2)
 -	  {
 -		  return str1.Compare(str2) >= 0;
 -	  }
 +		return strResult;
 +	}
 -	  friend bool __stdcall operator>=(const CMStringT& str1, PCXSTR psz2)
 -	  {
 -		  return str1.Compare(psz2) >= 0;
 -	  }
 +	friend CMStringT __stdcall operator+(wchar_t ch1, const CMStringT& str2)
 +	{
 +		CMStringT strResult;
 +		XCHAR chTemp = XCHAR(ch1);
 -	  friend bool __stdcall operator>=(PCXSTR psz1, const CMStringT& str2)
 -	  {
 -		  return str2.Compare(psz1) <= 0;
 -	  }
 +		Concatenate(strResult, &chTemp, 1, str2, str2.GetLength());
 -	  friend bool __stdcall operator==(XCHAR ch1, const CMStringT& str2)
 -	  {
 -		  return (str2.GetLength() == 1) && (str2[0] == ch1);
 -	  }
 +		return strResult;
 +	}
 -	  friend bool __stdcall operator==(const CMStringT& str1, XCHAR ch2)
 -	  {
 -		  return (str1.GetLength() == 1) && (str1[0] == ch2);
 -	  }
 +	friend CMStringT __stdcall operator+(char ch1, const CMStringT& str2)
 +	{
 +		CMStringT strResult;
 +		XCHAR chTemp = XCHAR(ch1);
 -	  friend bool __stdcall operator!=(XCHAR ch1, const CMStringT& str2)
 -	  {
 -		  return (str2.GetLength() != 1) || (str2[0] != ch1);
 -	  }
 +		Concatenate(strResult, &chTemp, 1, str2, str2.GetLength());
 -	  friend bool __stdcall operator!=(const CMStringT& str1, XCHAR ch2)
 -	  {
 -		  return (str1.GetLength() != 1) || (str1[0] != ch2);
 -	  }
 -};
 +		return strResult;
 +	}
 -template< typename BaseType, class StringTraits >
 -inline void CMStringT<BaseType, StringTraits>::Format(PCXSTR pszFormat, ...)
 -{
 -	va_list argList;
 -	va_start(argList, pszFormat);
 -	FormatV(pszFormat, argList);
 -	va_end(argList);
 -}
 +	friend bool __stdcall operator==(const CMStringT& str1, const CMStringT& str2)
 +	{
 +		return str1.Compare(str2) == 0;
 +	}
 -template< typename BaseType, class StringTraits >
 -inline void CMStringT<BaseType, StringTraits>::AppendFormat(PCXSTR pszFormat, ...)
 -{
 -	va_list argList;
 -	va_start(argList, pszFormat);
 -	AppendFormatV(pszFormat, argList);
 -	va_end(argList);
 -}
 +	friend bool __stdcall operator==(const CMStringT& str1, PCXSTR psz2)
 +	{
 +		return str1.Compare(psz2) == 0;
 +	}
 +
 +	friend bool __stdcall operator==(PCXSTR psz1, const CMStringT& str2)
 +	{
 +		return str2.Compare(psz1) == 0;
 +	}
 +
 +	friend bool __stdcall operator==(const CMStringT& str1, PCYSTR psz2)
 +	{
 +		CMStringT str2(psz2);
 +
 +		return str1 == str2;
 +	}
 +
 +	friend bool __stdcall operator==(PCYSTR psz1, const CMStringT& str2)
 +	{
 +		CMStringT str1(psz1);
 +
 +		return str1 == str2;
 +	}
 +
 +	friend bool __stdcall operator!=(const CMStringT& str1, const CMStringT& str2)
 +	{
 +		return str1.Compare(str2) != 0;
 +	}
 +
 +	friend bool __stdcall operator!=(const CMStringT& str1, PCXSTR psz2)
 +	{
 +		return str1.Compare(psz2) != 0;
 +	}
 +
 +	friend bool __stdcall operator!=(PCXSTR psz1, const CMStringT& str2)
 +	{
 +		return str2.Compare(psz1) != 0;
 +	}
 +
 +	friend bool __stdcall operator!=(const CMStringT& str1, PCYSTR psz2)
 +	{
 +		CMStringT str2(psz2);
 +
 +		return str1 != str2;
 +	}
 +
 +	friend bool __stdcall operator!=(PCYSTR psz1, const CMStringT& str2)
 +	{
 +		CMStringT str1(psz1);
 +
 +		return str1 != str2;
 +	}
 +
 +	friend bool __stdcall operator<(const CMStringT& str1, const CMStringT& str2)
 +	{
 +		return str1.Compare(str2) < 0;
 +	}
 +
 +	friend bool __stdcall operator<(const CMStringT& str1, PCXSTR psz2)
 +	{
 +		return str1.Compare(psz2) < 0;
 +	}
 +
 +	friend bool __stdcall operator<(PCXSTR psz1, const CMStringT& str2)
 +	{
 +		return str2.Compare(psz1) > 0;
 +	}
 +
 +	friend bool __stdcall operator>(const CMStringT& str1, const CMStringT& str2)
 +	{
 +		return str1.Compare(str2) > 0;
 +	}
 +
 +	friend bool __stdcall operator>(const CMStringT& str1, PCXSTR psz2)
 +	{
 +		return str1.Compare(psz2) > 0;
 +	}
 +
 +	friend bool __stdcall operator>(PCXSTR psz1, const CMStringT& str2)
 +	{
 +		return str2.Compare(psz1) < 0;
 +	}
 +
 +	friend bool __stdcall operator<=(const CMStringT& str1, const CMStringT& str2)
 +	{
 +		return str1.Compare(str2) <= 0;
 +	}
 +
 +	friend bool __stdcall operator<=(const CMStringT& str1, PCXSTR psz2)
 +	{
 +		return str1.Compare(psz2) <= 0;
 +	}
 +
 +	friend bool __stdcall operator<=(PCXSTR psz1, const CMStringT& str2)
 +	{
 +		return str2.Compare(psz1) >= 0;
 +	}
 +
 +	friend bool __stdcall operator>=(const CMStringT& str1, const CMStringT& str2)
 +	{
 +		return str1.Compare(str2) >= 0;
 +	}
 +
 +	friend bool __stdcall operator>=(const CMStringT& str1, PCXSTR psz2)
 +	{
 +		return str1.Compare(psz2) >= 0;
 +	}
 +
 +	friend bool __stdcall operator>=(PCXSTR psz1, const CMStringT& str2)
 +	{
 +		return str2.Compare(psz1) <= 0;
 +	}
 +
 +	friend bool __stdcall operator==(XCHAR ch1, const CMStringT& str2)
 +	{
 +		return (str2.GetLength() == 1) && (str2[0] == ch1);
 +	}
 +
 +	friend bool __stdcall operator==(const CMStringT& str1, XCHAR ch2)
 +	{
 +		return (str1.GetLength() == 1) && (str1[0] == ch2);
 +	}
 +
 +	friend bool __stdcall operator!=(XCHAR ch1, const CMStringT& str2)
 +	{
 +		return (str2.GetLength() != 1) || (str2[0] != ch1);
 +	}
 +
 +	friend bool __stdcall operator!=(const CMStringT& str1, XCHAR ch2)
 +	{
 +		return (str1.GetLength() != 1) || (str1[0] != ch2);
 +	}
 +};
  typedef CMStringT< wchar_t, ChTraitsCRT< wchar_t > > CMStringW;
  typedef CMStringT< char, ChTraitsCRT< char > > CMStringA;
 diff --git a/protocols/MRA/src/Mra_proto.cpp b/protocols/MRA/src/Mra_proto.cpp index 23f9a039ae..e085e8cc41 100644 --- a/protocols/MRA/src/Mra_proto.cpp +++ b/protocols/MRA/src/Mra_proto.cpp @@ -475,9 +475,7 @@ bool CMraProto::CmdMessageStatus(ULONG seq, BinBuffer &buf)  			ProtoBroadcastAck(hContact, dwAckType, ACKRESULT_FAILED, (HANDLE)seq, (LPARAM)"User does not accept offline flash animation");
  			break;
  		default:
 -			CMStringA szMsg;
 -			szMsg.Format("Undefined message delivery error, code: %lu", dwTemp);
 -			ProtoBroadcastAck(hContact, dwAckType, ACKRESULT_FAILED, (HANDLE)seq, (LPARAM)szMsg.c_str());
 +			ProtoBroadcastAck(hContact, dwAckType, ACKRESULT_FAILED, (HANDLE)seq, (LPARAM)CMStringA().Format("Undefined message delivery error, code: %lu", dwTemp));
  			break;
  		}
  		MraSendQueueFree(hSendQueueHandle, seq);
  | 
