Character search moved to separate thread for smoother experience

This commit is contained in:
Simon Rozman 2016-05-13 12:11:38 +02:00
parent 710937f8df
commit 155fb03c5a
7 changed files with 182 additions and 111 deletions

View File

@ -2432,7 +2432,7 @@
<property name="search_button">1</property> <property name="search_button">1</property>
<property name="show">1</property> <property name="show">1</property>
<property name="size"></property> <property name="size"></property>
<property name="style">wxTE_PROCESS_ENTER</property> <property name="style"></property>
<property name="subclass"></property> <property name="subclass"></property>
<property name="toolbar_pane">0</property> <property name="toolbar_pane">0</property>
<property name="tooltip"></property> <property name="tooltip"></property>
@ -2469,7 +2469,7 @@
<event name="OnSetFocus"></event> <event name="OnSetFocus"></event>
<event name="OnSize"></event> <event name="OnSize"></event>
<event name="OnText">OnSearchText</event> <event name="OnText">OnSearchText</event>
<event name="OnTextEnter">OnSearchEnter</event> <event name="OnTextEnter"></event>
<event name="OnUpdateUI"></event> <event name="OnUpdateUI"></event>
</object> </object>
</object> </object>
@ -3506,15 +3506,6 @@
</object> </object>
</object> </object>
</object> </object>
<object class="wxTimer" expanded="0">
<property name="enabled">0</property>
<property name="id">wxID_TIMER_SEARCH</property>
<property name="name">m_timerSearch</property>
<property name="oneshot">1</property>
<property name="period">1000</property>
<property name="permission">protected</property>
<event name="OnTimer">OnSearchTimer</event>
</object>
</object> </object>
</object> </object>
</wxFormBuilder_Project> </wxFormBuilder_Project>

View File

