Index: third_party/wtl/include/atlmisc.h |
diff --git a/third_party/wtl/include/atlmisc.h b/third_party/wtl/include/atlmisc.h |
deleted file mode 100644 |
index 8c7696b1929cecd451d31cdf285ae81cda7ea38f..0000000000000000000000000000000000000000 |
--- a/third_party/wtl/include/atlmisc.h |
+++ /dev/null |
@@ -1,4018 +0,0 @@ |
-// Windows Template Library - WTL version 8.0 |
-// Copyright (C) Microsoft Corporation. All rights reserved. |
-// |
-// This file is a part of the Windows Template Library. |
-// The use and distribution terms for this software are covered by the |
-// Microsoft Permissive License (Ms-PL) which can be found in the file |
-// Ms-PL.txt at the root of this distribution. |
- |
-#ifndef __ATLMISC_H__ |
-#define __ATLMISC_H__ |
- |
-#pragma once |
- |
-#ifndef __cplusplus |
- #error ATL requires C++ compilation (use a .cpp suffix) |
-#endif |
- |
-#ifndef __ATLAPP_H__ |
- #error atlmisc.h requires atlapp.h to be included first |
-#endif |
- |
- |
-#ifdef _ATL_TMP_NO_CSTRING |
- #define _WTL_NO_CSTRING |
-#endif |
- |
-#if defined(_WTL_USE_CSTRING) && defined(_WTL_NO_CSTRING) |
- #error Conflicting options - both _WTL_USE_CSTRING and _WTL_NO_CSTRING are defined |
-#endif // defined(_WTL_USE_CSTRING) && defined(_WTL_NO_CSTRING) |
- |
-#if !defined(_WTL_USE_CSTRING) && !defined(_WTL_NO_CSTRING) |
- #define _WTL_USE_CSTRING |
-#endif // !defined(_WTL_USE_CSTRING) && !defined(_WTL_NO_CSTRING) |
- |
-#ifndef _WTL_NO_CSTRING |
- #if defined(_ATL_USE_CSTRING_FLOAT) && defined(_ATL_MIN_CRT) |
- #error Cannot use CString floating point formatting with _ATL_MIN_CRT defined |
- #endif // defined(_ATL_USE_CSTRING_FLOAT) && defined(_ATL_MIN_CRT) |
-#endif // !_WTL_NO_CSTRING |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// Classes in this file: |
-// |
-// CSize |
-// CPoint |
-// CRect |
-// CString |
-// |
-// CRecentDocumentListBase<T, t_cchItemLen, t_nFirstID, t_nLastID> |
-// CRecentDocumentList |
-// CFindFile |
-// |
-// Global functions: |
-// AtlLoadAccelerators() |
-// AtlLoadMenu() |
-// AtlLoadBitmap() |
-// AtlLoadSysBitmap() |
-// AtlLoadCursor() |
-// AtlLoadSysCursor() |
-// AtlLoadIcon() |
-// AtlLoadSysIcon() |
-// AtlLoadBitmapImage() |
-// AtlLoadCursorImage() |
-// AtlLoadIconImage() |
-// AtlLoadSysBitmapImage() |
-// AtlLoadSysCursorImage() |
-// AtlLoadSysIconImage() |
-// AtlLoadString() |
-// |
-// AtlGetStockPen() |
-// AtlGetStockBrush() |
-// AtlGetStockFont() |
-// AtlGetStockPalette() |
-// |
-// AtlCompactPath() |
- |
- |
-namespace WTL |
-{ |
- |
-#ifndef _WTL_NO_WTYPES |
- |
-// forward declarations |
-class CSize; |
-class CPoint; |
-class CRect; |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// CSize - Wrapper for Windows SIZE structure. |
- |
-class CSize : public SIZE |
-{ |
-public: |
-// Constructors |
- CSize() |
- { |
- cx = 0; |
- cy = 0; |
- } |
- |
- CSize(int initCX, int initCY) |
- { |
- cx = initCX; |
- cy = initCY; |
- } |
- |
- CSize(SIZE initSize) |
- { |
- *(SIZE*)this = initSize; |
- } |
- |
- CSize(POINT initPt) |
- { |
- *(POINT*)this = initPt; |
- } |
- |
- CSize(DWORD dwSize) |
- { |
- cx = (short)LOWORD(dwSize); |
- cy = (short)HIWORD(dwSize); |
- } |
- |
-// Operations |
- BOOL operator ==(SIZE size) const |
- { |
- return (cx == size.cx && cy == size.cy); |
- } |
- |
- BOOL operator !=(SIZE size) const |
- { |
- return (cx != size.cx || cy != size.cy); |
- } |
- |
- void operator +=(SIZE size) |
- { |
- cx += size.cx; |
- cy += size.cy; |
- } |
- |
- void operator -=(SIZE size) |
- { |
- cx -= size.cx; |
- cy -= size.cy; |
- } |
- |
- void SetSize(int CX, int CY) |
- { |
- cx = CX; |
- cy = CY; |
- } |
- |
-// Operators returning CSize values |
- CSize operator +(SIZE size) const |
- { |
- return CSize(cx + size.cx, cy + size.cy); |
- } |
- |
- CSize operator -(SIZE size) const |
- { |
- return CSize(cx - size.cx, cy - size.cy); |
- } |
- |
- CSize operator -() const |
- { |
- return CSize(-cx, -cy); |
- } |
- |
-// Operators returning CPoint values |
- CPoint operator +(POINT point) const; |
- CPoint operator -(POINT point) const; |
- |
-// Operators returning CRect values |
- CRect operator +(const RECT* lpRect) const; |
- CRect operator -(const RECT* lpRect) const; |
-}; |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// CPoint - Wrapper for Windows POINT structure. |
- |
-class CPoint : public POINT |
-{ |
-public: |
-// Constructors |
- CPoint() |
- { |
- x = 0; |
- y = 0; |
- } |
- |
- CPoint(int initX, int initY) |
- { |
- x = initX; |
- y = initY; |
- } |
- |
- CPoint(POINT initPt) |
- { |
- *(POINT*)this = initPt; |
- } |
- |
- CPoint(SIZE initSize) |
- { |
- *(SIZE*)this = initSize; |
- } |
- |
- CPoint(DWORD dwPoint) |
- { |
- x = (short)LOWORD(dwPoint); |
- y = (short)HIWORD(dwPoint); |
- } |
- |
-// Operations |
- void Offset(int xOffset, int yOffset) |
- { |
- x += xOffset; |
- y += yOffset; |
- } |
- |
- void Offset(POINT point) |
- { |
- x += point.x; |
- y += point.y; |
- } |
- |
- void Offset(SIZE size) |
- { |
- x += size.cx; |
- y += size.cy; |
- } |
- |
- BOOL operator ==(POINT point) const |
- { |
- return (x == point.x && y == point.y); |
- } |
- |
- BOOL operator !=(POINT point) const |
- { |
- return (x != point.x || y != point.y); |
- } |
- |
- void operator +=(SIZE size) |
- { |
- x += size.cx; |
- y += size.cy; |
- } |
- |
- void operator -=(SIZE size) |
- { |
- x -= size.cx; |
- y -= size.cy; |
- } |
- |
- void operator +=(POINT point) |
- { |
- x += point.x; |
- y += point.y; |
- } |
- |
- void operator -=(POINT point) |
- { |
- x -= point.x; |
- y -= point.y; |
- } |
- |
- void SetPoint(int X, int Y) |
- { |
- x = X; |
- y = Y; |
- } |
- |
-// Operators returning CPoint values |
- CPoint operator +(SIZE size) const |
- { |
- return CPoint(x + size.cx, y + size.cy); |
- } |
- |
- CPoint operator -(SIZE size) const |
- { |
- return CPoint(x - size.cx, y - size.cy); |
- } |
- |
- CPoint operator -() const |
- { |
- return CPoint(-x, -y); |
- } |
- |
- CPoint operator +(POINT point) const |
- { |
- return CPoint(x + point.x, y + point.y); |
- } |
- |
-// Operators returning CSize values |
- CSize operator -(POINT point) const |
- { |
- return CSize(x - point.x, y - point.y); |
- } |
- |
-// Operators returning CRect values |
- CRect operator +(const RECT* lpRect) const; |
- CRect operator -(const RECT* lpRect) const; |
-}; |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// CRect - Wrapper for Windows RECT structure. |
- |
-class CRect : public RECT |
-{ |
-public: |
-// Constructors |
- CRect() |
- { |
- left = 0; |
- top = 0; |
- right = 0; |
- bottom = 0; |
- } |
- |
- CRect(int l, int t, int r, int b) |
- { |
- left = l; |
- top = t; |
- right = r; |
- bottom = b; |
- } |
- |
- CRect(const RECT& srcRect) |
- { |
- ::CopyRect(this, &srcRect); |
- } |
- |
- CRect(LPCRECT lpSrcRect) |
- { |
- ::CopyRect(this, lpSrcRect); |
- } |
- |
- CRect(POINT point, SIZE size) |
- { |
- right = (left = point.x) + size.cx; |
- bottom = (top = point.y) + size.cy; |
- } |
- |
- CRect(POINT topLeft, POINT bottomRight) |
- { |
- left = topLeft.x; |
- top = topLeft.y; |
- right = bottomRight.x; |
- bottom = bottomRight.y; |
- } |
- |
-// Attributes (in addition to RECT members) |
- int Width() const |
- { |
- return right - left; |
- } |
- |
- int Height() const |
- { |
- return bottom - top; |
- } |
- |
- CSize Size() const |
- { |
- return CSize(right - left, bottom - top); |
- } |
- |
- CPoint& TopLeft() |
- { |
- return *((CPoint*)this); |
- } |
- |
- CPoint& BottomRight() |
- { |
- return *((CPoint*)this + 1); |
- } |
- |
- const CPoint& TopLeft() const |
- { |
- return *((CPoint*)this); |
- } |
- |
- const CPoint& BottomRight() const |
- { |
- return *((CPoint*)this + 1); |
- } |
- |
- CPoint CenterPoint() const |
- { |
- return CPoint((left + right) / 2, (top + bottom) / 2); |
- } |
- |
- // convert between CRect and LPRECT/LPCRECT (no need for &) |
- operator LPRECT() |
- { |
- return this; |
- } |
- |
- operator LPCRECT() const |
- { |
- return this; |
- } |
- |
- BOOL IsRectEmpty() const |
- { |
- return ::IsRectEmpty(this); |
- } |
- |
- BOOL IsRectNull() const |
- { |
- return (left == 0 && right == 0 && top == 0 && bottom == 0); |
- } |
- |
- BOOL PtInRect(POINT point) const |
- { |
- return ::PtInRect(this, point); |
- } |
- |
-// Operations |
- void SetRect(int x1, int y1, int x2, int y2) |
- { |
- ::SetRect(this, x1, y1, x2, y2); |
- } |
- |
- void SetRect(POINT topLeft, POINT bottomRight) |
- { |
- ::SetRect(this, topLeft.x, topLeft.y, bottomRight.x, bottomRight.y); |
- } |
- |
- void SetRectEmpty() |
- { |
- ::SetRectEmpty(this); |
- } |
- |
- void CopyRect(LPCRECT lpSrcRect) |
- { |
- ::CopyRect(this, lpSrcRect); |
- } |
- |
- BOOL EqualRect(LPCRECT lpRect) const |
- { |
- return ::EqualRect(this, lpRect); |
- } |
- |
- void InflateRect(int x, int y) |
- { |
- ::InflateRect(this, x, y); |
- } |
- |
- void InflateRect(SIZE size) |
- { |
- ::InflateRect(this, size.cx, size.cy); |
- } |
- |
- void InflateRect(LPCRECT lpRect) |
- { |
- left -= lpRect->left; |
- top -= lpRect->top; |
- right += lpRect->right; |
- bottom += lpRect->bottom; |
- } |
- |
- void InflateRect(int l, int t, int r, int b) |
- { |
- left -= l; |
- top -= t; |
- right += r; |
- bottom += b; |
- } |
- |
- void DeflateRect(int x, int y) |
- { |
- ::InflateRect(this, -x, -y); |
- } |
- |
- void DeflateRect(SIZE size) |
- { |
- ::InflateRect(this, -size.cx, -size.cy); |
- } |
- |
- void DeflateRect(LPCRECT lpRect) |
- { |
- left += lpRect->left; |
- top += lpRect->top; |
- right -= lpRect->right; |
- bottom -= lpRect->bottom; |
- } |
- |
- void DeflateRect(int l, int t, int r, int b) |
- { |
- left += l; |
- top += t; |
- right -= r; |
- bottom -= b; |
- } |
- |
- void OffsetRect(int x, int y) |
- { |
- ::OffsetRect(this, x, y); |
- } |
- void OffsetRect(SIZE size) |
- { |
- ::OffsetRect(this, size.cx, size.cy); |
- } |
- |
- void OffsetRect(POINT point) |
- { |
- ::OffsetRect(this, point.x, point.y); |
- } |
- |
- void NormalizeRect() |
- { |
- int nTemp; |
- if (left > right) |
- { |
- nTemp = left; |
- left = right; |
- right = nTemp; |
- } |
- if (top > bottom) |
- { |
- nTemp = top; |
- top = bottom; |
- bottom = nTemp; |
- } |
- } |
- |
- // absolute position of rectangle |
- void MoveToY(int y) |
- { |
- bottom = Height() + y; |
- top = y; |
- } |
- |
- void MoveToX(int x) |
- { |
- right = Width() + x; |
- left = x; |
- } |
- |
- void MoveToXY(int x, int y) |
- { |
- MoveToX(x); |
- MoveToY(y); |
- } |
- |
- void MoveToXY(POINT pt) |
- { |
- MoveToX(pt.x); |
- MoveToY(pt.y); |
- } |
- |
- // operations that fill '*this' with result |
- BOOL IntersectRect(LPCRECT lpRect1, LPCRECT lpRect2) |
- { |
- return ::IntersectRect(this, lpRect1, lpRect2); |
- } |
- |
- BOOL UnionRect(LPCRECT lpRect1, LPCRECT lpRect2) |
- { |
- return ::UnionRect(this, lpRect1, lpRect2); |
- } |
- |
- BOOL SubtractRect(LPCRECT lpRectSrc1, LPCRECT lpRectSrc2) |
- { |
- return ::SubtractRect(this, lpRectSrc1, lpRectSrc2); |
- } |
- |
-// Additional Operations |
- void operator =(const RECT& srcRect) |
- { |
- ::CopyRect(this, &srcRect); |
- } |
- |
- BOOL operator ==(const RECT& rect) const |
- { |
- return ::EqualRect(this, &rect); |
- } |
- |
- BOOL operator !=(const RECT& rect) const |
- { |
- return !::EqualRect(this, &rect); |
- } |
- |
- void operator +=(POINT point) |
- { |
- ::OffsetRect(this, point.x, point.y); |
- } |
- |
- void operator +=(SIZE size) |
- { |
- ::OffsetRect(this, size.cx, size.cy); |
- } |
- |
- void operator +=(LPCRECT lpRect) |
- { |
- InflateRect(lpRect); |
- } |
- |
- void operator -=(POINT point) |
- { |
- ::OffsetRect(this, -point.x, -point.y); |
- } |
- |
- void operator -=(SIZE size) |
- { |
- ::OffsetRect(this, -size.cx, -size.cy); |
- } |
- |
- void operator -=(LPCRECT lpRect) |
- { |
- DeflateRect(lpRect); |
- } |
- |
- void operator &=(const RECT& rect) |
- { |
- ::IntersectRect(this, this, &rect); |
- } |
- |
- void operator |=(const RECT& rect) |
- { |
- ::UnionRect(this, this, &rect); |
- } |
- |
-// Operators returning CRect values |
- CRect operator +(POINT pt) const |
- { |
- CRect rect(*this); |
- ::OffsetRect(&rect, pt.x, pt.y); |
- return rect; |
- } |
- |
- CRect operator -(POINT pt) const |
- { |
- CRect rect(*this); |
- ::OffsetRect(&rect, -pt.x, -pt.y); |
- return rect; |
- } |
- |
- CRect operator +(LPCRECT lpRect) const |
- { |
- CRect rect(this); |
- rect.InflateRect(lpRect); |
- return rect; |
- } |
- |
- CRect operator +(SIZE size) const |
- { |
- CRect rect(*this); |
- ::OffsetRect(&rect, size.cx, size.cy); |
- return rect; |
- } |
- |
- CRect operator -(SIZE size) const |
- { |
- CRect rect(*this); |
- ::OffsetRect(&rect, -size.cx, -size.cy); |
- return rect; |
- } |
- |
- CRect operator -(LPCRECT lpRect) const |
- { |
- CRect rect(this); |
- rect.DeflateRect(lpRect); |
- return rect; |
- } |
- |
- CRect operator &(const RECT& rect2) const |
- { |
- CRect rect; |
- ::IntersectRect(&rect, this, &rect2); |
- return rect; |
- } |
- |
- CRect operator |(const RECT& rect2) const |
- { |
- CRect rect; |
- ::UnionRect(&rect, this, &rect2); |
- return rect; |
- } |
- |
- CRect MulDiv(int nMultiplier, int nDivisor) const |
- { |
- return CRect( |
- ::MulDiv(left, nMultiplier, nDivisor), |
- ::MulDiv(top, nMultiplier, nDivisor), |
- ::MulDiv(right, nMultiplier, nDivisor), |
- ::MulDiv(bottom, nMultiplier, nDivisor)); |
- } |
-}; |
- |
- |
-// CSize implementation |
- |
-inline CPoint CSize::operator +(POINT point) const |
-{ return CPoint(cx + point.x, cy + point.y); } |
- |
-inline CPoint CSize::operator -(POINT point) const |
-{ return CPoint(cx - point.x, cy - point.y); } |
- |
-inline CRect CSize::operator +(const RECT* lpRect) const |
-{ return CRect(lpRect) + *this; } |
- |
-inline CRect CSize::operator -(const RECT* lpRect) const |
-{ return CRect(lpRect) - *this; } |
- |
- |
-// CPoint implementation |
- |
-inline CRect CPoint::operator +(const RECT* lpRect) const |
-{ return CRect(lpRect) + *this; } |
- |
-inline CRect CPoint::operator -(const RECT* lpRect) const |
-{ return CRect(lpRect) - *this; } |
- |
-#endif // !_WTL_NO_WTYPES |
- |
- |
-// WTL::CSize or ATL::CSize scalar operators |
- |
-#if !defined(_WTL_NO_SIZE_SCALAR) && (!defined(_WTL_NO_WTYPES) || defined(__ATLTYPES_H__)) |
- |
-template <class Num> |
-inline CSize operator *(SIZE s, Num n) |
-{ |
- return CSize((int)(s.cx * n), (int)(s.cy * n)); |
-}; |
- |
-template <class Num> |
-inline void operator *=(SIZE & s, Num n) |
-{ |
- s = s * n; |
-}; |
- |
-template <class Num> |
-inline CSize operator /(SIZE s, Num n) |
-{ |
- return CSize((int)(s.cx / n), (int)(s.cy / n)); |
-}; |
- |
-template <class Num> |
-inline void operator /=(SIZE & s, Num n) |
-{ |
- s = s / n; |
-}; |
- |
-#endif // !defined(_WTL_NO_SIZE_SCALAR) && (!defined(_WTL_NO_WTYPES) || defined(__ATLTYPES_H__)) |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// CString - String class |
- |
-#ifndef _WTL_NO_CSTRING |
- |
-struct CStringData |
-{ |
- long nRefs; // reference count |
- int nDataLength; |
- int nAllocLength; |
- // TCHAR data[nAllocLength] |
- |
- TCHAR* data() |
- { return (TCHAR*)(this + 1); } |
-}; |
- |
-// Globals |
- |
-// For an empty string, m_pchData will point here |
-// (note: avoids special case of checking for NULL m_pchData) |
-// empty string data (and locked) |
-_declspec(selectany) int rgInitData[] = { -1, 0, 0, 0 }; |
-_declspec(selectany) CStringData* _atltmpDataNil = (CStringData*)&rgInitData; |
-_declspec(selectany) LPCTSTR _atltmpPchNil = (LPCTSTR)(((BYTE*)&rgInitData) + sizeof(CStringData)); |
- |
- |
-class CString |
-{ |
-public: |
-// Constructors |
- CString() |
- { |
- Init(); |
- } |
- |
- CString(const CString& stringSrc) |
- { |
- ATLASSERT(stringSrc.GetData()->nRefs != 0); |
- if (stringSrc.GetData()->nRefs >= 0) |
- { |
- ATLASSERT(stringSrc.GetData() != _atltmpDataNil); |
- m_pchData = stringSrc.m_pchData; |
- InterlockedIncrement(&GetData()->nRefs); |
- } |
- else |
- { |
- Init(); |
- *this = stringSrc.m_pchData; |
- } |
- } |
- |
- CString(TCHAR ch, int nRepeat = 1) |
- { |
- ATLASSERT(!_istlead(ch)); // can't create a lead byte string |
- Init(); |
- if (nRepeat >= 1) |
- { |
- if(AllocBuffer(nRepeat)) |
- { |
-#ifdef _UNICODE |
- for (int i = 0; i < nRepeat; i++) |
- m_pchData[i] = ch; |
-#else |
- memset(m_pchData, ch, nRepeat); |
-#endif |
- } |
- } |
- } |
- |
- CString(LPCTSTR lpsz) |
- { |
- Init(); |
- if (lpsz != NULL && HIWORD(lpsz) == NULL) |
- { |
- UINT nID = LOWORD((DWORD_PTR)lpsz); |
- if (!LoadString(nID)) |
- ATLTRACE2(atlTraceUI, 0, _T("Warning: implicit LoadString(%u) in CString failed\n"), nID); |
- } |
- else |
- { |
- int nLen = SafeStrlen(lpsz); |
- if (nLen != 0) |
- { |
- if(AllocBuffer(nLen)) |
- SecureHelper::memcpy_x(m_pchData, (nLen + 1) * sizeof(TCHAR), lpsz, nLen * sizeof(TCHAR)); |
- } |
- } |
- } |
- |
-#ifdef _UNICODE |
- CString(LPCSTR lpsz) |
- { |
- Init(); |
-#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800) |
- int nSrcLen = (lpsz != NULL) ? ATL::lstrlenA(lpsz) : 0; |
-#else |
- int nSrcLen = (lpsz != NULL) ? lstrlenA(lpsz) : 0; |
-#endif |
- if (nSrcLen != 0) |
- { |
- if(AllocBuffer(nSrcLen)) |
- { |
- _mbstowcsz(m_pchData, lpsz, nSrcLen + 1); |
- ReleaseBuffer(); |
- } |
- } |
- } |
-#else // !_UNICODE |
- CString(LPCWSTR lpsz) |
- { |
- Init(); |
- int nSrcLen = (lpsz != NULL) ? (int)wcslen(lpsz) : 0; |
- if (nSrcLen != 0) |
- { |
- if(AllocBuffer(nSrcLen * 2)) |
- { |
- _wcstombsz(m_pchData, lpsz, (nSrcLen * 2) + 1); |
- ReleaseBuffer(); |
- } |
- } |
- } |
-#endif // !_UNICODE |
- |
- CString(LPCTSTR lpch, int nLength) |
- { |
- Init(); |
- if (nLength != 0) |
- { |
- if(AllocBuffer(nLength)) |
- SecureHelper::memcpy_x(m_pchData, (nLength + 1) * sizeof(TCHAR), lpch, nLength * sizeof(TCHAR)); |
- } |
- } |
- |
-#ifdef _UNICODE |
- CString(LPCSTR lpsz, int nLength) |
- { |
- Init(); |
- if (nLength != 0) |
- { |
- if(AllocBuffer(nLength)) |
- { |
- int n = ::MultiByteToWideChar(CP_ACP, 0, lpsz, nLength, m_pchData, nLength + 1); |
- ReleaseBuffer((n >= 0) ? n : -1); |
- } |
- } |
- } |
-#else // !_UNICODE |
- CString(LPCWSTR lpsz, int nLength) |
- { |
- Init(); |
- if (nLength != 0) |
- { |
- if(((nLength * 2) > nLength) && AllocBuffer(nLength * 2)) |
- { |
- int n = ::WideCharToMultiByte(CP_ACP, 0, lpsz, nLength, m_pchData, (nLength * 2) + 1, NULL, NULL); |
- ReleaseBuffer((n >= 0) ? n : -1); |
- } |
- } |
- } |
-#endif // !_UNICODE |
- |
- CString(const unsigned char* lpsz) |
- { |
- Init(); |
- *this = (LPCSTR)lpsz; |
- } |
- |
-// Attributes & Operations |
- int GetLength() const // as an array of characters |
- { |
- return GetData()->nDataLength; |
- } |
- |
- BOOL IsEmpty() const |
- { |
- return GetData()->nDataLength == 0; |
- } |
- |
- void Empty() // free up the data |
- { |
- if (GetData()->nDataLength == 0) |
- return; |
- |
- if (GetData()->nRefs >= 0) |
- Release(); |
- else |
- *this = _T(""); |
- |
- ATLASSERT(GetData()->nDataLength == 0); |
- ATLASSERT(GetData()->nRefs < 0 || GetData()->nAllocLength == 0); |
- } |
- |
- TCHAR GetAt(int nIndex) const // 0 based |
- { |
- ATLASSERT(nIndex >= 0); |
- ATLASSERT(nIndex < GetData()->nDataLength); |
- return m_pchData[nIndex]; |
- } |
- |
- TCHAR operator [](int nIndex) const // same as GetAt |
- { |
- // same as GetAt |
- ATLASSERT(nIndex >= 0); |
- ATLASSERT(nIndex < GetData()->nDataLength); |
- return m_pchData[nIndex]; |
- } |
- |
- void SetAt(int nIndex, TCHAR ch) |
- { |
- ATLASSERT(nIndex >= 0); |
- ATLASSERT(nIndex < GetData()->nDataLength); |
- |
- CopyBeforeWrite(); |
- m_pchData[nIndex] = ch; |
- } |
- |
- operator LPCTSTR() const // as a C string |
- { |
- return m_pchData; |
- } |
- |
- // overloaded assignment |
- CString& operator =(const CString& stringSrc) |
- { |
- if (m_pchData != stringSrc.m_pchData) |
- { |
- if ((GetData()->nRefs < 0 && GetData() != _atltmpDataNil) || stringSrc.GetData()->nRefs < 0) |
- { |
- // actual copy necessary since one of the strings is locked |
- AssignCopy(stringSrc.GetData()->nDataLength, stringSrc.m_pchData); |
- } |
- else |
- { |
- // can just copy references around |
- Release(); |
- ATLASSERT(stringSrc.GetData() != _atltmpDataNil); |
- m_pchData = stringSrc.m_pchData; |
- InterlockedIncrement(&GetData()->nRefs); |
- } |
- } |
- return *this; |
- } |
- |
- CString& operator =(TCHAR ch) |
- { |
- ATLASSERT(!_istlead(ch)); // can't set single lead byte |
- AssignCopy(1, &ch); |
- return *this; |
- } |
- |
-#ifdef _UNICODE |
- CString& operator =(char ch) |
- { |
- *this = (TCHAR)ch; |
- return *this; |
- } |
-#endif |
- |
- CString& operator =(LPCTSTR lpsz) |
- { |
- ATLASSERT(lpsz == NULL || _IsValidString(lpsz)); |
- AssignCopy(SafeStrlen(lpsz), lpsz); |
- return *this; |
- } |
- |
-#ifdef _UNICODE |
- CString& operator =(LPCSTR lpsz) |
- { |
-#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800) |
- int nSrcLen = (lpsz != NULL) ? ATL::lstrlenA(lpsz) : 0; |
-#else |
- int nSrcLen = (lpsz != NULL) ? lstrlenA(lpsz) : 0; |
-#endif |
- if(AllocBeforeWrite(nSrcLen)) |
- { |
- _mbstowcsz(m_pchData, lpsz, nSrcLen + 1); |
- ReleaseBuffer(); |
- } |
- return *this; |
- } |
-#else // !_UNICODE |
- CString& operator =(LPCWSTR lpsz) |
- { |
- int nSrcLen = (lpsz != NULL) ? (int)wcslen(lpsz) : 0; |
- if(AllocBeforeWrite(nSrcLen * 2)) |
- { |
- _wcstombsz(m_pchData, lpsz, (nSrcLen * 2) + 1); |
- ReleaseBuffer(); |
- } |
- return *this; |
- } |
-#endif // !_UNICODE |
- |
- CString& operator =(const unsigned char* lpsz) |
- { |
- *this = (LPCSTR)lpsz; |
- return *this; |
- } |
- |
- // string concatenation |
- CString& operator +=(const CString& string) |
- { |
- ConcatInPlace(string.GetData()->nDataLength, string.m_pchData); |
- return *this; |
- } |
- |
- CString& operator +=(TCHAR ch) |
- { |
- ConcatInPlace(1, &ch); |
- return *this; |
- } |
- |
-#ifdef _UNICODE |
- CString& operator +=(char ch) |
- { |
- *this += (TCHAR)ch; |
- return *this; |
- } |
-#endif |
- |
- CString& operator +=(LPCTSTR lpsz) |
- { |
- ATLASSERT(lpsz == NULL || _IsValidString(lpsz)); |
- ConcatInPlace(SafeStrlen(lpsz), lpsz); |
- return *this; |
- } |
- |
- friend CString __stdcall operator +(const CString& string1, const CString& string2); |
- friend CString __stdcall operator +(const CString& string, TCHAR ch); |
- friend CString __stdcall operator +(TCHAR ch, const CString& string); |
-#ifdef _UNICODE |
- friend CString __stdcall operator +(const CString& string, char ch); |
- friend CString __stdcall operator +(char ch, const CString& string); |
-#endif |
- friend CString __stdcall operator +(const CString& string, LPCTSTR lpsz); |
- friend CString __stdcall operator +(LPCTSTR lpsz, const CString& string); |
- |
- // string comparison |
- int Compare(LPCTSTR lpsz) const // straight character (MBCS/Unicode aware) |
- { |
- return _cstrcmp(m_pchData, lpsz); |
- } |
- |
- int CompareNoCase(LPCTSTR lpsz) const // ignore case (MBCS/Unicode aware) |
- { |
- return _cstrcmpi(m_pchData, lpsz); |
- } |
- |
-#ifndef _WIN32_WCE |
- // CString::Collate is often slower than Compare but is MBSC/Unicode |
- // aware as well as locale-sensitive with respect to sort order. |
- int Collate(LPCTSTR lpsz) const // NLS aware |
- { |
- return _cstrcoll(m_pchData, lpsz); |
- } |
- |
- int CollateNoCase(LPCTSTR lpsz) const // ignore case |
- { |
- return _cstrcolli(m_pchData, lpsz); |
- } |
-#endif // !_WIN32_WCE |
- |
- // simple sub-string extraction |
- CString Mid(int nFirst, int nCount) const |
- { |
- // out-of-bounds requests return sensible things |
- if (nFirst < 0) |
- nFirst = 0; |
- if (nCount < 0) |
- nCount = 0; |
- |
- if (nFirst + nCount > GetData()->nDataLength) |
- nCount = GetData()->nDataLength - nFirst; |
- if (nFirst > GetData()->nDataLength) |
- nCount = 0; |
- |
- CString dest; |
- AllocCopy(dest, nCount, nFirst, 0); |
- return dest; |
- } |
- |
- CString Mid(int nFirst) const |
- { |
- return Mid(nFirst, GetData()->nDataLength - nFirst); |
- } |
- |
- CString Left(int nCount) const |
- { |
- if (nCount < 0) |
- nCount = 0; |
- else if (nCount > GetData()->nDataLength) |
- nCount = GetData()->nDataLength; |
- |
- CString dest; |
- AllocCopy(dest, nCount, 0, 0); |
- return dest; |
- } |
- |
- CString Right(int nCount) const |
- { |
- if (nCount < 0) |
- nCount = 0; |
- else if (nCount > GetData()->nDataLength) |
- nCount = GetData()->nDataLength; |
- |
- CString dest; |
- AllocCopy(dest, nCount, GetData()->nDataLength-nCount, 0); |
- return dest; |
- } |
- |
- CString SpanIncluding(LPCTSTR lpszCharSet) const // strspn equivalent |
- { |
- ATLASSERT(_IsValidString(lpszCharSet)); |
- return Left(_cstrspn(m_pchData, lpszCharSet)); |
- } |
- |
- CString SpanExcluding(LPCTSTR lpszCharSet) const // strcspn equivalent |
- { |
- ATLASSERT(_IsValidString(lpszCharSet)); |
- return Left(_cstrcspn(m_pchData, lpszCharSet)); |
- } |
- |
- // upper/lower/reverse conversion |
- void MakeUpper() |
- { |
- CopyBeforeWrite(); |
- CharUpper(m_pchData); |
- } |
- |
- void MakeLower() |
- { |
- CopyBeforeWrite(); |
- CharLower(m_pchData); |
- } |
- |
- void MakeReverse() |
- { |
- CopyBeforeWrite(); |
- _cstrrev(m_pchData); |
- } |
- |
- // trimming whitespace (either side) |
- void TrimRight() |
- { |
- CopyBeforeWrite(); |
- |
- // find beginning of trailing spaces by starting at beginning (DBCS aware) |
- LPTSTR lpsz = m_pchData; |
- LPTSTR lpszLast = NULL; |
- while (*lpsz != _T('\0')) |
- { |
- if (_cstrisspace(*lpsz)) |
- { |
- if (lpszLast == NULL) |
- lpszLast = lpsz; |
- } |
- else |
- { |
- lpszLast = NULL; |
- } |
- lpsz = ::CharNext(lpsz); |
- } |
- |
- if (lpszLast != NULL) |
- { |
- // truncate at trailing space start |
- *lpszLast = _T('\0'); |
- GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData); |
- } |
- } |
- |
- void TrimLeft() |
- { |
- CopyBeforeWrite(); |
- |
- // find first non-space character |
- LPCTSTR lpsz = m_pchData; |
- while (_cstrisspace(*lpsz)) |
- lpsz = ::CharNext(lpsz); |
- |
- // fix up data and length |
- int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData); |
- SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR)); |
- GetData()->nDataLength = nDataLength; |
- } |
- |
- // remove continuous occurrences of chTarget starting from right |
- void TrimRight(TCHAR chTarget) |
- { |
- // find beginning of trailing matches |
- // by starting at beginning (DBCS aware) |
- |
- CopyBeforeWrite(); |
- LPTSTR lpsz = m_pchData; |
- LPTSTR lpszLast = NULL; |
- |
- while (*lpsz != _T('\0')) |
- { |
- if (*lpsz == chTarget) |
- { |
- if (lpszLast == NULL) |
- lpszLast = lpsz; |
- } |
- else |
- lpszLast = NULL; |
- lpsz = ::CharNext(lpsz); |
- } |
- |
- if (lpszLast != NULL) |
- { |
- // truncate at left-most matching character |
- *lpszLast = _T('\0'); |
- GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData); |
- } |
- } |
- |
- // remove continuous occcurrences of characters in passed string, starting from right |
- void TrimRight(LPCTSTR lpszTargetList) |
- { |
- // find beginning of trailing matches by starting at beginning (DBCS aware) |
- |
- CopyBeforeWrite(); |
- LPTSTR lpsz = m_pchData; |
- LPTSTR lpszLast = NULL; |
- |
- while (*lpsz != _T('\0')) |
- { |
- TCHAR* pNext = ::CharNext(lpsz); |
- if(pNext > lpsz + 1) |
- { |
- if (_cstrchr_db(lpszTargetList, *lpsz, *(lpsz + 1)) != NULL) |
- { |
- if (lpszLast == NULL) |
- lpszLast = lpsz; |
- } |
- else |
- { |
- lpszLast = NULL; |
- } |
- } |
- else |
- { |
- if (_cstrchr(lpszTargetList, *lpsz) != NULL) |
- { |
- if (lpszLast == NULL) |
- lpszLast = lpsz; |
- } |
- else |
- { |
- lpszLast = NULL; |
- } |
- } |
- |
- lpsz = pNext; |
- } |
- |
- if (lpszLast != NULL) |
- { |
- // truncate at left-most matching character |
- *lpszLast = _T('\0'); |
- GetData()->nDataLength = (int)(DWORD_PTR)(lpszLast - m_pchData); |
- } |
- } |
- |
- // remove continuous occurrences of chTarget starting from left |
- void TrimLeft(TCHAR chTarget) |
- { |
- // find first non-matching character |
- |
- CopyBeforeWrite(); |
- LPCTSTR lpsz = m_pchData; |
- |
- while (chTarget == *lpsz) |
- lpsz = ::CharNext(lpsz); |
- |
- if (lpsz != m_pchData) |
- { |
- // fix up data and length |
- int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData); |
- SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR)); |
- GetData()->nDataLength = nDataLength; |
- } |
- } |
- |
- // remove continuous occcurrences of characters in passed string, starting from left |
- void TrimLeft(LPCTSTR lpszTargets) |
- { |
- // if we're not trimming anything, we're not doing any work |
- if (SafeStrlen(lpszTargets) == 0) |
- return; |
- |
- CopyBeforeWrite(); |
- LPCTSTR lpsz = m_pchData; |
- |
- while (*lpsz != _T('\0')) |
- { |
- TCHAR* pNext = ::CharNext(lpsz); |
- if(pNext > lpsz + 1) |
- { |
- if (_cstrchr_db(lpszTargets, *lpsz, *(lpsz + 1)) == NULL) |
- break; |
- } |
- else |
- { |
- if (_cstrchr(lpszTargets, *lpsz) == NULL) |
- break; |
- } |
- lpsz = pNext; |
- } |
- |
- if (lpsz != m_pchData) |
- { |
- // fix up data and length |
- int nDataLength = GetData()->nDataLength - (int)(DWORD_PTR)(lpsz - m_pchData); |
- SecureHelper::memmove_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpsz, (nDataLength + 1) * sizeof(TCHAR)); |
- GetData()->nDataLength = nDataLength; |
- } |
- } |
- |
- // advanced manipulation |
- // replace occurrences of chOld with chNew |
- int Replace(TCHAR chOld, TCHAR chNew) |
- { |
- int nCount = 0; |
- |
- // short-circuit the nop case |
- if (chOld != chNew) |
- { |
- // otherwise modify each character that matches in the string |
- CopyBeforeWrite(); |
- LPTSTR psz = m_pchData; |
- LPTSTR pszEnd = psz + GetData()->nDataLength; |
- while (psz < pszEnd) |
- { |
- // replace instances of the specified character only |
- if (*psz == chOld) |
- { |
- *psz = chNew; |
- nCount++; |
- } |
- psz = ::CharNext(psz); |
- } |
- } |
- return nCount; |
- } |
- |
- // replace occurrences of substring lpszOld with lpszNew; |
- // empty lpszNew removes instances of lpszOld |
- int Replace(LPCTSTR lpszOld, LPCTSTR lpszNew) |
- { |
- // can't have empty or NULL lpszOld |
- |
- int nSourceLen = SafeStrlen(lpszOld); |
- if (nSourceLen == 0) |
- return 0; |
- int nReplacementLen = SafeStrlen(lpszNew); |
- |
- // loop once to figure out the size of the result string |
- int nCount = 0; |
- LPTSTR lpszStart = m_pchData; |
- LPTSTR lpszEnd = m_pchData + GetData()->nDataLength; |
- LPTSTR lpszTarget = NULL; |
- while (lpszStart < lpszEnd) |
- { |
- while ((lpszTarget = (TCHAR*)_cstrstr(lpszStart, lpszOld)) != NULL) |
- { |
- nCount++; |
- lpszStart = lpszTarget + nSourceLen; |
- } |
- lpszStart += lstrlen(lpszStart) + 1; |
- } |
- |
- // if any changes were made, make them |
- if (nCount > 0) |
- { |
- CopyBeforeWrite(); |
- |
- // if the buffer is too small, just allocate a new buffer (slow but sure) |
- int nOldLength = GetData()->nDataLength; |
- int nNewLength = nOldLength + (nReplacementLen - nSourceLen) * nCount; |
- if (GetData()->nAllocLength < nNewLength || GetData()->nRefs > 1) |
- { |
- CStringData* pOldData = GetData(); |
- LPTSTR pstr = m_pchData; |
- if(!AllocBuffer(nNewLength)) |
- return -1; |
- SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, pOldData->nDataLength * sizeof(TCHAR)); |
- CString::Release(pOldData); |
- } |
- // else, we just do it in-place |
- lpszStart = m_pchData; |
- lpszEnd = m_pchData + GetData()->nDataLength; |
- |
- // loop again to actually do the work |
- while (lpszStart < lpszEnd) |
- { |
- while ((lpszTarget = (TCHAR*)_cstrstr(lpszStart, lpszOld)) != NULL) |
- { |
- int nBalance = nOldLength - ((int)(DWORD_PTR)(lpszTarget - m_pchData) + nSourceLen); |
- int cchBuffLen = GetData()->nAllocLength - (int)(DWORD_PTR)(lpszTarget - m_pchData); |
- SecureHelper::memmove_x(lpszTarget + nReplacementLen, (cchBuffLen - nReplacementLen + 1) * sizeof(TCHAR), lpszTarget + nSourceLen, nBalance * sizeof(TCHAR)); |
- SecureHelper::memcpy_x(lpszTarget, (cchBuffLen + 1) * sizeof(TCHAR), lpszNew, nReplacementLen * sizeof(TCHAR)); |
- lpszStart = lpszTarget + nReplacementLen; |
- lpszStart[nBalance] = _T('\0'); |
- nOldLength += (nReplacementLen - nSourceLen); |
- } |
- lpszStart += lstrlen(lpszStart) + 1; |
- } |
- ATLASSERT(m_pchData[nNewLength] == _T('\0')); |
- GetData()->nDataLength = nNewLength; |
- } |
- |
- return nCount; |
- } |
- |
- // remove occurrences of chRemove |
- int Remove(TCHAR chRemove) |
- { |
- CopyBeforeWrite(); |
- |
- LPTSTR pstrSource = m_pchData; |
- LPTSTR pstrDest = m_pchData; |
- LPTSTR pstrEnd = m_pchData + GetData()->nDataLength; |
- |
- while (pstrSource < pstrEnd) |
- { |
- if (*pstrSource != chRemove) |
- { |
- *pstrDest = *pstrSource; |
- pstrDest = ::CharNext(pstrDest); |
- } |
- pstrSource = ::CharNext(pstrSource); |
- } |
- *pstrDest = _T('\0'); |
- int nCount = (int)(DWORD_PTR)(pstrSource - pstrDest); |
- GetData()->nDataLength -= nCount; |
- |
- return nCount; |
- } |
- |
- // insert character at zero-based index; concatenates if index is past end of string |
- int Insert(int nIndex, TCHAR ch) |
- { |
- CopyBeforeWrite(); |
- |
- if (nIndex < 0) |
- nIndex = 0; |
- |
- int nNewLength = GetData()->nDataLength; |
- if (nIndex > nNewLength) |
- nIndex = nNewLength; |
- nNewLength++; |
- |
- if (GetData()->nAllocLength < nNewLength) |
- { |
- CStringData* pOldData = GetData(); |
- LPTSTR pstr = m_pchData; |
- if(!AllocBuffer(nNewLength)) |
- return -1; |
- SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, (pOldData->nDataLength + 1) * sizeof(TCHAR)); |
- CString::Release(pOldData); |
- } |
- |
- // move existing bytes down |
- SecureHelper::memmove_x(m_pchData + nIndex + 1, (GetData()->nAllocLength - nIndex) * sizeof(TCHAR), m_pchData + nIndex, (nNewLength - nIndex) * sizeof(TCHAR)); |
- m_pchData[nIndex] = ch; |
- GetData()->nDataLength = nNewLength; |
- |
- return nNewLength; |
- } |
- |
- // insert substring at zero-based index; concatenates if index is past end of string |
- int Insert(int nIndex, LPCTSTR pstr) |
- { |
- if (nIndex < 0) |
- nIndex = 0; |
- |
- int nInsertLength = SafeStrlen(pstr); |
- int nNewLength = GetData()->nDataLength; |
- if (nInsertLength > 0) |
- { |
- CopyBeforeWrite(); |
- if (nIndex > nNewLength) |
- nIndex = nNewLength; |
- nNewLength += nInsertLength; |
- |
- if (GetData()->nAllocLength < nNewLength) |
- { |
- CStringData* pOldData = GetData(); |
- LPTSTR pstr = m_pchData; |
- if(!AllocBuffer(nNewLength)) |
- return -1; |
- SecureHelper::memcpy_x(m_pchData, (nNewLength + 1) * sizeof(TCHAR), pstr, (pOldData->nDataLength + 1) * sizeof(TCHAR)); |
- CString::Release(pOldData); |
- } |
- |
- // move existing bytes down |
- SecureHelper::memmove_x(m_pchData + nIndex + nInsertLength, (GetData()->nAllocLength + 1 - nIndex - nInsertLength) * sizeof(TCHAR), m_pchData + nIndex, (nNewLength - nIndex - nInsertLength + 1) * sizeof(TCHAR)); |
- SecureHelper::memcpy_x(m_pchData + nIndex, (GetData()->nAllocLength + 1 - nIndex) * sizeof(TCHAR), pstr, nInsertLength * sizeof(TCHAR)); |
- GetData()->nDataLength = nNewLength; |
- } |
- |
- return nNewLength; |
- } |
- |
- // delete nCount characters starting at zero-based index |
- int Delete(int nIndex, int nCount = 1) |
- { |
- if (nIndex < 0) |
- nIndex = 0; |
- int nLength = GetData()->nDataLength; |
- if (nCount > 0 && nIndex < nLength) |
- { |
- if((nIndex + nCount) > nLength) |
- nCount = nLength - nIndex; |
- CopyBeforeWrite(); |
- int nBytesToCopy = nLength - (nIndex + nCount) + 1; |
- |
- SecureHelper::memmove_x(m_pchData + nIndex, (GetData()->nAllocLength + 1 - nIndex) * sizeof(TCHAR), m_pchData + nIndex + nCount, nBytesToCopy * sizeof(TCHAR)); |
- nLength -= nCount; |
- GetData()->nDataLength = nLength; |
- } |
- |
- return nLength; |
- } |
- |
- // searching (return starting index, or -1 if not found) |
- // look for a single character match |
- int Find(TCHAR ch) const // like "C" strchr |
- { |
- return Find(ch, 0); |
- } |
- |
- int ReverseFind(TCHAR ch) const |
- { |
- // find last single character |
- LPCTSTR lpsz = _cstrrchr(m_pchData, (_TUCHAR)ch); |
- |
- // return -1 if not found, distance from beginning otherwise |
- return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); |
- } |
- |
- int Find(TCHAR ch, int nStart) const // starting at index |
- { |
- int nLength = GetData()->nDataLength; |
- if (nStart < 0 || nStart >= nLength) |
- return -1; |
- |
- // find first single character |
- LPCTSTR lpsz = _cstrchr(m_pchData + nStart, (_TUCHAR)ch); |
- |
- // return -1 if not found and index otherwise |
- return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); |
- } |
- |
- int FindOneOf(LPCTSTR lpszCharSet) const |
- { |
- ATLASSERT(_IsValidString(lpszCharSet)); |
- LPCTSTR lpsz = _cstrpbrk(m_pchData, lpszCharSet); |
- return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); |
- } |
- |
- // look for a specific sub-string |
- // find a sub-string (like strstr) |
- int Find(LPCTSTR lpszSub) const // like "C" strstr |
- { |
- return Find(lpszSub, 0); |
- } |
- |
- int Find(LPCTSTR lpszSub, int nStart) const // starting at index |
- { |
- ATLASSERT(_IsValidString(lpszSub)); |
- |
- int nLength = GetData()->nDataLength; |
- if (nStart < 0 || nStart > nLength) |
- return -1; |
- |
- // find first matching substring |
- LPCTSTR lpsz = _cstrstr(m_pchData + nStart, lpszSub); |
- |
- // return -1 for not found, distance from beginning otherwise |
- return (lpsz == NULL) ? -1 : (int)(lpsz - m_pchData); |
- } |
- |
- // Concatentation for non strings |
- CString& Append(int n) |
- { |
- const int cchBuff = 12; |
- TCHAR szBuffer[cchBuff] = { 0 }; |
- SecureHelper::wsprintf_x(szBuffer, cchBuff, _T("%d"), n); |
- ConcatInPlace(SafeStrlen(szBuffer), szBuffer); |
- return *this; |
- } |
- |
- // simple formatting |
- // formatting (using wsprintf style formatting) |
- BOOL __cdecl Format(LPCTSTR lpszFormat, ...) |
- { |
- ATLASSERT(_IsValidString(lpszFormat)); |
- |
- va_list argList; |
- va_start(argList, lpszFormat); |
- BOOL bRet = FormatV(lpszFormat, argList); |
- va_end(argList); |
- return bRet; |
- } |
- |
- BOOL __cdecl Format(UINT nFormatID, ...) |
- { |
- CString strFormat; |
- BOOL bRet = strFormat.LoadString(nFormatID); |
- ATLASSERT(bRet != 0); |
- |
- va_list argList; |
- va_start(argList, nFormatID); |
- bRet = FormatV(strFormat, argList); |
- va_end(argList); |
- return bRet; |
- } |
- |
- BOOL FormatV(LPCTSTR lpszFormat, va_list argList) |
- { |
- ATLASSERT(_IsValidString(lpszFormat)); |
- |
- enum _FormatModifiers |
- { |
- FORCE_ANSI = 0x10000, |
- FORCE_UNICODE = 0x20000, |
- FORCE_INT64 = 0x40000 |
- }; |
- |
- va_list argListSave = argList; |
- |
- // make a guess at the maximum length of the resulting string |
- int nMaxLen = 0; |
- for (LPCTSTR lpsz = lpszFormat; *lpsz != _T('\0'); lpsz = ::CharNext(lpsz)) |
- { |
- // handle '%' character, but watch out for '%%' |
- if (*lpsz != _T('%') || *(lpsz = ::CharNext(lpsz)) == _T('%')) |
- { |
- nMaxLen += (int)(::CharNext(lpsz) - lpsz); |
- continue; |
- } |
- |
- int nItemLen = 0; |
- |
- // handle '%' character with format |
- int nWidth = 0; |
- for (; *lpsz != _T('\0'); lpsz = ::CharNext(lpsz)) |
- { |
- // check for valid flags |
- if (*lpsz == _T('#')) |
- nMaxLen += 2; // for '0x' |
- else if (*lpsz == _T('*')) |
- nWidth = va_arg(argList, int); |
- else if (*lpsz == _T('-') || *lpsz == _T('+') || *lpsz == _T('0') || *lpsz == _T(' ')) |
- ; |
- else // hit non-flag character |
- break; |
- } |
- // get width and skip it |
- if (nWidth == 0) |
- { |
- // width indicated by |
- nWidth = _cstrtoi(lpsz); |
- for (; *lpsz != _T('\0') && _cstrisdigit(*lpsz); lpsz = ::CharNext(lpsz)) |
- ; |
- } |
- ATLASSERT(nWidth >= 0); |
- |
- int nPrecision = 0; |
- if (*lpsz == _T('.')) |
- { |
- // skip past '.' separator (width.precision) |
- lpsz = ::CharNext(lpsz); |
- |
- // get precision and skip it |
- if (*lpsz == _T('*')) |
- { |
- nPrecision = va_arg(argList, int); |
- lpsz = ::CharNext(lpsz); |
- } |
- else |
- { |
- nPrecision = _cstrtoi(lpsz); |
- for (; *lpsz != _T('\0') && _cstrisdigit(*lpsz); lpsz = ::CharNext(lpsz)) |
- ; |
- } |
- ATLASSERT(nPrecision >= 0); |
- } |
- |
- // should be on type modifier or specifier |
- int nModifier = 0; |
- if(lpsz[0] == _T('I') && lpsz[1] == _T('6') && lpsz[2] == _T('4')) |
- { |
- lpsz += 3; |
- nModifier = FORCE_INT64; |
- } |
- else |
- { |
- switch (*lpsz) |
- { |
- // modifiers that affect size |
- case _T('h'): |
- nModifier = FORCE_ANSI; |
- lpsz = ::CharNext(lpsz); |
- break; |
- case _T('l'): |
- nModifier = FORCE_UNICODE; |
- lpsz = ::CharNext(lpsz); |
- break; |
- |
- // modifiers that do not affect size |
- case _T('F'): |
- case _T('N'): |
- case _T('L'): |
- lpsz = ::CharNext(lpsz); |
- break; |
- } |
- } |
- |
- // now should be on specifier |
- switch (*lpsz | nModifier) |
- { |
- // single characters |
- case _T('c'): |
- case _T('C'): |
- nItemLen = 2; |
- va_arg(argList, TCHAR); |
- break; |
- case _T('c') | FORCE_ANSI: |
- case _T('C') | FORCE_ANSI: |
- nItemLen = 2; |
- va_arg(argList, char); |
- break; |
- case _T('c') | FORCE_UNICODE: |
- case _T('C') | FORCE_UNICODE: |
- nItemLen = 2; |
- va_arg(argList, WCHAR); |
- break; |
- |
- // strings |
- case _T('s'): |
- { |
- LPCTSTR pstrNextArg = va_arg(argList, LPCTSTR); |
- if (pstrNextArg == NULL) |
- { |
- nItemLen = 6; // "(null)" |
- } |
- else |
- { |
- nItemLen = lstrlen(pstrNextArg); |
- nItemLen = __max(1, nItemLen); |
- } |
- break; |
- } |
- |
- case _T('S'): |
- { |
-#ifndef _UNICODE |
- LPWSTR pstrNextArg = va_arg(argList, LPWSTR); |
- if (pstrNextArg == NULL) |
- { |
- nItemLen = 6; // "(null)" |
- } |
- else |
- { |
- nItemLen = (int)wcslen(pstrNextArg); |
- nItemLen = __max(1, nItemLen); |
- } |
-#else // _UNICODE |
- LPCSTR pstrNextArg = va_arg(argList, LPCSTR); |
- if (pstrNextArg == NULL) |
- { |
- nItemLen = 6; // "(null)" |
- } |
- else |
- { |
-#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800) |
- nItemLen = ATL::lstrlenA(pstrNextArg); |
-#else |
- nItemLen = lstrlenA(pstrNextArg); |
-#endif |
- nItemLen = __max(1, nItemLen); |
- } |
-#endif // _UNICODE |
- break; |
- } |
- |
- case _T('s') | FORCE_ANSI: |
- case _T('S') | FORCE_ANSI: |
- { |
- LPCSTR pstrNextArg = va_arg(argList, LPCSTR); |
- if (pstrNextArg == NULL) |
- { |
- nItemLen = 6; // "(null)" |
- } |
- else |
- { |
-#if defined(_WIN32_WCE) && (_ATL_VER >= 0x0800) |
- nItemLen = ATL::lstrlenA(pstrNextArg); |
-#else |
- nItemLen = lstrlenA(pstrNextArg); |
-#endif |
- nItemLen = __max(1, nItemLen); |
- } |
- break; |
- } |
- |
- case _T('s') | FORCE_UNICODE: |
- case _T('S') | FORCE_UNICODE: |
- { |
- LPWSTR pstrNextArg = va_arg(argList, LPWSTR); |
- if (pstrNextArg == NULL) |
- { |
- nItemLen = 6; // "(null)" |
- } |
- else |
- { |
- nItemLen = (int)wcslen(pstrNextArg); |
- nItemLen = __max(1, nItemLen); |
- } |
- break; |
- } |
- } |
- |
- // adjust nItemLen for strings |
- if (nItemLen != 0) |
- { |
- nItemLen = __max(nItemLen, nWidth); |
- if (nPrecision != 0) |
- nItemLen = __min(nItemLen, nPrecision); |
- } |
- else |
- { |
- switch (*lpsz) |
- { |
- // integers |
- case _T('d'): |
- case _T('i'): |
- case _T('u'): |
- case _T('x'): |
- case _T('X'): |
- case _T('o'): |
- if (nModifier & FORCE_INT64) |
- va_arg(argList, __int64); |
- else |
- va_arg(argList, int); |
- nItemLen = 32; |
- nItemLen = __max(nItemLen, nWidth + nPrecision); |
- break; |
- |
-#ifndef _ATL_USE_CSTRING_FLOAT |
- case _T('e'): |
- case _T('E'): |
- case _T('f'): |
- case _T('g'): |
- case _T('G'): |
- ATLASSERT(!"Floating point (%%e, %%E, %%f, %%g, and %%G) is not supported by the WTL::CString class."); |
-#ifndef _DEBUG |
- ::OutputDebugString(_T("Floating point (%%e, %%f, %%g, and %%G) is not supported by the WTL::CString class.")); |
-#ifndef _WIN32_WCE |
- ::DebugBreak(); |
-#else // CE specific |
- DebugBreak(); |
-#endif // _WIN32_WCE |
-#endif // !_DEBUG |
- break; |
-#else // _ATL_USE_CSTRING_FLOAT |
- case _T('e'): |
- case _T('E'): |
- case _T('g'): |
- case _T('G'): |
- va_arg(argList, double); |
- nItemLen = 128; |
- nItemLen = __max(nItemLen, nWidth + nPrecision); |
- break; |
- case _T('f'): |
- { |
- double f = va_arg(argList, double); |
- // 312 == strlen("-1+(309 zeroes).") |
- // 309 zeroes == max precision of a double |
- // 6 == adjustment in case precision is not specified, |
- // which means that the precision defaults to 6 |
- int cchLen = __max(nWidth, 312 + nPrecision + 6); |
- CTempBuffer<TCHAR, _WTL_STACK_ALLOC_THRESHOLD> buff; |
- LPTSTR pszTemp = buff.Allocate(cchLen); |
- if(pszTemp != NULL) |
- { |
- SecureHelper::sprintf_x(pszTemp, cchLen, _T("%*.*f"), nWidth, nPrecision + 6, f); |
- nItemLen = (int)_tcslen(pszTemp); |
- } |
- else |
- { |
- nItemLen = cchLen; |
- } |
- } |
- break; |
-#endif // _ATL_USE_CSTRING_FLOAT |
- |
- case _T('p'): |
- va_arg(argList, void*); |
- nItemLen = 32; |
- nItemLen = __max(nItemLen, nWidth + nPrecision); |
- break; |
- |
- // no output |
- case _T('n'): |
- va_arg(argList, int*); |
- break; |
- |
- default: |
- ATLASSERT(FALSE); // unknown formatting option |
- } |
- } |
- |
- // adjust nMaxLen for output nItemLen |
- nMaxLen += nItemLen; |
- } |
- |
- if(GetBuffer(nMaxLen) == NULL) |
- return FALSE; |
-#ifndef _ATL_USE_CSTRING_FLOAT |
- int nRet = SecureHelper::wvsprintf_x(m_pchData, GetAllocLength() + 1, lpszFormat, argListSave); |
-#else // _ATL_USE_CSTRING_FLOAT |
- int nRet = SecureHelper::vsprintf_x(m_pchData, GetAllocLength() + 1, lpszFormat, argListSave); |
-#endif // _ATL_USE_CSTRING_FLOAT |
- nRet; // ref |
- ATLASSERT(nRet <= GetAllocLength()); |
- ReleaseBuffer(); |
- |
- va_end(argListSave); |
- return TRUE; |
- } |
- |
- // formatting for localization (uses FormatMessage API) |
- // formatting (using FormatMessage style formatting) |
- BOOL __cdecl FormatMessage(LPCTSTR lpszFormat, ...) |
- { |
- // format message into temporary buffer lpszTemp |
- va_list argList; |
- va_start(argList, lpszFormat); |
- LPTSTR lpszTemp; |
- BOOL bRet = TRUE; |
- |
- if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, |
- lpszFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 || lpszTemp == NULL) |
- bRet = FALSE; |
- |
- // assign lpszTemp into the resulting string and free the temporary |
- *this = lpszTemp; |
- LocalFree(lpszTemp); |
- va_end(argList); |
- return bRet; |
- } |
- |
- BOOL __cdecl FormatMessage(UINT nFormatID, ...) |
- { |
- // get format string from string table |
- CString strFormat; |
- BOOL bRetTmp = strFormat.LoadString(nFormatID); |
- bRetTmp; // ref |
- ATLASSERT(bRetTmp != 0); |
- |
- // format message into temporary buffer lpszTemp |
- va_list argList; |
- va_start(argList, nFormatID); |
- LPTSTR lpszTemp; |
- BOOL bRet = TRUE; |
- |
- if (::FormatMessage(FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER, |
- strFormat, 0, 0, (LPTSTR)&lpszTemp, 0, &argList) == 0 || lpszTemp == NULL) |
- bRet = FALSE; |
- |
- // assign lpszTemp into the resulting string and free lpszTemp |
- *this = lpszTemp; |
- LocalFree(lpszTemp); |
- va_end(argList); |
- return bRet; |
- } |
- |
- // Windows support |
- BOOL LoadString(UINT nID) // load from string resource (255 chars max.) |
- { |
-#ifdef _UNICODE |
- const int CHAR_FUDGE = 1; // one TCHAR unused is good enough |
-#else |
- const int CHAR_FUDGE = 2; // two BYTES unused for case of DBC last char |
-#endif |
- |
- // try fixed buffer first (to avoid wasting space in the heap) |
- TCHAR szTemp[256]; |
- int nCount = sizeof(szTemp) / sizeof(szTemp[0]); |
- int nLen = _LoadString(nID, szTemp, nCount); |
- if (nCount - nLen > CHAR_FUDGE) |
- { |
- *this = szTemp; |
- return (nLen > 0); |
- } |
- |
- // try buffer size of 512, then larger size until entire string is retrieved |
- int nSize = 256; |
- do |
- { |
- nSize += 256; |
- LPTSTR lpstr = GetBuffer(nSize - 1); |
- if(lpstr == NULL) |
- { |
- nLen = 0; |
- break; |
- } |
- nLen = _LoadString(nID, lpstr, nSize); |
- } while (nSize - nLen <= CHAR_FUDGE); |
- ReleaseBuffer(); |
- |
- return (nLen > 0); |
- } |
- |
-#ifndef _UNICODE |
- // ANSI <-> OEM support (convert string in place) |
- void AnsiToOem() |
- { |
- CopyBeforeWrite(); |
- ::AnsiToOem(m_pchData, m_pchData); |
- } |
- |
- void OemToAnsi() |
- { |
- CopyBeforeWrite(); |
- ::OemToAnsi(m_pchData, m_pchData); |
- } |
-#endif |
- |
-#ifndef _ATL_NO_COM |
- // OLE BSTR support (use for OLE automation) |
- BSTR AllocSysString() const |
- { |
-#if defined(_UNICODE) || defined(OLE2ANSI) |
- BSTR bstr = ::SysAllocStringLen(m_pchData, GetData()->nDataLength); |
-#else |
- int nLen = MultiByteToWideChar(CP_ACP, 0, m_pchData, |
- GetData()->nDataLength, NULL, NULL); |
- BSTR bstr = ::SysAllocStringLen(NULL, nLen); |
- if(bstr != NULL) |
- MultiByteToWideChar(CP_ACP, 0, m_pchData, GetData()->nDataLength, bstr, nLen); |
-#endif |
- return bstr; |
- } |
- |
- BSTR SetSysString(BSTR* pbstr) const |
- { |
-#if defined(_UNICODE) || defined(OLE2ANSI) |
- ::SysReAllocStringLen(pbstr, m_pchData, GetData()->nDataLength); |
-#else |
- int nLen = MultiByteToWideChar(CP_ACP, 0, m_pchData, |
- GetData()->nDataLength, NULL, NULL); |
- if(::SysReAllocStringLen(pbstr, NULL, nLen)) |
- MultiByteToWideChar(CP_ACP, 0, m_pchData, GetData()->nDataLength, *pbstr, nLen); |
-#endif |
- ATLASSERT(*pbstr != NULL); |
- return *pbstr; |
- } |
-#endif // !_ATL_NO_COM |
- |
- // Access to string implementation buffer as "C" character array |
- LPTSTR GetBuffer(int nMinBufLength) |
- { |
- ATLASSERT(nMinBufLength >= 0); |
- |
- if (GetData()->nRefs > 1 || nMinBufLength > GetData()->nAllocLength) |
- { |
- // we have to grow the buffer |
- CStringData* pOldData = GetData(); |
- int nOldLen = GetData()->nDataLength; // AllocBuffer will tromp it |
- if (nMinBufLength < nOldLen) |
- nMinBufLength = nOldLen; |
- |
- if(!AllocBuffer(nMinBufLength)) |
- return NULL; |
- |
- SecureHelper::memcpy_x(m_pchData, (nMinBufLength + 1) * sizeof(TCHAR), pOldData->data(), (nOldLen + 1) * sizeof(TCHAR)); |
- GetData()->nDataLength = nOldLen; |
- CString::Release(pOldData); |
- } |
- ATLASSERT(GetData()->nRefs <= 1); |
- |
- // return a pointer to the character storage for this string |
- ATLASSERT(m_pchData != NULL); |
- return m_pchData; |
- } |
- |
- void ReleaseBuffer(int nNewLength = -1) |
- { |
- CopyBeforeWrite(); // just in case GetBuffer was not called |
- |
- if (nNewLength == -1) |
- nNewLength = lstrlen(m_pchData); // zero terminated |
- |
- ATLASSERT(nNewLength <= GetData()->nAllocLength); |
- GetData()->nDataLength = nNewLength; |
- m_pchData[nNewLength] = _T('\0'); |
- } |
- |
- LPTSTR GetBufferSetLength(int nNewLength) |
- { |
- ATLASSERT(nNewLength >= 0); |
- |
- if(GetBuffer(nNewLength) == NULL) |
- return NULL; |
- |
- GetData()->nDataLength = nNewLength; |
- m_pchData[nNewLength] = _T('\0'); |
- return m_pchData; |
- } |
- |
- void FreeExtra() |
- { |
- ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength); |
- if (GetData()->nDataLength != GetData()->nAllocLength) |
- { |
- CStringData* pOldData = GetData(); |
- if(AllocBuffer(GetData()->nDataLength)) |
- { |
- SecureHelper::memcpy_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), pOldData->data(), pOldData->nDataLength * sizeof(TCHAR)); |
- ATLASSERT(m_pchData[GetData()->nDataLength] == _T('\0')); |
- CString::Release(pOldData); |
- } |
- } |
- ATLASSERT(GetData() != NULL); |
- } |
- |
- // Use LockBuffer/UnlockBuffer to turn refcounting off |
- LPTSTR LockBuffer() |
- { |
- LPTSTR lpsz = GetBuffer(0); |
- if(lpsz != NULL) |
- GetData()->nRefs = -1; |
- return lpsz; |
- } |
- |
- void UnlockBuffer() |
- { |
- ATLASSERT(GetData()->nRefs == -1); |
- if (GetData() != _atltmpDataNil) |
- GetData()->nRefs = 1; |
- } |
- |
-// Implementation |
-public: |
- ~CString() // free any attached data |
- { |
- if (GetData() != _atltmpDataNil) |
- { |
- if (InterlockedDecrement(&GetData()->nRefs) <= 0) |
- delete[] (BYTE*)GetData(); |
- } |
- } |
- |
- int GetAllocLength() const |
- { |
- return GetData()->nAllocLength; |
- } |
- |
- static BOOL __stdcall _IsValidString(LPCTSTR lpsz, int /*nLength*/ = -1) |
- { |
- return (lpsz != NULL) ? TRUE : FALSE; |
- } |
- |
-protected: |
- LPTSTR m_pchData; // pointer to ref counted string data |
- |
- // implementation helpers |
- CStringData* GetData() const |
- { |
- ATLASSERT(m_pchData != NULL); |
- return ((CStringData*)m_pchData) - 1; |
- } |
- |
- void Init() |
- { |
- m_pchData = _GetEmptyString().m_pchData; |
- } |
- |
- BOOL AllocCopy(CString& dest, int nCopyLen, int nCopyIndex, int nExtraLen) const |
- { |
- // will clone the data attached to this string |
- // allocating 'nExtraLen' characters |
- // Places results in uninitialized string 'dest' |
- // Will copy the part or all of original data to start of new string |
- |
- BOOL bRet = FALSE; |
- int nNewLen = nCopyLen + nExtraLen; |
- if (nNewLen == 0) |
- { |
- dest.Init(); |
- bRet = TRUE; |
- } |
- else if(nNewLen >= nCopyLen) |
- { |
- if(dest.AllocBuffer(nNewLen)) |
- { |
- SecureHelper::memcpy_x(dest.m_pchData, (nNewLen + 1) * sizeof(TCHAR), m_pchData + nCopyIndex, nCopyLen * sizeof(TCHAR)); |
- bRet = TRUE; |
- } |
- } |
- |
- return bRet; |
- } |
- |
- // always allocate one extra character for '\0' termination |
- // assumes [optimistically] that data length will equal allocation length |
- BOOL AllocBuffer(int nLen) |
- { |
- ATLASSERT(nLen >= 0); |
- ATLASSERT(nLen <= INT_MAX - 1); // max size (enough room for 1 extra) |
- |
- if (nLen == 0) |
- { |
- Init(); |
- } |
- else |
- { |
- CStringData* pData = NULL; |
- ATLTRY(pData = (CStringData*)new BYTE[sizeof(CStringData) + (nLen + 1) * sizeof(TCHAR)]); |
- if(pData == NULL) |
- return FALSE; |
- |
- pData->nRefs = 1; |
- pData->data()[nLen] = _T('\0'); |
- pData->nDataLength = nLen; |
- pData->nAllocLength = nLen; |
- m_pchData = pData->data(); |
- } |
- |
- return TRUE; |
- } |
- |
- // Assignment operators |
- // All assign a new value to the string |
- // (a) first see if the buffer is big enough |
- // (b) if enough room, copy on top of old buffer, set size and type |
- // (c) otherwise free old string data, and create a new one |
- // |
- // All routines return the new string (but as a 'const CString&' so that |
- // assigning it again will cause a copy, eg: s1 = s2 = "hi there". |
- // |
- void AssignCopy(int nSrcLen, LPCTSTR lpszSrcData) |
- { |
- if(AllocBeforeWrite(nSrcLen)) |
- { |
- SecureHelper::memcpy_x(m_pchData, (nSrcLen + 1) * sizeof(TCHAR), lpszSrcData, nSrcLen * sizeof(TCHAR)); |
- GetData()->nDataLength = nSrcLen; |
- m_pchData[nSrcLen] = _T('\0'); |
- } |
- } |
- |
- // Concatenation |
- // NOTE: "operator +" is done as friend functions for simplicity |
- // There are three variants: |
- // CString + CString |
- // and for ? = TCHAR, LPCTSTR |
- // CString + ? |
- // ? + CString |
- BOOL ConcatCopy(int nSrc1Len, LPCTSTR lpszSrc1Data, int nSrc2Len, LPCTSTR lpszSrc2Data) |
- { |
- // -- master concatenation routine |
- // Concatenate two sources |
- // -- assume that 'this' is a new CString object |
- |
- BOOL bRet = TRUE; |
- int nNewLen = nSrc1Len + nSrc2Len; |
- if(nNewLen < nSrc1Len || nNewLen < nSrc2Len) |
- { |
- bRet = FALSE; |
- } |
- else if(nNewLen != 0) |
- { |
- bRet = AllocBuffer(nNewLen); |
- if (bRet) |
- { |
- SecureHelper::memcpy_x(m_pchData, (nNewLen + 1) * sizeof(TCHAR), lpszSrc1Data, nSrc1Len * sizeof(TCHAR)); |
- SecureHelper::memcpy_x(m_pchData + nSrc1Len, (nNewLen + 1 - nSrc1Len) * sizeof(TCHAR), lpszSrc2Data, nSrc2Len * sizeof(TCHAR)); |
- } |
- } |
- return bRet; |
- } |
- |
- void ConcatInPlace(int nSrcLen, LPCTSTR lpszSrcData) |
- { |
- // -- the main routine for += operators |
- |
- // concatenating an empty string is a no-op! |
- if (nSrcLen == 0) |
- return; |
- |
- // if the buffer is too small, or we have a width mis-match, just |
- // allocate a new buffer (slow but sure) |
- if (GetData()->nRefs > 1 || GetData()->nDataLength + nSrcLen > GetData()->nAllocLength) |
- { |
- // we have to grow the buffer, use the ConcatCopy routine |
- CStringData* pOldData = GetData(); |
- if (ConcatCopy(GetData()->nDataLength, m_pchData, nSrcLen, lpszSrcData)) |
- { |
- ATLASSERT(pOldData != NULL); |
- CString::Release(pOldData); |
- } |
- } |
- else |
- { |
- // fast concatenation when buffer big enough |
- SecureHelper::memcpy_x(m_pchData + GetData()->nDataLength, (GetData()->nAllocLength + 1) * sizeof(TCHAR), lpszSrcData, nSrcLen * sizeof(TCHAR)); |
- GetData()->nDataLength += nSrcLen; |
- ATLASSERT(GetData()->nDataLength <= GetData()->nAllocLength); |
- m_pchData[GetData()->nDataLength] = _T('\0'); |
- } |
- } |
- |
- void CopyBeforeWrite() |
- { |
- if (GetData()->nRefs > 1) |
- { |
- CStringData* pData = GetData(); |
- Release(); |
- if(AllocBuffer(pData->nDataLength)) |
- SecureHelper::memcpy_x(m_pchData, (GetData()->nAllocLength + 1) * sizeof(TCHAR), pData->data(), (pData->nDataLength + 1) * sizeof(TCHAR)); |
- } |
- ATLASSERT(GetData()->nRefs <= 1); |
- } |
- |
- BOOL AllocBeforeWrite(int nLen) |
- { |
- BOOL bRet = TRUE; |
- if (GetData()->nRefs > 1 || nLen > GetData()->nAllocLength) |
- { |
- Release(); |
- bRet = AllocBuffer(nLen); |
- } |
- ATLASSERT(GetData()->nRefs <= 1); |
- return bRet; |
- } |
- |
- void Release() |
- { |
- if (GetData() != _atltmpDataNil) |
- { |
- ATLASSERT(GetData()->nRefs != 0); |
- if (InterlockedDecrement(&GetData()->nRefs) <= 0) |
- delete[] (BYTE*)GetData(); |
- Init(); |
- } |
- } |
- |
- static void PASCAL Release(CStringData* pData) |
- { |
- if (pData != _atltmpDataNil) |
- { |
- ATLASSERT(pData->nRefs != 0); |
- if (InterlockedDecrement(&pData->nRefs) <= 0) |
- delete[] (BYTE*)pData; |
- } |
- } |
- |
- static int PASCAL SafeStrlen(LPCTSTR lpsz) |
- { |
- return (lpsz == NULL) ? 0 : lstrlen(lpsz); |
- } |
- |
- static int __stdcall _LoadString(UINT nID, LPTSTR lpszBuf, UINT nMaxBuf) |
- { |
-#ifdef _DEBUG |
- // LoadString without annoying warning from the Debug kernel if the |
- // segment containing the string is not present |
- if (::FindResource(ModuleHelper::GetResourceInstance(), MAKEINTRESOURCE((nID >> 4) + 1), RT_STRING) == NULL) |
- { |
- lpszBuf[0] = _T('\0'); |
- return 0; // not found |
- } |
-#endif // _DEBUG |
- |
- int nLen = ::LoadString(ModuleHelper::GetResourceInstance(), nID, lpszBuf, nMaxBuf); |
- if (nLen == 0) |
- lpszBuf[0] = _T('\0'); |
- |
- return nLen; |
- } |
- |
- static const CString& __stdcall _GetEmptyString() |
- { |
- return *(CString*)&_atltmpPchNil; |
- } |
- |
-// CString conversion helpers |
- static int __cdecl _wcstombsz(char* mbstr, const wchar_t* wcstr, size_t count) |
- { |
- if (count == 0 && mbstr != NULL) |
- return 0; |
- |
- int result = ::WideCharToMultiByte(CP_ACP, 0, wcstr, -1, mbstr, (int)count, NULL, NULL); |
- ATLASSERT(mbstr == NULL || result <= (int)count); |
- if (result > 0) |
- mbstr[result - 1] = 0; |
- return result; |
- } |
- |
- static int __cdecl _mbstowcsz(wchar_t* wcstr, const char* mbstr, size_t count) |
- { |
- if (count == 0 && wcstr != NULL) |
- return 0; |
- |
- int result = ::MultiByteToWideChar(CP_ACP, 0, mbstr, -1, wcstr, (int)count); |
- ATLASSERT(wcstr == NULL || result <= (int)count); |
- if (result > 0) |
- wcstr[result - 1] = 0; |
- return result; |
- } |
- |
-// Helpers to avoid CRT startup code |
-#ifdef _ATL_MIN_CRT |
- static const TCHAR* _cstrchr(const TCHAR* p, TCHAR ch) |
- { |
- // strchr for '\0' should succeed |
- while (*p != 0) |
- { |
- if (*p == ch) |
- break; |
- p = ::CharNext(p); |
- } |
- return (*p == ch) ? p : NULL; |
- } |
- |
- static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch) |
- { |
- const TCHAR* lpsz = NULL; |
- while (*p != 0) |
- { |
- if (*p == ch) |
- lpsz = p; |
- p = ::CharNext(p); |
- } |
- return lpsz; |
- } |
- |
- static TCHAR* _cstrrev(TCHAR* pStr) |
- { |
- // optimize NULL, zero-length, and single-char case |
- if ((pStr == NULL) || (pStr[0] == _T('\0')) || (pStr[1] == _T('\0'))) |
- return pStr; |
- |
- TCHAR* p = pStr; |
- |
- while (*p != 0) |
- { |
- TCHAR* pNext = ::CharNext(p); |
- if(pNext > p + 1) |
- { |
- char p1 = *(char*)p; |
- *(char*)p = *(char*)(p + 1); |
- *(char*)(p + 1) = p1; |
- } |
- p = pNext; |
- } |
- |
- p--; |
- TCHAR* q = pStr; |
- |
- while (q < p) |
- { |
- TCHAR t = *q; |
- *q = *p; |
- *p = t; |
- q++; |
- p--; |
- } |
- return pStr; |
- } |
- |
- static const TCHAR* _cstrstr(const TCHAR* pStr, const TCHAR* pCharSet) |
- { |
- int nLen = lstrlen(pCharSet); |
- if (nLen == 0) |
- return (TCHAR*)pStr; |
- |
- const TCHAR* pRet = NULL; |
- const TCHAR* pCur = pStr; |
- while((pCur = _cstrchr(pCur, *pCharSet)) != NULL) |
- { |
- if(memcmp(pCur, pCharSet, nLen * sizeof(TCHAR)) == 0) |
- { |
- pRet = pCur; |
- break; |
- } |
- pCur = ::CharNext(pCur); |
- } |
- return pRet; |
- } |
- |
- static int _cstrspn(const TCHAR* pStr, const TCHAR* pCharSet) |
- { |
- int nRet = 0; |
- const TCHAR* p = pStr; |
- while (*p != 0) |
- { |
- const TCHAR* pNext = ::CharNext(p); |
- if(pNext > p + 1) |
- { |
- if(_cstrchr_db(pCharSet, *p, *(p + 1)) == NULL) |
- break; |
- nRet += 2; |
- } |
- else |
- { |
- if(_cstrchr(pCharSet, *p) == NULL) |
- break; |
- nRet++; |
- } |
- p = pNext; |
- } |
- return nRet; |
- } |
- |
- static int _cstrcspn(const TCHAR* pStr, const TCHAR* pCharSet) |
- { |
- int nRet = 0; |
- TCHAR* p = (TCHAR*)pStr; |
- while (*p != 0) |
- { |
- TCHAR* pNext = ::CharNext(p); |
- if(pNext > p + 1) |
- { |
- if(_cstrchr_db(pCharSet, *p, *(p + 1)) != NULL) |
- break; |
- nRet += 2; |
- } |
- else |
- { |
- if(_cstrchr(pCharSet, *p) != NULL) |
- break; |
- nRet++; |
- } |
- p = pNext; |
- } |
- return nRet; |
- } |
- |
- static const TCHAR* _cstrpbrk(const TCHAR* p, const TCHAR* lpszCharSet) |
- { |
- int n = _cstrcspn(p, lpszCharSet); |
- return (p[n] != 0) ? &p[n] : NULL; |
- } |
- |
- static int _cstrisdigit(TCHAR ch) |
- { |
- WORD type; |
- GetStringTypeEx(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type); |
- return (type & C1_DIGIT) == C1_DIGIT; |
- } |
- |
- static int _cstrisspace(TCHAR ch) |
- { |
- WORD type; |
- GetStringTypeEx(GetThreadLocale(), CT_CTYPE1, &ch, 1, &type); |
- return (type & C1_SPACE) == C1_SPACE; |
- } |
- |
- static int _cstrcmp(const TCHAR* pstrOne, const TCHAR* pstrOther) |
- { |
- return lstrcmp(pstrOne, pstrOther); |
- } |
- |
- static int _cstrcmpi(const TCHAR* pstrOne, const TCHAR* pstrOther) |
- { |
- return lstrcmpi(pstrOne, pstrOther); |
- } |
- |
- static int _cstrcoll(const TCHAR* pstrOne, const TCHAR* pstrOther) |
- { |
- int nRet = CompareString(GetThreadLocale(), 0, pstrOne, -1, pstrOther, -1); |
- ATLASSERT(nRet != 0); |
- return nRet - 2; // convert to strcmp convention |
- } |
- |
- static int _cstrcolli(const TCHAR* pstrOne, const TCHAR* pstrOther) |
- { |
- int nRet = CompareString(GetThreadLocale(), NORM_IGNORECASE, pstrOne, -1, pstrOther, -1); |
- ATLASSERT(nRet != 0); |
- return nRet - 2; // convert to strcmp convention |
- } |
- |
- static int _cstrtoi(const TCHAR* nptr) |
- { |
- int c; // current char |
- int total; // current total |
- int sign; // if '-', then negative, otherwise positive |
- |
- while (_cstrisspace(*nptr)) |
- ++nptr; |
- |
- c = (int)(_TUCHAR)*nptr++; |
- sign = c; // save sign indication |
- if (c == _T('-') || c == _T('+')) |
- c = (int)(_TUCHAR)*nptr++; // skip sign |
- |
- total = 0; |
- |
- while (_cstrisdigit((TCHAR)c)) |
- { |
- total = 10 * total + (c - '0'); // accumulate digit |
- c = (int)(_TUCHAR)*nptr++; // get next char |
- } |
- |
- if (sign == '-') |
- return -total; |
- else |
- return total; // return result, negated if necessary |
- } |
-#else // !_ATL_MIN_CRT |
- static const TCHAR* _cstrchr(const TCHAR* p, TCHAR ch) |
- { |
- return _tcschr(p, ch); |
- } |
- |
- static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch) |
- { |
- return _tcsrchr(p, ch); |
- } |
- |
- static TCHAR* _cstrrev(TCHAR* pStr) |
- { |
- return _tcsrev(pStr); |
- } |
- |
- static const TCHAR* _cstrstr(const TCHAR* pStr, const TCHAR* pCharSet) |
- { |
- return _tcsstr(pStr, pCharSet); |
- } |
- |
- static int _cstrspn(const TCHAR* pStr, const TCHAR* pCharSet) |
- { |
- return (int)_tcsspn(pStr, pCharSet); |
- } |
- |
- static int _cstrcspn(const TCHAR* pStr, const TCHAR* pCharSet) |
- { |
- return (int)_tcscspn(pStr, pCharSet); |
- } |
- |
- static const TCHAR* _cstrpbrk(const TCHAR* p, const TCHAR* lpszCharSet) |
- { |
- return _tcspbrk(p, lpszCharSet); |
- } |
- |
- static int _cstrisdigit(TCHAR ch) |
- { |
- return _istdigit(ch); |
- } |
- |
- static int _cstrisspace(TCHAR ch) |
- { |
- return _istspace((_TUCHAR)ch); |
- } |
- |
- static int _cstrcmp(const TCHAR* pstrOne, const TCHAR* pstrOther) |
- { |
- return _tcscmp(pstrOne, pstrOther); |
- } |
- |
- static int _cstrcmpi(const TCHAR* pstrOne, const TCHAR* pstrOther) |
- { |
- return _tcsicmp(pstrOne, pstrOther); |
- } |
- |
-#ifndef _WIN32_WCE |
- static int _cstrcoll(const TCHAR* pstrOne, const TCHAR* pstrOther) |
- { |
- return _tcscoll(pstrOne, pstrOther); |
- } |
- |
- static int _cstrcolli(const TCHAR* pstrOne, const TCHAR* pstrOther) |
- { |
- return _tcsicoll(pstrOne, pstrOther); |
- } |
-#endif // !_WIN32_WCE |
- |
- static int _cstrtoi(const TCHAR* nptr) |
- { |
- return _ttoi(nptr); |
- } |
-#endif // !_ATL_MIN_CRT |
- |
- static const TCHAR* _cstrchr_db(const TCHAR* p, TCHAR ch1, TCHAR ch2) |
- { |
- const TCHAR* lpsz = NULL; |
- while (*p != 0) |
- { |
- if (*p == ch1 && *(p + 1) == ch2) |
- { |
- lpsz = p; |
- break; |
- } |
- p = ::CharNext(p); |
- } |
- return lpsz; |
- } |
-}; |
- |
- |
-// Compare helpers |
- |
-inline bool __stdcall operator ==(const CString& s1, const CString& s2) |
-{ return s1.Compare(s2) == 0; } |
- |
-inline bool __stdcall operator ==(const CString& s1, LPCTSTR s2) |
-{ return s1.Compare(s2) == 0; } |
- |
-inline bool __stdcall operator ==(LPCTSTR s1, const CString& s2) |
-{ return s2.Compare(s1) == 0; } |
- |
-inline bool __stdcall operator !=(const CString& s1, const CString& s2) |
-{ return s1.Compare(s2) != 0; } |
- |
-inline bool __stdcall operator !=(const CString& s1, LPCTSTR s2) |
-{ return s1.Compare(s2) != 0; } |
- |
-inline bool __stdcall operator !=(LPCTSTR s1, const CString& s2) |
-{ return s2.Compare(s1) != 0; } |
- |
-inline bool __stdcall operator <(const CString& s1, const CString& s2) |
-{ return s1.Compare(s2) < 0; } |
- |
-inline bool __stdcall operator <(const CString& s1, LPCTSTR s2) |
-{ return s1.Compare(s2) < 0; } |
- |
-inline bool __stdcall operator <(LPCTSTR s1, const CString& s2) |
-{ return s2.Compare(s1) > 0; } |
- |
-inline bool __stdcall operator >(const CString& s1, const CString& s2) |
-{ return s1.Compare(s2) > 0; } |
- |
-inline bool __stdcall operator >(const CString& s1, LPCTSTR s2) |
-{ return s1.Compare(s2) > 0; } |
- |
-inline bool __stdcall operator >(LPCTSTR s1, const CString& s2) |
-{ return s2.Compare(s1) < 0; } |
- |
-inline bool __stdcall operator <=(const CString& s1, const CString& s2) |
-{ return s1.Compare(s2) <= 0; } |
- |
-inline bool __stdcall operator <=(const CString& s1, LPCTSTR s2) |
-{ return s1.Compare(s2) <= 0; } |
- |
-inline bool __stdcall operator <=(LPCTSTR s1, const CString& s2) |
-{ return s2.Compare(s1) >= 0; } |
- |
-inline bool __stdcall operator >=(const CString& s1, const CString& s2) |
-{ return s1.Compare(s2) >= 0; } |
- |
-inline bool __stdcall operator >=(const CString& s1, LPCTSTR s2) |
-{ return s1.Compare(s2) >= 0; } |
- |
-inline bool __stdcall operator >=(LPCTSTR s1, const CString& s2) |
-{ return s2.Compare(s1) <= 0; } |
- |
- |
-// CString "operator +" functions |
- |
-inline CString __stdcall operator +(const CString& string1, const CString& string2) |
-{ |
- CString s; |
- s.ConcatCopy(string1.GetData()->nDataLength, string1.m_pchData, string2.GetData()->nDataLength, string2.m_pchData); |
- return s; |
-} |
- |
-inline CString __stdcall operator +(const CString& string, TCHAR ch) |
-{ |
- CString s; |
- s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, 1, &ch); |
- return s; |
-} |
- |
-inline CString __stdcall operator +(TCHAR ch, const CString& string) |
-{ |
- CString s; |
- s.ConcatCopy(1, &ch, string.GetData()->nDataLength, string.m_pchData); |
- return s; |
-} |
- |
-#ifdef _UNICODE |
-inline CString __stdcall operator +(const CString& string, char ch) |
-{ |
- return string + (TCHAR)ch; |
-} |
- |
-inline CString __stdcall operator +(char ch, const CString& string) |
-{ |
- return (TCHAR)ch + string; |
-} |
-#endif // _UNICODE |
- |
-inline CString __stdcall operator +(const CString& string, LPCTSTR lpsz) |
-{ |
- ATLASSERT(lpsz == NULL || CString::_IsValidString(lpsz)); |
- CString s; |
- s.ConcatCopy(string.GetData()->nDataLength, string.m_pchData, CString::SafeStrlen(lpsz), lpsz); |
- return s; |
-} |
- |
-inline CString __stdcall operator +(LPCTSTR lpsz, const CString& string) |
-{ |
- ATLASSERT(lpsz == NULL || CString::_IsValidString(lpsz)); |
- CString s; |
- s.ConcatCopy(CString::SafeStrlen(lpsz), lpsz, string.GetData()->nDataLength, string.m_pchData); |
- return s; |
-} |
- |
-#endif // !_WTL_NO_CSTRING |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// CRecentDocumentList - MRU List Support |
- |
-#ifndef _WIN32_WCE |
- |
-#ifndef _WTL_MRUEMPTY_TEXT |
- #define _WTL_MRUEMPTY_TEXT _T("(empty)") |
-#endif |
- |
-// forward declaration |
-inline bool AtlCompactPath(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen); |
- |
-template <class T, int t_cchItemLen = MAX_PATH, int t_nFirstID = ID_FILE_MRU_FIRST, int t_nLastID = ID_FILE_MRU_LAST> |
-class CRecentDocumentListBase |
-{ |
-public: |
-// Declarations |
- struct _DocEntry |
- { |
- TCHAR szDocName[t_cchItemLen]; |
- bool operator ==(const _DocEntry& de) const |
- { return (lstrcmpi(szDocName, de.szDocName) == 0); } |
- }; |
- |
- enum |
- { |
- m_nMaxEntries_Min = 2, |
- m_nMaxEntries_Max = t_nLastID - t_nFirstID + 1, |
- m_cchMaxItemLen_Min = 6, |
- m_cchMaxItemLen_Max = t_cchItemLen, |
- m_cchItemNameLen = 11 |
- }; |
- |
-// Data members |
- ATL::CSimpleArray<_DocEntry> m_arrDocs; |
- int m_nMaxEntries; // default is 4 |
- HMENU m_hMenu; |
- |
- TCHAR m_szNoEntries[t_cchItemLen]; |
- |
- int m_cchMaxItemLen; |
- |
-// Constructor |
- CRecentDocumentListBase() : m_hMenu(NULL), m_nMaxEntries(4), m_cchMaxItemLen(-1) |
- { |
- // These ASSERTs verify values of the template arguments |
- ATLASSERT(t_cchItemLen > m_cchMaxItemLen_Min); |
- ATLASSERT(m_nMaxEntries_Max > m_nMaxEntries_Min); |
- } |
- |
-// Attributes |
- HMENU GetMenuHandle() const |
- { |
- return m_hMenu; |
- } |
- |
- void SetMenuHandle(HMENU hMenu) |
- { |
- ATLASSERT(hMenu == NULL || ::IsMenu(hMenu)); |
- m_hMenu = hMenu; |
- if(m_hMenu == NULL || (::GetMenuString(m_hMenu, t_nFirstID, m_szNoEntries, t_cchItemLen, MF_BYCOMMAND) == 0)) |
- { |
- T* pT = static_cast<T*>(this); |
- pT; // avoid level 4 warning |
- SecureHelper::strncpy_x(m_szNoEntries, _countof(m_szNoEntries), pT->GetMRUEmptyText(), _TRUNCATE); |
- } |
- } |
- |
- int GetMaxEntries() const |
- { |
- return m_nMaxEntries; |
- } |
- |
- void SetMaxEntries(int nMaxEntries) |
- { |
- ATLASSERT(nMaxEntries >= m_nMaxEntries_Min && nMaxEntries <= m_nMaxEntries_Max); |
- if(nMaxEntries < m_nMaxEntries_Min) |
- nMaxEntries = m_nMaxEntries_Min; |
- else if(nMaxEntries > m_nMaxEntries_Max) |
- nMaxEntries = m_nMaxEntries_Max; |
- m_nMaxEntries = nMaxEntries; |
- } |
- |
- int GetMaxItemLength() const |
- { |
- return m_cchMaxItemLen; |
- } |
- |
- void SetMaxItemLength(int cchMaxLen) |
- { |
- ATLASSERT((cchMaxLen >= m_cchMaxItemLen_Min && cchMaxLen <= m_cchMaxItemLen_Max) || cchMaxLen == -1); |
- if(cchMaxLen != -1) |
- { |
- if(cchMaxLen < m_cchMaxItemLen_Min) |
- cchMaxLen = m_cchMaxItemLen_Min; |
- else if(cchMaxLen > m_cchMaxItemLen_Max) |
- cchMaxLen = m_cchMaxItemLen_Max; |
- } |
- m_cchMaxItemLen = cchMaxLen; |
- T* pT = static_cast<T*>(this); |
- pT->UpdateMenu(); |
- } |
- |
-// Operations |
- BOOL AddToList(LPCTSTR lpstrDocName) |
- { |
- _DocEntry de; |
- errno_t nRet = SecureHelper::strncpy_x(de.szDocName, _countof(de.szDocName), lpstrDocName, _TRUNCATE); |
- if(nRet != 0 && nRet != STRUNCATE) |
- return FALSE; |
- |
- for(int i = 0; i < m_arrDocs.GetSize(); i++) |
- { |
- if(lstrcmpi(m_arrDocs[i].szDocName, lpstrDocName) == 0) |
- { |
- m_arrDocs.RemoveAt(i); |
- break; |
- } |
- } |
- |
- if(m_arrDocs.GetSize() == m_nMaxEntries) |
- m_arrDocs.RemoveAt(0); |
- |
- BOOL bRet = m_arrDocs.Add(de); |
- if(bRet) |
- { |
- T* pT = static_cast<T*>(this); |
- bRet = pT->UpdateMenu(); |
- } |
- return bRet; |
- } |
- |
- // This function is deprecated because it is not safe. |
- // Use the version below that accepts the buffer length. |
-#if (_MSC_VER >= 1300) |
- __declspec(deprecated) |
-#endif |
- BOOL GetFromList(int /*nItemID*/, LPTSTR /*lpstrDocName*/) |
- { |
- ATLASSERT(FALSE); |
- return FALSE; |
- } |
- |
- BOOL GetFromList(int nItemID, LPTSTR lpstrDocName, int cchLength) |
- { |
- int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1; |
- if(nIndex < 0 || nIndex >= m_arrDocs.GetSize()) |
- return FALSE; |
- if(lstrlen(m_arrDocs[nIndex].szDocName) >= cchLength) |
- return FALSE; |
- SecureHelper::strcpy_x(lpstrDocName, cchLength, m_arrDocs[nIndex].szDocName); |
- |
- return TRUE; |
- } |
- |
-#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) |
- BOOL GetFromList(int nItemID, _CSTRING_NS::CString& strDocName) |
- { |
- int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1; |
- if(nIndex < 0 || nIndex >= m_arrDocs.GetSize()) |
- return FALSE; |
- strDocName = m_arrDocs[nIndex].szDocName; |
- return TRUE; |
- } |
-#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) |
- |
- BOOL RemoveFromList(int nItemID) |
- { |
- int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1; |
- BOOL bRet = m_arrDocs.RemoveAt(nIndex); |
- if(bRet) |
- { |
- T* pT = static_cast<T*>(this); |
- bRet = pT->UpdateMenu(); |
- } |
- return bRet; |
- } |
- |
- BOOL MoveToTop(int nItemID) |
- { |
- int nIndex = m_arrDocs.GetSize() - (nItemID - t_nFirstID) - 1; |
- if(nIndex < 0 || nIndex >= m_arrDocs.GetSize()) |
- return FALSE; |
- _DocEntry de; |
- de = m_arrDocs[nIndex]; |
- m_arrDocs.RemoveAt(nIndex); |
- BOOL bRet = m_arrDocs.Add(de); |
- if(bRet) |
- { |
- T* pT = static_cast<T*>(this); |
- bRet = pT->UpdateMenu(); |
- } |
- return bRet; |
- } |
- |
- BOOL ReadFromRegistry(LPCTSTR lpstrRegKey) |
- { |
- T* pT = static_cast<T*>(this); |
- ATL::CRegKey rkParent; |
- ATL::CRegKey rk; |
- |
- LONG lRet = rkParent.Open(HKEY_CURRENT_USER, lpstrRegKey); |
- if(lRet != ERROR_SUCCESS) |
- return FALSE; |
- lRet = rk.Open(rkParent, pT->GetRegKeyName()); |
- if(lRet != ERROR_SUCCESS) |
- return FALSE; |
- |
- DWORD dwRet = 0; |
-#if (_ATL_VER >= 0x0700) |
- lRet = rk.QueryDWORDValue(pT->GetRegCountName(), dwRet); |
-#else |
- lRet = rk.QueryValue(dwRet, pT->GetRegCountName()); |
-#endif |
- if(lRet != ERROR_SUCCESS) |
- return FALSE; |
- SetMaxEntries(dwRet); |
- |
- m_arrDocs.RemoveAll(); |
- |
- TCHAR szRetString[t_cchItemLen] = { 0 }; |
- _DocEntry de; |
- |
- for(int nItem = m_nMaxEntries; nItem > 0; nItem--) |
- { |
- TCHAR szBuff[m_cchItemNameLen] = { 0 }; |
- SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem); |
-#if (_ATL_VER >= 0x0700) |
- ULONG ulCount = t_cchItemLen; |
- lRet = rk.QueryStringValue(szBuff, szRetString, &ulCount); |
-#else |
- DWORD dwCount = t_cchItemLen * sizeof(TCHAR); |
- lRet = rk.QueryValue(szRetString, szBuff, &dwCount); |
-#endif |
- if(lRet == ERROR_SUCCESS) |
- { |
- SecureHelper::strcpy_x(de.szDocName, _countof(de.szDocName), szRetString); |
- m_arrDocs.Add(de); |
- } |
- } |
- |
- rk.Close(); |
- rkParent.Close(); |
- |
- return pT->UpdateMenu(); |
- } |
- |
- BOOL WriteToRegistry(LPCTSTR lpstrRegKey) |
- { |
- T* pT = static_cast<T*>(this); |
- pT; // avoid level 4 warning |
- ATL::CRegKey rkParent; |
- ATL::CRegKey rk; |
- |
- LONG lRet = rkParent.Create(HKEY_CURRENT_USER, lpstrRegKey); |
- if(lRet != ERROR_SUCCESS) |
- return FALSE; |
- lRet = rk.Create(rkParent, pT->GetRegKeyName()); |
- if(lRet != ERROR_SUCCESS) |
- return FALSE; |
- |
-#if (_ATL_VER >= 0x0700) |
- lRet = rk.SetDWORDValue(pT->GetRegCountName(), m_nMaxEntries); |
-#else |
- lRet = rk.SetValue(m_nMaxEntries, pT->GetRegCountName()); |
-#endif |
- ATLASSERT(lRet == ERROR_SUCCESS); |
- |
- // set new values |
- int nItem; |
- for(nItem = m_arrDocs.GetSize(); nItem > 0; nItem--) |
- { |
- TCHAR szBuff[m_cchItemNameLen] = { 0 }; |
- SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem); |
- TCHAR szDocName[t_cchItemLen] = { 0 }; |
- GetFromList(t_nFirstID + nItem - 1, szDocName, t_cchItemLen); |
-#if (_ATL_VER >= 0x0700) |
- lRet = rk.SetStringValue(szBuff, szDocName); |
-#else |
- lRet = rk.SetValue(szDocName, szBuff); |
-#endif |
- ATLASSERT(lRet == ERROR_SUCCESS); |
- } |
- |
- // delete unused keys |
- for(nItem = m_arrDocs.GetSize() + 1; nItem < m_nMaxEntries_Max; nItem++) |
- { |
- TCHAR szBuff[m_cchItemNameLen] = { 0 }; |
- SecureHelper::wsprintf_x(szBuff, m_cchItemNameLen, pT->GetRegItemName(), nItem); |
- rk.DeleteValue(szBuff); |
- } |
- |
- rk.Close(); |
- rkParent.Close(); |
- |
- return TRUE; |
- } |
- |
-// Implementation |
- BOOL UpdateMenu() |
- { |
- if(m_hMenu == NULL) |
- return FALSE; |
- ATLASSERT(::IsMenu(m_hMenu)); |
- |
- int nItems = ::GetMenuItemCount(m_hMenu); |
- int nInsertPoint; |
- for(nInsertPoint = 0; nInsertPoint < nItems; nInsertPoint++) |
- { |
- CMenuItemInfo mi; |
- mi.fMask = MIIM_ID; |
- ::GetMenuItemInfo(m_hMenu, nInsertPoint, TRUE, &mi); |
- if (mi.wID == t_nFirstID) |
- break; |
- } |
- ATLASSERT(nInsertPoint < nItems && "You need a menu item with an ID = t_nFirstID"); |
- |
- int nItem; |
- for(nItem = t_nFirstID; nItem < t_nFirstID + m_nMaxEntries; nItem++) |
- { |
- // keep the first one as an insertion point |
- if (nItem != t_nFirstID) |
- ::DeleteMenu(m_hMenu, nItem, MF_BYCOMMAND); |
- } |
- |
- TCHAR szItemText[t_cchItemLen + 6] = { 0 }; // add space for &, 2 digits, and a space |
- int nSize = m_arrDocs.GetSize(); |
- nItem = 0; |
- if(nSize > 0) |
- { |
- for(nItem = 0; nItem < nSize; nItem++) |
- { |
- if(m_cchMaxItemLen == -1) |
- { |
- SecureHelper::wsprintf_x(szItemText, t_cchItemLen + 6, _T("&%i %s"), nItem + 1, m_arrDocs[nSize - 1 - nItem].szDocName); |
- } |
- else |
- { |
- TCHAR szBuff[t_cchItemLen] = { 0 }; |
- T* pT = static_cast<T*>(this); |
- pT; // avoid level 4 warning |
- bool bRet = pT->CompactDocumentName(szBuff, m_arrDocs[nSize - 1 - nItem].szDocName, m_cchMaxItemLen); |
- bRet; // avoid level 4 warning |
- ATLASSERT(bRet); |
- SecureHelper::wsprintf_x(szItemText, t_cchItemLen + 6, _T("&%i %s"), nItem + 1, szBuff); |
- } |
- ::InsertMenu(m_hMenu, nInsertPoint + nItem, MF_BYPOSITION | MF_STRING, t_nFirstID + nItem, szItemText); |
- } |
- } |
- else // empty |
- { |
- ::InsertMenu(m_hMenu, nInsertPoint, MF_BYPOSITION | MF_STRING, t_nFirstID, m_szNoEntries); |
- ::EnableMenuItem(m_hMenu, t_nFirstID, MF_GRAYED); |
- nItem++; |
- } |
- ::DeleteMenu(m_hMenu, nInsertPoint + nItem, MF_BYPOSITION); |
- |
- return TRUE; |
- } |
- |
-// Overrideables |
- // override to provide a different method of compacting document names |
- static bool CompactDocumentName(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen) |
- { |
- return AtlCompactPath(lpstrOut, lpstrIn, cchLen); |
- } |
- |
- static LPCTSTR GetRegKeyName() |
- { |
- return _T("Recent Document List"); |
- } |
- |
- static LPCTSTR GetRegCountName() |
- { |
- return _T("DocumentCount"); |
- } |
- |
- static LPCTSTR GetRegItemName() |
- { |
- // Note: This string is a format string used with wsprintf(). |
- // Resulting formatted string must be m_cchItemNameLen or less |
- // characters long, including the terminating null character. |
- return _T("Document%i"); |
- } |
- |
- static LPCTSTR GetMRUEmptyText() |
- { |
- return _WTL_MRUEMPTY_TEXT; |
- } |
-}; |
- |
-class CRecentDocumentList : public CRecentDocumentListBase<CRecentDocumentList> |
-{ |
-public: |
-// nothing here |
-}; |
- |
-#endif // _WIN32_WCE |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// CFindFile - file search helper class |
- |
-class CFindFile |
-{ |
-public: |
-// Data members |
- WIN32_FIND_DATA m_fd; |
- TCHAR m_lpszRoot[MAX_PATH]; |
- TCHAR m_chDirSeparator; |
- HANDLE m_hFind; |
- BOOL m_bFound; |
- |
-// Constructor/destructor |
- CFindFile() : m_hFind(NULL), m_chDirSeparator(_T('\\')), m_bFound(FALSE) |
- { } |
- |
- ~CFindFile() |
- { |
- Close(); |
- } |
- |
-// Attributes |
- ULONGLONG GetFileSize() const |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- ULARGE_INTEGER nFileSize = { 0 }; |
- |
- if(m_bFound) |
- { |
- nFileSize.LowPart = m_fd.nFileSizeLow; |
- nFileSize.HighPart = m_fd.nFileSizeHigh; |
- } |
- else |
- { |
- nFileSize.QuadPart = 0; |
- } |
- |
- return nFileSize.QuadPart; |
- } |
- |
- BOOL GetFileName(LPTSTR lpstrFileName, int cchLength) const |
- { |
- ATLASSERT(m_hFind != NULL); |
- if(lstrlen(m_fd.cFileName) >= cchLength) |
- return FALSE; |
- |
- if(m_bFound) |
- SecureHelper::strcpy_x(lpstrFileName, cchLength, m_fd.cFileName); |
- |
- return m_bFound; |
- } |
- |
- BOOL GetFilePath(LPTSTR lpstrFilePath, int cchLength) const |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- int nLen = lstrlen(m_lpszRoot); |
-#ifndef _WIN32_WCE |
- ATLASSERT(nLen > 0); |
- if(nLen == 0) |
- return FALSE; |
- |
- bool bAddSep = (m_lpszRoot[nLen - 1] != _T('\\') && m_lpszRoot[nLen - 1] !=_T('/')); |
-#else // CE specific |
- // allow diskless devices (nLen == 0) |
- bool bAddSep = ((nLen == 0) || (m_lpszRoot[nLen - 1] != _T('\\') && m_lpszRoot[nLen - 1] !=_T('/'))); |
-#endif // _WIN32_WCE |
- |
- if((lstrlen(m_lpszRoot) + (bAddSep ? 1 : 0)) >= cchLength) |
- return FALSE; |
- |
- SecureHelper::strcpy_x(lpstrFilePath, cchLength, m_lpszRoot); |
- |
- if(bAddSep) |
- { |
- TCHAR szSeparator[2] = { m_chDirSeparator, 0 }; |
- SecureHelper::strcat_x(lpstrFilePath, cchLength, szSeparator); |
- } |
- |
- SecureHelper::strcat_x(lpstrFilePath, cchLength, m_fd.cFileName); |
- |
- return TRUE; |
- } |
- |
-#ifndef _WIN32_WCE |
- BOOL GetFileTitle(LPTSTR lpstrFileTitle, int cchLength) const |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- TCHAR szBuff[MAX_PATH] = { 0 }; |
- if(!GetFileName(szBuff, MAX_PATH)) |
- return FALSE; |
- |
- if(lstrlen(szBuff) >= cchLength || cchLength < 1) |
- return FALSE; |
- |
- // find the last dot |
- LPTSTR pstrDot = (LPTSTR)_cstrrchr(szBuff, _T('.')); |
- if(pstrDot != NULL) |
- *pstrDot = 0; |
- |
- SecureHelper::strcpy_x(lpstrFileTitle, cchLength, szBuff); |
- |
- return TRUE; |
- } |
-#endif // !_WIN32_WCE |
- |
- BOOL GetFileURL(LPTSTR lpstrFileURL, int cchLength) const |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- TCHAR szBuff[MAX_PATH] = { 0 }; |
- if(!GetFilePath(szBuff, MAX_PATH)) |
- return FALSE; |
- LPCTSTR lpstrFileURLPrefix = _T("file://"); |
- if(lstrlen(szBuff) + lstrlen(lpstrFileURLPrefix) >= cchLength) |
- return FALSE; |
- SecureHelper::strcpy_x(lpstrFileURL, cchLength, lpstrFileURLPrefix); |
- SecureHelper::strcat_x(lpstrFileURL, cchLength, szBuff); |
- |
- return TRUE; |
- } |
- |
- BOOL GetRoot(LPTSTR lpstrRoot, int cchLength) const |
- { |
- ATLASSERT(m_hFind != NULL); |
- if(lstrlen(m_lpszRoot) >= cchLength) |
- return FALSE; |
- |
- SecureHelper::strcpy_x(lpstrRoot, cchLength, m_lpszRoot); |
- |
- return TRUE; |
- } |
- |
-#if defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) |
- _CSTRING_NS::CString GetFileName() const |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- _CSTRING_NS::CString ret; |
- |
- if(m_bFound) |
- ret = m_fd.cFileName; |
- return ret; |
- } |
- |
- _CSTRING_NS::CString GetFilePath() const |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- _CSTRING_NS::CString strResult = m_lpszRoot; |
- int nLen = strResult.GetLength(); |
-#ifndef _WIN32_WCE |
- ATLASSERT(nLen > 0); |
- if(nLen == 0) |
- return strResult; |
- |
- if((strResult[nLen - 1] != _T('\\')) && (strResult[nLen - 1] != _T('/'))) |
-#else // CE specific |
- // allow diskless devices (nLen == 0) |
- if((nLen == 0) || ((strResult[nLen - 1] != _T('\\')) && (strResult[nLen - 1] != _T('/')))) |
-#endif // _WIN32_WCE |
- strResult += m_chDirSeparator; |
- strResult += GetFileName(); |
- return strResult; |
- } |
- |
-#ifndef _WIN32_WCE |
- _CSTRING_NS::CString GetFileTitle() const |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- _CSTRING_NS::CString strResult; |
- GetFileTitle(strResult.GetBuffer(MAX_PATH), MAX_PATH); |
- strResult.ReleaseBuffer(); |
- |
- return strResult; |
- } |
-#endif // !_WIN32_WCE |
- |
- _CSTRING_NS::CString GetFileURL() const |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- _CSTRING_NS::CString strResult("file://"); |
- strResult += GetFilePath(); |
- return strResult; |
- } |
- |
- _CSTRING_NS::CString GetRoot() const |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- _CSTRING_NS::CString str = m_lpszRoot; |
- return str; |
- } |
-#endif // defined(_WTL_USE_CSTRING) || defined(__ATLSTR_H__) |
- |
- BOOL GetLastWriteTime(FILETIME* pTimeStamp) const |
- { |
- ATLASSERT(m_hFind != NULL); |
- ATLASSERT(pTimeStamp != NULL); |
- |
- if(m_bFound && pTimeStamp != NULL) |
- { |
- *pTimeStamp = m_fd.ftLastWriteTime; |
- return TRUE; |
- } |
- |
- return FALSE; |
- } |
- |
- BOOL GetLastAccessTime(FILETIME* pTimeStamp) const |
- { |
- ATLASSERT(m_hFind != NULL); |
- ATLASSERT(pTimeStamp != NULL); |
- |
- if(m_bFound && pTimeStamp != NULL) |
- { |
- *pTimeStamp = m_fd.ftLastAccessTime; |
- return TRUE; |
- } |
- |
- return FALSE; |
- } |
- |
- BOOL GetCreationTime(FILETIME* pTimeStamp) const |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- if(m_bFound && pTimeStamp != NULL) |
- { |
- *pTimeStamp = m_fd.ftCreationTime; |
- return TRUE; |
- } |
- |
- return FALSE; |
- } |
- |
- BOOL MatchesMask(DWORD dwMask) const |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- if(m_bFound) |
- return ((m_fd.dwFileAttributes & dwMask) != 0); |
- |
- return FALSE; |
- } |
- |
- BOOL IsDots() const |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- // return TRUE if the file name is "." or ".." and |
- // the file is a directory |
- |
- BOOL bResult = FALSE; |
- if(m_bFound && IsDirectory()) |
- { |
- if(m_fd.cFileName[0] == _T('.') && (m_fd.cFileName[1] == _T('\0') || (m_fd.cFileName[1] == _T('.') && m_fd.cFileName[2] == _T('\0')))) |
- bResult = TRUE; |
- } |
- |
- return bResult; |
- } |
- |
- BOOL IsReadOnly() const |
- { |
- return MatchesMask(FILE_ATTRIBUTE_READONLY); |
- } |
- |
- BOOL IsDirectory() const |
- { |
- return MatchesMask(FILE_ATTRIBUTE_DIRECTORY); |
- } |
- |
- BOOL IsCompressed() const |
- { |
- return MatchesMask(FILE_ATTRIBUTE_COMPRESSED); |
- } |
- |
- BOOL IsSystem() const |
- { |
- return MatchesMask(FILE_ATTRIBUTE_SYSTEM); |
- } |
- |
- BOOL IsHidden() const |
- { |
- return MatchesMask(FILE_ATTRIBUTE_HIDDEN); |
- } |
- |
- BOOL IsTemporary() const |
- { |
- return MatchesMask(FILE_ATTRIBUTE_TEMPORARY); |
- } |
- |
- BOOL IsNormal() const |
- { |
- return MatchesMask(FILE_ATTRIBUTE_NORMAL); |
- } |
- |
- BOOL IsArchived() const |
- { |
- return MatchesMask(FILE_ATTRIBUTE_ARCHIVE); |
- } |
- |
-// Operations |
- BOOL FindFile(LPCTSTR pstrName = NULL) |
- { |
- Close(); |
- |
- if(pstrName == NULL) |
- { |
- pstrName = _T("*.*"); |
- } |
- else if(lstrlen(pstrName) >= MAX_PATH) |
- { |
- ATLASSERT(FALSE); |
- return FALSE; |
- } |
- |
- SecureHelper::strcpy_x(m_fd.cFileName, _countof(m_fd.cFileName), pstrName); |
- |
- m_hFind = ::FindFirstFile(pstrName, &m_fd); |
- |
- if(m_hFind == INVALID_HANDLE_VALUE) |
- return FALSE; |
- |
-#ifndef _WIN32_WCE |
- bool bFullPath = (::GetFullPathName(pstrName, MAX_PATH, m_lpszRoot, NULL) != 0); |
-#else // CE specific |
- errno_t nRet = SecureHelper::strncpy_x(m_lpszRoot, _countof(m_lpszRoot), pstrName, _TRUNCATE); |
- bool bFullPath = (nRet == 0 || nRet == STRUNCATE); |
-#endif // _WIN32_WCE |
- |
- // passed name isn't a valid path but was found by the API |
- ATLASSERT(bFullPath); |
- if(!bFullPath) |
- { |
- Close(); |
- ::SetLastError(ERROR_INVALID_NAME); |
- return FALSE; |
- } |
- else |
- { |
- // find the last forward or backward whack |
- LPTSTR pstrBack = (LPTSTR)_cstrrchr(m_lpszRoot, _T('\\')); |
- LPTSTR pstrFront = (LPTSTR)_cstrrchr(m_lpszRoot, _T('/')); |
- |
- if(pstrFront != NULL || pstrBack != NULL) |
- { |
- if(pstrFront == NULL) |
- pstrFront = m_lpszRoot; |
- if(pstrBack == NULL) |
- pstrBack = m_lpszRoot; |
- |
- // from the start to the last whack is the root |
- |
- if(pstrFront >= pstrBack) |
- *pstrFront = _T('\0'); |
- else |
- *pstrBack = _T('\0'); |
- } |
- } |
- |
- m_bFound = TRUE; |
- |
- return TRUE; |
- } |
- |
- BOOL FindNextFile() |
- { |
- ATLASSERT(m_hFind != NULL); |
- |
- if(m_hFind == NULL) |
- return FALSE; |
- |
- if(!m_bFound) |
- return FALSE; |
- |
- m_bFound = ::FindNextFile(m_hFind, &m_fd); |
- |
- return m_bFound; |
- } |
- |
- void Close() |
- { |
- m_bFound = FALSE; |
- |
- if(m_hFind != NULL && m_hFind != INVALID_HANDLE_VALUE) |
- { |
- ::FindClose(m_hFind); |
- m_hFind = NULL; |
- } |
- } |
- |
-// Helper |
- static const TCHAR* _cstrrchr(const TCHAR* p, TCHAR ch) |
- { |
-#ifdef _ATL_MIN_CRT |
- const TCHAR* lpsz = NULL; |
- while (*p != 0) |
- { |
- if (*p == ch) |
- lpsz = p; |
- p = ::CharNext(p); |
- } |
- return lpsz; |
-#else // !_ATL_MIN_CRT |
- return _tcsrchr(p, ch); |
-#endif // !_ATL_MIN_CRT |
- } |
-}; |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// Global functions for loading resources |
- |
-inline HACCEL AtlLoadAccelerators(ATL::_U_STRINGorID table) |
-{ |
- return ::LoadAccelerators(ModuleHelper::GetResourceInstance(), table.m_lpstr); |
-} |
- |
-inline HMENU AtlLoadMenu(ATL::_U_STRINGorID menu) |
-{ |
- return ::LoadMenu(ModuleHelper::GetResourceInstance(), menu.m_lpstr); |
-} |
- |
-inline HBITMAP AtlLoadBitmap(ATL::_U_STRINGorID bitmap) |
-{ |
- return ::LoadBitmap(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr); |
-} |
- |
-#ifdef OEMRESOURCE |
-inline HBITMAP AtlLoadSysBitmap(ATL::_U_STRINGorID bitmap) |
-{ |
-#ifdef _DEBUG |
- WORD wID = (WORD)bitmap.m_lpstr; |
- ATLASSERT(wID >= 32734 && wID <= 32767); |
-#endif // _DEBUG |
- return ::LoadBitmap(NULL, bitmap.m_lpstr); |
-} |
-#endif // OEMRESOURCE |
- |
-inline HCURSOR AtlLoadCursor(ATL::_U_STRINGorID cursor) |
-{ |
- return ::LoadCursor(ModuleHelper::GetResourceInstance(), cursor.m_lpstr); |
-} |
- |
-inline HCURSOR AtlLoadSysCursor(LPCTSTR lpCursorName) |
-{ |
-#if (WINVER >= 0x0500) |
- ATLASSERT(lpCursorName == IDC_ARROW || lpCursorName == IDC_IBEAM || lpCursorName == IDC_WAIT || |
- lpCursorName == IDC_CROSS || lpCursorName == IDC_UPARROW || lpCursorName == IDC_SIZE || |
- lpCursorName == IDC_ICON || lpCursorName == IDC_SIZENWSE || lpCursorName == IDC_SIZENESW || |
- lpCursorName == IDC_SIZEWE || lpCursorName == IDC_SIZENS || lpCursorName == IDC_SIZEALL || |
- lpCursorName == IDC_NO || lpCursorName == IDC_APPSTARTING || lpCursorName == IDC_HELP || |
- lpCursorName == IDC_HAND); |
-#else // !(WINVER >= 0x0500) |
- ATLASSERT(lpCursorName == IDC_ARROW || lpCursorName == IDC_IBEAM || lpCursorName == IDC_WAIT || |
- lpCursorName == IDC_CROSS || lpCursorName == IDC_UPARROW || lpCursorName == IDC_SIZE || |
- lpCursorName == IDC_ICON || lpCursorName == IDC_SIZENWSE || lpCursorName == IDC_SIZENESW || |
- lpCursorName == IDC_SIZEWE || lpCursorName == IDC_SIZENS || lpCursorName == IDC_SIZEALL || |
- lpCursorName == IDC_NO || lpCursorName == IDC_APPSTARTING || lpCursorName == IDC_HELP); |
-#endif // !(WINVER >= 0x0500) |
- return ::LoadCursor(NULL, lpCursorName); |
-} |
- |
-inline HICON AtlLoadIcon(ATL::_U_STRINGorID icon) |
-{ |
- return ::LoadIcon(ModuleHelper::GetResourceInstance(), icon.m_lpstr); |
-} |
- |
-#ifndef _WIN32_WCE |
-inline HICON AtlLoadSysIcon(LPCTSTR lpIconName) |
-{ |
-#if (WINVER >= 0x0600) |
- ATLASSERT(lpIconName == IDI_APPLICATION || lpIconName == IDI_ASTERISK || lpIconName == IDI_EXCLAMATION || |
- lpIconName == IDI_HAND || lpIconName == IDI_QUESTION || lpIconName == IDI_WINLOGO || |
- lpIconName == IDI_SHIELD); |
-#else // !(WINVER >= 0x0600) |
- ATLASSERT(lpIconName == IDI_APPLICATION || lpIconName == IDI_ASTERISK || lpIconName == IDI_EXCLAMATION || |
- lpIconName == IDI_HAND || lpIconName == IDI_QUESTION || lpIconName == IDI_WINLOGO); |
-#endif // !(WINVER >= 0x0600) |
- return ::LoadIcon(NULL, lpIconName); |
-} |
-#endif // !_WIN32_WCE |
- |
-inline HBITMAP AtlLoadBitmapImage(ATL::_U_STRINGorID bitmap, UINT fuLoad = LR_DEFAULTCOLOR) |
-{ |
- return (HBITMAP)::LoadImage(ModuleHelper::GetResourceInstance(), bitmap.m_lpstr, IMAGE_BITMAP, 0, 0, fuLoad); |
-} |
- |
-inline HCURSOR AtlLoadCursorImage(ATL::_U_STRINGorID cursor, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0) |
-{ |
- return (HCURSOR)::LoadImage(ModuleHelper::GetResourceInstance(), cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad); |
-} |
- |
-inline HICON AtlLoadIconImage(ATL::_U_STRINGorID icon, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0) |
-{ |
- return (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad); |
-} |
- |
-#ifdef OEMRESOURCE |
-inline HBITMAP AtlLoadSysBitmapImage(WORD wBitmapID, UINT fuLoad = LR_DEFAULTCOLOR) |
-{ |
- ATLASSERT(wBitmapID >= 32734 && wBitmapID <= 32767); |
- ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0); // this one doesn't load from a file |
- return (HBITMAP)::LoadImage(NULL, MAKEINTRESOURCE(wBitmapID), IMAGE_BITMAP, 0, 0, fuLoad); |
-} |
-#endif // OEMRESOURCE |
- |
-inline HCURSOR AtlLoadSysCursorImage(ATL::_U_STRINGorID cursor, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0) |
-{ |
-#ifdef _DEBUG |
- WORD wID = (WORD)cursor.m_lpstr; |
- ATLASSERT((wID >= 32512 && wID <= 32516) || (wID >= 32640 && wID <= 32648) || (wID == 32650) || (wID == 32651)); |
- ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0); // this one doesn't load from a file |
-#endif // _DEBUG |
- return (HCURSOR)::LoadImage(NULL, cursor.m_lpstr, IMAGE_CURSOR, cxDesired, cyDesired, fuLoad); |
-} |
- |
-inline HICON AtlLoadSysIconImage(ATL::_U_STRINGorID icon, UINT fuLoad = LR_DEFAULTCOLOR | LR_DEFAULTSIZE, int cxDesired = 0, int cyDesired = 0) |
-{ |
-#ifdef _DEBUG |
- WORD wID = (WORD)icon.m_lpstr; |
- ATLASSERT(wID >= 32512 && wID <= 32517); |
- ATLASSERT((fuLoad & LR_LOADFROMFILE) == 0); // this one doesn't load from a file |
-#endif // _DEBUG |
- return (HICON)::LoadImage(NULL, icon.m_lpstr, IMAGE_ICON, cxDesired, cyDesired, fuLoad); |
-} |
- |
-#if (_ATL_VER < 0x0700) |
-inline int AtlLoadString(UINT uID, LPTSTR lpBuffer, int nBufferMax) |
-{ |
- return ::LoadString(_Module.GetResourceInstance(), uID, lpBuffer, nBufferMax); |
-} |
-#endif // (_ATL_VER < 0x0700) |
- |
-#ifdef _WIN32_WCE // CE only direct access to the resource |
-inline LPCTSTR AtlLoadString(UINT uID) |
-{ |
- LPCTSTR s = (LPCTSTR)::LoadString(ModuleHelper::GetResourceInstance(), uID, NULL, 0); |
-#ifdef DEBUG // Check for null-termination |
- if(s != NULL) |
- // Note: RC -n <file.rc> compiles null-terminated resource strings |
- ATLASSERT(s[*((WORD*)s -1) - 1] == L'\0'); |
-#endif |
- return s; |
-} |
-#endif // _WIN32_WCE |
- |
-inline bool AtlLoadString(UINT uID, BSTR& bstrText) |
-{ |
- USES_CONVERSION; |
- ATLASSERT(bstrText == NULL); |
- |
- LPTSTR lpstrText = NULL; |
- int nRes = 0; |
- for(int nLen = 256; ; nLen *= 2) |
- { |
- ATLTRY(lpstrText = new TCHAR[nLen]); |
- if(lpstrText == NULL) |
- break; |
- nRes = ::LoadString(ModuleHelper::GetResourceInstance(), uID, lpstrText, nLen); |
- if(nRes < nLen - 1) |
- break; |
- delete [] lpstrText; |
- lpstrText = NULL; |
- } |
- |
- if(lpstrText != NULL) |
- { |
- if(nRes != 0) |
- bstrText = ::SysAllocString(T2OLE(lpstrText)); |
- delete [] lpstrText; |
- } |
- |
- return (bstrText != NULL) ? true : false; |
-} |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// Global functions for stock GDI objects |
- |
-inline HPEN AtlGetStockPen(int nPen) |
-{ |
-#if (_WIN32_WINNT >= 0x0500) && !defined(_WIN32_WCE) |
- ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN || nPen == DC_PEN); |
-#else |
- ATLASSERT(nPen == WHITE_PEN || nPen == BLACK_PEN || nPen == NULL_PEN); |
-#endif |
- return (HPEN)::GetStockObject(nPen); |
-} |
- |
-inline HBRUSH AtlGetStockBrush(int nBrush) |
-{ |
-#if (_WIN32_WINNT >= 0x0500) && !defined(_WIN32_WCE) |
- ATLASSERT((nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH) || nBrush == DC_BRUSH); |
-#else |
- ATLASSERT(nBrush >= WHITE_BRUSH && nBrush <= HOLLOW_BRUSH); |
-#endif |
- return (HBRUSH)::GetStockObject(nBrush); |
-} |
- |
-inline HFONT AtlGetStockFont(int nFont) |
-{ |
-#ifndef _WIN32_WCE |
- ATLASSERT((nFont >= OEM_FIXED_FONT && nFont <= SYSTEM_FIXED_FONT) || nFont == DEFAULT_GUI_FONT); |
-#else // CE specific |
- ATLASSERT(nFont == SYSTEM_FONT); |
-#endif // _WIN32_WCE |
- return (HFONT)::GetStockObject(nFont); |
-} |
- |
-inline HPALETTE AtlGetStockPalette(int nPalette) |
-{ |
- ATLASSERT(nPalette == DEFAULT_PALETTE); // the only one supported |
- return (HPALETTE)::GetStockObject(nPalette); |
-} |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// Global function for compacting a path by replacing parts with ellipsis |
- |
-// helper for multi-byte character sets |
-inline bool _IsDBCSTrailByte(LPCTSTR lpstr, int nChar) |
-{ |
-#ifndef _UNICODE |
- int i = nChar; |
- for( ; i > 0; i--) |
- { |
- if(!::IsDBCSLeadByte(lpstr[i - 1])) |
- break; |
- } |
- return ((nChar > 0) && (((nChar - i) & 1) != 0)); |
-#else // _UNICODE |
- lpstr; nChar; |
- return false; |
-#endif // _UNICODE |
-} |
- |
-inline bool AtlCompactPath(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen) |
-{ |
- ATLASSERT(lpstrOut != NULL); |
- ATLASSERT(lpstrIn != NULL); |
- ATLASSERT(cchLen > 0); |
- |
- LPCTSTR szEllipsis = _T("..."); |
- const int cchEndEllipsis = 3; |
- const int cchMidEllipsis = 4; |
- |
- if(lstrlen(lpstrIn) < cchLen) |
- { |
- SecureHelper::strcpy_x(lpstrOut, cchLen, lpstrIn); |
- return true; |
- } |
- |
- lpstrOut[0] = 0; |
- |
- // check if the separator is a slash or a backslash |
- TCHAR chSlash = _T('\\'); |
- for(LPTSTR lpstr = (LPTSTR)lpstrIn; *lpstr != 0; lpstr = ::CharNext(lpstr)) |
- { |
- if((*lpstr == _T('/')) || (*lpstr == _T('\\'))) |
- chSlash = *lpstr; |
- } |
- |
- // find the filename portion of the path |
- LPCTSTR lpstrFileName = lpstrIn; |
- for(LPCTSTR pPath = lpstrIn; *pPath; pPath = ::CharNext(pPath)) |
- { |
- if((pPath[0] == _T('\\') || pPath[0] == _T(':') || pPath[0] == _T('/')) |
- && pPath[1] && pPath[1] != _T('\\') && pPath[1] != _T('/')) |
- lpstrFileName = pPath + 1; |
- } |
- int cchFileName = lstrlen(lpstrFileName); |
- |
- // handle just the filename without a path |
- if(lpstrFileName == lpstrIn && cchLen > cchEndEllipsis) |
- { |
- bool bRet = (SecureHelper::strncpy_x(lpstrOut, cchLen, lpstrIn, cchLen - cchEndEllipsis - 1) == 0); |
- if(bRet) |
- { |
-#ifndef _UNICODE |
- if(_IsDBCSTrailByte(lpstrIn, cchLen - cchEndEllipsis)) |
- lpstrOut[cchLen - cchEndEllipsis - 1] = 0; |
-#endif // _UNICODE |
- SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis); |
- } |
- return bRet; |
- } |
- |
- // handle just ellipsis |
- if((cchLen < (cchMidEllipsis + cchEndEllipsis))) |
- { |
- for(int i = 0; i < cchLen - 1; i++) |
- lpstrOut[i] = ((i + 1) == cchMidEllipsis) ? chSlash : _T('.'); |
- lpstrOut[cchLen - 1] = 0; |
- return true; |
- } |
- |
- // calc how much we have to copy |
- int cchToCopy = cchLen - (cchMidEllipsis + cchFileName) - 1; |
- |
- if(cchToCopy < 0) |
- cchToCopy = 0; |
- |
-#ifndef _UNICODE |
- if(cchToCopy > 0 && _IsDBCSTrailByte(lpstrIn, cchToCopy)) |
- cchToCopy--; |
-#endif // _UNICODE |
- |
- bool bRet = (SecureHelper::strncpy_x(lpstrOut, cchLen, lpstrIn, cchToCopy) == 0); |
- if(!bRet) |
- return false; |
- |
- // add ellipsis |
- SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis); |
- if(!bRet) |
- return false; |
- TCHAR szSlash[2] = { chSlash, 0 }; |
- SecureHelper::strcat_x(lpstrOut, cchLen, szSlash); |
- if(!bRet) |
- return false; |
- |
- // add filename (and ellipsis, if needed) |
- if(cchLen > (cchMidEllipsis + cchFileName)) |
- { |
- SecureHelper::strcat_x(lpstrOut, cchLen, lpstrFileName); |
- } |
- else |
- { |
- cchToCopy = cchLen - cchMidEllipsis - cchEndEllipsis - 1; |
-#ifndef _UNICODE |
- if(cchToCopy > 0 && _IsDBCSTrailByte(lpstrFileName, cchToCopy)) |
- cchToCopy--; |
-#endif // _UNICODE |
- bRet = (SecureHelper::strncpy_x(&lpstrOut[cchMidEllipsis], cchLen - cchMidEllipsis, lpstrFileName, cchToCopy) == 0); |
- if(bRet) |
- SecureHelper::strcat_x(lpstrOut, cchLen, szEllipsis); |
- } |
- |
- return bRet; |
-} |
- |
-}; // namespace WTL |
- |
-#endif // __ATLMISC_H__ |