summaryrefslogtreecommitdiffstatshomepage
path: root/src/frontend/mame/ui/swlist.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/frontend/mame/ui/swlist.cpp')
-rw-r--r--src/frontend/mame/ui/swlist.cpp299
1 files changed, 179 insertions, 120 deletions
diff --git a/src/frontend/mame/ui/swlist.cpp b/src/frontend/mame/ui/swlist.cpp
index bd2aa47aee5..989147f3bb4 100644
--- a/src/frontend/mame/ui/swlist.cpp
+++ b/src/frontend/mame/ui/swlist.cpp
@@ -14,10 +14,14 @@
#include "ui/swlist.h"
#include "ui/utils.h"
+#include "corestr.h"
#include "softlist_dev.h"
+#include <locale>
+
namespace ui {
+
/***************************************************************************
CONSTANTS
***************************************************************************/
@@ -50,8 +54,8 @@ static bool is_valid_softlist_part_char(char32_t ch)
//-------------------------------------------------
menu_software_parts::menu_software_parts(mame_ui_manager &mui, render_container &container, const software_info *info, const char *interface, const software_part **part, bool other_opt, result &result)
- : menu(mui, container),
- m_result(result)
+ : menu(mui, container)
+ , m_result(result)
{
m_info = info;
m_interface = interface;
@@ -73,7 +77,7 @@ menu_software_parts::~menu_software_parts()
// populate
//-------------------------------------------------
-void menu_software_parts::populate(float &customtop, float &custombottom)
+void menu_software_parts::populate()
{
m_entries.clear();
@@ -82,18 +86,18 @@ void menu_software_parts::populate(float &customtop, float &custombottom)
software_part_menu_entry &entry1(*m_entries.emplace(m_entries.end()));
entry1.type = result::EMPTY;
entry1.part = nullptr;
- item_append(_("[empty slot]"), "", 0, &entry1);
+ item_append(_("[empty slot]"), 0, &entry1);
software_part_menu_entry &entry2(*m_entries.emplace(m_entries.end()));
entry2.type = result::FMGR;
entry2.part = nullptr;
- item_append(_("[file manager]"), "", 0, &entry2);
+ item_append(_("[file manager]"), 0, &entry2);
software_part_menu_entry &entry3(*m_entries.emplace(m_entries.end()));
entry3.type = result::SWLIST;
entry3.part = nullptr;
- item_append(_("[software list]"), "", 0, &entry3);
+ item_append(_("[software list]"), 0, &entry3);
}
for (const software_part &swpart : m_info->parts())
@@ -111,6 +115,8 @@ void menu_software_parts::populate(float &customtop, float &custombottom)
item_append(m_info->shortname(), menu_part_name, 0, &entry);
}
}
+
+ item_append(menu_item_type::SEPARATOR);
}
@@ -118,18 +124,17 @@ void menu_software_parts::populate(float &customtop, float &custombottom)
// handle
//-------------------------------------------------
-void menu_software_parts::handle()
+bool menu_software_parts::handle(event const *ev)
{
- // process the menu
- const event *event = process(0);
-
- if (event != nullptr && event->iptkey == IPT_UI_SELECT && event->itemref != nullptr)
+ if (ev && (ev->iptkey == IPT_UI_SELECT) && ev->itemref)
{
- software_part_menu_entry *entry = (software_part_menu_entry *) event->itemref;
+ software_part_menu_entry *entry = (software_part_menu_entry *)ev->itemref;
m_result = entry->type;
*m_selected_part = entry->part;
stack_pop();
}
+
+ return false;
}
@@ -144,9 +149,12 @@ void menu_software_parts::handle()
menu_software_list::menu_software_list(mame_ui_manager &mui, render_container &container, software_list_device *swlist, const char *interface, std::string &result)
: menu(mui, container), m_result(result)
{
+ set_heading(swlist->description());
+
+ set_process_flags(PROCESS_IGNOREPAUSE);
m_swlist = swlist;
m_interface = interface;
- m_ordered_by_shortname = true;
+ m_ordered_by_shortname = false;
}
@@ -160,26 +168,6 @@ menu_software_list::~menu_software_list()
//-------------------------------------------------
-// compare_entries
-//-------------------------------------------------
-
-int menu_software_list::compare_entries(const entry_info &e1, const entry_info &e2, bool shortname)
-{
- int result;
- const char *e1_basename = shortname ? e1.short_name.c_str() : e1.long_name.c_str();
- const char *e2_basename = shortname ? e2.short_name.c_str() : e2.long_name.c_str();
-
- result = core_stricmp(e1_basename, e2_basename);
- if (result == 0)
- {
- result = strcmp(e1_basename, e2_basename);
- }
-
- return result;
-}
-
-
-//-------------------------------------------------
// append_software_entry - populate a specific list
//-------------------------------------------------
@@ -202,13 +190,54 @@ void menu_software_list::append_software_entry(const software_info &swinfo)
// skip this if no new entry has been allocated (e.g. if the software has no matching interface for this image device)
if (entry_updated)
+ m_entrylist.emplace_back(std::move(entry));
+}
+
+
+//-------------------------------------------------
+// update_search - update meunu for new search text
+//-------------------------------------------------
+
+void menu_software_list::update_search(void *selectedref)
+{
+ // display the popup
+ ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_search);
+
+ // identify the selected entry
+ entry_info const *const cur_selected = (uintptr_t(selectedref) != 1)
+ ? reinterpret_cast<entry_info const *>(get_selection_ref())
+ : nullptr;
+
+ // if it's a perfect match for the current selection, don't move it
+ if (!cur_selected || core_strnicmp((m_ordered_by_shortname ? cur_selected->short_name : cur_selected->long_name).c_str(), m_search.c_str(), m_search.size()))
{
- // find the end of the list
- auto iter = m_entrylist.begin();
- while (iter != m_entrylist.end() && compare_entries(entry, *iter, m_ordered_by_shortname) >= 0)
- ++iter;
+ std::string::size_type bestmatch(0);
+ entry_info const *selected_entry(cur_selected);
+ for (auto &entry : m_entrylist)
+ {
+ // TODO: more efficient "common prefix" code
+ auto const &compare_name = m_ordered_by_shortname ? entry.short_name : entry.long_name;
+ std::string::size_type match(0);
+ for (std::string::size_type i = 1; m_search.size() >= i; ++i)
+ {
+ if (!core_strnicmp(compare_name.c_str(), m_search.c_str(), i))
+ match = i;
+ else
+ break;
+ }
+
+ if (match > bestmatch)
+ {
+ bestmatch = match;
+ selected_entry = &entry;
+ }
+ }
- m_entrylist.emplace(iter, std::move(entry));
+ if (selected_entry && (selected_entry != cur_selected))
+ {
+ set_selection((void *)selected_entry);
+ centre_selection();
+ }
}
}
@@ -217,21 +246,53 @@ void menu_software_list::append_software_entry(const software_info &swinfo)
// populate
//-------------------------------------------------
-void menu_software_list::populate(float &customtop, float &custombottom)
+void menu_software_list::populate()
{
- // clear all entries before populating
- m_entrylist.clear();
-
// build up the list of entries for the menu
- for (const software_info &swinfo : m_swlist->get_info())
- append_software_entry(swinfo);
+ if (m_entrylist.empty())
+ for (const software_info &swinfo : m_swlist->get_info())
+ append_software_entry(swinfo);
- // add an entry to change ordering
- item_append(_("Switch Item Ordering"), "", 0, ITEMREF_SWITCH_ITEM_ORDERING);
+ if (m_entrylist.size() > 1)
+ {
+ // add an entry to change ordering
+ item_append(_("Switch Item Ordering"), 0, ITEMREF_SWITCH_ITEM_ORDERING);
- // append all of the menu entries
- for (auto &entry : m_entrylist)
- item_append(entry.short_name, entry.long_name, 0, &entry);
+ // initial cursor to first entry in the list
+ set_selected_index(1);
+ }
+
+ if (m_ordered_by_shortname)
+ {
+ // short names are restricted to lowercase ASCII anyway, a dumb compare works
+ m_entrylist.sort([] (entry_info const &e1, entry_info const &e2) { return e1.short_name < e2.short_name; });
+
+ // append all of the menu entries
+ for (auto &entry : m_entrylist)
+ item_append(entry.short_name, entry.long_name, 0, &entry);
+ }
+ else
+ {
+ std::locale const lcl;
+ std::collate<wchar_t> const &coll = std::use_facet<std::collate<wchar_t> >(lcl);
+ m_entrylist.sort(
+ [&coll] (entry_info const &e1, entry_info const &e2) -> bool
+ {
+ std::wstring const xstr = wstring_from_utf8(e1.long_name);
+ std::wstring const ystr = wstring_from_utf8(e2.long_name);
+ auto const cmp = coll.compare(xstr.data(), xstr.data() + xstr.size(), ystr.data(), ystr.data() + ystr.size());
+ if (cmp)
+ return cmp < 0;
+ else
+ return e1.short_name < e2.short_name;
+ });
+
+ // append all of the menu entries
+ for (auto &entry : m_entrylist)
+ item_append(entry.long_name, entry.short_name, 0, &entry);
+ }
+
+ item_append(menu_item_type::SEPARATOR);
}
@@ -239,84 +300,79 @@ void menu_software_list::populate(float &customtop, float &custombottom)
// handle
//-------------------------------------------------
-void menu_software_list::handle()
+bool menu_software_list::handle(event const *ev)
{
- const entry_info *selected_entry = nullptr;
- int bestmatch = 0;
-
- // process the menu
- const event *event = process(0);
-
- if (event && event->itemref)
+ if (!ev)
{
- if (event->itemref == ITEMREF_SWITCH_ITEM_ORDERING && event->iptkey == IPT_UI_SELECT)
+ return false;
+ }
+ else if (ev->iptkey == IPT_UI_SELECT)
+ {
+ if (ev->itemref == ITEMREF_SWITCH_ITEM_ORDERING)
{
m_ordered_by_shortname = !m_ordered_by_shortname;
// reset the char buffer if we change ordering criterion
- m_filename_buffer.clear();
+ m_search.clear();
// reload the menu with the new order
reset(reset_options::REMEMBER_REF);
- machine().popmessage(_("Switched Order: entries now ordered by %s"), m_ordered_by_shortname ? _("shortname") : _("description"));
+ machine().popmessage(
+ m_ordered_by_shortname
+ ? _("Switched Order: entries now ordered by shortname")
+ : _("Switched Order: entries now ordered by description"));
}
- // handle selections
- else if (event->iptkey == IPT_UI_SELECT)
+ else if (ev->itemref)
{
- entry_info *info = (entry_info *) event->itemref;
+ // handle selections
+ entry_info *info = (entry_info *)ev->itemref;
m_result = info->short_name;
stack_pop();
}
- else if (event->iptkey == IPT_SPECIAL)
+ return false;
+ }
+ else if (ev->iptkey == IPT_UI_PASTE)
+ {
+ if (paste_text(m_search, m_ordered_by_shortname ? is_valid_softlist_part_char : uchar_is_printable))
{
- if (input_character(m_filename_buffer, event->unichar, &is_valid_softlist_part_char))
- {
- // display the popup
- ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer);
-
- // identify the selected entry
- entry_info const *const cur_selected = (uintptr_t(event->itemref) != 1)
- ? reinterpret_cast<entry_info const *>(get_selection_ref())
- : nullptr;
-
- // loop through all entries
- for (auto &entry : m_entrylist)
- {
- // is this entry the selected entry?
- if (cur_selected != &entry)
- {
- auto &compare_name = m_ordered_by_shortname ? entry.short_name : entry.long_name;
-
- int match = 0;
- for (int i = 0; i < m_filename_buffer.size() + 1; i++)
- {
- if (core_strnicmp(compare_name.c_str(), m_filename_buffer.c_str(), i) == 0)
- match = i;
- }
-
- if (match > bestmatch)
- {
- bestmatch = match;
- selected_entry = &entry;
- }
- }
- }
-
- if (selected_entry != nullptr && selected_entry != cur_selected)
- {
- set_selection((void *)selected_entry);
- centre_selection();
- }
- }
+ update_search(ev->itemref);
+ return true;
}
- else if (event->iptkey == IPT_UI_CANCEL)
+ else
{
- // reset the char buffer also in this case
- m_filename_buffer.clear();
- m_result = m_filename_buffer;
- stack_pop();
+ return false;
}
}
+ else if (ev->iptkey == IPT_SPECIAL)
+ {
+ if (input_character(m_search, ev->unichar, m_ordered_by_shortname ? is_valid_softlist_part_char : uchar_is_printable))
+ {
+ update_search(ev->itemref);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else if (ev->iptkey == IPT_UI_CANCEL)
+ {
+ // reset the char buffer also in this case
+ if (!m_search.empty())
+ {
+ m_search.clear();
+ ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_search);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return false;
+ }
}
@@ -332,6 +388,8 @@ void menu_software_list::handle()
menu_software::menu_software(mame_ui_manager &mui, render_container &container, const char *interface, software_list_device **result)
: menu(mui, container)
{
+ set_heading(_("Software List"));
+
m_interface = interface;
m_result = result;
}
@@ -350,12 +408,12 @@ menu_software::~menu_software()
// populate
//-------------------------------------------------
-void menu_software::populate(float &customtop, float &custombottom)
+void menu_software::populate()
{
bool have_compatible = false;
// Add original software lists for this system
- software_list_device_iterator iter(machine().config().root_device());
+ software_list_device_enumerator iter(machine().config().root_device());
for (software_list_device &swlistdev : iter)
if (swlistdev.is_original())
if (!swlistdev.get_info().empty() && m_interface != nullptr)
@@ -369,7 +427,7 @@ void menu_software::populate(float &customtop, float &custombottom)
break;
}
if (found)
- item_append(swlistdev.description(), "", 0, (void *)&swlistdev);
+ item_append(swlistdev.description(), 0, (void *)&swlistdev);
}
// add compatible software lists for this system
@@ -388,11 +446,13 @@ void menu_software::populate(float &customtop, float &custombottom)
if (found)
{
if (!have_compatible)
- item_append(_("[compatible lists]"), "", FLAG_DISABLE, nullptr);
- item_append(swlistdev.description(), "", 0, (void *)&swlistdev);
+ item_append(_("[compatible lists]"), FLAG_UI_HEADING | FLAG_DISABLE, nullptr);
+ item_append(swlistdev.description(), 0, (void *)&swlistdev);
}
have_compatible = true;
}
+
+ item_append(menu_item_type::SEPARATOR);
}
@@ -400,17 +460,16 @@ void menu_software::populate(float &customtop, float &custombottom)
// handle
//-------------------------------------------------
-void menu_software::handle()
+bool menu_software::handle(event const *ev)
{
- // process the menu
- const event *event = process(0);
-
- if (event != nullptr && event->iptkey == IPT_UI_SELECT)
+ if (ev && (ev->iptkey == IPT_UI_SELECT))
{
- //menu::stack_push<menu_software_list>(ui(), container(), (software_list_config *)event->itemref, image);
- *m_result = reinterpret_cast<software_list_device *>(event->itemref);
+ //menu::stack_push<menu_software_list>(ui(), container(), (software_list_config *)ev->itemref, image);
+ *m_result = reinterpret_cast<software_list_device *>(ev->itemref);
stack_pop();
}
+
+ return false;
}
} // namespace ui