@ -20,32 +20,22 @@
#include "stdafx.h" #include "stdafx.h"
static int __cdecl compare_hits(const void *a, const void *b)
{
const std::pair<unsigned long, wchar_t> *_a = (const std::pair<unsigned long, wchar_t>*)a;
const std::pair<unsigned long, wchar_t> *_b = (const std::pair<unsigned long, wchar_t>*)b;
if (_a->first > _b->first) return -1;
else if (_a->first < _b->first) return 1;
if (_a->second < _b->second) return -1;
else if (_a->second > _b->second) return 1;
return 0;
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// wxZRColaCharSelect // wxZRColaCharSelect
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
wxDEFINE_EVENT(wxEVT_SEARCH_COMPLETE, wxThreadEvent);
wxZRColaCharSelect::wxZRColaCharSelect(wxWindow* parent) : wxZRColaCharSelect::wxZRColaCharSelect(wxWindow* parent) :
m_searchChanged(false), m_searchChanged(false),
m_unicodeChanged(false), m_unicodeChanged(false),
m_char(0), m_char(0),
m_searchThread(NULL),
wxZRColaCharSelectBase(parent) wxZRColaCharSelectBase(parent)
{ {
Connect(wxID_ANY, wxEVT_SEARCH_COMPLETE, wxThreadEventHandler(wxZRColaCharSelect::OnSearchComplete), NULL, this);
m_unicode->SetValidator(wxHexValidator<wchar_t>(&m_char)); m_unicode->SetValidator(wxHexValidator<wchar_t>(&m_char));
// Fill categories. // Fill categories.
@ -61,6 +51,15 @@ wxZRColaCharSelect::wxZRColaCharSelect(wxWindow* parent) :
} }
wxZRColaCharSelect::~wxZRColaCharSelect()
{
if (m_searchThread)
m_searchThread->Delete();
Disconnect(wxID_ANY, wxEVT_SEARCH_COMPLETE, wxThreadEventHandler(wxZRColaCharSelect::OnSearchComplete), NULL, this);
}
void wxZRColaCharSelect::OnIdle(wxIdleEvent& event) void wxZRColaCharSelect::OnIdle(wxIdleEvent& event)
{ {
event.Skip(); event.Skip();
@ -90,7 +89,31 @@ void wxZRColaCharSelect::OnIdle(wxIdleEvent& event)
m_unicodeChanged = false; m_unicodeChanged = false;
} else if (m_searchChanged) { } else if (m_searchChanged) {
m_timerSearch.Start(1000, true); if (m_searchThread)
m_searchThread->Delete();
wxString val(m_search->GetValue());
if (!val.IsEmpty()) {
ZRColaApp *app = (ZRColaApp*)wxTheApp;
m_searchThread = new SearchThread(this);
m_searchThread->m_search.assign(val.c_str(), val.Length());
// Select categories.
for (size_t i = 0, n = app->m_cc_db.idxRnk.size(); i < n; i++) {
const ZRCola::chrcat_db::chrcat &cc = app->m_cc_db.idxRnk[i];
if (m_categories->IsChecked(i))
m_searchThread->m_cats.insert(cc.id);
}
if (m_searchThread->Run() != wxTHREAD_NO_ERROR) {
wxFAIL_MSG("Can't create the thread!");
delete m_searchThread;
m_searchThread = NULL;
}
} else
ResetResults();
m_searchChanged = false; m_searchChanged = false;
} }
@ -101,75 +124,35 @@ void wxZRColaCharSelect::OnSearchText(wxCommandEvent& event)
{ {
event.Skip(); event.Skip();
m_timerSearch.Stop();
m_searchChanged = true; m_searchChanged = true;
} }
void wxZRColaCharSelect::OnSearchEnter(wxCommandEvent& event)
{
event.Skip();
m_timerSearch.Stop();
wxTimerEvent e(m_timerSearch);
GetEventHandler()->ProcessEvent(e);
m_searchChanged = false;
}
void wxZRColaCharSelect::OnSearchTimer(wxTimerEvent& event)
{
wxString val(m_search->GetValue());
if (!val.IsEmpty()) {
ZRColaApp *app = (ZRColaApp*)wxTheApp;
std::map<wchar_t, unsigned long> hits;
std::set<ZRCola::chrcatid_t> cats;
// Select categories.
for (size_t i = 0, n = app->m_cc_db.idxRnk.size(); i < n; i++) {
const ZRCola::chrcat_db::chrcat &cc = app->m_cc_db.idxRnk[i];
if (m_categories->IsChecked(i))
cats.insert(cc.id);
}
{
// Search by indexes and merge results.
std::map<wchar_t, unsigned long> hits_sub;
app->m_chr_db.Search(val.c_str(), cats, hits, hits_sub);
for (std::map<wchar_t, unsigned long>::const_iterator i = hits_sub.cbegin(), i_end = hits_sub.cend(); i != i_end; ++i) {
std::map<wchar_t, unsigned long>::iterator idx = hits.find(i->first);
if (idx == hits.end())
hits.insert(std::make_pair(i->first, i->second / 4));
else
idx->second += i->second / 4;
}
}
// Now sort the characters by rank.
std::vector< std::pair<unsigned long, wchar_t> > hits2;
hits2.reserve(hits.size());
for (std::map<wchar_t, unsigned long>::const_iterator i = hits.cbegin(), i_end = hits.cend(); i != i_end; ++i)
hits2.push_back(std::make_pair(i->second, i->first));
std::qsort(hits2.data(), hits2.size(), sizeof(std::pair<unsigned long, wchar_t>), compare_hits);
// Display results.
wxString chars;
chars.reserve(hits2.size());
for (std::vector< std::pair<unsigned long, wchar_t> >::const_iterator i = hits2.cbegin(), i_end = hits2.cend(); i != i_end; ++i)
chars += i->second;
m_gridResults->SetCharacters(chars);
} else
ResetResults();
m_gridResults->Scroll(0, 0);
}
void wxZRColaCharSelect::OnCategoriesToggle(wxCommandEvent& event) void wxZRColaCharSelect::OnCategoriesToggle(wxCommandEvent& event)
{ {
m_timerSearch.Stop(); event.Skip();
m_timerSearch.Start(500, true);
m_searchChanged = true;
}
void wxZRColaCharSelect::OnSearchComplete(wxThreadEvent& event)
{
event.Skip();
if (m_searchThread) {
// Display results.
wxString chars;
chars.reserve(m_searchThread->m_hits.size());
for (std::vector< std::pair<unsigned long, wchar_t> >::const_iterator i = m_searchThread->m_hits.cbegin(), i_end = m_searchThread->m_hits.cend(); i != i_end; ++i)
chars += i->second;
m_gridResults->SetCharacters(chars);
m_searchThread->Delete();
m_searchThread = NULL;
m_gridResults->Scroll(0, 0);
}
} }
@ -305,6 +288,74 @@ void wxZRColaCharSelect::ResetResults()
} }
wxZRColaCharSelect::SearchThread::SearchThread(wxZRColaCharSelect *parent) :
m_parent(parent),
wxThread(wxTHREAD_JOINABLE)
{
//// This is a worker thread. Set priority between minimal and normal.
//SetPriority((wxPRIORITY_MIN + wxPRIORITY_DEFAULT) / 2);
}
wxThread::ExitCode wxZRColaCharSelect::SearchThread::Entry()
{
ZRColaApp *app = (ZRColaApp*)wxTheApp;
std::map<wchar_t, unsigned long> hits;
if (TestDestroy()) return (wxThread::ExitCode)1;
{
// Search by indexes and merge results.
std::map<wchar_t, unsigned long> hits_sub;
if (!app->m_chr_db.Search(m_search.c_str(), m_cats, hits, hits_sub, TestDestroyS, this)) return (wxThread::ExitCode)1;
for (std::map<wchar_t, unsigned long>::const_iterator i = hits_sub.cbegin(), i_end = hits_sub.cend(); i != i_end; ++i) {
if (TestDestroy()) return (wxThread::ExitCode)1;
std::map<wchar_t, unsigned long>::iterator idx = hits.find(i->first);
if (idx == hits.end())
hits.insert(std::make_pair(i->first, i->second / 4));
else
idx->second += i->second / 4;
}
}
// Now sort the characters by rank.
m_hits.reserve(hits.size());
for (std::map<wchar_t, unsigned long>::const_iterator i = hits.cbegin(), i_end = hits.cend(); i != i_end; ++i) {
if (TestDestroy()) return (wxThread::ExitCode)1;
m_hits.push_back(std::make_pair(i->second, i->first));
}
std::qsort(m_hits.data(), m_hits.size(), sizeof(std::pair<unsigned long, wchar_t>), CompareHits);
// Signal the event handler that this thread is going to be destroyed.
// NOTE: here we assume that using the m_parent pointer is safe,
// (in this case this is assured by the wxZRColaCharSelect destructor)
wxQueueEvent(m_parent, new wxThreadEvent(wxEVT_SEARCH_COMPLETE));
return 0;
}
int __cdecl wxZRColaCharSelect::SearchThread::CompareHits(const void *a, const void *b)
{
const std::pair<unsigned long, wchar_t> *_a = (const std::pair<unsigned long, wchar_t>*)a;
const std::pair<unsigned long, wchar_t> *_b = (const std::pair<unsigned long, wchar_t>*)b;
if (_a->first > _b->first) return -1;
else if (_a->first < _b->first) return 1;
if (_a->second < _b->second) return -1;
else if (_a->second > _b->second) return 1;
return 0;
}
bool __cdecl wxZRColaCharSelect::SearchThread::TestDestroyS(void *cookie)
{
return static_cast<wxZRColaCharSelect::SearchThread*>(cookie)->TestDestroy();
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// wxPersistentZRColaCharSelect // wxPersistentZRColaCharSelect
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

View File

@ -30,9 +30,14 @@ class wxZRColaCharSelect;
#include <zrcola/character.h> #include <zrcola/character.h>
#include <wxex/valhex.h> #include <wxex/valhex.h>
#include <wxex/persist/dialog.h> #include <wxex/persist/dialog.h>
#include <wx/event.h>
#include <wx/thread.h>
#include <map> #include <map>
wxDECLARE_EVENT(wxEVT_SEARCH_COMPLETE, wxThreadEvent);
/// ///
/// ZRCola character select dialog /// ZRCola character select dialog
/// ///
@ -40,15 +45,16 @@ class wxZRColaCharSelect : public wxZRColaCharSelectBase
{ {
public: public:
wxZRColaCharSelect(wxWindow* parent); wxZRColaCharSelect(wxWindow* parent);
virtual ~wxZRColaCharSelect();
friend class wxPersistentZRColaCharSelect; // Allow saving/restoring window state. friend class wxPersistentZRColaCharSelect; // Allow saving/restoring window state.
friend class SearchThread; // For search thread back-notifications
protected: protected:
virtual void OnIdle(wxIdleEvent& event); virtual void OnIdle(wxIdleEvent& event);
virtual void OnSearchText(wxCommandEvent& event); virtual void OnSearchText(wxCommandEvent& event);
virtual void OnSearchEnter(wxCommandEvent& event);
virtual void OnSearchTimer(wxTimerEvent& event);
virtual void OnCategoriesToggle(wxCommandEvent& event); virtual void OnCategoriesToggle(wxCommandEvent& event);
void OnSearchComplete(wxThreadEvent& event);
virtual void OnResultSelectCell(wxGridEvent& event); virtual void OnResultSelectCell(wxGridEvent& event);
virtual void OnResultCellDClick(wxGridEvent& event); virtual void OnResultCellDClick(wxGridEvent& event);
virtual void OnResultsKeyDown(wxKeyEvent& event); virtual void OnResultsKeyDown(wxKeyEvent& event);
@ -65,12 +71,36 @@ public:
wchar_t m_char; ///< Currently selected character (0 when none) wchar_t m_char; ///< Currently selected character (0 when none)
protected: protected:
bool m_searchChanged; ///< Did Search field change? bool m_searchChanged; ///< Did Search field or category selection change?
std::map<ZRCola::chrcatid_t, int> m_ccOrder; ///< Character category order std::map<ZRCola::chrcatid_t, int> m_ccOrder; ///< Character category order
bool m_unicodeChanged; ///< Did Unicode field change? bool m_unicodeChanged; ///< Did Unicode field change?
///
/// Search worker thread
///
class SearchThread : public wxThread
{
public:
SearchThread(wxZRColaCharSelect *parent);
protected:
virtual ExitCode Entry();
static int __cdecl CompareHits(const void *a, const void *b);
static bool __cdecl TestDestroyS(void *cookie);
public:
std::wstring m_search; ///< Search phrase
std::set<ZRCola::chrcatid_t> m_cats; ///< Search categories
std::vector< std::pair<unsigned long, wchar_t> > m_hits; ///< Search results
protected:
wxZRColaCharSelect *m_parent; ///< Thread owner
} *m_searchThread; ///< Search thread
}; };
/// ///
/// Supports saving/restoring wxZRColaCharSelect state /// Supports saving/restoring wxZRColaCharSelect state
/// ///

View File

@ -416,7 +416,7 @@ wxZRColaCharSelectBase::wxZRColaCharSelectBase( wxWindow* parent, wxWindowID id,
wxStaticBoxSizer* sbSizerBrowse; wxStaticBoxSizer* sbSizerBrowse;
sbSizerBrowse = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("&Browse") ), wxVERTICAL ); sbSizerBrowse = new wxStaticBoxSizer( new wxStaticBox( this, wxID_ANY, _("&Browse") ), wxVERTICAL );
m_search = new wxSearchCtrl( sbSizerBrowse->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER ); m_search = new wxSearchCtrl( sbSizerBrowse->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
#ifndef __WXMAC__ #ifndef __WXMAC__
m_search->ShowSearchButton( true ); m_search->ShowSearchButton( true );
#endif #endif
@ -610,12 +610,10 @@ wxZRColaCharSelectBase::wxZRColaCharSelectBase( wxWindow* parent, wxWindowID id,
this->SetSizer( bSizerContent ); this->SetSizer( bSizerContent );
this->Layout(); this->Layout();
bSizerContent->Fit( this ); bSizerContent->Fit( this );
m_timerSearch.SetOwner( this, wxID_TIMER_SEARCH );
// Connect Events // Connect Events
this->Connect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaCharSelectBase::OnIdle ) ); this->Connect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaCharSelectBase::OnIdle ) );
m_search->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchText ), NULL, this ); m_search->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchText ), NULL, this );
m_search->Connect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchEnter ), NULL, this );
m_categories->Connect( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler( wxZRColaCharSelectBase::OnCategoriesToggle ), NULL, this ); m_categories->Connect( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler( wxZRColaCharSelectBase::OnCategoriesToggle ), NULL, this );
m_gridResults->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( wxZRColaCharSelectBase::OnResultCellDClick ), NULL, this ); m_gridResults->Connect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( wxZRColaCharSelectBase::OnResultCellDClick ), NULL, this );
m_gridResults->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnResultSelectCell ), NULL, this ); m_gridResults->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnResultSelectCell ), NULL, this );
@ -626,7 +624,6 @@ wxZRColaCharSelectBase::wxZRColaCharSelectBase( wxWindow* parent, wxWindowID id,
m_unicode->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnUnicodeText ), NULL, this ); m_unicode->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnUnicodeText ), NULL, this );
m_gridRelated->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnRelatedSelectCell ), NULL, this ); m_gridRelated->Connect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnRelatedSelectCell ), NULL, this );
m_sdbSizerButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxZRColaCharSelectBase::OnOKButtonClick ), NULL, this ); m_sdbSizerButtonsOK->Connect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxZRColaCharSelectBase::OnOKButtonClick ), NULL, this );
this->Connect( wxID_TIMER_SEARCH, wxEVT_TIMER, wxTimerEventHandler( wxZRColaCharSelectBase::OnSearchTimer ) );
} }
wxZRColaCharSelectBase::~wxZRColaCharSelectBase() wxZRColaCharSelectBase::~wxZRColaCharSelectBase()
@ -634,7 +631,6 @@ wxZRColaCharSelectBase::~wxZRColaCharSelectBase()
// Disconnect Events // Disconnect Events
this->Disconnect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaCharSelectBase::OnIdle ) ); this->Disconnect( wxEVT_IDLE, wxIdleEventHandler( wxZRColaCharSelectBase::OnIdle ) );
m_search->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchText ), NULL, this ); m_search->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchText ), NULL, this );
m_search->Disconnect( wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler( wxZRColaCharSelectBase::OnSearchEnter ), NULL, this );
m_categories->Disconnect( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler( wxZRColaCharSelectBase::OnCategoriesToggle ), NULL, this ); m_categories->Disconnect( wxEVT_COMMAND_CHECKLISTBOX_TOGGLED, wxCommandEventHandler( wxZRColaCharSelectBase::OnCategoriesToggle ), NULL, this );
m_gridResults->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( wxZRColaCharSelectBase::OnResultCellDClick ), NULL, this ); m_gridResults->Disconnect( wxEVT_GRID_CELL_LEFT_DCLICK, wxGridEventHandler( wxZRColaCharSelectBase::OnResultCellDClick ), NULL, this );
m_gridResults->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnResultSelectCell ), NULL, this ); m_gridResults->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnResultSelectCell ), NULL, this );
@ -645,6 +641,5 @@ wxZRColaCharSelectBase::~wxZRColaCharSelectBase()
m_unicode->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnUnicodeText ), NULL, this ); m_unicode->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( wxZRColaCharSelectBase::OnUnicodeText ), NULL, this );
m_gridRelated->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnRelatedSelectCell ), NULL, this ); m_gridRelated->Disconnect( wxEVT_GRID_SELECT_CELL, wxGridEventHandler( wxZRColaCharSelectBase::OnRelatedSelectCell ), NULL, this );
m_sdbSizerButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxZRColaCharSelectBase::OnOKButtonClick ), NULL, this ); m_sdbSizerButtonsOK->Disconnect( wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler( wxZRColaCharSelectBase::OnOKButtonClick ), NULL, this );
this->Disconnect( wxID_TIMER_SEARCH, wxEVT_TIMER, wxTimerEventHandler( wxZRColaCharSelectBase::OnSearchTimer ) );
} }

