1 ////////////////////////////////////////////////////////////////////////////
2 // File: ceditreplacedlg.cpp
4 // Created: 29-Dec-1998
6 // Author: Stcherbatchenko Andrei
7 // E-mail: windfall@gmx.de
9 // Implementation of the CEditReplaceDlg dialog, a part of Crystal Edit -
10 // syntax coloring text editor.
12 // You are free to use or modify this code to the following restrictions:
13 // - Acknowledge me somewhere in your about box, simple "Parts of code by.."
14 // will be enough. If you can't (or don't want to), contact me personally.
15 // - LEAVE THIS HEADER INTACT
16 ////////////////////////////////////////////////////////////////////////////
18 ////////////////////////////////////////////////////////////////////////////
21 // + FEATURE: regular expressions, go to line and things ...
22 // + FEATURE: some other things I've forgotten ...
24 // ... it's being edited very rapidly so sorry for non-commented
25 // and maybe "ugly" code ...
26 ////////////////////////////////////////////////////////////////////////////
28 * @file ceditreplacedlg.cpp
30 * @brief Implementation of Replace-dialog.
32 // RCS ID line follows -- this is updated by CVS
37 #include "ceditreplacedlg.h"
38 #include "ccrystaleditview.h"
40 #include "DDXHelper.h"
46 #ifndef MB_DONT_DISPLAY_AGAIN
47 #define MB_DONT_DISPLAY_AGAIN 0x01000000L // Additional style.
50 /////////////////////////////////////////////////////////////////////////////
51 // CEditReplaceDlg dialog
54 CEditReplaceDlg::CEditReplaceDlg (CCrystalEditView * pBuddy)
55 : CDialog (CEditReplaceDlg::IDD, nullptr)
63 , m_bEnableScopeSelection(true)
67 ASSERT (pBuddy != nullptr);
70 void CEditReplaceDlg::
75 m_ctlWholeWord.EnableWindow (false);
80 m_ctlWholeWord.EnableWindow (true);
84 void CEditReplaceDlg::
85 DoDataExchange (CDataExchange * pDX)
87 CDialog::DoDataExchange (pDX);
88 //{{AFX_DATA_MAP(CEditReplaceDlg)
89 DDX_Control (pDX, IDC_EDIT_FINDTEXT, m_ctlFindText);
90 DDX_Control (pDX, IDC_EDIT_REPLACE_WITH, m_ctlReplText);
91 DDX_Control (pDX, IDC_EDIT_WHOLE_WORD, m_ctlWholeWord);
92 DDX_Check (pDX, IDC_EDIT_MATCH_CASE, m_bMatchCase);
93 DDX_Check (pDX, IDC_EDIT_WHOLE_WORD, m_bWholeWord);
94 DDX_Check (pDX, IDC_EDIT_REGEXP, m_bRegExp);
95 DDX_CBString (pDX, IDC_EDIT_FINDTEXT, m_sText);
96 DDX_CBString (pDX, IDC_EDIT_REPLACE_WITH, m_sNewText);
97 DDX_Radio (pDX, IDC_EDIT_SCOPE_SELECTION, m_nScope);
98 DDX_Check (pDX, IDC_EDIT_SCOPE_DONT_WRAP, m_bDontWrap);
103 BEGIN_MESSAGE_MAP (CEditReplaceDlg, CDialog)
104 //{{AFX_MSG_MAP(CEditReplaceDlg)
105 ON_CBN_EDITCHANGE (IDC_EDIT_FINDTEXT, OnChangeEditText)
106 ON_CBN_SELCHANGE (IDC_EDIT_FINDTEXT, OnChangeSelected)
107 ON_BN_CLICKED (IDC_EDIT_REPLACE, OnEditReplace)
108 ON_BN_CLICKED (IDC_EDIT_REPLACE_ALL, OnEditReplaceAll)
109 ON_BN_CLICKED (IDC_EDIT_SKIP, OnEditSkip)
110 ON_BN_CLICKED (IDC_EDIT_FINDPREV, OnEditFindPrev)
111 ON_BN_CLICKED (IDC_EDIT_REGEXP, OnRegExp)
115 BOOL CEditReplaceDlg::PreTranslateMessage(MSG* pMsg)
117 if (pMsg->message == WM_KEYDOWN && pMsg->wParam == VK_RETURN)
119 CButton *pSkip = (CButton*) GetDlgItem (IDC_EDIT_SKIP);
120 if (pSkip->GetButtonStyle () & BS_DEFPUSHBUTTON)
130 return CDialog::PreTranslateMessage(pMsg);
133 /////////////////////////////////////////////////////////////////////////////
134 // CEditReplaceDlg message handlers
136 void CEditReplaceDlg::OnChangeEditText ()
141 void CEditReplaceDlg::OnChangeSelected ()
143 int sel = m_ctlFindText.GetCurSel();
146 m_ctlFindText.GetLBText(sel, m_sText);
147 m_ctlFindText.SetWindowText(m_sText);
152 void CEditReplaceDlg::
155 VERIFY (UpdateData ());
156 CDialog::OnCancel ();
157 m_pBuddy->SetFocus();
160 BOOL CEditReplaceDlg::
163 LangTranslateDialog(m_hWnd);
164 CDialog::OnInitDialog ();
166 CMemComboBox::LoadSettings();
167 m_ctlReplText.m_sGroup = _T ("ReplaceText");
168 m_ctlReplText.OnSetfocus ();
169 GetDlgItem (IDC_EDIT_REPLACE_WITH)->GetWindowText (m_sNewText);
171 m_ctlFindText.m_sGroup = _T ("FindText");
172 m_ctlFindText.OnSetfocus ();
174 GetDlgItem (IDC_EDIT_SCOPE_SELECTION)->EnableWindow (m_bEnableScopeSelection);
180 LastSearchInfos * CEditReplaceDlg::
186 bool CEditReplaceDlg::
187 DoHighlightText ( bool bNotifyIfNotFound )
189 ASSERT (m_pBuddy != nullptr);
190 DWORD dwSearchFlags = 0;
192 dwSearchFlags |= FIND_MATCH_CASE;
194 dwSearchFlags |= FIND_WHOLE_WORD;
196 dwSearchFlags |= FIND_REGEXP;
197 if (m_nDirection == 0)
198 dwSearchFlags |= FIND_DIRECTION_UP;
200 m_ptFoundAt = m_pBuddy->GetSearchPos (dwSearchFlags);
205 // Searching selection only
206 bFound = m_pBuddy->FindTextInBlock (m_sText, m_ptFoundAt, m_ptBlockBegin, m_ptBlockEnd,
207 dwSearchFlags, false, &m_ptFoundAt);
209 else if (m_bDontWrap)
211 // Searching whole text, no wrap
212 bFound = m_pBuddy->FindText (m_sText, m_ptFoundAt, dwSearchFlags, false, &m_ptFoundAt);
216 // Searching whole text, wrap
217 bFound = m_pBuddy->FindText (m_sText, m_ptFoundAt, dwSearchFlags, true, &m_ptFoundAt);
222 if ( bNotifyIfNotFound )
224 CString prompt, text(m_sText);
225 prompt.Format (LoadResString(IDS_EDIT_TEXT_NOT_FOUND).c_str(), (LPCTSTR)text);
226 AfxMessageBox (prompt, MB_ICONINFORMATION);
229 m_ptCurrentPos = m_ptBlockBegin;
234 m_pBuddy->HighlightText (m_ptFoundAt, m_pBuddy->m_nLastFindWhatLen);
238 bool CEditReplaceDlg::
239 DoReplaceText (LPCTSTR /*pszNewText*/, DWORD dwSearchFlags)
241 ASSERT (m_pBuddy != nullptr);
242 // m_pBuddy->m_nLastFindWhatLen
247 // Searching selection only
248 bFound = m_pBuddy->FindTextInBlock (m_sText, m_ptFoundAt, m_ptBlockBegin, m_ptBlockEnd,
249 dwSearchFlags, false, &m_ptFoundAt);
251 else if (m_bDontWrap)
253 // Searching whole text, no wrap
254 bFound = m_pBuddy->FindText (m_sText, m_ptFoundAt, dwSearchFlags, false, &m_ptFoundAt);
258 // Searching whole text, wrap
259 bFound = m_pBuddy->FindText (m_sText, m_ptFoundAt, dwSearchFlags, true, &m_ptFoundAt);
264 CString prompt, text(m_sText);
265 prompt.Format (LoadResString(IDS_EDIT_TEXT_NOT_FOUND).c_str(), (LPCTSTR)text);
266 AfxMessageBox (prompt, MB_ICONINFORMATION);
268 m_ptCurrentPos = m_ptBlockBegin;
272 m_pBuddy->HighlightText (m_ptFoundAt, m_pBuddy->m_nLastFindWhatLen);
276 void CEditReplaceDlg::
277 FindNextPrev (bool bNext)
282 m_nDirection = bNext;
283 m_ctlFindText.FillCurrent();
284 m_ctlReplText.FillCurrent();
285 CMemComboBox::SaveSettings();
288 CButton *pSkip = (CButton*) GetDlgItem (IDC_EDIT_SKIP);
289 CButton *pRepl = (CButton*) GetDlgItem (IDC_EDIT_REPLACE);
293 m_bFound = DoHighlightText ( true );
296 pSkip->SetButtonStyle (pSkip->GetButtonStyle () & ~BS_DEFPUSHBUTTON);
297 pRepl->SetButtonStyle (pRepl->GetButtonStyle () | BS_DEFPUSHBUTTON);
298 // pRepl->SetFocus ();
302 pRepl->SetButtonStyle (pRepl->GetButtonStyle () & ~BS_DEFPUSHBUTTON);
303 pSkip->SetButtonStyle (pSkip->GetButtonStyle () | BS_DEFPUSHBUTTON);
304 // pSkip->SetFocus ();
309 if (!m_pBuddy->m_nLastFindWhatLen)
310 if (m_ptFoundAt.y + 1 < m_pBuddy->GetLineCount ())
322 m_bFound = DoHighlightText ( true );
325 pSkip->SetButtonStyle (pSkip->GetButtonStyle () & ~BS_DEFPUSHBUTTON);
326 pRepl->SetButtonStyle (pRepl->GetButtonStyle () | BS_DEFPUSHBUTTON);
327 // pRepl->SetFocus ();
331 pRepl->SetButtonStyle (pRepl->GetButtonStyle () & ~BS_DEFPUSHBUTTON);
332 pSkip->SetButtonStyle (pSkip->GetButtonStyle () | BS_DEFPUSHBUTTON);
333 // pSkip->SetFocus ();
337 void CEditReplaceDlg::
343 void CEditReplaceDlg::
346 FindNextPrev (false);
349 void CEditReplaceDlg::
355 m_ctlFindText.FillCurrent();
356 m_ctlReplText.FillCurrent();
357 CMemComboBox::SaveSettings();
362 m_bFound = DoHighlightText ( true );
363 CButton *pSkip = (CButton*) GetDlgItem (IDC_EDIT_SKIP);
364 CButton *pRepl = (CButton*) GetDlgItem (IDC_EDIT_REPLACE);
367 pSkip->SetButtonStyle (pSkip->GetButtonStyle () & ~BS_DEFPUSHBUTTON);
368 pRepl->SetButtonStyle (pRepl->GetButtonStyle () | BS_DEFPUSHBUTTON);
369 // pRepl->SetFocus ();
373 pRepl->SetButtonStyle (pRepl->GetButtonStyle () & ~BS_DEFPUSHBUTTON);
374 pSkip->SetButtonStyle (pSkip->GetButtonStyle () | BS_DEFPUSHBUTTON);
375 // pSkip->SetFocus ();
379 DWORD dwSearchFlags = 0;
381 dwSearchFlags |= FIND_MATCH_CASE;
383 dwSearchFlags |= FIND_WHOLE_WORD;
385 dwSearchFlags |= FIND_REGEXP;
386 if (m_nDirection == 0)
387 dwSearchFlags |= FIND_DIRECTION_UP;
389 // We have highlighted text
390 VERIFY (m_pBuddy->ReplaceSelection (m_sNewText, m_sNewText.GetLength(), dwSearchFlags));
392 // Manually recalculate points
393 if (m_bEnableScopeSelection)
395 if (m_ptBlockBegin.y == m_ptFoundAt.y && m_ptBlockBegin.x > m_ptFoundAt.x)
397 m_ptBlockBegin.x -= m_pBuddy->m_nLastFindWhatLen;
398 m_ptBlockBegin.x += m_pBuddy->m_nLastReplaceLen;
400 if (m_ptBlockEnd.y == m_ptFoundAt.y && m_ptBlockEnd.x > m_ptFoundAt.x)
402 m_ptBlockEnd.x -= m_pBuddy->m_nLastFindWhatLen;
403 m_ptBlockEnd.x += m_pBuddy->m_nLastReplaceLen;
406 m_ptFoundAt = m_pBuddy->GetCursorPos ();
407 m_bFound = DoHighlightText ( true );
409 m_pBuddy->SaveLastSearch(&lastSearch);
412 void CEditReplaceDlg::
418 m_ctlFindText.FillCurrent();
419 m_ctlReplText.FillCurrent();
420 CMemComboBox::SaveSettings();
423 int nNumReplaced = 0;
424 bool bWrapped = false;
425 CWaitCursor waitCursor;
430 m_ptFoundAt = m_ptCurrentPos;
431 m_bFound = DoHighlightText ( false );
434 CPoint m_ptFirstFound = m_ptFoundAt;
435 bool bGroupWithPrevious = false;
439 DWORD dwSearchFlags = 0;
441 dwSearchFlags |= FIND_MATCH_CASE;
443 dwSearchFlags |= FIND_WHOLE_WORD;
445 dwSearchFlags |= FIND_REGEXP;
447 // We have highlighted text
448 VERIFY (m_pBuddy->ReplaceSelection (m_sNewText, m_sNewText.GetLength(), dwSearchFlags, bGroupWithPrevious));
450 // Manually recalculate points
451 if (m_bEnableScopeSelection)
453 if (m_ptBlockBegin.y == m_ptFoundAt.y && m_ptBlockBegin.x > m_ptFoundAt.x)
455 m_ptBlockBegin.x -= m_pBuddy->m_nLastFindWhatLen;
456 m_ptBlockBegin.x += m_pBuddy->m_nLastReplaceLen;
458 if (m_ptBlockEnd.y == m_ptFoundAt.y && m_ptBlockEnd.x > m_ptFoundAt.x)
460 m_ptBlockEnd.x -= m_pBuddy->m_nLastFindWhatLen;
461 m_ptBlockEnd.x += m_pBuddy->m_nLastReplaceLen;
464 // recalculate m_ptFirstFound
465 if (m_ptFirstFound.y == m_ptFoundAt.y && m_ptFirstFound.x > m_ptFoundAt.x)
467 m_ptFirstFound.x -= m_pBuddy->m_nLastFindWhatLen;
468 m_ptFirstFound.x += m_pBuddy->m_nLastReplaceLen;
471 // calculate the end of the current replacement
472 CPoint m_ptCurrentReplacedEnd = m_pBuddy->GetCursorPos ();
474 // m_ptFoundAt.x has two meanings:
475 // (1) One is the position of the word that was found.
476 // (2) The other is next position to search.
477 // The code below calculates the latter.
478 m_ptFoundAt = m_pBuddy->GetCursorPos ();
481 // find the next instance
482 m_bFound = DoHighlightText ( false );
484 // detect if we just wrapped at end of file
485 if (m_ptFoundAt.y < m_ptCurrentReplacedEnd.y || (m_ptFoundAt.y == m_ptCurrentReplacedEnd.y && m_ptFoundAt.x < m_ptCurrentReplacedEnd.x))
488 // after wrapping, stop at m_ptFirstFound
489 // so we don't replace twice when replacement string includes replaced string
490 // (like replace "here" with "there")
492 if (m_ptFoundAt.y > m_ptFirstFound.y || (m_ptFoundAt.y == m_ptFirstFound.y && m_ptFoundAt.x >= m_ptFirstFound.x))
495 bGroupWithPrevious = true;
498 // Let user know how many strings were replaced
501 strNumber.Format ( _T("%d"), nNumReplaced );
502 LPCTSTR lpsz = static_cast<LPCTSTR>(strNumber);
503 AfxFormatStrings (strMessage, LoadResString(IDS_NUM_REPLACED).c_str(), &lpsz, 1);
505 AfxMessageBox( strMessage, MB_ICONINFORMATION|MB_DONT_DISPLAY_AGAIN, IDS_NUM_REPLACED);
507 m_pBuddy->SaveLastSearch(&lastSearch);
510 void CEditReplaceDlg::
518 void CEditReplaceDlg::
521 GetDlgItem(IDC_EDIT_SKIP)->EnableWindow( !m_sText.IsEmpty() );
522 GetDlgItem(IDC_EDIT_REPLACE)->EnableWindow( !m_sText.IsEmpty() );
523 GetDlgItem(IDC_EDIT_REPLACE_ALL)->EnableWindow( !m_sText.IsEmpty() );
530 // Last search functions
532 void CEditReplaceDlg::
533 SetLastSearch (LPCTSTR sText, bool bMatchCase, bool bWholeWord, bool bRegExp, int nScope, int nDirection)
535 lastSearch.m_bMatchCase = bMatchCase;
536 lastSearch.m_bWholeWord = bWholeWord;
537 lastSearch.m_bRegExp = bRegExp;
538 lastSearch.m_sText = sText;
539 lastSearch.m_bNoWrap = m_bDontWrap;
540 lastSearch.m_nDirection = nDirection;
544 void CEditReplaceDlg::
547 SetLastSearch (m_sText, m_bMatchCase, m_bWholeWord, m_bRegExp, m_nScope, m_nDirection);
550 void CEditReplaceDlg::
553 m_bMatchCase = lastSearch.m_bMatchCase;
554 m_bWholeWord = lastSearch.m_bWholeWord;
555 m_bRegExp = lastSearch.m_bRegExp;
556 m_sText = lastSearch.m_sText;
557 m_bDontWrap = lastSearch.m_bNoWrap;
558 m_nDirection = lastSearch.m_nDirection;
561 void CEditReplaceDlg::
562 SetScope(bool bWithSelection)