diff options
author | 2019-03-25 23:13:40 +0100 | |
---|---|---|
committer | 2019-03-25 23:13:40 +0100 | |
commit | b380514764cf857469bae61c11143a19f79a74c5 (patch) | |
tree | 63c8012e262618f08a332da31dd714281aa2c5ed /src/frontend/mame/ui/selsoft.cpp | |
parent | c24473ddff715ecec2e258a6eb38960cf8c8e98e (diff) |
Revert "conflict resolution (nw)"
This reverts commit c24473ddff715ecec2e258a6eb38960cf8c8e98e, reversing
changes made to 009cba4fb8102102168ef32870892438327f3705.
Diffstat (limited to 'src/frontend/mame/ui/selsoft.cpp')
-rw-r--r-- | src/frontend/mame/ui/selsoft.cpp | 383 |
1 files changed, 148 insertions, 235 deletions
diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp index 26635c6d31a..e7ebc3effa2 100644 --- a/src/frontend/mame/ui/selsoft.cpp +++ b/src/frontend/mame/ui/selsoft.cpp @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Maurizio Petrarota, Vas Crabb +// copyright-holders:Maurizio Petrarota /*************************************************************************** ui/selsoft.cpp @@ -12,7 +12,6 @@ #include "ui/selsoft.h" #include "ui/ui.h" -#include "ui/icorender.h" #include "ui/inifile.h" #include "ui/selector.h" @@ -25,97 +24,75 @@ #include "uiinput.h" #include "luaengine.h" -#include <algorithm> -#include <iterator> -#include <functional> - namespace ui { -namespace { - //------------------------------------------------- // compares two items in the software list and // sort them by parent-clone //------------------------------------------------- -bool compare_software(ui_software_info const &a, ui_software_info const &b) +bool compare_software(ui_software_info a, ui_software_info b) { - bool const clonex = !a.parentname.empty() && !a.parentlongname.empty(); - bool const cloney = !b.parentname.empty() && !b.parentlongname.empty(); + ui_software_info *x = &a; + ui_software_info *y = &b; + + bool clonex = !x->parentname.empty(); + bool cloney = !y->parentname.empty(); if (!clonex && !cloney) + return (strmakelower(x->longname) < strmakelower(y->longname)); + + std::string cx(x->parentlongname), cy(y->parentlongname); + + if (cx.empty()) + clonex = false; + + if (cy.empty()) + cloney = false; + + if (!clonex && !cloney) + return (strmakelower(x->longname) < strmakelower(y->longname)); + else if (clonex && cloney) { - return 0 > core_stricmp(a.longname.c_str(), b.longname.c_str()); + if (!core_stricmp(x->parentname.c_str(), y->parentname.c_str()) && !core_stricmp(x->instance.c_str(), y->instance.c_str())) + return (strmakelower(x->longname) < strmakelower(y->longname)); + else + return (strmakelower(cx) < strmakelower(cy)); } else if (!clonex && cloney) { - if ((a.shortname == b.parentname) && (a.instance == b.instance)) + if (!core_stricmp(x->shortname.c_str(), y->parentname.c_str()) && !core_stricmp(x->instance.c_str(), y->instance.c_str())) return true; else - return 0 > core_stricmp(a.longname.c_str(), b.parentlongname.c_str()); + return (strmakelower(x->longname) < strmakelower(cy)); } - else if (clonex && !cloney) + else { - if ((a.parentname == b.shortname) && (a.instance == b.instance)) + if (!core_stricmp(x->parentname.c_str(), y->shortname.c_str()) && !core_stricmp(x->instance.c_str(), y->instance.c_str())) return false; else - return 0 > core_stricmp(a.parentlongname.c_str(), b.longname.c_str()); - } - else if ((a.parentname == b.parentname) && (a.instance == b.instance)) - { - return 0 > core_stricmp(a.longname.c_str(), b.longname.c_str()); - } - else - { - return 0 > core_stricmp(a.parentlongname.c_str(), b.parentlongname.c_str()); + return (strmakelower(cx) < strmakelower(y->longname)); } } -} // anonymous namespace - - -menu_select_software::search_item::search_item(ui_software_info const &s) - : software(s) - , ucs_shortname(ustr_from_utf8(normalize_unicode(s.shortname, unicode_normalization_form::D, true))) - , ucs_longname(ustr_from_utf8(normalize_unicode(s.longname, unicode_normalization_form::D, true))) - , penalty(1.0) -{ -} - -void menu_select_software::search_item::set_penalty(std::u32string const &search) -{ - // TODO: search alternate title as well - penalty = util::edit_distance(search, ucs_shortname); - if (penalty) - penalty = (std::min)(penalty, util::edit_distance(search, ucs_longname)); -} - - //------------------------------------------------- // ctor //------------------------------------------------- -menu_select_software::menu_select_software(mame_ui_manager &mui, render_container &container, game_driver const &driver) +menu_select_software::menu_select_software(mame_ui_manager &mui, render_container &container, const game_driver *driver) : menu_select_launch(mui, container, true) - , m_icon_paths() - , m_icons(MAX_ICONS_RENDER) - , m_driver(driver) - , m_has_empty_start(false) - , m_filter_data() - , m_filters() , m_filter_type(software_filter::ALL) - , m_swinfo() - , m_searchlist() - , m_displaylist() { reselect_last::reselect(false); + m_driver = driver; build_software_list(); load_sw_custom_filters(); m_filter_highlight = m_filter_type; - set_switch_image(); + ui_globals::curimage_view = SNAPSHOT_VIEW; + ui_globals::switch_image = true; ui_globals::cur_sw_dats_view = 0; ui_globals::cur_sw_dats_total = 1; } @@ -126,6 +103,8 @@ menu_select_software::menu_select_software(mame_ui_manager &mui, render_containe menu_select_software::~menu_select_software() { + ui_globals::curimage_view = CABINETS_VIEW; + ui_globals::switch_image = true; } //------------------------------------------------- @@ -156,10 +135,12 @@ void menu_select_software::handle() break; case IPT_UI_LEFT: - if (ui_globals::rpanel == RP_IMAGES) + if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view > FIRST_VIEW) { // Images - previous_image_view(); + ui_globals::curimage_view--; + ui_globals::switch_image = true; + ui_globals::default_image = false; } else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view > 0) { @@ -170,10 +151,12 @@ void menu_select_software::handle() break; case IPT_UI_RIGHT: - if (ui_globals::rpanel == RP_IMAGES) + if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view < LAST_VIEW) { // Images - next_image_view(); + ui_globals::curimage_view++; + ui_globals::switch_image = true; + ui_globals::default_image = false; } else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view < (ui_globals::cur_sw_dats_total - 1)) { @@ -222,16 +205,16 @@ void menu_select_software::handle() if ((uintptr_t)swinfo > 2) { favorite_manager &mfav = mame_machine_manager::instance()->favorite(); - if (!mfav.is_favorite_system_software(*swinfo)) + if (!mfav.isgame_favorite(*swinfo)) { - mfav.add_favorite_software(*swinfo); + mfav.add_favorite_game(*swinfo); machine().popmessage(_("%s\n added to favorites list."), swinfo->longname.c_str()); } else { machine().popmessage(_("%s\n removed from favorites list."), swinfo->longname.c_str()); - mfav.remove_favorite_software(*swinfo); + mfav.remove_favorite_game(); } } } @@ -249,27 +232,17 @@ void menu_select_software::handle() void menu_select_software::populate(float &customtop, float &custombottom) { - for (auto &icon : m_icons) // TODO: why is this here? maybe better on resize or setting change? - icon.second.texture.reset(); - uint32_t flags_ui = FLAG_LEFT_ARROW | FLAG_RIGHT_ARROW; m_has_empty_start = true; int old_software = -1; - // FIXME: why does it do this relatively expensive operation every time? - machine_config config(m_driver, machine().options()); + machine_config config(*m_driver, machine().options()); for (device_image_interface &image : image_interface_iterator(config.root_device())) - { - if (!image.filename() && image.must_be_loaded()) + if (image.filename() == nullptr && image.must_be_loaded()) { m_has_empty_start = false; break; } - } - - // start with an empty list - m_displaylist.clear(); - filter_map::const_iterator const flt(m_filters.find(m_filter_type)); // no active search if (m_search.empty()) @@ -278,44 +251,37 @@ void menu_select_software::populate(float &customtop, float &custombottom) if (m_has_empty_start) item_append("[Start empty]", "", flags_ui, (void *)&m_swinfo[0]); - if (m_filters.end() == flt) - std::copy(std::next(m_swinfo.begin()), m_swinfo.end(), std::back_inserter(m_displaylist)); - else - flt->second->apply(std::next(m_swinfo.begin()), m_swinfo.end(), std::back_inserter(m_displaylist)); - } - else - { - find_matches(); + m_displaylist.clear(); + m_tmp.clear(); - if (m_filters.end() == flt) - { - std::transform( - m_searchlist.begin(), - std::next(m_searchlist.begin(), (std::min)(m_searchlist.size(), MAX_VISIBLE_SEARCH)), - std::back_inserter(m_displaylist), - [] (search_item const &entry) { return entry.software; }); - } + filter_map::const_iterator const it(m_filters.find(m_filter_type)); + if (m_filters.end() == it) + m_displaylist = m_sortedlist; else + it->second->apply(std::begin(m_sortedlist), std::end(m_sortedlist), std::back_inserter(m_displaylist)); + + // iterate over entries + for (size_t curitem = 0; curitem < m_displaylist.size(); ++curitem) { - for (auto it = m_searchlist.begin(); (m_searchlist.end() != it) && (MAX_VISIBLE_SEARCH > m_displaylist.size()); ++it) - { - if (flt->second->apply(it->software)) - m_displaylist.emplace_back(it->software); - } + if (reselect_last::software() == "[Start empty]" && !reselect_last::driver().empty()) + old_software = 0; + + else if (m_displaylist[curitem]->shortname == reselect_last::software() && m_displaylist[curitem]->listname == reselect_last::swlist()) + old_software = m_has_empty_start ? curitem + 1 : curitem; + + item_append(m_displaylist[curitem]->longname, m_displaylist[curitem]->devicetype, + m_displaylist[curitem]->parentname.empty() ? flags_ui : (FLAG_INVERT | flags_ui), (void *)m_displaylist[curitem]); } } - // iterate over entries - for (size_t curitem = 0; curitem < m_displaylist.size(); ++curitem) + else { - if (reselect_last::software() == "[Start empty]" && !reselect_last::driver().empty()) - old_software = 0; - else if (m_displaylist[curitem].get().shortname == reselect_last::software() && m_displaylist[curitem].get().listname == reselect_last::swlist()) - old_software = m_has_empty_start ? curitem + 1 : curitem; - - item_append( - m_displaylist[curitem].get().longname, m_displaylist[curitem].get().devicetype, - m_displaylist[curitem].get().parentname.empty() ? flags_ui : (FLAG_INVERT | flags_ui), (void *)&m_displaylist[curitem].get()); + find_matches(m_search.c_str(), VISIBLE_GAMES_IN_SEARCH); + + for (int curitem = 0; m_searchlist[curitem] != nullptr; ++curitem) + item_append(m_searchlist[curitem]->longname, m_searchlist[curitem]->devicetype, + m_searchlist[curitem]->parentname.empty() ? flags_ui : (FLAG_INVERT | flags_ui), + (void *)m_searchlist[curitem]); } item_append(menu_item_type::SEPARATOR, flags_ui); @@ -340,51 +306,21 @@ void menu_select_software::populate(float &customtop, float &custombottom) void menu_select_software::build_software_list() { // add start empty item - m_swinfo.emplace_back(m_driver); + m_swinfo.emplace_back(*m_driver); - machine_config config(m_driver, machine().options()); + machine_config config(*m_driver, machine().options()); - // iterate through all software lists - std::vector<std::size_t> orphans; - struct orphan_less - { - std::vector<ui_software_info> &swinfo; - bool operator()(std::string const &a, std::string const &b) const { return a < b; }; - bool operator()(std::string const &a, std::size_t b) const { return a < swinfo[b].parentname; }; - bool operator()(std::size_t a, std::string const &b) const { return swinfo[a].parentname < b; }; - bool operator()(std::size_t a, std::size_t b) const { return swinfo[a].parentname < swinfo[b].parentname; }; - }; - orphan_less const orphan_cmp{ m_swinfo }; + // iterate thru all software lists for (software_list_device &swlist : software_list_device_iterator(config.root_device())) { m_filter_data.add_list(swlist.list_name(), swlist.description()); - check_for_icons(swlist.list_name().c_str()); - orphans.clear(); - std::map<std::string, std::string> parentnames; - std::map<std::string, std::string>::const_iterator prevparent(parentnames.end()); for (const software_info &swinfo : swlist.get_info()) { - // check for previously-encountered clones - if (swinfo.parentname().empty()) - { - if (parentnames.emplace(swinfo.shortname(), swinfo.longname()).second) - { - auto const clones(std::equal_range(orphans.begin(), orphans.end(), swinfo.shortname(), orphan_cmp)); - for (auto it = clones.first; clones.second != it; ++it) - m_swinfo[*it].parentlongname = swinfo.longname(); - orphans.erase(clones.first, clones.second); - } - else - { - assert([] (auto const x) { return x.first == x.second; } (std::equal_range(orphans.begin(), orphans.end(), swinfo.shortname(), orphan_cmp))); - } - } - const software_part &part = swinfo.parts().front(); if (swlist.is_compatible(part) == SOFTWARE_IS_COMPATIBLE) { - char const *instance_name(nullptr); - char const *type_name(nullptr); + const char *instance_name = nullptr; + const char *type_name = nullptr; for (device_image_interface &image : image_interface_iterator(config.root_device())) { char const *const interface = image.image_interface(); @@ -395,35 +331,45 @@ void menu_select_software::build_software_list() break; } } + if (!instance_name || !type_name) + continue; - if (instance_name && type_name) - { - // add to collection and try to resolve parent if applicable - auto const ins(m_swinfo.emplace(m_swinfo.end(), swinfo, part, m_driver, swlist.list_name(), instance_name, type_name)); - if (!swinfo.parentname().empty()) - { - if ((parentnames.end() == prevparent) || (swinfo.parentname() != prevparent->first)) - prevparent = parentnames.find(swinfo.parentname()); + ui_software_info tmpmatches(swinfo, part, *m_driver, swlist.list_name(), instance_name, type_name); - if (parentnames.end() != prevparent) - { - ins->parentlongname = prevparent->second; - } - else - { - orphans.emplace( - std::upper_bound(orphans.begin(), orphans.end(), swinfo.parentname(), orphan_cmp), - std::distance(m_swinfo.begin(), ins)); - } - } + m_filter_data.add_region(tmpmatches.longname); + m_filter_data.add_publisher(tmpmatches.publisher); + m_filter_data.add_year(tmpmatches.year); + m_filter_data.add_device_type(tmpmatches.devicetype); + m_swinfo.emplace_back(std::move(tmpmatches)); + } + } + } + m_displaylist.resize(m_swinfo.size() + 1); + + // retrieve and set the long name of software for parents + for (size_t y = 1; y < m_swinfo.size(); ++y) + { + if (!m_swinfo[y].parentname.empty()) + { + std::string lparent(m_swinfo[y].parentname); + bool found = false; - // populate filter choices - m_filter_data.add_region(ins->longname); - m_filter_data.add_publisher(ins->publisher); - m_filter_data.add_year(ins->year); - m_filter_data.add_device_type(ins->devicetype); + // first scan backward + for (int x = y; x > 0; --x) + if (lparent == m_swinfo[x].shortname && m_swinfo[y].listname == m_swinfo[x].listname) + { + m_swinfo[y].parentlongname = m_swinfo[x].longname; + found = true; + break; + } + + // not found? then scan forward + for (size_t x = y; !found && x < m_swinfo.size(); ++x) + if (lparent == m_swinfo[x].shortname && m_swinfo[y].listname == m_swinfo[x].listname) + { + m_swinfo[y].parentlongname = m_swinfo[x].longname; + break; } - } } } @@ -462,6 +408,9 @@ void menu_select_software::build_software_list() // sort array std::stable_sort(m_swinfo.begin() + 1, m_swinfo.end(), compare_software); m_filter_data.finalise(); + + for (size_t x = 1; x < m_swinfo.size(); ++x) + m_sortedlist.push_back(&m_swinfo[x]); } @@ -525,7 +474,7 @@ void menu_select_software::load_sw_custom_filters() { // attempt to open the output file emu_file file(ui().options().ui_path(), OPEN_FLAG_READ); - if (file.open("custom_", m_driver.name, "_filter.ini") == osd_file::error::NONE) + if (file.open("custom_", m_driver->name, "_filter.ini") == osd_file::error::NONE) { software_filter::ptr flt(software_filter::create(file, m_filter_data)); if (flt) @@ -538,25 +487,38 @@ void menu_select_software::load_sw_custom_filters() // find approximate matches //------------------------------------------------- -void menu_select_software::find_matches() +void menu_select_software::find_matches(const char *str, int count) { - // ensure search list is populated - if (m_searchlist.empty()) + // allocate memory to track the penalty value + std::vector<int> penalty(count, 9999); + int index = 0; + + for (; index < m_displaylist.size(); ++index) { - m_searchlist.reserve(m_swinfo.size()); - std::copy(m_swinfo.begin(), m_swinfo.end(), std::back_inserter(m_searchlist)); - } + // pick the best match between driver name and description + int curpenalty = fuzzy_substring(str, m_displaylist[index]->longname); + int tmp = fuzzy_substring(str, m_displaylist[index]->shortname); + curpenalty = std::min(curpenalty, tmp); + + // insert into the sorted table of matches + for (int matchnum = count - 1; matchnum >= 0; --matchnum) + { + // stop if we're worse than the current entry + if (curpenalty >= penalty[matchnum]) + break; - // update search - const std::u32string ucs_search(ustr_from_utf8(normalize_unicode(m_search, unicode_normalization_form::D, true))); - for (search_item &entry : m_searchlist) - entry.set_penalty(ucs_search); + // as long as this isn't the last entry, bump this one down + if (matchnum < count - 1) + { + penalty[matchnum + 1] = penalty[matchnum]; + m_searchlist[matchnum + 1] = m_searchlist[matchnum]; + } - // sort according to edit distance - std::stable_sort( - m_searchlist.begin(), - m_searchlist.end(), - [] (search_item const &lhs, search_item const &rhs) { return lhs.penalty < rhs.penalty; }); + m_searchlist[matchnum] = m_displaylist[index]; + penalty[matchnum] = curpenalty; + } + } + (index < count) ? m_searchlist[index] = nullptr : m_searchlist[count] = nullptr; } //------------------------------------------------- @@ -570,56 +532,6 @@ float menu_select_software::draw_left_panel(float x1, float y1, float x2, float //------------------------------------------------- -// get (possibly cached) icon texture -//------------------------------------------------- - -render_texture *menu_select_software::get_icon_texture(int linenum, void *selectedref) -{ - ui_software_info const *const swinfo(reinterpret_cast<ui_software_info const *>(selectedref)); - assert(swinfo); - - if (swinfo->startempty) - return nullptr; - - icon_cache::iterator icon(m_icons.find(swinfo)); - if ((m_icons.end() == icon) || !icon->second.texture) - { - std::map<std::string, std::string>::iterator paths(m_icon_paths.find(swinfo->listname)); - if (m_icon_paths.end() == paths) - paths = m_icon_paths.emplace(swinfo->listname, make_icon_paths(swinfo->listname.c_str())).first; - - // allocate an entry or allocate a texture on forced redraw - if (m_icons.end() == icon) - { - icon = m_icons.emplace(swinfo, texture_ptr(machine().render().texture_alloc(), machine().render())).first; - } - else - { - assert(!icon->second.texture); - icon->second.texture.reset(machine().render().texture_alloc()); - } - - bitmap_argb32 tmp; - emu_file snapfile(std::string(paths->second), OPEN_FLAG_READ); - if (snapfile.open(std::string(swinfo->shortname), ".ico") == osd_file::error::NONE) - { - render_load_ico_highest_detail(snapfile, tmp); - snapfile.close(); - } - if (!tmp.valid() && !swinfo->parentname.empty() && (snapfile.open(std::string(swinfo->parentname), ".ico") == osd_file::error::NONE)) - { - render_load_ico_highest_detail(snapfile, tmp); - snapfile.close(); - } - - scale_icon(std::move(tmp), icon->second); - } - - return icon->second.bitmap.valid() ? icon->second.texture.get() : nullptr; -} - - -//------------------------------------------------- // get selected software and/or driver //------------------------------------------------- @@ -635,7 +547,7 @@ void menu_select_software::make_topbox_text(std::string &line0, std::string &lin // determine the text for the header int vis_item = !m_search.empty() ? visible_items : (m_has_empty_start ? visible_items - 1 : visible_items); line0 = string_format(_("%1$s %2$s ( %3$d / %4$d software packages )"), emulator_info::get_appname(), bare_build_version, vis_item, m_swinfo.size() - 1); - line1 = string_format(_("Driver: \"%1$s\" software list "), m_driver.type.fullname()); + line1 = string_format(_("Driver: \"%1$s\" software list "), m_driver->type.fullname()); filter_map::const_iterator const it(m_filters.find(m_filter_type)); char const *const filter((m_filters.end() != it) ? it->second->filter_text() : nullptr); @@ -664,19 +576,20 @@ void menu_select_software::filter_selected() { if ((software_filter::FIRST <= m_filter_highlight) && (software_filter::LAST >= m_filter_highlight)) { + m_search.clear(); filter_map::const_iterator it(m_filters.find(software_filter::type(m_filter_highlight))); if (m_filters.end() == it) it = m_filters.emplace(software_filter::type(m_filter_highlight), software_filter::create(software_filter::type(m_filter_highlight), m_filter_data)).first; it->second->show_ui( ui(), container(), - [this] (software_filter &filter) + [this, driver = m_driver] (software_filter &filter) { software_filter::type const new_type(filter.get_type()); if (software_filter::CUSTOM == new_type) { emu_file file(ui().options().ui_path(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - if (file.open("custom_", m_driver.name, "_filter.ini") == osd_file::error::NONE) + if (file.open("custom_", driver->name, "_filter.ini") == osd_file::error::NONE) { filter.save_ini(file, 0); file.close(); |