📄 atsstring.h
字号:
if (lpszLast == NULL)
lpszLast = lpsz;
}
else
{
lpszLast = NULL;
}
lpsz = ::CharNext(lpsz);
}
if (lpszLast != NULL)
{
// truncate at trailing space start
*lpszLast = '\0';
GetData()->nDataLength = (int)(ADWORD_PTR)(lpszLast - m_pchData);
}
}
inline void CAtsString::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)(ADWORD_PTR)(lpsz - m_pchData);
memmove(m_pchData, lpsz, (nDataLength + 1) * sizeof(TCHAR));
GetData()->nDataLength = nDataLength;
}
inline void CAtsString::TrimRight(LPCTSTR lpszTargetList)
{
// find beginning of trailing matches
// by starting at beginning (DBCS aware)
CopyBeforeWrite();
LPTSTR lpsz = m_pchData;
LPTSTR lpszLast = NULL;
while (*lpsz != '\0')
{
if (_cstrchr(lpszTargetList, *lpsz) != NULL)
{
if (lpszLast == NULL)
lpszLast = lpsz;
}
else
lpszLast = NULL;
lpsz = ::CharNext(lpsz);
}
if (lpszLast != NULL)
{
// truncate at left-most matching character
*lpszLast = '\0';
GetData()->nDataLength = (int)(ADWORD_PTR)(lpszLast - m_pchData);
}
}
inline void CAtsString::TrimRight(TCHAR chTarget)
{
// find beginning of trailing matches
// by starting at beginning (DBCS aware)
CopyBeforeWrite();
LPTSTR lpsz = m_pchData;
LPTSTR lpszLast = NULL;
while (*lpsz != '\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 = '\0';
GetData()->nDataLength = (int)(ADWORD_PTR)(lpszLast - m_pchData);
}
}
inline void CAtsString::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 != '\0')
{
if (_cstrchr(lpszTargets, *lpsz) == NULL)
break;
lpsz = ::CharNext(lpsz);
}
if (lpsz != m_pchData)
{
// fix up data and length
int nDataLength = GetData()->nDataLength - (int)(ADWORD_PTR)(lpsz - m_pchData);
memmove(m_pchData, lpsz, (nDataLength + 1) * sizeof(TCHAR));
GetData()->nDataLength = nDataLength;
}
}
inline void CAtsString::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)(ADWORD_PTR)(lpsz - m_pchData);
memmove(m_pchData, lpsz, (nDataLength + 1) * sizeof(TCHAR));
GetData()->nDataLength = nDataLength;
}
}
inline int CAtsString::Delete(int nIndex, int nCount /* = 1 */)
{
if (nIndex < 0)
nIndex = 0;
int nNewLength = GetData()->nDataLength;
if (nCount > 0 && nIndex < nNewLength)
{
CopyBeforeWrite();
int nBytesToCopy = nNewLength - (nIndex + nCount) + 1;
memmove(m_pchData + nIndex, m_pchData + nIndex + nCount, nBytesToCopy * sizeof(TCHAR));
GetData()->nDataLength = nNewLength - nCount;
}
return nNewLength;
}
inline int CAtsString::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)
{
CAtsStringData* pOldData = GetData();
LPTSTR pstr = m_pchData;
if(!AllocBuffer(nNewLength))
return -1;
memcpy(m_pchData, pstr, (pOldData->nDataLength + 1) * sizeof(TCHAR));
CAtsString::Release(pOldData);
}
// move existing bytes down
memmove(m_pchData + nIndex + 1, m_pchData + nIndex, (nNewLength - nIndex) * sizeof(TCHAR));
m_pchData[nIndex] = ch;
GetData()->nDataLength = nNewLength;
return nNewLength;
}
inline int CAtsString::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)
{
CAtsStringData* pOldData = GetData();
LPTSTR pstr = m_pchData;
if(!AllocBuffer(nNewLength))
return -1;
memcpy(m_pchData, pstr, (pOldData->nDataLength + 1) * sizeof(TCHAR));
CAtsString::Release(pOldData);
}
// move existing bytes down
memmove(m_pchData + nIndex + nInsertLength, m_pchData + nIndex, (nNewLength - nIndex - nInsertLength + 1) * sizeof(TCHAR));
memcpy(m_pchData + nIndex, pstr, nInsertLength * sizeof(TCHAR));
GetData()->nDataLength = nNewLength;
}
return nNewLength;
}
inline int CAtsString::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;
}
inline int CAtsString::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;
while (lpszStart < lpszEnd)
{
while ((lpszTarget = _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)
{
CAtsStringData* pOldData = GetData();
LPTSTR pstr = m_pchData;
if(!AllocBuffer(nNewLength))
return -1;
memcpy(m_pchData, pstr, pOldData->nDataLength * sizeof(TCHAR));
CAtsString::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 = _cstrstr(lpszStart, lpszOld)) != NULL)
{
int nBalance = nOldLength - ((int)(ADWORD_PTR)(lpszTarget - m_pchData) + nSourceLen);
memmove(lpszTarget + nReplacementLen, lpszTarget + nSourceLen, nBalance * sizeof(TCHAR));
memcpy(lpszTarget, lpszNew, nReplacementLen * sizeof(TCHAR));
lpszStart = lpszTarget + nReplacementLen;
lpszStart[nBalance] = '\0';
nOldLength += (nReplacementLen - nSourceLen);
}
lpszStart += lstrlen(lpszStart) + 1;
}
ATLASSERT(m_pchData[nNewLength] == '\0');
GetData()->nDataLength = nNewLength;
}
return nCount;
}
inline int CAtsString::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 = '\0';
int nCount = (int)(ADWORD_PTR)(pstrSource - pstrDest);
GetData()->nDataLength -= nCount;
return nCount;
}
#ifdef _UNICODE
#define CHAR_FUDGE 1 // one TCHAR unused is good enough
#else
#define CHAR_FUDGE 2 // two BYTES unused for case of DBC last char
#endif
inline BOOL CAtsString::LoadString(UINT nID)
{
// 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 _ATL_NO_COM
inline BSTR CAtsString::AllocSysString() const
{
#if defined(_UNICODE) || defined(OLE2ANSI)
BSTR bstr = ::SysAlloCAtsStringLen(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;
}
inline BSTR CAtsString::SetSysString(BSTR* pbstr) const
{
#if defined(_UNICODE) || defined(OLE2ANSI)
::SysReAlloCAtsStringLen(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
#endif //!_WTL_NO_CAtsString
/////////////////////////////////////////////////////////////////////////////
// CRecentDocumentList - MRU List Support
#ifndef _WTL_MRUEMPTY_TEXT
#define _WTL_MRUEMPTY_TEXT _T("(empty)")
#endif
// forward declaration
inline bool AtlCompactPath(LPTSTR lpstrOut, LPCTSTR lpstrIn, int cchLen);
/////////////////////////////////////////////////////////////////////////////
// Global functions for loading resources
#if (_ATL_VER < 0x0700)
inline int AtlLoadString(UINT uID, LPTSTR lpBuffer, int nBufferMax)
{
return 0;// return ::LoadString(_Module.GetResourceInstance(), uID, lpBuffer, nBufferMax);
}
#endif //(_ATL_VER < 0x0700)
inline bool AtlLoadString(UINT uID, BSTR& bstrText)
{
/*jonfei
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(_Module.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;*/
return false;
}
/////////////////////////////////////////////////////////////////////////////
// Global functions for stock GDI objects
/////////////////////////////////////////////////////////////////////////////
// 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
for(int i = nChar; 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) + 1 < cchLen)
return (lstrcpy(lpstrOut, lpstrIn) != NULL);
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 = (lstrcpyn(lpstrOut, lpstrIn, cchLen - cchEndEllipsis) != NULL);
if(bRet)
{
#ifndef _UNICODE
if(_IsDBCSTrailByte(lpstrIn, cchLen - cchEndEllipsis))
lpstrOut[cchLen - cchEndEllipsis - 1] = 0;
#endif //_UNICODE
bRet = (lstrcat(lpstrOut, szEllipsis) != NULL);
}
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[i] = 0;
return true;
}
// calc how much we have to copy
int cchToCopy = cchLen - (cchMidEllipsis + cchFileName);
if(cchToCopy < 0)
cchToCopy = 0;
#ifndef _UNICODE
if(cchToCopy > 0 && _IsDBCSTrailByte(lpstrIn, cchToCopy))
cchToCopy--;
#endif //_UNICODE
bool bRet = (lstrcpyn(lpstrOut, lpstrIn, cchToCopy) != NULL);
if(!bRet)
return false;
// add ellipsis
bRet = (lstrcat(lpstrOut, szEllipsis) != NULL);
if(!bRet)
return false;
TCHAR szSlash[2] = { chSlash, 0 };
bRet = (lstrcat(lpstrOut, szSlash) != NULL);
if(!bRet)
return false;
// add filename (and ellipsis, if needed)
if(cchLen > (cchMidEllipsis + cchFileName))
{
bRet = (lstrcat(lpstrOut, lpstrFileName) != NULL);
}
else
{
cchToCopy = cchLen - cchMidEllipsis - cchEndEllipsis;
#ifndef _UNICODE
if(cchToCopy > 0 && _IsDBCSTrailByte(lpstrFileName, cchToCopy))
cchToCopy--;
#endif //_UNICODE
bRet = (lstrcpyn(&lpstrOut[cchMidEllipsis], lpstrFileName, cchToCopy) != NULL);
if(bRet)
bRet = (lstrcat(lpstrOut, szEllipsis) != NULL);
}
return bRet;
}
#endif // __ACTIVESTRING_H__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -