diff --git a/src/actions.cpp b/src/actions.cpp index 342d17d5..7e7e5a29 100644 --- a/src/actions.cpp +++ b/src/actions.cpp @@ -1879,15 +1879,16 @@ void ApplyFilter::Run() using Global::wFooter; Filterable *f = dynamic_cast(myScreen); + std::string filter = f->currentFilter(); LockStatusbar(); Statusbar() << NC::fmtBold << "Apply filter: " << NC::fmtBoldEnd; - wFooter->setGetStringHelper(std::bind(StatusbarApplyFilterImmediately, f, _1)); - wFooter->getString(f->currentFilter()); + wFooter->setGetStringHelper(StatusbarApplyFilterImmediately(f, ToWString(filter))); + wFooter->getString(filter); wFooter->setGetStringHelper(StatusbargetStringHelper); UnlockStatusbar(); - std::string filter = f->currentFilter(); + filter = f->currentFilter(); if (filter.empty()) { myPlaylist->Items->clearFilterResults(); diff --git a/src/status.cpp b/src/status.cpp index a88343e9..1274a61e 100644 --- a/src/status.cpp +++ b/src/status.cpp @@ -78,16 +78,23 @@ void StatusbargetStringHelper(const std::wstring &) TraceMpdStatus(); } -void StatusbarApplyFilterImmediately(Filterable *f, const std::wstring &ws) +void StatusbarApplyFilterImmediately::operator()(const std::wstring &ws) { - static std::wstring cmp; - if (cmp != ws) + // if input queue is not empty, we don't want to update filter since next + // character will be taken from queue immediately, trigering this function + // again and thus making it inefficient, so let's apply filter only if + // "real" user input arrived. however, we want to apply filter if ENTER + // is next in queue, so its effects will be seen. + if (wFooter->inputQueue().empty() || wFooter->inputQueue().front() == KEY_ENTER) { - cmp = ws; - f->applyFilter(ToString(cmp)); - myScreen->RefreshWindow(); + if (m_ws != ws) + { + m_ws = ws; + m_f->applyFilter(ToString(m_ws)); + myScreen->RefreshWindow(); + } + TraceMpdStatus(); } - TraceMpdStatus(); } void LockProgressbar() diff --git a/src/status.h b/src/status.h index 099f73c6..428b74fa 100644 --- a/src/status.h +++ b/src/status.h @@ -46,7 +46,18 @@ void ShowMessage(const char *, ...) GNUC_PRINTF(1, 2); void StatusbarMPDCallback(); void StatusbargetStringHelper(const std::wstring &); -void StatusbarApplyFilterImmediately(Filterable *f, const std::wstring &ws); + +struct StatusbarApplyFilterImmediately +{ + StatusbarApplyFilterImmediately(Filterable *f, const std::wstring &filter) + : m_f(f), m_ws(filter) { } + + void operator()(const std::wstring &ws); + +private: + Filterable *m_f; + std::wstring m_ws; +}; #endif diff --git a/src/utility/string.cpp b/src/utility/string.cpp index c1cd9a38..554dd1b7 100644 --- a/src/utility/string.cpp +++ b/src/utility/string.cpp @@ -174,6 +174,8 @@ std::string getEnclosedString(const std::string &s, char a, char b, size_t *pos) // we want to set pos to char after b if possible if (i < s.length()) ++i; + else // we reached end of string and didn't encounter closing char + result.clear(); } if (pos != 0) *pos = i; diff --git a/src/window.h b/src/window.h index 1984c583..936ea03e 100644 --- a/src/window.h +++ b/src/window.h @@ -340,6 +340,9 @@ struct Window /// Push single character into input queue, so it can get consumed by ReadKey void pushChar(int ch); + /// @return const reference to internal input queue + const std::queue &inputQueue() { return m_input_queue; } + /// Scrolls the window by amount of lines given in its parameter /// @param where indicates how many lines it has to scroll virtual void scroll(Where where);