View File

@ -186,11 +186,6 @@ class wxZRColaCharSelectBase : public wxDialog
private: private:
protected: protected:
enum
{
wxID_TIMER_SEARCH = 1000
};
wxSearchCtrl* m_search; wxSearchCtrl* m_search;
wxCheckListBox* m_categories; wxCheckListBox* m_categories;
wxZRColaCharGrid* m_gridResults; wxZRColaCharGrid* m_gridResults;
@ -203,12 +198,10 @@ class wxZRColaCharSelectBase : public wxDialog
wxStdDialogButtonSizer* m_sdbSizerButtons; wxStdDialogButtonSizer* m_sdbSizerButtons;
wxButton* m_sdbSizerButtonsOK; wxButton* m_sdbSizerButtonsOK;
wxButton* m_sdbSizerButtonsCancel; wxButton* m_sdbSizerButtonsCancel;
wxTimer m_timerSearch;
// Virtual event handlers, overide them in your derived class // Virtual event handlers, overide them in your derived class
virtual void OnIdle( wxIdleEvent& event ) { event.Skip(); } virtual void OnIdle( wxIdleEvent& event ) { event.Skip(); }
virtual void OnSearchText( wxCommandEvent& event ) { event.Skip(); } virtual void OnSearchText( wxCommandEvent& event ) { event.Skip(); }
virtual void OnSearchEnter( wxCommandEvent& event ) { event.Skip(); }
virtual void OnCategoriesToggle( wxCommandEvent& event ) { event.Skip(); } virtual void OnCategoriesToggle( wxCommandEvent& event ) { event.Skip(); }
virtual void OnResultCellDClick( wxGridEvent& event ) { event.Skip(); } virtual void OnResultCellDClick( wxGridEvent& event ) { event.Skip(); }
virtual void OnResultSelectCell( wxGridEvent& event ) { event.Skip(); } virtual void OnResultSelectCell( wxGridEvent& event ) { event.Skip(); }
@ -219,7 +212,6 @@ class wxZRColaCharSelectBase : public wxDialog
virtual void OnUnicodeText( wxCommandEvent& event ) { event.Skip(); } virtual void OnUnicodeText( wxCommandEvent& event ) { event.Skip(); }
virtual void OnRelatedSelectCell( wxGridEvent& event ) { event.Skip(); } virtual void OnRelatedSelectCell( wxGridEvent& event ) { event.Skip(); }
virtual void OnOKButtonClick( wxCommandEvent& event ) { event.Skip(); } virtual void OnOKButtonClick( wxCommandEvent& event ) { event.Skip(); }
virtual void OnSearchTimer( wxTimerEvent& event ) { event.Skip(); }
public: public:

