Index: third_party/wtl/include/atlfind.h |
diff --git a/third_party/wtl/include/atlfind.h b/third_party/wtl/include/atlfind.h |
deleted file mode 100644 |
index 35a630e79470545665f16ebc7ab634908b8dd474..0000000000000000000000000000000000000000 |
--- a/third_party/wtl/include/atlfind.h |
+++ /dev/null |
@@ -1,1033 +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 __ATLFIND_H__ |
-#define __ATLFIND_H__ |
- |
-#pragma once |
- |
-#ifndef __cplusplus |
- #error ATL requires C++ compilation (use a .cpp suffix) |
-#endif |
- |
-#ifdef _WIN32_WCE |
- #error atlfind.h is not supported on Windows CE |
-#endif |
- |
-#ifndef __ATLCTRLS_H__ |
- #error atlfind.h requires atlctrls.h to be included first |
-#endif |
- |
-#ifndef __ATLDLGS_H__ |
- #error atlfind.h requires atldlgs.h to be included first |
-#endif |
- |
-#if !((defined(__ATLMISC_H__) && defined(_WTL_USE_CSTRING)) || defined(__ATLSTR_H__)) |
- #error atlfind.h requires CString (either from ATL's atlstr.h or WTL's atlmisc.h with _WTL_USE_CSTRING) |
-#endif |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// Classes in this file: |
-// |
-// CEditFindReplaceImplBase<T, TFindReplaceDialog> |
-// CEditFindReplaceImpl<T, TFindReplaceDialog> |
-// CRichEditFindReplaceImpl<T, TFindReplaceDialog> |
- |
- |
-namespace WTL |
-{ |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// CEditFindReplaceImplBase - Base class for mixin classes that |
-// help implement Find/Replace for CEdit or CRichEditCtrl based window classes. |
- |
-template <class T, class TFindReplaceDialog = CFindReplaceDialog> |
-class CEditFindReplaceImplBase |
-{ |
-protected: |
-// Typedefs |
- typedef CEditFindReplaceImplBase<T, TFindReplaceDialog> thisClass; |
- |
-// Data members |
- TFindReplaceDialog* m_pFindReplaceDialog; |
- _CSTRING_NS::CString m_sFindNext, m_sReplaceWith; |
- BOOL m_bFindOnly, m_bFirstSearch, m_bMatchCase, m_bWholeWord, m_bFindDown; |
- LONG m_nInitialSearchPos; |
- HCURSOR m_hOldCursor; |
- |
-// Enumerations |
- enum TranslationTextItem |
- { |
- eText_OnReplaceAllMessage = 0, |
- eText_OnReplaceAllTitle = 1, |
- eText_OnTextNotFoundMessage = 2, |
- eText_OnTextNotFoundTitle = 3 |
- }; |
- |
-public: |
-// Constructors |
- CEditFindReplaceImplBase() : |
- m_pFindReplaceDialog(NULL), |
- m_bFindOnly(TRUE), |
- m_bFirstSearch(TRUE), |
- m_bMatchCase(FALSE), |
- m_bWholeWord(FALSE), |
- m_bFindDown(TRUE), |
- m_nInitialSearchPos(0), |
- m_hOldCursor(NULL) |
- { |
- } |
- |
-// Message Handlers |
- BEGIN_MSG_MAP(thisClass) |
- ALT_MSG_MAP(1) |
- MESSAGE_HANDLER(WM_DESTROY, OnDestroy) |
- MESSAGE_HANDLER(TFindReplaceDialog::GetFindReplaceMsg(), OnFindReplaceCmd) |
- COMMAND_ID_HANDLER(ID_EDIT_FIND, OnEditFind) |
- COMMAND_ID_HANDLER(ID_EDIT_REPEAT, OnEditRepeat) |
- COMMAND_ID_HANDLER(ID_EDIT_REPLACE, OnEditReplace) |
- END_MSG_MAP() |
- |
- LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled) |
- { |
- if(m_pFindReplaceDialog != NULL) |
- { |
- m_pFindReplaceDialog->SendMessage(WM_CLOSE); |
- ATLASSERT(m_pFindReplaceDialog == NULL); |
- } |
- |
- bHandled = FALSE; |
- return 0; |
- } |
- |
- LRESULT OnFindReplaceCmd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) |
- { |
- T* pT = static_cast<T*>(this); |
- |
- TFindReplaceDialog* pDialog = TFindReplaceDialog::GetNotifier(lParam); |
- if(pDialog == NULL) |
- { |
- ATLASSERT(FALSE); |
- ::MessageBeep(MB_ICONERROR); |
- return 1; |
- } |
- ATLASSERT(pDialog == m_pFindReplaceDialog); |
- |
- LPFINDREPLACE findReplace = (LPFINDREPLACE)lParam; |
- if((m_pFindReplaceDialog != NULL) && (findReplace != NULL)) |
- { |
- if(pDialog->FindNext()) |
- { |
- pT->OnFindNext(pDialog->GetFindString(), pDialog->SearchDown(), |
- pDialog->MatchCase(), pDialog->MatchWholeWord()); |
- } |
- else if(pDialog->ReplaceCurrent()) |
- { |
- pT->OnReplaceSel(pDialog->GetFindString(), |
- pDialog->SearchDown(), pDialog->MatchCase(), pDialog->MatchWholeWord(), |
- pDialog->GetReplaceString()); |
- } |
- else if(pDialog->ReplaceAll()) |
- { |
- pT->OnReplaceAll(pDialog->GetFindString(), pDialog->GetReplaceString(), |
- pDialog->MatchCase(), pDialog->MatchWholeWord()); |
- } |
- else if(pDialog->IsTerminating()) |
- { |
- // Dialog is going away (but hasn't gone away yet) |
- // OnFinalMessage will "delete this" |
- pT->OnTerminatingFindReplaceDialog(m_pFindReplaceDialog); |
- m_pFindReplaceDialog = NULL; |
- } |
- } |
- |
- return 0; |
- } |
- |
- LRESULT OnEditFind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
- { |
- T* pT = static_cast<T*>(this); |
- pT->FindReplace(TRUE); |
- |
- return 0; |
- } |
- |
- LRESULT OnEditRepeat(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/) |
- { |
- T* pT = static_cast<T*>(this); |
- |
- // If the user is holding down SHIFT when hitting F3, we'll |
- // search in reverse. Otherwise, we'll search forward. |
- // (be sure to have an accelerator mapped to ID_EDIT_REPEAT |
- // for both F3 and Shift+F3) |
- m_bFindDown = !((::GetKeyState(VK_SHIFT) & 0x8000) == 0x8000); |
- |
- if(m_sFindNext.IsEmpty()) |
- { |
- pT->FindReplace(TRUE); |
- } |
- else |
- { |
- if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)) |
- pT->TextNotFound(m_sFindNext); |
- } |
- |
- return 0; |
- } |
- |
- LRESULT OnEditReplace(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& bHandled) |
- { |
- T* pT = static_cast<T*>(this); |
- |
- DWORD style = pT->GetStyle(); |
- if((style & ES_READONLY) != ES_READONLY) |
- { |
- pT->FindReplace(FALSE); |
- } |
- else |
- { |
- // Don't allow replace when the edit control is read only |
- bHandled = FALSE; |
- } |
- |
- return 0; |
- } |
- |
-// Operations (overrideable) |
- TFindReplaceDialog* CreateFindReplaceDialog(BOOL bFindOnly, // TRUE for Find, FALSE for FindReplace |
- LPCTSTR lpszFindWhat, |
- LPCTSTR lpszReplaceWith = NULL, |
- DWORD dwFlags = FR_DOWN, |
- HWND hWndParent = NULL) |
- { |
- // You can override all of this in a derived class |
- |
- TFindReplaceDialog* findReplaceDialog = new TFindReplaceDialog(); |
- if(findReplaceDialog == NULL) |
- { |
- ::MessageBeep(MB_ICONHAND); |
- } |
- else |
- { |
- HWND hWndFindReplace = findReplaceDialog->Create(bFindOnly, |
- lpszFindWhat, lpszReplaceWith, dwFlags, hWndParent); |
- if(hWndFindReplace == NULL) |
- { |
- delete findReplaceDialog; |
- findReplaceDialog = NULL; |
- } |
- else |
- { |
- findReplaceDialog->SetActiveWindow(); |
- findReplaceDialog->ShowWindow(SW_SHOW); |
- } |
- } |
- |
- return findReplaceDialog; |
- } |
- |
- void AdjustDialogPosition(HWND hWndDialog) |
- { |
- ATLASSERT((hWndDialog != NULL) && ::IsWindow(hWndDialog)); |
- |
- T* pT = static_cast<T*>(this); |
- LONG nStartChar = 0, nEndChar = 0; |
- // Send EM_GETSEL so we can use both Edit and RichEdit |
- // (CEdit::GetSel uses int&, and CRichEditCtrlT::GetSel uses LONG&) |
- ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar); |
- POINT point = pT->PosFromChar(nStartChar); |
- ::ClientToScreen(pT->GetParent(), &point); |
- CRect rect; |
- ::GetWindowRect(hWndDialog, &rect); |
- if(rect.PtInRect(point)) |
- { |
- if(point.y > rect.Height()) |
- { |
- rect.OffsetRect(0, point.y - rect.bottom - 20); |
- } |
- else |
- { |
- int nVertExt = GetSystemMetrics(SM_CYSCREEN); |
- if(point.y + rect.Height() < nVertExt) |
- rect.OffsetRect(0, 40 + point.y - rect.top); |
- } |
- |
- ::MoveWindow(hWndDialog, rect.left, rect.top, rect.Width(), rect.Height(), TRUE); |
- } |
- } |
- |
- DWORD GetFindReplaceDialogFlags(void) const |
- { |
- DWORD dwFlags = 0; |
- |
- if(m_bFindDown) |
- dwFlags |= FR_DOWN; |
- if(m_bMatchCase) |
- dwFlags |= FR_MATCHCASE; |
- if(m_bWholeWord) |
- dwFlags |= FR_WHOLEWORD; |
- |
- return dwFlags; |
- } |
- |
- void FindReplace(BOOL bFindOnly) |
- { |
- T* pT = static_cast<T*>(this); |
- m_bFirstSearch = TRUE; |
- if(m_pFindReplaceDialog != NULL) |
- { |
- if(m_bFindOnly == bFindOnly) |
- { |
- m_pFindReplaceDialog->SetActiveWindow(); |
- m_pFindReplaceDialog->ShowWindow(SW_SHOW); |
- return; |
- } |
- else |
- { |
- m_pFindReplaceDialog->SendMessage(WM_CLOSE); |
- ATLASSERT(m_pFindReplaceDialog == NULL); |
- } |
- } |
- |
- ATLASSERT(m_pFindReplaceDialog == NULL); |
- |
- _CSTRING_NS::CString findNext; |
- pT->GetSelText(findNext); |
- // if selection is empty or spans multiple lines use old find text |
- if(findNext.IsEmpty() || (findNext.FindOneOf(_T("\n\r")) != -1)) |
- findNext = m_sFindNext; |
- _CSTRING_NS::CString replaceWith = m_sReplaceWith; |
- DWORD dwFlags = pT->GetFindReplaceDialogFlags(); |
- |
- m_pFindReplaceDialog = pT->CreateFindReplaceDialog(bFindOnly, |
- findNext, replaceWith, dwFlags, pT->operator HWND()); |
- ATLASSERT(m_pFindReplaceDialog != NULL); |
- if(m_pFindReplaceDialog != NULL) |
- m_bFindOnly = bFindOnly; |
- } |
- |
- BOOL SameAsSelected(LPCTSTR lpszCompare, BOOL bMatchCase, BOOL /*bWholeWord*/) |
- { |
- T* pT = static_cast<T*>(this); |
- |
- // check length first |
- size_t nLen = lstrlen(lpszCompare); |
- LONG nStartChar = 0, nEndChar = 0; |
- // Send EM_GETSEL so we can use both Edit and RichEdit |
- // (CEdit::GetSel uses int&, and CRichEditCtrlT::GetSel uses LONG&) |
- ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARAM)&nEndChar); |
- if(nLen != (size_t)(nEndChar - nStartChar)) |
- return FALSE; |
- |
- // length is the same, check contents |
- _CSTRING_NS::CString selectedText; |
- pT->GetSelText(selectedText); |
- |
- return (bMatchCase && selectedText.Compare(lpszCompare) == 0) || |
- (!bMatchCase && selectedText.CompareNoCase(lpszCompare) == 0); |
- } |
- |
- void TextNotFound(LPCTSTR lpszFind) |
- { |
- T* pT = static_cast<T*>(this); |
- m_bFirstSearch = TRUE; |
- pT->OnTextNotFound(lpszFind); |
- } |
- |
- _CSTRING_NS::CString GetTranslationText(enum TranslationTextItem eItem) const |
- { |
- _CSTRING_NS::CString text; |
- switch(eItem) |
- { |
- case eText_OnReplaceAllMessage: |
- text = _T("Replaced %d occurances of \"%s\" with \"%s\""); |
- break; |
- case eText_OnReplaceAllTitle: |
- text = _T("Replace All"); |
- break; |
- case eText_OnTextNotFoundMessage: |
- text = _T("Unable to find the text \"%s\""); |
- break; |
- case eText_OnTextNotFoundTitle: |
- text = _T("Text not found"); |
- break; |
- } |
- |
- return text; |
- } |
- |
-// Overrideable Handlers |
- void OnFindNext(LPCTSTR lpszFind, BOOL bFindDown, BOOL bMatchCase, BOOL bWholeWord) |
- { |
- T* pT = static_cast<T*>(this); |
- |
- m_sFindNext = lpszFind; |
- m_bMatchCase = bMatchCase; |
- m_bWholeWord = bWholeWord; |
- m_bFindDown = bFindDown; |
- |
- if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)) |
- pT->TextNotFound(m_sFindNext); |
- else |
- pT->AdjustDialogPosition(m_pFindReplaceDialog->operator HWND()); |
- } |
- |
- void OnReplaceSel(LPCTSTR lpszFind, BOOL bFindDown, BOOL bMatchCase, BOOL bWholeWord, LPCTSTR lpszReplace) |
- { |
- T* pT = static_cast<T*>(this); |
- |
- m_sFindNext = lpszFind; |
- m_sReplaceWith = lpszReplace; |
- m_bMatchCase = bMatchCase; |
- m_bWholeWord = bWholeWord; |
- m_bFindDown = bFindDown; |
- |
- if(pT->SameAsSelected(m_sFindNext, m_bMatchCase, m_bWholeWord)) |
- pT->ReplaceSel(m_sReplaceWith); |
- |
- if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)) |
- pT->TextNotFound(m_sFindNext); |
- else |
- pT->AdjustDialogPosition(m_pFindReplaceDialog->operator HWND()); |
- } |
- |
- void OnReplaceAll(LPCTSTR lpszFind, LPCTSTR lpszReplace, BOOL bMatchCase, BOOL bWholeWord) |
- { |
- T* pT = static_cast<T*>(this); |
- |
- m_sFindNext = lpszFind; |
- m_sReplaceWith = lpszReplace; |
- m_bMatchCase = bMatchCase; |
- m_bWholeWord = bWholeWord; |
- m_bFindDown = TRUE; |
- |
- // no selection or different than what looking for |
- if(!pT->SameAsSelected(m_sFindNext, m_bMatchCase, m_bWholeWord)) |
- { |
- if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)) |
- { |
- pT->TextNotFound(m_sFindNext); |
- return; |
- } |
- } |
- |
- pT->OnReplaceAllCoreBegin(); |
- |
- int replaceCount=0; |
- do |
- { |
- ++replaceCount; |
- pT->ReplaceSel(m_sReplaceWith); |
- } while(pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown)); |
- |
- pT->OnReplaceAllCoreEnd(replaceCount); |
- } |
- |
- void OnReplaceAllCoreBegin() |
- { |
- T* pT = static_cast<T*>(this); |
- |
- m_hOldCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT)); |
- |
- pT->HideSelection(TRUE, FALSE); |
- |
- } |
- |
- void OnReplaceAllCoreEnd(int replaceCount) |
- { |
- T* pT = static_cast<T*>(this); |
- pT->HideSelection(FALSE, FALSE); |
- |
- ::SetCursor(m_hOldCursor); |
- |
- _CSTRING_NS::CString message = pT->GetTranslationText(eText_OnReplaceAllMessage); |
- if(message.GetLength() > 0) |
- { |
- _CSTRING_NS::CString formattedMessage; |
- formattedMessage.Format(message, |
- replaceCount, m_sFindNext, m_sReplaceWith); |
- if(m_pFindReplaceDialog != NULL) |
- { |
- m_pFindReplaceDialog->MessageBox(formattedMessage, |
- pT->GetTranslationText(eText_OnReplaceAllTitle), |
- MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); |
- } |
- else |
- { |
- pT->MessageBox(formattedMessage, |
- pT->GetTranslationText(eText_OnReplaceAllTitle), |
- MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); |
- } |
- } |
- } |
- |
- void OnTextNotFound(LPCTSTR lpszFind) |
- { |
- T* pT = static_cast<T*>(this); |
- _CSTRING_NS::CString message = pT->GetTranslationText(eText_OnTextNotFoundMessage); |
- if(message.GetLength() > 0) |
- { |
- _CSTRING_NS::CString formattedMessage; |
- formattedMessage.Format(message, lpszFind); |
- if(m_pFindReplaceDialog != NULL) |
- { |
- m_pFindReplaceDialog->MessageBox(formattedMessage, |
- pT->GetTranslationText(eText_OnTextNotFoundTitle), |
- MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); |
- } |
- else |
- { |
- pT->MessageBox(formattedMessage, |
- pT->GetTranslationText(eText_OnTextNotFoundTitle), |
- MB_OK | MB_ICONINFORMATION | MB_APPLMODAL); |
- } |
- } |
- else |
- { |
- ::MessageBeep(MB_ICONHAND); |
- } |
- } |
- |
- void OnTerminatingFindReplaceDialog(TFindReplaceDialog*& /*findReplaceDialog*/) |
- { |
- } |
-}; |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// CEditFindReplaceImpl - Mixin class for implementing Find/Replace for CEdit |
-// based window classes. |
- |
-// Chain to CEditFindReplaceImpl message map. Your class must also derive from CEdit. |
-// Example: |
-// class CMyEdit : public CWindowImpl<CMyEdit, CEdit>, |
-// public CEditFindReplaceImpl<CMyEdit> |
-// { |
-// public: |
-// BEGIN_MSG_MAP(CMyEdit) |
-// // your handlers... |
-// CHAIN_MSG_MAP_ALT(CEditFindReplaceImpl<CMyEdit>, 1) |
-// END_MSG_MAP() |
-// // other stuff... |
-// }; |
- |
-template <class T, class TFindReplaceDialog = CFindReplaceDialog> |
-class CEditFindReplaceImpl : public CEditFindReplaceImplBase<T, TFindReplaceDialog> |
-{ |
-protected: |
- typedef CEditFindReplaceImpl<T, TFindReplaceDialog> thisClass; |
- typedef CEditFindReplaceImplBase<T, TFindReplaceDialog> baseClass; |
- |
-// Data members |
- LPTSTR m_pShadowBuffer; // Special shadow buffer only used in some cases. |
- UINT m_nShadowSize; |
- int m_bShadowBufferNeeded; // TRUE, FALSE, < 0 => Need to check |
- |
-public: |
-// Constructors |
- CEditFindReplaceImpl() : |
- m_pShadowBuffer(NULL), |
- m_nShadowSize(0), |
- m_bShadowBufferNeeded(-1) |
- { |
- } |
- |
- virtual ~CEditFindReplaceImpl() |
- { |
- if(m_pShadowBuffer != NULL) |
- { |
- delete [] m_pShadowBuffer; |
- m_pShadowBuffer = NULL; |
- } |
- } |
- |
-// Message Handlers |
- BEGIN_MSG_MAP(thisClass) |
- ALT_MSG_MAP(1) |
- CHAIN_MSG_MAP_ALT(baseClass, 1) |
- END_MSG_MAP() |
- |
-// Operations |
- // Supported only for RichEdit, so this does nothing for Edit |
- void HideSelection(BOOL /*bHide*/ = TRUE, BOOL /*bChangeStyle*/ = FALSE) |
- { |
- } |
- |
-// Operations (overrideable) |
- BOOL FindTextSimple(LPCTSTR lpszFind, BOOL bMatchCase, BOOL bWholeWord, BOOL bFindDown = TRUE) |
- { |
- T* pT = static_cast<T*>(this); |
- |
- ATLASSERT(lpszFind != NULL); |
- ATLASSERT(*lpszFind != _T('\0')); |
- |
- UINT nLen = pT->GetBufferLength(); |
- int nStartChar = 0, nEndChar = 0; |
- pT->GetSel(nStartChar, nEndChar); |
- UINT nStart = nStartChar; |
- int iDir = bFindDown ? +1 : -1; |
- |
- // can't find a match before the first character |
- if(nStart == 0 && iDir < 0) |
- return FALSE; |
- |
- LPCTSTR lpszText = pT->LockBuffer(); |
- |
- bool isDBCS = false; |
-#ifdef _MBCS |
- CPINFO info = { 0 }; |
- ::GetCPInfo(::GetOEMCP(), &info); |
- isDBCS = (info.MaxCharSize > 1); |
-#endif |
- |
- if(iDir < 0) |
- { |
- // always go back one for search backwards |
- nStart -= int((lpszText + nStart) - ::CharPrev(lpszText, lpszText + nStart)); |
- } |
- else if(nStartChar != nEndChar && pT->SameAsSelected(lpszFind, bMatchCase, bWholeWord)) |
- { |
- // easy to go backward/forward with SBCS |
-#ifndef _UNICODE |
- if(::IsDBCSLeadByte(lpszText[nStart])) |
- nStart++; |
-#endif |
- nStart += iDir; |
- } |
- |
- // handle search with nStart past end of buffer |
- UINT nLenFind = ::lstrlen(lpszFind); |
- if(nStart + nLenFind - 1 >= nLen) |
- { |
- if(iDir < 0 && nLen >= nLenFind) |
- { |
- if(isDBCS) |
- { |
- // walk back to previous character n times |
- nStart = nLen; |
- int n = nLenFind; |
- while(n--) |
- { |
- nStart -= int((lpszText + nStart) - ::CharPrev(lpszText, lpszText + nStart)); |
- } |
- } |
- else |
- { |
- // single-byte character set is easy and fast |
- nStart = nLen - nLenFind; |
- } |
- ATLASSERT(nStart + nLenFind - 1 <= nLen); |
- } |
- else |
- { |
- pT->UnlockBuffer(); |
- return FALSE; |
- } |
- } |
- |
- // start the search at nStart |
- LPCTSTR lpsz = lpszText + nStart; |
- typedef int (WINAPI* CompareProc)(LPCTSTR str1, LPCTSTR str2); |
- CompareProc pfnCompare = bMatchCase ? lstrcmp : lstrcmpi; |
- |
- if(isDBCS) |
- { |
- // double-byte string search |
- LPCTSTR lpszStop = NULL; |
- if(iDir > 0) |
- { |
- // start at current and find _first_ occurrance |
- lpszStop = lpszText + nLen - nLenFind + 1; |
- } |
- else |
- { |
- // start at top and find _last_ occurrance |
- lpszStop = lpsz; |
- lpsz = lpszText; |
- } |
- |
- LPCTSTR lpszFound = NULL; |
- while(lpsz <= lpszStop) |
- { |
-#ifndef _UNICODE |
- if(!bMatchCase || (*lpsz == *lpszFind && (!::IsDBCSLeadByte(*lpsz) || lpsz[1] == lpszFind[1]))) |
-#else |
- if(!bMatchCase || (*lpsz == *lpszFind && lpsz[1] == lpszFind[1])) |
-#endif |
- { |
- LPTSTR lpch = (LPTSTR)(lpsz + nLenFind); |
- TCHAR chSave = *lpch; |
- *lpch = _T('\0'); |
- int nResult = (*pfnCompare)(lpsz, lpszFind); |
- *lpch = chSave; |
- if(nResult == 0) |
- { |
- lpszFound = lpsz; |
- if(iDir > 0) |
- break; |
- } |
- } |
- lpsz = ::CharNext(lpsz); |
- } |
- pT->UnlockBuffer(); |
- |
- if(lpszFound != NULL) |
- { |
- int n = (int)(lpszFound - lpszText); |
- pT->SetSel(n, n + nLenFind); |
- return TRUE; |
- } |
- } |
- else |
- { |
- // single-byte string search |
- UINT nCompare; |
- if(iDir < 0) |
- nCompare = (UINT)(lpsz - lpszText) + 1; |
- else |
- nCompare = nLen - (UINT)(lpsz - lpszText) - nLenFind + 1; |
- |
- while(nCompare > 0) |
- { |
- ATLASSERT(lpsz >= lpszText); |
- ATLASSERT(lpsz + nLenFind - 1 <= lpszText + nLen - 1); |
- |
- LPSTR lpch = (LPSTR)(lpsz + nLenFind); |
- char chSave = *lpch; |
- *lpch = '\0'; |
- int nResult = (*pfnCompare)(lpsz, lpszFind); |
- *lpch = chSave; |
- if(nResult == 0) |
- { |
- pT->UnlockBuffer(); |
- int n = (int)(lpsz - lpszText); |
- pT->SetSel(n, n + nLenFind); |
- return TRUE; |
- } |
- |
- // restore character at end of search |
- *lpch = chSave; |
- |
- // move on to next substring |
- nCompare--; |
- lpsz += iDir; |
- } |
- pT->UnlockBuffer(); |
- } |
- |
- return FALSE; |
- } |
- |
- LPCTSTR LockBuffer() const |
- { |
- const T* pT = static_cast<const T*>(this); |
- |
- ATLASSERT(pT->m_hWnd != NULL); |
- |
- BOOL useShadowBuffer = pT->UseShadowBuffer(); |
- if(useShadowBuffer) |
- { |
- if(m_pShadowBuffer == NULL || pT->GetModify()) |
- { |
- ATLASSERT(m_pShadowBuffer != NULL || m_nShadowSize == 0); |
- UINT nSize = pT->GetWindowTextLength() + 1; |
- if(nSize > m_nShadowSize) |
- { |
- // need more room for shadow buffer |
- T* pThisNoConst = const_cast<T*>(pT); |
- delete[] m_pShadowBuffer; |
- pThisNoConst->m_pShadowBuffer = NULL; |
- pThisNoConst->m_nShadowSize = 0; |
- pThisNoConst->m_pShadowBuffer = new TCHAR[nSize]; |
- pThisNoConst->m_nShadowSize = nSize; |
- } |
- |
- // update the shadow buffer with GetWindowText |
- ATLASSERT(m_nShadowSize >= nSize); |
- ATLASSERT(m_pShadowBuffer != NULL); |
- pT->GetWindowText(m_pShadowBuffer, nSize); |
- } |
- |
- return m_pShadowBuffer; |
- } |
- |
- HLOCAL hLocal = pT->GetHandle(); |
- ATLASSERT(hLocal != NULL); |
- LPCTSTR lpszText = (LPCTSTR)::LocalLock(hLocal); |
- ATLASSERT(lpszText != NULL); |
- |
- return lpszText; |
- } |
- |
- void UnlockBuffer() const |
- { |
- const T* pT = static_cast<const T*>(this); |
- |
- ATLASSERT(pT->m_hWnd != NULL); |
- |
- BOOL useShadowBuffer = pT->UseShadowBuffer(); |
- if(!useShadowBuffer) |
- { |
- HLOCAL hLocal = pT->GetHandle(); |
- ATLASSERT(hLocal != NULL); |
- ::LocalUnlock(hLocal); |
- } |
- } |
- |
- UINT GetBufferLength() const |
- { |
- const T* pT = static_cast<const T*>(this); |
- |
- ATLASSERT(pT->m_hWnd != NULL); |
- UINT nLen = 0; |
- LPCTSTR lpszText = pT->LockBuffer(); |
- if(lpszText != NULL) |
- nLen = ::lstrlen(lpszText); |
- pT->UnlockBuffer(); |
- |
- return nLen; |
- } |
- |
- LONG EndOfLine(LPCTSTR lpszText, UINT nLen, UINT nIndex) const |
- { |
- LPCTSTR lpsz = lpszText + nIndex; |
- LPCTSTR lpszStop = lpszText + nLen; |
- while(lpsz < lpszStop && *lpsz != _T('\r')) |
- ++lpsz; |
- return LONG(lpsz - lpszText); |
- } |
- |
- LONG GetSelText(_CSTRING_NS::CString& strText) const |
- { |
- const T* pT = static_cast<const T*>(this); |
- |
- int nStartChar = 0, nEndChar = 0; |
- pT->GetSel(nStartChar, nEndChar); |
- ATLASSERT((UINT)nEndChar <= pT->GetBufferLength()); |
- LPCTSTR lpszText = pT->LockBuffer(); |
- LONG nLen = pT->EndOfLine(lpszText, nEndChar, nStartChar) - nStartChar; |
- SecureHelper::memcpy_x(strText.GetBuffer(nLen), nLen * sizeof(TCHAR), lpszText + nStartChar, nLen * sizeof(TCHAR)); |
- strText.ReleaseBuffer(nLen); |
- pT->UnlockBuffer(); |
- |
- return nLen; |
- } |
- |
- BOOL UseShadowBuffer(void) const |
- { |
- const T* pT = static_cast<const T*>(this); |
- |
- if(pT->m_bShadowBufferNeeded < 0) |
- { |
- T* pThisNoConst = const_cast<T*>(pT); |
- |
- OSVERSIONINFO ovi = { 0 }; |
- ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); |
- ::GetVersionEx(&ovi); |
- |
- bool bWin9x = (ovi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS); |
- if(bWin9x) |
- { |
- // Windows 95, 98, ME |
- // Under Win9x, it is necessary to maintain a shadow buffer. |
- // It is only updated when the control contents have been changed. |
- pThisNoConst->m_bShadowBufferNeeded = TRUE; |
- } |
- else |
- { |
- // Windows NT, 2000, XP, etc. |
- pThisNoConst->m_bShadowBufferNeeded = FALSE; |
- |
-#ifndef _UNICODE |
- // On Windows XP (or later), if common controls version 6 is in use |
- // (such as via theming), then EM_GETHANDLE will always return a UNICODE string. |
- // If theming is enabled and Common Controls version 6 is in use, |
- // you're really not suppose to superclass or subclass common controls |
- // with an ANSI windows procedure (so its best to only theme if you use UNICODE). |
- // Using a shadow buffer uses GetWindowText instead, so it solves |
- // this problem for us (although it makes it a little less efficient). |
- |
- if((ovi.dwMajorVersion == 5 && ovi.dwMinorVersion >= 1) || (ovi.dwMajorVersion > 5)) |
- { |
- // We use DLLVERSIONINFO_private so we don't have to depend on shlwapi.h |
- typedef struct _DLLVERSIONINFO_private |
- { |
- DWORD cbSize; |
- DWORD dwMajorVersion; |
- DWORD dwMinorVersion; |
- DWORD dwBuildNumber; |
- DWORD dwPlatformID; |
- } DLLVERSIONINFO_private; |
- |
- HMODULE hModule = ::LoadLibrary("comctl32.dll"); |
- if(hModule != NULL) |
- { |
- typedef HRESULT (CALLBACK *LPFN_DllGetVersion)(DLLVERSIONINFO_private *); |
- LPFN_DllGetVersion fnDllGetVersion = (LPFN_DllGetVersion)::GetProcAddress(hModule, "DllGetVersion"); |
- if(fnDllGetVersion != NULL) |
- { |
- DLLVERSIONINFO_private version = { 0 }; |
- version.cbSize = sizeof(DLLVERSIONINFO_private); |
- if(SUCCEEDED(fnDllGetVersion(&version))) |
- { |
- if(version.dwMajorVersion >= 6) |
- { |
- pThisNoConst->m_bShadowBufferNeeded = TRUE; |
- |
- ATLTRACE2(atlTraceUI, 0, _T("Warning: You have compiled for MBCS/ANSI but are using common controls version 6 or later (likely through a manifest file).\r\n")); |
- ATLTRACE2(atlTraceUI, 0, _T("If you use common controls version 6 or later, you should only do so for UNICODE builds.\r\n")); |
- } |
- } |
- } |
- |
- ::FreeLibrary(hModule); |
- hModule = NULL; |
- } |
- } |
-#endif // !_UNICODE |
- } |
- } |
- |
- return (pT->m_bShadowBufferNeeded == TRUE); |
- } |
-}; |
- |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-// CRichEditFindReplaceImpl - Mixin class for implementing Find/Replace for CRichEditCtrl |
-// based window classes. |
- |
-// Chain to CRichEditFindReplaceImpl message map. Your class must also derive from CRichEditCtrl. |
-// Example: |
-// class CMyRichEdit : public CWindowImpl<CMyRichEdit, CRichEditCtrl>, |
-// public CRichEditFindReplaceImpl<CMyRichEdit> |
-// { |
-// public: |
-// BEGIN_MSG_MAP(CMyRichEdit) |
-// // your handlers... |
-// CHAIN_MSG_MAP_ALT(CRichEditFindReplaceImpl<CMyRichEdit>, 1) |
-// END_MSG_MAP() |
-// // other stuff... |
-// }; |
- |
-template <class T, class TFindReplaceDialog = CFindReplaceDialog> |
-class CRichEditFindReplaceImpl : public CEditFindReplaceImplBase<T, TFindReplaceDialog> |
-{ |
-protected: |
- typedef CRichEditFindReplaceImpl<T, TFindReplaceDialog> thisClass; |
- typedef CEditFindReplaceImplBase<T, TFindReplaceDialog> baseClass; |
- |
-public: |
- BEGIN_MSG_MAP(thisClass) |
- ALT_MSG_MAP(1) |
- CHAIN_MSG_MAP_ALT(baseClass, 1) |
- END_MSG_MAP() |
- |
-// Operations (overrideable) |
- BOOL FindTextSimple(LPCTSTR lpszFind, BOOL bMatchCase, BOOL bWholeWord, BOOL bFindDown = TRUE) |
- { |
- T* pT = static_cast<T*>(this); |
- |
- ATLASSERT(lpszFind != NULL); |
- FINDTEXTEX ft = { 0 }; |
- |
- pT->GetSel(ft.chrg); |
- if(m_bFirstSearch) |
- { |
- if(bFindDown) |
- m_nInitialSearchPos = ft.chrg.cpMin; |
- else |
- m_nInitialSearchPos = ft.chrg.cpMax; |
- m_bFirstSearch = FALSE; |
- } |
- |
-#if (_RICHEDIT_VER >= 0x0200) |
- ft.lpstrText = (LPTSTR)lpszFind; |
-#else // !(_RICHEDIT_VER >= 0x0200) |
- USES_CONVERSION; |
- ft.lpstrText = T2A((LPTSTR)lpszFind); |
-#endif // !(_RICHEDIT_VER >= 0x0200) |
- |
- if(ft.chrg.cpMin != ft.chrg.cpMax) // i.e. there is a selection |
- { |
- if(bFindDown) |
- { |
- ft.chrg.cpMin++; |
- } |
- else |
- { |
- // won't wraparound backwards |
- ft.chrg.cpMin = __max(ft.chrg.cpMin, 0); |
- } |
- } |
- |
- DWORD dwFlags = bMatchCase ? FR_MATCHCASE : 0; |
- dwFlags |= bWholeWord ? FR_WHOLEWORD : 0; |
- |
- ft.chrg.cpMax = pT->GetTextLength() + m_nInitialSearchPos; |
- |
- if(bFindDown) |
- { |
- if(m_nInitialSearchPos >= 0) |
- ft.chrg.cpMax = pT->GetTextLength(); |
- |
- dwFlags |= FR_DOWN; |
- ATLASSERT(ft.chrg.cpMax >= ft.chrg.cpMin); |
- } |
- else |
- { |
- if(m_nInitialSearchPos >= 0) |
- ft.chrg.cpMax = 0; |
- |
- dwFlags &= ~FR_DOWN; |
- ATLASSERT(ft.chrg.cpMax <= ft.chrg.cpMin); |
- } |
- |
- BOOL bRet = FALSE; |
- |
- if(pT->FindAndSelect(dwFlags, ft) != -1) |
- { |
- bRet = TRUE; // we found the text |
- } |
- else if(m_nInitialSearchPos > 0) |
- { |
- // if the original starting point was not the beginning |
- // of the buffer and we haven't already been here |
- if(bFindDown) |
- { |
- ft.chrg.cpMin = 0; |
- ft.chrg.cpMax = m_nInitialSearchPos; |
- } |
- else |
- { |
- ft.chrg.cpMin = pT->GetTextLength(); |
- ft.chrg.cpMax = m_nInitialSearchPos; |
- } |
- m_nInitialSearchPos = m_nInitialSearchPos - pT->GetTextLength(); |
- |
- bRet = (pT->FindAndSelect(dwFlags, ft) != -1) ? TRUE : FALSE; |
- } |
- |
- return bRet; |
- } |
- |
- long FindAndSelect(DWORD dwFlags, FINDTEXTEX& ft) |
- { |
- T* pT = static_cast<T*>(this); |
- LONG index = pT->FindText(dwFlags, ft); |
- if(index != -1) // i.e. we found something |
- pT->SetSel(ft.chrgText); |
- |
- return index; |
- } |
-}; |
- |
-}; // namespace WTL |
- |
-#endif // __ATLFIND_H__ |