Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(261)

Side by Side Diff: third_party/wtl/include/atlfind.h

Issue 703753005: More Windows build fixes. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: remove generated files Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/wtl/include/atldlgs.h ('k') | third_party/wtl/include/atlframe.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Windows Template Library - WTL version 8.0
2 // Copyright (C) Microsoft Corporation. All rights reserved.
3 //
4 // This file is a part of the Windows Template Library.
5 // The use and distribution terms for this software are covered by the
6 // Microsoft Permissive License (Ms-PL) which can be found in the file
7 // Ms-PL.txt at the root of this distribution.
8
9 #ifndef __ATLFIND_H__
10 #define __ATLFIND_H__
11
12 #pragma once
13
14 #ifndef __cplusplus
15 #error ATL requires C++ compilation (use a .cpp suffix)
16 #endif
17
18 #ifdef _WIN32_WCE
19 #error atlfind.h is not supported on Windows CE
20 #endif
21
22 #ifndef __ATLCTRLS_H__
23 #error atlfind.h requires atlctrls.h to be included first
24 #endif
25
26 #ifndef __ATLDLGS_H__
27 #error atlfind.h requires atldlgs.h to be included first
28 #endif
29
30 #if !((defined(__ATLMISC_H__) && defined(_WTL_USE_CSTRING)) || defined(__ATLSTR_ H__))
31 #error atlfind.h requires CString (either from ATL's atlstr.h or WTL's a tlmisc.h with _WTL_USE_CSTRING)
32 #endif
33
34
35 ///////////////////////////////////////////////////////////////////////////////
36 // Classes in this file:
37 //
38 // CEditFindReplaceImplBase<T, TFindReplaceDialog>
39 // CEditFindReplaceImpl<T, TFindReplaceDialog>
40 // CRichEditFindReplaceImpl<T, TFindReplaceDialog>
41
42
43 namespace WTL
44 {
45
46 ///////////////////////////////////////////////////////////////////////////////
47 // CEditFindReplaceImplBase - Base class for mixin classes that
48 // help implement Find/Replace for CEdit or CRichEditCtrl based window classes.
49
50 template <class T, class TFindReplaceDialog = CFindReplaceDialog>
51 class CEditFindReplaceImplBase
52 {
53 protected:
54 // Typedefs
55 typedef CEditFindReplaceImplBase<T, TFindReplaceDialog> thisClass;
56
57 // Data members
58 TFindReplaceDialog* m_pFindReplaceDialog;
59 _CSTRING_NS::CString m_sFindNext, m_sReplaceWith;
60 BOOL m_bFindOnly, m_bFirstSearch, m_bMatchCase, m_bWholeWord, m_bFindDow n;
61 LONG m_nInitialSearchPos;
62 HCURSOR m_hOldCursor;
63
64 // Enumerations
65 enum TranslationTextItem
66 {
67 eText_OnReplaceAllMessage = 0,
68 eText_OnReplaceAllTitle = 1,
69 eText_OnTextNotFoundMessage = 2,
70 eText_OnTextNotFoundTitle = 3
71 };
72
73 public:
74 // Constructors
75 CEditFindReplaceImplBase() :
76 m_pFindReplaceDialog(NULL),
77 m_bFindOnly(TRUE),
78 m_bFirstSearch(TRUE),
79 m_bMatchCase(FALSE),
80 m_bWholeWord(FALSE),
81 m_bFindDown(TRUE),
82 m_nInitialSearchPos(0),
83 m_hOldCursor(NULL)
84 {
85 }
86
87 // Message Handlers
88 BEGIN_MSG_MAP(thisClass)
89 ALT_MSG_MAP(1)
90 MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
91 MESSAGE_HANDLER(TFindReplaceDialog::GetFindReplaceMsg(), OnFindR eplaceCmd)
92 COMMAND_ID_HANDLER(ID_EDIT_FIND, OnEditFind)
93 COMMAND_ID_HANDLER(ID_EDIT_REPEAT, OnEditRepeat)
94 COMMAND_ID_HANDLER(ID_EDIT_REPLACE, OnEditReplace)
95 END_MSG_MAP()
96
97 LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, B OOL& bHandled)
98 {
99 if(m_pFindReplaceDialog != NULL)
100 {
101 m_pFindReplaceDialog->SendMessage(WM_CLOSE);
102 ATLASSERT(m_pFindReplaceDialog == NULL);
103 }
104
105 bHandled = FALSE;
106 return 0;
107 }
108
109 LRESULT OnFindReplaceCmd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam , BOOL& /*bHandled*/)
110 {
111 T* pT = static_cast<T*>(this);
112
113 TFindReplaceDialog* pDialog = TFindReplaceDialog::GetNotifier(lP aram);
114 if(pDialog == NULL)
115 {
116 ATLASSERT(FALSE);
117 ::MessageBeep(MB_ICONERROR);
118 return 1;
119 }
120 ATLASSERT(pDialog == m_pFindReplaceDialog);
121
122 LPFINDREPLACE findReplace = (LPFINDREPLACE)lParam;
123 if((m_pFindReplaceDialog != NULL) && (findReplace != NULL))
124 {
125 if(pDialog->FindNext())
126 {
127 pT->OnFindNext(pDialog->GetFindString(), pDialog ->SearchDown(),
128 pDialog->MatchCase(), pDialog->MatchWhol eWord());
129 }
130 else if(pDialog->ReplaceCurrent())
131 {
132 pT->OnReplaceSel(pDialog->GetFindString(),
133 pDialog->SearchDown(), pDialog->MatchCas e(), pDialog->MatchWholeWord(),
134 pDialog->GetReplaceString());
135 }
136 else if(pDialog->ReplaceAll())
137 {
138 pT->OnReplaceAll(pDialog->GetFindString(), pDial og->GetReplaceString(),
139 pDialog->MatchCase(), pDialog->MatchWhol eWord());
140 }
141 else if(pDialog->IsTerminating())
142 {
143 // Dialog is going away (but hasn't gone away ye t)
144 // OnFinalMessage will "delete this"
145 pT->OnTerminatingFindReplaceDialog(m_pFindReplac eDialog);
146 m_pFindReplaceDialog = NULL;
147 }
148 }
149
150 return 0;
151 }
152
153 LRESULT OnEditFind(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
154 {
155 T* pT = static_cast<T*>(this);
156 pT->FindReplace(TRUE);
157
158 return 0;
159 }
160
161 LRESULT OnEditRepeat(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl* /, BOOL& /*bHandled*/)
162 {
163 T* pT = static_cast<T*>(this);
164
165 // If the user is holding down SHIFT when hitting F3, we'll
166 // search in reverse. Otherwise, we'll search forward.
167 // (be sure to have an accelerator mapped to ID_EDIT_REPEAT
168 // for both F3 and Shift+F3)
169 m_bFindDown = !((::GetKeyState(VK_SHIFT) & 0x8000) == 0x8000);
170
171 if(m_sFindNext.IsEmpty())
172 {
173 pT->FindReplace(TRUE);
174 }
175 else
176 {
177 if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWho leWord, m_bFindDown))
178 pT->TextNotFound(m_sFindNext);
179 }
180
181 return 0;
182 }
183
184 LRESULT OnEditReplace(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl */, BOOL& bHandled)
185 {
186 T* pT = static_cast<T*>(this);
187
188 DWORD style = pT->GetStyle();
189 if((style & ES_READONLY) != ES_READONLY)
190 {
191 pT->FindReplace(FALSE);
192 }
193 else
194 {
195 // Don't allow replace when the edit control is read onl y
196 bHandled = FALSE;
197 }
198
199 return 0;
200 }
201
202 // Operations (overrideable)
203 TFindReplaceDialog* CreateFindReplaceDialog(BOOL bFindOnly, // TRUE for Find, FALSE for FindReplace
204 LPCTSTR lpszFindWhat,
205 LPCTSTR lpszReplaceWith = NULL,
206 DWORD dwFlags = FR_DOWN,
207 HWND hWndParent = NULL)
208 {
209 // You can override all of this in a derived class
210
211 TFindReplaceDialog* findReplaceDialog = new TFindReplaceDialog() ;
212 if(findReplaceDialog == NULL)
213 {
214 ::MessageBeep(MB_ICONHAND);
215 }
216 else
217 {
218 HWND hWndFindReplace = findReplaceDialog->Create(bFindOn ly,
219 lpszFindWhat, lpszReplaceWith, dwFlags, hWndPare nt);
220 if(hWndFindReplace == NULL)
221 {
222 delete findReplaceDialog;
223 findReplaceDialog = NULL;
224 }
225 else
226 {
227 findReplaceDialog->SetActiveWindow();
228 findReplaceDialog->ShowWindow(SW_SHOW);
229 }
230 }
231
232 return findReplaceDialog;
233 }
234
235 void AdjustDialogPosition(HWND hWndDialog)
236 {
237 ATLASSERT((hWndDialog != NULL) && ::IsWindow(hWndDialog));
238
239 T* pT = static_cast<T*>(this);
240 LONG nStartChar = 0, nEndChar = 0;
241 // Send EM_GETSEL so we can use both Edit and RichEdit
242 // (CEdit::GetSel uses int&, and CRichEditCtrlT::GetSel uses LON G&)
243 ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARA M)&nEndChar);
244 POINT point = pT->PosFromChar(nStartChar);
245 ::ClientToScreen(pT->GetParent(), &point);
246 CRect rect;
247 ::GetWindowRect(hWndDialog, &rect);
248 if(rect.PtInRect(point))
249 {
250 if(point.y > rect.Height())
251 {
252 rect.OffsetRect(0, point.y - rect.bottom - 20);
253 }
254 else
255 {
256 int nVertExt = GetSystemMetrics(SM_CYSCREEN);
257 if(point.y + rect.Height() < nVertExt)
258 rect.OffsetRect(0, 40 + point.y - rect.t op);
259 }
260
261 ::MoveWindow(hWndDialog, rect.left, rect.top, rect.Width (), rect.Height(), TRUE);
262 }
263 }
264
265 DWORD GetFindReplaceDialogFlags(void) const
266 {
267 DWORD dwFlags = 0;
268
269 if(m_bFindDown)
270 dwFlags |= FR_DOWN;
271 if(m_bMatchCase)
272 dwFlags |= FR_MATCHCASE;
273 if(m_bWholeWord)
274 dwFlags |= FR_WHOLEWORD;
275
276 return dwFlags;
277 }
278
279 void FindReplace(BOOL bFindOnly)
280 {
281 T* pT = static_cast<T*>(this);
282 m_bFirstSearch = TRUE;
283 if(m_pFindReplaceDialog != NULL)
284 {
285 if(m_bFindOnly == bFindOnly)
286 {
287 m_pFindReplaceDialog->SetActiveWindow();
288 m_pFindReplaceDialog->ShowWindow(SW_SHOW);
289 return;
290 }
291 else
292 {
293 m_pFindReplaceDialog->SendMessage(WM_CLOSE);
294 ATLASSERT(m_pFindReplaceDialog == NULL);
295 }
296 }
297
298 ATLASSERT(m_pFindReplaceDialog == NULL);
299
300 _CSTRING_NS::CString findNext;
301 pT->GetSelText(findNext);
302 // if selection is empty or spans multiple lines use old find te xt
303 if(findNext.IsEmpty() || (findNext.FindOneOf(_T("\n\r")) != -1))
304 findNext = m_sFindNext;
305 _CSTRING_NS::CString replaceWith = m_sReplaceWith;
306 DWORD dwFlags = pT->GetFindReplaceDialogFlags();
307
308 m_pFindReplaceDialog = pT->CreateFindReplaceDialog(bFindOnly,
309 findNext, replaceWith, dwFlags, pT->operator HWND());
310 ATLASSERT(m_pFindReplaceDialog != NULL);
311 if(m_pFindReplaceDialog != NULL)
312 m_bFindOnly = bFindOnly;
313 }
314
315 BOOL SameAsSelected(LPCTSTR lpszCompare, BOOL bMatchCase, BOOL /*bWholeW ord*/)
316 {
317 T* pT = static_cast<T*>(this);
318
319 // check length first
320 size_t nLen = lstrlen(lpszCompare);
321 LONG nStartChar = 0, nEndChar = 0;
322 // Send EM_GETSEL so we can use both Edit and RichEdit
323 // (CEdit::GetSel uses int&, and CRichEditCtrlT::GetSel uses LON G&)
324 ::SendMessage(pT->m_hWnd, EM_GETSEL, (WPARAM)&nStartChar, (LPARA M)&nEndChar);
325 if(nLen != (size_t)(nEndChar - nStartChar))
326 return FALSE;
327
328 // length is the same, check contents
329 _CSTRING_NS::CString selectedText;
330 pT->GetSelText(selectedText);
331
332 return (bMatchCase && selectedText.Compare(lpszCompare) == 0) ||
333 (!bMatchCase && selectedText.CompareNoCase(lpszCompare) == 0);
334 }
335
336 void TextNotFound(LPCTSTR lpszFind)
337 {
338 T* pT = static_cast<T*>(this);
339 m_bFirstSearch = TRUE;
340 pT->OnTextNotFound(lpszFind);
341 }
342
343 _CSTRING_NS::CString GetTranslationText(enum TranslationTextItem eItem) const
344 {
345 _CSTRING_NS::CString text;
346 switch(eItem)
347 {
348 case eText_OnReplaceAllMessage:
349 text = _T("Replaced %d occurances of \"%s\" with \"%s\"" );
350 break;
351 case eText_OnReplaceAllTitle:
352 text = _T("Replace All");
353 break;
354 case eText_OnTextNotFoundMessage:
355 text = _T("Unable to find the text \"%s\"");
356 break;
357 case eText_OnTextNotFoundTitle:
358 text = _T("Text not found");
359 break;
360 }
361
362 return text;
363 }
364
365 // Overrideable Handlers
366 void OnFindNext(LPCTSTR lpszFind, BOOL bFindDown, BOOL bMatchCase, BOOL bWholeWord)
367 {
368 T* pT = static_cast<T*>(this);
369
370 m_sFindNext = lpszFind;
371 m_bMatchCase = bMatchCase;
372 m_bWholeWord = bWholeWord;
373 m_bFindDown = bFindDown;
374
375 if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown))
376 pT->TextNotFound(m_sFindNext);
377 else
378 pT->AdjustDialogPosition(m_pFindReplaceDialog->operator HWND());
379 }
380
381 void OnReplaceSel(LPCTSTR lpszFind, BOOL bFindDown, BOOL bMatchCase, BOO L bWholeWord, LPCTSTR lpszReplace)
382 {
383 T* pT = static_cast<T*>(this);
384
385 m_sFindNext = lpszFind;
386 m_sReplaceWith = lpszReplace;
387 m_bMatchCase = bMatchCase;
388 m_bWholeWord = bWholeWord;
389 m_bFindDown = bFindDown;
390
391 if(pT->SameAsSelected(m_sFindNext, m_bMatchCase, m_bWholeWord))
392 pT->ReplaceSel(m_sReplaceWith);
393
394 if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWord, m_bFindDown))
395 pT->TextNotFound(m_sFindNext);
396 else
397 pT->AdjustDialogPosition(m_pFindReplaceDialog->operator HWND());
398 }
399
400 void OnReplaceAll(LPCTSTR lpszFind, LPCTSTR lpszReplace, BOOL bMatchCase , BOOL bWholeWord)
401 {
402 T* pT = static_cast<T*>(this);
403
404 m_sFindNext = lpszFind;
405 m_sReplaceWith = lpszReplace;
406 m_bMatchCase = bMatchCase;
407 m_bWholeWord = bWholeWord;
408 m_bFindDown = TRUE;
409
410 // no selection or different than what looking for
411 if(!pT->SameAsSelected(m_sFindNext, m_bMatchCase, m_bWholeWord))
412 {
413 if(!pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWho leWord, m_bFindDown))
414 {
415 pT->TextNotFound(m_sFindNext);
416 return;
417 }
418 }
419
420 pT->OnReplaceAllCoreBegin();
421
422 int replaceCount=0;
423 do
424 {
425 ++replaceCount;
426 pT->ReplaceSel(m_sReplaceWith);
427 } while(pT->FindTextSimple(m_sFindNext, m_bMatchCase, m_bWholeWo rd, m_bFindDown));
428
429 pT->OnReplaceAllCoreEnd(replaceCount);
430 }
431
432 void OnReplaceAllCoreBegin()
433 {
434 T* pT = static_cast<T*>(this);
435
436 m_hOldCursor = ::SetCursor(::LoadCursor(NULL, IDC_WAIT));
437
438 pT->HideSelection(TRUE, FALSE);
439
440 }
441
442 void OnReplaceAllCoreEnd(int replaceCount)
443 {
444 T* pT = static_cast<T*>(this);
445 pT->HideSelection(FALSE, FALSE);
446
447 ::SetCursor(m_hOldCursor);
448
449 _CSTRING_NS::CString message = pT->GetTranslationText(eText_OnRe placeAllMessage);
450 if(message.GetLength() > 0)
451 {
452 _CSTRING_NS::CString formattedMessage;
453 formattedMessage.Format(message,
454 replaceCount, m_sFindNext, m_sReplaceWith);
455 if(m_pFindReplaceDialog != NULL)
456 {
457 m_pFindReplaceDialog->MessageBox(formattedMessag e,
458 pT->GetTranslationText(eText_OnReplaceAl lTitle),
459 MB_OK | MB_ICONINFORMATION | MB_APPLMODA L);
460 }
461 else
462 {
463 pT->MessageBox(formattedMessage,
464 pT->GetTranslationText(eText_OnReplaceAl lTitle),
465 MB_OK | MB_ICONINFORMATION | MB_APPLMODA L);
466 }
467 }
468 }
469
470 void OnTextNotFound(LPCTSTR lpszFind)
471 {
472 T* pT = static_cast<T*>(this);
473 _CSTRING_NS::CString message = pT->GetTranslationText(eText_OnTe xtNotFoundMessage);
474 if(message.GetLength() > 0)
475 {
476 _CSTRING_NS::CString formattedMessage;
477 formattedMessage.Format(message, lpszFind);
478 if(m_pFindReplaceDialog != NULL)
479 {
480 m_pFindReplaceDialog->MessageBox(formattedMessag e,
481 pT->GetTranslationText(eText_OnTextNotFo undTitle),
482 MB_OK | MB_ICONINFORMATION | MB_APPLMODA L);
483 }
484 else
485 {
486 pT->MessageBox(formattedMessage,
487 pT->GetTranslationText(eText_OnTextNotFo undTitle),
488 MB_OK | MB_ICONINFORMATION | MB_APPLMODA L);
489 }
490 }
491 else
492 {
493 ::MessageBeep(MB_ICONHAND);
494 }
495 }
496
497 void OnTerminatingFindReplaceDialog(TFindReplaceDialog*& /*findReplaceDi alog*/)
498 {
499 }
500 };
501
502
503 ///////////////////////////////////////////////////////////////////////////////
504 // CEditFindReplaceImpl - Mixin class for implementing Find/Replace for CEdit
505 // based window classes.
506
507 // Chain to CEditFindReplaceImpl message map. Your class must also derive from C Edit.
508 // Example:
509 // class CMyEdit : public CWindowImpl<CMyEdit, CEdit>,
510 // public CEditFindReplaceImpl<CMyEdit>
511 // {
512 // public:
513 // BEGIN_MSG_MAP(CMyEdit)
514 // // your handlers...
515 // CHAIN_MSG_MAP_ALT(CEditFindReplaceImpl<CMyEdit>, 1)
516 // END_MSG_MAP()
517 // // other stuff...
518 // };
519
520 template <class T, class TFindReplaceDialog = CFindReplaceDialog>
521 class CEditFindReplaceImpl : public CEditFindReplaceImplBase<T, TFindReplaceDial og>
522 {
523 protected:
524 typedef CEditFindReplaceImpl<T, TFindReplaceDialog> thisClass;
525 typedef CEditFindReplaceImplBase<T, TFindReplaceDialog> baseClass;
526
527 // Data members
528 LPTSTR m_pShadowBuffer; // Special shadow buffer only used in some c ases.
529 UINT m_nShadowSize;
530 int m_bShadowBufferNeeded; // TRUE, FALSE, < 0 => Need to check
531
532 public:
533 // Constructors
534 CEditFindReplaceImpl() :
535 m_pShadowBuffer(NULL),
536 m_nShadowSize(0),
537 m_bShadowBufferNeeded(-1)
538 {
539 }
540
541 virtual ~CEditFindReplaceImpl()
542 {
543 if(m_pShadowBuffer != NULL)
544 {
545 delete [] m_pShadowBuffer;
546 m_pShadowBuffer = NULL;
547 }
548 }
549
550 // Message Handlers
551 BEGIN_MSG_MAP(thisClass)
552 ALT_MSG_MAP(1)
553 CHAIN_MSG_MAP_ALT(baseClass, 1)
554 END_MSG_MAP()
555
556 // Operations
557 // Supported only for RichEdit, so this does nothing for Edit
558 void HideSelection(BOOL /*bHide*/ = TRUE, BOOL /*bChangeStyle*/ = FALSE)
559 {
560 }
561
562 // Operations (overrideable)
563 BOOL FindTextSimple(LPCTSTR lpszFind, BOOL bMatchCase, BOOL bWholeWord, BOOL bFindDown = TRUE)
564 {
565 T* pT = static_cast<T*>(this);
566
567 ATLASSERT(lpszFind != NULL);
568 ATLASSERT(*lpszFind != _T('\0'));
569
570 UINT nLen = pT->GetBufferLength();
571 int nStartChar = 0, nEndChar = 0;
572 pT->GetSel(nStartChar, nEndChar);
573 UINT nStart = nStartChar;
574 int iDir = bFindDown ? +1 : -1;
575
576 // can't find a match before the first character
577 if(nStart == 0 && iDir < 0)
578 return FALSE;
579
580 LPCTSTR lpszText = pT->LockBuffer();
581
582 bool isDBCS = false;
583 #ifdef _MBCS
584 CPINFO info = { 0 };
585 ::GetCPInfo(::GetOEMCP(), &info);
586 isDBCS = (info.MaxCharSize > 1);
587 #endif
588
589 if(iDir < 0)
590 {
591 // always go back one for search backwards
592 nStart -= int((lpszText + nStart) - ::CharPrev(lpszText, lpszText + nStart));
593 }
594 else if(nStartChar != nEndChar && pT->SameAsSelected(lpszFind, b MatchCase, bWholeWord))
595 {
596 // easy to go backward/forward with SBCS
597 #ifndef _UNICODE
598 if(::IsDBCSLeadByte(lpszText[nStart]))
599 nStart++;
600 #endif
601 nStart += iDir;
602 }
603
604 // handle search with nStart past end of buffer
605 UINT nLenFind = ::lstrlen(lpszFind);
606 if(nStart + nLenFind - 1 >= nLen)
607 {
608 if(iDir < 0 && nLen >= nLenFind)
609 {
610 if(isDBCS)
611 {
612 // walk back to previous character n tim es
613 nStart = nLen;
614 int n = nLenFind;
615 while(n--)
616 {
617 nStart -= int((lpszText + nStart ) - ::CharPrev(lpszText, lpszText + nStart));
618 }
619 }
620 else
621 {
622 // single-byte character set is easy and fast
623 nStart = nLen - nLenFind;
624 }
625 ATLASSERT(nStart + nLenFind - 1 <= nLen);
626 }
627 else
628 {
629 pT->UnlockBuffer();
630 return FALSE;
631 }
632 }
633
634 // start the search at nStart
635 LPCTSTR lpsz = lpszText + nStart;
636 typedef int (WINAPI* CompareProc)(LPCTSTR str1, LPCTSTR str2);
637 CompareProc pfnCompare = bMatchCase ? lstrcmp : lstrcmpi;
638
639 if(isDBCS)
640 {
641 // double-byte string search
642 LPCTSTR lpszStop = NULL;
643 if(iDir > 0)
644 {
645 // start at current and find _first_ occurrance
646 lpszStop = lpszText + nLen - nLenFind + 1;
647 }
648 else
649 {
650 // start at top and find _last_ occurrance
651 lpszStop = lpsz;
652 lpsz = lpszText;
653 }
654
655 LPCTSTR lpszFound = NULL;
656 while(lpsz <= lpszStop)
657 {
658 #ifndef _UNICODE
659 if(!bMatchCase || (*lpsz == *lpszFind && (!::IsD BCSLeadByte(*lpsz) || lpsz[1] == lpszFind[1])))
660 #else
661 if(!bMatchCase || (*lpsz == *lpszFind && lpsz[1] == lpszFind[1]))
662 #endif
663 {
664 LPTSTR lpch = (LPTSTR)(lpsz + nLenFind);
665 TCHAR chSave = *lpch;
666 *lpch = _T('\0');
667 int nResult = (*pfnCompare)(lpsz, lpszFi nd);
668 *lpch = chSave;
669 if(nResult == 0)
670 {
671 lpszFound = lpsz;
672 if(iDir > 0)
673 break;
674 }
675 }
676 lpsz = ::CharNext(lpsz);
677 }
678 pT->UnlockBuffer();
679
680 if(lpszFound != NULL)
681 {
682 int n = (int)(lpszFound - lpszText);
683 pT->SetSel(n, n + nLenFind);
684 return TRUE;
685 }
686 }
687 else
688 {
689 // single-byte string search
690 UINT nCompare;
691 if(iDir < 0)
692 nCompare = (UINT)(lpsz - lpszText) + 1;
693 else
694 nCompare = nLen - (UINT)(lpsz - lpszText) - nLen Find + 1;
695
696 while(nCompare > 0)
697 {
698 ATLASSERT(lpsz >= lpszText);
699 ATLASSERT(lpsz + nLenFind - 1 <= lpszText + nLen - 1);
700
701 LPSTR lpch = (LPSTR)(lpsz + nLenFind);
702 char chSave = *lpch;
703 *lpch = '\0';
704 int nResult = (*pfnCompare)(lpsz, lpszFind);
705 *lpch = chSave;
706 if(nResult == 0)
707 {
708 pT->UnlockBuffer();
709 int n = (int)(lpsz - lpszText);
710 pT->SetSel(n, n + nLenFind);
711 return TRUE;
712 }
713
714 // restore character at end of search
715 *lpch = chSave;
716
717 // move on to next substring
718 nCompare--;
719 lpsz += iDir;
720 }
721 pT->UnlockBuffer();
722 }
723
724 return FALSE;
725 }
726
727 LPCTSTR LockBuffer() const
728 {
729 const T* pT = static_cast<const T*>(this);
730
731 ATLASSERT(pT->m_hWnd != NULL);
732
733 BOOL useShadowBuffer = pT->UseShadowBuffer();
734 if(useShadowBuffer)
735 {
736 if(m_pShadowBuffer == NULL || pT->GetModify())
737 {
738 ATLASSERT(m_pShadowBuffer != NULL || m_nShadowSi ze == 0);
739 UINT nSize = pT->GetWindowTextLength() + 1;
740 if(nSize > m_nShadowSize)
741 {
742 // need more room for shadow buffer
743 T* pThisNoConst = const_cast<T*>(pT);
744 delete[] m_pShadowBuffer;
745 pThisNoConst->m_pShadowBuffer = NULL;
746 pThisNoConst->m_nShadowSize = 0;
747 pThisNoConst->m_pShadowBuffer = new TCHA R[nSize];
748 pThisNoConst->m_nShadowSize = nSize;
749 }
750
751 // update the shadow buffer with GetWindowText
752 ATLASSERT(m_nShadowSize >= nSize);
753 ATLASSERT(m_pShadowBuffer != NULL);
754 pT->GetWindowText(m_pShadowBuffer, nSize);
755 }
756
757 return m_pShadowBuffer;
758 }
759
760 HLOCAL hLocal = pT->GetHandle();
761 ATLASSERT(hLocal != NULL);
762 LPCTSTR lpszText = (LPCTSTR)::LocalLock(hLocal);
763 ATLASSERT(lpszText != NULL);
764
765 return lpszText;
766 }
767
768 void UnlockBuffer() const
769 {
770 const T* pT = static_cast<const T*>(this);
771
772 ATLASSERT(pT->m_hWnd != NULL);
773
774 BOOL useShadowBuffer = pT->UseShadowBuffer();
775 if(!useShadowBuffer)
776 {
777 HLOCAL hLocal = pT->GetHandle();
778 ATLASSERT(hLocal != NULL);
779 ::LocalUnlock(hLocal);
780 }
781 }
782
783 UINT GetBufferLength() const
784 {
785 const T* pT = static_cast<const T*>(this);
786
787 ATLASSERT(pT->m_hWnd != NULL);
788 UINT nLen = 0;
789 LPCTSTR lpszText = pT->LockBuffer();
790 if(lpszText != NULL)
791 nLen = ::lstrlen(lpszText);
792 pT->UnlockBuffer();
793
794 return nLen;
795 }
796
797 LONG EndOfLine(LPCTSTR lpszText, UINT nLen, UINT nIndex) const
798 {
799 LPCTSTR lpsz = lpszText + nIndex;
800 LPCTSTR lpszStop = lpszText + nLen;
801 while(lpsz < lpszStop && *lpsz != _T('\r'))
802 ++lpsz;
803 return LONG(lpsz - lpszText);
804 }
805
806 LONG GetSelText(_CSTRING_NS::CString& strText) const
807 {
808 const T* pT = static_cast<const T*>(this);
809
810 int nStartChar = 0, nEndChar = 0;
811 pT->GetSel(nStartChar, nEndChar);
812 ATLASSERT((UINT)nEndChar <= pT->GetBufferLength());
813 LPCTSTR lpszText = pT->LockBuffer();
814 LONG nLen = pT->EndOfLine(lpszText, nEndChar, nStartChar) - nSta rtChar;
815 SecureHelper::memcpy_x(strText.GetBuffer(nLen), nLen * sizeof(TC HAR), lpszText + nStartChar, nLen * sizeof(TCHAR));
816 strText.ReleaseBuffer(nLen);
817 pT->UnlockBuffer();
818
819 return nLen;
820 }
821
822 BOOL UseShadowBuffer(void) const
823 {
824 const T* pT = static_cast<const T*>(this);
825
826 if(pT->m_bShadowBufferNeeded < 0)
827 {
828 T* pThisNoConst = const_cast<T*>(pT);
829
830 OSVERSIONINFO ovi = { 0 };
831 ovi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
832 ::GetVersionEx(&ovi);
833
834 bool bWin9x = (ovi.dwPlatformId == VER_PLATFORM_WIN32_WI NDOWS);
835 if(bWin9x)
836 {
837 // Windows 95, 98, ME
838 // Under Win9x, it is necessary to maintain a sh adow buffer.
839 // It is only updated when the control contents have been changed.
840 pThisNoConst->m_bShadowBufferNeeded = TRUE;
841 }
842 else
843 {
844 // Windows NT, 2000, XP, etc.
845 pThisNoConst->m_bShadowBufferNeeded = FALSE;
846
847 #ifndef _UNICODE
848 // On Windows XP (or later), if common controls version 6 is in use
849 // (such as via theming), then EM_GETHANDLE will always return a UNICODE string.
850 // If theming is enabled and Common Controls ver sion 6 is in use,
851 // you're really not suppose to superclass or su bclass common controls
852 // with an ANSI windows procedure (so its best t o only theme if you use UNICODE).
853 // Using a shadow buffer uses GetWindowText inst ead, so it solves
854 // this problem for us (although it makes it a l ittle less efficient).
855
856 if((ovi.dwMajorVersion == 5 && ovi.dwMinorVersio n >= 1) || (ovi.dwMajorVersion > 5))
857 {
858 // We use DLLVERSIONINFO_private so we d on't have to depend on shlwapi.h
859 typedef struct _DLLVERSIONINFO_private
860 {
861 DWORD cbSize;
862 DWORD dwMajorVersion;
863 DWORD dwMinorVersion;
864 DWORD dwBuildNumber;
865 DWORD dwPlatformID;
866 } DLLVERSIONINFO_private;
867
868 HMODULE hModule = ::LoadLibrary("comctl3 2.dll");
869 if(hModule != NULL)
870 {
871 typedef HRESULT (CALLBACK *LPFN_ DllGetVersion)(DLLVERSIONINFO_private *);
872 LPFN_DllGetVersion fnDllGetVersi on = (LPFN_DllGetVersion)::GetProcAddress(hModule, "DllGetVersion");
873 if(fnDllGetVersion != NULL)
874 {
875 DLLVERSIONINFO_private v ersion = { 0 };
876 version.cbSize = sizeof( DLLVERSIONINFO_private);
877 if(SUCCEEDED(fnDllGetVer sion(&version)))
878 {
879 if(version.dwMaj orVersion >= 6)
880 {
881 pThisNoC onst->m_bShadowBufferNeeded = TRUE;
882
883 ATLTRACE 2(atlTraceUI, 0, _T("Warning: You have compiled for MBCS/ANSI but are using comm on controls version 6 or later (likely through a manifest file).\r\n"));
884 ATLTRACE 2(atlTraceUI, 0, _T("If you use common controls version 6 or later, you should o nly do so for UNICODE builds.\r\n"));
885 }
886 }
887 }
888
889 ::FreeLibrary(hModule);
890 hModule = NULL;
891 }
892 }
893 #endif // !_UNICODE
894 }
895 }
896
897 return (pT->m_bShadowBufferNeeded == TRUE);
898 }
899 };
900
901
902 ///////////////////////////////////////////////////////////////////////////////
903 // CRichEditFindReplaceImpl - Mixin class for implementing Find/Replace for CRic hEditCtrl
904 // based window classes.
905
906 // Chain to CRichEditFindReplaceImpl message map. Your class must also derive fr om CRichEditCtrl.
907 // Example:
908 // class CMyRichEdit : public CWindowImpl<CMyRichEdit, CRichEditCtrl>,
909 // public CRichEditFindReplaceImpl<CMyRichEdit>
910 // {
911 // public:
912 // BEGIN_MSG_MAP(CMyRichEdit)
913 // // your handlers...
914 // CHAIN_MSG_MAP_ALT(CRichEditFindReplaceImpl<CMyRichEdit>, 1)
915 // END_MSG_MAP()
916 // // other stuff...
917 // };
918
919 template <class T, class TFindReplaceDialog = CFindReplaceDialog>
920 class CRichEditFindReplaceImpl : public CEditFindReplaceImplBase<T, TFindReplace Dialog>
921 {
922 protected:
923 typedef CRichEditFindReplaceImpl<T, TFindReplaceDialog> thisClass;
924 typedef CEditFindReplaceImplBase<T, TFindReplaceDialog> baseClass;
925
926 public:
927 BEGIN_MSG_MAP(thisClass)
928 ALT_MSG_MAP(1)
929 CHAIN_MSG_MAP_ALT(baseClass, 1)
930 END_MSG_MAP()
931
932 // Operations (overrideable)
933 BOOL FindTextSimple(LPCTSTR lpszFind, BOOL bMatchCase, BOOL bWholeWord, BOOL bFindDown = TRUE)
934 {
935 T* pT = static_cast<T*>(this);
936
937 ATLASSERT(lpszFind != NULL);
938 FINDTEXTEX ft = { 0 };
939
940 pT->GetSel(ft.chrg);
941 if(m_bFirstSearch)
942 {
943 if(bFindDown)
944 m_nInitialSearchPos = ft.chrg.cpMin;
945 else
946 m_nInitialSearchPos = ft.chrg.cpMax;
947 m_bFirstSearch = FALSE;
948 }
949
950 #if (_RICHEDIT_VER >= 0x0200)
951 ft.lpstrText = (LPTSTR)lpszFind;
952 #else // !(_RICHEDIT_VER >= 0x0200)
953 USES_CONVERSION;
954 ft.lpstrText = T2A((LPTSTR)lpszFind);
955 #endif // !(_RICHEDIT_VER >= 0x0200)
956
957 if(ft.chrg.cpMin != ft.chrg.cpMax) // i.e. there is a selection
958 {
959 if(bFindDown)
960 {
961 ft.chrg.cpMin++;
962 }
963 else
964 {
965 // won't wraparound backwards
966 ft.chrg.cpMin = __max(ft.chrg.cpMin, 0);
967 }
968 }
969
970 DWORD dwFlags = bMatchCase ? FR_MATCHCASE : 0;
971 dwFlags |= bWholeWord ? FR_WHOLEWORD : 0;
972
973 ft.chrg.cpMax = pT->GetTextLength() + m_nInitialSearchPos;
974
975 if(bFindDown)
976 {
977 if(m_nInitialSearchPos >= 0)
978 ft.chrg.cpMax = pT->GetTextLength();
979
980 dwFlags |= FR_DOWN;
981 ATLASSERT(ft.chrg.cpMax >= ft.chrg.cpMin);
982 }
983 else
984 {
985 if(m_nInitialSearchPos >= 0)
986 ft.chrg.cpMax = 0;
987
988 dwFlags &= ~FR_DOWN;
989 ATLASSERT(ft.chrg.cpMax <= ft.chrg.cpMin);
990 }
991
992 BOOL bRet = FALSE;
993
994 if(pT->FindAndSelect(dwFlags, ft) != -1)
995 {
996 bRet = TRUE; // we found the text
997 }
998 else if(m_nInitialSearchPos > 0)
999 {
1000 // if the original starting point was not the beginning
1001 // of the buffer and we haven't already been here
1002 if(bFindDown)
1003 {
1004 ft.chrg.cpMin = 0;
1005 ft.chrg.cpMax = m_nInitialSearchPos;
1006 }
1007 else
1008 {
1009 ft.chrg.cpMin = pT->GetTextLength();
1010 ft.chrg.cpMax = m_nInitialSearchPos;
1011 }
1012 m_nInitialSearchPos = m_nInitialSearchPos - pT->GetTextL ength();
1013
1014 bRet = (pT->FindAndSelect(dwFlags, ft) != -1) ? TRUE : F ALSE;
1015 }
1016
1017 return bRet;
1018 }
1019
1020 long FindAndSelect(DWORD dwFlags, FINDTEXTEX& ft)
1021 {
1022 T* pT = static_cast<T*>(this);
1023 LONG index = pT->FindText(dwFlags, ft);
1024 if(index != -1) // i.e. we found something
1025 pT->SetSel(ft.chrgText);
1026
1027 return index;
1028 }
1029 };
1030
1031 }; // namespace WTL
1032
1033 #endif // __ATLFIND_H__
OLDNEW
« no previous file with comments | « third_party/wtl/include/atldlgs.h ('k') | third_party/wtl/include/atlframe.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698