From 2bd6aeb5017215e8e3d19f8e161e96774a7c5d14 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Sat, 9 Oct 2021 23:41:27 +1100 Subject: frontend: Support phonetic reading field from localised system name lists. --- src/frontend/mame/ui/selgame.cpp | 165 ++++++++++++++++++++++++--------------- src/frontend/mame/ui/utils.cpp | 6 +- src/frontend/mame/ui/utils.h | 5 ++ 3 files changed, 111 insertions(+), 65 deletions(-) diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp index 93c3f3e5760..f4d2948b8e1 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -191,10 +191,8 @@ private: // sort drivers and notify std::collate const &coll = std::use_facet >(std::locale()); auto const compare_names = - [&coll] (std::string const &x, std::string const &y) -> bool + [&coll] (std::wstring const &wx, std::wstring const &wy) -> bool { - std::wstring const wx = wstring_from_utf8(x); - std::wstring const wy = wstring_from_utf8(y); return 0 > coll.compare(wx.data(), wx.data() + wx.size(), wy.data(), wy.data() + wy.size()); }; std::stable_sort( @@ -207,28 +205,50 @@ private: if (!lhs.is_clone && !rhs.is_clone) { - return compare_names(lhs.description, rhs.description); + return compare_names( + lhs.reading_description.empty() ? wstring_from_utf8(lhs.description) : lhs.reading_description, + rhs.reading_description.empty() ? wstring_from_utf8(rhs.description) : rhs.reading_description); } else if (lhs.is_clone && rhs.is_clone) { if (!std::strcmp(x.parent, y.parent)) - return compare_names(lhs.description, rhs.description); + { + return compare_names( + lhs.reading_description.empty() ? wstring_from_utf8(lhs.description) : lhs.reading_description, + rhs.reading_description.empty() ? wstring_from_utf8(rhs.description) : rhs.reading_description); + } else - return compare_names(lhs.parent, rhs.parent); + { + return compare_names( + lhs.reading_parent.empty() ? wstring_from_utf8(lhs.parent) : lhs.reading_parent, + rhs.reading_parent.empty() ? wstring_from_utf8(rhs.parent) : rhs.reading_parent); + } } else if (!lhs.is_clone && rhs.is_clone) { if (!std::strcmp(x.name, y.parent)) + { return true; + } else - return compare_names(lhs.description, rhs.parent); + { + return compare_names( + lhs.reading_description.empty() ? wstring_from_utf8(lhs.description) : lhs.reading_description, + rhs.reading_parent.empty() ? wstring_from_utf8(rhs.parent) : rhs.reading_parent); + } } else { if (!std::strcmp(x.parent, y.name)) + { return false; + } else - return compare_names(lhs.parent, rhs.description); + { + return compare_names( + lhs.reading_parent.empty() ? wstring_from_utf8(lhs.parent) : lhs.reading_parent, + rhs.reading_description.empty() ? wstring_from_utf8(rhs.description) : rhs.reading_description); + } } }); notify_available(AVAIL_SORTED_LIST); @@ -336,11 +356,17 @@ private: void load_titles(util::core_file &file) { char readbuf[1024]; + std::string convbuf; while (file.gets(readbuf, std::size(readbuf))) { - // shortname and description separated by tab - auto const split(std::find(std::begin(readbuf), std::end(readbuf), '\t')); - if (std::end(readbuf) == split) + // shortname, description, and description reading separated by tab + auto const eoln( + std::find_if( + std::begin(readbuf), + std::end(readbuf), + [] (char ch) { return !ch || ('\n' == ch) || ('\r' == ch); })); + auto const split(std::find(std::begin(readbuf), eoln, '\t')); + if (eoln == split) continue; std::string_view const shortname(readbuf, split - readbuf); @@ -360,10 +386,10 @@ private: continue; } - // strip additional columns - auto const start(std::next(split)); - auto const end(std::find(start, std::end(readbuf), '\t')); - auto const description(strtrimspace(std::string_view(start, end - start))); + // find the end of the description + auto const descstart(std::next(split)); + auto const descend(std::find(descstart, eoln, '\t')); + auto const description(strtrimspace(std::string_view(descstart, descend - descstart))); if (description.empty()) { osd_printf_warning("Empty translated description for system '%s'\n", shortname); @@ -380,6 +406,26 @@ private: { found->description = description; } + + // populate the reading if it's present + if (eoln == descend) + continue; + auto const readstart(std::next(descend)); + auto const readend(std::find(readstart, eoln, '\t')); + auto const reading(strtrimspace(std::string_view(readstart, readend - readstart))); + if (reading.empty()) + { + osd_printf_warning("Empty translated description reading for system '%s'\n", shortname); + } + else + { + found->reading_description = wstring_from_utf8(reading); + found->ucs_reading_description = ustr_from_utf8(normalize_unicode(reading, unicode_normalization_form::D, true)); + convbuf.assign(found->driver->manufacturer); + convbuf.append(1, ' '); + convbuf.append(reading); + found->ucs_manufacturer_reading_description = ustr_from_utf8(normalize_unicode(convbuf, unicode_normalization_form::D, true)); + } } // fill in untranslated descriptions @@ -406,9 +452,14 @@ private: return a.driver->name < b; })); if (m_sorted_list.end() != found) + { info.parent = found->description; + info.reading_parent = found->reading_description; + } else + { info.parent = info.driver->parent; + } } } } @@ -1204,67 +1255,53 @@ void menu_select_game::populate_search() // keep track of what we matched against const std::u32string ucs_search(ustr_from_utf8(normalize_unicode(m_search, unicode_normalization_form::D, true))); - // match shortnames + // check available search data if (m_persistent_data.is_available(persistent_data::AVAIL_UCS_SHORTNAME)) - { m_searched_fields |= persistent_data::AVAIL_UCS_SHORTNAME; - for (std::pair > &info : m_searchlist) - info.first = util::edit_distance(ucs_search, info.second.get().ucs_shortname); - } - - // match descriptions if (m_persistent_data.is_available(persistent_data::AVAIL_UCS_DESCRIPTION)) - { m_searched_fields |= persistent_data::AVAIL_UCS_DESCRIPTION; - for (std::pair > &info : m_searchlist) - { - if (info.first) - { - double const penalty(util::edit_distance(ucs_search, info.second.get().ucs_description)); - info.first = (std::min)(penalty, info.first); - } - } - } - - // match " " if (m_persistent_data.is_available(persistent_data::AVAIL_UCS_MANUF_DESC)) - { m_searched_fields |= persistent_data::AVAIL_UCS_MANUF_DESC; - for (std::pair > &info : m_searchlist) - { - if (info.first) - { - double const penalty(util::edit_distance(ucs_search, info.second.get().ucs_manufacturer_description)); - info.first = (std::min)(penalty, info.first); - } - } - } - - // match default description if (m_persistent_data.is_available(persistent_data::AVAIL_UCS_DFLT_DESC)) - { m_searched_fields |= persistent_data::AVAIL_UCS_DFLT_DESC; - for (std::pair > &info : m_searchlist) + if (m_persistent_data.is_available(persistent_data::AVAIL_UCS_MANUF_DFLT_DESC)) + m_searched_fields |= persistent_data::AVAIL_UCS_MANUF_DFLT_DESC; + + for (std::pair > &info : m_searchlist) + { + info.first = 1.0; + ui_system_info const &sys(info.second); + + // match shortnames + if (m_searched_fields & persistent_data::AVAIL_UCS_SHORTNAME) + info.first = util::edit_distance(ucs_search, sys.ucs_shortname); + + // match reading + if (info.first && !sys.ucs_reading_description.empty()) { - if (info.first && !info.second.get().ucs_default_description.empty()) - { - double const penalty(util::edit_distance(ucs_search, info.second.get().ucs_default_description)); - info.first = (std::min)(penalty, info.first); - } + info.first = (std::min)(util::edit_distance(ucs_search, sys.ucs_reading_description), info.first); + + // match " " + if (info.first) + info.first = (std::min)(util::edit_distance(ucs_search, sys.ucs_manufacturer_reading_description), info.first); } - } - // match default description - if (m_persistent_data.is_available(persistent_data::AVAIL_UCS_MANUF_DFLT_DESC)) - { - m_searched_fields |= persistent_data::AVAIL_UCS_DFLT_DESC; - for (std::pair > &info : m_searchlist) + // match descriptions + if (info.first && (m_searched_fields & persistent_data::AVAIL_UCS_DESCRIPTION)) + info.first = (std::min)(util::edit_distance(ucs_search, sys.ucs_description), info.first); + + // match " " + if (info.first && (m_searched_fields & persistent_data::AVAIL_UCS_MANUF_DESC)) + info.first = (std::min)(util::edit_distance(ucs_search, sys.ucs_manufacturer_description), info.first); + + // match default description + if (info.first && (m_searched_fields & persistent_data::AVAIL_UCS_DFLT_DESC) && !sys.ucs_default_description.empty()) { - if (info.first && !info.second.get().ucs_manufacturer_default_description.empty()) - { - double const penalty(util::edit_distance(ucs_search, info.second.get().ucs_manufacturer_default_description)); - info.first = (std::min)(penalty, info.first); - } + info.first = (std::min)(util::edit_distance(ucs_search, sys.ucs_default_description), info.first); + + // match " " + if (info.first && (m_searched_fields & persistent_data::AVAIL_UCS_MANUF_DFLT_DESC)) + info.first = (std::min)(util::edit_distance(ucs_search, sys.ucs_manufacturer_default_description), info.first); } } diff --git a/src/frontend/mame/ui/utils.cpp b/src/frontend/mame/ui/utils.cpp index ea41c1337ad..dead21e8184 100644 --- a/src/frontend/mame/ui/utils.cpp +++ b/src/frontend/mame/ui/utils.cpp @@ -2151,9 +2151,13 @@ void swap(ui_system_info &a, ui_system_info &b) noexcept swap(a.available, b.available); swap(a.description, b.description); swap(a.parent, b.parent); + swap(a.reading_description, b.reading_description); + swap(a.reading_parent, b.reading_parent); swap(a.ucs_shortname, b.ucs_shortname); swap(a.ucs_description, b.ucs_description); + swap(a.ucs_reading_description, b.ucs_reading_description); swap(a.ucs_manufacturer_description, b.ucs_manufacturer_description); - swap(a.ucs_description, b.ucs_description); + swap(a.ucs_manufacturer_reading_description, b.ucs_manufacturer_reading_description); + swap(a.ucs_default_description, b.ucs_default_description); swap(a.ucs_manufacturer_default_description, b.ucs_manufacturer_default_description); } diff --git a/src/frontend/mame/ui/utils.h b/src/frontend/mame/ui/utils.h index 496786c5f2a..4ef91eb5e2e 100644 --- a/src/frontend/mame/ui/utils.h +++ b/src/frontend/mame/ui/utils.h @@ -48,9 +48,14 @@ struct ui_system_info std::string description; std::string parent; + std::wstring reading_description; + std::wstring reading_parent; + std::u32string ucs_shortname; std::u32string ucs_description; + std::u32string ucs_reading_description; std::u32string ucs_manufacturer_description; + std::u32string ucs_manufacturer_reading_description; std::u32string ucs_default_description; std::u32string ucs_manufacturer_default_description; }; -- cgit v1.2.3