diff --git a/README.md b/README.md index 7c1c54e..ac68f03 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,6 @@ UX: - **Auto re-attach control** — keep it visible/controllable when not connected (today it can be enabled-but-invisible). - **Tooltips on disabled controls** — explain *why* Inject/subsystem controls are disabled. -- **Case-insensitive log filter.** Code quality: - **Stale comments** — `hook_guard.hpp` top block (still the old destroy-on-remove model), diff --git a/host/src/log_panel.cpp b/host/src/log_panel.cpp index 996c0d2..62d1ac2 100644 --- a/host/src/log_panel.cpp +++ b/host/src/log_panel.cpp @@ -1,7 +1,10 @@ #include "log_panel.hpp" +#include +#include #include #include +#include #include "imgui.h" @@ -11,6 +14,24 @@ namespace coop { +namespace +{ +// Case-insensitive substring test, so the log filter matches regardless of case (consistent with the +// rest of the app, where "error" should find "ERROR"). +bool icontains(const std::string& hay, const char* needle) +{ + if (needle == nullptr || needle[0] == '\0') + { + return true; + } + auto lower = [](std::string s) { + std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c) { return static_cast(std::tolower(c)); }); + return s; + }; + return lower(hay).find(lower(needle)) != std::string::npos; +} +} // namespace + void LogPanel::add_line(const LogRecord& rec) { if (first_millis_ == 0) @@ -55,7 +76,7 @@ void LogPanel::draw() const bool has_filter = filter_[0] != '\0'; for (const Line& line : lines_) { - if (has_filter && line.text.find(filter_) == std::string::npos) + if (has_filter && !icontains(line.text, filter_)) { continue; }