summaryrefslogtreecommitdiffstats
path: root/src/frontend/mame/ui/selsoft.cpp
diff options
context:
space:
mode:
author andreasnaive <andreasnaive@gmail.com>2019-03-25 23:13:40 +0100
committer andreasnaive <andreasnaive@gmail.com>2019-03-25 23:13:40 +0100
commitb380514764cf857469bae61c11143a19f79a74c5 (patch)
tree63c8012e262618f08a332da31dd714281aa2c5ed /src/frontend/mame/ui/selsoft.cpp
parentc24473ddff715ecec2e258a6eb38960cf8c8e98e (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.cpp383
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();