1 #include "StdAfx.h"
2 #include "FindReplaceForm.h"
3 #include "Document.h"
4 
5 using namespace System;
6 using namespace System::Windows::Forms;
7 using namespace WeifenLuo::WinFormsUI::Docking;
8 
9 namespace ContextFreeNet {
10     System::Void FindReplaceForm::findText_Changed(System::Object^  sender, System::EventArgs^  e)
11     {
12         bool canFind = findText->Text->Length > 0;
13         nextButton->Enabled = canFind;
14         prevButton->Enabled = canFind;
15         replaceButton->Enabled = canFind;
16         replaceAllButton->Enabled = canFind;
17         replaceAllSelectionButton->Enabled = canFind;
18     }
19 
20     System::Void FindReplaceForm::find_Click(System::Object^  sender, System::EventArgs^  e)
21     {
22         ScintillaNET::Scintilla^ haystack = getRTB();
23         if (findText->Text->Length == 0 || haystack == nullptr) {
24             System::Media::SystemSounds::Beep->Play();
25             return;
26         }
27 
28         doFind(haystack, true);
29         haystack->Focus();
30     }
31 
32     System::Void ContextFreeNet::FindReplaceForm::prev_Click(System::Object ^ sender, System::EventArgs ^ e)
33     {
34         ScintillaNET::Scintilla^ haystack = getRTB();
35         if (findText->Text->Length == 0 || haystack == nullptr) {
36             System::Media::SystemSounds::Beep->Play();
37             return;
38         }
39 
40         doFind(haystack, false);
41         haystack->Focus();
42     }
43 
44     System::Void FindReplaceForm::replace_Click(System::Object^  sender, System::EventArgs^  e)
45     {
46         ScintillaNET::Scintilla^ haystack = getRTB();
47         if (findText->Text->Length == 0 || haystack == nullptr) {
48             System::Media::SystemSounds::Beep->Play();
49             return;
50         }
51 
52         doReplace(haystack, false, false);
53         haystack->Focus();
54     }
55 
56     System::Void FindReplaceForm::replaceAll_Click(System::Object^  sender, System::EventArgs^  e)
57     {
58         ScintillaNET::Scintilla^ haystack = getRTB();
59         if (findText->Text->Length == 0 || haystack == nullptr) {
60             System::Media::SystemSounds::Beep->Play();
61             return;
62         }
63 
64         doReplace(haystack, true, false);
65         haystack->Focus();
66     }
67 
68     System::Void FindReplaceForm::replaceAllSelection_Click(System::Object^  sender, System::EventArgs^  e)
69     {
70         ScintillaNET::Scintilla^ haystack = getRTB();
71         if (findText->Text->Length == 0 || haystack == nullptr) {
72             System::Media::SystemSounds::Beep->Play();
73             return;
74         }
75 
76         doReplace(haystack, true, true);
77         haystack->Focus();
78     }
79 
80     bool FindReplaceForm::doFind(ScintillaNET::Scintilla^ haystack, bool forward)
81     {
82         bool found = false;
83         if (haystack == nullptr) return false;
84 
85         bool up = !forward;
86         bool whole = findWhole->Checked;
87         bool start = findStarts->Checked;
88         bool ic = ignoreCaseCheck->Checked;
89         bool wrap = wrapAroundCheck->Checked;
90         auto finds =
91             (whole ? ScintillaNET::SearchFlags::WholeWord : ScintillaNET::SearchFlags::None) |
92             (start ? ScintillaNET::SearchFlags::WordStart : ScintillaNET::SearchFlags::None) |
93             (ic ? ScintillaNET::SearchFlags::None : ScintillaNET::SearchFlags::MatchCase);
94 
95         if (up) {
96             haystack->TargetStart = haystack->AnchorPosition;
97             haystack->TargetEnd = 0;
98         } else {
99             haystack->TargetStart = haystack->CurrentPosition;
100             haystack->TargetEnd = haystack->TextLength;
101         }
102         haystack->SearchFlags = finds;
103 
104         auto needle = haystack->SearchInTarget(findText->Text);
105         found = needle >= 0;
106 
107         if (!found && wrap) {
108             if (up) {
109                 haystack->TargetStart = haystack->TextLength;
110                 haystack->TargetEnd = 0;
111             } else {
112                 haystack->TargetStart = 0;
113                 haystack->TargetEnd = haystack->TextLength;
114             }
115             needle = haystack->SearchInTarget(findText->Text);
116             found = needle >= 0;
117         }
118 
119         if (found) {
120             haystack->SetSelection(haystack->TargetEnd, haystack->TargetStart);
121             haystack->ScrollCaret();
122         } else {
123             notFoundSound->Play();
124         }
125 
126         notFound->Visible = !found;
127 
128         return found;
129     }
130 
131     void FindReplaceForm::doReplace(ScintillaNET::Scintilla^ rtb, bool all, bool selection)
132     {
133         ScintillaNET::Scintilla^ haystack = rtb;
134 
135         bool whole = findWhole->Checked;
136         bool start = findStarts->Checked;
137         bool ic = ignoreCaseCheck->Checked;
138         bool wrap = wrapAroundCheck->Checked;
139         auto finds =
140             (whole ? ScintillaNET::SearchFlags::WholeWord : ScintillaNET::SearchFlags::None) |
141             (start ? ScintillaNET::SearchFlags::WordStart : ScintillaNET::SearchFlags::None) |
142             (ic ? ScintillaNET::SearchFlags::None : ScintillaNET::SearchFlags::MatchCase);
143 
144         int startPosition = (all && !selection) ? 0 : haystack->CurrentPosition;
145         int endPosition = (all && selection) ? haystack->AnchorPosition : haystack->TextLength;
146 
147         if (all && endPosition < startPosition)
148             std::swap(startPosition, endPosition);
149         if (all && endPosition == startPosition)
150             return;
151 
152         haystack->SearchFlags = finds;
153         haystack->TargetStart = startPosition;
154         haystack->TargetEnd = endPosition;
155 
156         if (all) {
157             bool replaced = false;
158             auto delta = replaceText->Text->Length - findText->Text->Length;
159             for (;;) {
160                 auto needle = haystack->SearchInTarget(findText->Text);
161                 if (needle < 0) break;
162 
163                 if (!replaced)
164                     haystack->BeginUndoAction();
165                 replaced = true;
166 
167                 haystack->ReplaceTarget(replaceText->Text);
168 
169                 if (selection)
170                     endPosition += delta;
171                 else
172                     endPosition = haystack->TextLength;
173                 haystack->TargetStart = haystack->TargetEnd;
174                 haystack->TargetEnd = endPosition;
175             }
176             notFound->Visible = !replaced;
177             if (replaced)
178                 haystack->EndUndoAction();
179             else
180                 notFoundSound->Play();
181         } else {
182             auto needle = haystack->SearchInTarget(findText->Text);
183             if (needle < 0 && wrap) {
184                 haystack->TargetStart = 0;
185                 haystack->TargetEnd = haystack->TextLength;
186                 needle = haystack->SearchInTarget(findText->Text);
187             }
188             notFound->Visible = needle < 0;
189             if (needle >= 0) {
190                 haystack->ReplaceTarget(replaceText->Text);
191                 haystack->SetSelection(haystack->TargetEnd, haystack->TargetStart);
192                 haystack->ScrollCaret();
193             } else {
194                 notFoundSound->Play();
195             }
196         }
197     }
198 
199     ScintillaNET::Scintilla^ FindReplaceForm::getRTB()
200     {
201         Document^ cfdg = dynamic_cast<Document^>(DockPanel->ActiveDocument);
202         return (cfdg != nullptr) ? cfdg->cfdgText : nullptr;
203     }
204 }