summaryrefslogtreecommitdiffstats
path: root/src/frontend/mame/ui/utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mame/ui/utils.cpp')
-rw-r--r--src/frontend/mame/ui/utils.cpp379
1 files changed, 310 insertions, 69 deletions
diff --git a/src/frontend/mame/ui/utils.cpp b/src/frontend/mame/ui/utils.cpp
index b18b3aa22af..7da3abb7111 100644
--- a/src/frontend/mame/ui/utils.cpp
+++ b/src/frontend/mame/ui/utils.cpp
@@ -30,6 +30,7 @@
#include <cstring>
#include <iterator>
#include <unordered_set>
+#include <utility>
namespace ui {
@@ -57,46 +58,87 @@ constexpr char const *SOFTWARE_REGIONS[] = {
"tha", "tpe", "tw",
"uk", "ukr", "usa" };
+// must be sorted in std::string comparison order
+constexpr std::pair<char const *, char const *> SOFTWARE_INFO_NAMES[] = {
+ { "alt_title", N_p("swlist-info", "Alternate Title") },
+ { "author", N_p("swlist-info", "Author") },
+ { "barcode", N_p("swlist-info", "Barcode Number") },
+ { "developer", N_p("swlist-info", "Developer") },
+ { "distributor", N_p("swlist-info", "Distributor") },
+ { "install", N_p("swlist-info", "Installation Instructions") },
+ { "isbn", N_p("swlist-info", "ISBN") },
+ { "oem", N_p("swlist-info", "OEM") },
+ { "original_publisher", N_p("swlist-info", "Original Publisher") },
+ { "partno", N_p("swlist-info", "Part Number") },
+ { "pcb", N_p("swlist-info", "PCB") },
+ { "programmer", N_p("swlist-info", "Programmer") },
+ { "release", N_p("swlist-info", "Release Date") },
+ { "serial", N_p("swlist-info", "Serial Number") },
+ { "usage", N_p("swlist-info", "Usage Instructions") },
+ { "version", N_p("swlist-info", "Version") } };
+
+
+
+// must be in sync with the machine_filter::type enum
constexpr char const *MACHINE_FILTER_NAMES[machine_filter::COUNT] = {
- __("Unfiltered"),
- __("Available"),
- __("Unavailable"),
- __("Working"),
- __("Not Working"),
- __("Mechanical"),
- __("Not Mechanical"),
- __("Category"),
- __("Favorites"),
- __("BIOS"),
- __("Not BIOS"),
- __("Parents"),
- __("Clones"),
- __("Manufacturer"),
- __("Year"),
- __("Save Supported"),
- __("Save Unsupported"),
- __("CHD Required"),
- __("No CHD Required"),
- __("Vertical Screen"),
- __("Horizontal Screen"),
- __("Custom Filter") };
-
+ N_p("machine-filter", "Unfiltered"),
+ N_p("machine-filter", "Available"),
+ N_p("machine-filter", "Unavailable"),
+ N_p("machine-filter", "Working"),
+ N_p("machine-filter", "Not Working"),
+ N_p("machine-filter", "Mechanical"),
+ N_p("machine-filter", "Not Mechanical"),
+ N_p("machine-filter", "Category"),
+ N_p("machine-filter", "Favorites"),
+ N_p("machine-filter", "BIOS"),
+ N_p("machine-filter", "Not BIOS"),
+ N_p("machine-filter", "Parents"),
+ N_p("machine-filter", "Clones"),
+ N_p("machine-filter", "Manufacturer"),
+ N_p("machine-filter", "Year"),
+ N_p("machine-filter", "Save Supported"),
+ N_p("machine-filter", "Save Unsupported"),
+ N_p("machine-filter", "CHD Required"),
+ N_p("machine-filter", "No CHD Required"),
+ N_p("machine-filter", "Vertical Screen"),
+ N_p("machine-filter", "Horizontal Screen"),
+ N_p("machine-filter", "Custom Filter") };
+
+// must be in sync with the software_filter::type enum
constexpr char const *SOFTWARE_FILTER_NAMES[software_filter::COUNT] = {
- __("Unfiltered"),
- __("Available"),
- __("Unavailable"),
- __("Favorites"),
- __("Parents"),
- __("Clones"),
- __("Year"),
- __("Publisher"),
- __("Supported"),
- __("Partially Supported"),
- __("Unsupported"),
- __("Release Region"),
- __("Device Type"),
- __("Software List"),
- __("Custom Filter") };
+ N_p("software-filter", "Unfiltered"),
+ N_p("software-filter", "Available"),
+ N_p("software-filter", "Unavailable"),
+ N_p("software-filter", "Favorites"),
+ N_p("software-filter", "Parents"),
+ N_p("software-filter", "Clones"),
+ N_p("software-filter", "Year"),
+ N_p("software-filter", "Publisher"),
+ N_p("software-filter", "Developer"),
+ N_p("software-filter", "Distributor"),
+ N_p("software-filter", "Author"),
+ N_p("software-filter", "Programmer"),
+ N_p("software-filter", "Supported"),
+ N_p("software-filter", "Partially Supported"),
+ N_p("software-filter", "Unsupported"),
+ N_p("software-filter", "Release Region"),
+ N_p("software-filter", "Device Type"),
+ N_p("software-filter", "Software List"),
+ N_p("software-filter", "Custom Filter") };
+
+
+
+//-------------------------------------------------
+// helper for building a sorted vector
+//-------------------------------------------------
+
+template <typename T>
+void add_info_value(std::vector<std::string> &items, T &&value)
+{
+ std::vector<std::string>::iterator const pos(std::lower_bound(items.begin(), items.end(), value));
+ if ((items.end() == pos) || (*pos != value))
+ items.emplace(pos, std::forward<T>(value));
+}
@@ -213,11 +255,14 @@ protected:
, m_selection(0U)
{
if (value)
- {
- std::vector<std::string>::const_iterator const found(std::find(choices.begin(), choices.end(), value));
- if (choices.end() != found)
- m_selection = std::distance(choices.begin(), found);
- }
+ set_value(value);
+ }
+
+ void set_value(char const *value)
+ {
+ auto const found(std::find(m_choices.begin(), m_choices.end(), value));
+ if (m_choices.end() != found)
+ m_selection = std::distance(m_choices.begin(), found);
}
bool have_choices() const { return !m_choices.empty(); }
@@ -1395,6 +1440,93 @@ private:
//-------------------------------------------------
+// software info filters
+//-------------------------------------------------
+
+template <software_filter::type Type>
+class software_info_filter_base : public choice_filter_impl_base<software_filter, Type>
+{
+public:
+ virtual bool apply(ui_software_info const &info) const override
+ {
+ if (!this->have_choices())
+ {
+ return true;
+ }
+ else if (!this->selection_valid())
+ {
+ return false;
+ }
+ else
+ {
+ auto const found(
+ std::find_if(
+ info.info.begin(),
+ info.info.end(),
+ [this] (software_info_item const &i) { return this->apply(i); }));
+ return info.info.end() != found;
+ }
+ }
+
+protected:
+ software_info_filter_base(char const *type, std::vector<std::string> const &choices, char const *value)
+ : choice_filter_impl_base<software_filter, Type>(choices, value)
+ , m_info_type(type)
+ {
+ }
+
+private:
+ bool apply(software_info_item const &info) const
+ {
+ return (info.name() == m_info_type) && (info.value() == this->selection_text());
+ }
+
+ char const *const m_info_type;
+};
+
+
+class developer_software_filter : public software_info_filter_base<software_filter::DEVELOPERS>
+{
+public:
+ developer_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent)
+ : software_info_filter_base<software_filter::DEVELOPERS>("developer", data.developers(), value)
+ {
+ }
+};
+
+
+class distributor_software_filter : public software_info_filter_base<software_filter::DISTRIBUTORS>
+{
+public:
+ distributor_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent)
+ : software_info_filter_base<software_filter::DISTRIBUTORS>("distributor", data.distributors(), value)
+ {
+ }
+};
+
+
+class author_software_filter : public software_info_filter_base<software_filter::AUTHORS>
+{
+public:
+ author_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent)
+ : software_info_filter_base<software_filter::AUTHORS>("author", data.authors(), value)
+ {
+ }
+};
+
+
+class programmer_software_filter : public software_info_filter_base<software_filter::PROGRAMMERS>
+{
+public:
+ programmer_software_filter(software_filter_data const &data, char const *value, emu_file *file, unsigned indent)
+ : software_info_filter_base<software_filter::PROGRAMMERS>("programmer", data.programmers(), value)
+ {
+ }
+};
+
+
+
+//-------------------------------------------------
// composite software filter
//-------------------------------------------------
@@ -1432,6 +1564,10 @@ public:
case FAVORITE:
case YEAR:
case PUBLISHERS:
+ case DEVELOPERS:
+ case DISTRIBUTORS:
+ case AUTHORS:
+ case PROGRAMMERS:
case REGION:
case DEVICE_TYPE:
case LIST:
@@ -1444,7 +1580,15 @@ public:
static bool is_inclusion(type n)
{
- return (YEAR == n) || (PUBLISHERS == n) || (REGION == n) || (DEVICE_TYPE == n) || (LIST == n);
+ return (YEAR == n)
+ || (PUBLISHERS == n)
+ || (DEVELOPERS == n)
+ || (DISTRIBUTORS == n)
+ || (AUTHORS == n)
+ || (PROGRAMMERS == n)
+ || (REGION == n)
+ || (DEVICE_TYPE == n)
+ || (LIST == n);
}
private:
@@ -1542,31 +1686,35 @@ bool machine_filter_data::load_ini(emu_file &file)
void software_filter_data::add_region(std::string const &longname)
{
std::string name(extract_region(longname));
- std::vector<std::string>::iterator const pos(std::lower_bound(m_regions.begin(), m_regions.end(), name));
- if ((m_regions.end() == pos) || (*pos != name))
- m_regions.emplace(pos, std::move(name));
+ add_info_value(m_regions, std::move(name));
}
void software_filter_data::add_publisher(std::string const &publisher)
{
std::string name(extract_publisher(publisher));
- std::vector<std::string>::iterator const pos(std::lower_bound(m_publishers.begin(), m_publishers.end(), name));
- if ((m_publishers.end() == pos) || (*pos != name))
- m_publishers.emplace(pos, std::move(name));
+ add_info_value(m_publishers, std::move(name));
}
void software_filter_data::add_year(std::string const &year)
{
- std::vector<std::string>::iterator const pos(std::lower_bound(m_years.begin(), m_years.end(), year));
- if ((m_years.end() == pos) || (*pos != year))
- m_years.emplace(pos, year);
+ add_info_value(m_years, year);
+}
+
+void software_filter_data::add_info(software_info_item const &info)
+{
+ if (info.name() == "developer")
+ add_info_value(m_developers, info.value());
+ else if (info.name() == "distributor")
+ add_info_value(m_distributors, info.value());
+ else if (info.name() == "author")
+ add_info_value(m_authors, info.value());
+ else if (info.name() == "programmer")
+ add_info_value(m_programmers, info.value());
}
void software_filter_data::add_device_type(std::string const &device_type)
{
- std::vector<std::string>::iterator const pos(std::lower_bound(m_device_types.begin(), m_device_types.end(), device_type));
- if ((m_device_types.end() == pos) || (*pos != device_type))
- m_device_types.emplace(pos, device_type);
+ add_info_value(m_device_types, device_type);
}
void software_filter_data::add_list(std::string const &name, std::string const &description)
@@ -1707,7 +1855,7 @@ char const *machine_filter::config_name(type n)
char const *machine_filter::display_name(type n)
{
assert(COUNT > n);
- return _(MACHINE_FILTER_NAMES[n]);
+ return _("machine-filter", MACHINE_FILTER_NAMES[n]);
}
machine_filter::machine_filter()
@@ -1728,7 +1876,7 @@ char const *software_filter::config_name(type n)
char const *software_filter::display_name(type n)
{
assert(COUNT > n);
- return _(SOFTWARE_FILTER_NAMES[n]);
+ return _("software-filter", SOFTWARE_FILTER_NAMES[n]);
}
software_filter::software_filter()
@@ -1756,6 +1904,14 @@ software_filter::ptr software_filter::create(type n, software_filter_data const
return std::make_unique<years_software_filter>(data, value, file, indent);
case PUBLISHERS:
return std::make_unique<publishers_software_filter>(data, value, file, indent);
+ case DEVELOPERS:
+ return std::make_unique<developer_software_filter>(data, value, file, indent);
+ case DISTRIBUTORS:
+ return std::make_unique<distributor_software_filter>(data, value, file, indent);
+ case AUTHORS:
+ return std::make_unique<author_software_filter>(data, value, file, indent);
+ case PROGRAMMERS:
+ return std::make_unique<programmer_software_filter>(data, value, file, indent);
case SUPPORTED:
return std::make_unique<supported_software_filter>(data, value, file, indent);
case PARTIAL_SUPPORTED:
@@ -1866,31 +2022,52 @@ std::vector<std::string> tokenize(const std::string &text, char sep)
ui_software_info::ui_software_info(
- software_info const &info,
+ software_info const &sw,
software_part const &p,
game_driver const &d,
std::string const &li,
std::string const &is,
std::string const &de)
- : shortname(info.shortname()), longname(info.longname()), parentname(info.parentname())
- , year(info.year()), publisher(info.publisher())
- , supported(info.supported())
+ : shortname(sw.shortname()), longname(sw.longname()), parentname(sw.parentname())
+ , year(sw.year()), publisher(sw.publisher())
+ , supported(sw.supported())
, part(p.name())
, driver(&d)
, listname(li), interface(p.interface()), instance(is)
, startempty(0)
, parentlongname()
- , usage()
+ , infotext()
, devicetype(de)
+ , info()
+ , alttitles()
, available(false)
{
- for (feature_list_item const &feature : info.other_info())
+ info.reserve(sw.info().size());
+ bool firstinfo(true);
+ for (software_info_item const &feature : sw.info())
{
- if (feature.name() == "usage")
- {
- usage = feature.value();
- break;
- }
+ // add info for the internal UI, localising recognised
+ if (!firstinfo)
+ infotext.append(2, '\n');
+ firstinfo = false;
+ auto const found = std::lower_bound(
+ std::begin(ui::SOFTWARE_INFO_NAMES),
+ std::end(ui::SOFTWARE_INFO_NAMES),
+ feature.name().c_str(),
+ [] (std::pair<char const *, char const *> const &a, char const *b)
+ {
+ return 0 > std::strcmp(a.first, b);
+ });
+ if ((std::end(ui::SOFTWARE_INFO_NAMES) != found) && (feature.name() == found->first))
+ infotext.append(_("swlist-info", found->second));
+ else
+ infotext.append(feature.name());
+ infotext.append(1, '\n').append(feature.value());
+
+ // keep references to stuff for filtering and searching
+ auto const &ins = info.emplace_back(feature.name(), feature.value());
+ if (feature.name() == "alt_title")
+ alttitles.emplace_back(ins.value());
}
}
@@ -1899,3 +2076,67 @@ ui_software_info::ui_software_info(game_driver const &d)
: shortname(d.name), longname(d.type.fullname()), driver(&d), startempty(1), available(true)
{
}
+
+ui_software_info::ui_software_info(ui_software_info const &that)
+ : shortname(that.shortname)
+ , longname(that.longname)
+ , parentname(that.parentname)
+ , year(that.year)
+ , publisher(that.publisher)
+ , supported(that.supported)
+ , part(that.part)
+ , driver(that.driver)
+ , listname(that.listname)
+ , interface(that.interface)
+ , instance(that.instance)
+ , startempty(that.startempty)
+ , parentlongname(that.parentlongname)
+ , infotext(that.infotext)
+ , devicetype(that.devicetype)
+ , info(that.info)
+ , alttitles()
+ , available(that.available)
+{
+ // build self-referencing member
+ alttitles.reserve(that.alttitles.size());
+ for (software_info_item const &feature : info)
+ {
+ if (feature.name() == "alt_title")
+ alttitles.emplace_back(feature.value());
+ }
+}
+
+ui_software_info &ui_software_info::operator=(ui_software_info const &that)
+{
+ if (&that != this)
+ {
+ // copy simple stuff
+ shortname = that.shortname;
+ longname = that.longname;
+ parentname = that.parentname;
+ year = that.year;
+ publisher = that.publisher;
+ supported = that.supported;
+ part = that.part;
+ driver = that.driver;
+ listname = that.listname;
+ interface = that.interface;
+ instance = that.instance;
+ startempty = that.startempty;
+ parentlongname = that.parentlongname;
+ infotext = that.infotext;
+ devicetype = that.devicetype;
+ info = that.info;
+ alttitles.clear();
+ available = that.available;
+
+ // build self-referencing member
+ alttitles.reserve(that.alttitles.size());
+ for (software_info_item const &feature : info)
+ {
+ if (feature.name() == "alt_title")
+ alttitles.emplace_back(feature.value());
+ }
+ }
+ return *this;
+}