Smoother directory navigation using search. Normalize away full-width chars for search.

This commit is contained in:
Henrik Rydgård committed 2026-04-16 12:46:34 -06:00
1 parent 0f7300b453
commit 786b835ba1
3 files changed
+51 -3

No files matched your search

+41
View File
@@ -24,6 +24,7 @@
#include <cstdint>
#include <algorithm>
#include <string>
#include <string_view>
#include "Common/Data/Encoding/Utf8.h"
#include "Common/Data/Encoding/Utf16.h"
@@ -373,6 +374,46 @@ void ConvertUTF8ToJavaModifiedUTF8(std::string *output, std::string_view input)
_dbg_assert_(output->size() >= input.size());
}
std::string NormalizeForSearch(std::string_view input) {
std::string result;
// Pre-allocating input size is a good heuristic, though the
// result could be slightly smaller after normalization.
result.reserve(input.size());
int index = 0;
int size = static_cast<int>(input.size());
char buffer[4]; // Temporary buffer for UTF-8 encoding
while (index < size) {
uint32_t codepoint = u8_nextchar(input.data(), &index, size);
// 1. Convert Fullwidth Roman/Numbers to ASCII
// Range: U+FF01 (!) to U+FF5E (~)
if (codepoint >= 0xFF01 && codepoint <= 0xFF5E) {
codepoint -= 0xFEE0;
}
// Convert Fullwidth Space (U+3000) to standard space
else if (codepoint == 0x3000) {
codepoint = 0x20;
}
// 2. Lowercase (Basic Latin range)
// We do this after the wide-to-ascii conversion to catch characters
// that were originally wide uppercase (e.g., 'A' -> 'A' -> 'a').
if (codepoint >= 'A' && codepoint <= 'Z') {
codepoint += ('a' - 'A');
}
// 3. Re-encode back to UTF-8
int bytes_written = u8_wc_toutf8(buffer, codepoint);
if (bytes_written > 0) {
result.append(buffer, bytes_written);
}
}
return result;
}
#ifndef _WIN32
// Replacements for the Win32 wstring functions. Not to be used from emulation code!
+3
View File
@@ -129,3 +129,6 @@ std::u16string ConvertUTF8ToUCS2(std::string_view source);
// Java needs 4-byte UTF-8 to be converted to surrogate pairs, each component of which get
// encoded into 3-byte UTF-8.
void ConvertUTF8ToJavaModifiedUTF8(std::string *output, std::string_view input);
// Applies "tolower" and also rewrites full-with japanese characters.
std::string NormalizeForSearch(std::string_view input);
+7 -3
View File
@@ -563,6 +563,8 @@ bool GameBrowser::Key(const KeyInput &input) {
// TODO: Restore focus state here.
UI::EnableFocusMovement(false);
}
} else {
// Empty search filter. Navigate upwards on backspace?
}
} else if (!searchFilter_.empty() && input.keyCode == NKCODE_ESCAPE) {
searchFilter_.clear();
@@ -594,8 +596,7 @@ void GameBrowser::ApplySearchFilter(bool setKeyboardFocus) {
return;
}
std::string filter = searchFilter_;
std::transform(filter.begin(), filter.end(), filter.begin(), tolower);
std::string filter = NormalizeForSearch(searchFilter_);
searchPending_ = false;
// By default, everything is matching.
@@ -632,7 +633,7 @@ void GameBrowser::ApplySearchFilter(bool setKeyboardFocus) {
continue;
}
std::transform(label.begin(), label.end(), label.begin(), tolower);
label = NormalizeForSearch(label);
bool match = v->CanBeFocused() && label.find(filter) != label.npos;
if (match && !firstMatch) {
firstMatch = v;
@@ -1152,6 +1153,9 @@ void GameBrowser::NavigateClick(UI::EventParams &e) {
path_.Navigate(text.ToString());
}
g_Config.currentDirectory = path_.GetPath();
// Clear the search filter. This allow for smooth directory navigation using search
// (although there's no good way of going up...)
SetSearchFilter("", false);
Refresh();
}