1 /***************************************************************
2  * Name:      ThreadSearch
3  * Purpose:   ThreadSearch Code::Blocks plugin
4  *            Most of the interactions with C::B are handled here.
5  * Author:    Jerome ANTOINE
6  * Created:   2007-10-08
7  * Copyright: Jerome ANTOINE
8  * License:   GPL
9  **************************************************************/
10 
11 #include <sdk.h> // Code::Blocks SDK
12 #ifndef CB_PRECOMP
13     #include <wx/combobox.h>
14     #include <wx/menu.h>
15     #include <wx/toolbar.h>
16     #include <wx/xrc/xmlres.h>
17     #include "cbeditor.h"
18     #include "configmanager.h"
19     #include "sdk_events.h"
20 #endif
21 
22 #include "cbstyledtextctrl.h"
23 #include "ThreadSearch.h"
24 #include "ThreadSearchView.h"
25 #include "ThreadSearchCommon.h"
26 #include "ThreadSearchConfPanel.h"
27 #include "ThreadSearchControlIds.h"
28 #include "logging.h" //(pecan 2007/7/26)
29 
30 // Register the plugin with Code::Blocks.
31 // We are using an anonymous namespace so we don't litter the global one.
32 namespace
33 {
34     PluginRegistrant<ThreadSearch> reg(_T("ThreadSearch"));
35 }
36 
37 // ----------------------------------------------------------------------------
38 // CodeBlocks main.cpp managers all the following UI entries in one routine.
39 // So if only one changes, all will change. Therefore, to enable/disable copy/paste,
40 // we have to capture all the following to see if it really belongs to us
41 int idEditUndo = XRCID("idEditUndo");
42 int idEditRedo = XRCID("idEditRedo");
43 int idEditCopy = XRCID("idEditCopy");
44 int idEditCut = XRCID("idEditCut");
45 int idEditPaste = XRCID("idEditPaste");
46 int idEditSwapHeaderSource = XRCID("idEditSwapHeaderSource");
47 int idEditGotoMatchingBrace = XRCID("idEditGotoMatchingBrace");
48 int idEditBookmarks = XRCID("idEditBookmarks");
49 int idEditBookmarksToggle = XRCID("idEditBookmarksToggle");
50 int idEditBookmarksPrevious = XRCID("idEditBookmarksPrevious");
51 int idEditBookmarksNext = XRCID("idEditBookmarksNext");
52 int idEditFoldAll = XRCID("idEditFoldAll");
53 int idEditUnfoldAll = XRCID("idEditUnfoldAll");
54 int idEditToggleAllFolds = XRCID("idEditToggleAllFolds");
55 int idEditFoldBlock = XRCID("idEditFoldBlock");
56 int idEditUnfoldBlock = XRCID("idEditUnfoldBlock");
57 int idEditToggleFoldBlock = XRCID("idEditToggleFoldBlock");
58 int idEditEOLCRLF = XRCID("idEditEOLCRLF");
59 int idEditEOLCR = XRCID("idEditEOLCR");
60 int idEditEOLLF = XRCID("idEditEOLLF");
61 int idEditEncoding = XRCID("idEditEncoding");
62 int idEditSelectAll = XRCID("idEditSelectAll");
63 int idEditCommentSelected = XRCID("idEditCommentSelected");
64 int idEditUncommentSelected = XRCID("idEditUncommentSelected");
65 int idEditToggleCommentSelected = XRCID("idEditToggleCommentSelected");
66 int idEditAutoComplete = XRCID("idEditAutoComplete");
67 // ----------------------------------------------------------------------------
68 
69 int idMenuEditCopy = XRCID("idEditCopy");
70 int idMenuEditPaste = XRCID("idEditPaste");
71 
72 // events handling
BEGIN_EVENT_TABLE(ThreadSearch,cbPlugin)73 BEGIN_EVENT_TABLE(ThreadSearch, cbPlugin)
74     // add any events you want to handle here
75     EVT_UPDATE_UI (controlIDs.Get(ControlIDs::idMenuViewThreadSearch),   ThreadSearch::OnMnuViewThreadSearchUpdateUI)
76     EVT_MENU      (controlIDs.Get(ControlIDs::idMenuViewThreadSearch),   ThreadSearch::OnMnuViewThreadSearch)
77     EVT_UPDATE_UI (controlIDs.Get(ControlIDs::idMenuViewFocusThreadSearch),   ThreadSearch::OnMnuViewFocusThreadSearchUpdateUI)
78     EVT_MENU      (controlIDs.Get(ControlIDs::idMenuViewFocusThreadSearch),   ThreadSearch::OnMnuViewFocusThreadSearch)
79     EVT_UPDATE_UI (controlIDs.Get(ControlIDs::idMenuSearchThreadSearch), ThreadSearch::OnMnuSearchThreadSearchUpdateUI)
80     EVT_MENU      (controlIDs.Get(ControlIDs::idMenuSearchThreadSearch), ThreadSearch::OnMnuSearchThreadSearch)
81     EVT_MENU      (controlIDs.Get(ControlIDs::idMenuCtxThreadSearch),    ThreadSearch::OnCtxThreadSearch)
82     EVT_MENU      (idMenuEditCopy,           ThreadSearch::OnMnuEditCopy)
83     EVT_UPDATE_UI (idMenuEditCopy,           ThreadSearch::OnMnuEditCopyUpdateUI)
84     EVT_MENU      (idMenuEditPaste,          ThreadSearch::OnMnuEditPaste)
85     EVT_TOOL      (controlIDs.Get(ControlIDs::idBtnOptions),             ThreadSearch::OnBtnOptionsClick)
86     EVT_TOOL      (controlIDs.Get(ControlIDs::idBtnSearch),              ThreadSearch::OnBtnSearchClick)
87     EVT_TEXT_ENTER(controlIDs.Get(ControlIDs::idCboSearchExpr),          ThreadSearch::OnCboSearchExprEnter)
88     EVT_TEXT      (controlIDs.Get(ControlIDs::idCboSearchExpr),          ThreadSearch::OnCboSearchExprEnter)
89     EVT_TEXT_ENTER(controlIDs.Get(ControlIDs::idSearchDirPath),       ThreadSearch::OnCboSearchExprEnter)
90     EVT_TEXT_ENTER(controlIDs.Get(ControlIDs::idSearchMask),          ThreadSearch::OnCboSearchExprEnter)
91 // ---------------------------------------------------------------------------
92     // CodeBlocks main.cpp managers all the following UI entires in ONE routine.
93     // So if only one changes, all may change.
94     //Therefore, to enable/disable copy/paste, we have to capture all the following
95     // to see if the event actually belongs to us.
96     EVT_UPDATE_UI(idEditUndo, ThreadSearch::OnMnuEditCopyUpdateUI)
97     EVT_UPDATE_UI(idEditRedo, ThreadSearch::OnMnuEditCopyUpdateUI)
98     EVT_UPDATE_UI(idEditCopy, ThreadSearch::OnMnuEditCopyUpdateUI)
99     EVT_UPDATE_UI(idEditCut, ThreadSearch::OnMnuEditCopyUpdateUI)
100     EVT_UPDATE_UI(idEditPaste, ThreadSearch::OnMnuEditCopyUpdateUI)
101     EVT_UPDATE_UI(idEditSwapHeaderSource, ThreadSearch::OnMnuEditCopyUpdateUI)
102     EVT_UPDATE_UI(idEditGotoMatchingBrace, ThreadSearch::OnMnuEditCopyUpdateUI)
103     EVT_UPDATE_UI(idEditFoldAll, ThreadSearch::OnMnuEditCopyUpdateUI)
104     EVT_UPDATE_UI(idEditUnfoldAll, ThreadSearch::OnMnuEditCopyUpdateUI)
105     EVT_UPDATE_UI(idEditToggleAllFolds, ThreadSearch::OnMnuEditCopyUpdateUI)
106     EVT_UPDATE_UI(idEditFoldBlock, ThreadSearch::OnMnuEditCopyUpdateUI)
107     EVT_UPDATE_UI(idEditUnfoldBlock, ThreadSearch::OnMnuEditCopyUpdateUI)
108     EVT_UPDATE_UI(idEditToggleFoldBlock, ThreadSearch::OnMnuEditCopyUpdateUI)
109     EVT_UPDATE_UI(idEditEOLCRLF, ThreadSearch::OnMnuEditCopyUpdateUI)
110     EVT_UPDATE_UI(idEditEOLCR, ThreadSearch::OnMnuEditCopyUpdateUI)
111     EVT_UPDATE_UI(idEditEOLLF, ThreadSearch::OnMnuEditCopyUpdateUI)
112     EVT_UPDATE_UI(idEditEncoding, ThreadSearch::OnMnuEditCopyUpdateUI)
113     EVT_UPDATE_UI(idEditSelectAll, ThreadSearch::OnMnuEditCopyUpdateUI)
114     EVT_UPDATE_UI(idEditBookmarksToggle, ThreadSearch::OnMnuEditCopyUpdateUI)
115     EVT_UPDATE_UI(idEditBookmarksNext, ThreadSearch::OnMnuEditCopyUpdateUI)
116     EVT_UPDATE_UI(idEditBookmarksPrevious, ThreadSearch::OnMnuEditCopyUpdateUI)
117     EVT_UPDATE_UI(idEditCommentSelected, ThreadSearch::OnMnuEditCopyUpdateUI)
118     EVT_UPDATE_UI(idEditAutoComplete, ThreadSearch::OnMnuEditCopyUpdateUI)
119     EVT_UPDATE_UI(idEditUncommentSelected, ThreadSearch::OnMnuEditCopyUpdateUI)
120     EVT_UPDATE_UI(idEditToggleCommentSelected, ThreadSearch::OnMnuEditCopyUpdateUI)
121 END_EVENT_TABLE()
122 
123 // constructor
124 ThreadSearch::ThreadSearch()
125              :m_SearchedWord(wxEmptyString),
126               m_pThreadSearchView(NULL),
127               m_pViewManager(NULL),
128               m_pToolbar(NULL),
129               m_CtxMenuIntegration(true),
130               m_UseDefValsForThreadSearch(true),
131               m_ShowSearchControls(true),
132               m_ShowDirControls(false),
133               m_ShowCodePreview(true),
134               m_DeletePreviousResults(true),
135               m_LoggerType(ThreadSearchLoggerBase::TypeList),
136               m_DisplayLogHeaders(true),
137               m_DrawLogLines(false),
138               m_AutosizeLogColumns(false),
139               m_pCboSearchExpr(0),
140               m_SplitterMode(wxSPLIT_VERTICAL),
141               m_FileSorting(InsertIndexManager::SortByFilePath)
142 {
143 }
144 
145 // destructor
~ThreadSearch()146 ThreadSearch::~ThreadSearch()
147 {
148 }
149 
OnAttach()150 void ThreadSearch::OnAttach()
151 {
152     // NOTE: after this function, the inherited member variable
153     // m_IsAttached will be TRUE...
154     // You should check for it in other functions, because if it
155     // is FALSE, it means that the application did *not* "load"
156     // (see: does not need) this plugin...
157 
158     #if LOGGING
159      wxLog::EnableLogging(true);
160      m_pLog = new wxLogWindow(Manager::Get()->GetAppWindow(), _T(" ThreadSearch Plugin"), true, false);
161      wxLog::SetActiveTarget( m_pLog);
162      m_pLog->Flush();
163      m_pLog->GetFrame()->SetSize(20,30,600,300);
164      LOGIT( _T("ThreadSearch Plugin Logging Started"));
165     #endif
166 
167     bool showPanel;
168     int  sashPosition;
169     ThreadSearchViewManagerBase::eManagerTypes mgrType;
170     wxArrayString searchPatterns, searchDirs, searchMasks;
171 
172     // Loads configuration from default.conf
173     LoadConfig(showPanel, sashPosition, mgrType, searchPatterns, searchDirs, searchMasks);
174 
175     // Adds window to the manager
176     m_pThreadSearchView = new ThreadSearchView(*this);
177     m_pThreadSearchView->SetSearchHistory(searchPatterns, searchDirs, searchMasks);
178 
179     // Builds manager
180     m_pViewManager = ThreadSearchViewManagerBase::BuildThreadSearchViewManagerBase(m_pThreadSearchView, true, mgrType);
181 
182     // Ensure view is shown or hidden
183     m_pViewManager->ShowView(showPanel);
184 
185     // Sets splitter sash in the middle of the width of the window
186     // and creates columns as it is not managed in ctor on Linux
187     int x, y;
188     m_pThreadSearchView->GetSize(&x, &y);
189     m_pThreadSearchView->SetSashPosition(x/2);
190     m_pThreadSearchView->Update();
191 
192     // Set the splitter posn from the config
193     if (sashPosition != 0)
194         m_pThreadSearchView->SetSashPosition(sashPosition);
195 
196     // Shows/Hides search widgets on the Messages notebook ThreadSearch panel
197     m_pThreadSearchView->ShowSearchControls(m_ShowSearchControls);
198 
199     // true if it enters in OnRelease for the first time
200     m_OnReleased = false;
201 }
202 
OnRelease(bool)203 void ThreadSearch::OnRelease(bool /*appShutDown*/)
204 {
205     // do de-initialization for your plugin
206     // if appShutDown is false, the plugin is unloaded because Code::Blocks is being shut down,
207     // which means you must not use any of the SDK Managers
208     // NOTE: after this function, the inherited member variable
209     // m_IsAttached will be FALSE...
210 
211     // --------------------------------------------------------------
212     // Carefull! This routine can be entered consecutive times
213     // --------------------------------------------------------------
214     if ( m_OnReleased ) return;
215     m_OnReleased = true;
216 
217     // Removes Thread search menu item from the View menu
218     RemoveMenuItems();
219 
220     m_pToolbar = 0;
221 
222     if ( m_pThreadSearchView != 0 )
223     {
224         m_pViewManager->RemoveViewFromManager();
225         m_pThreadSearchView->Destroy();
226     }
227 
228     delete m_pViewManager;
229     m_pViewManager = 0;
230 }
231 
232 
OnThreadSearchViewDestruction()233 void ThreadSearch::OnThreadSearchViewDestruction()
234 {
235     // Method is called from view destructor.
236     // Destruction is either made by plugin or
237     // Messages Notebook.
238 
239     // We show code preview to save a consistent
240     // value of splitter sash position.
241     m_pThreadSearchView->ApplySplitterSettings(m_ShowCodePreview, m_SplitterMode);
242 
243     // Saves configuration to default.conf
244     SaveConfig(m_pViewManager->IsViewShown(),
245                m_pThreadSearchView->GetSashPosition(),
246                m_pViewManager->GetManagerType(),
247                m_pThreadSearchView->GetSearchHistory(),
248                m_pThreadSearchView->GetSearchDirsHistory(),
249                m_pThreadSearchView->GetSearchMasksHistory());
250 
251     // Reset of the pointer as view is being deleted
252     m_pThreadSearchView = NULL;
253 }
254 
BuildMenu(wxMenuBar * menuBar)255 void ThreadSearch::BuildMenu(wxMenuBar* menuBar)
256 {
257     //The application is offering its menubar for your plugin,
258     //to add any menu items you want...
259     //Append any items you need in the menu...
260     //NOTE: Be careful in here... The application's menubar is at your disposal.
261     size_t i;
262     int idx = menuBar->FindMenu(_("&View"));
263     if (idx != wxNOT_FOUND)
264     {
265         wxMenu* menu = menuBar->GetMenu(idx);
266         wxMenuItemList& items = menu->GetMenuItems();
267 
268         // find the first separator and insert before it
269         for (i = 0; i < items.GetCount(); ++i)
270         {
271             if (items[i]->IsSeparator())
272             {
273                 menu->InsertCheckItem(i, controlIDs.Get(ControlIDs::idMenuViewThreadSearch), _("Thread search"),
274                                       _("Toggle displaying the 'Thread search' panel"));
275                 break;
276             }
277         }
278 
279         if ( i == items.GetCount() )
280         {
281             // not found, just append
282             menu->AppendCheckItem(controlIDs.Get(ControlIDs::idMenuViewThreadSearch), _("Thread search"),
283                                   _("Toggle displaying the 'Thread search' panel"));
284         }
285 
286         menu->Append(controlIDs.Get(ControlIDs::idMenuViewFocusThreadSearch), _("Focus Thread Search"),
287                      _("Makes the search box of the Thread search panel the focused control"));
288     }
289 
290     idx = menuBar->FindMenu(_("Sea&rch"));
291     if (idx != wxNOT_FOUND)
292     {
293         wxMenu* menu = menuBar->GetMenu(idx);
294         wxMenuItemList& items = menu->GetMenuItems();
295 
296         // find the first separator and insert separator + entry before it
297         for (i = 0; i < items.GetCount(); ++i)
298         {
299             if (items[i]->IsSeparator())
300             {
301                 menu->Insert(i, controlIDs.Get(ControlIDs::idMenuSearchThreadSearch), _("Thread search"),
302                                 _("Perform a Threaded search with the current word"));
303                 menu->InsertSeparator(i);
304                 break;
305             }
306         }
307 
308         if ( i == items.GetCount() )
309         {
310             // not found, just append
311             menu->Append(controlIDs.Get(ControlIDs::idMenuSearchThreadSearch), _("Thread search"),
312                             _("Perform a Threaded search with the current word"));
313             menu->AppendSeparator();
314         }
315     }
316 }
317 
RemoveMenuItems()318 void ThreadSearch::RemoveMenuItems()
319 {
320     // Removes 'Thread search' item from View and Search menu
321     wxMenuBar* menuBar = Manager::Get()->GetAppFrame()->GetMenuBar();
322     int idx = menuBar->FindMenu(_("&View"));
323     if (idx != wxNOT_FOUND)
324     {
325         wxMenu* viewMenu = menuBar->GetMenu(idx);
326         if ( viewMenu != 0 )
327         {
328             viewMenu->Remove(controlIDs.Get(ControlIDs::idMenuViewThreadSearch));
329         }
330     }
331 
332     idx = menuBar->FindMenu(_("Sea&rch"));
333     if (idx != wxNOT_FOUND)
334     {
335         wxMenu* searchMenu = menuBar->GetMenu(idx);
336         if ( searchMenu != 0 )
337         {
338             searchMenu->Remove(controlIDs.Get(ControlIDs::idMenuSearchThreadSearch));
339         }
340     }
341 }
342 
343 
OnMnuViewThreadSearch(wxCommandEvent & event)344 void ThreadSearch::OnMnuViewThreadSearch(wxCommandEvent& event)
345 {
346     if ( !IsAttached() )
347         return;
348 
349     m_pViewManager->ShowView(event.IsChecked());
350 }
351 
352 
OnMnuSearchThreadSearch(wxCommandEvent &)353 void ThreadSearch::OnMnuSearchThreadSearch(wxCommandEvent& /*event*/)
354 {
355     if ( !IsAttached() )
356         return;
357 
358     // Need to get the cursor word first and ensure it is consistent.
359     if ( (GetCursorWord(m_SearchedWord) == true) && (m_SearchedWord.IsEmpty() == false) )
360     {
361         // m_SearchedWord is Ok => Search
362         RunThreadSearch(m_SearchedWord, true);
363     }
364     else
365     {
366         // Word is KO, just show the panel
367         m_pViewManager->ShowView(true);
368     }
369 }
370 
OnMnuViewFocusThreadSearch(wxCommandEvent &)371 void ThreadSearch::OnMnuViewFocusThreadSearch(wxCommandEvent& /*event*/)
372 {
373     if ( !IsAttached() )
374         return;
375 
376     GetCursorWord(m_SearchedWord);
377 
378     m_pViewManager->ShowView(true);
379     m_pViewManager->Raise();
380     m_pThreadSearchView->FocusSearchCombo(m_SearchedWord);
381 }
382 
383 
OnCtxThreadSearch(wxCommandEvent &)384 void ThreadSearch::OnCtxThreadSearch(wxCommandEvent& /*event*/)
385 {
386     if ( !IsAttached() )
387         return;
388 
389     // m_SearchedWord was set in BuildModuleMenu
390     RunThreadSearch(m_SearchedWord, true);
391 }
392 
393 
OnMnuViewThreadSearchUpdateUI(wxUpdateUIEvent &)394 void ThreadSearch::OnMnuViewThreadSearchUpdateUI(wxUpdateUIEvent& /*event*/)
395 {
396     if ( !IsAttached() )
397         return;
398 
399     wxMenuBar *menubar = Manager::Get()->GetAppFrame()->GetMenuBar();
400     menubar->Check(controlIDs.Get(ControlIDs::idMenuViewThreadSearch), m_pViewManager->IsViewShown());
401 }
402 
403 
OnMnuSearchThreadSearchUpdateUI(wxUpdateUIEvent & event)404 void ThreadSearch::OnMnuSearchThreadSearchUpdateUI(wxUpdateUIEvent& event)
405 {
406     if ( !IsAttached() )
407         return;
408 
409     event.Enable(m_pThreadSearchView->IsSearchRunning() == false);
410 }
411 
OnMnuViewFocusThreadSearchUpdateUI(wxUpdateUIEvent & event)412 void ThreadSearch::OnMnuViewFocusThreadSearchUpdateUI(wxUpdateUIEvent& event)
413 {
414     if ( !IsAttached() )
415         return;
416 
417     event.Enable(m_pThreadSearchView->IsSearchRunning() == false);
418 }
419 
420 
BuildModuleMenu(const ModuleType type,wxMenu * pMenu,const FileTreeData *)421 void ThreadSearch::BuildModuleMenu(const ModuleType type, wxMenu* pMenu, const FileTreeData* /*data*/)
422 {
423     wxMenuItem* pMenuItem = NULL;
424     if (!pMenu || !IsAttached())
425         return;
426 
427     // Triggs editor events if 'Find occurrences' is integrated in context menu
428     if ( (type == mtEditorManager) && (m_CtxMenuIntegration == true) )
429     {
430         // Gets current word
431         if ( GetCursorWord(m_SearchedWord) == true )
432         {
433             wxString sText = _("Find occurrences of: '") + m_SearchedWord + wxT("'");
434 
435             PluginManager *pluginManager = Manager::Get()->GetPluginManager();
436             int dIndex = pluginManager->GetFindMenuItemFirst() + pluginManager->GetFindMenuItemCount();
437             pMenuItem = pMenu->Insert(dIndex, controlIDs.Get(ControlIDs::idMenuCtxThreadSearch), sText);
438             Manager::Get()->GetPluginManager()->RegisterFindMenuItems(false, 1);
439 
440             // Disables item if a threaded search is running
441             pMenuItem->Enable(!m_pThreadSearchView->IsSearchRunning());
442         }
443     }
444 }
445 
GetConfigurationPanel(wxWindow * parent)446 cbConfigurationPanel* ThreadSearch::GetConfigurationPanel(wxWindow* parent)
447 {
448     if ( !IsAttached() )
449         return NULL;
450 
451     return new ThreadSearchConfPanel(*this, parent);
452 }
453 
454 
Notify()455 void ThreadSearch::Notify()
456 {
457     if ( !IsAttached() )
458         return;
459 
460     m_pThreadSearchView->Update();
461     SaveConfig(m_pViewManager->IsViewShown(),
462                m_pThreadSearchView->GetSashPosition(),
463                m_pViewManager->GetManagerType(),
464                m_pThreadSearchView->GetSearchHistory(),
465                m_pThreadSearchView->GetSearchDirsHistory(),
466                m_pThreadSearchView->GetSearchMasksHistory());
467 }
468 
469 
LoadConfig(bool & showPanel,int & sashPosition,ThreadSearchViewManagerBase::eManagerTypes & mgrType,wxArrayString & searchPatterns,wxArrayString & searchDirs,wxArrayString & searchMasks)470 void ThreadSearch::LoadConfig(bool& showPanel, int& sashPosition,
471                               ThreadSearchViewManagerBase::eManagerTypes& mgrType,
472                               wxArrayString& searchPatterns, wxArrayString& searchDirs, wxArrayString& searchMasks)
473 {
474     if ( !IsAttached() )
475         return;
476 
477     ConfigManager* pCfg = Manager::Get()->GetConfigManager(_T("ThreadSearch"));
478 
479     m_FindData.SetMatchWord       (pCfg->ReadBool(wxT("/MatchWord"),             true));
480     m_FindData.SetStartWord       (pCfg->ReadBool(wxT("/StartWord"),             false));
481     m_FindData.SetMatchCase       (pCfg->ReadBool(wxT("/MatchCase"),             true));
482     m_FindData.SetRegEx           (pCfg->ReadBool(wxT("/RegEx"),                 false));
483     m_FindData.SetHiddenSearch    (pCfg->ReadBool(wxT("/HiddenSearch"),          true));
484     m_FindData.SetRecursiveSearch (pCfg->ReadBool(wxT("/RecursiveSearch"),       true));
485 
486     m_CtxMenuIntegration         = pCfg->ReadBool(wxT("/CtxMenuIntegration"),    true);
487     m_UseDefValsForThreadSearch  = pCfg->ReadBool(wxT("/UseDefaultValues"),      true);
488     m_ShowSearchControls         = pCfg->ReadBool(wxT("/ShowSearchControls"),    true);
489     m_ShowDirControls            = pCfg->ReadBool(wxT("/ShowDirControls"),       false);
490     m_ShowCodePreview            = pCfg->ReadBool(wxT("/ShowCodePreview"),       false);
491     m_DeletePreviousResults      = pCfg->ReadBool(wxT("/DeletePreviousResults"), false);
492     m_DisplayLogHeaders          = pCfg->ReadBool(wxT("/DisplayLogHeaders"),     true);
493     m_DrawLogLines               = pCfg->ReadBool(wxT("/DrawLogLines"),          false);
494     m_AutosizeLogColumns         = pCfg->ReadBool(wxT("/AutosizeLogColumns"),    true);
495 
496     showPanel                    = pCfg->ReadBool(wxT("/ShowPanel"),             true);
497 
498     m_FindData.SetScope           (pCfg->ReadInt (wxT("/Scope"),                 ScopeProjectFiles));
499 
500     m_FindData.SetSearchPath      (pCfg->Read    (wxT("/DirPath"),               wxEmptyString));
501     m_FindData.SetSearchMask      (pCfg->Read    (wxT("/Mask"),                  wxT("*.cpp;*.c;*.h")));
502 
503     sashPosition                 = pCfg->ReadInt(wxT("/SplitterPosn"),           0);
504     int splitterMode             = pCfg->ReadInt(wxT("/SplitterMode"),           wxSPLIT_VERTICAL);
505     m_SplitterMode               = wxSPLIT_VERTICAL;
506     if ( splitterMode == wxSPLIT_HORIZONTAL )
507     {
508         m_SplitterMode = wxSPLIT_HORIZONTAL;
509     }
510 
511     int managerType              = pCfg->ReadInt(wxT("/ViewManagerType"),        ThreadSearchViewManagerBase::TypeMessagesNotebook);
512     mgrType                      = ThreadSearchViewManagerBase::TypeMessagesNotebook;
513     if ( managerType == ThreadSearchViewManagerBase::TypeLayout )
514     {
515         mgrType = ThreadSearchViewManagerBase::TypeLayout;
516     }
517 
518     int loggerType               = pCfg->ReadInt(wxT("/LoggerType"),             ThreadSearchLoggerBase::TypeList);
519     m_LoggerType                 = ThreadSearchLoggerBase::TypeList;
520     if ( loggerType == ThreadSearchLoggerBase::TypeTree )
521     {
522         m_LoggerType = ThreadSearchLoggerBase::TypeTree;
523     }
524 
525     searchPatterns = pCfg->ReadArrayString(wxT("/SearchPatterns"));
526     searchDirs = pCfg->ReadArrayString(wxT("/SearchDirs"));
527     if (searchDirs.empty())
528         searchDirs.push_back(m_FindData.GetSearchPath());
529     searchMasks = pCfg->ReadArrayString(wxT("/SearchMasks"));
530     if (searchMasks.empty())
531         searchMasks.push_back(m_FindData.GetSearchMask());
532 }
533 
534 
SaveConfig(bool showPanel,int sashPosition,ThreadSearchViewManagerBase::eManagerTypes,const wxArrayString & searchPatterns,const wxArrayString & searchDirs,const wxArrayString & searchMasks)535 void ThreadSearch::SaveConfig(bool showPanel, int sashPosition,
536                               ThreadSearchViewManagerBase::eManagerTypes /*mgrType*/,
537                               const wxArrayString& searchPatterns, const wxArrayString& searchDirs,
538                               const wxArrayString& searchMasks)
539 {
540     ConfigManager* pCfg = Manager::Get()->GetConfigManager(_T("ThreadSearch"));
541 
542     pCfg->Write(wxT("/MatchWord"),             m_FindData.GetMatchWord());
543     pCfg->Write(wxT("/StartWord"),             m_FindData.GetStartWord());
544     pCfg->Write(wxT("/MatchCase"),             m_FindData.GetMatchCase());
545     pCfg->Write(wxT("/RegEx"),                 m_FindData.GetRegEx());
546     pCfg->Write(wxT("/HiddenSearch"),          m_FindData.GetHiddenSearch());
547     pCfg->Write(wxT("/RecursiveSearch"),       m_FindData.GetRecursiveSearch());
548 
549     pCfg->Write(wxT("/CtxMenuIntegration"),    m_CtxMenuIntegration);
550     pCfg->Write(wxT("/UseDefaultValues"),      m_UseDefValsForThreadSearch);
551     pCfg->Write(wxT("/ShowSearchControls"),    m_ShowSearchControls);
552     pCfg->Write(wxT("/ShowDirControls"),       m_ShowDirControls);
553     pCfg->Write(wxT("/ShowCodePreview"),       m_ShowCodePreview);
554     pCfg->Write(wxT("/DeletePreviousResults"), m_DeletePreviousResults);
555     pCfg->Write(wxT("/DisplayLogHeaders"),     m_DisplayLogHeaders);
556     pCfg->Write(wxT("/DrawLogLines"),          m_DrawLogLines);
557     pCfg->Write(wxT("/AutosizeLogColumns"),    m_AutosizeLogColumns);
558 
559     pCfg->Write(wxT("/ShowPanel"),             showPanel);
560 
561     pCfg->Write(wxT("/Scope"),                 m_FindData.GetScope());
562 
563     pCfg->Write(wxT("/DirPath"),               m_FindData.GetSearchPath());
564     pCfg->Write(wxT("/Mask"),                  m_FindData.GetSearchMask());
565 
566     pCfg->Write(wxT("/SplitterPosn"),          sashPosition);
567     pCfg->Write(wxT("/SplitterMode"),          (int)m_SplitterMode);
568     pCfg->Write(wxT("/ViewManagerType"),       m_pViewManager->GetManagerType());
569     pCfg->Write(wxT("/LoggerType"),            m_LoggerType);
570     pCfg->Write(wxT("/FileSorting"),           m_FileSorting);
571 
572     pCfg->Write(wxT("/SearchPatterns"),        searchPatterns);
573     pCfg->Write(wxT("/SearchDirs"),            searchDirs);
574     pCfg->Write(wxT("/SearchMasks"),           searchMasks);
575 }
576 
BuildToolBar(wxToolBar * toolBar)577 bool ThreadSearch::BuildToolBar(wxToolBar* toolBar)
578 {
579     if ( !IsAttached() || !toolBar )
580         return false;
581 
582     m_pToolbar = toolBar;
583     m_pThreadSearchView->SetToolBar(toolBar);
584 
585     const wxString &prefix = GetImagePrefix(true);
586 
587     m_pCboSearchExpr = new wxComboBox(toolBar, controlIDs.Get(ControlIDs::idCboSearchExpr),
588                                       wxEmptyString, wxDefaultPosition, wxSize(130, -1), 0, NULL, wxCB_DROPDOWN);
589     m_pCboSearchExpr->SetToolTip(_("Text to search"));
590 
591     const double scaleFactor = cbGetContentScaleFactor(*toolBar);
592 
593     wxBitmap bmpFind = cbLoadBitmapScaled(prefix + wxT("findf.png"), wxBITMAP_TYPE_PNG,
594                                           scaleFactor);
595     wxBitmap bmpFindDisabled = cbLoadBitmapScaled(prefix + wxT("findfdisabled.png"),
596                                                   wxBITMAP_TYPE_PNG, scaleFactor);
597     wxBitmap bmpOptions = cbLoadBitmapScaled(prefix + wxT("options.png"), wxBITMAP_TYPE_PNG,
598                                              scaleFactor);
599     wxBitmap bmpOptionsDisabled = cbLoadBitmapScaled(prefix + wxT("optionsdisabled.png"),
600                                                      wxBITMAP_TYPE_PNG, scaleFactor);
601 
602     toolBar->AddControl(m_pCboSearchExpr);
603     toolBar->AddTool(controlIDs.Get(ControlIDs::idBtnSearch), _(""),
604                      bmpFind, bmpFindDisabled,
605                      wxITEM_NORMAL, _("Run search"));
606     toolBar->AddTool(controlIDs.Get(ControlIDs::idBtnOptions), _(""),
607                      bmpOptions, bmpOptionsDisabled,
608                      wxITEM_NORMAL, _("Show options window"));
609     m_pThreadSearchView->UpdateOptionsButtonImage(m_FindData);
610 
611     m_pCboSearchExpr->Append(m_pThreadSearchView->GetSearchHistory());
612     if ( m_pCboSearchExpr->GetCount() > 0 )
613     {
614         m_pCboSearchExpr->SetSelection(0);
615     }
616 
617     toolBar->Realize();
618     toolBar->SetInitialSize();
619 
620     return true;
621 }
622 
623 
OnBtnOptionsClick(wxCommandEvent & event)624 void ThreadSearch::OnBtnOptionsClick(wxCommandEvent &event)
625 {
626     if ( !IsAttached() )
627         return;
628 
629     m_pThreadSearchView->OnBtnOptionsClick(event);
630 }
631 
632 
OnBtnSearchClick(wxCommandEvent & event)633 void ThreadSearch::OnBtnSearchClick(wxCommandEvent &event)
634 {
635     if ( !IsAttached() )
636         return;
637 
638     // Behaviour differs if a search is running.
639     if ( m_pThreadSearchView->IsSearchRunning() )
640     {
641         // In this case, user wants to stops search,
642         // we just transmit event
643         m_pThreadSearchView->OnBtnSearchClick(event);
644 
645     }
646     else
647     {
648         // User wants to search for a word.
649         // Forwarding the event would search for the view combo text whereas we want
650         // to look for the toolbar combo text.
651         const long id = controlIDs.Get(ControlIDs::idCboSearchExpr);
652         wxComboBox* pCboBox = static_cast<wxComboBox*>(m_pToolbar->FindControl(id));
653         wxASSERT(pCboBox != NULL);
654         RunThreadSearch(pCboBox->GetValue());
655     }
656 }
657 
RunThreadSearch(const wxString & text,bool isCtxSearch)658 void ThreadSearch::RunThreadSearch(const wxString& text, bool isCtxSearch/*=false*/)
659 {
660     if ( !IsAttached() )
661         return;
662 
663     ThreadSearchFindData findData = m_FindData;
664 
665     // User may prefer to set default options for contextual search
666     if ( (isCtxSearch == true) && (m_UseDefValsForThreadSearch == true) )
667     {
668         findData.SetMatchCase(true);
669         findData.SetMatchWord(true);
670         findData.SetStartWord(false);
671         findData.SetRegEx    (false);
672     }
673 
674     // m_SearchedWord was set in BuildModuleMenu
675     findData.SetFindText(text);
676 
677     // Displays m_pThreadSearchView in manager
678     m_pViewManager->ShowView(true);
679 
680     // Runs the search through a worker thread
681     m_pThreadSearchView->ThreadedSearch(findData);
682 }
683 
684 
OnCboSearchExprEnter(wxCommandEvent & event)685 void ThreadSearch::OnCboSearchExprEnter(wxCommandEvent &event)
686 {
687     if ( !IsAttached() )
688         return;
689 
690     // Event handler used when user clicks on enter after typing
691     // in combo box text control.
692     // Runs a multi threaded search with combo text
693     const long id = controlIDs.Get(ControlIDs::idCboSearchExpr);
694     wxComboBox* pCboBox = static_cast<wxComboBox*>(m_pToolbar->FindControl(id));
695     wxASSERT(pCboBox != NULL);
696     if ( event.GetEventType() == wxEVT_COMMAND_TEXT_ENTER )
697         RunThreadSearch(pCboBox->GetValue());
698 }
699 
700 
ShowToolBar(bool show)701 void ThreadSearch::ShowToolBar(bool show)
702 {
703     if ( !IsAttached() )
704         return;
705 
706     bool isShown = IsWindowReallyShown(m_pToolbar);
707 
708     if ( show != isShown )
709     {
710         CodeBlocksDockEvent evt(show ? cbEVT_SHOW_DOCK_WINDOW : cbEVT_HIDE_DOCK_WINDOW);
711         evt.pWindow = (wxWindow*)m_pToolbar;
712         evt.shown = show;
713         Manager::Get()->ProcessEvent(evt);
714     }
715 }
716 
717 
IsToolbarVisible()718 bool ThreadSearch::IsToolbarVisible()
719 {
720     if ( !IsAttached() )
721         return false;
722 
723     return IsWindowReallyShown(m_pToolbar);
724 }
725 
726 
GetCursorWord(wxString & sWord)727 bool ThreadSearch::GetCursorWord(wxString& sWord)
728 {
729     bool wordFound = false;
730     sWord = wxEmptyString;
731 
732     // Gets active editor
733     cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
734     if ( ed != NULL )
735     {
736         cbStyledTextCtrl* control = ed->GetControl();
737 
738         sWord = control->GetSelectedText();
739         if (sWord != wxEmptyString)
740         {
741             sWord.Trim(true);
742             sWord.Trim(false);
743 
744             wxString::size_type pos = sWord.find(wxT('\n'));
745             if (pos != wxString::npos)
746             {
747                 sWord.Remove(pos, sWord.length() - pos);
748                 sWord.Trim(true);
749                 sWord.Trim(false);
750             }
751 
752             return !sWord.IsEmpty();
753         }
754 
755         // Gets word under cursor
756         int pos = control->GetCurrentPos();
757         int ws  = control->WordStartPosition(pos, true);
758         int we  = control->WordEndPosition(pos, true);
759         const wxString word = control->GetTextRange(ws, we);
760         if (!word.IsEmpty()) // Avoid empty strings
761         {
762             sWord.Clear();
763 
764             // m_SearchedWord will be used if 'Find occurrences' ctx menu is clicked
765             sWord << word;
766             wordFound = true;
767         }
768     }
769 
770     return wordFound;
771 }
772 
773 
OnMnuEditCopy(wxCommandEvent & event)774 void ThreadSearch::OnMnuEditCopy(wxCommandEvent& event)
775 {
776        if ( !IsAttached() )
777     {
778         event.Skip();
779         return;
780     }
781 
782     wxWindow* pFocused = wxWindow::FindFocus();
783 
784     // if the following window have the focus, own the copy.
785     if ( pFocused == m_pCboSearchExpr )
786     {
787         if ( m_pCboSearchExpr->CanCopy() )
788             m_pCboSearchExpr->Copy();
789         LOGIT( _T("OnMnuEditcopy for m_pCboSearchExpr") );
790     }
791     else if ( pFocused == m_pThreadSearchView->m_pCboSearchExpr )
792     {
793         if ( m_pThreadSearchView->m_pCboSearchExpr->CanCopy() )
794             m_pThreadSearchView->m_pCboSearchExpr->Copy();
795         LOGIT( _T("OnMnuEditcopy for m_pThreadSearchView->m_pCboSearchExpr") );
796     }
797     else if ( pFocused == static_cast<wxWindow*>(m_pThreadSearchView->m_pSearchPreview) )
798     {
799         bool hasSel = m_pThreadSearchView->m_pSearchPreview->GetSelectionStart() != m_pThreadSearchView->m_pSearchPreview->GetSelectionEnd();
800         if (hasSel)
801             m_pThreadSearchView->m_pSearchPreview->Copy();
802         LOGIT( _T("OnMnuEditcopy for m_pSearchPreview") );
803     }
804     else
805     {
806         event.Skip();
807     }
808 
809     // If you Skip(), CB main.cpp will wrongly paste your text into the current editor
810     // because CB main.cpp thinks it owns the clipboard.
811     //- event.Skip();
812     return; //own the event
813 }
814 
815 
OnMnuEditCopyUpdateUI(wxUpdateUIEvent & event)816 void ThreadSearch::OnMnuEditCopyUpdateUI(wxUpdateUIEvent& event)
817 {
818     if ( !IsAttached() )
819     {
820         event.Skip(); return;
821     }
822 
823     wxWindow* pFocused = wxWindow::FindFocus();
824     if (not pFocused) return;
825 
826     wxMenuBar* mbar = Manager::Get()->GetAppFrame()->GetMenuBar();
827     if (not mbar) return;
828 
829     bool hasSel = false;
830     // if the following window have the focus, own the copy.
831     if ( pFocused == m_pCboSearchExpr )
832     {
833         //event.Enable(m_pCboSearchExpr->CanCopy());
834         hasSel =  m_pCboSearchExpr->CanCopy() ;
835         //LOGIT( _T("OnMnuEditCopyUpdateUI m_pCboSearchExpr") );
836     }
837     else if ( pFocused == m_pThreadSearchView->m_pCboSearchExpr )
838     {
839         //event.Enable(m_pThreadSearchView->m_pCboSearchExpr->CanCopy());
840         hasSel = m_pThreadSearchView->m_pCboSearchExpr->CanCopy();
841         //LOGIT( _T("OnMnuEditCopyUpdateUI m_pThreadSearchView->m_pCboSearchExpr") );
842     }
843     else if ( pFocused == static_cast<wxWindow*>(m_pThreadSearchView->m_pSearchPreview) )
844     {
845         hasSel = m_pThreadSearchView->m_pSearchPreview->GetSelectionStart() != m_pThreadSearchView->m_pSearchPreview->GetSelectionEnd();
846         //LOGIT( _T("OnMnuEditCopyUpdateUI m_pSearchPreview") );
847     }
848     if ( hasSel )
849     {
850         mbar->Enable(idMenuEditCopy, hasSel);
851         wxToolBar* pMainToolBar = (wxToolBar*) ::wxFindWindowByName(wxT("toolbar"), NULL);
852         if (pMainToolBar) pMainToolBar->EnableTool(idMenuEditCopy, hasSel);
853         return;
854     }
855 
856     event.Skip();
857     return;
858 
859 }
860 // ----------------------------------------------------------------------------
OnMnuEditPaste(wxCommandEvent & event)861 void ThreadSearch::OnMnuEditPaste(wxCommandEvent& event)
862 // ----------------------------------------------------------------------------
863 {
864     // Process clipboard data only if we have the focus
865 
866     // ----------------------------------------------------------------
867     // NB:  A bug in CB main.cpp causes a ctrl-v to always paste into the
868     //      current editor. Here, we'll make checks to see if the paste
869     //      is for our search combo boxes and paste the data there.
870     //      If the focused window is one of ours that shouldn't get pasted
871     //      data, we'll simply ignore it.
872     //      If the window isn't one of ours, we'll event.Skip();
873     // ----------------------------------------------------------------
874 
875        if ( !IsAttached() )
876         { event.Skip(); return; }
877 
878     if (not m_IsAttached) {event.Skip(); return;}
879 
880     wxWindow* pFocused = wxWindow::FindFocus();
881     if (not pFocused) { event.Skip(); return; }
882 
883     wxString focusedStr = pFocused->GetName();
884 //    DBGLOG(wxT("OnMnuEditPaste:Focused[%p][%s]"), pFocused, focusedStr.c_str());
885 
886     // don't allow paste when the following windows have the focus
887     if ( (pFocused == m_pThreadSearchView->m_pSearchPreview) ||
888          (pFocused == (wxWindow*)m_pThreadSearchView->m_pLogger) )
889     {
890         return;
891     }
892 
893     // if the following window have the focus, own the paste.
894     if ( (pFocused != m_pCboSearchExpr)
895         && (pFocused != m_pThreadSearchView->m_pCboSearchExpr) )
896         { event.Skip(); return;}
897 
898     if (pFocused == m_pCboSearchExpr)
899         m_pCboSearchExpr->Paste();
900     if (pFocused == m_pThreadSearchView->m_pCboSearchExpr)
901         m_pThreadSearchView->m_pCboSearchExpr->Paste();
902 
903     // If you Skip(), CB main.cpp will wrongly paste your text into the current editor
904     // because CB main.cpp thinks it owns the clipboard.
905     //- event.Skip();
906     return; //own the event
907 }//OnMnuEditPaste
908 
909 
SetManagerType(ThreadSearchViewManagerBase::eManagerTypes mgrType)910 void ThreadSearch::SetManagerType(ThreadSearchViewManagerBase::eManagerTypes mgrType)
911 {
912     // Is type different from current one ?
913     if ( mgrType != m_pViewManager->GetManagerType() )
914     {
915         // Get show state and destroy current view manager.
916         bool show(true);
917         if ( m_pViewManager != NULL )
918         {
919             show = m_pViewManager->IsViewShown();
920             m_pViewManager->RemoveViewFromManager();
921             delete m_pViewManager;
922         }
923 
924         // Create and show new view manager.
925         m_pViewManager = ThreadSearchViewManagerBase::BuildThreadSearchViewManagerBase(m_pThreadSearchView, true, mgrType);
926         m_pViewManager->ShowView(show);
927     }
928 }
929 
930 
931 
932 
933