Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1896 lines
50 KiB

  1. // This is a part of the Active Template Library.
  2. // Copyright (C) 1996-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Active Template Library Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Active Template Library product.
  10. // atltmp.h - temporary location for these classes
  11. #ifndef __ATLTMP_H__
  12. #define __ATLTMP_H__
  13. #ifndef __cplusplus
  14. #error ATL requires C++ compilation (use a .cpp suffix)
  15. #endif
  16. #ifndef __ATLBASE_H__
  17. #error atltmp.h requires atlbase.h to be included first
  18. #endif
  19. #pragma once
  20. #ifndef _ATL_TMP_NO_CSTRING
  21. #include <limits.h>
  22. #include <stdio.h>
  23. #endif //!_ATL_TMP_NO_CSTRING
  24. namespace ATL
  25. {
  26. /////////////////////////////////////////////////////////////////////////////
  27. // Forward declarations
  28. class CSize;
  29. class CPoint;
  30. class CRect;
  31. #ifndef _ATL_TMP_NO_CSTRING
  32. class CString;
  33. #endif //!_ATL_TMP_NO_CSTRING
  34. /////////////////////////////////////////////////////////////////////////////
  35. // CSize - An extent, similar to Windows SIZE structure.
  36. class CSize : public tagSIZE
  37. {
  38. public:
  39. // Constructors
  40. CSize();
  41. CSize(int initCX, int initCY);
  42. CSize(SIZE initSize);
  43. CSize(POINT initPt);
  44. CSize(DWORD dwSize);
  45. // Operations
  46. BOOL operator==(SIZE size) const;
  47. BOOL operator!=(SIZE size) const;
  48. void operator+=(SIZE size);
  49. void operator-=(SIZE size);
  50. bool operator!() { return !cx && !cy; }
  51. // Operators returning CSize values
  52. CSize operator+(SIZE size) const;
  53. CSize operator-(SIZE size) const;
  54. CSize operator-() const;
  55. // Operators returning CPoint values
  56. CPoint operator+(POINT point) const;
  57. CPoint operator-(POINT point) const;
  58. // Operators returning CRect values
  59. CRect operator+(const RECT* lpRect) const;
  60. CRect operator-(const RECT* lpRect) const;
  61. };
  62. /////////////////////////////////////////////////////////////////////////////
  63. // CPoint - A 2-D point, similar to Windows POINT structure.
  64. class CPoint : public tagPOINT
  65. {
  66. public:
  67. // Constructors
  68. CPoint() {
  69. x = 0;
  70. y = 0;
  71. }
  72. CPoint(int initX, int initY);
  73. CPoint(POINT initPt);
  74. CPoint(SIZE initSize);
  75. CPoint(DWORD dwPoint);
  76. // Operations
  77. void Offset(int xOffset, int yOffset);
  78. void Offset(POINT point);
  79. void Offset(SIZE size);
  80. BOOL operator==(POINT point) const;
  81. BOOL operator!=(POINT point) const;
  82. void operator+=(SIZE size);
  83. void operator-=(SIZE size);
  84. void operator+=(POINT point);
  85. void operator-=(POINT point);
  86. bool operator!() { return !x && !y; }
  87. // Operators returning CPoint values
  88. CPoint operator+(SIZE size) const;
  89. CPoint operator-(SIZE size) const;
  90. CPoint operator-() const;
  91. CPoint operator+(POINT point) const;
  92. // Operators returning CSize values
  93. CSize operator-(POINT point) const;
  94. // Operators returning CRect values
  95. CRect operator+(const RECT* lpRect) const;
  96. CRect operator-(const RECT* lpRect) const;
  97. };
  98. /////////////////////////////////////////////////////////////////////////////
  99. // CRect - A 2-D rectangle, similar to Windows RECT structure.
  100. //typedef const RECT* LPCRECT; // pointer to read/only RECT
  101. class CRect : public tagRECT
  102. {
  103. public:
  104. // Constructors
  105. CRect() {
  106. left = 0;
  107. top = 0;
  108. right = 0;
  109. bottom = 0;
  110. }
  111. CRect(int l, int t, int r, int b);
  112. CRect(const RECT& srcRect);
  113. CRect(LPCRECT lpSrcRect);
  114. CRect(POINT point, SIZE size);
  115. CRect(POINT topLeft, POINT bottomRight);
  116. // Attributes (in addition to RECT members)
  117. int Width() const;
  118. int Height() const;
  119. CSize Size() const;
  120. CPoint& TopLeft();
  121. CPoint& BottomRight();
  122. const CPoint& TopLeft() const;
  123. const CPoint& BottomRight() const;
  124. CPoint CenterPoint() const;
  125. // convert between CRect and LPRECT/LPCRECT (no need for &)
  126. operator LPRECT();
  127. operator LPCRECT() const;
  128. BOOL IsRectEmpty() const;
  129. BOOL IsRectNull() const;
  130. BOOL PtInRect(POINT point) const;
  131. // Operations
  132. void SetRect(int x1, int y1, int x2, int y2);
  133. void SetRect(POINT topLeft, POINT bottomRight);
  134. void SetRectEmpty();
  135. void CopyRect(LPCRECT lpSrcRect);
  136. BOOL EqualRect(LPCRECT lpRect) const;
  137. void InflateRect(int x, int y);
  138. void InflateRect(SIZE size);
  139. void InflateRect(LPCRECT lpRect);
  140. void InflateRect(int l, int t, int r, int b);
  141. void DeflateRect(int x, int y);
  142. void DeflateRect(SIZE size);
  143. void DeflateRect(LPCRECT lpRect);
  144. void DeflateRect(int l, int t, int r, int b);
  145. void OffsetRect(int x, int y);
  146. void OffsetRect(SIZE size);
  147. void OffsetRect(POINT point);
  148. void NormalizeRect();
  149. // operations that fill '*this' with result
  150. BOOL IntersectRect(LPCRECT lpRect1, LPCRECT lpRect2);
  151. BOOL IntersectRect(LPCRECT lpRect2); // use this for rect1
  152. BOOL UnionRect(LPCRECT lpRect1, LPCRECT lpRect2);
  153. BOOL SubtractRect(LPCRECT lpRectSrc1, LPCRECT lpRectSrc2);
  154. // Additional Operations
  155. void operator=(const RECT& srcRect);
  156. BOOL operator==(const RECT& rect) const;
  157. BOOL operator!=(const RECT& rect) const;
  158. bool operator!() { return !left && !top && !right && !bottom; }
  159. void operator+=(POINT point);
  160. void operator+=(SIZE size);
  161. void operator+=(LPCRECT lpRect);
  162. void operator-=(POINT point);
  163. void operator-=(SIZE size);
  164. void operator-=(LPCRECT lpRect);
  165. void operator&=(const RECT& rect);
  166. void operator|=(const RECT& rect);
  167. // Operators returning CRect values
  168. CRect operator+(POINT point) const;
  169. CRect operator-(POINT point) const;
  170. CRect operator+(LPCRECT lpRect) const;
  171. CRect operator+(SIZE size) const;
  172. CRect operator-(SIZE size) const;
  173. CRect operator-(LPCRECT lpRect) const;
  174. CRect operator&(const RECT& rect2) const;
  175. CRect operator|(const RECT& rect2) const;
  176. CRect MulDiv(int nMultiplier, int nDivisor) const;
  177. };
  178. /////////////////////////////////////////////////////////////////////////////
  179. // Strings
  180. #ifndef _ATL_TMP_NO_CSTRING
  181. #ifndef _OLEAUTO_H_
  182. #ifdef OLE2ANSI
  183. typedef LPSTR BSTR;
  184. #else
  185. typedef LPWSTR BSTR; // must (semantically) match typedef in oleauto.h
  186. #endif
  187. #endif
  188. int __stdcall AfxLoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf);
  189. struct CStringData
  190. {
  191. long nRefs; // reference count
  192. int nDataLength;
  193. int nAllocLength;
  194. // TCHAR data[nAllocLength]
  195. TCHAR* data()
  196. { return (TCHAR*)(this+1); }
  197. };
  198. class CString
  199. {
  200. public:
  201. // Constructors
  202. CString();
  203. CString(const CString& stringSrc);
  204. CString(TCHAR ch, int nRepeat = 1);
  205. CString(LPCSTR lpsz);
  206. CString(LPCWSTR lpsz);
  207. CString(LPCTSTR lpch, int nLength);
  208. CString(const unsigned char* psz);
  209. // Attributes & Operations
  210. // as an array of characters
  211. int GetLength() const;
  212. BOOL IsEmpty() const;
  213. void Empty(); // free up the data
  214. TCHAR GetAt(int nIndex) const; // 0 based
  215. TCHAR operator[](int nIndex) const; // same as GetAt
  216. void SetAt(int nIndex, TCHAR ch);
  217. operator LPCTSTR() const; // as a C string
  218. // overloaded assignment
  219. const CString& operator=(const CString& stringSrc);
  220. const CString& operator=(TCHAR ch);
  221. #ifdef _UNICODE
  222. const CString& operator=(char ch);
  223. #endif
  224. const CString& operator=(LPCSTR lpsz);
  225. const CString& operator=(LPCWSTR lpsz);
  226. const CString& operator=(const unsigned char* psz);
  227. // string concatenation
  228. const CString& operator+=(const CString& string);
  229. const CString& operator+=(TCHAR ch);
  230. #ifdef _UNICODE
  231. const CString& operator+=(char ch);
  232. #endif
  233. const CString& operator+=(LPCTSTR lpsz);
  234. friend CString __stdcall operator+(const CString& string1, const CString& string2);
  235. friend CString __stdcall operator+(const CString& string, TCHAR ch);
  236. friend CString __stdcall operator+(TCHAR ch, const CString& string);
  237. #ifdef _UNICODE
  238. friend CString __stdcall operator+(const CString& string, char ch);
  239. friend CString __stdcall operator+(char ch, const CString& string);
  240. #endif
  241. friend CString __stdcall operator+(const CString& string, LPCTSTR lpsz);
  242. friend CString __stdcall operator+(LPCTSTR lpsz, const CString& string);
  243. // string comparison
  244. int Compare(LPCTSTR lpsz) const; // straight character
  245. int CompareNoCase(LPCTSTR lpsz) const; // ignore case
  246. int Collate(LPCTSTR lpsz) const; // NLS aware
  247. // simple sub-string extraction
  248. CString Mid(int nFirst, int nCount) const;
  249. CString Mid(int nFirst) const;
  250. CString Left(int nCount) const;
  251. CString Right(int nCount) const;
  252. CString SpanIncluding(LPCTSTR lpszCharSet) const;
  253. CString SpanExcluding(LPCTSTR lpszCharSet) const;
  254. // upper/lower/reverse conversion
  255. void MakeUpper();
  256. void MakeLower();
  257. void MakeReverse();
  258. // trimming whitespace (either side)
  259. void TrimRight();
  260. void TrimLeft();
  261. // searching (return starting index, or -1 if not found)
  262. // look for a single character match
  263. int Find(TCHAR ch) const; // like "C" strchr
  264. int ReverseFind(TCHAR ch) const;
  265. int FindOneOf(LPCTSTR lpszCharSet) const;
  266. // look for a specific sub-string
  267. int Find(LPCTSTR lpszSub) const; // like "C" strstr
  268. // simple formatting
  269. void __cdecl Format(LPCTSTR lpszFormat, ...);
  270. void __cdecl Format(UINT nFormatID, ...);
  271. // formatting for localization (uses FormatMessage API)
  272. BOOL __cdecl FormatMessage(LPCTSTR lpszFormat, ...);
  273. BOOL __cdecl FormatMessage(UINT nFormatID, ...);
  274. // Windows support
  275. BOOL LoadString(UINT nID); // load from string resource
  276. // 255 chars max
  277. #ifndef _UNICODE
  278. // ANSI <-> OEM support (convert string in place)
  279. void AnsiToOem();
  280. void OemToAnsi();
  281. #endif
  282. #ifndef _ATL_NO_COM
  283. // OLE BSTR support (use for OLE automation)
  284. BSTR AllocSysString() const;
  285. BSTR SetSysString(BSTR* pbstr) const;
  286. #endif //!_ATL_NO_COM
  287. // Access to string implementation buffer as "C" character array
  288. LPTSTR GetBuffer(int nMinBufLength);
  289. void ReleaseBuffer(int nNewLength = -1);
  290. LPTSTR GetBufferSetLength(int nNewLength);
  291. void FreeExtra();
  292. // Use LockBuffer/UnlockBuffer to turn refcounting off
  293. LPTSTR LockBuffer();
  294. void UnlockBuffer();
  295. // Implementation
  296. public:
  297. ~CString();
  298. int GetAllocLength() const;
  299. protected:
  300. LPTSTR m_pchData; // pointer to ref counted string data
  301. // implementation helpers
  302. CStringData* GetData() const;
  303. void Init();
  304. void AllocCopy(CString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const;
  305. BOOL AllocBuffer(int nLen);
  306. void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData);
  307. void ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data);
  308. void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData);
  309. void FormatV(LPCTSTR lpszFormat, va_list argList);
  310. void CopyBeforeWrite();
  311. BOOL AllocBeforeWrite(int nLen);
  312. void Release();
  313. static void PASCAL Release(CStringData* pData);
  314. static int PASCAL SafeStrlen(LPCTSTR lpsz);
  315. };
  316. // Compare helpers
  317. bool __stdcall operator==(const CString& s1, const CString& s2);
  318. bool __stdcall operator==(const CString& s1, LPCTSTR s2);
  319. bool __stdcall operator==(LPCTSTR s1, const CString& s2);
  320. bool __stdcall operator!=(const CString& s1, const CString& s2);
  321. bool __stdcall operator!=(const CString& s1, LPCTSTR s2);
  322. bool __stdcall operator!=(LPCTSTR s1, const CString& s2);
  323. bool __stdcall operator<(const CString& s1, const CString& s2);
  324. bool __stdcall operator<(const CString& s1, LPCTSTR s2);
  325. bool __stdcall operator<(LPCTSTR s1, const CString& s2);
  326. bool __stdcall operator>(const CString& s1, const CString& s2);
  327. bool __stdcall operator>(const CString& s1, LPCTSTR s2);
  328. bool __stdcall operator>(LPCTSTR s1, const CString& s2);
  329. bool __stdcall operator<=(const CString& s1, const CString& s2);
  330. bool __stdcall operator<=(const CString& s1, LPCTSTR s2);
  331. bool __stdcall operator<=(LPCTSTR s1, const CString& s2);
  332. bool __stdcall operator>=(const CString& s1, const CString& s2);
  333. bool __stdcall operator>=(const CString& s1, LPCTSTR s2);
  334. bool __stdcall operator>=(LPCTSTR s1, const CString& s2);
  335. // conversion helpers
  336. int __cdecl _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count);
  337. int __cdecl _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count);
  338. // Globals
  339. // afxChNil is left for backward compatibility
  340. _declspec(selectany) TCHAR afxChNil = '\0';
  341. // For an empty string, m_pchData will point here
  342. // (note: avoids special case of checking for NULL m_pchData)
  343. // empty string data (and locked)
  344. _declspec(selectany) int rgInitData[] = { -1, 0, 0, 0 };
  345. _declspec(selectany) CStringData* afxDataNil = (CStringData*)&rgInitData;
  346. _declspec(selectany) LPCTSTR afxPchNil = (LPCTSTR)(((BYTE*)&rgInitData)+sizeof(CStringData));
  347. inline const CString& __stdcall AfxGetEmptyString()
  348. { return *(CString*)&afxPchNil; }
  349. #define afxEmptyString AfxGetEmptyString()
  350. #endif //!_ATL_TMP_NO_CSTRING
  351. /////////////////////////////////////////////////////////////////////////////
  352. // Implementation
  353. // CSize
  354. inline CSize::CSize() {
  355. cx = 0;
  356. cy = 0;
  357. }
  358. inline CSize::CSize(int initCX, int initCY)
  359. { cx = initCX; cy = initCY; }
  360. inline CSize::CSize(SIZE initSize)
  361. { *(SIZE*)this = initSize; }
  362. inline CSize::CSize(POINT initPt)
  363. { *(POINT*)this = initPt; }
  364. inline CSize::CSize(DWORD dwSize)
  365. {
  366. cx = (short)LOWORD(dwSize);
  367. cy = (short)HIWORD(dwSize);
  368. }
  369. inline BOOL CSize::operator==(SIZE size) const
  370. { return (cx == size.cx && cy == size.cy); }
  371. inline BOOL CSize::operator!=(SIZE size) const
  372. { return (cx != size.cx || cy != size.cy); }
  373. inline void CSize::operator+=(SIZE size)
  374. { cx += size.cx; cy += size.cy; }
  375. inline void CSize::operator-=(SIZE size)
  376. { cx -= size.cx; cy -= size.cy; }
  377. inline CSize CSize::operator+(SIZE size) const
  378. { return CSize(cx + size.cx, cy + size.cy); }
  379. inline CSize CSize::operator-(SIZE size) const
  380. { return CSize(cx - size.cx, cy - size.cy); }
  381. inline CSize CSize::operator-() const
  382. { return CSize(-cx, -cy); }
  383. inline CPoint CSize::operator+(POINT point) const
  384. { return CPoint(cx + point.x, cy + point.y); }
  385. inline CPoint CSize::operator-(POINT point) const
  386. { return CPoint(cx - point.x, cy - point.y); }
  387. inline CRect CSize::operator+(const RECT* lpRect) const
  388. { return CRect(lpRect) + *this; }
  389. inline CRect CSize::operator-(const RECT* lpRect) const
  390. { return CRect(lpRect) - *this; }
  391. // CPoint
  392. inline CPoint::CPoint(int initX, int initY)
  393. { x = initX; y = initY; }
  394. inline CPoint::CPoint(POINT initPt)
  395. { *(POINT*)this = initPt; }
  396. inline CPoint::CPoint(SIZE initSize)
  397. { *(SIZE*)this = initSize; }
  398. inline CPoint::CPoint(DWORD dwPoint)
  399. {
  400. x = (short)LOWORD(dwPoint);
  401. y = (short)HIWORD(dwPoint);
  402. }
  403. inline void CPoint::Offset(int xOffset, int yOffset)
  404. { x += xOffset; y += yOffset; }
  405. inline void CPoint::Offset(POINT point)
  406. { x += point.x; y += point.y; }
  407. inline void CPoint::Offset(SIZE size)
  408. { x += size.cx; y += size.cy; }
  409. inline BOOL CPoint::operator==(POINT point) const
  410. { return (x == point.x && y == point.y); }
  411. inline BOOL CPoint::operator!=(POINT point) const
  412. { return (x != point.x || y != point.y); }
  413. inline void CPoint::operator+=(SIZE size)
  414. { x += size.cx; y += size.cy; }
  415. inline void CPoint::operator-=(SIZE size)
  416. { x -= size.cx; y -= size.cy; }
  417. inline void CPoint::operator+=(POINT point)
  418. { x += point.x; y += point.y; }
  419. inline void CPoint::operator-=(POINT point)
  420. { x -= point.x; y -= point.y; }
  421. inline CPoint CPoint::operator+(SIZE size) const
  422. { return CPoint(x + size.cx, y + size.cy); }
  423. inline CPoint CPoint::operator-(SIZE size) const
  424. { return CPoint(x - size.cx, y - size.cy); }
  425. inline CPoint CPoint::operator-() const
  426. { return CPoint(-x, -y); }
  427. inline CPoint CPoint::operator+(POINT point) const
  428. { return CPoint(x + point.x, y + point.y); }
  429. inline CSize CPoint::operator-(POINT point) const
  430. { return CSize(x - point.x, y - point.y); }
  431. inline CRect CPoint::operator+(const RECT* lpRect) const
  432. { return CRect(lpRect) + *this; }
  433. inline CRect CPoint::operator-(const RECT* lpRect) const
  434. { return CRect(lpRect) - *this; }
  435. // CRect
  436. inline CRect::CRect(int l, int t, int r, int b)
  437. { left = l; top = t; right = r; bottom = b; }
  438. inline CRect::CRect(const RECT& srcRect)
  439. { ::CopyRect(this, &srcRect); }
  440. inline CRect::CRect(LPCRECT lpSrcRect)
  441. { ::CopyRect(this, lpSrcRect); }
  442. inline CRect::CRect(POINT point, SIZE size)
  443. { right = (left = point.x) + size.cx; bottom = (top = point.y) + size.cy; }
  444. inline CRect::CRect(POINT topLeft, POINT bottomRight)
  445. { left = topLeft.x; top = topLeft.y;
  446. right = bottomRight.x; bottom = bottomRight.y; }
  447. inline int CRect::Width() const
  448. { return right - left; }
  449. inline int CRect::Height() const
  450. { return bottom - top; }
  451. inline CSize CRect::Size() const
  452. { return CSize(right - left, bottom - top); }
  453. inline CPoint& CRect::TopLeft()
  454. { return *((CPoint*)this); }
  455. inline CPoint& CRect::BottomRight()
  456. { return *((CPoint*)this+1); }
  457. inline const CPoint& CRect::TopLeft() const
  458. { return *((CPoint*)this); }
  459. inline const CPoint& CRect::BottomRight() const
  460. { return *((CPoint*)this+1); }
  461. inline CPoint CRect::CenterPoint() const
  462. { return CPoint((left+right)/2, (top+bottom)/2); }
  463. inline CRect::operator LPRECT()
  464. { return this; }
  465. inline CRect::operator LPCRECT() const
  466. { return this; }
  467. inline BOOL CRect::IsRectEmpty() const
  468. { return ::IsRectEmpty(this); }
  469. inline BOOL CRect::IsRectNull() const
  470. { return (left == 0 && right == 0 && top == 0 && bottom == 0); }
  471. inline BOOL CRect::PtInRect(POINT point) const
  472. { return ::PtInRect(this, point); }
  473. inline void CRect::SetRect(int x1, int y1, int x2, int y2)
  474. { ::SetRect(this, x1, y1, x2, y2); }
  475. inline void CRect::SetRect(POINT topLeft, POINT bottomRight)
  476. { ::SetRect(this, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y); }
  477. inline void CRect::SetRectEmpty()
  478. { ::SetRectEmpty(this); }
  479. inline void CRect::CopyRect(LPCRECT lpSrcRect)
  480. { ::CopyRect(this, lpSrcRect); }
  481. inline BOOL CRect::EqualRect(LPCRECT lpRect) const
  482. { return ::EqualRect(this, lpRect); }
  483. inline void CRect::InflateRect(int x, int y)
  484. { ::InflateRect(this, x, y); }
  485. inline void CRect::InflateRect(SIZE size)
  486. { ::InflateRect(this, size.cx, size.cy); }
  487. inline void CRect::DeflateRect(int x, int y)
  488. { ::InflateRect(this, -x, -y); }
  489. inline void CRect::DeflateRect(SIZE size)
  490. { ::InflateRect(this, -size.cx, -size.cy); }
  491. inline void CRect::OffsetRect(int x, int y)
  492. { ::OffsetRect(this, x, y); }
  493. inline void CRect::OffsetRect(POINT point)
  494. { ::OffsetRect(this, point.x, point.y); }
  495. inline void CRect::OffsetRect(SIZE size)
  496. { ::OffsetRect(this, size.cx, size.cy); }
  497. inline BOOL CRect::IntersectRect(LPCRECT lpRect1, LPCRECT lpRect2)
  498. { return ::IntersectRect(this, lpRect1, lpRect2);}
  499. inline BOOL CRect::IntersectRect(LPCRECT lpRect2)
  500. { return ::IntersectRect(this, this, lpRect2);}
  501. inline BOOL CRect::UnionRect(LPCRECT lpRect1, LPCRECT lpRect2)
  502. { return ::UnionRect(this, lpRect1, lpRect2); }
  503. inline void CRect::operator=(const RECT& srcRect)
  504. { ::CopyRect(this, &srcRect); }
  505. inline BOOL CRect::operator==(const RECT& rect) const
  506. { return ::EqualRect(this, &rect); }
  507. inline BOOL CRect::operator!=(const RECT& rect) const
  508. { return !::EqualRect(this, &rect); }
  509. inline void CRect::operator+=(POINT point)
  510. { ::OffsetRect(this, point.x, point.y); }
  511. inline void CRect::operator+=(SIZE size)
  512. { ::OffsetRect(this, size.cx, size.cy); }
  513. inline void CRect::operator+=(LPCRECT lpRect)
  514. { InflateRect(lpRect); }
  515. inline void CRect::operator-=(POINT point)
  516. { ::OffsetRect(this, -point.x, -point.y); }
  517. inline void CRect::operator-=(SIZE size)
  518. { ::OffsetRect(this, -size.cx, -size.cy); }
  519. inline void CRect::operator-=(LPCRECT lpRect)
  520. { DeflateRect(lpRect); }
  521. inline void CRect::operator&=(const RECT& rect)
  522. { ::IntersectRect(this, this, &rect); }
  523. inline void CRect::operator|=(const RECT& rect)
  524. { ::UnionRect(this, this, &rect); }
  525. inline CRect CRect::operator+(POINT pt) const
  526. { CRect rect(*this); ::OffsetRect(&rect, pt.x, pt.y); return rect; }
  527. inline CRect CRect::operator-(POINT pt) const
  528. { CRect rect(*this); ::OffsetRect(&rect, -pt.x, -pt.y); return rect; }
  529. inline CRect CRect::operator+(SIZE size) const
  530. { CRect rect(*this); ::OffsetRect(&rect, size.cx, size.cy); return rect; }
  531. inline CRect CRect::operator-(SIZE size) const
  532. { CRect rect(*this); ::OffsetRect(&rect, -size.cx, -size.cy); return rect; }
  533. inline CRect CRect::operator+(LPCRECT lpRect) const
  534. { CRect rect(this); rect.InflateRect(lpRect); return rect; }
  535. inline CRect CRect::operator-(LPCRECT lpRect) const
  536. { CRect rect(this); rect.DeflateRect(lpRect); return rect; }
  537. inline CRect CRect::operator&(const RECT& rect2) const
  538. { CRect rect; ::IntersectRect(&rect, this, &rect2);
  539. return rect; }
  540. inline CRect CRect::operator|(const RECT& rect2) const
  541. { CRect rect; ::UnionRect(&rect, this, &rect2);
  542. return rect; }
  543. inline BOOL CRect::SubtractRect(LPCRECT lpRectSrc1, LPCRECT lpRectSrc2)
  544. { return ::SubtractRect(this, lpRectSrc1, lpRectSrc2); }
  545. inline void CRect::NormalizeRect()
  546. {
  547. int nTemp;
  548. if (left > right)
  549. {
  550. nTemp = left;
  551. left = right;
  552. right = nTemp;
  553. }
  554. if (top > bottom)
  555. {
  556. nTemp = top;
  557. top = bottom;
  558. bottom = nTemp;
  559. }
  560. }
  561. inline void CRect::InflateRect(LPCRECT lpRect)
  562. {
  563. left -= lpRect->left;
  564. top -= lpRect->top;
  565. right += lpRect->right;
  566. bottom += lpRect->bottom;
  567. }
  568. inline void CRect::InflateRect(int l, int t, int r, int b)
  569. {
  570. left -= l;
  571. top -= t;
  572. right += r;
  573. bottom += b;
  574. }
  575. inline void CRect::DeflateRect(LPCRECT lpRect)
  576. {
  577. left += lpRect->left;
  578. top += lpRect->top;
  579. right -= lpRect->right;
  580. bottom -= lpRect->bottom;
  581. }
  582. inline void CRect::DeflateRect(int l, int t, int r, int b)
  583. {
  584. left += l;
  585. top += t;
  586. right -= r;
  587. bottom -= b;
  588. }
  589. inline CRect CRect::MulDiv(int nMultiplier, int nDivisor) const
  590. {
  591. return CRect(
  592. ::MulDiv(left, nMultiplier, nDivisor),
  593. ::MulDiv(top, nMultiplier, nDivisor),
  594. ::MulDiv(right, nMultiplier, nDivisor),
  595. ::MulDiv(bottom, nMultiplier, nDivisor));
  596. }
  597. #ifndef _ATL_TMP_NO_CSTRING
  598. // CString
  599. inline CStringData* CString::GetData() const
  600. { ATLASSERT(m_pchData != NULL); return ((CStringData*)m_pchData)-1; }
  601. inline void CString::Init()
  602. { m_pchData = afxEmptyString.m_pchData; }
  603. inline CString::CString(const unsigned char* lpsz)
  604. { Init(); *this = (LPCSTR)lpsz; }
  605. inline const CString& CString::operator=(const unsigned char* lpsz)
  606. { *this = (LPCSTR)lpsz; return *this; }
  607. #ifdef _UNICODE
  608. inline const CString& CString::operator+=(char ch)
  609. { *this += (TCHAR)ch; return *this; }
  610. inline const CString& CString::operator=(char ch)
  611. { *this = (TCHAR)ch; return *this; }
  612. inline CString __stdcall operator+(const CString& string, char ch)
  613. { return string + (TCHAR)ch; }
  614. inline CString __stdcall operator+(char ch, const CString& string)
  615. { return (TCHAR)ch + string; }
  616. #endif
  617. inline int CString::GetLength() const
  618. { return GetData()->nDataLength; }
  619. inline int CString::GetAllocLength() const
  620. { return GetData()->nAllocLength; }
  621. inline BOOL CString::IsEmpty() const
  622. { return GetData()->nDataLength == 0; }
  623. inline CString::operator LPCTSTR() const
  624. { return m_pchData; }
  625. inline int PASCAL CString::SafeStrlen(LPCTSTR lpsz)
  626. { return (lpsz == NULL) ? 0 : lstrlen(lpsz); }
  627. // CString support (windows specific)
  628. inline int CString::Compare(LPCTSTR lpsz) const
  629. { return _tcscmp(m_pchData, lpsz); } // MBCS/Unicode aware
  630. inline int CString::CompareNoCase(LPCTSTR lpsz) const
  631. { return _tcsicmp(m_pchData, lpsz); } // MBCS/Unicode aware
  632. // CString::Collate is often slower than Compare but is MBSC/Unicode
  633. // aware as well as locale-sensitive with respect to sort order.
  634. inline int CString::Collate(LPCTSTR lpsz) const
  635. { return _tcscoll(m_pchData, lpsz); } // locale sensitive
  636. inline TCHAR CString::GetAt(int nIndex) const
  637. {
  638. ATLASSERT(nIndex >= 0);
  639. ATLASSERT(nIndex < GetData()->nDataLength);
  640. return m_pchData[nIndex];
  641. }
  642. inline TCHAR CString::operator[](int nIndex) const
  643. {
  644. // same as GetAt
  645. ATLASSERT(nIndex >= 0);
  646. ATLASSERT(nIndex < GetData()->nDataLength);
  647. return m_pchData[nIndex];
  648. }
  649. inline bool __stdcall operator==(const CString& s1, const CString& s2)
  650. { return s1.Compare(s2) == 0; }
  651. inline bool __stdcall operator==(const CString& s1, LPCTSTR s2)
  652. { return s1.Compare(s2) == 0; }
  653. inline bool __stdcall operator==(LPCTSTR s1, const CString& s2)
  654. { return s2.Compare(s1) == 0; }
  655. inline bool __stdcall operator!=(const CString& s1, const CString& s2)
  656. { return s1.Compare(s2) != 0; }
  657. inline bool __stdcall operator!=(const CString& s1, LPCTSTR s2)
  658. { return s1.Compare(s2) != 0; }
  659. inline bool __stdcall operator!=(LPCTSTR s1, const CString& s2)
  660. { return s2.Compare(s1) != 0; }
  661. inline bool __stdcall operator<(const CString& s1, const CString& s2)
  662. { return s1.Compare(s2) < 0; }
  663. inline bool __stdcall operator<(const CString& s1, LPCTSTR s2)
  664. { return s1.Compare(s2) < 0; }
  665. inline bool __stdcall operator<(LPCTSTR s1, const CString& s2)
  666. { return s2.Compare(s1) > 0; }
  667. inline bool __stdcall operator>(const CString& s1, const CString& s2)
  668. { return s1.Compare(s2) > 0; }
  669. inline bool __stdcall operator>(const CString& s1, LPCTSTR s2)
  670. { return s1.Compare(s2) > 0; }
  671. inline bool __stdcall operator>(LPCTSTR s1, const CString& s2)
  672. { return s2.Compare(s1) < 0; }
  673. inline bool __stdcall operator<=(const CString& s1, const CString& s2)
  674. { return s1.Compare(s2) <= 0; }
  675. inline bool __stdcall operator<=(const CString& s1, LPCTSTR s2)
  676. { return s1.Compare(s2) <= 0; }
  677. inline bool __stdcall operator<=(LPCTSTR s1, const CString& s2)
  678. { return s2.Compare(s1) >= 0; }
  679. inline bool __stdcall operator>=(const CString& s1, const CString& s2)
  680. { return s1.Compare(s2) >= 0; }
  681. inline bool __stdcall operator>=(const CString& s1, LPCTSTR s2)
  682. { return s1.Compare(s2) >= 0; }
  683. inline bool __stdcall operator>=(LPCTSTR s1, const CString& s2)
  684. { return s2.Compare(s1) <= 0; }
  685. inline BOOL __stdcall AfxIsValidString(LPCWSTR lpsz, int nLength)
  686. {
  687. if(lpsz == NULL)
  688. return FALSE;
  689. return !::IsBadStringPtrW(lpsz, nLength);
  690. }
  691. inline BOOL __stdcall AfxIsValidString(LPCSTR lpsz, int nLength)
  692. {
  693. if(lpsz == NULL)
  694. return FALSE;
  695. return !::IsBadStringPtrA(lpsz, nLength);
  696. }
  697. inline BOOL __stdcall AfxIsValidAddress(const void* lp, UINT nBytes, BOOL bReadWrite = TRUE)
  698. {
  699. // simple version using Win-32 APIs for pointer validation.
  700. return (lp != NULL && !IsBadReadPtr(lp, nBytes) &&
  701. (!bReadWrite || !IsBadWritePtr((LPVOID)lp, nBytes)));
  702. }
  703. inline CString::CString()
  704. {
  705. Init();
  706. }
  707. inline CString::CString(const CString& stringSrc)
  708. {
  709. ATLASSERT(stringSrc.GetData()->nRefs != 0);
  710. if (stringSrc.GetData()->nRefs >= 0)
  711. {
  712. ATLASSERT(stringSrc.GetData() != afxDataNil);
  713. m_pchData = stringSrc.m_pchData;
  714. InterlockedIncrement(&GetData()->nRefs);
  715. }
  716. else
  717. {
  718. Init();
  719. *this = stringSrc.m_pchData;
  720. }
  721. }
  722. inline BOOL CString::AllocBuffer(int nLen)
  723. // always allocate one extra character for '\0' termination
  724. // assumes [optimistically] that data length will equal allocation length
  725. {
  726. ATLASSERT(nLen >= 0);
  727. ATLASSERT(nLen <= INT_MAX-1); // max size (enough room for 1 extra)
  728. if (nLen == 0)
  729. Init();
  730. else
  731. {
  732. CStringData* pData = NULL;
  733. ATLTRY(pData = (CStringData*)new BYTE[sizeof(CStringData) + (nLen+1)*sizeof(TCHAR)]);
  734. if(pData == NULL)
  735. return FALSE;
  736. pData->nRefs = 1;
  737. pData->data()[nLen] = '\0';
  738. pData->nDataLength = nLen;
  739. pData->nAllocLength = nLen;
  740. m_pchData = pData->data();
  741. }
  742. return TRUE;
  743. }
  744. inline void CString::Release()
  745. {
  746. if (GetData() != afxDataNil)
  747. {
  748. ATLASSERT(GetData()->nRefs != 0);
  749. if (InterlockedDecrement(&GetData()->nRefs) <= 0)
  750. delete[] (BYTE*)GetData();
  751. Init();
  752. }
  753. }
  754. inline void PASCAL CString::Release(CStringData* pData)
  755. {
  756. if (pData != afxDataNil)
  757. {
  758. ATLASSERT(pData->nRefs != 0);
  759. if (InterlockedDecrement(&pData->nRefs) <= 0)
  760. delete[] (BYTE*)pData;
  761. }
  762. }
  763. inline void CString::Empty()
  764. {
  765. if (GetData()->nDataLength == 0)
  766. return;
  767. if (GetData()->nRefs >= 0)
  768. Release();
  769. else
  770. *this = &afxChNil;
  771. ATLASSERT(GetData()->nDataLength == 0);
  772. ATLASSERT(GetData()->nRefs < 0 || GetData()->nAllocLength == 0);
  773. }
  774. inline void CString::CopyBeforeWrite()
  775. {
  776. if (GetData()->nRefs > 1)
  777. {
  778. CStringData* pData = GetData();
  779. Release();
  780. if(AllocBuffer(pData->nDataLength))
  781. memcpy(m_pchData, pData->data(), (pData->nDataLength+1)*sizeof(TCHAR));
  782. }
  783. ATLASSERT(GetData()->nRefs <= 1);
  784. }
  785. inline BOOL CString::AllocBeforeWrite(int nLen)
  786. {
  787. BOOL bRet = TRUE;
  788. if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength)
  789. {
  790. Release();
  791. bRet = AllocBuffer(nLen);
  792. }
  793. ATLASSERT(GetData()->nRefs <= 1);
  794. return bRet;
  795. }
  796. inline CString::~CString()
  797. // free any attached data
  798. {
  799. if (GetData() != afxDataNil)
  800. {
  801. if (InterlockedDecrement(&GetData()->nRefs) <= 0)
  802. delete[] (BYTE*)GetData();
  803. }
  804. }
  805. inline void CString::AllocCopy(CString& dest, int nCopyLen, int nCopyIndex,
  806. int nExtraLen) const
  807. {
  808. // will clone the data attached to this string
  809. // allocating 'nExtraLen' characters
  810. // Places results in uninitialized string 'dest'
  811. // Will copy the part or all of original data to start of new string
  812. int nNewLen = nCopyLen + nExtraLen;
  813. if (nNewLen == 0)
  814. {
  815. dest.Init();
  816. }
  817. else
  818. {
  819. if(dest.AllocBuffer(nNewLen))
  820. memcpy(dest.m_pchData, m_pchData+nCopyIndex, nCopyLen*sizeof(TCHAR));
  821. }
  822. }
  823. inline CString::CString(LPCTSTR lpsz)
  824. {
  825. Init();
  826. if (lpsz != NULL && HIWORD(lpsz) == NULL)
  827. {
  828. UINT nID = LOWORD((DWORD_PTR)lpsz);
  829. if (!LoadString(nID))
  830. #if (_ATL_VER >= 0x0300)
  831. ATLTRACE2(atlTraceGeneral, 0, _T("Warning: implicit LoadString(%u) in CString failed\n"), nID);
  832. #else
  833. ATLTRACE2(atlTraceGeneral, 0, _T("Warning: implicit LoadString in CString failed\n"));
  834. #endif //(_ATL_VER >= 0x0300)
  835. }
  836. else
  837. {
  838. int nLen = SafeStrlen(lpsz);
  839. if (nLen != 0)
  840. {
  841. if(AllocBuffer(nLen))
  842. memcpy(m_pchData, lpsz, nLen*sizeof(TCHAR));
  843. }
  844. }
  845. }
  846. #ifdef _UNICODE
  847. inline CString::CString(LPCSTR lpsz)
  848. {
  849. Init();
  850. int nSrcLen = lpsz != NULL ? lstrlenA(lpsz) : 0;
  851. if (nSrcLen != 0)
  852. {
  853. if(AllocBuffer(nSrcLen))
  854. {
  855. _mbstowcsz(m_pchData, lpsz, nSrcLen+1);
  856. ReleaseBuffer();
  857. }
  858. }
  859. }
  860. #else //_UNICODE
  861. inline CString::CString(LPCWSTR lpsz)
  862. {
  863. Init();
  864. int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
  865. if (nSrcLen != 0)
  866. {
  867. if(AllocBuffer(nSrcLen*2))
  868. {
  869. _wcstombsz(m_pchData, lpsz, (nSrcLen*2)+1);
  870. ReleaseBuffer();
  871. }
  872. }
  873. }
  874. #endif //!_UNICODE
  875. // Assignment operators
  876. // All assign a new value to the string
  877. // (a) first see if the buffer is big enough
  878. // (b) if enough room, copy on top of old buffer, set size and type
  879. // (c) otherwise free old string data, and create a new one
  880. //
  881. // All routines return the new string (but as a 'const CString&' so that
  882. // assigning it again will cause a copy, eg: s1 = s2 = "hi there".
  883. //
  884. inline void CString::AssignCopy(int nSrcLen, LPCTSTR lpszSrcData)
  885. {
  886. if(AllocBeforeWrite(nSrcLen))
  887. {
  888. memcpy(m_pchData, lpszSrcData, nSrcLen*sizeof(TCHAR));
  889. GetData()->nDataLength = nSrcLen;
  890. m_pchData[nSrcLen] = '\0';
  891. }
  892. }
  893. inline const CString& CString::operator=(const CString& stringSrc)
  894. {
  895. if (m_pchData != stringSrc.m_pchData)
  896. {
  897. if ((GetData()->nRefs < 0 && GetData() != afxDataNil) ||
  898. stringSrc.GetData()->nRefs < 0)
  899. {
  900. // actual copy necessary since one of the strings is locked
  901. AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData);
  902. }
  903. else
  904. {
  905. // can just copy references around
  906. Release();
  907. ATLASSERT(stringSrc.GetData() != afxDataNil);
  908. m_pchData = stringSrc.m_pchData;
  909. InterlockedIncrement(&GetData()->nRefs);
  910. }
  911. }
  912. return *this;
  913. }
  914. inline const CString& CString::operator=(LPCTSTR lpsz)
  915. {
  916. ATLASSERT(lpsz == NULL || AfxIsValidString(lpsz, FALSE));
  917. AssignCopy(SafeStrlen(lpsz), lpsz);
  918. return *this;
  919. }
  920. #ifdef _UNICODE
  921. inline const CString& CString::operator=(LPCSTR lpsz)
  922. {
  923. int nSrcLen = lpsz != NULL ? lstrlenA(lpsz) : 0;
  924. if(AllocBeforeWrite(nSrcLen))
  925. {
  926. _mbstowcsz(m_pchData, lpsz, nSrcLen+1);
  927. ReleaseBuffer();
  928. }
  929. return *this;
  930. }
  931. #else //!_UNICODE
  932. inline const CString& CString::operator=(LPCWSTR lpsz)
  933. {
  934. int nSrcLen = lpsz != NULL ? wcslen(lpsz) : 0;
  935. if(AllocBeforeWrite(nSrcLen*2))
  936. {
  937. _wcstombsz(m_pchData, lpsz, (nSrcLen*2)+1);
  938. ReleaseBuffer();
  939. }
  940. return *this;
  941. }
  942. #endif //!_UNICODE
  943. // Concatenation
  944. // NOTE: "operator+" is done as friend functions for simplicity
  945. // There are three variants:
  946. // CString + CString
  947. // and for ? = TCHAR, LPCTSTR
  948. // CString + ?
  949. // ? + CString
  950. inline void CString::ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data,
  951. int nSrc2Len, LPCTSTR lpszSrc2Data)
  952. {
  953. // -- master concatenation routine
  954. // Concatenate two sources
  955. // -- assume that 'this' is a new CString object
  956. int nNewLen = nSrc1Len + nSrc2Len;
  957. if (nNewLen != 0)
  958. {
  959. if(AllocBuffer(nNewLen))
  960. {
  961. memcpy(m_pchData, lpszSrc1Data, nSrc1Len*sizeof(TCHAR));
  962. memcpy(m_pchData+nSrc1Len, lpszSrc2Data, nSrc2Len*sizeof(TCHAR));
  963. }
  964. }
  965. }
  966. inline CString __stdcall operator+(const CString& string1, const CString& string2)
  967. {
  968. CString s;
  969. s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData,
  970. string2.GetData()->nDataLength, string2.m_pchData);
  971. return s;
  972. }
  973. inline CString __stdcall operator+(const CString& string, LPCTSTR lpsz)
  974. {
  975. ATLASSERT(lpsz == NULL || AfxIsValidString(lpsz, FALSE));
  976. CString s;
  977. s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData,
  978. CString::SafeStrlen(lpsz), lpsz);
  979. return s;
  980. }
  981. inline CString __stdcall operator+(LPCTSTR lpsz, const CString& string)
  982. {
  983. ATLASSERT(lpsz == NULL || AfxIsValidString(lpsz, FALSE));
  984. CString s;
  985. s.ConcatCopy(CString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength,
  986. string.m_pchData);
  987. return s;
  988. }
  989. inline void CString::ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData)
  990. {
  991. // -- the main routine for += operators
  992. // concatenating an empty string is a no-op!
  993. if (nSrcLen == 0)
  994. return;
  995. // if the buffer is too small, or we have a width mis-match, just
  996. // allocate a new buffer (slow but sure)
  997. if (GetData()->nRefs > 1 || GetData()->nDataLength + nSrcLen > GetData()->nAllocLength)
  998. {
  999. // we have to grow the buffer, use the ConcatCopy routine
  1000. CStringData* pOldData = GetData();
  1001. ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData);
  1002. ATLASSERT(pOldData != NULL);
  1003. CString::Release(pOldData);
  1004. }
  1005. else
  1006. {
  1007. // fast concatenation when buffer big enough
  1008. memcpy(m_pchData+GetData()->nDataLength, lpszSrcData, nSrcLen*sizeof(TCHAR));
  1009. GetData()->nDataLength += nSrcLen;
  1010. ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
  1011. m_pchData[GetData()->nDataLength] = '\0';
  1012. }
  1013. }
  1014. inline const CString& CString::operator+=(LPCTSTR lpsz)
  1015. {
  1016. ATLASSERT(lpsz == NULL || AfxIsValidString(lpsz, FALSE));
  1017. ConcatInPlace(SafeStrlen(lpsz), lpsz);
  1018. return *this;
  1019. }
  1020. inline const CString& CString::operator+=(TCHAR ch)
  1021. {
  1022. ConcatInPlace(1, &ch);
  1023. return *this;
  1024. }
  1025. inline const CString& CString::operator+=(const CString& string)
  1026. {
  1027. ConcatInPlace(string.GetData()->nDataLength, string.m_pchData);
  1028. return *this;
  1029. }
  1030. inline LPTSTR CString::GetBuffer(int nMinBufLength)
  1031. {
  1032. ATLASSERT(nMinBufLength >= 0);
  1033. if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength)
  1034. {
  1035. // we have to grow the buffer
  1036. CStringData* pOldData = GetData();
  1037. int nOldLen = GetData()->nDataLength; // AllocBuffer will tromp it
  1038. if (nMinBufLength < nOldLen)
  1039. nMinBufLength = nOldLen;
  1040. if(AllocBuffer(nMinBufLength))
  1041. {
  1042. memcpy(m_pchData, pOldData->data(), (nOldLen+1)*sizeof(TCHAR));
  1043. GetData()->nDataLength = nOldLen;
  1044. CString::Release(pOldData);
  1045. }
  1046. }
  1047. ATLASSERT(GetData()->nRefs <= 1);
  1048. // return a pointer to the character storage for this string
  1049. ATLASSERT(m_pchData != NULL);
  1050. return m_pchData;
  1051. }
  1052. inline void CString::ReleaseBuffer(int nNewLength)
  1053. {
  1054. CopyBeforeWrite(); // just in case GetBuffer was not called
  1055. if (nNewLength == -1)
  1056. nNewLength = lstrlen(m_pchData); // zero terminated
  1057. ATLASSERT(nNewLength <= GetData()->nAllocLength);
  1058. GetData()->nDataLength = nNewLength;
  1059. m_pchData[nNewLength] = '\0';
  1060. }
  1061. inline LPTSTR CString::GetBufferSetLength(int nNewLength)
  1062. {
  1063. ATLASSERT(nNewLength >= 0);
  1064. GetBuffer(nNewLength);
  1065. GetData()->nDataLength = nNewLength;
  1066. m_pchData[nNewLength] = '\0';
  1067. return m_pchData;
  1068. }
  1069. inline void CString::FreeExtra()
  1070. {
  1071. ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength);
  1072. if (GetData()->nDataLength != GetData()->nAllocLength)
  1073. {
  1074. CStringData* pOldData = GetData();
  1075. if(AllocBuffer(GetData()->nDataLength))
  1076. {
  1077. memcpy(m_pchData, pOldData->data(), pOldData->nDataLength*sizeof(TCHAR));
  1078. ATLASSERT(m_pchData[GetData()->nDataLength] == '\0');
  1079. CString::Release(pOldData);
  1080. }
  1081. }
  1082. ATLASSERT(GetData() != NULL);
  1083. }
  1084. inline LPTSTR CString::LockBuffer()
  1085. {
  1086. LPTSTR lpsz = GetBuffer(0);
  1087. GetData()->nRefs = -1;
  1088. return lpsz;
  1089. }
  1090. inline void CString::UnlockBuffer()
  1091. {
  1092. ATLASSERT(GetData()->nRefs == -1);
  1093. if (GetData() != afxDataNil)
  1094. GetData()->nRefs = 1;
  1095. }
  1096. inline int CString::Find(TCHAR ch) const
  1097. {
  1098. // find first single character
  1099. LPTSTR lpsz = _tcschr(m_pchData, (_TUCHAR)ch);
  1100. // return -1 if not found and index otherwise
  1101. return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
  1102. }
  1103. inline int CString::FindOneOf(LPCTSTR lpszCharSet) const
  1104. {
  1105. ATLASSERT(AfxIsValidString(lpszCharSet, FALSE));
  1106. LPTSTR lpsz = _tcspbrk(m_pchData, lpszCharSet);
  1107. return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
  1108. }
  1109. inline void CString::MakeUpper()
  1110. {
  1111. CopyBeforeWrite();
  1112. _tcsupr(m_pchData);
  1113. }
  1114. inline void CString::MakeLower()
  1115. {
  1116. CopyBeforeWrite();
  1117. _tcslwr(m_pchData);
  1118. }
  1119. inline void CString::MakeReverse()
  1120. {
  1121. CopyBeforeWrite();
  1122. _tcsrev(m_pchData);
  1123. }
  1124. inline void CString::SetAt(int nIndex, TCHAR ch)
  1125. {
  1126. ATLASSERT(nIndex >= 0);
  1127. ATLASSERT(nIndex < GetData()->nDataLength);
  1128. CopyBeforeWrite();
  1129. m_pchData[nIndex] = ch;
  1130. }
  1131. #ifndef _UNICODE
  1132. inline void CString::AnsiToOem()
  1133. {
  1134. CopyBeforeWrite();
  1135. ::AnsiToOem(m_pchData, m_pchData);
  1136. }
  1137. inline void CString::OemToAnsi()
  1138. {
  1139. CopyBeforeWrite();
  1140. ::OemToAnsi(m_pchData, m_pchData);
  1141. }
  1142. #endif
  1143. // CString conversion helpers (these use the current system locale)
  1144. inline int __cdecl _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count)
  1145. {
  1146. if (count == 0 && mbstr != NULL)
  1147. return 0;
  1148. int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1,
  1149. mbstr, count, NULL, NULL);
  1150. ATLASSERT(mbstr == NULL || result <= (int)count);
  1151. if (result > 0)
  1152. mbstr[result-1] = 0;
  1153. return result;
  1154. }
  1155. inline int __cdecl _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count)
  1156. {
  1157. if (count == 0 && wcstr != NULL)
  1158. return 0;
  1159. int result = ::MultiByteToWideChar(CP_ACP, 0, mbstr, -1,
  1160. wcstr, count);
  1161. ATLASSERT(wcstr == NULL || result <= (int)count);
  1162. if (result > 0)
  1163. wcstr[result-1] = 0;
  1164. return result;
  1165. }
  1166. inline CString::CString(TCHAR ch, int nLength)
  1167. {
  1168. ATLASSERT(!_istlead(ch)); // can't create a lead byte string
  1169. Init();
  1170. if (nLength >= 1)
  1171. {
  1172. if(AllocBuffer(nLength))
  1173. {
  1174. #ifdef _UNICODE
  1175. for (int i = 0; i < nLength; i++)
  1176. m_pchData[i] = ch;
  1177. #else
  1178. memset(m_pchData, ch, nLength);
  1179. #endif
  1180. }
  1181. }
  1182. }
  1183. inline CString::CString(LPCTSTR lpch, int nLength)
  1184. {
  1185. Init();
  1186. if (nLength != 0)
  1187. {
  1188. ATLASSERT(AfxIsValidAddress(lpch, nLength, FALSE));
  1189. if(AllocBuffer(nLength))
  1190. memcpy(m_pchData, lpch, nLength*sizeof(TCHAR));
  1191. }
  1192. }
  1193. inline const CString& CString::operator=(TCHAR ch)
  1194. {
  1195. ATLASSERT(!_istlead(ch)); // can't set single lead byte
  1196. AssignCopy(1, &ch);
  1197. return *this;
  1198. }
  1199. inline CString __stdcall operator+(const CString& string1, TCHAR ch)
  1200. {
  1201. CString s;
  1202. s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, 1, &ch);
  1203. return s;
  1204. }
  1205. inline CString __stdcall operator+(TCHAR ch, const CString& string)
  1206. {
  1207. CString s;
  1208. s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData);
  1209. return s;
  1210. }
  1211. inline CString CString::Mid(int nFirst) const
  1212. {
  1213. return Mid(nFirst, GetData()->nDataLength - nFirst);
  1214. }
  1215. inline CString CString::Mid(int nFirst, int nCount) const
  1216. {
  1217. // out-of-bounds requests return sensible things
  1218. if (nFirst < 0)
  1219. nFirst = 0;
  1220. if (nCount < 0)
  1221. nCount = 0;
  1222. if (nFirst + nCount > GetData()->nDataLength)
  1223. nCount = GetData()->nDataLength - nFirst;
  1224. if (nFirst > GetData()->nDataLength)
  1225. nCount = 0;
  1226. CString dest;
  1227. AllocCopy(dest, nCount, nFirst, 0);
  1228. return dest;
  1229. }
  1230. inline CString CString::Right(int nCount) const
  1231. {
  1232. if (nCount < 0)
  1233. nCount = 0;
  1234. else if (nCount > GetData()->nDataLength)
  1235. nCount = GetData()->nDataLength;
  1236. CString dest;
  1237. AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0);
  1238. return dest;
  1239. }
  1240. inline CString CString::Left(int nCount) const
  1241. {
  1242. if (nCount < 0)
  1243. nCount = 0;
  1244. else if (nCount > GetData()->nDataLength)
  1245. nCount = GetData()->nDataLength;
  1246. CString dest;
  1247. AllocCopy(dest, nCount, 0, 0);
  1248. return dest;
  1249. }
  1250. // strspn equivalent
  1251. inline CString CString::SpanIncluding(LPCTSTR lpszCharSet) const
  1252. {
  1253. ATLASSERT(AfxIsValidString(lpszCharSet, FALSE));
  1254. return Left(_tcsspn(m_pchData, lpszCharSet));
  1255. }
  1256. // strcspn equivalent
  1257. inline CString CString::SpanExcluding(LPCTSTR lpszCharSet) const
  1258. {
  1259. ATLASSERT(AfxIsValidString(lpszCharSet, FALSE));
  1260. return Left(_tcscspn(m_pchData, lpszCharSet));
  1261. }
  1262. inline int CString::ReverseFind(TCHAR ch) const
  1263. {
  1264. // find last single character
  1265. LPTSTR lpsz = _tcsrchr(m_pchData, (_TUCHAR)ch);
  1266. // return -1 if not found, distance from beginning otherwise
  1267. return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
  1268. }
  1269. // find a sub-string (like strstr)
  1270. inline int CString::Find(LPCTSTR lpszSub) const
  1271. {
  1272. ATLASSERT(AfxIsValidString(lpszSub, FALSE));
  1273. // find first matching substring
  1274. LPTSTR lpsz = _tcsstr(m_pchData, lpszSub);
  1275. // return -1 for not found, distance from beginning otherwise
  1276. return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData);
  1277. }
  1278. #define TCHAR_ARG TCHAR
  1279. #define WCHAR_ARG WCHAR
  1280. #define CHAR_ARG char
  1281. struct _AFX_DOUBLE { BYTE doubleBits[sizeof(double)]; };
  1282. #if defined(_X86_)
  1283. #define DOUBLE_ARG _AFX_DOUBLE
  1284. #else
  1285. #define DOUBLE_ARG double
  1286. #endif
  1287. #define FORCE_ANSI 0x10000
  1288. #define FORCE_UNICODE 0x20000
  1289. inline void CString::FormatV(LPCTSTR lpszFormat, va_list argList)
  1290. {
  1291. ATLASSERT(AfxIsValidString(lpszFormat, FALSE));
  1292. va_list argListSave = argList;
  1293. // make a guess at the maximum length of the resulting string
  1294. int nMaxLen = 0;
  1295. for (LPCTSTR lpsz = lpszFormat; *lpsz != '\0'; lpsz = _tcsinc(lpsz))
  1296. {
  1297. // handle '%' character, but watch out for '%%'
  1298. if (*lpsz != '%' || *(lpsz = _tcsinc(lpsz)) == '%')
  1299. {
  1300. nMaxLen += _tclen(lpsz);
  1301. continue;
  1302. }
  1303. int nItemLen = 0;
  1304. // handle '%' character with format
  1305. int nWidth = 0;
  1306. for (; *lpsz != '\0'; lpsz = _tcsinc(lpsz))
  1307. {
  1308. // check for valid flags
  1309. if (*lpsz == '#')
  1310. nMaxLen += 2; // for '0x'
  1311. else if (*lpsz == '*')
  1312. nWidth = va_arg(argList, int);
  1313. else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0' ||
  1314. *lpsz == ' ')
  1315. ;
  1316. else // hit non-flag character
  1317. break;
  1318. }
  1319. // get width and skip it
  1320. if (nWidth == 0)
  1321. {
  1322. // width indicated by
  1323. nWidth = _ttoi(lpsz);
  1324. for (; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
  1325. ;
  1326. }
  1327. ATLASSERT(nWidth >= 0);
  1328. int nPrecision = 0;
  1329. if (*lpsz == '.')
  1330. {
  1331. // skip past '.' separator (width.precision)
  1332. lpsz = _tcsinc(lpsz);
  1333. // get precision and skip it
  1334. if (*lpsz == '*')
  1335. {
  1336. nPrecision = va_arg(argList, int);
  1337. lpsz = _tcsinc(lpsz);
  1338. }
  1339. else
  1340. {
  1341. nPrecision = _ttoi(lpsz);
  1342. for (; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz))
  1343. ;
  1344. }
  1345. ATLASSERT(nPrecision >= 0);
  1346. }
  1347. // should be on type modifier or specifier
  1348. int nModifier = 0;
  1349. switch (*lpsz)
  1350. {
  1351. // modifiers that affect size
  1352. case 'h':
  1353. nModifier = FORCE_ANSI;
  1354. lpsz = _tcsinc(lpsz);
  1355. break;
  1356. case 'l':
  1357. nModifier = FORCE_UNICODE;
  1358. lpsz = _tcsinc(lpsz);
  1359. break;
  1360. // modifiers that do not affect size
  1361. case 'F':
  1362. case 'N':
  1363. case 'L':
  1364. lpsz = _tcsinc(lpsz);
  1365. break;
  1366. }
  1367. // now should be on specifier
  1368. switch (*lpsz | nModifier)
  1369. {
  1370. // single characters
  1371. case 'c':
  1372. case 'C':
  1373. nItemLen = 2;
  1374. va_arg(argList, TCHAR_ARG);
  1375. break;
  1376. case 'c'|FORCE_ANSI:
  1377. case 'C'|FORCE_ANSI:
  1378. nItemLen = 2;
  1379. va_arg(argList, CHAR_ARG);
  1380. break;
  1381. case 'c'|FORCE_UNICODE:
  1382. case 'C'|FORCE_UNICODE:
  1383. nItemLen = 2;
  1384. va_arg(argList, WCHAR_ARG);
  1385. break;
  1386. // strings
  1387. case 's':
  1388. {
  1389. LPCTSTR pstrNextArg = va_arg(argList, LPCTSTR);
  1390. if (pstrNextArg == NULL)
  1391. nItemLen = 6; // "(null)"
  1392. else
  1393. {
  1394. nItemLen = lstrlen(pstrNextArg);
  1395. nItemLen = max(1, nItemLen);
  1396. }
  1397. break;
  1398. }
  1399. case 'S':
  1400. {
  1401. #ifndef _UNICODE
  1402. LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
  1403. if (pstrNextArg == NULL)
  1404. nItemLen = 6; // "(null)"
  1405. else
  1406. {
  1407. nItemLen = wcslen(pstrNextArg);
  1408. nItemLen = max(1, nItemLen);
  1409. }
  1410. #else
  1411. LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
  1412. if (pstrNextArg == NULL)
  1413. nItemLen = 6; // "(null)"
  1414. else
  1415. {
  1416. nItemLen = lstrlenA(pstrNextArg);
  1417. nItemLen = max(1, nItemLen);
  1418. }
  1419. #endif
  1420. break;
  1421. }
  1422. case 's'|FORCE_ANSI:
  1423. case 'S'|FORCE_ANSI:
  1424. {
  1425. LPCSTR pstrNextArg = va_arg(argList, LPCSTR);
  1426. if (pstrNextArg == NULL)
  1427. nItemLen = 6; // "(null)"
  1428. else
  1429. {
  1430. nItemLen = lstrlenA(pstrNextArg);
  1431. nItemLen = max(1, nItemLen);
  1432. }
  1433. break;
  1434. }
  1435. case 's'|FORCE_UNICODE:
  1436. case 'S'|FORCE_UNICODE:
  1437. {
  1438. LPWSTR pstrNextArg = va_arg(argList, LPWSTR);
  1439. if (pstrNextArg == NULL)
  1440. nItemLen = 6; // "(null)"
  1441. else
  1442. {
  1443. nItemLen = wcslen(pstrNextArg);
  1444. nItemLen = max(1, nItemLen);
  1445. }
  1446. break;
  1447. }
  1448. }
  1449. // adjust nItemLen for strings
  1450. if (nItemLen != 0)
  1451. {
  1452. nItemLen = max(nItemLen, nWidth);
  1453. if (nPrecision != 0)
  1454. nItemLen = min(nItemLen, nPrecision);
  1455. }
  1456. else
  1457. {
  1458. switch (*lpsz)
  1459. {
  1460. // integers
  1461. case 'd':
  1462. case 'i':
  1463. case 'u':
  1464. case 'x':
  1465. case 'X':
  1466. case 'o':
  1467. va_arg(argList, int);
  1468. nItemLen = 32;
  1469. nItemLen = max(nItemLen, nWidth+nPrecision);
  1470. break;
  1471. case 'e':
  1472. case 'f':
  1473. case 'g':
  1474. case 'G':
  1475. va_arg(argList, DOUBLE_ARG);
  1476. nItemLen = 128;
  1477. nItemLen = max(nItemLen, nWidth+nPrecision);
  1478. break;
  1479. case 'p':
  1480. va_arg(argList, void*);
  1481. nItemLen = 32;
  1482. nItemLen = max(nItemLen, nWidth+nPrecision);
  1483. break;
  1484. // no output
  1485. case 'n':
  1486. va_arg(argList, int*);
  1487. break;
  1488. default:
  1489. ATLASSERT(FALSE); // unknown formatting option
  1490. }
  1491. }
  1492. // adjust nMaxLen for output nItemLen
  1493. nMaxLen += nItemLen;
  1494. }
  1495. GetBuffer(nMaxLen);
  1496. int nRet = _vstprintf(m_pchData, lpszFormat, argListSave);
  1497. nRet; // ref
  1498. ATLASSERT(nRet <= GetAllocLength());
  1499. ReleaseBuffer();
  1500. va_end(argListSave);
  1501. }
  1502. // formatting (using wsprintf style formatting)
  1503. inline void __cdecl CString::Format(LPCTSTR lpszFormat, ...)
  1504. {
  1505. ATLASSERT(AfxIsValidString(lpszFormat, FALSE));
  1506. va_list argList;
  1507. va_start(argList, lpszFormat);
  1508. FormatV(lpszFormat, argList);
  1509. va_end(argList);
  1510. }
  1511. inline void __cdecl CString::Format(UINT nFormatID, ...)
  1512. {
  1513. CString strFormat;
  1514. BOOL bRet = strFormat.LoadString(nFormatID);
  1515. bRet; // ref
  1516. ATLASSERT(bRet != 0);
  1517. va_list argList;
  1518. va_start(argList, nFormatID);
  1519. FormatV(strFormat, argList);
  1520. va_end(argList);
  1521. }
  1522. // formatting (using FormatMessage style formatting)
  1523. inline BOOL __cdecl CString::FormatMessage(LPCTSTR lpszFormat, ...)
  1524. {
  1525. // format message into temporary buffer lpszTemp
  1526. va_list argList;
  1527. va_start(argList, lpszFormat);
  1528. LPTSTR lpszTemp;
  1529. BOOL bRet = TRUE;
  1530. if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
  1531. lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 ||
  1532. lpszTemp == NULL)
  1533. bRet = FALSE;
  1534. // assign lpszTemp into the resulting string and free the temporary
  1535. *this = lpszTemp;
  1536. LocalFree(lpszTemp);
  1537. va_end(argList);
  1538. return bRet;
  1539. }
  1540. inline BOOL __cdecl CString::FormatMessage(UINT nFormatID, ...)
  1541. {
  1542. // get format string from string table
  1543. CString strFormat;
  1544. BOOL bRetTmp = strFormat.LoadString(nFormatID);
  1545. bRetTmp; // ref
  1546. ATLASSERT(bRetTmp != 0);
  1547. // format message into temporary buffer lpszTemp
  1548. va_list argList;
  1549. va_start(argList, nFormatID);
  1550. LPTSTR lpszTemp;
  1551. BOOL bRet = TRUE;
  1552. if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER,
  1553. strFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 ||
  1554. lpszTemp == NULL)
  1555. bRet = FALSE;
  1556. // assign lpszTemp into the resulting string and free lpszTemp
  1557. *this = lpszTemp;
  1558. LocalFree(lpszTemp);
  1559. va_end(argList);
  1560. return bRet;
  1561. }
  1562. inline void CString::TrimRight()
  1563. {
  1564. CopyBeforeWrite();
  1565. // find beginning of trailing spaces by starting at beginning (DBCS aware)
  1566. LPTSTR lpsz = m_pchData;
  1567. LPTSTR lpszLast = NULL;
  1568. while (*lpsz != '\0')
  1569. {
  1570. if (_istspace(*lpsz))
  1571. {
  1572. if (lpszLast == NULL)
  1573. lpszLast = lpsz;
  1574. }
  1575. else
  1576. lpszLast = NULL;
  1577. lpsz = _tcsinc(lpsz);
  1578. }
  1579. if (lpszLast != NULL)
  1580. {
  1581. // truncate at trailing space start
  1582. *lpszLast = '\0';
  1583. GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData);
  1584. }
  1585. }
  1586. inline void CString::TrimLeft()
  1587. {
  1588. CopyBeforeWrite();
  1589. // find first non-space character
  1590. LPCTSTR lpsz = m_pchData;
  1591. while (_istspace(*lpsz))
  1592. lpsz = _tcsinc(lpsz);
  1593. // fix up data and length
  1594. int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData);
  1595. memmove(m_pchData, lpsz, (nDataLength+1)*sizeof(TCHAR));
  1596. GetData()->nDataLength = nDataLength;
  1597. }
  1598. #ifdef _UNICODE
  1599. #define CHAR_FUDGE 1 // one TCHAR unused is good enough
  1600. #else
  1601. #define CHAR_FUDGE 2 // two BYTES unused for case of DBC last char
  1602. #endif
  1603. inline BOOL CString::LoadString(UINT nID)
  1604. {
  1605. // try fixed buffer first (to avoid wasting space in the heap)
  1606. TCHAR szTemp[256];
  1607. int nCount = sizeof(szTemp) / sizeof(szTemp[0]);
  1608. int nLen = AfxLoadString(nID, szTemp, nCount);
  1609. if (nCount - nLen > CHAR_FUDGE)
  1610. {
  1611. *this = szTemp;
  1612. return nLen > 0;
  1613. }
  1614. // try buffer size of 512, then larger size until entire string is retrieved
  1615. int nSize = 256;
  1616. do
  1617. {
  1618. nSize += 256;
  1619. nLen = AfxLoadString(nID, GetBuffer(nSize-1), nSize);
  1620. } while (nSize - nLen <= CHAR_FUDGE);
  1621. ReleaseBuffer();
  1622. return nLen > 0;
  1623. }
  1624. inline int __stdcall AfxLoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf)
  1625. {
  1626. ATLASSERT(AfxIsValidAddress(lpszBuf, nMaxBuf*sizeof(TCHAR)));
  1627. #ifdef _DEBUG
  1628. // LoadString without annoying warning from the Debug kernel if the
  1629. // segment containing the string is not present
  1630. if (::FindResource(_Module.GetResourceInstance(),
  1631. MAKEINTRESOURCE((nID>>4)+1), RT_STRING) == NULL)
  1632. {
  1633. lpszBuf[0] = '\0';
  1634. return 0; // not found
  1635. }
  1636. #endif //_DEBUG
  1637. int nLen = ::LoadString(_Module.GetResourceInstance(), nID, lpszBuf, nMaxBuf);
  1638. if (nLen == 0)
  1639. lpszBuf[0] = '\0';
  1640. return nLen;
  1641. }
  1642. #ifndef _ATL_NO_COM
  1643. inline BSTR CString::AllocSysString() const
  1644. {
  1645. #if defined(_UNICODE) || defined(OLE2ANSI)
  1646. BSTR bstr = ::SysAllocStringLen(m_pchData, GetData()->nDataLength);
  1647. #else
  1648. int nLen = MultiByteToWideChar(CP_ACP, 0, m_pchData,
  1649. GetData()->nDataLength, NULL, NULL);
  1650. BSTR bstr = ::SysAllocStringLen(NULL, nLen);
  1651. if(bstr != NULL)
  1652. MultiByteToWideChar(CP_ACP, 0, m_pchData, GetData()->nDataLength, bstr, nLen);
  1653. #endif
  1654. return bstr;
  1655. }
  1656. inline BSTR CString::SetSysString(BSTR* pbstr) const
  1657. {
  1658. ATLASSERT(AfxIsValidAddress(pbstr, sizeof(BSTR)));
  1659. #if defined(_UNICODE) || defined(OLE2ANSI)
  1660. ::SysReAllocStringLen(pbstr, m_pchData, GetData()->nDataLength);
  1661. #else
  1662. int nLen = MultiByteToWideChar(CP_ACP, 0, m_pchData,
  1663. GetData()->nDataLength, NULL, NULL);
  1664. if(::SysReAllocStringLen(pbstr, NULL, nLen))
  1665. MultiByteToWideChar(CP_ACP, 0, m_pchData, GetData()->nDataLength, *pbstr, nLen);
  1666. #endif
  1667. ATLASSERT(*pbstr != NULL);
  1668. return *pbstr;
  1669. }
  1670. #endif //!_ATL_NO_COM
  1671. #endif //!_ATL_TMP_NO_CSTRING
  1672. }; //namespace ATL
  1673. #endif // __ATLTMP_H__
  1674. /////////////////////////////////////////////////////////////////////////////