View File

@ -234,8 +234,10 @@ namespace ZRCola {
/// \param[in ] cats Set of categories, character must be a part of /// \param[in ] cats Set of categories, character must be a part of
/// \param[inout] hits (character, count) map to append full-word hits to /// \param[inout] hits (character, count) map to append full-word hits to
/// \param[inout] hits_sub (character, count) map to append partial-word hits to /// \param[inout] hits_sub (character, count) map to append partial-word hits to
/// \param[in] fn_abort Pointer to function to periodically test for search cancellation
/// \param[in] cookie Cookie for \p fn_abort call
/// ///
void Search(_In_z_ const wchar_t *str, _In_ const std::set<chrcatid_t> &cats, _Inout_ std::map<wchar_t, unsigned long> &hits, _Inout_ std::map<wchar_t, unsigned long> &hits_sub) const; bool Search(_In_z_ const wchar_t *str, _In_ const std::set<chrcatid_t> &cats, _Inout_ std::map<wchar_t, unsigned long> &hits, _Inout_ std::map<wchar_t, unsigned long> &hits_sub, _In_opt_ bool (__cdecl *fn_abort)(void *cookie) = NULL, _In_opt_ void *cookie = NULL) const;
/// ///
/// Get character category /// Get character category

View File

@ -20,15 +20,17 @@
#include "stdafx.h" #include "stdafx.h"
void ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set<chrcatid_t> &cats, _Inout_ std::map<wchar_t, unsigned long> &hits, _Inout_ std::map<wchar_t, unsigned long> &hits_sub) const bool ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set<chrcatid_t> &cats, _Inout_ std::map<wchar_t, unsigned long> &hits, _Inout_ std::map<wchar_t, unsigned long> &hits_sub, _In_opt_ bool (__cdecl *fn_abort)(void *cookie), _In_opt_ void *cookie) const
{ {
assert(str); assert(str);
while (*str) { while (*str) {
if (fn_abort && fn_abort(cookie)) return false;
// Skip white space. // Skip white space.
for (;;) { for (;;) {
if (*str == 0) if (*str == 0)
return; return true;
else if (!iswspace(*str)) else if (!iswspace(*str))
break; break;
else else
@ -59,15 +61,20 @@ void ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set
} }
if (!term.empty()) { if (!term.empty()) {
if (fn_abort && fn_abort(cookie)) return false;
// Find the term. // Find the term.
std::transform(term.begin(), term.end(), term.begin(), std::towlower); std::transform(term.begin(), term.end(), term.begin(), std::towlower);
if (fn_abort && fn_abort(cookie)) return false;
const wchar_t *data; const wchar_t *data;
size_t len; size_t len;
if (idxDsc.find(term.c_str(), term.size(), &data, &len)) { if (idxDsc.find(term.c_str(), term.size(), &data, &len)) {
// The term was found. // The term was found.
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
if (fn_abort && fn_abort(cookie)) return false;
wchar_t c = data[i]; wchar_t c = data[i];
if (cats.find(GetCharCat(c)) != cats.end()) { if (cats.find(GetCharCat(c)) != cats.end()) {
std::map<wchar_t, unsigned long>::iterator idx = hits.find(c); std::map<wchar_t, unsigned long>::iterator idx = hits.find(c);
@ -85,6 +92,7 @@ void ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set
if (idxDscSub.find(term.c_str(), term.size(), &data, &len)) { if (idxDscSub.find(term.c_str(), term.size(), &data, &len)) {
// The term was found in the sub-term index. // The term was found in the sub-term index.
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
if (fn_abort && fn_abort(cookie)) return false;
wchar_t c = data[i]; wchar_t c = data[i];
if (cats.find(GetCharCat(c)) != cats.end()) { if (cats.find(GetCharCat(c)) != cats.end()) {
std::map<wchar_t, unsigned long>::iterator idx = hits_sub.find(c); std::map<wchar_t, unsigned long>::iterator idx = hits_sub.find(c);
@ -100,4 +108,6 @@ void ZRCola::character_db::Search(_In_z_ const wchar_t *str, _In_ const std::set
} }
} }
} }
return true;
} }