diff options
author | 2021-10-31 12:31:16 +1100 | |
---|---|---|
committer | 2021-10-31 12:31:16 +1100 | |
commit | d64ea5331b2312f81df464fb22dcef0191216d86 (patch) | |
tree | a3f3784371da401e6a675e5b6b9734b88281a08d /src | |
parent | cfffc54b61cabc5ef9533396bf87324eb5eeb63e (diff) |
-frontend: Refactored menu event handling and fixed a number of issues. (#8777)
* Moved common code for drawing about box, info viewer, and other text box menus to a base class; removed the last of the info viewer logic and the multi-line item hack from the base menu class.
* Added previous/next group navigation for general inputs and plugin input selection menus.
* Moved message catalog logic to lib/util, allowing osd and emu to use localised messages.
* Made the base menu class use the UI manager’s feature for holding session state rather than a static map and mutex.
* Improved menu event handling model, and fixed many issues, particularly with menus behaving badly when hidden/shown.
* Added better support for menus that don’t participate in the usual menu stack, like the menuless sliders and the save/load state menus.
* Made a number of menus refresh state when being shown after being hidden (fixes MT08121 among other issues).
* Fixed indication of mounted slot option in the slot option details menu.
* Improved appearance of background menus when emulation isn't running - draw all menus in the stack, and darken the background menus to make the edges of the active menu clearer.
* Fixed locale issues in -listxml.
-debugger: Made GUI debuggers more uniform.
* Added new memory view features to Win32 debugger.
* Fixed spelling of hexadecimal in Cocoa debugger and added decimal address option.
* Fixed duplicate keyboard shortcut in Cocoa debugger (Shift-Cmd-D was both new device window and 64-bit float format).
* Made keyboard shortcuts slightly more consistent across debuggers.
-plugins: Moved input selection menu and sequence polling code to a common library. Fixed the issue that prevented keyboard inputs being mapped with -steadykey on.
-docs: Started adding some documentation for MAME's internal UI, and updated the list of example front-ends.
-Regenerated message catalog sources. For translators, the new strings are mostly:
* The names of the inputs provided by the OS-dependent layer for things like fullscreen and video features. These show up in the user interface inputs menu.
* The names for automatically generated views. These show up in the video options menu - test with a system with a lot of screens to see more variants.
* The input macro plugin UI.
* A few format strings for analog input assignments.
* A few strings for the about box header.
Diffstat (limited to 'src')
97 files changed, 2466 insertions, 2161 deletions
diff --git a/src/emu/inpttype.ipp b/src/emu/inpttype.ipp index 1e99615b873..235f1c421d5 100644 --- a/src/emu/inpttype.ipp +++ b/src/emu/inpttype.ipp @@ -8,6 +8,8 @@ ***************************************************************************/ +#include "util/language.h" + /*************************************************************************** BUILT-IN CORE MAPPINGS @@ -15,12 +17,6 @@ namespace { -// can't get frontend/mame/language.h from here -#ifndef N_p -#define N_p(ctx, msg) (msg) -#endif - - #define CORE_INPUT_TYPES_P1 \ CORE_INPUT_TYPES_BEGIN(p1) \ INPUT_PORT_DIGITAL_TYPE( 1, PLAYER1, JOYSTICK_UP, N_p("input-name", "P1 Up"), input_seq(KEYCODE_UP, input_seq::or_code, JOYCODE_Y_UP_SWITCH_INDEXED(0)) ) \ diff --git a/src/emu/render.cpp b/src/emu/render.cpp index ec718d25df5..0fef6bafe41 100644 --- a/src/emu/render.cpp +++ b/src/emu/render.cpp @@ -51,6 +51,7 @@ #include "ui/uimain.h" #include "util/ioprocsfilter.h" +#include "util/language.h" #include "util/path.h" #include "util/xmlfile.h" @@ -1693,6 +1694,8 @@ void render_target::load_layout_files(util::xml::data_node const &rootnode, bool void render_target::load_additional_layout_files(const char *basename, bool have_artwork) { + using util::lang_translate; + m_external_artwork = false; // if override_artwork defined, load that and skip artwork other than default @@ -1841,7 +1844,7 @@ void render_target::load_additional_layout_files(const char *basename, bool have viewnode->set_attribute( "name", util::string_format( - "Screen %1$u Standard (%2$u:%3$u)", + _("view-name", "Screen %1$u Standard (%2$u:%3$u)"), i, screens[i].physical_x(), screens[i].physical_y()).c_str()); util::xml::data_node *const screennode(viewnode->add_child("screen", nullptr)); if (!screennode) @@ -1867,7 +1870,7 @@ void render_target::load_additional_layout_files(const char *basename, bool have viewnode->set_attribute( "name", util::string_format( - "Screen %1$u Pixel Aspect (%2$u:%3$u)", + _("view-name", "Screen %1$u Pixel Aspect (%2$u:%3$u)"), i, screens[i].native_x(), screens[i].native_y()).c_str()); util::xml::data_node *const screennode(viewnode->add_child("screen", nullptr)); if (!screennode) @@ -1889,7 +1892,7 @@ void render_target::load_additional_layout_files(const char *basename, bool have util::xml::data_node *const viewnode(layoutnode->add_child("view", nullptr)); if (!viewnode) throw emu_fatalerror("Couldn't create XML node??"); - viewnode->set_attribute("name", "Cocktail"); + viewnode->set_attribute("name", _("view-name", "Cocktail")); util::xml::data_node *const mirrornode(viewnode->add_child("screen", nullptr)); if (!mirrornode) @@ -2009,10 +2012,10 @@ void render_target::load_additional_layout_files(const char *basename, bool have }; // generate linear views - generate_view("Left-to-Right", screens.size(), false, [] (unsigned x, unsigned y) { return x; }); - generate_view("Left-to-Right (Gapless)", screens.size(), true, [] (unsigned x, unsigned y) { return x; }); - generate_view("Top-to-Bottom", 1U, false, [] (unsigned x, unsigned y) { return y; }); - generate_view("Top-to-Bottom (Gapless)", 1U, true, [] (unsigned x, unsigned y) { return y; }); + generate_view(_("view-name", "Left-to-Right"), screens.size(), false, [] (unsigned x, unsigned y) { return x; }); + generate_view(_("view-name", "Left-to-Right (Gapless)"), screens.size(), true, [] (unsigned x, unsigned y) { return x; }); + generate_view(_("view-name", "Top-to-Bottom"), 1U, false, [] (unsigned x, unsigned y) { return y; }); + generate_view(_("view-name", "Top-to-Bottom (Gapless)"), 1U, true, [] (unsigned x, unsigned y) { return y; }); // generate fake cocktail view for systems with two screens if (screens.size() == 2U) @@ -2024,7 +2027,7 @@ void render_target::load_additional_layout_files(const char *basename, bool have util::xml::data_node *const viewnode(layoutnode->add_child("view", nullptr)); if (!viewnode) throw emu_fatalerror("Couldn't create XML node??"); - viewnode->set_attribute("name", "Cocktail"); + viewnode->set_attribute("name", _("view-name", "Cocktail")); util::xml::data_node *const mirrornode(viewnode->add_child("screen", nullptr)); if (!mirrornode) @@ -2063,7 +2066,7 @@ void render_target::load_additional_layout_files(const char *basename, bool have if (!remainder || (((majdim + 1) / 2) <= remainder)) { generate_view( - util::string_format("%1$u\xC3\x97%2$u Left-to-Right, Top-to-Bottom", majdim, mindim).c_str(), + util::string_format(_("view-name", u8"%1$u×%2$u Left-to-Right, Top-to-Bottom"), majdim, mindim).c_str(), majdim, false, [&screens, majdim] (unsigned x, unsigned y) @@ -2072,7 +2075,7 @@ void render_target::load_additional_layout_files(const char *basename, bool have return (screens.size() > i) ? int(i) : -1; }); generate_view( - util::string_format("%1$u\xC3\x97%2$u Left-to-Right, Top-to-Bottom (Gapless)", majdim, mindim).c_str(), + util::string_format(_("view-name", u8"%1$u×%2$u Left-to-Right, Top-to-Bottom (Gapless)"), majdim, mindim).c_str(), majdim, true, [&screens, majdim] (unsigned x, unsigned y) @@ -2081,7 +2084,7 @@ void render_target::load_additional_layout_files(const char *basename, bool have return (screens.size() > i) ? int(i) : -1; }); generate_view( - util::string_format("%1$u\xC3\x97%2$u Top-to-Bottom, Left-to-Right", mindim, majdim).c_str(), + util::string_format(_("view-name", u8"%1$u×%2$u Top-to-Bottom, Left-to-Right"), mindim, majdim).c_str(), mindim, false, [&screens, majdim] (unsigned x, unsigned y) @@ -2090,7 +2093,7 @@ void render_target::load_additional_layout_files(const char *basename, bool have return (screens.size() > i) ? int(i) : -1; }); generate_view( - util::string_format("%1$u\xC3\x97%2$u Top-to-Bottom, Left-to-Right (Gapless)", mindim, majdim).c_str(), + util::string_format(_("view-name", u8"%1$u×%2$u Top-to-Bottom, Left-to-Right (Gapless)"), mindim, majdim).c_str(), mindim, true, [&screens, majdim] (unsigned x, unsigned y) diff --git a/src/frontend/mame/clifront.cpp b/src/frontend/mame/clifront.cpp index 19160cc9784..312c96eff65 100644 --- a/src/frontend/mame/clifront.cpp +++ b/src/frontend/mame/clifront.cpp @@ -81,6 +81,7 @@ namespace { + //************************************************************************** // COMMAND-LINE OPTIONS //************************************************************************** diff --git a/src/frontend/mame/infoxml.cpp b/src/frontend/mame/infoxml.cpp index cb9f5ff56a7..8ff033194bf 100644 --- a/src/frontend/mame/infoxml.cpp +++ b/src/frontend/mame/infoxml.cpp @@ -30,6 +30,7 @@ #include <cctype> #include <cstring> #include <future> +#include <locale> #include <queue> #include <type_traits> #include <unordered_set> @@ -100,6 +101,7 @@ private: typedef std::set<std::add_pointer_t<device_type>, device_type_compare> device_type_set; std::string normalize_string(const char *string); +std::string normalize_string(std::string_view string); // internal helper void output_header(std::ostream &out, bool dtd); @@ -440,6 +442,11 @@ void info_xml_creator::output(std::ostream &out, const std::function<bool(const device_type_set m_dev_set; }; + // TODO: maybe not the best place for this as it affects the stream passed in + // if the device part is threaded, the local streams used by the tasks can be + // imbued and the stream passed in can be left alone + out.imbue(std::locale::classic()); + // prepare a driver enumerator and the queue driver_enumerator drivlist(m_lookup_options); device_filter devfilter(filter); @@ -491,6 +498,7 @@ void info_xml_creator::output(std::ostream &out, const std::function<bool(const { prepared_info result; std::ostringstream stream; + stream.imbue(std::locale::classic()); // output each of the drivers for (const game_driver &driver : drivers) @@ -568,26 +576,30 @@ namespace std::string normalize_string(const char *string) { - std::ostringstream stream; + if (string) + return normalize_string(std::string_view(string)); + else + return std::string(); +} + +std::string normalize_string(std::string_view string) +{ + std::string result; + result.reserve(string.length()); - if (string != nullptr) + for (char ch : string) { - while (*string) + switch (ch) { - switch (*string) - { - case '\"': stream << """; break; - case '&': stream << "&"; break; - case '<': stream << "<"; break; - case '>': stream << ">"; break; - default: - stream << *string; - break; - } - ++string; + case '\"': result.append("""); break; + case '&': result.append("&"); break; + case '<': result.append("<"); break; + case '>': result.append(">"); break; + default: result.append(1, ch); break; } } - return stream.str(); + + return result; } @@ -647,7 +659,8 @@ void output_header(std::ostream &out, bool dtd) } // top-level tag - out << util::string_format("<%s build=\"%s\" debug=\"" + util::stream_format(out, + "<%s build=\"%s\" debug=\"" #ifdef MAME_DEBUG "yes" #else @@ -667,7 +680,7 @@ void output_header(std::ostream &out, bool dtd) void output_footer(std::ostream &out) { // close the top level tag - out << util::string_format("</%s>\n", XML_ROOT); + util::stream_format(out, "</%s>\n", XML_ROOT); } @@ -726,14 +739,14 @@ void output_one(std::ostream &out, driver_enumerator &drivlist, const game_drive } // print the header and the machine name - out << util::string_format("\t<%s name=\"%s\"", XML_TOP, normalize_string(driver.name)); + util::stream_format(out, "\t<%s name=\"%s\"", XML_TOP, normalize_string(driver.name)); // strip away any path information from the source_file and output it const char *start = strrchr(driver.type.source(), '/'); if (!start) start = strrchr(driver.type.source(), '\\'); start = start ? (start + 1) : driver.type.source(); - out << util::string_format(" sourcefile=\"%s\"", normalize_string(start)); + util::stream_format(out, " sourcefile=\"%s\"", normalize_string(start)); // append bios and runnable flags if (driver.flags & machine_flags::IS_BIOS_ROOT) @@ -744,9 +757,9 @@ void output_one(std::ostream &out, driver_enumerator &drivlist, const game_drive // display clone information int clone_of = drivlist.find(driver.parent); if (clone_of != -1 && !(drivlist.driver(clone_of).flags & machine_flags::IS_BIOS_ROOT)) - out << util::string_format(" cloneof=\"%s\"", normalize_string(drivlist.driver(clone_of).name)); + util::stream_format(out, " cloneof=\"%s\"", normalize_string(drivlist.driver(clone_of).name)); if (clone_of != -1) - out << util::string_format(" romof=\"%s\"", normalize_string(drivlist.driver(clone_of).name)); + util::stream_format(out, " romof=\"%s\"", normalize_string(drivlist.driver(clone_of).name)); // display sample information and close the game tag output_sampleof(out, config.root_device()); @@ -754,15 +767,15 @@ void output_one(std::ostream &out, driver_enumerator &drivlist, const game_drive // output game description if (driver.type.fullname() != nullptr) - out << util::string_format("\t\t<description>%s</description>\n", normalize_string(driver.type.fullname())); + util::stream_format(out, "\t\t<description>%s</description>\n", normalize_string(driver.type.fullname())); // print the year only if is a number or another allowed character (? or +) - if (driver.year != nullptr && strspn(driver.year, "0123456789?+") == strlen(driver.year)) - out << util::string_format("\t\t<year>%s</year>\n", normalize_string(driver.year)); + if (driver.year && strspn(driver.year, "0123456789?+") == strlen(driver.year)) + util::stream_format(out, "\t\t<year>%s</year>\n", normalize_string(driver.year)); // print the manufacturer information if (driver.manufacturer != nullptr) - out << util::string_format("\t\t<manufacturer>%s</manufacturer>\n", normalize_string(driver.manufacturer)); + util::stream_format(out, "\t\t<manufacturer>%s</manufacturer>\n", normalize_string(driver.manufacturer)); // now print various additional information output_bios(out, config.root_device()); @@ -785,7 +798,7 @@ void output_one(std::ostream &out, driver_enumerator &drivlist, const game_drive output_ramoptions(out, config.root_device()); // close the topmost tag - out << util::string_format("\t</%s>\n", XML_TOP); + util::stream_format(out, "\t</%s>\n", XML_TOP); } @@ -824,15 +837,16 @@ void output_one_device(std::ostream &out, machine_config &config, device_t &devi } // start to output info - out << util::string_format("\t<%s name=\"%s\"", XML_TOP, normalize_string(device.shortname())); + util::stream_format(out, "\t<%s name=\"%s\"", XML_TOP, normalize_string(device.shortname())); std::string src(device.source()); strreplace(src,"../", ""); - out << util::string_format(" sourcefile=\"%s\" isdevice=\"yes\" runnable=\"no\"", normalize_string(src.c_str())); + util::stream_format(out, " sourcefile=\"%s\" isdevice=\"yes\" runnable=\"no\"", normalize_string(src)); auto const parent(device.type().parent_rom_device_type()); if (parent) - out << util::string_format(" romof=\"%s\"", normalize_string(parent->shortname())); + util::stream_format(out, " romof=\"%s\"", normalize_string(parent->shortname())); output_sampleof(out, device); - out << ">\n" << util::string_format("\t\t<description>%s</description>\n", normalize_string(device.name())); + out << ">\n"; + util::stream_format(out, "\t\t<description>%s</description>\n", normalize_string(device.name())); output_bios(out, device); output_rom(out, config, nullptr, nullptr, device); @@ -854,7 +868,7 @@ void output_one_device(std::ostream &out, machine_config &config, device_t &devi output_images(out, device, devtag); output_slots(out, config, device, devtag, nullptr); output_software_lists(out, device, devtag); - out << util::string_format("\t</%s>\n", XML_TOP); + util::stream_format(out, "\t</%s>\n", XML_TOP); } @@ -909,7 +923,7 @@ void output_device_refs(std::ostream &out, device_t &root) { for (device_t &device : device_enumerator(root)) if (&device != &root) - out << util::string_format("\t\t<device_ref name=\"%s\"/>\n", normalize_string(device.shortname())); + util::stream_format(out, "\t\t<device_ref name=\"%s\"/>\n", normalize_string(device.shortname())); } @@ -926,7 +940,7 @@ void output_sampleof(std::ostream &out, device_t &device) samples_iterator sampiter(samples); if (sampiter.altbasename() != nullptr) { - out << util::string_format(" sampleof=\"%s\"", normalize_string(sampiter.altbasename())); + util::stream_format(out, " sampleof=\"%s\"", normalize_string(sampiter.altbasename())); // must stop here, as there can only be one attribute of the same name return; @@ -954,8 +968,8 @@ void output_bios(std::ostream &out, device_t const &device) { // output extracted name and descriptions' out << "\t\t<biosset"; - out << util::string_format(" name=\"%s\"", normalize_string(bios.get_name())); - out << util::string_format(" description=\"%s\"", normalize_string(bios.get_description())); + util::stream_format(out, " name=\"%s\"", normalize_string(bios.get_name())); + util::stream_format(out, " description=\"%s\"", normalize_string(bios.get_description())); if (defaultname && !std::strcmp(defaultname, bios.get_name())) out << " default=\"yes\""; out << "/>\n"; @@ -1062,13 +1076,13 @@ void output_rom(std::ostream &out, machine_config &config, driver_enumerator *dr // add name, merge, bios, and size tags char const *const name(rom->name); if (name && name[0]) - out << util::string_format(" name=\"%s\"", normalize_string(name)); + util::stream_format(out, " name=\"%s\"", normalize_string(name)); if (merge_name) - out << util::string_format(" merge=\"%s\"", normalize_string(merge_name)); + util::stream_format(out, " merge=\"%s\"", normalize_string(merge_name)); if (bios_name) - out << util::string_format(" bios=\"%s\"", normalize_string(bios_name)); + util::stream_format(out, " bios=\"%s\"", normalize_string(bios_name)); if (!is_disk) - out << util::string_format(" size=\"%u\"", rom_file_size(rom)); + util::stream_format(out, " size=\"%u\"", rom_file_size(rom)); // dump checksum information only if there is a known dump if (!hashes.flag(util::hash_collection::FLAG_NO_DUMP)) @@ -1077,17 +1091,17 @@ void output_rom(std::ostream &out, machine_config &config, driver_enumerator *dr out << " status=\"nodump\""; // append a region name - out << util::string_format(" region=\"%s\"", region->name); + util::stream_format(out, " region=\"%s\"", region->name); if (!is_disk) { // for non-disk entries, print offset - out << util::string_format(" offset=\"%x\"", ROM_GETOFFSET(rom)); + util::stream_format(out, " offset=\"%x\"", ROM_GETOFFSET(rom)); } else { // for disk entries, add the disk index - out << util::string_format(" index=\"%x\" writable=\"%s\"", DISK_GETINDEX(rom), DISK_ISREADONLY(rom) ? "no" : "yes"); + util::stream_format(out, " index=\"%x\" writable=\"%s\"", DISK_GETINDEX(rom), DISK_ISREADONLY(rom) ? "no" : "yes"); } // add optional flag @@ -1120,7 +1134,7 @@ void output_sample(std::ostream &out, device_t &device) continue; // output the sample name - out << util::string_format("\t\t<sample name=\"%s\"/>\n", normalize_string(samplename)); + util::stream_format(out, "\t\t<sample name=\"%s\"/>\n", normalize_string(samplename)); } } } @@ -1143,9 +1157,9 @@ void output_chips(std::ostream &out, device_t &device, const char *root_tag) out << "\t\t<chip"; out << " type=\"cpu\""; - out << util::string_format(" tag=\"%s\"", normalize_string(newtag.c_str())); - out << util::string_format(" name=\"%s\"", normalize_string(exec.device().name())); - out << util::string_format(" clock=\"%d\"", exec.device().clock()); + util::stream_format(out, " tag=\"%s\"", normalize_string(newtag)); + util::stream_format(out, " name=\"%s\"", normalize_string(exec.device().name())); + util::stream_format(out, " clock=\"%d\"", exec.device().clock()); out << "/>\n"; } } @@ -1160,10 +1174,10 @@ void output_chips(std::ostream &out, device_t &device, const char *root_tag) out << "\t\t<chip"; out << " type=\"audio\""; - out << util::string_format(" tag=\"%s\"", normalize_string(newtag.c_str())); - out << util::string_format(" name=\"%s\"", normalize_string(sound.device().name())); + util::stream_format(out, " tag=\"%s\"", normalize_string(newtag)); + util::stream_format(out, " name=\"%s\"", normalize_string(sound.device().name())); if (sound.device().clock() != 0) - out << util::string_format(" clock=\"%d\"", sound.device().clock()); + util::stream_format(out, " clock=\"%d\"", sound.device().clock()); out << "/>\n"; } } @@ -1185,7 +1199,7 @@ void output_display(std::ostream &out, device_t &device, machine_flags::type con std::string newtag(screendev.tag()), oldtag(":"); newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); - out << util::string_format("\t\t<display tag=\"%s\"", normalize_string(newtag.c_str())); + util::stream_format(out, "\t\t<display tag=\"%s\"", normalize_string(newtag)); switch (screendev.screen_type()) { @@ -1229,12 +1243,12 @@ void output_display(std::ostream &out, device_t &device, machine_flags::type con if (screendev.screen_type() != SCREEN_TYPE_VECTOR) { const rectangle &visarea = screendev.visible_area(); - out << util::string_format(" width=\"%d\"", visarea.width()); - out << util::string_format(" height=\"%d\"", visarea.height()); + util::stream_format(out, " width=\"%d\"", visarea.width()); + util::stream_format(out, " height=\"%d\"", visarea.height()); } // output refresh rate - out << util::string_format(" refresh=\"%f\"", ATTOSECONDS_TO_HZ(screendev.refresh_attoseconds())); + util::stream_format(out, " refresh=\"%f\"", ATTOSECONDS_TO_HZ(screendev.refresh_attoseconds())); // output raw video parameters only for games that are not vector // and had raw parameters specified @@ -1242,13 +1256,13 @@ void output_display(std::ostream &out, device_t &device, machine_flags::type con { int pixclock = screendev.width() * screendev.height() * ATTOSECONDS_TO_HZ(screendev.refresh_attoseconds()); - out << util::string_format(" pixclock=\"%d\"", pixclock); - out << util::string_format(" htotal=\"%d\"", screendev.width()); - out << util::string_format(" hbend=\"%d\"", screendev.visible_area().min_x); - out << util::string_format(" hbstart=\"%d\"", screendev.visible_area().max_x+1); - out << util::string_format(" vtotal=\"%d\"", screendev.height()); - out << util::string_format(" vbend=\"%d\"", screendev.visible_area().min_y); - out << util::string_format(" vbstart=\"%d\"", screendev.visible_area().max_y+1); + util::stream_format(out, " pixclock=\"%d\"", pixclock); + util::stream_format(out, " htotal=\"%d\"", screendev.width()); + util::stream_format(out, " hbend=\"%d\"", screendev.visible_area().min_x); + util::stream_format(out, " hbstart=\"%d\"", screendev.visible_area().max_x+1); + util::stream_format(out, " vtotal=\"%d\"", screendev.height()); + util::stream_format(out, " vbend=\"%d\"", screendev.visible_area().min_y); + util::stream_format(out, " vbstart=\"%d\"", screendev.visible_area().max_y+1); } out << " />\n"; } @@ -1271,7 +1285,7 @@ void output_sound(std::ostream &out, device_t &device) if (snditer.first() == nullptr) speakers = 0; - out << util::string_format("\t\t<sound channels=\"%d\"/>\n", speakers); + util::stream_format(out, "\t\t<sound channels=\"%d\"/>\n", speakers); } @@ -1297,7 +1311,7 @@ void output_ioport_condition(std::ostream &out, const ioport_condition &conditio case ioport_condition::NOTLESSTHAN: rel = "ge"; break; } - out << util::string_format("<condition tag=\"%s\" mask=\"%u\" relation=\"%s\" value=\"%u\"/>\n", normalize_string(condition.tag()), condition.mask(), rel, condition.value()); + util::stream_format(out, "<condition tag=\"%s\" mask=\"%u\" relation=\"%s\" value=\"%u\"/>\n", normalize_string(condition.tag()), condition.mask(), rel, condition.value()); } //------------------------------------------------- @@ -1700,13 +1714,13 @@ void output_input(std::ostream &out, const ioport_list &portlist) // Output the input info // First basic info out << "\t\t<input"; - out << util::string_format(" players=\"%d\"", nplayer); + util::stream_format(out, " players=\"%d\"", nplayer); if (ncoin != 0) - out << util::string_format(" coins=\"%d\"", ncoin); + util::stream_format(out, " coins=\"%d\"", ncoin); if (service) - out << util::string_format(" service=\"yes\""); + util::stream_format(out, " service=\"yes\""); if (tilt) - out << util::string_format(" tilt=\"yes\""); + util::stream_format(out, " tilt=\"yes\""); out << ">\n"; // Then controller specific ones @@ -1716,21 +1730,21 @@ void output_input(std::ostream &out, const ioport_list &portlist) //printf("type %s - player %d - buttons %d\n", elem.type, elem.player, elem.nbuttons); if (elem.analog) { - out << util::string_format("\t\t\t<control type=\"%s\"", normalize_string(elem.type)); + util::stream_format(out, "\t\t\t<control type=\"%s\"", normalize_string(elem.type)); if (nplayer > 1) - out << util::string_format(" player=\"%d\"", elem.player); + util::stream_format(out, " player=\"%d\"", elem.player); if (elem.nbuttons > 0) { - out << util::string_format(" buttons=\"%d\"", strcmp(elem.type, "stick") ? elem.nbuttons : elem.maxbuttons); + util::stream_format(out, " buttons=\"%d\"", strcmp(elem.type, "stick") ? elem.nbuttons : elem.maxbuttons); if (elem.reqbuttons < elem.nbuttons) - out << util::string_format(" reqbuttons=\"%d\"", elem.reqbuttons); + util::stream_format(out, " reqbuttons=\"%d\"", elem.reqbuttons); } if (elem.min != 0 || elem.max != 0) - out << util::string_format(" minimum=\"%d\" maximum=\"%d\"", elem.min, elem.max); + util::stream_format(out, " minimum=\"%d\" maximum=\"%d\"", elem.min, elem.max); if (elem.sensitivity != 0) - out << util::string_format(" sensitivity=\"%d\"", elem.sensitivity); + util::stream_format(out, " sensitivity=\"%d\"", elem.sensitivity); if (elem.keydelta != 0) - out << util::string_format(" keydelta=\"%d\"", elem.keydelta); + util::stream_format(out, " keydelta=\"%d\"", elem.keydelta); if (elem.reverse) out << " reverse=\"yes\""; @@ -1742,14 +1756,14 @@ void output_input(std::ostream &out, const ioport_list &portlist) if (elem.helper[0] == 0 && elem.helper[1] != 0) { elem.helper[0] = elem.helper[1]; elem.helper[1] = 0; } if (elem.helper[1] == 0 && elem.helper[2] != 0) { elem.helper[1] = elem.helper[2]; elem.helper[2] = 0; } const char *joys = (elem.helper[2] != 0) ? "triple" : (elem.helper[1] != 0) ? "double" : ""; - out << util::string_format("\t\t\t<control type=\"%s%s\"", joys, normalize_string(elem.type)); + util::stream_format(out, "\t\t\t<control type=\"%s%s\"", joys, normalize_string(elem.type)); if (nplayer > 1) - out << util::string_format(" player=\"%d\"", elem.player); + util::stream_format(out, " player=\"%d\"", elem.player); if (elem.nbuttons > 0) { - out << util::string_format(" buttons=\"%d\"", strcmp(elem.type, "joy") ? elem.nbuttons : elem.maxbuttons); + util::stream_format(out, " buttons=\"%d\"", strcmp(elem.type, "joy") ? elem.nbuttons : elem.maxbuttons); if (elem.reqbuttons < elem.nbuttons) - out << util::string_format(" reqbuttons=\"%d\"", elem.reqbuttons); + util::stream_format(out, " reqbuttons=\"%d\"", elem.reqbuttons); } for (int lp = 0; lp < 3 && elem.helper[lp] != 0; lp++) { @@ -1759,7 +1773,7 @@ void output_input(std::ostream &out, const ioport_list &portlist) switch (elem.helper[lp] & (DIR_UP | DIR_DOWN | DIR_LEFT | DIR_RIGHT)) { case DIR_UP | DIR_DOWN | DIR_LEFT | DIR_RIGHT: - helper = string_format("%d", (elem.ways == 0) ? 8 : elem.ways); + helper = util::string_format(std::locale::classic(), "%d", (elem.ways == 0) ? 8 : elem.ways); ways = helper.c_str(); break; case DIR_LEFT | DIR_RIGHT: @@ -1784,7 +1798,7 @@ void output_input(std::ostream &out, const ioport_list &portlist) ways = "strange2"; break; } - out << util::string_format(" ways%s=\"%s\"", plural, ways); + util::stream_format(out, " ways%s=\"%s\"", plural, ways); } out << "/>\n"; } @@ -1811,15 +1825,15 @@ void output_switches(std::ostream &out, const ioport_list &portlist, const char // output the switch name information std::string const normalized_field_name(normalize_string(field.name())); - std::string const normalized_newtag(normalize_string(newtag.c_str())); - out << util::string_format("\t\t<%s name=\"%s\" tag=\"%s\" mask=\"%u\">\n", outertag, normalized_field_name.c_str(), normalized_newtag.c_str(), field.mask()); + std::string const normalized_newtag(normalize_string(newtag)); + util::stream_format(out, "\t\t<%s name=\"%s\" tag=\"%s\" mask=\"%u\">\n", outertag, normalized_field_name, normalized_newtag, field.mask()); if (!field.condition().none()) output_ioport_condition(out, field.condition(), 3); // loop over locations for (ioport_diplocation const &diploc : field.diplocations()) { - out << util::string_format("\t\t\t<%s name=\"%s\" number=\"%u\"", loctag, normalize_string(diploc.name()), diploc.number()); + util::stream_format(out, "\t\t\t<%s name=\"%s\" number=\"%u\"", loctag, normalize_string(diploc.name()), diploc.number()); if (diploc.inverted()) out << " inverted=\"yes\""; out << "/>\n"; @@ -1828,7 +1842,7 @@ void output_switches(std::ostream &out, const ioport_list &portlist, const char // loop over settings for (ioport_setting const &setting : field.settings()) { - out << util::string_format("\t\t\t<%s name=\"%s\" value=\"%u\"", innertag, normalize_string(setting.name()), setting.value()); + util::stream_format(out, "\t\t\t<%s name=\"%s\" value=\"%u\"", innertag, normalize_string(setting.name()), setting.value()); if (setting.value() == field.defvalue()) out << " default=\"yes\""; if (setting.condition().none()) @@ -1839,12 +1853,12 @@ void output_switches(std::ostream &out, const ioport_list &portlist, const char { out << ">\n"; output_ioport_condition(out, setting.condition(), 4); - out << util::string_format("\t\t\t</%s>\n", innertag); + util::stream_format(out, "\t\t\t</%s>\n", innertag); } } // terminate the switch entry - out << util::string_format("\t\t</%s>\n", outertag); + util::stream_format(out, "\t\t</%s>\n", outertag); } } @@ -1857,13 +1871,13 @@ void output_ports(std::ostream &out, const ioport_list &portlist) // cycle through ports for (auto &port : portlist) { - out << util::string_format("\t\t<port tag=\"%s\">\n", normalize_string(port.second->tag())); + util::stream_format(out, "\t\t<port tag=\"%s\">\n", normalize_string(port.second->tag())); for (ioport_field const &field : port.second->fields()) { if (field.is_analog()) - out << util::string_format("\t\t\t<analog mask=\"%u\"/>\n", field.mask()); + util::stream_format(out, "\t\t\t<analog mask=\"%u\"/>\n", field.mask()); } - out << util::string_format("\t\t</port>\n"); + util::stream_format(out, "\t\t</port>\n"); } } @@ -1880,7 +1894,7 @@ void output_adjusters(std::ostream &out, const ioport_list &portlist) for (ioport_field const &field : port.second->fields()) if (field.type() == IPT_ADJUSTER) { - out << util::string_format("\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", normalize_string(field.name()), field.defvalue()); + util::stream_format(out, "\t\t<adjuster name=\"%s\" default=\"%d\"/>\n", normalize_string(field.name()), field.defvalue()); } } @@ -1955,7 +1969,7 @@ void output_features(std::ostream &out, device_type type, device_t::feature_type { if (flags & feature.first) { - out << util::string_format("\t\t<feature type=\"%s\"", feature.second); + util::stream_format(out, "\t\t<feature type=\"%s\"", feature.second); if (type.unemulated_features() & feature.first) { out << " status=\"unemulated\""; @@ -1991,11 +2005,11 @@ void output_images(std::ostream &out, device_t &device, const char *root_tag) newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); // print m_output device type - out << util::string_format("\t\t<device type=\"%s\"", normalize_string(imagedev.image_type_name())); + util::stream_format(out, "\t\t<device type=\"%s\"", normalize_string(imagedev.image_type_name())); // does this device have a tag? if (imagedev.device().tag()) - out << util::string_format(" tag=\"%s\"", normalize_string(newtag.c_str())); + util::stream_format(out, " tag=\"%s\"", normalize_string(newtag)); // is this device available as media switch? if (!loadable) @@ -2006,7 +2020,7 @@ void output_images(std::ostream &out, device_t &device, const char *root_tag) out << " mandatory=\"1\""; if (imagedev.image_interface() && imagedev.image_interface()[0]) - out << util::string_format(" interface=\"%s\"", normalize_string(imagedev.image_interface())); + util::stream_format(out, " interface=\"%s\"", normalize_string(imagedev.image_interface())); // close the XML tag out << ">\n"; @@ -2017,8 +2031,8 @@ void output_images(std::ostream &out, device_t &device, const char *root_tag) char const *const shortname = imagedev.brief_instance_name().c_str(); out << "\t\t\t<instance"; - out << util::string_format(" name=\"%s\"", normalize_string(name)); - out << util::string_format(" briefname=\"%s\"", normalize_string(shortname)); + util::stream_format(out, " name=\"%s\"", normalize_string(name)); + util::stream_format(out, " briefname=\"%s\"", normalize_string(shortname)); out << "/>\n"; char const *extensions(imagedev.file_extensions()); @@ -2027,7 +2041,7 @@ void output_images(std::ostream &out, device_t &device, const char *root_tag) char const *end(extensions); while (*end && (',' != *end)) ++end; - out << util::string_format("\t\t\t<extension name=\"%s\"/>\n", normalize_string(std::string(extensions, end).c_str())); + util::stream_format(out, "\t\t\t<extension name=\"%s\"/>\n", normalize_string(std::string_view(extensions, end - extensions))); extensions = *end ? (end + 1) : nullptr; } } @@ -2056,7 +2070,7 @@ void output_slots(std::ostream &out, machine_config &config, device_t &device, c // print m_output device type if (listed) - out << util::string_format("\t\t<slot name=\"%s\">\n", normalize_string(newtag.c_str())); + util::stream_format(out, "\t\t<slot name=\"%s\">\n", normalize_string(newtag)); for (auto &option : slot.option_list()) { @@ -2071,9 +2085,9 @@ void output_slots(std::ostream &out, machine_config &config, device_t &device, c if (listed && option.second->selectable()) { - out << util::string_format("\t\t\t<slotoption name=\"%s\"", normalize_string(option.second->name())); - out << util::string_format(" devname=\"%s\"", normalize_string(dev->shortname())); - if (slot.default_option() != nullptr && strcmp(slot.default_option(), option.second->name())==0) + util::stream_format(out, "\t\t\t<slotoption name=\"%s\"", normalize_string(option.second->name())); + util::stream_format(out, " devname=\"%s\"", normalize_string(dev->shortname())); + if (slot.default_option() && !strcmp(slot.default_option(), option.second->name())) out << " default=\"yes\""; out << "/>\n"; } @@ -2106,10 +2120,10 @@ void output_software_lists(std::ostream &out, device_t &root, const char *root_t std::string newtag(swlist.tag()), oldtag(":"); newtag = newtag.substr(newtag.find(oldtag.append(root_tag)) + oldtag.length()); - out << util::string_format("\t\t<softwarelist tag=\"%s\" name=\"%s\" status=\"%s\"", normalize_string(newtag.c_str()), normalize_string(swlist.list_name().c_str()), swlist.is_original() ? "original" : "compatible"); + util::stream_format(out, "\t\t<softwarelist tag=\"%s\" name=\"%s\" status=\"%s\"", normalize_string(newtag), normalize_string(swlist.list_name()), swlist.is_original() ? "original" : "compatible"); if (swlist.filter()) - out << util::string_format(" filter=\"%s\"", normalize_string(swlist.filter())); + util::stream_format(out, " filter=\"%s\"", normalize_string(swlist.filter())); out << "/>\n"; } } @@ -2135,15 +2149,15 @@ void output_ramoptions(std::ostream &out, device_t &root) { assert(!havedefault); havedefault = true; - out << util::string_format("\t\t<ramoption name=\"%s\" default=\"yes\">%u</ramoption>\n", normalize_string(option.first.c_str()), option.second); + util::stream_format(out, "\t\t<ramoption name=\"%s\" default=\"yes\">%u</ramoption>\n", normalize_string(option.first), option.second); } else { - out << util::string_format("\t\t<ramoption name=\"%s\">%u</ramoption>\n", normalize_string(option.first.c_str()), option.second); + util::stream_format(out, "\t\t<ramoption name=\"%s\">%u</ramoption>\n", normalize_string(option.first), option.second); } } if (!havedefault) - out << util::string_format("\t\t<ramoption name=\"%s\" default=\"yes\">%u</ramoption>\n", ram.default_size_string(), defsize); + util::stream_format(out, "\t\t<ramoption name=\"%s\" default=\"yes\">%u</ramoption>\n", ram.default_size_string(), defsize); break; } } diff --git a/src/frontend/mame/language.cpp b/src/frontend/mame/language.cpp index 4ecdc2aba0c..6602dffaa8e 100644 --- a/src/frontend/mame/language.cpp +++ b/src/frontend/mame/language.cpp @@ -15,28 +15,12 @@ #include "corestr.h" -#include <cstring> -#include <memory> -#include <new> -#include <unordered_map> -#include <utility> - - -namespace { - -constexpr u32 MO_MAGIC = 0x950412de; -constexpr u32 MO_MAGIC_REVERSED = 0xde120495; - -std::unique_ptr<u32 []> f_translation_data; -std::unordered_map<std::string_view, std::pair<char const *, u32> > f_translation_map; - -} // anonymous namespace +#include <string> void load_translation(emu_options &m_options) { - f_translation_data.reset(); - f_translation_map.clear(); + util::unload_translation(); std::string name = m_options.language(); if (name.empty()) @@ -52,174 +36,6 @@ void load_translation(emu_options &m_options) return; } - u64 const size = file.size(); - if (20 > size) - { - file.close(); - osd_printf_error("Error reading translation file %s: %u-byte file is too small to contain translation data\n", name, size); - return; - } - - f_translation_data.reset(new (std::nothrow) u32 [(size + 3) / 4]); - if (!f_translation_data) - { - file.close(); - osd_printf_error("Failed to allocate %u bytes to load translation data file %s\n", size, name); - return; - } - - auto const read = file.read(f_translation_data.get(), size); - file.close(); - if (read != size) - { - osd_printf_error("Error reading translation file %s: requested %u bytes but got %u bytes\n", name, size, read); - f_translation_data.reset(); - return; - } - - if ((f_translation_data[0] != MO_MAGIC) && (f_translation_data[0] != MO_MAGIC_REVERSED)) - { - osd_printf_error("Error reading translation file %s: unrecognized magic number 0x%08X\n", name, f_translation_data[0]); - f_translation_data.reset(); - return; - } - - auto fetch_word = - [reversed = f_translation_data[0] == MO_MAGIC_REVERSED, words = f_translation_data.get()] (size_t offset) - { - return reversed ? swapendian_int32(words[offset]) : words[offset]; - }; - - // FIXME: check major/minor version number - - if ((fetch_word(3) % 4) || (fetch_word(4) % 4)) - { - osd_printf_error("Error reading translation file %s: table offsets %u and %u are not word-aligned\n", name, fetch_word(3), fetch_word(4)); - f_translation_data.reset(); - return; - } - - u32 const number_of_strings = fetch_word(2); - u32 const original_table_offset = fetch_word(3) >> 2; - u32 const translation_table_offset = fetch_word(4) >> 2; - if ((4 * (original_table_offset + (u64(number_of_strings) * 2))) > size) - { - osd_printf_error("Error reading translation file %s: %u-entry original string table at offset %u extends past end of %u-byte file\n", name, number_of_strings, fetch_word(3), size); - f_translation_data.reset(); - return; - } - if ((4 * (translation_table_offset + (u64(number_of_strings) * 2))) > size) - { - osd_printf_error("Error reading translation file %s: %u-entry translated string table at offset %u extends past end of %u-byte file\n", name, number_of_strings, fetch_word(4), size); - f_translation_data.reset(); - return; - } - osd_printf_verbose("Reading translation file %s: %u strings, original table at word offset %u, translated table at word offset %u\n", name, number_of_strings, original_table_offset, translation_table_offset); - - char const *const data = reinterpret_cast<char const *>(f_translation_data.get()); - for (u32 i = 1; number_of_strings > i; ++i) - { - u32 const original_length = fetch_word(original_table_offset + (2 * i)); - u32 const original_offset = fetch_word(original_table_offset + (2 * i) + 1); - if ((original_length + original_offset) >= size) - { - osd_printf_error("Error reading translation file %s: %u-byte original string %u at offset %u extends past end of %u-byte file\n", name, original_length, i, original_offset, size); - continue; - } - if (data[original_length + original_offset]) - { - osd_printf_error("Error reading translation file %s: %u-byte original string %u at offset %u is not correctly NUL-terminated\n", name, original_length, i, original_offset); - continue; - } - - u32 const translation_length = fetch_word(translation_table_offset + (2 * i)); - u32 const translation_offset = fetch_word(translation_table_offset + (2 * i) + 1); - if ((translation_length + translation_offset) >= size) - { - osd_printf_error("Error reading translation file %s: %u-byte translated string %u at offset %u extends past end of %u-byte file\n", name, translation_length, i, translation_offset, size); - continue; - } - if (data[translation_length + translation_offset]) - { - osd_printf_error("Error reading translation file %s: %u-byte translated string %u at offset %u is not correctly NUL-terminated\n", name, translation_length, i, translation_offset); - continue; - } - - std::string_view const original(&data[original_offset], original_length); - char const *const translation(&data[translation_offset]); - auto const ins = f_translation_map.emplace(original, std::make_pair(translation, translation_length)); - if (!ins.second) - { - osd_printf_warning( - "Loading translation file %s: translation %u '%s'='%s' conflicts with previous translation '%s'='%s'\n", - name, - i, - original, - translation, - ins.first->first, - ins.first->second.first); - } - } - - osd_printf_verbose("Loaded %u translations from file %s\n", f_translation_map.size(), name); -} - - -char const *lang_translate(char const *message) -{ - auto const found = f_translation_map.find(message); - if (f_translation_map.end() != found) - return found->second.first; - return message; -} - - -std::string_view lang_translate(std::string_view message) -{ - auto const found = f_translation_map.find(message); - if (f_translation_map.end() != found) - return std::string_view(found->second.first, found->second.second); - return message; -} - - -char const *lang_translate(char const *context, char const *message) -{ - if (!f_translation_map.empty()) - { - auto const ctxlen(std::strlen(context)); - auto const msglen(std::strlen(message)); - std::string key; - key.reserve(ctxlen + 1 + msglen); - key.append(context, ctxlen); - key.append(1, '\004'); - key.append(message, msglen); - auto const found = f_translation_map.find(key); - if (f_translation_map.end() != found) - return found->second.first; - } - return message; -} - - -std::string_view lang_translate(char const *context, std::string_view message) -{ - return lang_translate(std::string_view(context), message); -} - - -std::string_view lang_translate(std::string_view context, std::string_view message) -{ - if (!f_translation_map.empty()) - { - std::string key; - key.reserve(context.length() + 1 + message.length()); - key.append(context); - key.append(1, '\004'); - key.append(message); - auto const found = f_translation_map.find(key); - if (f_translation_map.end() != found) - return std::string_view(found->second.first, found->second.second); - } - return message; + osd_printf_verbose("Loading translation file %s\n", file.fullpath()); + util::load_translation(file); } diff --git a/src/frontend/mame/language.h b/src/frontend/mame/language.h index 93e3c491382..100d36774ff 100644 --- a/src/frontend/mame/language.h +++ b/src/frontend/mame/language.h @@ -12,25 +12,11 @@ #pragma once -#include <string_view> +#include "util/language.h" -//************************************************************************** -// LOCALIZATION SUPPORT -//************************************************************************** +void load_translation(emu_options &options); -#define _(...) lang_translate(__VA_ARGS__) - -#define N_(msg) (msg) -#define N_p(ctx, msg) (msg) - -void load_translation(emu_options &option); - -char const *lang_translate(char const *message); -std::string_view lang_translate(std::string_view message); - -char const *lang_translate(char const *context, char const *message); -std::string_view lang_translate(char const *context, std::string_view message); -std::string_view lang_translate(std::string_view context, std::string_view message); +using util::lang_translate; #endif // MAME_FRONTEND_MAME_LANGUAGE_H diff --git a/src/frontend/mame/luaengine.cpp b/src/frontend/mame/luaengine.cpp index e8e246b5efc..6954116283c 100644 --- a/src/frontend/mame/luaengine.cpp +++ b/src/frontend/mame/luaengine.cpp @@ -747,6 +747,8 @@ void lua_engine::initialize() emu["print_error"] = [] (const char *str) { osd_printf_error("%s\n", str); }; emu["print_info"] = [] (const char *str) { osd_printf_info("%s\n", str); }; emu["print_debug"] = [] (const char *str) { osd_printf_debug("%s\n", str); }; + emu["osd_ticks"] = &osd_ticks; + emu["osd_ticks_per_second"] = &osd_ticks_per_second; emu["driver_find"] = [] (sol::this_state s, const char *driver) -> sol::object { @@ -1737,6 +1739,10 @@ void lua_engine::initialize() ui_type["get_char_width"] = [] (mame_ui_manager &m, uint32_t utf8char) { return m.get_char_width(utf8char); }; ui_type["get_string_width"] = &mame_ui_manager::get_string_width; ui_type["set_aggressive_input_focus"] = [](mame_ui_manager &m, bool aggressive_focus) { osd_set_aggressive_input_focus(aggressive_focus); }; + ui_type["get_general_input_setting"] = sol::overload( + // TODO: overload with sequence type string - parser isn't available here + [] (mame_ui_manager &ui, ioport_type type, int player) { return ui.get_general_input_setting(type, player, SEQ_TYPE_STANDARD); }, + [] (mame_ui_manager &ui, ioport_type type) { return ui.get_general_input_setting(type, 0, SEQ_TYPE_STANDARD); }); ui_type["options"] = sol::property([] (mame_ui_manager &m) { return static_cast<core_options *>(&m.options()); }); ui_type["line_height"] = sol::property(&mame_ui_manager::get_line_height); ui_type["menu_active"] = sol::property(&mame_ui_manager::is_menu_active); diff --git a/src/frontend/mame/ui/about.cpp b/src/frontend/mame/ui/about.cpp index ac38d9c08b7..05ba893ae00 100644 --- a/src/frontend/mame/ui/about.cpp +++ b/src/frontend/mame/ui/about.cpp @@ -12,12 +12,9 @@ #include "ui/about.h" #include "ui/ui.h" -#include "ui/utils.h" #include "mame.h" -#include <string_view> - namespace ui { @@ -38,21 +35,22 @@ namespace { //------------------------------------------------- menu_about::menu_about(mame_ui_manager &mui, render_container &container) - : menu(mui, container) + : menu_textbox(mui, container) , m_header{ util::string_format( #ifdef MAME_DEBUG - _("%1$s %2$s (%3$s%4$sP%5$s, debug)"), + _("about-header", "%1$s %2$s (%3$s%4$sP%5$s, debug)"), #else - _("%1$s %2$s (%3$s%4$sP%5$s)"), + _("about-header", "%1$s %2$s (%3$s%4$sP%5$s)"), #endif emulator_info::get_appname(), bare_build_version, (sizeof(int) == sizeof(void *)) ? "I" : "", (sizeof(long) == sizeof(void *)) ? "L" : (sizeof(long long) == sizeof(void *)) ? "LL" : "", sizeof(void *) * 8), - util::string_format(_("Revision: %1$s"), bare_vcs_revision) } + util::string_format(_("about-header", "Revision: %1$s"), bare_vcs_revision) } { + set_process_flags(PROCESS_CUSTOM_NAV); } @@ -81,136 +79,23 @@ void menu_about::custom_render(void *selectedref, float top, float bottom, float //------------------------------------------------- -// draw - draw about +// populate_text - populate the about box text //------------------------------------------------- -void menu_about::draw(uint32_t flags) +void menu_about::populate_text(std::optional<text_layout> &layout, float &width, int &lines) { - rgb_t const color = ui().colors().text_color(); - float const aspect = machine().render().ui_aspect(&container()); - float const line_height = ui().get_line_height(); - float const ud_arrow_width = line_height * aspect; - float const gutter_width = 0.52f * line_height * aspect; - float const visible_width = 1.0f - (2.0f * ui().box_lr_border() * aspect); - float const visible_left = (1.0f - visible_width) * 0.5f; - float const extra_height = 2.0f * line_height; - float const visible_extra_menu_height = get_customtop() + get_custombottom() + extra_height; - - // determine effective positions taking into account the hilighting arrows - float const maximum_width = visible_width - 2.0f * gutter_width; - - draw_background(); - map_mouse(); - - // account for extra space at the top and bottom - float visible_main_menu_height = 1.0f - 2.0f * ui().box_tb_border() - visible_extra_menu_height; - m_visible_lines = int(std::trunc(visible_main_menu_height / line_height)); - visible_main_menu_height = float(m_visible_lines) * line_height; - - // compute top/left of inner menu area by centering, if the menu is at the bottom of the extra, adjust - float const visible_top = ((1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f) + get_customtop(); - - // lay out the text if necessary - if (!m_layout || (m_layout->width() != maximum_width)) + if (!layout || (layout->width() != width)) { - m_layout.emplace(ui().create_layout(container(), maximum_width)); + rgb_t const color = ui().colors().text_color(); + layout.emplace(ui().create_layout(container(), width)); for (char const *const *line = copying_text; *line; ++line) { - m_layout->add_text(*line, color); - m_layout->add_text("\n", color); - } - } - float const actual_width = m_layout->actual_width(); - - // compute text box size - float const x1 = visible_left + ((maximum_width - actual_width) * 0.5f); - float const y1 = visible_top - ui().box_tb_border(); - float const x2 = visible_left + visible_width - ((maximum_width - actual_width) * 0.5f); - float const y2 = visible_top + visible_main_menu_height + ui().box_tb_border() + extra_height; - float const effective_left = x1 + gutter_width; - float const line_x0 = x1 + 0.5f * UI_LINE_WIDTH; - float const line_x1 = x2 - 0.5f * UI_LINE_WIDTH; - float const separator = visible_top + float(m_visible_lines) * line_height; - - ui().draw_outlined_box(container(), x1, y1, x2, y2, ui().colors().background_color()); - - int const visible_items = m_layout->lines(); - m_visible_lines = (std::min)(visible_items, m_visible_lines); - top_line = (std::max)(0, top_line); - if (top_line + m_visible_lines >= visible_items) - top_line = visible_items - m_visible_lines; - - clear_hover(); - if (top_line) - { - // if we're on the top line, display the up arrow - rgb_t fgcolor = ui().colors().text_color(); - if (mouse_in_rect(line_x0, visible_top, line_x1, visible_top + line_height)) - { - fgcolor = ui().colors().mouseover_color(); - highlight( - line_x0, visible_top, - line_x1, visible_top + line_height, - ui().colors().mouseover_bg_color()); - set_hover(HOVER_ARROW_UP); + layout->add_text(*line, color); + layout->add_text("\n", color); } - draw_arrow( - 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, visible_top + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, visible_top + 0.75f * line_height, - fgcolor, ROT0); + lines = layout->lines(); } - if ((top_line + m_visible_lines) < visible_items) - { - // if we're on the bottom line, display the down arrow - float const line_y = visible_top + float(m_visible_lines - 1) * line_height; - rgb_t fgcolor = ui().colors().text_color(); - if (mouse_in_rect(line_x0, line_y, line_x1, line_y + line_height)) - { - fgcolor = ui().colors().mouseover_color(); - highlight( - line_x0, line_y, - line_x1, line_y + line_height, - ui().colors().mouseover_bg_color()); - set_hover(HOVER_ARROW_DOWN); - } - draw_arrow( - 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, - fgcolor, ROT0 ^ ORIENTATION_FLIP_Y); - } - - // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow - m_visible_items = m_visible_lines - (top_line ? 1 : 0) - (top_line + m_visible_lines != visible_items); - m_layout->emit( - container(), - top_line ? (top_line + 1) : 0, m_visible_items, - effective_left, visible_top + (top_line ? line_height : 0.0f)); - - // add visual separator before the "return to prevous menu" item - container().add_line( - x1, separator + (0.5f * line_height), - x2, separator + (0.5f * line_height), - UI_LINE_WIDTH, ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - - menu_item const &pitem = item(0); - std::string_view const itemtext = pitem.text; - float const line_y0 = separator + line_height; - float const line_y1 = line_y0 + line_height; - - if (mouse_in_rect(line_x0, line_y0, line_x1, line_y1) && is_selectable(pitem)) - set_hover(0); - - highlight(line_x0, line_y0, line_x1, line_y1, ui().colors().selected_bg_color()); - ui().draw_text_full( - container(), itemtext, - effective_left, line_y0, actual_width, - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, - mame_ui_manager::NORMAL, - ui().colors().selected_color(), ui().colors().selected_bg_color(), - nullptr, nullptr); - - // if there is something special to add, do it by calling the virtual method - custom_render(get_selection_ref(), get_customtop(), get_custombottom(), x1, y1, x2, y2); + width = layout->actual_width(); } @@ -229,38 +114,10 @@ void menu_about::populate(float &customtop, float &custombottom) // handle - manages inputs in the about modal //------------------------------------------------- -void menu_about::handle() +void menu_about::handle(event const *ev) { - const event *event = process(PROCESS_CUSTOM_NAV); - if (event) - { - switch (event->iptkey) - { - case IPT_UI_UP: - --top_line; - break; - - case IPT_UI_DOWN: - ++top_line; - break; - - case IPT_UI_PAGE_UP: - top_line -= m_visible_lines - 3; - break; - - case IPT_UI_PAGE_DOWN: - top_line += m_visible_lines - 3; - break; - - case IPT_UI_HOME: - top_line = 0; - break; - - case IPT_UI_END: - top_line = m_layout->lines() - m_visible_lines; - break; - } - } + if (ev) + handle_key(ev->iptkey); } -}; +} // namespace ui diff --git a/src/frontend/mame/ui/about.h b/src/frontend/mame/ui/about.h index 8ef133c43c6..13fc8e3e84f 100644 --- a/src/frontend/mame/ui/about.h +++ b/src/frontend/mame/ui/about.h @@ -12,7 +12,8 @@ #pragma once -#include "ui/menu.h" +#include "ui/text.h" +#include "ui/textbox.h" #include <optional> #include <string> @@ -21,7 +22,7 @@ namespace ui { -class menu_about : public menu +class menu_about : public menu_textbox { public: menu_about(mame_ui_manager &mui, render_container &container); @@ -30,13 +31,13 @@ public: protected: virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; + virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) override; + private: - virtual void draw(uint32_t flags) override; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; std::vector<std::string> const m_header; - std::optional<text_layout> m_layout; }; } // namespace ui diff --git a/src/frontend/mame/ui/analogipt.cpp b/src/frontend/mame/ui/analogipt.cpp index 2f1d1a7128d..209a84b4f06 100644 --- a/src/frontend/mame/ui/analogipt.cpp +++ b/src/frontend/mame/ui/analogipt.cpp @@ -52,6 +52,7 @@ menu_analog::menu_analog(mame_ui_manager &mui, render_container &container) , m_field_data() , m_visible_fields(0U) { + set_process_flags(PROCESS_LR_REPEAT); } @@ -121,18 +122,15 @@ void menu_analog::custom_render(void *selectedref, float top, float bottom, floa } -void menu_analog::handle() +void menu_analog::handle(event const *ev) { - // process the menu - event const *const menu_event(process(PROCESS_LR_REPEAT)); - // handle events - if (menu_event && menu_event->itemref) + if (ev && ev->itemref) { - item_data &data(*reinterpret_cast<item_data *>(menu_event->itemref)); + item_data &data(*reinterpret_cast<item_data *>(ev->itemref)); int newval(data.cur); - switch (menu_event->iptkey) + switch (ev->iptkey) { // if selected, reset to default value case IPT_UI_SELECT: diff --git a/src/frontend/mame/ui/analogipt.h b/src/frontend/mame/ui/analogipt.h index 2982aa142fe..36ab7906ee3 100644 --- a/src/frontend/mame/ui/analogipt.h +++ b/src/frontend/mame/ui/analogipt.h @@ -66,7 +66,7 @@ private: using field_data_vector = std::vector<field_data>; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; void find_fields(); diff --git a/src/frontend/mame/ui/auditmenu.cpp b/src/frontend/mame/ui/auditmenu.cpp index 9c93cf361bd..aaad0967f00 100644 --- a/src/frontend/mame/ui/auditmenu.cpp +++ b/src/frontend/mame/ui/auditmenu.cpp @@ -139,32 +139,28 @@ void menu_audit::populate(float &customtop, float &custombottom) custombottom = (ui().get_line_height() * 1.0f) + (ui().box_tb_border() * 3.0f); } -void menu_audit::handle() +void menu_audit::handle(event const *ev) { switch (m_phase) { case phase::CONFIRMATION: + if (ev && (IPT_UI_SELECT == ev->iptkey)) { - event const *const menu_event(process(0)); - if (menu_event && (IPT_UI_SELECT == menu_event->iptkey)) + if ((ITEMREF_START_FULL == ev->itemref) || (ITEMREF_START_FAST == ev->itemref)) { - if ((ITEMREF_START_FULL == menu_event->itemref) || (ITEMREF_START_FAST == menu_event->itemref)) - { - m_phase = phase::AUDIT; - m_fast = ITEMREF_START_FAST == menu_event->itemref; - m_prompt = util::string_format(_("Press %1$s to cancel\n"), ui().get_general_input_setting(IPT_UI_CANCEL)); - m_future.resize(std::thread::hardware_concurrency()); - for (auto &future : m_future) - future = std::async(std::launch::async, [this] () { return do_audit(); }); - } + set_process_flags(PROCESS_CUSTOM_ONLY | PROCESS_NOINPUT); + m_phase = phase::AUDIT; + m_fast = ITEMREF_START_FAST == ev->itemref; + m_prompt = util::string_format(_("Press %1$s to cancel\n"), ui().get_general_input_setting(IPT_UI_CANCEL)); + m_future.resize(std::thread::hardware_concurrency()); + for (auto &future : m_future) + future = std::async(std::launch::async, [this] () { return do_audit(); }); } } break; case phase::AUDIT: case phase::CANCELLATION: - process(PROCESS_CUSTOM_ONLY | PROCESS_NOINPUT); - if ((m_next.load() >= m_availablesorted.size()) || m_cancel.load()) { bool done(true); diff --git a/src/frontend/mame/ui/auditmenu.h b/src/frontend/mame/ui/auditmenu.h index ea1dfa26821..de42c33b6d1 100644 --- a/src/frontend/mame/ui/auditmenu.h +++ b/src/frontend/mame/ui/auditmenu.h @@ -36,7 +36,7 @@ private: enum class phase { CONFIRMATION, AUDIT, CANCELLATION }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; bool do_audit(); void save_available_machines(); diff --git a/src/frontend/mame/ui/barcode.cpp b/src/frontend/mame/ui/barcode.cpp index 846f2cc97c5..7181445e240 100644 --- a/src/frontend/mame/ui/barcode.cpp +++ b/src/frontend/mame/ui/barcode.cpp @@ -9,12 +9,14 @@ ***************************************************************************/ #include "emu.h" - #include "ui/barcode.h" + #include "ui/ui.h" #include "ui/utils.h" + namespace ui { + // itemrefs for key menu items #define ITEMREF_NEW_BARCODE ((void *) 0x0001) #define ITEMREF_ENTER_BARCODE ((void *) 0x0002) @@ -35,6 +37,7 @@ namespace ui { menu_barcode_reader::menu_barcode_reader(mame_ui_manager &mui, render_container &container, barcode_reader_device *device) : menu_device_control<barcode_reader_device>(mui, container, device) { + set_process_flags(PROCESS_LR_REPEAT); } @@ -86,29 +89,26 @@ void menu_barcode_reader::populate(float &customtop, float &custombottom) // handle - manages inputs in the barcode input menu //------------------------------------------------- -void menu_barcode_reader::handle() +void menu_barcode_reader::handle(event const *ev) { - // process the menu - const event *event = process(PROCESS_LR_REPEAT); - // process the event - if (event) + if (ev) { // handle selections - switch (event->iptkey) + switch (ev->iptkey) { case IPT_UI_LEFT: - if (event->itemref == ITEMREF_SELECT_READER) + if (ev->itemref == ITEMREF_SELECT_READER) previous(); break; case IPT_UI_RIGHT: - if (event->itemref == ITEMREF_SELECT_READER) + if (ev->itemref == ITEMREF_SELECT_READER) next(); break; case IPT_UI_SELECT: - if (event->itemref == ITEMREF_ENTER_BARCODE) + if (ev->itemref == ITEMREF_ENTER_BARCODE) { std::string tmp_file(m_barcode_buffer); //printf("code %s\n", m_barcode_buffer); @@ -135,7 +135,7 @@ void menu_barcode_reader::handle() case IPT_SPECIAL: if (get_selection_ref() == ITEMREF_NEW_BARCODE) { - if (input_character(m_barcode_buffer, event->unichar, uchar_is_digit)) + if (input_character(m_barcode_buffer, ev->unichar, uchar_is_digit)) reset(reset_options::REMEMBER_POSITION); } break; diff --git a/src/frontend/mame/ui/barcode.h b/src/frontend/mame/ui/barcode.h index 7f48d4f78ed..e171485cf79 100644 --- a/src/frontend/mame/ui/barcode.h +++ b/src/frontend/mame/ui/barcode.h @@ -17,6 +17,7 @@ #include "ui/devctrl.h" namespace ui { + class menu_barcode_reader : public menu_device_control<barcode_reader_device> { public: menu_barcode_reader(mame_ui_manager &mui, render_container &container, barcode_reader_device *device); @@ -24,7 +25,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; std::string m_barcode_buffer; }; diff --git a/src/frontend/mame/ui/cheatopt.cpp b/src/frontend/mame/ui/cheatopt.cpp index 1bfd8e4e0b3..9aae81134ef 100644 --- a/src/frontend/mame/ui/cheatopt.cpp +++ b/src/frontend/mame/ui/cheatopt.cpp @@ -9,12 +9,12 @@ *********************************************************************/ #include "emu.h" -#include "cheat.h" -#include "mame.h" +#include "ui/cheatopt.h" #include "ui/ui.h" -#include "ui/menu.h" -#include "ui/cheatopt.h" + +#include "cheat.h" +#include "mame.h" namespace ui { @@ -29,78 +29,73 @@ namespace ui { menu_cheat - handle the cheat menu -------------------------------------------------*/ -void menu_cheat::handle() +void menu_cheat::handle(event const *ev) { - /* process the menu */ - const event *menu_event = process(PROCESS_LR_REPEAT); - - - /* handle events */ - if (menu_event != nullptr && menu_event->itemref != nullptr) + // handle events + if (ev && ev->itemref) { bool changed = false; - /* clear cheat comment on any movement or keypress */ + // clear cheat comment on any movement or keypress machine().popmessage(); - /* handle reset all + reset all cheats for reload all option */ - if ((menu_event->itemref == ITEMREF_CHEATS_RESET_ALL || menu_event->itemref == ITEMREF_CHEATS_RELOAD_ALL) && menu_event->iptkey == IPT_UI_SELECT) + if ((ev->itemref == ITEMREF_CHEATS_RESET_ALL || ev->itemref == ITEMREF_CHEATS_RELOAD_ALL) && ev->iptkey == IPT_UI_SELECT) { + // handle reset all + reset all cheats for reload all option for (auto &curcheat : mame_machine_manager::instance()->cheat().entries()) if (curcheat->select_default_state()) changed = true; } - - /* handle individual cheats */ - else if (menu_event->itemref >= ITEMREF_CHEATS_FIRST_ITEM) + else if (ev->itemref >= ITEMREF_CHEATS_FIRST_ITEM) { - cheat_entry *curcheat = reinterpret_cast<cheat_entry *>(menu_event->itemref); + // handle individual cheats + cheat_entry *curcheat = reinterpret_cast<cheat_entry *>(ev->itemref); const char *string; - switch (menu_event->iptkey) + switch (ev->iptkey) { - /* if selected, activate a oneshot */ + // if selected, activate a oneshot case IPT_UI_SELECT: changed = curcheat->activate(); break; - /* if cleared, reset to default value */ + // if cleared, reset to default value case IPT_UI_CLEAR: changed = curcheat->select_default_state(); break; - /* left decrements */ + // left decrements case IPT_UI_LEFT: changed = curcheat->select_previous_state(); break; - /* right increments */ + // right increments case IPT_UI_RIGHT: changed = curcheat->select_next_state(); break; - /* bring up display comment if one exists */ + // bring up display comment if one exists case IPT_UI_DISPLAY_COMMENT: case IPT_UI_UP: case IPT_UI_DOWN: string = curcheat->comment(); - if (string != nullptr && string[0] != 0) + if (string && *string) machine().popmessage(_("Cheat Comment:\n%s"), string); break; } } - /* handle reload all */ - if (menu_event->itemref == ITEMREF_CHEATS_RELOAD_ALL && menu_event->iptkey == IPT_UI_SELECT) + // handle reload all + if (ev->itemref == ITEMREF_CHEATS_RELOAD_ALL && ev->iptkey == IPT_UI_SELECT) { - /* re-init cheat engine and thus reload cheats/cheats have already been turned off by here */ + // re-init cheat engine and thus reload cheats/cheats have already been turned off by here mame_machine_manager::instance()->cheat().reload(); - /* display the reloaded cheats */ + // display the reloaded cheats reset(reset_options::REMEMBER_REF); machine().popmessage(_("All cheats reloaded")); } - /* if things changed, update */ + // if things changed, update if (changed) reset(reset_options::REMEMBER_REF); } @@ -113,6 +108,7 @@ void menu_cheat::handle() menu_cheat::menu_cheat(mame_ui_manager &mui, render_container &container) : menu(mui, container) { + set_process_flags(PROCESS_LR_REPEAT); } void menu_cheat::populate(float &customtop, float &custombottom) diff --git a/src/frontend/mame/ui/cheatopt.h b/src/frontend/mame/ui/cheatopt.h index 1d925cb2a71..c01ec151189 100644 --- a/src/frontend/mame/ui/cheatopt.h +++ b/src/frontend/mame/ui/cheatopt.h @@ -25,7 +25,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; }; } // namespace ui diff --git a/src/frontend/mame/ui/confswitch.cpp b/src/frontend/mame/ui/confswitch.cpp index be1346171d3..3aa10cd9133 100644 --- a/src/frontend/mame/ui/confswitch.cpp +++ b/src/frontend/mame/ui/confswitch.cpp @@ -82,6 +82,13 @@ menu_confswitch::~menu_confswitch() } +void menu_confswitch::menu_activated() +{ + // switches can have input assignments, and scripts are a thing + reset(reset_options::REMEMBER_REF); +} + + void menu_confswitch::populate(float &customtop, float &custombottom) { // locate relevant fields if necessary @@ -162,31 +169,28 @@ void menu_confswitch::populate(float &customtop, float &custombottom) } item_append(menu_item_type::SEPARATOR); - item_append(_("Reset"), 0, (void *)1); + item_append(_("Reset Machine"), 0, (void *)1); } -void menu_confswitch::handle() +void menu_confswitch::handle(event const *ev) { - // process the menu - event const *const menu_event(process(0)); - // handle events - if (menu_event && menu_event->itemref) + if (ev && ev->itemref) { - if (uintptr_t(menu_event->itemref) == 1U) + if (uintptr_t(ev->itemref) == 1U) { // reset - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) machine().schedule_hard_reset(); } else { // actual settings - ioport_field &field(*reinterpret_cast<ioport_field *>(menu_event->itemref)); + ioport_field &field(*reinterpret_cast<ioport_field *>(ev->itemref)); bool changed(false); - switch (menu_event->iptkey) + switch (ev->iptkey) { // if selected, reset to default value case IPT_UI_SELECT: diff --git a/src/frontend/mame/ui/confswitch.h b/src/frontend/mame/ui/confswitch.h index 5ece14ae4c1..598b0208085 100644 --- a/src/frontend/mame/ui/confswitch.h +++ b/src/frontend/mame/ui/confswitch.h @@ -56,6 +56,7 @@ protected: menu_confswitch(mame_ui_manager &mui, render_container &container, uint32_t type); + virtual void menu_activated() override; virtual void populate(float &customtop, float &custombottom) override; field_vector const &fields() { return m_fields; } @@ -63,7 +64,7 @@ protected: unsigned active_switch_groups() const { return m_active_switch_groups; } private: - virtual void handle() override; + virtual void handle(event const *ev) override; void find_fields(); diff --git a/src/frontend/mame/ui/custui.cpp b/src/frontend/mame/ui/custui.cpp index 76d5b282534..982ec8bde39 100644 --- a/src/frontend/mame/ui/custui.cpp +++ b/src/frontend/mame/ui/custui.cpp @@ -45,6 +45,7 @@ menu_custom_ui::menu_custom_ui(mame_ui_manager &mui, render_container &container , m_currlang(0) , m_currsysnames(0) { + set_process_flags(PROCESS_LR_REPEAT); find_languages(); find_sysnames(); } @@ -72,19 +73,17 @@ menu_custom_ui::~menu_custom_ui() // handle //------------------------------------------------- -void menu_custom_ui::handle() +void menu_custom_ui::handle(event const *ev) { bool changed = false; // process the menu - const event *menu_event = process(PROCESS_LR_REPEAT); - - if (menu_event != nullptr && menu_event->itemref != nullptr) + if (ev && ev->itemref) { - switch ((uintptr_t)menu_event->itemref) + switch ((uintptr_t)ev->itemref) { case FONT_MENU: - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) menu::stack_push<menu_font_ui>( ui(), container(), @@ -95,16 +94,16 @@ void menu_custom_ui::handle() }); break; case COLORS_MENU: - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) menu::stack_push<menu_colors_ui>(ui(), container()); break; case HIDE_MENU: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { changed = true; - (menu_event->iptkey == IPT_UI_RIGHT) ? ui_globals::panels_status++ : ui_globals::panels_status--; + (ev->iptkey == IPT_UI_RIGHT) ? ui_globals::panels_status++ : ui_globals::panels_status--; } - else if (menu_event->iptkey == IPT_UI_SELECT) + else if (ev->iptkey == IPT_UI_SELECT) { std::vector<std::string> s_sel(std::size(HIDE_STATUS)); std::transform(std::begin(HIDE_STATUS), std::end(HIDE_STATUS), s_sel.begin(), [](auto &s) { return _(s); }); @@ -118,15 +117,15 @@ void menu_custom_ui::handle() } break; case LANGUAGE_MENU: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { changed = true; - if (menu_event->iptkey == IPT_UI_LEFT) + if (ev->iptkey == IPT_UI_LEFT) m_currlang = (m_currlang ? m_currlang : m_languages.size())- 1; else if (++m_currlang >= m_languages.size()) m_currlang = 0; } - else if (menu_event->iptkey == IPT_UI_SELECT) + else if (ev->iptkey == IPT_UI_SELECT) { // copying list of language names - expensive menu::stack_push<menu_selector>( @@ -139,15 +138,15 @@ void menu_custom_ui::handle() } break; case SYSNAMES_MENU: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { changed = true; - if (menu_event->iptkey == IPT_UI_LEFT) + if (ev->iptkey == IPT_UI_LEFT) m_currsysnames = (m_currsysnames ? m_currsysnames : m_sysnames.size())- 1; else if (++m_currsysnames >= m_sysnames.size()) m_currsysnames = 0; } - else if (menu_event->iptkey == IPT_UI_SELECT) + else if (ev->iptkey == IPT_UI_SELECT) { // copying list of file names - expensive menu::stack_push<menu_selector>( @@ -308,6 +307,8 @@ menu_font_ui::menu_font_ui(mame_ui_manager &mui, render_container &container, st , m_changed(false) , m_actual(0U) { + set_process_flags(PROCESS_LR_REPEAT); + std::string name(mui.machine().options().ui_font()); list(); @@ -374,41 +375,39 @@ menu_font_ui::~menu_font_ui() // handle //------------------------------------------------- -void menu_font_ui::handle() +void menu_font_ui::handle(event const *ev) { bool changed = false; // process the menu - const event *menu_event = process(PROCESS_LR_REPEAT); - - if (menu_event && menu_event->itemref) + if (ev && ev->itemref) { - switch ((uintptr_t)menu_event->itemref) + switch ((uintptr_t)ev->itemref) { case INFOS_SIZE: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { - (menu_event->iptkey == IPT_UI_RIGHT) ? m_info_size += 0.05f : m_info_size -= 0.05f; + (ev->iptkey == IPT_UI_RIGHT) ? m_info_size += 0.05f : m_info_size -= 0.05f; changed = true; } break; case FONT_SIZE: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { - (menu_event->iptkey == IPT_UI_RIGHT) ? m_font_size++ : m_font_size--; + (ev->iptkey == IPT_UI_RIGHT) ? m_font_size++ : m_font_size--; changed = true; } break; case MUI_FNT: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { - (menu_event->iptkey == IPT_UI_RIGHT) ? m_actual++ : m_actual--; + (ev->iptkey == IPT_UI_RIGHT) ? m_actual++ : m_actual--; changed = true; } - else if (menu_event->iptkey == IPT_UI_SELECT) + else if (ev->iptkey == IPT_UI_SELECT) { std::vector<std::string> display_names; display_names.reserve(m_fonts.size()); @@ -428,9 +427,9 @@ void menu_font_ui::handle() #ifdef UI_WINDOWS case MUI_BOLD: case MUI_ITALIC: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT || menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT || ev->iptkey == IPT_UI_SELECT) { - ((uintptr_t)menu_event->itemref == MUI_BOLD) ? m_bold = !m_bold : m_italic = !m_italic; + ((uintptr_t)ev->itemref == MUI_BOLD) ? m_bold = !m_bold : m_italic = !m_italic; changed = true; } break; @@ -551,17 +550,17 @@ menu_colors_ui::~menu_colors_ui() // handle //------------------------------------------------- -void menu_colors_ui::handle() +void menu_colors_ui::handle(event const *ev) { bool changed = false; // process the menu - const event *menu_event = process(0); - - if (menu_event != nullptr && menu_event->itemref != nullptr && menu_event->iptkey == IPT_UI_SELECT) + if (ev && ev->itemref && ev->iptkey == IPT_UI_SELECT) { - if ((uintptr_t)menu_event->itemref != MUI_RESTORE) - menu::stack_push<menu_rgb_ui>(ui(), container(), &m_color_table[(uintptr_t)menu_event->itemref].color, selected_item().text); + if ((uintptr_t)ev->itemref != MUI_RESTORE) + { + menu::stack_push<menu_rgb_ui>(ui(), container(), &m_color_table[(uintptr_t)ev->itemref].color, selected_item().text); + } else { changed = true; @@ -767,6 +766,7 @@ menu_rgb_ui::menu_rgb_ui(mame_ui_manager &mui, render_container &container, rgb_ m_lock_ref(0), m_title(_title) { + set_process_flags(PROCESS_LR_REPEAT); } //------------------------------------------------- @@ -781,26 +781,19 @@ menu_rgb_ui::~menu_rgb_ui() // handle //------------------------------------------------- -void menu_rgb_ui::handle() +void menu_rgb_ui::handle(event const *ev) { // process the menu - const event *menu_event; - - if (!m_key_active) - menu_event = process(PROCESS_LR_REPEAT); - else - menu_event = process(PROCESS_ONLYCHAR); - - if (menu_event && menu_event->itemref != nullptr) + if (ev && ev->itemref) { bool changed = false; - switch (menu_event->iptkey) + switch (ev->iptkey) { case IPT_UI_LEFT: case IPT_UI_RIGHT: { - int updated = (IPT_UI_LEFT == menu_event->iptkey) ? -1 : 1; - switch (uintptr_t(menu_event->itemref)) + int updated = (IPT_UI_LEFT == ev->iptkey) ? -1 : 1; + switch (uintptr_t(ev->itemref)) { case RGB_ALPHA: updated += m_color->a(); @@ -839,20 +832,20 @@ void menu_rgb_ui::handle() break; case IPT_UI_SELECT: - if (uintptr_t(menu_event->itemref) == PALETTE_CHOOSE) + if (uintptr_t(ev->itemref) == PALETTE_CHOOSE) { menu::stack_push<menu_palette_sel>(ui(), container(), *m_color); break; } [[fallthrough]]; case IPT_SPECIAL: - switch (uintptr_t(menu_event->itemref)) + switch (uintptr_t(ev->itemref)) { case RGB_ALPHA: case RGB_RED: case RGB_GREEN: case RGB_BLUE: - inkey_special(menu_event); + inkey_special(ev); changed = true; break; } @@ -1004,6 +997,7 @@ void menu_rgb_ui::inkey_special(const event *menu_event) if (menu_event->iptkey == IPT_UI_SELECT) { m_key_active = !m_key_active; + set_process_flags(m_key_active ? PROCESS_ONLYCHAR : PROCESS_LR_REPEAT); m_lock_ref = (uintptr_t)menu_event->itemref; if (!m_key_active) @@ -1079,13 +1073,12 @@ menu_palette_sel::~menu_palette_sel() // handle //------------------------------------------------- -void menu_palette_sel::handle() +void menu_palette_sel::handle(event const *ev) { // process the menu - const event *menu_event = process(0); - if (menu_event != nullptr && menu_event->itemref != nullptr) + if (ev && ev->itemref) { - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) { m_original = rgb_t(uint32_t(strtoul(selected_item().subtext.c_str(), nullptr, 16))); reset_parent(reset_options::SELECT_FIRST); diff --git a/src/frontend/mame/ui/custui.h b/src/frontend/mame/ui/custui.h index 33e8149ffdc..f693b9eab24 100644 --- a/src/frontend/mame/ui/custui.h +++ b/src/frontend/mame/ui/custui.h @@ -44,7 +44,7 @@ private: }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; void find_languages(); void find_sysnames(); @@ -82,7 +82,7 @@ private: }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; void list(); @@ -143,7 +143,7 @@ private: }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; s_color_table m_color_table[MUI_RESTORE]; void restore_colors(); @@ -173,7 +173,7 @@ private: }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; void inkey_special(const event *menu_event); @@ -196,7 +196,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; static std::pair<const char *, const char *> const s_palette[]; rgb_t &m_original; diff --git a/src/frontend/mame/ui/datmenu.cpp b/src/frontend/mame/ui/datmenu.cpp index 10c5e3c9717..df8ac0a7e67 100644 --- a/src/frontend/mame/ui/datmenu.cpp +++ b/src/frontend/mame/ui/datmenu.cpp @@ -24,6 +24,7 @@ #include "uiinput.h" #include <cmath> +#include <limits> #include <string_view> @@ -34,14 +35,14 @@ namespace ui { //------------------------------------------------- menu_dats_view::menu_dats_view(mame_ui_manager &mui, render_container &container, const ui_system_info *system) - : menu(mui, container) + : menu_textbox(mui, container) , m_system(!system ? &system_list::instance().systems()[driver_list::find(mui.machine().system().name)] : system) , m_swinfo(nullptr) , m_issoft(false) - , m_layout() , m_actual(0) { + set_process_flags(PROCESS_LR_ALWAYS | PROCESS_CUSTOM_NAV); for (device_image_interface& image : image_interface_enumerator(mui.machine().root_device())) { if (image.filename()) @@ -71,11 +72,10 @@ menu_dats_view::menu_dats_view(mame_ui_manager &mui, render_container &container //------------------------------------------------- menu_dats_view::menu_dats_view(mame_ui_manager &mui, render_container &container, const ui_software_info &swinfo) - : menu(mui, container) + : menu_textbox(mui, container) , m_system(nullptr) , m_swinfo(&swinfo) , m_issoft(true) - , m_layout() , m_actual(0) , m_list(swinfo.listname) , m_short(swinfo.shortname) @@ -83,6 +83,7 @@ menu_dats_view::menu_dats_view(mame_ui_manager &mui, render_container &container , m_parent(swinfo.parentname) { + set_process_flags(PROCESS_LR_ALWAYS | PROCESS_CUSTOM_NAV); if (!swinfo.infotext.empty()) m_items_list.emplace_back(_("Software List Info"), 0, ""); std::vector<std::string> lua_list; @@ -165,18 +166,17 @@ void menu_dats_view::add_info_text(text_layout &layout, std::string_view text, r // handle //------------------------------------------------- -void menu_dats_view::handle() +void menu_dats_view::handle(event const *ev) { - event const *const menu_event = process(PROCESS_LR_ALWAYS | PROCESS_CUSTOM_NAV); - if (menu_event) + if (ev) { - switch (menu_event->iptkey) + switch (ev->iptkey) { case IPT_UI_LEFT: if (m_actual > 0) { m_actual--; - reset(reset_options::SELECT_FIRST); + reset_layout(); } break; @@ -184,33 +184,12 @@ void menu_dats_view::handle() if ((m_actual + 1) < m_items_list.size()) { m_actual++; - reset(reset_options::SELECT_FIRST); + reset_layout(); } break; - case IPT_UI_UP: - --top_line; - break; - - case IPT_UI_DOWN: - ++top_line; - break; - - case IPT_UI_PAGE_UP: - top_line -= m_visible_lines - 3; - break; - - case IPT_UI_PAGE_DOWN: - top_line += m_visible_lines - 3; - break; - - case IPT_UI_HOME: - top_line = 0; - break; - - case IPT_UI_END: - top_line = m_layout->lines() - m_visible_lines; - break; + default: + handle_key(ev->iptkey); } } } @@ -221,150 +200,8 @@ void menu_dats_view::handle() void menu_dats_view::populate(float &customtop, float &custombottom) { - bool paused = machine().paused(); - if (!paused) - machine().pause(); - - m_layout = std::nullopt; - customtop = 2.0f * ui().get_line_height() + 4.0f * ui().box_tb_border(); custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); - - if (!paused) - machine().resume(); -} - -//------------------------------------------------- -// draw - draw dats menu -//------------------------------------------------- - -void menu_dats_view::draw(uint32_t flags) -{ - float const aspect = machine().render().ui_aspect(&container()); - float const line_height = ui().get_line_height(); - float const ud_arrow_width = line_height * aspect; - float const gutter_width = 0.52f * line_height * aspect; - float const visible_width = 1.0f - (2.0f * ui().box_lr_border() * aspect); - float const visible_left = (1.0f - visible_width) * 0.5f; - float const extra_height = 2.0f * line_height; - float const visible_extra_menu_height = get_customtop() + get_custombottom() + extra_height; - - // determine effective positions taking into account the hilighting arrows - float const effective_width = visible_width - 2.0f * gutter_width; - float const effective_left = visible_left + gutter_width; - - draw_background(); - map_mouse(); - - // account for extra space at the top and bottom - float visible_main_menu_height = 1.0f - 2.0f * ui().box_tb_border() - visible_extra_menu_height; - m_visible_lines = int(std::trunc(visible_main_menu_height / line_height)); - visible_main_menu_height = float(m_visible_lines) * line_height; - - // compute top/left of inner menu area by centering, if the menu is at the bottom of the extra, adjust - float const visible_top = ((1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f) + get_customtop(); - - // compute text box size - float const x1 = visible_left; - float const y1 = visible_top - ui().box_tb_border(); - float const x2 = x1 + visible_width; - float const y2 = visible_top + visible_main_menu_height + ui().box_tb_border() + extra_height; - float const line_x0 = x1 + 0.5f * UI_LINE_WIDTH; - float const line_x1 = x2 - 0.5f * UI_LINE_WIDTH; - float const separator = visible_top + float(m_visible_lines) * line_height; - - ui().draw_outlined_box(container(), x1, y1, x2, y2, ui().colors().background_color()); - - if (!m_layout || (m_layout->width() != effective_width)) - { - std::string buffer; - if (!m_items_list.empty()) - { - if (m_issoft) - get_data_sw(buffer); - else - get_data(buffer); - } - m_layout.emplace(ui().create_layout(container(), effective_width)); - add_info_text(*m_layout, buffer, ui().colors().text_color()); - } - int const visible_items = m_layout->lines(); - m_visible_lines = (std::min)(visible_items, m_visible_lines); - top_line = (std::max)(0, top_line); - if (top_line + m_visible_lines >= visible_items) - top_line = visible_items - m_visible_lines; - - clear_hover(); - if (top_line) - { - // if we're on the top line, display the up arrow - rgb_t fgcolor = ui().colors().text_color(); - if (mouse_in_rect(line_x0, visible_top, line_x1, visible_top + line_height)) - { - fgcolor = ui().colors().mouseover_color(); - highlight( - line_x0, visible_top, - line_x1, visible_top + line_height, - ui().colors().mouseover_bg_color()); - set_hover(HOVER_ARROW_UP); - } - draw_arrow( - 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, visible_top + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, visible_top + 0.75f * line_height, - fgcolor, ROT0); - } - if ((top_line + m_visible_lines) < visible_items) - { - // if we're on the bottom line, display the down arrow - float const line_y = visible_top + float(m_visible_lines - 1) * line_height; - rgb_t fgcolor = ui().colors().text_color(); - if (mouse_in_rect(line_x0, line_y, line_x1, line_y + line_height)) - { - fgcolor = ui().colors().mouseover_color(); - highlight( - line_x0, line_y, - line_x1, line_y + line_height, - ui().colors().mouseover_bg_color()); - set_hover(HOVER_ARROW_DOWN); - } - draw_arrow( - 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, - 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, - fgcolor, ROT0 ^ ORIENTATION_FLIP_Y); - } - - // return the number of visible lines, minus 1 for top arrow and 1 for bottom arrow - m_visible_items = m_visible_lines - (top_line ? 1 : 0) - (top_line + m_visible_lines != visible_items); - m_layout->emit( - container(), - top_line ? (top_line + 1) : 0, m_visible_items, - effective_left, visible_top + (top_line ? line_height : 0.0f)); - - // add visual separator before the "return to prevous menu" item - container().add_line( - x1, separator + (0.5f * line_height), - x2, separator + (0.5f * line_height), - UI_LINE_WIDTH, ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); - - menu_item const &pitem = item(0); - std::string_view const itemtext = pitem.text; - float const line_y0 = separator + line_height; - float const line_y1 = line_y0 + line_height; - - if (mouse_in_rect(line_x0, line_y0, line_x1, line_y1) && is_selectable(pitem)) - set_hover(0); - - highlight(line_x0, line_y0, line_x1, line_y1, ui().colors().selected_bg_color()); - ui().draw_text_full( - container(), itemtext, - effective_left, line_y0, effective_width, - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, - mame_ui_manager::NORMAL, - ui().colors().selected_color(), ui().colors().selected_bg_color(), - nullptr, nullptr); - - // if there is something special to add, do it by calling the virtual method - custom_render(get_selection_ref(), get_customtop(), get_custombottom(), x1, y1, x2, y2); } //------------------------------------------------- @@ -512,7 +349,7 @@ void menu_dats_view::custom_render(void *selectedref, float top, float bottom, f } //------------------------------------------------- -// load data from DATs +// custom mouse click handling //------------------------------------------------- bool menu_dats_view::custom_mouse_down() @@ -533,6 +370,28 @@ bool menu_dats_view::custom_mouse_down() } //------------------------------------------------- +// populate selected DAT text +//------------------------------------------------- + +void menu_dats_view::populate_text(std::optional<text_layout> &layout, float &width, int &lines) +{ + if (!layout || (layout->width() != width)) + { + std::string buffer; + if (!m_items_list.empty()) + { + if (m_issoft) + get_data_sw(buffer); + else + get_data(buffer); + } + layout.emplace(ui().create_layout(container(), width)); + add_info_text(*layout, buffer, ui().colors().text_color()); + lines = std::numeric_limits<int>::max(); + } +} + +//------------------------------------------------- // load data from DATs //------------------------------------------------- diff --git a/src/frontend/mame/ui/datmenu.h b/src/frontend/mame/ui/datmenu.h index 9e81d9e2d2e..79b9bd8c1f6 100644 --- a/src/frontend/mame/ui/datmenu.h +++ b/src/frontend/mame/ui/datmenu.h @@ -14,8 +14,8 @@ #pragma once -#include "ui/menu.h" #include "ui/text.h" +#include "ui/textbox.h" #include <optional> #include <string> @@ -33,7 +33,7 @@ namespace ui { // class dats menu //------------------------------------------------- -class menu_dats_view : public menu +class menu_dats_view : public menu_textbox { public: menu_dats_view(mame_ui_manager &mui, render_container &container, const ui_software_info &swinfo); @@ -46,6 +46,8 @@ protected: virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual bool custom_mouse_down() override; + virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) override; + private: struct list_items { @@ -56,11 +58,8 @@ private: std::string revision; }; - // draw dats menu - virtual void draw(uint32_t flags) override; - virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; void get_data(std::string &buffer); void get_data_sw(std::string &buffer); @@ -68,7 +67,6 @@ private: ui_system_info const *const m_system; ui_software_info const *const m_swinfo; bool const m_issoft; - std::optional<text_layout> m_layout; int m_actual; std::string m_list, m_short, m_long, m_parent; std::vector<list_items> m_items_list; diff --git a/src/frontend/mame/ui/devopt.cpp b/src/frontend/mame/ui/devopt.cpp index 178f0af8d96..fea0f5106d3 100644 --- a/src/frontend/mame/ui/devopt.cpp +++ b/src/frontend/mame/ui/devopt.cpp @@ -22,290 +22,337 @@ namespace ui { menu -------------------------------------------------*/ -menu_device_config::menu_device_config(mame_ui_manager &mui, render_container &container, device_slot_interface *slot, device_slot_interface::slot_option const *option) : menu(mui, container) +menu_device_config::menu_device_config( + mame_ui_manager &mui, + render_container &container, + device_slot_interface *slot, + device_slot_interface::slot_option const *option) + : menu_textbox(mui, container) + , m_option(option) { - m_option = option; - m_owner = slot; - m_mounted = slot->device().subdevice(option->name()) != nullptr; + m_mounted = machine().root_device().subdevice(slot->device().subtag(option->name())) != nullptr; } -void menu_device_config::populate(float &customtop, float &custombottom) +menu_device_config::~menu_device_config() +{ +} + +void menu_device_config::populate_text(std::optional<text_layout> &layout, float &width, int &lines) { - machine_config &mconfig(const_cast<machine_config &>(machine().config())); - machine_config::token const tok(mconfig.begin_configuration(mconfig.root_device())); - device_t *const dev = mconfig.device_add(m_option->name(), m_option->devtype(), 0); - for (device_t &d : device_enumerator(*dev)) - if (!d.configured()) - d.config_complete(); - - std::ostringstream str; - util::stream_format( - str, - m_mounted - ? _("[This option is currently mounted in the running system]\n\nOption: %1$s\nDevice: %2$s\n\nThe selected option enables the following items:\n") - : _("[This option is NOT currently mounted in the running system]\n\nOption: %1$s\nDevice: %2$s\n\nIf you select this option, the following items will be enabled:\n"), - m_option->name(), - dev->name()); - - // loop over all CPUs - execute_interface_enumerator execiter(*dev); - if (execiter.count() > 0) + if (!layout || (layout->width() != width)) { - str << _("* CPU:\n"); - std::unordered_set<std::string> exectags; - for (device_execute_interface &exec : execiter) + rgb_t const color = ui().colors().text_color(); + layout.emplace(ui().create_layout(container(), width)); + + machine_config &mconfig(const_cast<machine_config &>(machine().config())); + machine_config::token const tok(mconfig.begin_configuration(mconfig.root_device())); + device_t *const dev = mconfig.device_add(m_option->name(), m_option->devtype(), 0); + for (device_t &d : device_enumerator(*dev)) + if (!d.configured()) + d.config_complete(); + + layout->add_text( + util::string_format( + m_mounted + ? _("[This option is currently mounted in the running system]\n\nOption: %1$s\nDevice: %2$s\n\nThe selected option enables the following items:\n") + : _("[This option is NOT currently mounted in the running system]\n\nOption: %1$s\nDevice: %2$s\n\nIf you select this option, the following items will be enabled:\n"), + m_option->name(), + dev->name()), + color); + + // loop over all CPUs + execute_interface_enumerator execiter(*dev); + if (execiter.count() > 0) { - if (!exectags.insert(exec.device().tag()).second) - continue; + layout->add_text(_("* CPU:\n"), color); + std::unordered_set<std::string> exectags; + for (device_execute_interface &exec : execiter) + { + if (!exectags.insert(exec.device().tag()).second) + continue; - // get cpu specific clock that takes internal multiplier/dividers into account - u32 clock = exec.device().clock(); + // get cpu specific clock that takes internal multiplier/dividers into account + u32 clock = exec.device().clock(); - // count how many identical CPUs we have - int count = 1; - const char *name = exec.device().name(); - for (device_execute_interface &scan : execiter) - { - if (exec.device().type() == scan.device().type() && strcmp(name, scan.device().name()) == 0 && exec.device().clock() == scan.device().clock()) - if (exectags.insert(scan.device().tag()).second) - count++; - } + // count how many identical CPUs we have + int count = 1; + const char *name = exec.device().name(); + for (device_execute_interface &scan : execiter) + { + if (exec.device().type() == scan.device().type() && strcmp(name, scan.device().name()) == 0 && exec.device().clock() == scan.device().clock()) + if (exectags.insert(scan.device().tag()).second) + count++; + } - std::string hz(std::to_string(clock)); - int d = (clock >= 1'000'000'000) ? 9 : (clock >= 1'000'000) ? 6 : (clock >= 1000) ? 3 : 0; - if (d > 0) - { - size_t dpos = hz.length() - d; - hz.insert(dpos, "."); - size_t last = hz.find_last_not_of('0'); - hz = hz.substr(0, last + (last != dpos ? 1 : 0)); - } + std::string hz(std::to_string(clock)); + int d = (clock >= 1'000'000'000) ? 9 : (clock >= 1'000'000) ? 6 : (clock >= 1000) ? 3 : 0; + if (d > 0) + { + size_t dpos = hz.length() - d; + hz.insert(dpos, "."); + size_t last = hz.find_last_not_of('0'); + hz = hz.substr(0, last + (last != dpos ? 1 : 0)); + } - // if more than one, prepend a #x in front of the CPU name and display clock - util::stream_format(str, - (count > 1) - ? ((clock != 0) ? " %1$d" UTF8_MULTIPLY "%2$s %3$s" UTF8_NBSP "%4$s\n" : " %1$d" UTF8_MULTIPLY "%2$s\n") - : ((clock != 0) ? " %2$s %3$s" UTF8_NBSP "%4$s\n" : " %2$s\n"), - count, name, hz, - (d == 9) ? _("GHz") : (d == 6) ? _("MHz") : (d == 3) ? _("kHz") : _("Hz")); + // if more than one, prepend a #x in front of the CPU name and display clock + layout->add_text( + util::string_format( + (count > 1) + ? ((clock != 0) ? " %1$d" UTF8_MULTIPLY "%2$s %3$s" UTF8_NBSP "%4$s\n" : " %1$d" UTF8_MULTIPLY "%2$s\n") + : ((clock != 0) ? " %2$s %3$s" UTF8_NBSP "%4$s\n" : " %2$s\n"), + count, name, hz, + (d == 9) ? _("GHz") : (d == 6) ? _("MHz") : (d == 3) ? _("kHz") : _("Hz")), + color); + } } - } - // display screen information - screen_device_enumerator scriter(*dev); - if (scriter.count() > 0) - { - str << _("* Video:\n"); - for (screen_device &screen : scriter) + // display screen information + screen_device_enumerator scriter(*dev); + if (scriter.count() > 0) { - if (screen.screen_type() == SCREEN_TYPE_VECTOR) + layout->add_text(_("* Video:\n"), color); + for (screen_device &screen : scriter) { - util::stream_format(str, _(" Screen '%1$s': Vector\n"), screen.tag()); + if (screen.screen_type() == SCREEN_TYPE_VECTOR) + { + layout->add_text(util::string_format(_(" Screen '%1$s': Vector\n"), screen.tag()), color); + } + else + { + std::string hz(std::to_string(float(screen.frame_period().as_hz()))); + size_t last = hz.find_last_not_of('0'); + size_t dpos = hz.find_last_of('.'); + hz = hz.substr(0, last + (last != dpos ? 1 : 0)); + + const rectangle &visarea = screen.visible_area(); + layout->add_text( + util::string_format( + (screen.orientation() & ORIENTATION_SWAP_XY) + ? _(" Screen '%1$s': %2$d \xC3\x97 %3$d (V) %4$s\xC2\xA0Hz\n") + : _(" Screen '%1$s': %2$d \xC3\x97 %3$d (H) %4$s\xC2\xA0Hz\n"), + screen.tag(), + visarea.width(), + visarea.height(), + hz), + color); + } } - else + } + + // loop over all sound chips + sound_interface_enumerator snditer(*dev); + if (snditer.count() > 0) + { + layout->add_text(_("* Sound:\n"), color); + std::unordered_set<std::string> soundtags; + for (device_sound_interface &sound : snditer) { - std::string hz(std::to_string(float(screen.frame_period().as_hz()))); - size_t last = hz.find_last_not_of('0'); - size_t dpos = hz.find_last_of('.'); - hz = hz.substr(0, last + (last != dpos ? 1 : 0)); - - const rectangle &visarea = screen.visible_area(); - util::stream_format( - str, - (screen.orientation() & ORIENTATION_SWAP_XY) - ? _(" Screen '%1$s': %2$d \xC3\x97 %3$d (V) %4$s\xC2\xA0Hz\n") - : _(" Screen '%1$s': %2$d \xC3\x97 %3$d (H) %4$s\xC2\xA0Hz\n"), - screen.tag(), - visarea.width(), - visarea.height(), - hz); + if (!sound.issound() || !soundtags.insert(sound.device().tag()).second) + continue; + + // count how many identical sound chips we have + int count = 1; + for (device_sound_interface &scan : snditer) + { + if (sound.device().type() == scan.device().type() && sound.device().clock() == scan.device().clock()) + if (soundtags.insert(scan.device().tag()).second) + count++; + } + + const u32 clock = sound.device().clock(); + std::string hz(std::to_string(clock)); + int d = (clock >= 1'000'000'000) ? 9 : (clock >= 1'000'000) ? 6 : (clock >= 1000) ? 3 : 0; + if (d > 0) + { + size_t dpos = hz.length() - d; + hz.insert(dpos, "."); + size_t last = hz.find_last_not_of('0'); + hz = hz.substr(0, last + (last != dpos ? 1 : 0)); + } + + // if more than one, prepend a #x in front of the name and display clock + layout->add_text( + util::string_format( + (count > 1) + ? ((clock != 0) ? " %1$d" UTF8_MULTIPLY "%2$s %3$s" UTF8_NBSP "%4$s\n" : " %1$d" UTF8_MULTIPLY "%2$s\n") + : ((clock != 0) ? " %2$s %3$s" UTF8_NBSP "%4$s\n" : " %2$s\n"), + count, sound.device().name(), hz, + (d == 9) ? _("GHz") : (d == 6) ? _("MHz") : (d == 3) ? _("kHz") : _("Hz")), + color); } } - } - // loop over all sound chips - sound_interface_enumerator snditer(*dev); - if (snditer.count() > 0) - { - str << _("* Sound:\n"); - std::unordered_set<std::string> soundtags; - for (device_sound_interface &sound : snditer) + // scan for BIOS settings + int bios = 0; + if (dev->rom_region()) { - if (!sound.issound() || !soundtags.insert(sound.device().tag()).second) - continue; - - // count how many identical sound chips we have - int count = 1; - for (device_sound_interface &scan : snditer) + // first loop through roms in search of default bios (shortname) + char const *bios_str(nullptr); + for (const tiny_rom_entry *rom = dev->rom_region(); !ROMENTRY_ISEND(rom); ++rom) { - if (sound.device().type() == scan.device().type() && sound.device().clock() == scan.device().clock()) - if (soundtags.insert(scan.device().tag()).second) - count++; + if (ROMENTRY_ISDEFAULT_BIOS(rom)) + bios_str = rom->name; } - const u32 clock = sound.device().clock(); - std::string hz(std::to_string(clock)); - int d = (clock >= 1'000'000'000) ? 9 : (clock >= 1'000'000) ? 6 : (clock >= 1000) ? 3 : 0; - if (d > 0) + // then loop again to count bios options and to get the default bios complete name + char const *bios_desc(nullptr); + for (romload::system_bios const &rom : romload::entries(dev->rom_region()).get_system_bioses()) { - size_t dpos = hz.length() - d; - hz.insert(dpos, "."); - size_t last = hz.find_last_not_of('0'); - hz = hz.substr(0, last + (last != dpos ? 1 : 0)); + bios++; + if (bios_str && !std::strcmp(bios_str, rom.get_name())) + bios_desc = rom.get_description(); } - // if more than one, prepend a #x in front of the name and display clock - util::stream_format(str, - (count > 1) - ? ((clock != 0) ? " %1$d" UTF8_MULTIPLY "%2$s %3$s" UTF8_NBSP "%4$s\n" : " %1$d" UTF8_MULTIPLY "%2$s\n") - : ((clock != 0) ? " %2$s %3$s" UTF8_NBSP "%4$s\n" : " %2$s\n"), - count, sound.device().name(), hz, - (d == 9) ? _("GHz") : (d == 6) ? _("MHz") : (d == 3) ? _("kHz") : _("Hz")); - } - } - - // scan for BIOS settings - int bios = 0; - if (dev->rom_region()) - { - // first loop through roms in search of default bios (shortname) - char const *bios_str(nullptr); - for (const tiny_rom_entry *rom = dev->rom_region(); !ROMENTRY_ISEND(rom); ++rom) - { - if (ROMENTRY_ISDEFAULT_BIOS(rom)) - bios_str = rom->name; - } - - // then loop again to count bios options and to get the default bios complete name - char const *bios_desc(nullptr); - for (romload::system_bios const &rom : romload::entries(dev->rom_region()).get_system_bioses()) - { - bios++; - if (bios_str && !std::strcmp(bios_str, rom.get_name())) - bios_desc = rom.get_description(); + if (bios) + { + layout->add_text( + util::string_format( + _("* BIOS settings:\n %1$d options [default: %2$s]\n"), + bios, + bios_desc ? bios_desc : bios_str ? bios_str : ""), + color); + } } - if (bios) - util::stream_format(str, _("* BIOS settings:\n %1$d options [default: %2$s]\n"), bios, bios_desc ? bios_desc : bios_str ? bios_str : ""); - } - - int input = 0, input_mj = 0, input_hana = 0, input_gamble = 0, input_analog = 0, input_adjust = 0; - int input_keypad = 0, input_keyboard = 0, dips = 0, confs = 0; - std::string errors; - std::ostringstream dips_opt, confs_opt; - ioport_list portlist; - for (device_t &iptdev : device_enumerator(*dev)) - portlist.append(iptdev, errors); - - // check if the device adds inputs to the system - for (auto &port : portlist) - for (ioport_field &field : port.second->fields()) - { - if (field.type() >= IPT_MAHJONG_FIRST && field.type() < IPT_MAHJONG_LAST) - input_mj++; - else if (field.type() >= IPT_HANAFUDA_FIRST && field.type() < IPT_HANAFUDA_LAST) - input_hana++; - else if (field.type() >= IPT_GAMBLING_FIRST && field.type() < IPT_GAMBLING_LAST) - input_gamble++; - else if (field.type() >= IPT_ANALOG_FIRST && field.type() < IPT_ANALOG_LAST) - input_analog++; - else if (field.type() == IPT_ADJUSTER) - input_adjust++; - else if (field.type() == IPT_KEYPAD) - input_keypad++; - else if (field.type() == IPT_KEYBOARD) - input_keyboard++; - else if (field.type() >= IPT_START1 && field.type() < IPT_UI_FIRST) - input++; - else if (field.type() == IPT_DIPSWITCH) + int input = 0, input_mj = 0, input_hana = 0, input_gamble = 0, input_analog = 0, input_adjust = 0; + int input_keypad = 0, input_keyboard = 0, dips = 0, confs = 0; + std::string errors; + std::ostringstream dips_opt, confs_opt; + ioport_list portlist; + for (device_t &iptdev : device_enumerator(*dev)) + portlist.append(iptdev, errors); + + // check if the device adds inputs to the system + for (auto &port : portlist) + for (ioport_field &field : port.second->fields()) { - dips++; - bool def(false); - for (ioport_setting const &setting : field.settings()) + if (field.type() >= IPT_MAHJONG_FIRST && field.type() < IPT_MAHJONG_LAST) + input_mj++; + else if (field.type() >= IPT_HANAFUDA_FIRST && field.type() < IPT_HANAFUDA_LAST) + input_hana++; + else if (field.type() >= IPT_GAMBLING_FIRST && field.type() < IPT_GAMBLING_LAST) + input_gamble++; + else if (field.type() >= IPT_ANALOG_FIRST && field.type() < IPT_ANALOG_LAST) + input_analog++; + else if (field.type() == IPT_ADJUSTER) + input_adjust++; + else if (field.type() == IPT_KEYPAD) + input_keypad++; + else if (field.type() == IPT_KEYBOARD) + input_keyboard++; + else if (field.type() >= IPT_START1 && field.type() < IPT_UI_FIRST) + input++; + else if (field.type() == IPT_DIPSWITCH) { - if (setting.value() == field.defvalue()) + dips++; + bool def(false); + for (ioport_setting const &setting : field.settings()) { - def = true; - util::stream_format(dips_opt, _(" %1$s [default: %2$s]\n"), field.name(), setting.name()); - break; + if (setting.value() == field.defvalue()) + { + def = true; + util::stream_format(dips_opt, _(" %1$s [default: %2$s]\n"), field.name(), setting.name()); + break; + } } + if (!def) + util::stream_format(dips_opt, _(" %1$s\n"), field.name()); } - if (!def) - util::stream_format(dips_opt, _(" %1$s\n"), field.name()); - } - else if (field.type() == IPT_CONFIG) - { - confs++; - bool def(false); - for (ioport_setting const &setting : field.settings()) + else if (field.type() == IPT_CONFIG) { - if (setting.value() == field.defvalue()) + confs++; + bool def(false); + for (ioport_setting const &setting : field.settings()) { - def = true; - util::stream_format(confs_opt, _(" %1$s [default: %2$s]\n"), field.name(), setting.name()); - break; + if (setting.value() == field.defvalue()) + { + def = true; + util::stream_format(confs_opt, _(" %1$s [default: %2$s]\n"), field.name(), setting.name()); + break; + } } + if (!def) + util::stream_format(confs_opt, _(" %1$s\n"), field.name()); } - if (!def) - util::stream_format(confs_opt, _(" %1$s\n"), field.name()); } - } - if (dips) - str << _("* DIP switch settings:\n") << dips_opt.str(); - if (confs) - str << _("* Configuration settings:\n") << confs_opt.str(); - if (input || input_mj || input_hana || input_gamble || input_analog || input_adjust || input_keypad || input_keyboard) - str << _("* Input device(s):\n"); - if (input) - util::stream_format(str, _(" User inputs [%1$d inputs]\n"), input); - if (input_mj) - util::stream_format(str, _(" Mahjong inputs [%1$d inputs]\n"), input_mj); - if (input_hana) - util::stream_format(str, _(" Hanafuda inputs [%1$d inputs]\n"), input_hana); - if (input_gamble) - util::stream_format(str, _(" Gambling inputs [%1$d inputs]\n"), input_gamble); - if (input_analog) - util::stream_format(str, _(" Analog inputs [%1$d inputs]\n"), input_analog); - if (input_adjust) - util::stream_format(str, _(" Adjuster inputs [%1$d inputs]\n"), input_adjust); - if (input_keypad) - util::stream_format(str, _(" Keypad inputs [%1$d inputs]\n"), input_keypad); - if (input_keyboard) - util::stream_format(str, _(" Keyboard inputs [%1$d inputs]\n"), input_keyboard); - - image_interface_enumerator imgiter(*dev); - if (imgiter.count() > 0) - { - str << _("* Media Options:\n"); - for (const device_image_interface &imagedev : imgiter) - util::stream_format(str, _(" %1$s [tag: %2$s]\n"), imagedev.image_type_name(), imagedev.device().tag()); - } + if (dips) + { + layout->add_text(_("* DIP switch settings:\n"), color); + layout->add_text(std::move(dips_opt).str(), color); + } + if (confs) + { + layout->add_text(_("* Configuration settings:\n"), color); + layout->add_text(std::move(confs_opt).str(), color); + } + if (input || input_mj || input_hana || input_gamble || input_analog || input_adjust || input_keypad || input_keyboard) + layout->add_text(_("* Input device(s):\n"), color); + if (input) + layout->add_text(util::string_format(_(" User inputs [%1$d inputs]\n"), input), color); + if (input_mj) + layout->add_text(util::string_format(_(" Mahjong inputs [%1$d inputs]\n"), input_mj), color); + if (input_hana) + layout->add_text(util::string_format(_(" Hanafuda inputs [%1$d inputs]\n"), input_hana), color); + if (input_gamble) + layout->add_text(util::string_format(_(" Gambling inputs [%1$d inputs]\n"), input_gamble), color); + if (input_analog) + layout->add_text(util::string_format(_(" Analog inputs [%1$d inputs]\n"), input_analog), color); + if (input_adjust) + layout->add_text(util::string_format(_(" Adjuster inputs [%1$d inputs]\n"), input_adjust), color); + if (input_keypad) + layout->add_text(util::string_format(_(" Keypad inputs [%1$d inputs]\n"), input_keypad), color); + if (input_keyboard) + layout->add_text(util::string_format(_(" Keyboard inputs [%1$d inputs]\n"), input_keyboard), color); + + image_interface_enumerator imgiter(*dev); + if (imgiter.count() > 0) + { + layout->add_text(_("* Media Options:\n"), color); + for (const device_image_interface &imagedev : imgiter) + { + layout->add_text( + util::string_format( + _(" %1$s [tag: %2$s]\n"), + imagedev.image_type_name(), + imagedev.device().tag()), + color); + } + } - slot_interface_enumerator slotiter(*dev); - if (slotiter.count() > 0) - { - str << _("* Slot Options:\n"); - for (const device_slot_interface &slot : slotiter) - util::stream_format(str, _(" %1$s [default: %2$s]\n"), slot.device().tag(), slot.default_option() ? slot.default_option() : "----"); - } + slot_interface_enumerator slotiter(*dev); + if (slotiter.count() > 0) + { + layout->add_text(_("* Slot Options:\n"), color); + for (const device_slot_interface &slot : slotiter) + { + layout->add_text( + util::string_format( + _(" %1$s [default: %2$s]\n"), + slot.device().tag(), + slot.default_option() ? slot.default_option() : "----"), + color); + } + } - if ((execiter.count() + scriter.count() + snditer.count() + imgiter.count() + slotiter.count() + bios + dips + confs - + input + input_mj + input_hana + input_gamble + input_analog + input_adjust + input_keypad + input_keyboard) == 0) - str << _("[None]\n"); + if ((execiter.count() + scriter.count() + snditer.count() + imgiter.count() + slotiter.count() + bios + dips + confs + + input + input_mj + input_hana + input_gamble + input_analog + input_adjust + input_keypad + input_keyboard) == 0) + layout->add_text(_("[None]\n"), color); - mconfig.device_remove(m_option->name()); - item_append(str.str(), FLAG_MULTILINE, nullptr); + mconfig.device_remove(m_option->name()); + lines = layout->lines(); + } + width = layout->actual_width(); } -void menu_device_config::handle() +void menu_device_config::populate(float &customtop, float &custombottom) { - /* process the menu */ - process(0); } -menu_device_config::~menu_device_config() +void menu_device_config::handle(event const *ev) { + if (ev) + handle_key(ev->iptkey); } } // namespace ui diff --git a/src/frontend/mame/ui/devopt.h b/src/frontend/mame/ui/devopt.h index 2bb4e24c6c0..b0e7a6a4d39 100644 --- a/src/frontend/mame/ui/devopt.h +++ b/src/frontend/mame/ui/devopt.h @@ -8,29 +8,33 @@ ***************************************************************************/ -#pragma once - #ifndef MAME_FRONTEND_UI_DEVOPT_H #define MAME_FRONTEND_UI_DEVOPT_H -#include "ui/menu.h" +#pragma once + +#include "ui/textbox.h" + namespace ui { -class menu_device_config : public menu + +class menu_device_config : public menu_textbox { public: menu_device_config(mame_ui_manager &mui, render_container &container, device_slot_interface *slot, device_slot_interface::slot_option const *option); virtual ~menu_device_config() override; +protected: + virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) override; + private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; - device_slot_interface *m_owner; - device_slot_interface::slot_option const *m_option; + device_slot_interface::slot_option const *const m_option; bool m_mounted; }; } // namespace ui -#endif /* MAME_FRONTEND_UI_DEVOPT_H */ +#endif // MAME_FRONTEND_UI_DEVOPT_H diff --git a/src/frontend/mame/ui/dirmenu.cpp b/src/frontend/mame/ui/dirmenu.cpp index f610189b771..9a6b3c09b8d 100644 --- a/src/frontend/mame/ui/dirmenu.cpp +++ b/src/frontend/mame/ui/dirmenu.cpp @@ -90,12 +90,10 @@ menu_directory::~menu_directory() // handle //------------------------------------------------- -void menu_directory::handle() +void menu_directory::handle(event const *ev) { // process the menu - const event *menu_event = process(0); - - if (menu_event != nullptr && menu_event->itemref != nullptr && menu_event->iptkey == IPT_UI_SELECT) + if (ev && ev->itemref && ev->iptkey == IPT_UI_SELECT) menu::stack_push<menu_display_actual>(ui(), container(), selected_index()); } @@ -146,12 +144,11 @@ menu_display_actual::~menu_display_actual() // handle //------------------------------------------------- -void menu_display_actual::handle() +void menu_display_actual::handle(event const *ev) { // process the menu - const event *menu_event = process(0); - if (menu_event != nullptr && menu_event->itemref != nullptr && menu_event->iptkey == IPT_UI_SELECT) - switch ((uintptr_t)menu_event->itemref) + if (ev && ev->itemref && ev->iptkey == IPT_UI_SELECT) + switch ((uintptr_t)ev->itemref) { case REMOVE: menu::stack_push<menu_remove_folder>(ui(), container(), m_ref); @@ -245,16 +242,14 @@ menu_add_change_folder::~menu_add_change_folder() // handle //------------------------------------------------- -void menu_add_change_folder::handle() +void menu_add_change_folder::handle(event const *ev) { // process the menu - const event *menu_event = process(0); - - if (menu_event != nullptr && menu_event->itemref != nullptr) + if (ev && ev->itemref) { - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) { - int index = (uintptr_t)menu_event->itemref - 1; + int index = (uintptr_t)ev->itemref - 1; const menu_item &pitem = item(index); // go up to the parent path @@ -283,11 +278,11 @@ void menu_add_change_folder::handle() m_search.clear(); reset(reset_options::SELECT_FIRST); } - else if (menu_event->iptkey == IPT_SPECIAL) + else if (ev->iptkey == IPT_SPECIAL) { bool update_selected = false; - if (menu_event->unichar == 0x09) + if (ev->unichar == 0x09) { // Tab key, save current path std::string error_string; @@ -325,7 +320,7 @@ void menu_add_change_folder::handle() else { // if it's any other key and we're not maxed out, update - update_selected = input_character(m_search, menu_event->unichar, uchar_is_printable); + update_selected = input_character(m_search, ev->unichar, uchar_is_printable); } // check for entries which matches our search buffer @@ -374,7 +369,7 @@ void menu_add_change_folder::handle() centre_selection(); } } - else if (menu_event->iptkey == IPT_UI_CANCEL) + else if (ev->iptkey == IPT_UI_CANCEL) { // reset the char buffer also in this case m_search.clear(); @@ -467,11 +462,10 @@ menu_remove_folder::~menu_remove_folder() // handle //------------------------------------------------- -void menu_remove_folder::handle() +void menu_remove_folder::handle(event const *ev) { // process the menu - const event *menu_event = process(0); - if (menu_event != nullptr && menu_event->itemref != nullptr && menu_event->iptkey == IPT_UI_SELECT) + if (ev && ev->itemref && ev->iptkey == IPT_UI_SELECT) { std::string tmppath, error_string; m_folders.erase(m_folders.begin() + selected_index()); diff --git a/src/frontend/mame/ui/dirmenu.h b/src/frontend/mame/ui/dirmenu.h index 5d794319b7c..556427425e0 100644 --- a/src/frontend/mame/ui/dirmenu.h +++ b/src/frontend/mame/ui/dirmenu.h @@ -19,6 +19,7 @@ #include <vector> namespace ui { + //------------------------------------------------- // class directory menu //------------------------------------------------- @@ -34,7 +35,7 @@ protected: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; }; //------------------------------------------------- @@ -58,7 +59,7 @@ private: }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; std::string m_heading[1], m_searchpath; std::vector<std::string> m_folders; @@ -80,7 +81,7 @@ protected: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; std::string m_searchpath; int m_ref; @@ -104,7 +105,7 @@ protected: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; int m_ref; std::string m_current_path; @@ -115,4 +116,4 @@ private: } // namespace ui -#endif /* MAME_FRONTEND_UI_DIRMENU_H */ +#endif // MAME_FRONTEND_UI_DIRMENU_H diff --git a/src/frontend/mame/ui/filecreate.cpp b/src/frontend/mame/ui/filecreate.cpp index 1474c562829..875fe1cd197 100644 --- a/src/frontend/mame/ui/filecreate.cpp +++ b/src/frontend/mame/ui/filecreate.cpp @@ -12,19 +12,18 @@ ***************************************************************************/ #include "emu.h" - #include "ui/filecreate.h" + #include "ui/ui.h" #include "ui/utils.h" -#include "imagedev/floppy.h" - #include "zippath.h" #include <cstring> namespace ui { + /*************************************************************************** CONSTANTS ***************************************************************************/ @@ -86,15 +85,12 @@ void menu_confirm_save_as::populate(float &customtop, float &custombottom) // handle - confirm save as menu //------------------------------------------------- -void menu_confirm_save_as::handle() +void menu_confirm_save_as::handle(event const *ev) { - // process the menu - const event *event = process(0); - // process the event - if ((event != nullptr) && (event->iptkey == IPT_UI_SELECT)) + if (ev && (ev->iptkey == IPT_UI_SELECT)) { - if (event->itemref == ITEMREF_YES) + if (ev->itemref == ITEMREF_YES) *m_yes = true; // no matter what, pop out @@ -190,19 +186,16 @@ void menu_file_create::populate(float &customtop, float &custombottom) // handle - file creator menu //------------------------------------------------- -void menu_file_create::handle() +void menu_file_create::handle(event const *ev) { - // process the menu - const event *event = process(0); - // process the event - if (event) + if (ev) { // handle selections - switch (event->iptkey) + switch (ev->iptkey) { case IPT_UI_SELECT: - if ((event->itemref == ITEMREF_CREATE) || (event->itemref == ITEMREF_NEW_IMAGE_NAME)) + if ((ev->itemref == ITEMREF_CREATE) || (ev->itemref == ITEMREF_NEW_IMAGE_NAME)) { std::string tmp_file(m_filename); if (tmp_file.find('.') != -1 && tmp_file.find('.') < tmp_file.length() - 1) @@ -218,7 +211,7 @@ void menu_file_create::handle() case IPT_SPECIAL: if (get_selection_ref() == ITEMREF_NEW_IMAGE_NAME) { - input_character(m_filename, event->unichar, &osd_is_valid_filename_char); + input_character(m_filename, ev->unichar, &osd_is_valid_filename_char); reset(reset_options::REMEMBER_POSITION); } break; @@ -278,13 +271,12 @@ void menu_select_format::populate(float &customtop, float &custombottom) // handle //------------------------------------------------- -void menu_select_format::handle() +void menu_select_format::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) { - *m_result = (floppy_image_format_t *)event->itemref; + *m_result = (floppy_image_format_t *)ev->itemref; stack_pop(); } } @@ -333,13 +325,12 @@ void menu_select_floppy_init::populate(float &customtop, float &custombottom) // handle //------------------------------------------------- -void menu_select_floppy_init::handle() +void menu_select_floppy_init::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) { - *m_result = int(uintptr_t(event->itemref)); + *m_result = int(uintptr_t(ev->itemref)); stack_pop(); } } diff --git a/src/frontend/mame/ui/filecreate.h b/src/frontend/mame/ui/filecreate.h index f4e0b670fbd..2debc892859 100644 --- a/src/frontend/mame/ui/filecreate.h +++ b/src/frontend/mame/ui/filecreate.h @@ -14,11 +14,14 @@ #pragma once #include "ui/menu.h" + #include "imagedev/floppy.h" + class floppy_image_format_t; namespace ui { + // ======================> menu_confirm_save_as class menu_confirm_save_as : public menu @@ -29,7 +32,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; bool *m_yes; }; @@ -48,7 +51,7 @@ protected: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; bool & m_ok; device_image_interface * m_image; @@ -69,7 +72,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; // internal state std::vector<floppy_image_format_t *> m_formats; @@ -88,7 +91,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; // internal state const std::vector<floppy_image_device::fs_info> &m_fs; diff --git a/src/frontend/mame/ui/filemngr.cpp b/src/frontend/mame/ui/filemngr.cpp index 1ef861e5475..029950865d4 100644 --- a/src/frontend/mame/ui/filemngr.cpp +++ b/src/frontend/mame/ui/filemngr.cpp @@ -106,7 +106,6 @@ void menu_file_manager::fill_image_line(device_image_interface *img, std::string void menu_file_manager::populate(float &customtop, float &custombottom) { std::string tmp_inst, tmp_name; - bool first_entry = true; if (!m_warnings.empty()) { @@ -132,18 +131,14 @@ void menu_file_manager::populate(float &customtop, float &custombottom) if (!scan.user_loadable()) continue; - // if it is a children device, and not something further down the device tree, we want it in the menu! + // if it is a child device, and not something further down the device tree, we want it in the menu! if (strcmp(scan.device().owner()->tag(), dev.tag()) == 0) if (devtags.insert(scan.device().tag()).second) { // check whether we already had some devices with the same owner: if not, output the owner tag! if (!tag_appended) { - if (first_entry) - first_entry = false; - else - item_append(menu_item_type::SEPARATOR); - item_append(string_format("[root%s]", dev.tag()), 0, nullptr); + item_append(string_format(_("[root%1$s]"), dev.tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr); tag_appended = true; } // finally, append the image interface to the menu @@ -156,7 +151,7 @@ void menu_file_manager::populate(float &customtop, float &custombottom) item_append(menu_item_type::SEPARATOR); if (m_warnings.empty() || m_curr_selected) - item_append("Reset", 0, (void *)1); + item_append(_("Reset Machine"), 0, (void *)1); custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); } @@ -166,19 +161,18 @@ void menu_file_manager::populate(float &customtop, float &custombottom) // handle //------------------------------------------------- -void menu_file_manager::handle() +void menu_file_manager::handle(event const *ev) { // process the menu - const event *event = process(0); - if (event && event->itemref && (event->iptkey == IPT_UI_SELECT)) + if (ev && ev->itemref && (ev->iptkey == IPT_UI_SELECT)) { - if ((uintptr_t)event->itemref == 1) + if ((uintptr_t)ev->itemref == 1) { machine().schedule_hard_reset(); } else { - selected_device = (device_image_interface *) event->itemref; + selected_device = (device_image_interface *) ev->itemref; if (selected_device) { m_curr_selected = true; @@ -199,7 +193,7 @@ void menu_file_manager::handle() void menu_file_manager::force_file_manager(mame_ui_manager &mui, render_container &container, const char *warnings) { // reset the menu stack - menu::stack_reset(mui.machine()); + menu::stack_reset(mui); // add the quit entry followed by the game select entry menu::stack_push_special_main<menu_quit_game>(mui, container); diff --git a/src/frontend/mame/ui/filemngr.h b/src/frontend/mame/ui/filemngr.h index d656bb9e692..a925e24b35e 100644 --- a/src/frontend/mame/ui/filemngr.h +++ b/src/frontend/mame/ui/filemngr.h @@ -34,7 +34,7 @@ protected: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; void fill_image_line(device_image_interface *img, std::string &instance, std::string &filename); @@ -44,4 +44,4 @@ private: } // namespace ui -#endif /* MAME_FRONTEND_UI_FILEMNGR_H */ +#endif // MAME_FRONTEND_UI_FILEMNGR_H diff --git a/src/frontend/mame/ui/filesel.cpp b/src/frontend/mame/ui/filesel.cpp index 1ddabffbb23..ea5c1e02e37 100644 --- a/src/frontend/mame/ui/filesel.cpp +++ b/src/frontend/mame/ui/filesel.cpp @@ -478,18 +478,17 @@ void menu_file_selector::populate(float &customtop, float &custombottom) // handle //------------------------------------------------- -void menu_file_selector::handle() +void menu_file_selector::handle(event const *ev) { // process the menu - event const *const event = process(0); - if (event) + if (ev) { - if (event->iptkey == IPT_SPECIAL) + if (ev->iptkey == IPT_SPECIAL) { // if it's any other key and we're not maxed out, update - type_search_char(event->unichar); + type_search_char(ev->unichar); } - else if (event->iptkey == IPT_UI_CANCEL) + else if (ev->iptkey == IPT_UI_CANCEL) { // reset the char buffer also in this case if (!m_filename.empty()) @@ -498,10 +497,10 @@ void menu_file_selector::handle() ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename); } } - else if (event->itemref && (event->iptkey == IPT_UI_SELECT)) + else if (ev->itemref && (ev->iptkey == IPT_UI_SELECT)) { // handle selections - select_item(*reinterpret_cast<file_selector_entry const *>(event->itemref)); + select_item(*reinterpret_cast<file_selector_entry const *>(ev->itemref)); // reset the char buffer when pressing IPT_UI_SELECT m_filename.clear(); @@ -556,13 +555,12 @@ void menu_select_rw::populate(float &customtop, float &custombottom) // handle //------------------------------------------------- -void menu_select_rw::handle() +void menu_select_rw::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) { - m_result = result_from_itemref(event->itemref); + m_result = result_from_itemref(ev->itemref); stack_pop(); } } diff --git a/src/frontend/mame/ui/filesel.h b/src/frontend/mame/ui/filesel.h index 8eefce9462a..9f7eea7dbea 100644 --- a/src/frontend/mame/ui/filesel.h +++ b/src/frontend/mame/ui/filesel.h @@ -82,7 +82,7 @@ private: std::string m_filename; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; // methods int compare_entries(const file_selector_entry *e1, const file_selector_entry *e2); @@ -120,7 +120,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; // internal state bool m_can_in_place; diff --git a/src/frontend/mame/ui/floppycntrl.cpp b/src/frontend/mame/ui/floppycntrl.cpp index 2f1cc9e0192..d38691831f1 100644 --- a/src/frontend/mame/ui/floppycntrl.cpp +++ b/src/frontend/mame/ui/floppycntrl.cpp @@ -93,7 +93,7 @@ void menu_control_floppy_image::hook_load(const std::string &filename) m_state = SELECT_RW; } -void menu_control_floppy_image::handle() +void menu_control_floppy_image::menu_activated() { switch (m_state) { case DO_CREATE: { @@ -121,7 +121,7 @@ void menu_control_floppy_image::handle() case SELECT_FORMAT: if(!output_format) { m_state = START_FILE; - handle(); + menu_activated(); } else { const auto &fs = fd.get_create_fs(); output_filename = util::zippath_combine(m_current_directory, m_current_file); @@ -140,7 +140,7 @@ void menu_control_floppy_image::handle() case SELECT_INIT: if(m_submenu_result.i == -1) { m_state = START_FILE; - handle(); + menu_activated(); } else { create_fs = &fd.get_create_fs()[m_submenu_result.i]; do_load_create(); @@ -179,7 +179,7 @@ void menu_control_floppy_image::handle() break; default: - menu_control_device_image::handle(); + menu_control_device_image::menu_activated(); } } diff --git a/src/frontend/mame/ui/floppycntrl.h b/src/frontend/mame/ui/floppycntrl.h index 9b80cc7edaa..bdc1104d0a5 100644 --- a/src/frontend/mame/ui/floppycntrl.h +++ b/src/frontend/mame/ui/floppycntrl.h @@ -26,6 +26,9 @@ public: menu_control_floppy_image(mame_ui_manager &ui, render_container &container, device_image_interface &image); virtual ~menu_control_floppy_image() override; +protected: + virtual void menu_activated() override; + private: enum { SELECT_FORMAT = LAST_ID, SELECT_MEDIA, SELECT_INIT, SELECT_RW }; @@ -34,12 +37,10 @@ private: const floppy_image_device::fs_info *create_fs; std::string input_filename, output_filename; - virtual void handle() override; - void do_load_create(); virtual void hook_load(const std::string &filename) override; }; } // namespace ui -#endif /* MAME_FRONTEND_UI_FLOPPYCNTRL_H */ +#endif // MAME_FRONTEND_UI_FLOPPYCNTRL_H diff --git a/src/frontend/mame/ui/imgcntrl.cpp b/src/frontend/mame/ui/imgcntrl.cpp index 43f40603479..d4b00ee3077 100644 --- a/src/frontend/mame/ui/imgcntrl.cpp +++ b/src/frontend/mame/ui/imgcntrl.cpp @@ -185,6 +185,7 @@ void menu_control_device_image::hook_load(const std::string &name) void menu_control_device_image::populate(float &customtop, float &custombottom) { + throw emu_fatalerror("menu_control_device_image::populate: Shouldn't get here!"); } @@ -192,7 +193,17 @@ void menu_control_device_image::populate(float &customtop, float &custombottom) // handle //------------------------------------------------- -void menu_control_device_image::handle() +void menu_control_device_image::handle(event const *ev) +{ + throw emu_fatalerror("menu_control_device_image::handle: Shouldn't get here!"); +} + + +//------------------------------------------------- +// menu_activated +//------------------------------------------------- + +void menu_control_device_image::menu_activated() { switch(m_state) { @@ -244,28 +255,28 @@ void menu_control_device_image::handle() break; case SELECT_ONE_PART: - switch(m_submenu_result.swparts) { - case menu_software_parts::result::ENTRY: { + switch (m_submenu_result.swparts) + { + case menu_software_parts::result::ENTRY: load_software_part(); break; - } default: // return to list m_state = SELECT_SOFTLIST; break; - } break; case SELECT_OTHER_PART: - switch(m_submenu_result.swparts) { + switch (m_submenu_result.swparts) + { case menu_software_parts::result::ENTRY: load_software_part(); break; case menu_software_parts::result::FMGR: m_state = START_FILE; - handle(); + menu_activated(); break; case menu_software_parts::result::EMPTY: @@ -275,18 +286,17 @@ void menu_control_device_image::handle() case menu_software_parts::result::SWLIST: m_state = START_SOFTLIST; - handle(); + menu_activated(); break; case menu_software_parts::result::INVALID: // return to system stack_pop(); break; - } break; case SELECT_FILE: - switch(m_submenu_result.filesel) + switch (m_submenu_result.filesel) { case menu_file_selector::result::EMPTY: m_image.unload(); @@ -304,7 +314,7 @@ void menu_control_device_image::handle() case menu_file_selector::result::SOFTLIST: m_state = START_SOFTLIST; - handle(); + menu_activated(); break; default: // return to system @@ -313,43 +323,51 @@ void menu_control_device_image::handle() } break; - case CREATE_FILE: { - bool can_create, need_confirm; - test_create(can_create, need_confirm); - if(can_create) { - if(need_confirm) { - menu::stack_push<menu_confirm_save_as>(ui(), container(), &m_create_confirmed); - m_state = CREATE_CONFIRM; - } else { - m_state = DO_CREATE; - handle(); + case CREATE_FILE: + { + bool can_create, need_confirm; + test_create(can_create, need_confirm); + if (can_create) + { + if (need_confirm) + { + menu::stack_push<menu_confirm_save_as>(ui(), container(), &m_create_confirmed); + m_state = CREATE_CONFIRM; + } + else + { + m_state = DO_CREATE; + menu_activated(); + } + } + else + { + m_state = START_FILE; + menu_activated(); } - } else { - m_state = START_FILE; - handle(); } break; - } case CREATE_CONFIRM: m_state = m_create_confirmed ? DO_CREATE : START_FILE; - handle(); + menu_activated(); break; case CHECK_CREATE: m_state = m_create_ok ? CREATE_FILE : START_FILE; - handle(); + menu_activated(); break; - case DO_CREATE: { - auto path = util::zippath_combine(m_current_directory, m_current_file); - image_init_result err = m_image.create(path, nullptr, nullptr); - if (err != image_init_result::PASS) - machine().popmessage("Error: %s", m_image.error()); - stack_pop(); + case DO_CREATE: + { + auto path = util::zippath_combine(m_current_directory, m_current_file); + image_init_result err = m_image.create(path, nullptr, nullptr); + if (err != image_init_result::PASS) + machine().popmessage("Error: %s", m_image.error()); + stack_pop(); + } break; } - } } } // namespace ui diff --git a/src/frontend/mame/ui/imgcntrl.h b/src/frontend/mame/ui/imgcntrl.h index a41a3f85f77..66a5ee5f81a 100644 --- a/src/frontend/mame/ui/imgcntrl.h +++ b/src/frontend/mame/ui/imgcntrl.h @@ -8,16 +8,18 @@ ***************************************************************************/ -#pragma once - #ifndef MAME_FRONTEND_UI_IMAGECNTRL_H #define MAME_FRONTEND_UI_IMAGECNTRL_H -#include "ui/menu.h" +#pragma once + #include "ui/filesel.h" +#include "ui/menu.h" #include "ui/swlist.h" + namespace ui { + // ======================> menu_control_device_image class menu_control_device_image : public menu @@ -53,8 +55,9 @@ protected: bool m_create_ok; // methods + virtual void menu_activated() override; + virtual void handle(event const *ev) override; virtual void hook_load(const std::string &filename); - virtual void handle() override; private: // instance variables @@ -72,4 +75,4 @@ private: } // namespace ui -#endif /* MAME_FRONTEND_UI_IMAGECNTRL_H */ +#endif // MAME_FRONTEND_UI_IMAGECNTRL_H diff --git a/src/frontend/mame/ui/info.cpp b/src/frontend/mame/ui/info.cpp index 0dc8b8979e9..8c5d1b43d2b 100644 --- a/src/frontend/mame/ui/info.cpp +++ b/src/frontend/mame/ui/info.cpp @@ -481,7 +481,7 @@ std::string machine_info::get_screen_desc(screen_device &screen) const menu_game_info - handle the game information menu -------------------------------------------------*/ -menu_game_info::menu_game_info(mame_ui_manager &mui, render_container &container) : menu(mui, container) +menu_game_info::menu_game_info(mame_ui_manager &mui, render_container &container) : menu_textbox(mui, container) { } @@ -489,15 +489,26 @@ menu_game_info::~menu_game_info() { } +void menu_game_info::populate_text(std::optional<text_layout> &layout, float &width, int &lines) +{ + if (!layout || (layout->width() != width)) + { + rgb_t const color = ui().colors().text_color(); + layout.emplace(ui().create_layout(container(), width)); + layout->add_text(ui().machine_info().game_info_string(), color); + lines = layout->lines(); + } + width = layout->actual_width(); +} + void menu_game_info::populate(float &customtop, float &custombottom) { - item_append(ui().machine_info().game_info_string(), FLAG_MULTILINE, nullptr); } -void menu_game_info::handle() +void menu_game_info::handle(event const *ev) { - // process the menu - process(0); + if (ev) + handle_key(ev->iptkey); } @@ -505,7 +516,7 @@ void menu_game_info::handle() menu_warn_info - handle the emulation warnings menu -------------------------------------------------*/ -menu_warn_info::menu_warn_info(mame_ui_manager &mui, render_container &container) : menu(mui, container) +menu_warn_info::menu_warn_info(mame_ui_manager &mui, render_container &container) : menu_textbox(mui, container) { } @@ -513,15 +524,26 @@ menu_warn_info::~menu_warn_info() { } +void menu_warn_info::populate_text(std::optional<text_layout> &layout, float &width, int &lines) +{ + if (!layout || (layout->width() != width)) + { + rgb_t const color = ui().colors().text_color(); + layout.emplace(ui().create_layout(container(), width)); + layout->add_text(ui().machine_info().warnings_string(), color); + lines = layout->lines(); + } + width = layout->actual_width(); +} + void menu_warn_info::populate(float &customtop, float &custombottom) { - item_append(ui().machine_info().warnings_string(), FLAG_MULTILINE, nullptr); } -void menu_warn_info::handle() +void menu_warn_info::handle(event const *ev) { - // process the menu - process(0); + if (ev) + handle_key(ev->iptkey); } @@ -537,6 +559,11 @@ menu_image_info::~menu_image_info() { } +void menu_image_info::menu_activated() +{ + reset(reset_options::REMEMBER_POSITION); +} + void menu_image_info::populate(float &customtop, float &custombottom) { ui_system_info const &system(system_list::instance().systems()[driver_list::find(machine().system().name)]); @@ -547,10 +574,8 @@ void menu_image_info::populate(float &customtop, float &custombottom) image_info(&image); } -void menu_image_info::handle() +void menu_image_info::handle(event const *ev) { - // process the menu - process(0); } diff --git a/src/frontend/mame/ui/info.h b/src/frontend/mame/ui/info.h index 7acb64c2a38..3f9fd7d8edb 100644 --- a/src/frontend/mame/ui/info.h +++ b/src/frontend/mame/ui/info.h @@ -13,7 +13,7 @@ #pragma once -#include "ui/menu.h" +#include "ui/textbox.h" namespace ui { @@ -86,27 +86,33 @@ private: }; -class menu_game_info : public menu +class menu_game_info : public menu_textbox { public: menu_game_info(mame_ui_manager &mui, render_container &container); virtual ~menu_game_info() override; +protected: + virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) override; + private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; }; -class menu_warn_info : public menu +class menu_warn_info : public menu_textbox { public: menu_warn_info(mame_ui_manager &mui, render_container &container); virtual ~menu_warn_info() override; +protected: + virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) override; + private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; }; @@ -116,9 +122,12 @@ public: menu_image_info(mame_ui_manager &mui, render_container &container); virtual ~menu_image_info() override; +protected: + virtual void menu_activated() override; + private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; void image_info(device_image_interface *image); }; diff --git a/src/frontend/mame/ui/info_pty.cpp b/src/frontend/mame/ui/info_pty.cpp index 12c2733af1a..4e541a7988c 100644 --- a/src/frontend/mame/ui/info_pty.cpp +++ b/src/frontend/mame/ui/info_pty.cpp @@ -41,9 +41,8 @@ void menu_pty_info::populate(float &customtop, float &custombottom) } } -void menu_pty_info::handle() +void menu_pty_info::handle(event const *ev) { - process(0); } } // namespace ui diff --git a/src/frontend/mame/ui/info_pty.h b/src/frontend/mame/ui/info_pty.h index 55249a34d34..16f65435be2 100644 --- a/src/frontend/mame/ui/info_pty.h +++ b/src/frontend/mame/ui/info_pty.h @@ -16,6 +16,7 @@ #include "ui/menu.h" namespace ui { + class menu_pty_info : public menu { public: @@ -24,7 +25,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; }; } // namespace ui diff --git a/src/frontend/mame/ui/inputmap.cpp b/src/frontend/mame/ui/inputmap.cpp index 5ddf7864adf..a651795ef6c 100644 --- a/src/frontend/mame/ui/inputmap.cpp +++ b/src/frontend/mame/ui/inputmap.cpp @@ -45,12 +45,11 @@ void menu_input_groups::populate(float &customtop, float &custombottom) item_append(menu_item_type::SEPARATOR); } -void menu_input_groups::handle() +void menu_input_groups::handle(event const *ev) { // process the menu - const event *const menu_event = process(0); - if (menu_event && menu_event->iptkey == IPT_UI_SELECT) - menu::stack_push<menu_input_general>(ui(), container(), int(uintptr_t(menu_event->itemref) - 1)); + if (ev && (ev->iptkey == IPT_UI_SELECT)) + menu::stack_push<menu_input_general>(ui(), container(), int(uintptr_t(ev->itemref) - 1)); } @@ -243,6 +242,7 @@ void menu_input_specific::update_input(input_item_data &seqchangeditem) /*------------------------------------------------- menu_input - display a menu for inputs -------------------------------------------------*/ + menu_input::menu_input(mame_ui_manager &mui, render_container &container) : menu(mui, container) , data() @@ -254,12 +254,20 @@ menu_input::menu_input(mame_ui_manager &mui, render_container &container) , record_next(false) , modified_ticks(0) { + set_process_flags(PROCESS_LR_ALWAYS); } menu_input::~menu_input() { } +void menu_input::menu_activated() +{ + // scripts can change settings out from under us + reset(reset_options::REMEMBER_REF); +} + + /*------------------------------------------------- toggle_none_default - toggle between "NONE" and the default item @@ -329,13 +337,12 @@ void menu_input::custom_render(void *selectedref, float top, float bottom, float } } -void menu_input::handle() +void menu_input::handle(event const *ev) { input_item_data *seqchangeditem = nullptr; bool invalidate = false; // process the menu - const event *const menu_event = process(pollingitem ? PROCESS_NOKEYS : PROCESS_LR_ALWAYS); if (pollingitem) { // if we are polling, handle as a special case @@ -349,6 +356,7 @@ void menu_input::handle() { // if UI_CANCEL is pressed, abort pollingitem = nullptr; + set_process_flags(PROCESS_LR_ALWAYS); if (!seq_poll->modified() || modified_ticks == osd_ticks()) { // cancelled immediately - toggle between default and none @@ -366,6 +374,7 @@ void menu_input::handle() else if (seq_poll->poll()) // poll again; if finished, update the sequence { pollingitem = nullptr; + set_process_flags(PROCESS_LR_ALWAYS); if (seq_poll->valid()) { record_next = true; @@ -382,13 +391,15 @@ void menu_input::handle() seq_poll.reset(); } } - else if (menu_event && menu_event->itemref) + else if (ev && ev->itemref) { // otherwise, handle the events - input_item_data &item = *reinterpret_cast<input_item_data *>(menu_event->itemref); - switch (menu_event->iptkey) + input_item_data &item = *reinterpret_cast<input_item_data *>(ev->itemref); + input_item_data *newsel = &item; + switch (ev->iptkey) { case IPT_UI_SELECT: // an item was selected: begin polling + set_process_flags(PROCESS_NOKEYS); errormsg.clear(); erroritem = nullptr; modified_ticks = 0; @@ -415,14 +426,63 @@ void menu_input::handle() break; case IPT_UI_LEFT: // flip between set and append - case IPT_UI_RIGHT: // not very discoverable, but with the prompt it isn't opaque + case IPT_UI_RIGHT: // not very discoverable, but with the prompt it isn't completely opaque if (record_next || !item.seq.empty()) record_next = !record_next; break; + + case IPT_UI_PREV_GROUP: + { + auto current = std::distance(data.data(), &item); + bool found_break = false; + while (0 < current) + { + if (!found_break) + { + if (data[--current].owner != item.owner) + found_break = true; + } + else if (data[current].owner != data[current - 1].owner) + { + newsel = &data[current]; + set_selection(newsel); + set_top_line(selected_index() - 1); + break; + } + else + { + --current; + } + if (found_break && !current) + { + newsel = &data[current]; + set_selection(newsel); + set_top_line(selected_index() - 1); + break; + } + } + } + break; + + case IPT_UI_NEXT_GROUP: + { + auto current = std::distance(data.data(), &item); + while (data.size() > ++current) + { + if (data[current].owner != item.owner) + { + newsel = &data[current]; + set_selection(newsel); + set_top_line(selected_index() - 1); + break; + } + } + } + break; } // if the selection changed, reset the "record next" flag - if (&item != lastitem) + if (newsel != lastitem) { if (erroritem) { @@ -460,15 +520,14 @@ void menu_input::populate_sorted(float &customtop, float &custombottom) const char *nameformat[INPUT_TYPE_TOTAL] = { nullptr }; // create a mini lookup table for name format based on type - nameformat[INPUT_TYPE_DIGITAL] = "%s"; - nameformat[INPUT_TYPE_ANALOG] = "%s Analog"; - nameformat[INPUT_TYPE_ANALOG_INC] = "%s Analog Inc"; - nameformat[INPUT_TYPE_ANALOG_DEC] = "%s Analog Dec"; + nameformat[INPUT_TYPE_DIGITAL] = "%1$s"; + nameformat[INPUT_TYPE_ANALOG] = _("input-name", "%1$s Analog"); + nameformat[INPUT_TYPE_ANALOG_INC] = _("input-name", "%1$s Analog Inc"); + nameformat[INPUT_TYPE_ANALOG_DEC] = _("input-name", "%1$s Analog Dec"); // build the menu std::string text, subtext; const device_t *prev_owner = nullptr; - bool first_entry = true; for (input_item_data &item : data) { // generate the name of the item itself, based off the base name and the type @@ -476,10 +535,6 @@ void menu_input::populate_sorted(float &customtop, float &custombottom) if (item.owner && (item.owner != prev_owner)) { - if (first_entry) - first_entry = false; - else - item_append(menu_item_type::SEPARATOR); if (item.owner->owner()) item_append(string_format(_("%1$s [root%2$s]"), item.owner->type().fullname(), item.owner->tag()), FLAG_UI_HEADING | FLAG_DISABLE, nullptr); else diff --git a/src/frontend/mame/ui/inputmap.h b/src/frontend/mame/ui/inputmap.h index 8058342515e..841382daf21 100644 --- a/src/frontend/mame/ui/inputmap.h +++ b/src/frontend/mame/ui/inputmap.h @@ -29,7 +29,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; }; @@ -63,6 +63,9 @@ protected: using data_vector = std::vector<input_item_data>; menu_input(mame_ui_manager &mui, render_container &container); + + virtual void menu_activated() override; + void populate_sorted(float &customtop, float &custombottom); void toggle_none_default(input_seq &selected_seq, input_seq &original_seq, const input_seq &selected_defseq); @@ -81,7 +84,7 @@ private: input_seq starting_seq; virtual void custom_render(void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2) override; - virtual void handle() override; + virtual void handle(event const *ev) override; virtual void update_input(input_item_data &seqchangeditem) = 0; }; diff --git a/src/frontend/mame/ui/keyboard.cpp b/src/frontend/mame/ui/keyboard.cpp index 36f12753e0c..7f6ffefb064 100644 --- a/src/frontend/mame/ui/keyboard.cpp +++ b/src/frontend/mame/ui/keyboard.cpp @@ -64,15 +64,14 @@ menu_keyboard_mode::~menu_keyboard_mode() { } -void menu_keyboard_mode::handle() +void menu_keyboard_mode::handle(event const *ev) { - event const *const menu_event(process(0)); - if (menu_event && uintptr_t(menu_event->itemref)) + if (ev && uintptr_t(ev->itemref)) { natural_keyboard &natkbd(machine().natkeyboard()); - uintptr_t const ref(uintptr_t(menu_event->itemref)); - bool const left(IPT_UI_LEFT == menu_event->iptkey); - bool const right(IPT_UI_RIGHT == menu_event->iptkey); + uintptr_t const ref(uintptr_t(ev->itemref)); + bool const left(IPT_UI_LEFT == ev->iptkey); + bool const right(IPT_UI_RIGHT == ev->iptkey); if (ITEM_KBMODE == ref) { if ((left || right) && (natkbd.in_use() != right)) diff --git a/src/frontend/mame/ui/keyboard.h b/src/frontend/mame/ui/keyboard.h index 899385e74c2..22ab3fe759a 100644 --- a/src/frontend/mame/ui/keyboard.h +++ b/src/frontend/mame/ui/keyboard.h @@ -25,7 +25,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; }; } // namespace ui diff --git a/src/frontend/mame/ui/mainmenu.cpp b/src/frontend/mame/ui/mainmenu.cpp index a50c346a1fe..132902b8f81 100644 --- a/src/frontend/mame/ui/mainmenu.cpp +++ b/src/frontend/mame/ui/mainmenu.cpp @@ -84,7 +84,7 @@ enum : unsigned { ***************************************************************************/ /*------------------------------------------------- - menu_main constructor - populate the main menu + menu_main constructor/destructor -------------------------------------------------*/ menu_main::menu_main(mame_ui_manager &mui, render_container &container) : menu(mui, container) @@ -92,9 +92,30 @@ menu_main::menu_main(mame_ui_manager &mui, render_container &container) : menu(m set_needs_prev_menu_item(false); } +menu_main::~menu_main() +{ +} + + +/*------------------------------------------------- + menu_activated - handle coming to foreground +-------------------------------------------------*/ + +void menu_main::menu_activated() +{ + if (machine().phase() != m_phase) + reset(reset_options::REMEMBER_REF); +} + + +/*------------------------------------------------- + populate - populate main menu items +-------------------------------------------------*/ + void menu_main::populate(float &customtop, float &custombottom) { - /* add main menu items */ + m_phase = machine().phase(); + item_append(_("Input (general)"), 0, (void *)INPUT_GROUPS); item_append(_("Input (this Machine)"), 0, (void *)INPUT_SPECIFIC); @@ -156,7 +177,7 @@ void menu_main::populate(float &customtop, float &custombottom) if (machine().options().cheat()) item_append(_("Cheat"), 0, (void *)CHEAT); - if (machine().phase() >= machine_phase::RESET) + if (machine_phase::RESET <= m_phase) { if (machine().options().plugins() && !mame_machine_manager::instance()->lua()->get_menu().empty()) item_append(_("Plugin Options"), 0, (void *)PLUGINS); @@ -180,7 +201,7 @@ void menu_main::populate(float &customtop, float &custombottom) // item_append(_("Quit from Machine"), 0, (void *)QUIT_GAME); - if (machine().phase() == machine_phase::INIT) + if (machine_phase::INIT == m_phase) { item_append(_("Start Machine"), 0, (void *)DISMISS); } @@ -191,20 +212,18 @@ void menu_main::populate(float &customtop, float &custombottom) } } -menu_main::~menu_main() -{ -} /*------------------------------------------------- - menu_main - handle the main menu + handle - handle main menu events -------------------------------------------------*/ -void menu_main::handle() +void menu_main::handle(event const *ev) { - /* process the menu */ - const event *menu_event = process(0); - if (menu_event != nullptr && menu_event->iptkey == IPT_UI_SELECT) { - switch(uintptr_t(menu_event->itemref)) { + // process the menu + if (ev && (ev->iptkey == IPT_UI_SELECT)) + { + switch (uintptr_t(ev->itemref)) + { case INPUT_GROUPS: menu::stack_push<menu_input_groups>(ui(), container()); break; @@ -314,12 +333,12 @@ void menu_main::handle() case ADD_FAVORITE: mame_machine_manager::instance()->favorite().add_favorite(machine()); - reset(reset_options::REMEMBER_POSITION); + reset(reset_options::REMEMBER_REF); break; case REMOVE_FAVORITE: mame_machine_manager::instance()->favorite().remove_favorite(machine()); - reset(reset_options::REMEMBER_POSITION); + reset(reset_options::REMEMBER_REF); break; case QUIT_GAME: diff --git a/src/frontend/mame/ui/mainmenu.h b/src/frontend/mame/ui/mainmenu.h index 284655c64c9..6671dd9f554 100644 --- a/src/frontend/mame/ui/mainmenu.h +++ b/src/frontend/mame/ui/mainmenu.h @@ -24,11 +24,16 @@ public: menu_main(mame_ui_manager &mui, render_container &container); virtual ~menu_main(); +protected: + virtual void menu_activated() override; + private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; + + machine_phase m_phase; }; } // namespace ui -#endif /* MAME_FRONTEND_UI_MAINMENU_H */ +#endif // MAME_FRONTEND_UI_MAINMENU_H diff --git a/src/frontend/mame/ui/menu.cpp b/src/frontend/mame/ui/menu.cpp index 9e98511a882..4df4731cb4f 100644 --- a/src/frontend/mame/ui/menu.cpp +++ b/src/frontend/mame/ui/menu.cpp @@ -33,21 +33,12 @@ namespace ui { /*************************************************************************** - GLOBAL VARIABLES -***************************************************************************/ - -std::mutex menu::s_global_state_guard; -menu::global_state_map menu::s_global_states; - -/*************************************************************************** INLINE FUNCTIONS ***************************************************************************/ -menu::global_state_ptr menu::get_global_state(running_machine &machine) +menu::global_state &menu::get_global_state(mame_ui_manager &ui) { - std::lock_guard<std::mutex> guard(s_global_state_guard); - auto const it(s_global_states.find(&machine)); - return (it != s_global_states.end()) ? it->second : global_state_ptr(); + return ui.get_session_data<menu, global_state_wrapper>(ui); } //------------------------------------------------- @@ -75,19 +66,20 @@ bool menu::exclusive_input_pressed(int &iptkey, int key, int repeat) CORE SYSTEM MANAGEMENT ***************************************************************************/ -menu::global_state::global_state(running_machine &machine, ui_options const &options) - : widgets_manager(machine) - , m_machine(machine) +menu::global_state::global_state(mame_ui_manager &ui) + : widgets_manager(ui.machine()) + , m_ui(ui) , m_bgrnd_bitmap() - , m_bgrnd_texture(nullptr, machine.render()) + , m_bgrnd_texture(nullptr, ui.machine().render()) , m_stack() , m_free() + , m_hide(false) { - render_manager &render(machine.render()); + render_manager &render(ui.machine().render()); // create a texture for main menu background m_bgrnd_texture.reset(render.texture_alloc(render_texture::hq_scale)); - if (options.use_background_image() && (&machine.system() == &GAME_NAME(___empty))) + if (ui.options().use_background_image() && (&ui.machine().system() == &GAME_NAME(___empty))) { m_bgrnd_bitmap = std::make_unique<bitmap_argb32>(0, 0); emu_file backgroundfile(".", OPEN_FLAG_READ); @@ -113,10 +105,6 @@ menu::global_state::global_state(running_machine &machine, ui_options const &opt menu::global_state::~global_state() { - // it shouldn't really be possible to get here with active menus because of reference loops - assert(!m_stack); - assert(!m_free); - stack_reset(); clear_free_list(); } @@ -124,6 +112,11 @@ menu::global_state::~global_state() void menu::global_state::stack_push(std::unique_ptr<menu> &&menu) { + if (m_stack && m_stack->m_active) + { + m_stack->m_active = false; + m_stack->menu_deactivated(); + } menu->m_parent = std::move(m_stack); m_stack = std::move(menu); m_stack->machine().ui_input().reset(); @@ -134,11 +127,14 @@ void menu::global_state::stack_pop() { if (m_stack) { + if (m_stack->m_one_shot) + m_hide = true; + m_stack->menu_dismissed(); std::unique_ptr<menu> menu(std::move(m_stack)); m_stack = std::move(menu->m_parent); menu->m_parent = std::move(m_free); m_free = std::move(menu); - m_machine.ui_input().reset(); + m_ui.machine().ui_input().reset(); } } @@ -177,40 +173,46 @@ bool menu::global_state::stack_has_special_main_menu() const } - - -//------------------------------------------------- -// init - initialize the menu system -//------------------------------------------------- - -void menu::init(running_machine &machine, ui_options &mopt) +uint32_t menu::global_state::ui_handler(render_container &container) { - // initialize the menu stack + // if we have no menus stacked up, start with the main menu + if (!m_stack) + stack_push(std::unique_ptr<menu>(make_unique_clear<menu_main>(m_ui, container))); + + // ensure topmost menu is active - need a loop because it could push another menu + while (m_stack && !m_stack->m_active) { - std::lock_guard<std::mutex> guard(s_global_state_guard); - auto const ins(s_global_states.emplace(&machine, std::make_shared<global_state>(machine, mopt))); - assert(ins.second); // calling init twice is bad - if (ins.second) - machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&menu::exit, &machine)); // add an exit callback to free memory - else - ins.first->second->stack_reset(); + m_stack->m_active = true; + m_stack->menu_activated(); } -} + // update the menu state + m_hide = false; + if (m_stack) + m_stack->do_handle(); -//------------------------------------------------- -// exit - clean up after ourselves -//------------------------------------------------- + // clear up anything pending being released + clear_free_list(); -void menu::exit(running_machine &machine) -{ - // free menus - global_state_ptr const state(get_global_state(machine)); - state->stack_reset(); - state->clear_free_list(); + // if the menus are to be hidden, return a cancel here + if (m_ui.is_menu_active() && (m_hide || !m_stack)) + { + if (m_stack) + { + if (m_stack->m_one_shot) + { + stack_pop(); + } + else if (m_stack->m_active) + { + m_stack->m_active = false; + m_stack->menu_deactivated(); + } + } + return UI_HANDLER_CANCEL; + } - std::lock_guard<std::mutex> guard(s_global_state_guard); - s_global_states.erase(&machine); + return 0; } @@ -224,16 +226,18 @@ void menu::exit(running_machine &machine) //------------------------------------------------- menu::menu(mame_ui_manager &mui, render_container &container) - : m_selected(0) - , m_items() - , m_visible_lines(0) - , m_visible_items(0) - , m_global_state(get_global_state(mui.machine())) - , m_special_main_menu(false) - , m_needs_prev_menu_item(true) + : m_global_state(get_global_state(mui)) , m_ui(mui) , m_container(container) , m_parent() + , m_items() + , m_process_flags(0) + , m_selected(0) + , m_hover(1) + , m_special_main_menu(false) + , m_one_shot(false) + , m_needs_prev_menu_item(true) + , m_active(false) , m_event() , m_customtop(0.0f) , m_custombottom(0.0f) @@ -244,11 +248,11 @@ menu::menu(mame_ui_manager &mui, render_container &container) , m_mouse_x(-1.0f) , m_mouse_y(-1.0f) { - assert(m_global_state); // not calling init is bad - reset(reset_options::SELECT_FIRST); top_line = 0; + m_visible_lines = 0; + m_visible_items = 0; } @@ -322,11 +326,6 @@ void menu::item_append(menu_item_type type, uint32_t flags) void menu::item_append(std::string &&text, std::string &&subtext, uint32_t flags, void *ref, menu_item_type type) { - if ((flags & FLAG_MULTILINE) != 0) // only allow multiline as the first item - assert(m_items.size() == 1); - else if (m_items.size() >= 2) // only allow a single multi-line item - assert((m_items[0].flags & FLAG_MULTILINE) == 0); - // allocate a new item and populate it menu_item pitem; pitem.text = std::move(text); @@ -374,7 +373,7 @@ void menu::item_append_on_off(const std::string &text, bool state, uint32_t flag // and returning any interesting events //------------------------------------------------- -const menu::event *menu::process(uint32_t flags, float x0, float y0) +const menu::event *menu::process() { // reset the event m_event.iptkey = IPT_INVALID; @@ -382,21 +381,31 @@ const menu::event *menu::process(uint32_t flags, float x0, float y0) // first make sure our selection is valid validate_selection(1); - // draw the menu - if (m_items.size() > 1 && (m_items[0].flags & FLAG_MULTILINE) != 0) - draw_text_box(); - else - draw(flags); + // if we're not running the emulation, draw parent menus in the background + auto const draw_parent = + [] (auto &self, menu *parent) -> bool + { + if (!parent || !(parent->is_special_main_menu() || self(self, parent->m_parent.get()))) + return false; + else + parent->draw(PROCESS_NOINPUT); + return true; + }; + if (draw_parent(draw_parent, m_parent.get())) + container().add_rect(0.0f, 0.0f, 1.0f, 1.0f, rgb_t(114, 0, 0, 0), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + + // draw the menu proper + draw(m_process_flags); // process input - if (!(flags & PROCESS_NOKEYS) && !(flags & PROCESS_NOINPUT)) + if (!(m_process_flags & (PROCESS_NOKEYS | PROCESS_NOINPUT))) { // read events - handle_events(flags, m_event); + handle_events(m_process_flags, m_event); // handle the keys if we don't already have an event if (m_event.iptkey == IPT_INVALID) - handle_keys(flags, m_event.iptkey); + handle_keys(m_process_flags, m_event.iptkey); } // update the selected item in the event @@ -456,7 +465,6 @@ void menu::draw(uint32_t flags) } bool const customonly = (flags & PROCESS_CUSTOM_ONLY); - bool const noimage = (flags & PROCESS_NOIMAGE); bool const noinput = (flags & PROCESS_NOINPUT); float const aspect = machine().render().ui_aspect(&container()); float const line_height = ui().get_line_height(); @@ -465,7 +473,7 @@ void menu::draw(uint32_t flags) float const gutter_width = lr_arrow_width * 1.3f; float const lr_border = ui().box_lr_border() * aspect; - if (&machine().system() == &GAME_NAME(___empty) && !noimage) + if (is_special_main_menu()) draw_background(); // compute the width and height of the full menu @@ -778,87 +786,6 @@ void menu::custom_render(void *selectedref, float top, float bottom, float x, fl { } -//------------------------------------------------- -// draw_text_box - draw a multiline -// word-wrapped text box with a menu item at the -// bottom -//------------------------------------------------- - -void menu::draw_text_box() -{ - std::string_view const text = m_items[0].text; - std::string_view const backtext = m_items[1].text; - float const aspect = machine().render().ui_aspect(&container()); - float line_height = ui().get_line_height(); - float lr_arrow_width = 0.4f * line_height * aspect; - float gutter_width = lr_arrow_width; - float const lr_border = ui().box_lr_border() * aspect; - float target_width, target_height, prior_width; - float target_x, target_y; - - // compute the multi-line target width/height - ui().draw_text_full( - container(), - text, - 0, 0, 1.0f - 2.0f * lr_border - 2.0f * gutter_width, - text_layout::text_justify::LEFT, text_layout::word_wrapping::WORD, - mame_ui_manager::NONE, rgb_t::white(), rgb_t::black(), - &target_width, &target_height); - target_height += 2.0f * line_height; - if (target_height > 1.0f - 2.0f * ui().box_tb_border()) - target_height = floorf((1.0f - 2.0f * ui().box_tb_border()) / line_height) * line_height; - - // maximum against "return to prior menu" text - prior_width = ui().get_string_width(backtext) + 2.0f * gutter_width; - target_width = std::max(target_width, prior_width); - - // determine the target location - target_x = 0.5f - 0.5f * target_width; - target_y = 0.5f - 0.5f * target_height; - - // make sure we stay on-screen - if (target_x < lr_border + gutter_width) - target_x = lr_border + gutter_width; - if (target_x + target_width + gutter_width + lr_border > 1.0f) - target_x = 1.0f - lr_border - gutter_width - target_width; - if (target_y < ui().box_tb_border()) - target_y = ui().box_tb_border(); - if (target_y + target_height + ui().box_tb_border() > 1.0f) - target_y = 1.0f - ui().box_tb_border() - target_height; - - // add a box around that - ui().draw_outlined_box( - container(), - target_x - lr_border - gutter_width, target_y - ui().box_tb_border(), - target_x + target_width + gutter_width + lr_border, target_y + target_height + ui().box_tb_border(), - (m_items[0].flags & FLAG_REDTEXT) ? UI_RED_COLOR : ui().colors().background_color()); - ui().draw_text_full( - container(), - text, - target_x, target_y, target_width, - text_layout::text_justify::LEFT, text_layout::word_wrapping::WORD, - mame_ui_manager::NORMAL, ui().colors().text_color(), ui().colors().text_bg_color(), - nullptr, nullptr); - - // draw the "return to prior menu" text with a hilight behind it - highlight( - target_x + 0.5f * UI_LINE_WIDTH, - target_y + target_height - line_height, - target_x + target_width - 0.5f * UI_LINE_WIDTH, - target_y + target_height, - ui().colors().selected_bg_color()); - ui().draw_text_full( - container(), - backtext, - target_x, target_y + target_height - line_height, target_width, - text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, - mame_ui_manager::NORMAL, ui().colors().selected_color(), ui().colors().selected_bg_color(), - nullptr, nullptr); - - // artificially set the hover to the last item so a double-click exits - m_hover = m_items.size() - 1; -} - //------------------------------------------------- // map_mouse - map mouse pointer location to menu @@ -978,16 +905,11 @@ void menu::handle_events(uint32_t flags, event &ev) // caught scroll event case ui_event::type::MOUSE_WHEEL: - if (!(flags & PROCESS_ONLYCHAR)) + if (!custom_mouse_scroll((0 < local_menu_event.zdelta) ? -local_menu_event.num_lines : local_menu_event.num_lines) && !(flags & (PROCESS_ONLYCHAR | PROCESS_CUSTOM_NAV))) { if (local_menu_event.zdelta > 0) { - if (flags & PROCESS_CUSTOM_NAV) // FIXME: DAT menu logic - let the derived class handle this - { - top_line -= local_menu_event.num_lines; - return; - } - else if (is_first_selected()) + if (is_first_selected()) { select_last_item(); } @@ -1002,12 +924,7 @@ void menu::handle_events(uint32_t flags, event &ev) } else { - if (flags & PROCESS_CUSTOM_NAV) // FIXME: DAT menu logic - let the derived class handle this - { - top_line += local_menu_event.num_lines; - return; - } - else if (is_last_selected()) + if (is_last_selected()) { select_first_item(); } @@ -1045,8 +962,7 @@ void menu::handle_events(uint32_t flags, event &ev) void menu::handle_keys(uint32_t flags, int &iptkey) { - bool ignorepause = stack_has_special_main_menu(); - int code; + bool const ignorepause = (flags & PROCESS_IGNOREPAUSE) || stack_has_special_main_menu(); // bail if no items if (m_items.empty()) @@ -1063,6 +979,16 @@ void menu::handle_keys(uint32_t flags, int &iptkey) return; } + // UI configure hides the menus + if (!(flags & PROCESS_NOKEYS) && exclusive_input_pressed(iptkey, IPT_UI_CONFIGURE, 0) && !m_global_state.stack_has_special_main_menu()) + { + if (m_one_shot) + stack_pop(); + else + m_global_state.hide_menu(); + return; + } + // bail out if (flags & PROCESS_ONLYCHAR) return; @@ -1082,11 +1008,15 @@ void menu::handle_keys(uint32_t flags, int &iptkey) bool const ignoreleft = !(flags & PROCESS_LR_ALWAYS) && !(selected_item().flags & FLAG_LEFT_ARROW); bool const ignoreright = !(flags & PROCESS_LR_ALWAYS) && !(selected_item().flags & FLAG_RIGHT_ARROW); - // accept left/right keys as-is with repeat + // accept left/right/prev/next keys as-is with repeat if appropriate if (!ignoreleft && exclusive_input_pressed(iptkey, IPT_UI_LEFT, (flags & PROCESS_LR_REPEAT) ? 6 : 0)) return; if (!ignoreright && exclusive_input_pressed(iptkey, IPT_UI_RIGHT, (flags & PROCESS_LR_REPEAT) ? 6 : 0)) return; + if (exclusive_input_pressed(iptkey, IPT_UI_PREV_GROUP, 0)) + return; + if (exclusive_input_pressed(iptkey, IPT_UI_NEXT_GROUP, 0)) + return; // up backs up by one item if (exclusive_input_pressed(iptkey, IPT_UI_UP, 6)) @@ -1187,10 +1117,23 @@ void menu::handle_keys(uint32_t flags, int &iptkey) // see if any other UI keys are pressed if (iptkey == IPT_INVALID) { - for (code = IPT_UI_FIRST + 1; code < IPT_UI_LAST; code++) + for (int code = IPT_UI_FIRST + 1; code < IPT_UI_LAST; code++) { - if (code == IPT_UI_CONFIGURE || (code == IPT_UI_LEFT && ignoreleft) || (code == IPT_UI_RIGHT && ignoreright) || (code == IPT_UI_PAUSE && ignorepause)) - continue; + switch (code) + { + case IPT_UI_LEFT: + if (ignoreleft) + continue; + break; + case IPT_UI_RIGHT: + if (ignoreright) + continue; + break; + case IPT_UI_PAUSE: + if (ignorepause) + continue; + break; + } if (exclusive_input_pressed(iptkey, code, 0)) break; } @@ -1258,7 +1201,7 @@ void menu::do_handle() // let implementation add other items populate(m_customtop, m_custombottom); } - handle(); + handle(process()); } @@ -1271,26 +1214,10 @@ void menu::do_handle() // and calls the menu handler //------------------------------------------------- -uint32_t menu::ui_handler(render_container &container, mame_ui_manager &mui) +delegate<uint32_t (render_container &)> menu::get_ui_handler(mame_ui_manager &mui) { - global_state_ptr const state(get_global_state(mui.machine())); - - // if we have no menus stacked up, start with the main menu - if (!state->topmost_menu<menu>()) - state->stack_push(std::unique_ptr<menu>(make_unique_clear<menu_main>(mui, container))); - - // update the menu state - if (state->topmost_menu<menu>()) - state->topmost_menu<menu>()->do_handle(); - - // clear up anything pending to be released - state->clear_free_list(); - - // if the menus are to be hidden, return a cancel here - if (mui.is_menu_active() && ((mui.machine().ui_input().pressed(IPT_UI_CONFIGURE) && !state->stack_has_special_main_menu()) || !state->topmost_menu<menu>())) - return UI_HANDLER_CANCEL; - - return 0; + global_state &state(get_global_state(mui)); + return delegate<uint32_t (render_container &)>(&global_state::ui_handler, &state); } /*************************************************************************** @@ -1303,7 +1230,7 @@ uint32_t menu::ui_handler(render_container &container, mame_ui_manager &mui) void menu::highlight(float x0, float y0, float x1, float y1, rgb_t bgcolor) { - container().add_quad(x0, y0, x1, y1, bgcolor, m_global_state->hilight_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(1) | PRIMFLAG_PACKABLE); + container().add_quad(x0, y0, x1, y1, bgcolor, m_global_state.hilight_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXWRAP(1) | PRIMFLAG_PACKABLE); } @@ -1313,7 +1240,7 @@ void menu::highlight(float x0, float y0, float x1, float y1, rgb_t bgcolor) void menu::draw_arrow(float x0, float y0, float x1, float y1, rgb_t fgcolor, uint32_t orientation) { - container().add_quad(x0, y0, x1, y1, fgcolor, m_global_state->arrow_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(orientation) | PRIMFLAG_PACKABLE); + container().add_quad(x0, y0, x1, y1, fgcolor, m_global_state.arrow_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_TEXORIENT(orientation) | PRIMFLAG_PACKABLE); } @@ -1347,8 +1274,8 @@ void menu::extra_text_draw_box(float origx1, float origx2, float origy, float ys void menu::draw_background() { // draw background image if available - if (ui().options().use_background_image() && m_global_state->bgrnd_bitmap() && m_global_state->bgrnd_bitmap()->valid()) - container().add_quad(0.0f, 0.0f, 1.0f, 1.0f, rgb_t::white(), m_global_state->bgrnd_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + if (ui().options().use_background_image() && m_global_state.bgrnd_bitmap() && m_global_state.bgrnd_bitmap()->valid()) + container().add_quad(0.0f, 0.0f, 1.0f, 1.0f, rgb_t::white(), m_global_state.bgrnd_texture(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); } diff --git a/src/frontend/mame/ui/menu.h b/src/frontend/mame/ui/menu.h index 958c1e86af8..b2111168dc4 100644 --- a/src/frontend/mame/ui/menu.h +++ b/src/frontend/mame/ui/menu.h @@ -42,11 +42,9 @@ public: FLAG_LEFT_ARROW = 1U << 0, FLAG_RIGHT_ARROW = 1U << 1, FLAG_INVERT = 1U << 2, - FLAG_MULTILINE = 1U << 3, - FLAG_REDTEXT = 1U << 4, - FLAG_DISABLE = 1U << 5, - FLAG_UI_HEADING = 1U << 7, - FLAG_COLOR_BOX = 1U << 8 + FLAG_DISABLE = 1U << 4, + FLAG_UI_HEADING = 1U << 5, + FLAG_COLOR_BOX = 1U << 6 }; virtual ~menu(); @@ -60,11 +58,8 @@ public: void item_append(menu_item_type type, uint32_t flags = 0); void item_append_on_off(const std::string &text, bool state, uint32_t flags, void *ref, menu_item_type type = menu_item_type::UNKNOWN); - // Global initialization - static void init(running_machine &machine, ui_options &mopt); - // reset the menus, clearing everything - static void stack_reset(running_machine &machine) { get_global_state(machine)->stack_reset(); } + static void stack_reset(mame_ui_manager &ui) { get_global_state(ui).stack_reset(); } // push a new menu onto the stack template <typename T, typename... Params> @@ -81,28 +76,24 @@ public: } // pop a menu from the stack - static void stack_pop(running_machine &machine) { get_global_state(machine)->stack_pop(); } + static void stack_pop(mame_ui_manager &ui) { get_global_state(ui).stack_pop(); } // test if one of the menus in the stack requires hide disable - static bool stack_has_special_main_menu(running_machine &machine) { return get_global_state(machine)->stack_has_special_main_menu(); } + static bool stack_has_special_main_menu(mame_ui_manager &ui) { return get_global_state(ui).stack_has_special_main_menu(); } // master handler - static uint32_t ui_handler(render_container &container, mame_ui_manager &mui); + static delegate<uint32_t (render_container &)> get_ui_handler(mame_ui_manager &mui); // Used by sliders void validate_selection(int scandir); void do_handle(); -private: - virtual void draw(uint32_t flags); - void draw_text_box(); - protected: using bitmap_ptr = widgets_manager::bitmap_ptr; using texture_ptr = widgets_manager::texture_ptr; - // flags to pass to process + // flags to pass to set_process_flags enum { PROCESS_NOKEYS = 1 << 0, @@ -112,7 +103,7 @@ protected: PROCESS_CUSTOM_ONLY = 1 << 4, PROCESS_ONLYCHAR = 1 << 5, PROCESS_NOINPUT = 1 << 6, - PROCESS_NOIMAGE = 1 << 7 + PROCESS_IGNOREPAUSE = 1 << 7 }; // options for reset @@ -139,19 +130,16 @@ protected: running_machine &machine() const { return m_ui.machine(); } render_container &container() const { return m_container; } + void set_one_shot(bool oneshot) { m_one_shot = oneshot; } void set_needs_prev_menu_item(bool needs) { m_needs_prev_menu_item = needs; } void reset(reset_options options); void reset_parent(reset_options options) { m_parent->reset(options); } - template <typename T> T *topmost_menu() const { return m_global_state->topmost_menu<T>(); } - template <typename T> static T *topmost_menu(running_machine &machine) { return get_global_state(machine)->topmost_menu<T>(); } - void stack_pop() { m_global_state->stack_pop(); } - void stack_reset() { m_global_state->stack_reset(); } - bool stack_has_special_main_menu() const { return m_global_state->stack_has_special_main_menu(); } - - // process a menu, drawing it and returning any interesting events - const event *process(uint32_t flags, float x0 = 0.0f, float y0 = 0.0f); - void process_parent() { m_parent->process(PROCESS_NOINPUT); } + template <typename T> T *topmost_menu() const { return m_global_state.topmost_menu<T>(); } + template <typename T> static T *topmost_menu(mame_ui_manager &ui) { return get_global_state(ui).topmost_menu<T>(); } + void stack_pop() { m_global_state.stack_pop(); } + void stack_reset() { m_global_state.stack_reset(); } + bool stack_has_special_main_menu() const { return m_global_state.stack_has_special_main_menu(); } menu_item &item(int index) { return m_items[index]; } menu_item const &item(int index) const { return m_items[index]; } @@ -179,6 +167,7 @@ protected: void clear_hover() { m_hover = m_items.size() + 1; } // scroll position control + void set_top_line(int index) { top_line = (0 < index) ? (index - 1) : index; } void centre_selection() { top_line = m_selected - (m_visible_lines / 2); } // test if the given key is pressed and we haven't already reported a key @@ -190,7 +179,7 @@ protected: // highlight void highlight(float x0, float y0, float x1, float y1, rgb_t bgcolor); - render_texture *hilight_main_texture() { return m_global_state->hilight_main_texture(); } + render_texture *hilight_main_texture() { return m_global_state.hilight_main_texture(); } // draw arrow void draw_arrow(float x0, float y0, float x1, float y1, rgb_t fgcolor, uint32_t orientation); @@ -274,14 +263,21 @@ protected: } // overridable event handling + void set_process_flags(uint32_t flags) { m_process_flags = flags; } virtual void handle_events(uint32_t flags, event &ev); virtual void handle_keys(uint32_t flags, int &iptkey); virtual bool custom_ui_cancel() { return false; } virtual bool custom_mouse_down() { return false; } + virtual bool custom_mouse_scroll(int lines) { return false; } + + // event notifications + virtual void menu_activated() { } + virtual void menu_deactivated() { } + virtual void menu_dismissed() { } static bool is_selectable(menu_item const &item) { - return ((item.flags & (menu::FLAG_MULTILINE | menu::FLAG_DISABLE)) == 0 && item.type != menu_item_type::SEPARATOR); + return (!(item.flags & menu::FLAG_DISABLE) && (item.type != menu_item_type::SEPARATOR)); } // get arrows status @@ -295,7 +291,7 @@ private: class global_state : public widgets_manager { public: - global_state(running_machine &machine, ui_options const &options); + global_state(mame_ui_manager &ui); global_state(global_state const &) = delete; global_state(global_state &&) = delete; ~global_state(); @@ -312,70 +308,88 @@ private: void clear_free_list(); bool stack_has_special_main_menu() const; - private: - running_machine &m_machine; + void hide_menu() { m_hide = true; } + + uint32_t ui_handler(render_container &container); + protected: + mame_ui_manager &m_ui; + + private: bitmap_ptr m_bgrnd_bitmap; texture_ptr m_bgrnd_texture; std::unique_ptr<menu> m_stack; std::unique_ptr<menu> m_free; + + bool m_hide; }; - using global_state_ptr = std::shared_ptr<global_state>; - using global_state_map = std::map<running_machine *, global_state_ptr>; + + // this is to satisfy the std::any requirement that objects be copyable + class global_state_wrapper : public global_state + { + public: + global_state_wrapper(mame_ui_manager &ui) : global_state(ui) { } + global_state_wrapper(global_state_wrapper const &that) : global_state(that.m_ui) { } + }; + + // process a menu, drawing it and returning any interesting events + const event *process(); + virtual void draw(uint32_t flags); // request the specific handling of the game selection main menu bool is_special_main_menu() const; void set_special_main_menu(bool disable); - // To be reimplemented in the menu subclass + // to be implemented in derived classes virtual void populate(float &customtop, float &custombottom) = 0; - // To be reimplemented in the menu subclass - virtual void handle() = 0; + // to be implemented in derived classes + virtual void handle(event const *ev) = 0; // push a new menu onto the stack - static void stack_push(std::unique_ptr<menu> &&menu) { get_global_state(menu->machine())->stack_push(std::move(menu)); } + static void stack_push(std::unique_ptr<menu> &&menu) { menu->m_global_state.stack_push(std::move(menu)); } void extra_text_draw_box(float origx1, float origx2, float origy, float yspan, std::string_view text, int direction); bool first_item_visible() const { return top_line <= 0; } bool last_item_visible() const { return (top_line + m_visible_lines) >= m_items.size(); } - static void exit(running_machine &machine); - static global_state_ptr get_global_state(running_machine &machine); - - int m_selected; // which item is selected - int m_hover; // which item is being hovered over - std::vector<menu_item> m_items; // array of items + static global_state &get_global_state(mame_ui_manager &ui); -protected: // TODO: remove need to expose these +protected: // TODO: remove need to expose these - only used here and in selmenu.cpp int top_line; // main box top line int m_visible_lines; // main box visible lines int m_visible_items; // number of visible items private: - global_state_ptr const m_global_state; - bool m_special_main_menu; - bool m_needs_prev_menu_item; - mame_ui_manager &m_ui; // UI we are attached to - render_container &m_container; // render_container we render to - std::unique_ptr<menu> m_parent; // pointer to parent menu - event m_event; // the UI event that occurred + global_state &m_global_state; // reference to global state for session + mame_ui_manager &m_ui; // UI we are attached to + render_container &m_container; // render_container we render to + std::unique_ptr<menu> m_parent; // pointer to parent menu in the stack + + std::vector<menu_item> m_items; // array of items - float m_customtop; // amount of extra height to add at the top - float m_custombottom; // amount of extra height to add at the bottom + uint32_t m_process_flags; // event processing options + int m_selected; // which item is selected + int m_hover; // which item is being hovered over + bool m_special_main_menu; // true if no real emulation running under the menu + bool m_one_shot; // true for menus outside the normal stack + bool m_needs_prev_menu_item; // true to automatically create item to dismiss menu + bool m_active; // whether the menu is currently visible and topmost - int m_resetpos; // reset position - void *m_resetref; // reset reference + event m_event; // the UI event that occurred + + float m_customtop; // amount of extra height to add at the top + float m_custombottom; // amount of extra height to add at the bottom + + int m_resetpos; // item index to select after repopulating + void *m_resetref; // item reference value to select after repopulating bool m_mouse_hit; bool m_mouse_button; float m_mouse_x; float m_mouse_y; - - static std::mutex s_global_state_guard; - static global_state_map s_global_states; }; } // namespace ui diff --git a/src/frontend/mame/ui/miscmenu.cpp b/src/frontend/mame/ui/miscmenu.cpp index 135963406ad..42c963ee083 100644 --- a/src/frontend/mame/ui/miscmenu.cpp +++ b/src/frontend/mame/ui/miscmenu.cpp @@ -86,21 +86,19 @@ menu_bios_selection::~menu_bios_selection() menu_bios_selection - menu that -------------------------------------------------*/ -void menu_bios_selection::handle() +void menu_bios_selection::handle(event const *ev) { // process the menu - const event *menu_event = process(0); - - if (menu_event != nullptr && menu_event->itemref != nullptr) + if (ev && ev->itemref) { - if ((uintptr_t)menu_event->itemref == 1 && menu_event->iptkey == IPT_UI_SELECT) + if ((uintptr_t)ev->itemref == 1 && ev->iptkey == IPT_UI_SELECT) machine().schedule_hard_reset(); else { - device_t *dev = (device_t *)menu_event->itemref; + device_t *dev = (device_t *)ev->itemref; int bios_val = 0; - switch (menu_event->iptkey) + switch (ev->iptkey) { // reset to default case IPT_UI_SELECT: @@ -111,7 +109,7 @@ void menu_bios_selection::handle() case IPT_UI_LEFT: case IPT_UI_RIGHT: { int const cnt = ([bioses = romload::entries(dev->rom_region()).get_system_bioses()] () { return std::distance(bioses.begin(), bioses.end()); })(); - bios_val = dev->system_bios() + ((menu_event->iptkey == IPT_UI_LEFT) ? -1 : +1); + bios_val = dev->system_bios() + ((ev->iptkey == IPT_UI_LEFT) ? -1 : +1); // wrap if (bios_val < 1) @@ -181,18 +179,21 @@ void menu_network_devices::populate(float &customtop, float &custombottom) menu_network_devices - menu that -------------------------------------------------*/ -void menu_network_devices::handle() +void menu_network_devices::handle(event const *ev) { - /* process the menu */ - const event *menu_event = process(0); - - if (menu_event != nullptr && menu_event->itemref != nullptr) + // process the menu + if (ev && ev->itemref) { - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) { - device_network_interface *network = (device_network_interface *)menu_event->itemref; + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) + { + device_network_interface *network = (device_network_interface *)ev->itemref; int curr = network->get_interface(); - if (menu_event->iptkey == IPT_UI_LEFT) curr--; else curr++; - if (curr==-2) curr = netdev_count() - 1; + if (ev->iptkey == IPT_UI_LEFT) + curr--; + else + curr++; + if (curr == -2) + curr = netdev_count() - 1; network->set_interface(curr); reset(reset_options::REMEMBER_REF); } @@ -205,7 +206,7 @@ void menu_network_devices::handle() information menu -------------------------------------------------*/ -menu_bookkeeping::menu_bookkeeping(mame_ui_manager &mui, render_container &container) : menu(mui, container) +menu_bookkeeping::menu_bookkeeping(mame_ui_manager &mui, render_container &container) : menu_textbox(mui, container) { } @@ -213,71 +214,86 @@ menu_bookkeeping::~menu_bookkeeping() { } -void menu_bookkeeping::handle() +void menu_bookkeeping::menu_activated() { - /* process the menu */ - process(0); - - /* if the time has rolled over another second, regenerate */ - attotime const curtime = machine().time(); - if (prevtime.seconds() != curtime.seconds()) - reset(reset_options::REMEMBER_POSITION); + // stuff can change while the menu is hidden + reset_layout(); } -void menu_bookkeeping::populate(float &customtop, float &custombottom) +void menu_bookkeeping::populate_text(std::optional<text_layout> &layout, float &width, int &lines) { - int tickets = machine().bookkeeping().get_dispensed_tickets(); - std::ostringstream tempstring; - int ctrnum; + if (!layout || (layout->width() != width)) + { + rgb_t const color = ui().colors().text_color(); + layout.emplace(ui().create_layout(container(), width)); - /* show total time first */ - prevtime = machine().time(); - if (prevtime.seconds() >= (60 * 60)) - util::stream_format(tempstring, _("Uptime: %1$d:%2$02d:%3$02d\n\n"), prevtime.seconds() / (60 * 60), (prevtime.seconds() / 60) % 60, prevtime.seconds() % 60); - else - util::stream_format(tempstring, _("Uptime: %1$d:%2$02d\n\n"), (prevtime.seconds() / 60) % 60, prevtime.seconds() % 60); + // show total time first + prevtime = machine().time(); + if (prevtime.seconds() >= (60 * 60)) + layout->add_text(util::string_format(_("Uptime: %1$d:%2$02d:%3$02d\n\n"), prevtime.seconds() / (60 * 60), (prevtime.seconds() / 60) % 60, prevtime.seconds() % 60), color); + else + layout->add_text(util::string_format(_("Uptime: %1$d:%2$02d\n\n"), (prevtime.seconds() / 60) % 60, prevtime.seconds() % 60), color); - /* show tickets at the top */ - if (tickets > 0) - util::stream_format(tempstring, _("Tickets dispensed: %1$d\n\n"), tickets); + // show tickets at the top + int const tickets = machine().bookkeeping().get_dispensed_tickets(); + if (tickets > 0) + layout->add_text(util::string_format(_("Tickets dispensed: %1$d\n\n"), tickets), color); - /* loop over coin counters */ - for (ctrnum = 0; ctrnum < bookkeeping_manager::COIN_COUNTERS; ctrnum++) - { - int count = machine().bookkeeping().coin_counter_get_count(ctrnum); - - /* display the coin counter number */ - /* display how many coins */ - /* display whether or not we are locked out */ - util::stream_format(tempstring, - (count == 0) ? _("Coin %1$c: NA%3$s\n") : _("Coin %1$c: %2$d%3$s\n"), - ctrnum + 'A', - count, - machine().bookkeeping().coin_lockout_get_state(ctrnum) ? _(" (locked)") : ""); + // loop over coin counters + for (int ctrnum = 0; ctrnum < bookkeeping_manager::COIN_COUNTERS; ctrnum++) + { + int const count = machine().bookkeeping().coin_counter_get_count(ctrnum); + bool const locked = machine().bookkeeping().coin_lockout_get_state(ctrnum); + + // display the coin counter number + // display how many coins + // display whether or not we are locked out + layout->add_text( + util::string_format( + (count == 0) ? _("Coin %1$c: NA%3$s\n") : _("Coin %1$c: %2$d%3$s\n"), + ctrnum + 'A', + count, + locked ? _(" (locked)") : ""), + color); + } + + lines = layout->lines(); } + width = layout->actual_width(); +} - /* append the single item */ - item_append(tempstring.str(), FLAG_MULTILINE, nullptr); +void menu_bookkeeping::populate(float &customtop, float &custombottom) +{ } +void menu_bookkeeping::handle(event const *ev) +{ + // if the time has rolled over another second, regenerate + // TODO: what about other bookkeeping events happening with the menu open? + attotime const curtime = machine().time(); + if (curtime.seconds() != prevtime.seconds()) + reset_layout(); + + if (ev) + handle_key(ev->iptkey); +} + + /*------------------------------------------------- menu_crosshair - handle the crosshair settings menu -------------------------------------------------*/ -void menu_crosshair::handle() +void menu_crosshair::handle(event const *ev) { - // process the menu - event const *const menu_event(process(PROCESS_LR_REPEAT)); - // handle events - if (menu_event && menu_event->itemref) + if (ev && ev->itemref) { - crosshair_item_data &data(*reinterpret_cast<crosshair_item_data *>(menu_event->itemref)); + crosshair_item_data &data(*reinterpret_cast<crosshair_item_data *>(ev->itemref)); bool changed(false); int newval(data.cur); - switch (menu_event->iptkey) + switch (ev->iptkey) { // if selected, reset to default value case IPT_UI_SELECT: @@ -325,7 +341,7 @@ void menu_crosshair::handle() // crosshair graphic name if (data.type == CROSSHAIR_ITEM_PIC) { - switch (menu_event->iptkey) + switch (ev->iptkey) { case IPT_UI_SELECT: { @@ -371,6 +387,7 @@ void menu_crosshair::handle() menu_crosshair::menu_crosshair(mame_ui_manager &mui, render_container &container) : menu(mui, container) { + set_process_flags(PROCESS_LR_REPEAT); } void menu_crosshair::populate(float &customtop, float &custombottom) @@ -559,12 +576,12 @@ void menu_quit_game::populate(float &customtop, float &custombottom) { } -void menu_quit_game::handle() +void menu_quit_game::handle(event const *ev) { - /* request a reset */ + // request a reset machine().schedule_exit(); - /* reset the menu stack */ + // reset the menu stack stack_reset(); } @@ -582,21 +599,19 @@ menu_export::~menu_export() } //------------------------------------------------- -// handlethe options menu +// handle the export menu //------------------------------------------------- -void menu_export::handle() +void menu_export::handle(event const *ev) { // process the menu - process_parent(); - const event *const menu_event = process(PROCESS_NOIMAGE); - if (menu_event && menu_event->itemref) + if (ev && ev->itemref) { - switch (uintptr_t(menu_event->itemref)) + switch (uintptr_t(ev->itemref)) { case 1: case 3: - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) { std::string filename("exported"); emu_file infile(ui().options().ui_path(), OPEN_FLAG_READ); @@ -631,7 +646,7 @@ void menu_export::handle() }; // do we want to show devices? - bool include_devices = uintptr_t(menu_event->itemref) == 1; + bool include_devices = uintptr_t(ev->itemref) == 1; // and do the dirty work info_xml_creator creator(machine().options()); @@ -641,7 +656,7 @@ void menu_export::handle() } break; case 2: - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) { std::string filename("exported"); emu_file infile(ui().options().ui_path(), OPEN_FLAG_READ); @@ -704,13 +719,10 @@ menu_machine_configure::menu_machine_configure( mame_ui_manager &mui, render_container &container, ui_system_info const &info, - std::function<void (bool, bool)> &&handler, - float x0, float y0) + std::function<void (bool, bool)> &&handler) : menu(mui, container) , m_handler(std::move(handler)) , m_sys(info) - , m_x0(x0) - , m_y0(y0) , m_curbios(0) , m_was_favorite(mame_machine_manager::instance()->favorite().is_favorite_system(*info.driver)) , m_want_favorite(m_was_favorite) @@ -737,19 +749,18 @@ menu_machine_configure::~menu_machine_configure() } //------------------------------------------------- -// handlethe options menu +// handle the machine options menu //------------------------------------------------- -void menu_machine_configure::handle() +void menu_machine_configure::handle(event const *ev) { // process the menu - process_parent(); - const event *menu_event = process(PROCESS_NOIMAGE, m_x0, m_y0); - if (menu_event != nullptr && menu_event->itemref != nullptr) + //process_parent(); FIXME: drawn in the wrong order, can't see menu + if (ev && ev->itemref) { - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) { - switch ((uintptr_t)menu_event->itemref) + switch ((uintptr_t)ev->itemref) { case SAVE: { @@ -773,24 +784,24 @@ void menu_machine_configure::handle() reset(reset_options::REMEMBER_POSITION); break; case CONTROLLER: - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) menu::stack_push<submenu>(ui(), container(), submenu::control_options(), m_sys.driver, &m_opts); break; case VIDEO: - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) menu::stack_push<submenu>(ui(), container(), submenu::video_options(), m_sys.driver, &m_opts); break; case ADVANCED: - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) menu::stack_push<submenu>(ui(), container(), submenu::advanced_options(), m_sys.driver, &m_opts); break; default: break; } } - else if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + else if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { - (menu_event->iptkey == IPT_UI_LEFT) ? --m_curbios : ++m_curbios; + (ev->iptkey == IPT_UI_LEFT) ? --m_curbios : ++m_curbios; m_opts.set_value(OPTION_BIOS, m_bios[m_curbios].second, OPTION_PRIORITY_CMDLINE); reset(reset_options::REMEMBER_POSITION); } @@ -903,21 +914,19 @@ menu_plugins_configure::~menu_plugins_configure() } //------------------------------------------------- -// handlethe options menu +// handle the plugins menu //------------------------------------------------- -void menu_plugins_configure::handle() +void menu_plugins_configure::handle(event const *ev) { // process the menu bool changed = false; - plugin_options& plugins = mame_machine_manager::instance()->plugins(); - process_parent(); - const event *menu_event = process(PROCESS_NOIMAGE); - if (menu_event != nullptr && menu_event->itemref != nullptr) + plugin_options &plugins = mame_machine_manager::instance()->plugins(); + if (ev && ev->itemref) { - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT || menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT || ev->iptkey == IPT_UI_SELECT) { - plugin_options::plugin *p = plugins.find((const char*)menu_event->itemref); + plugin_options::plugin *p = plugins.find((const char*)ev->itemref); if (p) { p->m_start = !p->m_start; diff --git a/src/frontend/mame/ui/miscmenu.h b/src/frontend/mame/ui/miscmenu.h index 78ed68cc35a..1b19b4c5d45 100644 --- a/src/frontend/mame/ui/miscmenu.h +++ b/src/frontend/mame/ui/miscmenu.h @@ -12,7 +12,7 @@ #pragma once -#include "ui/menu.h" +#include "ui/textbox.h" #include "crsshair.h" #include "emuopts.h" @@ -34,18 +34,22 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; }; -class menu_bookkeeping : public menu +class menu_bookkeeping : public menu_textbox { public: menu_bookkeeping(mame_ui_manager &mui, render_container &container); virtual ~menu_bookkeeping(); +protected: + virtual void menu_activated() override; + virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) override; + private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; attotime prevtime; }; @@ -77,7 +81,7 @@ private: }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; std::vector<crosshair_item_data> m_data; std::vector<std::string> m_pics; @@ -91,7 +95,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; }; class menu_bios_selection : public menu @@ -102,7 +106,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; }; @@ -118,7 +122,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; std::vector<const game_driver*> m_list; }; @@ -134,8 +138,7 @@ public: mame_ui_manager &mui, render_container &container, ui_system_info const &info, - std::function<void (bool, bool)> &&handler = nullptr, - float x0 = 0.0f, float y0 = 0.0f); + std::function<void (bool, bool)> &&handler = nullptr); virtual ~menu_machine_configure(); protected: @@ -157,15 +160,13 @@ private: }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; void setup_bios(); std::function<void (bool, bool)> const m_handler; ui_system_info const &m_sys; emu_options m_opts; - float const m_x0; - float const m_y0; s_bios m_bios; std::size_t m_curbios; bool const m_was_favorite; @@ -184,7 +185,7 @@ public: protected: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; }; diff --git a/src/frontend/mame/ui/optsmenu.cpp b/src/frontend/mame/ui/optsmenu.cpp index 998c8d17c23..d21f069f6f7 100644 --- a/src/frontend/mame/ui/optsmenu.cpp +++ b/src/frontend/mame/ui/optsmenu.cpp @@ -38,6 +38,7 @@ menu_simple_game_options::menu_simple_game_options( : menu(mui, container) , m_handler(std::move(handler)) { + set_process_flags(PROCESS_LR_REPEAT); } //------------------------------------------------- @@ -55,12 +56,11 @@ menu_simple_game_options::~menu_simple_game_options() // handle //------------------------------------------------- -void menu_simple_game_options::handle() +void menu_simple_game_options::handle(event const *ev) { // process the menu - event const *const menu_event(process(PROCESS_LR_REPEAT)); - if (menu_event && menu_event->itemref) - handle_item_event(*menu_event); + if (ev && ev->itemref) + handle_item_event(*ev); } //------------------------------------------------- @@ -167,6 +167,7 @@ menu_game_options::menu_game_options( , m_filter_data(filter_data) , m_main_filter(filter_data.get_current_filter_type()) { + set_process_flags(PROCESS_LR_REPEAT); } //------------------------------------------------- @@ -182,13 +183,11 @@ menu_game_options::~menu_game_options() // handle //------------------------------------------------- -void menu_game_options::handle() +void menu_game_options::handle(event const *ev) { // process the menu - process_parent(); - event const *const menu_event(process(PROCESS_LR_REPEAT | PROCESS_NOIMAGE)); - if (menu_event && menu_event->itemref) - handle_item_event(*menu_event); + if (ev && ev->itemref) + handle_item_event(*ev); } //------------------------------------------------- diff --git a/src/frontend/mame/ui/optsmenu.h b/src/frontend/mame/ui/optsmenu.h index 1809f1bd204..297ec7aa64f 100644 --- a/src/frontend/mame/ui/optsmenu.h +++ b/src/frontend/mame/ui/optsmenu.h @@ -29,7 +29,7 @@ public: protected: virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; - virtual void handle() override; + virtual void handle(event const *ev) override; virtual void populate(float &customtop, float &custombottom) override; void handle_item_event(event const &menu_event); @@ -62,7 +62,7 @@ public: virtual ~menu_game_options() override; protected: - virtual void handle() override; + virtual void handle(event const *ev) override; virtual void populate(float &customtop, float &custombottom) override; void handle_item_event(event const &menu_event); diff --git a/src/frontend/mame/ui/pluginopt.cpp b/src/frontend/mame/ui/pluginopt.cpp index 4bc726c9aea..f21511f1645 100644 --- a/src/frontend/mame/ui/pluginopt.cpp +++ b/src/frontend/mame/ui/pluginopt.cpp @@ -19,14 +19,12 @@ namespace ui { -void menu_plugin::handle() +void menu_plugin::handle(event const *ev) { - const event *menu_event = process(0); - - if (menu_event && menu_event->itemref) + if (ev && ev->itemref) { - if (menu_event->iptkey == IPT_UI_SELECT) - menu::stack_push<menu_plugin_opt>(ui(), container(), (char *)menu_event->itemref); + if (ev->iptkey == IPT_UI_SELECT) + menu::stack_push<menu_plugin_opt>(ui(), container(), (char *)ev->itemref); } } @@ -46,7 +44,7 @@ void menu_plugin::populate(float &customtop, float &custombottom) void menu_plugin::show_menu(mame_ui_manager &mui, render_container &container, char *menu) { // reset the menu stack - menu::stack_reset(mui.machine()); + menu::stack_reset(mui); // add the plugin menu entry menu::stack_push<menu_plugin_opt>(mui, container, menu); @@ -65,19 +63,17 @@ menu_plugin::~menu_plugin() menu_plugin_opt::menu_plugin_opt(mame_ui_manager &mui, render_container &container, std::string_view menu) : ui::menu(mui, container), m_menu(menu), - m_process_flags(0U), m_need_idle(false) { } -void menu_plugin_opt::handle() +void menu_plugin_opt::handle(event const *ev) { - event const *const menu_event = process(m_process_flags); - void *const itemref = menu_event ? menu_event->itemref : get_selection_ref(); + void *const itemref = ev ? ev->itemref : get_selection_ref(); std::string key; - if (menu_event) + if (ev) { - switch (menu_event->iptkey) + switch (ev->iptkey) { case IPT_UI_UP: key = "up"; @@ -91,6 +87,12 @@ void menu_plugin_opt::handle() case IPT_UI_RIGHT: key = "right"; break; + case IPT_UI_PREV_GROUP: + key = "prevgroup"; + break; + case IPT_UI_NEXT_GROUP: + key = "nextgroup"; + break; case IPT_UI_SELECT: key = "select"; break; @@ -104,7 +106,7 @@ void menu_plugin_opt::handle() key = "cancel"; break; case IPT_SPECIAL: - key = std::to_string((u32)menu_event->unichar); + key = std::to_string((u32)ev->unichar); break; default: break; @@ -117,7 +119,7 @@ void menu_plugin_opt::handle() set_selection(reinterpret_cast<void *>(uintptr_t(*result.second))); if (result.first) reset(reset_options::REMEMBER_REF); - else if (menu_event && (menu_event->iptkey == IPT_UI_CANCEL)) + else if (ev && (ev->iptkey == IPT_UI_CANCEL)) stack_pop(); } } @@ -173,7 +175,7 @@ void menu_plugin_opt::populate(float &customtop, float &custombottom) if (sel) set_selection(reinterpret_cast<void *>(uintptr_t(*sel))); - m_process_flags = 0U; + uint32_t process_flags = 0U; m_need_idle = false; if (!flags.empty()) { @@ -188,15 +190,20 @@ void menu_plugin_opt::populate(float &customtop, float &custombottom) flag_start = mflags.find_first_not_of(' '); if (flag == "lralways") - m_process_flags |= PROCESS_LR_ALWAYS; + process_flags |= PROCESS_LR_ALWAYS; else if (flag == "lrrepeat") - m_process_flags |= PROCESS_LR_REPEAT; + process_flags |= PROCESS_LR_REPEAT; else if (flag == "customnav") - m_process_flags |= PROCESS_CUSTOM_NAV; + process_flags |= PROCESS_CUSTOM_NAV; else if (flag == "idle") m_need_idle = true; + else if (flag == "nokeys") + process_flags |= PROCESS_NOKEYS; } + if (process_flags & PROCESS_NOKEYS) + m_need_idle = true; } + set_process_flags(process_flags); } menu_plugin_opt::~menu_plugin_opt() diff --git a/src/frontend/mame/ui/pluginopt.h b/src/frontend/mame/ui/pluginopt.h index c639c3caa15..15196c1ca2d 100644 --- a/src/frontend/mame/ui/pluginopt.h +++ b/src/frontend/mame/ui/pluginopt.h @@ -33,7 +33,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; std::vector<std::string> &m_plugins; }; @@ -49,10 +49,9 @@ protected: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; std::string const m_menu; - uint32_t m_process_flags; bool m_need_idle; }; diff --git a/src/frontend/mame/ui/selector.cpp b/src/frontend/mame/ui/selector.cpp index bbc1bf357c5..6a583346400 100644 --- a/src/frontend/mame/ui/selector.cpp +++ b/src/frontend/mame/ui/selector.cpp @@ -47,32 +47,30 @@ menu_selector::~menu_selector() // handle //------------------------------------------------- -void menu_selector::handle() +void menu_selector::handle(event const *ev) { // process the menu - const event *menu_event = process(0); - - if (menu_event != nullptr && menu_event->itemref != nullptr) + if (ev && ev->itemref) { - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) { int selection(-1); for (size_t idx = 0; (m_str_items.size() > idx) && (0 > selection); ++idx) - if ((void*)&m_str_items[idx] == menu_event->itemref) + if ((void*)&m_str_items[idx] == ev->itemref) selection = int(unsigned(idx)); m_handler(selection); stack_pop(); } - else if (menu_event->iptkey == IPT_SPECIAL) + else if (ev->iptkey == IPT_SPECIAL) { - if (input_character(m_search, menu_event->unichar, uchar_is_printable)) + if (input_character(m_search, ev->unichar, uchar_is_printable)) reset(reset_options::SELECT_FIRST); } // escape pressed with non-empty text clears the text - else if (menu_event->iptkey == IPT_UI_CANCEL && !m_search.empty()) + else if (ev->iptkey == IPT_UI_CANCEL && !m_search.empty()) { m_search.clear(); reset(reset_options::SELECT_FIRST); diff --git a/src/frontend/mame/ui/selector.h b/src/frontend/mame/ui/selector.h index 1f53a244bfb..d8b0abc0472 100644 --- a/src/frontend/mame/ui/selector.h +++ b/src/frontend/mame/ui/selector.h @@ -41,7 +41,7 @@ private: enum { VISIBLE_GAMES_IN_SEARCH = 200 }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; void find_matches(const char *str); diff --git a/src/frontend/mame/ui/selgame.cpp b/src/frontend/mame/ui/selgame.cpp index f748f872f72..0572b1dcf86 100644 --- a/src/frontend/mame/ui/selgame.cpp +++ b/src/frontend/mame/ui/selgame.cpp @@ -147,14 +147,11 @@ menu_select_game::~menu_select_game() } //------------------------------------------------- -// handle +// menu_activated //------------------------------------------------- -void menu_select_game::handle() +void menu_select_game::menu_activated() { - if (!m_prev_selected) - m_prev_selected = item(0).ref; - // if I have to load datfile, perform a hard reset if (ui_globals::reset) { @@ -167,10 +164,21 @@ void menu_select_game::handle() stack_reset(); return; } +} + +//------------------------------------------------- +// handle +//------------------------------------------------- + +void menu_select_game::handle(event const *ev) +{ + if (!m_prev_selected) + m_prev_selected = item(0).ref; // if I have to select software, force software list submenu if (reselect_last::get()) { + // FIXME: this is never hit, need a better way to return to software selection if necessary const ui_system_info *system; const ui_software_info *software; get_selection(software, system); @@ -178,18 +186,16 @@ void menu_select_game::handle() return; } - // ignore pause keys by swallowing them before we process the menu - machine().ui_input().pressed(IPT_UI_PAUSE); + // FIXME: everything above here used to run before events were processed // process the menu - const event *menu_event = process(PROCESS_LR_REPEAT); - if (menu_event) + if (ev) { if (dismiss_error()) { - // reset the error on any future menu_event + // reset the error on any subsequent menu event } - else switch (menu_event->iptkey) + else switch (ev->iptkey) { case IPT_UI_UP: if ((get_focus() == focused_menu::LEFT) && (machine_filter::FIRST < m_filter_highlight)) @@ -220,17 +226,17 @@ void menu_select_game::handle() break; default: - if (menu_event->itemref) + if (ev->itemref) { - switch (menu_event->iptkey) + switch (ev->iptkey) { case IPT_UI_SELECT: if (get_focus() == focused_menu::MAIN) { if (m_populated_favorites) - inkey_select_favorite(menu_event); + inkey_select_favorite(ev); else - inkey_select(menu_event); + inkey_select(ev); } break; @@ -242,8 +248,7 @@ void menu_select_game::handle() ui(), container(), *reinterpret_cast<ui_system_info const *>(m_prev_selected), - nullptr, - menu_event->mouse.x0, menu_event->mouse.y0); + nullptr); } else { @@ -257,8 +262,7 @@ void menu_select_game::handle() { if (changed) reset(empty ? reset_options::SELECT_FIRST : reset_options::REMEMBER_REF); - }, - menu_event->mouse.x0, menu_event->mouse.y0); + }); } break; @@ -289,12 +293,12 @@ void menu_select_game::handle() break; case IPT_UI_FAVORITES: - if (uintptr_t(menu_event->itemref) > skip_main_items) + if (uintptr_t(ev->itemref) > skip_main_items) { favorite_manager &mfav(mame_machine_manager::instance()->favorite()); if (!m_populated_favorites) { - auto const &info(*reinterpret_cast<ui_system_info const *>(menu_event->itemref)); + auto const &info(*reinterpret_cast<ui_system_info const *>(ev->itemref)); auto const &driver(*info.driver); if (!mfav.is_favorite_system(driver)) { @@ -309,7 +313,7 @@ void menu_select_game::handle() } else { - ui_software_info const *const swinfo(reinterpret_cast<ui_software_info const *>(menu_event->itemref)); + ui_software_info const *const swinfo(reinterpret_cast<ui_software_info const *>(ev->itemref)); machine().popmessage(_("%s\n removed from favorites list."), swinfo->longname); mfav.remove_favorite_software(*swinfo); reset(reset_options::SELECT_FIRST); @@ -573,7 +577,7 @@ void menu_select_game::build_available_list() void menu_select_game::force_game_select(mame_ui_manager &mui, render_container &container) { // reset the menu stack - menu::stack_reset(mui.machine()); + menu::stack_reset(mui); // add the quit entry followed by the game select entry menu::stack_push_special_main<menu_quit_game>(mui, container); diff --git a/src/frontend/mame/ui/selgame.h b/src/frontend/mame/ui/selgame.h index 8b54024ece1..4099e248f54 100644 --- a/src/frontend/mame/ui/selgame.h +++ b/src/frontend/mame/ui/selgame.h @@ -32,6 +32,9 @@ public: // force game select menu static void force_game_select(mame_ui_manager &mui, render_container &container); +protected: + void menu_activated() override; + private: enum { @@ -53,7 +56,7 @@ private: static bool s_first_start; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; // drawing virtual float draw_left_panel(float x1, float y1, float x2, float y2) override; diff --git a/src/frontend/mame/ui/selmenu.cpp b/src/frontend/mame/ui/selmenu.cpp index 2228f7b1b60..d55009623e8 100644 --- a/src/frontend/mame/ui/selmenu.cpp +++ b/src/frontend/mame/ui/selmenu.cpp @@ -171,7 +171,7 @@ protected: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; ui_software_info const &m_uiinfo; s_parts const m_parts; @@ -191,7 +191,7 @@ private: bios_selection(mame_ui_manager &mui, render_container &container, s_bios &&biosname, void const *driver, bool software, bool inlist); virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; void const *m_driver; bool m_software, m_inlist; @@ -294,15 +294,14 @@ void menu_select_launch::software_parts::populate(float &customtop, float &custo // handle //------------------------------------------------- -void menu_select_launch::software_parts::handle() +void menu_select_launch::software_parts::handle(event const *ev) { // process the menu - const event *menu_event = process(0); - if (menu_event && (menu_event->iptkey) == IPT_UI_SELECT && menu_event->itemref) + if (ev && (ev->iptkey == IPT_UI_SELECT) && ev->itemref) { for (auto const &elem : m_parts) { - if ((void*)&elem == menu_event->itemref) + if ((void*)&elem == ev->itemref) { launch_system(ui(), *m_uiinfo.driver, &m_uiinfo, &elem.first, nullptr); break; @@ -374,15 +373,14 @@ void menu_select_launch::bios_selection::populate(float &customtop, float &custo // handle //------------------------------------------------- -void menu_select_launch::bios_selection::handle() +void menu_select_launch::bios_selection::handle(event const *ev) { // process the menu - const event *menu_event = process(0); - if (menu_event && menu_event->iptkey == IPT_UI_SELECT && menu_event->itemref) + if (ev && (ev->iptkey == IPT_UI_SELECT) && ev->itemref) { for (auto & elem : m_bios) { - if ((void*)&elem.first == menu_event->itemref) + if ((void*)&elem.first == ev->itemref) { if (!m_software) { @@ -541,6 +539,7 @@ menu_select_launch::menu_select_launch(mame_ui_manager &mui, render_container &c , m_flags(256) { set_needs_prev_menu_item(false); + set_process_flags(PROCESS_LR_REPEAT); } @@ -636,7 +635,7 @@ void menu_select_launch::launch_system(mame_ui_manager &mui, game_driver const & mame_machine_manager::instance()->schedule_new_driver(driver); mui.machine().schedule_hard_reset(); - stack_reset(mui.machine()); + stack_reset(mui); } @@ -675,11 +674,11 @@ void menu_select_launch::custom_render(void *selectedref, float top, float botto tempbuf[0] = make_software_description(*swinfo, system); // next line is year, publisher - tempbuf[1] = string_format(_("%1$s, %2$-.100s"), swinfo->year, swinfo->publisher); + tempbuf[1] = string_format(_("%1$s, %2$s"), swinfo->year, swinfo->publisher); // next line is parent/clone if (!swinfo->parentname.empty()) - tempbuf[2] = string_format(_("Software is clone of: %1$-.100s"), !swinfo->parentlongname.empty() ? swinfo->parentlongname : swinfo->parentname); + tempbuf[2] = string_format(_("Software is clone of: %1$s"), !swinfo->parentlongname.empty() ? swinfo->parentlongname : swinfo->parentname); else tempbuf[2] = _("Software is parent"); @@ -706,7 +705,7 @@ void menu_select_launch::custom_render(void *selectedref, float top, float botto isstar = mame_machine_manager::instance()->favorite().is_favorite_system(driver); // first line is year, manufacturer - tempbuf[0] = string_format(_("%1$s, %2$-.100s"), driver.year, driver.manufacturer); + tempbuf[0] = string_format(_("%1$s, %2$s"), driver.year, driver.manufacturer); // next line is clone/parent status int cloneof = driver_list::non_bios_clone(driver); @@ -714,9 +713,9 @@ void menu_select_launch::custom_render(void *selectedref, float top, float botto if (0 > cloneof) tempbuf[1] = _("Driver is parent"); else if (system) - tempbuf[1] = string_format(_("Driver is clone of: %1$-.100s"), system->parent); + tempbuf[1] = string_format(_("Driver is clone of: %1$s"), system->parent); else - tempbuf[1] = string_format(_("Driver is clone of: %1$-.100s"), driver_list::driver(cloneof).type.fullname()); + tempbuf[1] = string_format(_("Driver is clone of: %1$s"), driver_list::driver(cloneof).type.fullname()); // next line is overall driver status system_flags const &flags(get_system_flags(driver)); @@ -1278,7 +1277,7 @@ void menu_select_launch::draw_toolbar(float x1, float y1, float x2, float y2) float const ypos = y2 + ui().get_line_height() + 2.0f * ui().box_tb_border(); ui().draw_text_box( container(), - have_parent ? _("Return to previous menu") : _("Exit"), + have_parent ? _("Return to Previous Menu") : _("Exit"), text_layout::text_justify::RIGHT, 1.0f - lr_border, ypos, ui().colors().background_color()); } @@ -1407,8 +1406,6 @@ void menu_select_launch::get_title_search(std::string &snaptext, std::string &se void menu_select_launch::handle_keys(uint32_t flags, int &iptkey) { - bool const ignorepause = stack_has_special_main_menu(); - // bail if no items if (item_count() == 0) return; @@ -1603,15 +1600,6 @@ void menu_select_launch::handle_keys(uint32_t flags, int &iptkey) rotate_focus(-1); } - // pause enables/disables pause - if (!m_ui_error && !ignorepause && exclusive_input_pressed(iptkey, IPT_UI_PAUSE, 0)) - { - if (machine().paused()) - machine().resume(); - else - machine().pause(); - } - // handle a toggle cheats request if (!m_ui_error && machine().ui_input().pressed_repeat(IPT_UI_TOGGLE_CHEAT, 0)) mame_machine_manager::instance()->cheat().set_enable(!mame_machine_manager::instance()->cheat().enabled()); @@ -1628,6 +1616,7 @@ void menu_select_launch::handle_keys(uint32_t flags, int &iptkey) { case IPT_UI_FOCUS_NEXT: case IPT_UI_FOCUS_PREV: + case IPT_UI_PAUSE: continue; case IPT_UI_LEFT: if (ignoreleft) @@ -1637,10 +1626,6 @@ void menu_select_launch::handle_keys(uint32_t flags, int &iptkey) if (ignoreright) continue; break; - case IPT_UI_PAUSE: - if (ignorepause) - continue; - break; } if (exclusive_input_pressed(iptkey, code, 0)) diff --git a/src/frontend/mame/ui/selsoft.cpp b/src/frontend/mame/ui/selsoft.cpp index 05ce1302a70..e0d3023050a 100644 --- a/src/frontend/mame/ui/selsoft.cpp +++ b/src/frontend/mame/ui/selsoft.cpp @@ -394,27 +394,25 @@ menu_select_software::~menu_select_software() // handle //------------------------------------------------- -void menu_select_software::handle() +void menu_select_software::handle(event const *ev) { if (m_prev_selected == nullptr) m_prev_selected = item(0).ref; - // ignore pause keys by swallowing them before we process the menu - machine().ui_input().pressed(IPT_UI_PAUSE); + // FIXME: everything above here used run before events were processed // process the menu - const event *menu_event = process(PROCESS_LR_REPEAT); - if (menu_event) + if (ev) { if (dismiss_error()) { - // reset the error on any future event + // reset the error on any subsequent menu event } - else switch (menu_event->iptkey) + else switch (ev->iptkey) { case IPT_UI_SELECT: - if ((get_focus() == focused_menu::MAIN) && menu_event->itemref) - inkey_select(menu_event); + if ((get_focus() == focused_menu::MAIN) && ev->itemref) + inkey_select(ev); break; case IPT_UI_LEFT: @@ -470,12 +468,12 @@ void menu_select_software::handle() break; default: - if (menu_event->itemref) + if (ev->itemref) { - if (menu_event->iptkey == IPT_UI_FAVORITES) + if (ev->iptkey == IPT_UI_FAVORITES) { // handle UI_FAVORITES - ui_software_info *swinfo = (ui_software_info *)menu_event->itemref; + ui_software_info *swinfo = (ui_software_info *)ev->itemref; if ((uintptr_t)swinfo > 2) { diff --git a/src/frontend/mame/ui/selsoft.h b/src/frontend/mame/ui/selsoft.h index d3b2d88f71b..c91495d568d 100644 --- a/src/frontend/mame/ui/selsoft.h +++ b/src/frontend/mame/ui/selsoft.h @@ -40,7 +40,7 @@ private: class machine_data; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; // drawing virtual float draw_left_panel(float x1, float y1, float x2, float y2) override; diff --git a/src/frontend/mame/ui/simpleselgame.cpp b/src/frontend/mame/ui/simpleselgame.cpp index 9ad2fe62dc3..4803b390247 100644 --- a/src/frontend/mame/ui/simpleselgame.cpp +++ b/src/frontend/mame/ui/simpleselgame.cpp @@ -35,7 +35,7 @@ namespace ui { simple_menu_select_game::simple_menu_select_game(mame_ui_manager &mui, render_container &container, const char *gamename) : menu(mui, container) - , m_error(false), m_rerandomize(false) + , m_nomatch(false), m_error(false), m_rerandomize(false) , m_search() , m_driverlist(driver_list::total() + 1) , m_drivlist() @@ -44,6 +44,7 @@ simple_menu_select_game::simple_menu_select_game(mame_ui_manager &mui, render_co , m_cached_unemulated(device_t::feature::NONE), m_cached_imperfect(device_t::feature::NONE) , m_cached_color(ui().colors().background_color()) { + set_process_flags(PROCESS_IGNOREPAUSE); set_needs_prev_menu_item(false); build_driver_list(); if (gamename) @@ -109,34 +110,30 @@ void simple_menu_select_game::build_driver_list() // handle - handle the game select menu //------------------------------------------------- -void simple_menu_select_game::handle() +void simple_menu_select_game::handle(event const *ev) { - // ignore pause keys by swallowing them before we process the menu - machine().ui_input().pressed(IPT_UI_PAUSE); - // process the menu - const event *menu_event = process(0); - if (menu_event) + if (ev) { if (m_error) { - // reset the error on any future menu_event + // reset the error on any subsequent menu event m_error = false; machine().ui_input().reset(); } else { // handle selections - switch(menu_event->iptkey) + switch(ev->iptkey) { case IPT_UI_SELECT: - inkey_select(menu_event); + inkey_select(*ev); break; case IPT_UI_CANCEL: inkey_cancel(); break; case IPT_SPECIAL: - inkey_special(menu_event); + inkey_special(*ev); break; } } @@ -158,9 +155,9 @@ void simple_menu_select_game::handle() // inkey_select //------------------------------------------------- -void simple_menu_select_game::inkey_select(const event *menu_event) +void simple_menu_select_game::inkey_select(const event &menu_event) { - const game_driver *driver = (const game_driver *)menu_event->itemref; + const game_driver *driver = (const game_driver *)menu_event.itemref; if ((uintptr_t)driver == 1) // special case for configure inputs { @@ -217,11 +214,11 @@ void simple_menu_select_game::inkey_cancel() // inkey_special - typed characters append to the buffer //------------------------------------------------- -void simple_menu_select_game::inkey_special(const event *menu_event) +void simple_menu_select_game::inkey_special(const event &menu_event) { // typed characters append to the buffer size_t old_size = m_search.size(); - if (input_character(m_search, menu_event->unichar, uchar_is_printable)) + if (input_character(m_search, menu_event.unichar, uchar_is_printable)) { if (m_search.size() < old_size) m_rerandomize = true; @@ -243,49 +240,41 @@ void simple_menu_select_game::populate(float &customtop, float &custombottom) matchcount++; // if nothing there, add a single multiline item and return - if (matchcount == 0) - { - std::string txt = string_format( - _("No machines found. Please check the rompath specified in the %1$s.ini file.\n\n" - "If this is your first time using %2$s, please see the config.txt file in " - "the docs directory for information on configuring %2$s."), - emulator_info::get_configname(), - emulator_info::get_appname()); - item_append(txt, FLAG_MULTILINE | FLAG_REDTEXT, nullptr); - return; - } + m_nomatch = !matchcount; // otherwise, rebuild the match list - assert(m_drivlist != nullptr); - if (!m_search.empty() || m_matchlist[0] == -1 || m_rerandomize) - m_drivlist->find_approximate_matches(m_search, matchcount, m_matchlist); - m_rerandomize = false; - - // iterate over entries - for (curitem = 0; curitem < matchcount; curitem++) + if (matchcount) { - int curmatch = m_matchlist[curitem]; - if (curmatch != -1) + assert(m_drivlist != nullptr); + if (!m_search.empty() || m_matchlist[0] == -1 || m_rerandomize) + m_drivlist->find_approximate_matches(m_search, matchcount, m_matchlist); + m_rerandomize = false; + + // iterate over entries + for (curitem = 0; curitem < matchcount; curitem++) { - int cloneof = m_drivlist->non_bios_clone(curmatch); - item_append( - m_drivlist->driver(curmatch).type.fullname(), - m_drivlist->driver(curmatch).name, - (cloneof == -1) ? 0 : FLAG_INVERT, - (void *)&m_drivlist->driver(curmatch)); + int curmatch = m_matchlist[curitem]; + if (curmatch != -1) + { + int cloneof = m_drivlist->non_bios_clone(curmatch); + item_append( + m_drivlist->driver(curmatch).type.fullname(), + m_drivlist->driver(curmatch).name, + (cloneof == -1) ? 0 : FLAG_INVERT, + (void *)&m_drivlist->driver(curmatch)); + } } + item_append(menu_item_type::SEPARATOR); } // if we're forced into this, allow general input configuration as well if (stack_has_special_main_menu()) { - item_append(menu_item_type::SEPARATOR); item_append(_("Configure Options"), 0, (void *)1); item_append(_("Exit"), 0, nullptr); } else { - item_append(menu_item_type::SEPARATOR); item_append(_("Return to Previous Menu"), 0, nullptr); } @@ -301,6 +290,23 @@ void simple_menu_select_game::populate(float &customtop, float &custombottom) void simple_menu_select_game::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { + // if no matches, display the error message + if (m_nomatch) + { + ui().draw_text_box( + container(), + string_format( + _("No machines found. Please check the rompath specified in the %1$s.ini file.\n\n" + "If this is your first time using %2$s, please see the config.txt file in " + "the docs directory for information on configuring %2$s."), + emulator_info::get_configname(), + emulator_info::get_appname()), + text_layout::text_justify::CENTER, + 0.5f, origy2 + ui().box_tb_border() + (0.5f * (bottom - ui().box_tb_border())), + UI_RED_COLOR); + return; + } + const game_driver *driver; std::string tempbuf[5]; @@ -328,7 +334,7 @@ void simple_menu_select_game::custom_render(void *selectedref, float top, float tempbuf[1] = string_format(_("%1$s, %2$-.100s"), driver->year, driver->manufacturer); // next line source path - tempbuf[2] = string_format(_("Driver: %1$-.100s"), core_filename_extract_base(driver->type.source())); + tempbuf[2] = string_format(_("Driver: %1$s"), core_filename_extract_base(driver->type.source())); // update cached values if selection changed if (driver != m_cached_driver) @@ -411,7 +417,7 @@ void simple_menu_select_game::force_game_select(mame_ui_manager &mui, render_con char *gamename = (char *)mui.machine().options().system_name(); // reset the menu stack - menu::stack_reset(mui.machine()); + menu::stack_reset(mui); // add the quit entry followed by the game select entry menu::stack_push_special_main<menu_quit_game>(mui, container); diff --git a/src/frontend/mame/ui/simpleselgame.h b/src/frontend/mame/ui/simpleselgame.h index 7a581b5ea32..e5ea310c7ec 100644 --- a/src/frontend/mame/ui/simpleselgame.h +++ b/src/frontend/mame/ui/simpleselgame.h @@ -36,15 +36,16 @@ private: enum { VISIBLE_GAMES_IN_LIST = 15 }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; // internal methods void build_driver_list(); - void inkey_select(const event *menu_event); + void inkey_select(const event &menu_event); void inkey_cancel(); - void inkey_special(const event *menu_event); + void inkey_special(const event &menu_event); // internal state + bool m_nomatch; bool m_error; bool m_rerandomize; std::string m_search; diff --git a/src/frontend/mame/ui/sliders.cpp b/src/frontend/mame/ui/sliders.cpp index 99b3756bfec..e26b76e2302 100644 --- a/src/frontend/mame/ui/sliders.cpp +++ b/src/frontend/mame/ui/sliders.cpp @@ -19,9 +19,13 @@ namespace ui { -menu_sliders::menu_sliders(mame_ui_manager &mui, render_container &container, bool menuless_mode) : menu(mui, container) +menu_sliders::menu_sliders(mame_ui_manager &mui, render_container &container, bool menuless_mode) + : menu(mui, container) + , m_menuless_mode(menuless_mode) + , m_hidden(menuless_mode) { - m_menuless_mode = m_hidden = menuless_mode; + set_one_shot(menuless_mode); + set_process_flags(PROCESS_LR_REPEAT | (m_hidden ? PROCESS_CUSTOM_ONLY : 0)); } menu_sliders::~menu_sliders() @@ -32,32 +36,34 @@ menu_sliders::~menu_sliders() // menu_sliders - handle the sliders menu //------------------------------------------------- -void menu_sliders::handle() +void menu_sliders::handle(event const *ev) { - const event *menu_event; - // process the menu - menu_event = process(PROCESS_LR_REPEAT | (m_hidden ? PROCESS_CUSTOM_ONLY : 0)); - if (menu_event != nullptr) + if (ev) { // handle keys if there is a valid item selected - if (menu_event->itemref != nullptr && menu_event->type == menu_item_type::SLIDER) + if (ev->itemref && (ev->type == menu_item_type::SLIDER)) { - const slider_state *slider = (const slider_state *)menu_event->itemref; + const slider_state *slider = (const slider_state *)ev->itemref; int32_t curvalue = slider->update(nullptr, SLIDER_NOCHANGE); int32_t increment = 0; bool alt_pressed = machine().input().code_pressed(KEYCODE_LALT) || machine().input().code_pressed(KEYCODE_RALT); bool ctrl_pressed = machine().input().code_pressed(KEYCODE_LCONTROL) || machine().input().code_pressed(KEYCODE_RCONTROL); bool shift_pressed = machine().input().code_pressed(KEYCODE_LSHIFT) || machine().input().code_pressed(KEYCODE_RSHIFT); - switch (menu_event->iptkey) + switch (ev->iptkey) { // toggle visibility case IPT_UI_ON_SCREEN_DISPLAY: if (m_menuless_mode) + { stack_pop(); + } else + { m_hidden = !m_hidden; + set_process_flags(PROCESS_LR_REPEAT | (m_hidden ? PROCESS_CUSTOM_ONLY : 0)); + } break; // decrease value @@ -114,9 +120,9 @@ void menu_sliders::handle() // if we are selecting an invalid item and we are hidden, skip to the next one else if (m_hidden) { - // if we got here via up or page up, select the previous item - if (menu_event->iptkey == IPT_UI_UP || menu_event->iptkey == IPT_UI_PAGE_UP) + if (ev->iptkey == IPT_UI_UP || ev->iptkey == IPT_UI_PAGE_UP) { + // if we got here via up or page up, select the previous item if (is_first_selected()) select_last_item(); else @@ -125,10 +131,9 @@ void menu_sliders::handle() validate_selection(-1); } } - - // otherwise select the next item - else if (menu_event->iptkey == IPT_UI_DOWN || menu_event->iptkey == IPT_UI_PAGE_DOWN) + else if (ev->iptkey == IPT_UI_DOWN || ev->iptkey == IPT_UI_PAGE_DOWN) { + // otherwise select the next item if (is_last_selected()) select_first_item(); else @@ -157,7 +162,7 @@ void menu_sliders::populate(float &customtop, float &custombottom) { if (item.type == menu_item_type::SLIDER) { - slider_state* slider = reinterpret_cast<slider_state *>(item.ref); + slider_state *const slider = reinterpret_cast<slider_state *>(item.ref); bool display(true); #if 0 // FIXME: this test should be reimplemented in a dedicated menu @@ -286,30 +291,4 @@ void menu_sliders::custom_render(void *selectedref, float top, float bottom, flo } } - -//------------------------------------------------- -// slider_ui_handler - pushes the slider -// menu on the stack and hands off to the -// standard menu handler -//------------------------------------------------- - -uint32_t menu_sliders::ui_handler(render_container &container, mame_ui_manager &mui) -{ - uint32_t result; - - // if this is the first call, push the sliders menu - if (topmost_menu<menu_sliders>(mui.machine()) == nullptr) - menu::stack_push<menu_sliders>(mui, container, true); - - // handle standard menus - result = menu::ui_handler(container, mui); - - // if we are cancelled, pop the sliders menu - if (result == UI_HANDLER_CANCEL) - menu::stack_pop(mui.machine()); - - menu_sliders *uim = topmost_menu<menu_sliders>(mui.machine()); - return uim && uim->m_menuless_mode ? 0 : UI_HANDLER_CANCEL; -} - } // namespace ui diff --git a/src/frontend/mame/ui/sliders.h b/src/frontend/mame/ui/sliders.h index 4ef399173e3..6dd763b9c2f 100644 --- a/src/frontend/mame/ui/sliders.h +++ b/src/frontend/mame/ui/sliders.h @@ -8,38 +8,33 @@ ***************************************************************************/ -#pragma once - #ifndef MAME_FRONTEND_UI_SLIDERS_H #define MAME_FRONTEND_UI_SLIDERS_H +#pragma once + #include "ui/menu.h" + namespace ui { + class menu_sliders : public menu { public: menu_sliders(mame_ui_manager &mui, render_container &container, bool menuless_mode = false); virtual ~menu_sliders() override; - static uint32_t ui_handler(render_container &container, mame_ui_manager &mui); - protected: virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; private: - enum { - INPUT_GROUPS, - INPUT_SPECIFIC, - }; - virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; - bool m_menuless_mode; + bool const m_menuless_mode; bool m_hidden; }; } // namespace ui -#endif /* MAME_FRONTEND_UI_SLIDERS_H */ +#endif // MAME_FRONTEND_UI_SLIDERS_H diff --git a/src/frontend/mame/ui/slotopt.cpp b/src/frontend/mame/ui/slotopt.cpp index b21a039f86a..e27e6261c63 100644 --- a/src/frontend/mame/ui/slotopt.cpp +++ b/src/frontend/mame/ui/slotopt.cpp @@ -200,7 +200,7 @@ void menu_slot_devices::populate(float &customtop, float &custombottom) item_append(slot.slot_name(), opt_name, item_flags, (void *)&slot); } item_append(menu_item_type::SEPARATOR); - item_append(_("Reset"), 0, ITEMREF_RESET); + item_append(_("Reset Machine"), 0, ITEMREF_RESET); // leave space for the name of the current option at the bottom custombottom = ui().get_line_height() + 3.0f * ui().box_tb_border(); @@ -231,26 +231,24 @@ void menu_slot_devices::custom_render(void *selectedref, float top, float bottom // handle - process an input event //------------------------------------------------- -void menu_slot_devices::handle() +void menu_slot_devices::handle(event const *ev) { // process the menu - event const *const menu_event(process(0)); - - if (menu_event && menu_event->itemref != nullptr) + if (ev && ev->itemref != nullptr) { - if (menu_event->itemref == ITEMREF_RESET) + if (ev->itemref == ITEMREF_RESET) { - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) machine().schedule_hard_reset(); } - else if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + else if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { - device_slot_interface *slot = (device_slot_interface *)menu_event->itemref; - rotate_slot_device(*slot, menu_event->iptkey == IPT_UI_LEFT ? step_t::PREVIOUS : step_t::NEXT); + device_slot_interface *slot = (device_slot_interface *)ev->itemref; + rotate_slot_device(*slot, ev->iptkey == IPT_UI_LEFT ? step_t::PREVIOUS : step_t::NEXT); } - else if (menu_event->iptkey == IPT_UI_SELECT) + else if (ev->iptkey == IPT_UI_SELECT) { - device_slot_interface *slot = (device_slot_interface *)menu_event->itemref; + device_slot_interface *slot = (device_slot_interface *)ev->itemref; device_slot_interface::slot_option const *const option = get_current_option(*slot); if (option) menu::stack_push<menu_device_config>(ui(), container(), slot, option); diff --git a/src/frontend/mame/ui/slotopt.h b/src/frontend/mame/ui/slotopt.h index ec8c08416cf..449d22627aa 100644 --- a/src/frontend/mame/ui/slotopt.h +++ b/src/frontend/mame/ui/slotopt.h @@ -34,7 +34,7 @@ private: virtual void populate(float &customtop, float &custombottom) override; virtual void custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) override; - virtual void handle() override; + virtual void handle(event const *ev) override; device_slot_interface::slot_option const *get_current_option(device_slot_interface &slot) const; void set_slot_device(device_slot_interface &slot, std::string_view val); diff --git a/src/frontend/mame/ui/sndmenu.cpp b/src/frontend/mame/ui/sndmenu.cpp index 8eff1ed1b92..b1842969f8f 100644 --- a/src/frontend/mame/ui/sndmenu.cpp +++ b/src/frontend/mame/ui/sndmenu.cpp @@ -9,12 +9,16 @@ *********************************************************************/ #include "emu.h" -#include "ui/ui.h" #include "ui/sndmenu.h" + #include "ui/selector.h" +#include "ui/ui.h" + #include "../osd/modules/lib/osdobj_common.h" // TODO: remove + namespace ui { + const int menu_sound_options::m_sound_rate[] = { 11025, 22050, 44100, 48000 }; //------------------------------------------------- @@ -70,19 +74,17 @@ menu_sound_options::~menu_sound_options() // handle //------------------------------------------------- -void menu_sound_options::handle() +void menu_sound_options::handle(event const *ev) { bool changed = false; // process the menu - const event *menu_event = process(0); - - if (menu_event != nullptr && menu_event->itemref != nullptr) + if (ev && ev->itemref) { - switch ((uintptr_t)menu_event->itemref) + switch ((uintptr_t)ev->itemref) { case ENABLE_SOUND: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT || menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT || ev->iptkey == IPT_UI_SELECT) { m_sound = !m_sound; changed = true; @@ -90,7 +92,7 @@ void menu_sound_options::handle() break; case ENABLE_COMPRESSOR: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT || menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT || ev->iptkey == IPT_UI_SELECT) { m_compressor = !m_compressor; changed = true; @@ -98,12 +100,12 @@ void menu_sound_options::handle() break; case SAMPLE_RATE: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { - (menu_event->iptkey == IPT_UI_LEFT) ? m_cur_rates-- : m_cur_rates++; + (ev->iptkey == IPT_UI_LEFT) ? m_cur_rates-- : m_cur_rates++; changed = true; } - else if (menu_event->iptkey == IPT_UI_SELECT) + else if (ev->iptkey == IPT_UI_SELECT) { int total = std::size(m_sound_rate); std::vector<std::string> s_sel(total); @@ -121,7 +123,7 @@ void menu_sound_options::handle() break; case ENABLE_SAMPLES: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT || menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT || ev->iptkey == IPT_UI_SELECT) { m_samples = !m_samples; changed = true; diff --git a/src/frontend/mame/ui/sndmenu.h b/src/frontend/mame/ui/sndmenu.h index 2684f9c7854..35ac73981df 100644 --- a/src/frontend/mame/ui/sndmenu.h +++ b/src/frontend/mame/ui/sndmenu.h @@ -16,9 +16,11 @@ #include "ui/menu.h" namespace ui { + //------------------------------------------------- // class sound options menu //------------------------------------------------- + class menu_sound_options : public menu { public: @@ -38,7 +40,7 @@ private: }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; uint16_t m_cur_rates; static const int m_sound_rate[]; @@ -48,4 +50,4 @@ private: } // namespace ui -#endif /* MAME_FRONTEND_UI_SNDMENU_H */ +#endif // MAME_FRONTEND_UI_SNDMENU_H diff --git a/src/frontend/mame/ui/state.cpp b/src/frontend/mame/ui/state.cpp index af56b28e298..72ed3941196 100644 --- a/src/frontend/mame/ui/state.cpp +++ b/src/frontend/mame/ui/state.cpp @@ -82,17 +82,26 @@ menu_load_save_state_base::file_entry::file_entry(std::string &&file_name, std:: // ctor //------------------------------------------------- -menu_load_save_state_base::menu_load_save_state_base(mame_ui_manager &mui, render_container &container, std::string_view header, std::string_view footer, bool must_exist) +menu_load_save_state_base::menu_load_save_state_base( + mame_ui_manager &mui, + render_container &container, + std::string_view header, + std::string_view footer, + bool must_exist, + bool one_shot) : menu(mui, container) , m_switch_poller(machine().input()) , m_header(header) , m_footer(footer) , m_confirm_delete(nullptr) , m_must_exist(must_exist) + , m_one_shot(one_shot) , m_first_time(true) , m_was_paused(false) , m_keys_released(false) { + set_one_shot(one_shot); + set_needs_prev_menu_item(!one_shot); } @@ -212,10 +221,12 @@ void menu_load_save_state_base::populate(float &customtop, float &custombottom) if (m_entries_vec.empty()) { - item_append(_("No save states found"), 0, nullptr); + item_append(_("[no saved states found]"), FLAG_DISABLE, nullptr); set_selection(nullptr); } item_append(menu_item_type::SEPARATOR); + if (m_one_shot) + item_append(_("Cancel"), 0, nullptr); // set up custom render proc customtop = ui().get_line_height() + (3.0f * ui().box_tb_border()); @@ -240,27 +251,28 @@ void menu_load_save_state_base::populate(float &customtop, float &custombottom) // handle //------------------------------------------------- -void menu_load_save_state_base::handle() +void menu_load_save_state_base::handle(event const *ev) { - // process the menu - event const *const event = process(0); - // process the event - if (event && (event->iptkey == IPT_UI_SELECT)) + if (ev && (ev->iptkey == IPT_UI_SELECT)) { - if (event->itemref) + if (ev->itemref) { // user selected one of the entries - file_entry const &entry = file_entry_from_itemref(event->itemref); + file_entry const &entry = file_entry_from_itemref(ev->itemref); slot_selected(std::string(entry.file_name())); } + else + { + stack_pop(); + } } - else if (event && (event->iptkey == IPT_UI_CLEAR)) + else if (ev && (ev->iptkey == IPT_UI_CLEAR)) { - if (event->itemref) + if (ev->itemref) { // prompt to confirm delete - m_confirm_delete = &file_entry_from_itemref(event->itemref); + m_confirm_delete = &file_entry_from_itemref(ev->itemref); m_confirm_prompt = util::string_format( _("Delete saved state %1$s?\nPress %2$s to delete\nPress %3$s to cancel"), m_confirm_delete->visible_name(), @@ -344,7 +356,7 @@ void menu_load_save_state_base::slot_selected(std::string &&name) s_last_file_selected = std::move(name); // no matter what, pop out - menu::stack_pop(machine()); + menu::stack_pop(); } @@ -409,7 +421,13 @@ void menu_load_save_state_base::handle_keys(uint32_t flags, int &iptkey) void menu_load_save_state_base::custom_render(void *selectedref, float top, float bottom, float origx1, float origy1, float origx2, float origy2) { - extra_text_render(top, bottom, origx1, origy1, origx2, origy2, m_header, std::string_view()); + // draw menu title + draw_text_box( + &m_header, &m_header + 1, + origx1, origx2, origy1 - top, origy1 - ui().box_tb_border(), + text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, false, + ui().colors().text_color(), UI_GREEN_COLOR, 1.0f); + std::string_view text[2]; unsigned count(0U); @@ -493,8 +511,8 @@ bool menu_load_save_state_base::is_present(const std::string &name) const // ctor //------------------------------------------------- -menu_load_state::menu_load_state(mame_ui_manager &mui, render_container &container) - : menu_load_save_state_base(mui, container, _("Load State"), _("Select state to load"), true) +menu_load_state::menu_load_state(mame_ui_manager &mui, render_container &container, bool one_shot) + : menu_load_save_state_base(mui, container, _("Load State"), _("Select state to load"), true, one_shot) { } @@ -517,8 +535,8 @@ void menu_load_state::process_file(std::string &&file_name) // ctor //------------------------------------------------- -menu_save_state::menu_save_state(mame_ui_manager &mui, render_container &container) - : menu_load_save_state_base(mui, container, _("Save State"), _("Press a key or joystick button, or select state to overwrite"), false) +menu_save_state::menu_save_state(mame_ui_manager &mui, render_container &container, bool one_shot) + : menu_load_save_state_base(mui, container, _("Save State"), _("Press a key or joystick button, or select state to overwrite"), false, one_shot) { } diff --git a/src/frontend/mame/ui/state.h b/src/frontend/mame/ui/state.h index 4ad3ebcd26f..f6a48331981 100644 --- a/src/frontend/mame/ui/state.h +++ b/src/frontend/mame/ui/state.h @@ -28,12 +28,18 @@ public: virtual ~menu_load_save_state_base() override; protected: - menu_load_save_state_base(mame_ui_manager &mui, render_container &container, std::string_view header, std::string_view footer, bool must_exist); + menu_load_save_state_base( + mame_ui_manager &mui, + render_container &container, + std::string_view header, + std::string_view footer, + bool must_exist, + bool one_shot); virtual void custom_render(void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; virtual void handle_keys(uint32_t flags, int &iptkey) override; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; virtual void process_file(std::string &&file_name) = 0; @@ -67,6 +73,7 @@ private: std::string m_confirm_prompt; file_entry const * m_confirm_delete; bool const m_must_exist; + bool const m_one_shot; bool m_first_time; bool m_was_paused; bool m_keys_released; @@ -86,7 +93,7 @@ private: class menu_load_state : public menu_load_save_state_base { public: - menu_load_state(mame_ui_manager &mui, render_container &container); + menu_load_state(mame_ui_manager &mui, render_container &container, bool one_shot); protected: virtual void process_file(std::string &&file_name) override; @@ -96,7 +103,7 @@ protected: class menu_save_state : public menu_load_save_state_base { public: - menu_save_state(mame_ui_manager &mui, render_container &container); + menu_save_state(mame_ui_manager &mui, render_container &container, bool one_shot); protected: virtual void process_file(std::string &&file_name) override; diff --git a/src/frontend/mame/ui/submenu.cpp b/src/frontend/mame/ui/submenu.cpp index e4bd44763d4..1b55556f564 100644 --- a/src/frontend/mame/ui/submenu.cpp +++ b/src/frontend/mame/ui/submenu.cpp @@ -150,6 +150,8 @@ submenu::submenu(mame_ui_manager &mui, render_container &container, std::vector< , m_options(std::move(suboptions)) , m_driver(drv) { + set_process_flags(PROCESS_LR_REPEAT); + core_options *opts = nullptr; if (m_driver == nullptr) opts = dynamic_cast<core_options *>(&mui.machine().options()); @@ -234,19 +236,16 @@ submenu::~submenu() // handle the options menu //------------------------------------------------- -void submenu::handle() +void submenu::handle(event const *ev) { bool changed = false; std::string error_string, tmptxt; float f_cur, f_step; // process the menu - const event *menu_event = process(PROCESS_LR_REPEAT); - - if (menu_event != nullptr && menu_event->itemref != nullptr && - (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT || menu_event->iptkey == IPT_UI_SELECT)) + if (ev && ev->itemref && (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT || ev->iptkey == IPT_UI_SELECT)) { - option &sm_option = *reinterpret_cast<option *>(menu_event->itemref); + option &sm_option = *reinterpret_cast<option *>(ev->itemref); switch (sm_option.type) { @@ -260,16 +259,16 @@ void submenu::handle() sm_option.options->set_value(sm_option.name, !strcmp(sm_option.entry->value(),"1") ? "0" : "1", OPTION_PRIORITY_CMDLINE); break; case OPTION_INTEGER: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { changed = true; int i_cur = atoi(sm_option.entry->value()); - (menu_event->iptkey == IPT_UI_LEFT) ? i_cur-- : i_cur++; + (ev->iptkey == IPT_UI_LEFT) ? i_cur-- : i_cur++; sm_option.options->set_value(sm_option.name, i_cur, OPTION_PRIORITY_CMDLINE); } break; case OPTION_FLOAT: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { changed = true; f_cur = atof(sm_option.entry->value()); @@ -291,7 +290,7 @@ void submenu::handle() tmptxt = '1' + std::string(precision, '0'); f_step = 1 / atof(tmptxt.c_str()); } - if (menu_event->iptkey == IPT_UI_LEFT) + if (ev->iptkey == IPT_UI_LEFT) f_cur -= f_step; else f_cur += f_step; @@ -300,12 +299,12 @@ void submenu::handle() } break; case OPTION_STRING: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { changed = true; std::string v_cur(sm_option.entry->value()); int cur_value = std::distance(sm_option.value.begin(), std::find(sm_option.value.begin(), sm_option.value.end(), v_cur)); - if (menu_event->iptkey == IPT_UI_LEFT) + if (ev->iptkey == IPT_UI_LEFT) v_cur = sm_option.value[--cur_value]; else v_cur = sm_option.value[++cur_value]; diff --git a/src/frontend/mame/ui/submenu.h b/src/frontend/mame/ui/submenu.h index f5c26c7eecb..4f2a5352715 100644 --- a/src/frontend/mame/ui/submenu.h +++ b/src/frontend/mame/ui/submenu.h @@ -64,7 +64,7 @@ protected: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; std::vector<option> m_options; game_driver const *m_driver; diff --git a/src/frontend/mame/ui/swlist.cpp b/src/frontend/mame/ui/swlist.cpp index ac7235c1b1c..72e076df67c 100644 --- a/src/frontend/mame/ui/swlist.cpp +++ b/src/frontend/mame/ui/swlist.cpp @@ -124,14 +124,12 @@ void menu_software_parts::populate(float &customtop, float &custombottom) // handle //------------------------------------------------- -void menu_software_parts::handle() +void 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(); @@ -239,16 +237,14 @@ void menu_software_list::populate(float &customtop, float &custombottom) // handle //------------------------------------------------- -void menu_software_list::handle() +void menu_software_list::handle(event const *ev) { // process the menu - const event *event = process(0); - - if (event) + if (ev) { - if (event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) { - if (event->itemref == ITEMREF_SWITCH_ITEM_ORDERING) + if (ev->itemref == ITEMREF_SWITCH_ITEM_ORDERING) { m_ordered_by_shortname = !m_ordered_by_shortname; @@ -262,23 +258,23 @@ void menu_software_list::handle() ? _("Switched Order: entries now ordered by shortname") : _("Switched Order: entries now ordered by description")); } - else if (event->itemref) + else if (ev->itemref) { // handle selections - entry_info *info = (entry_info *) event->itemref; + entry_info *info = (entry_info *)ev->itemref; m_result = info->short_name; stack_pop(); } } - else if (event->iptkey == IPT_SPECIAL) + else if (ev->iptkey == IPT_SPECIAL) { - if (input_character(m_search, event->unichar, m_ordered_by_shortname ? is_valid_softlist_part_char : [] (char32_t ch) { return true; })) + if (input_character(m_search, ev->unichar, m_ordered_by_shortname ? is_valid_softlist_part_char : [] (char32_t ch) { return true; })) { // display the popup ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_search); // identify the selected entry - entry_info const *const cur_selected = (uintptr_t(event->itemref) != 1) + entry_info const *const cur_selected = (uintptr_t(ev->itemref) != 1) ? reinterpret_cast<entry_info const *>(get_selection_ref()) : nullptr; @@ -315,7 +311,7 @@ void menu_software_list::handle() } } } - else if (event->iptkey == IPT_UI_CANCEL) + else if (ev->iptkey == IPT_UI_CANCEL) { // reset the char buffer also in this case if (!m_search.empty()) @@ -410,15 +406,13 @@ void menu_software::populate(float &customtop, float &custombottom) // handle //------------------------------------------------- -void menu_software::handle() +void 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(); } } diff --git a/src/frontend/mame/ui/swlist.h b/src/frontend/mame/ui/swlist.h index b62ec167b02..36e5d3c6eaf 100644 --- a/src/frontend/mame/ui/swlist.h +++ b/src/frontend/mame/ui/swlist.h @@ -44,7 +44,7 @@ private: using entry_list = std::list<software_part_menu_entry>; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; // variables entry_list m_entries; @@ -89,7 +89,7 @@ private: bool m_ordered_by_shortname; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; // functions void append_software_entry(const software_info &swinfo); @@ -104,7 +104,7 @@ public: menu_software(mame_ui_manager &mui, render_container &container, const char *interface, software_list_device **result); virtual ~menu_software() override; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; private: const char * m_interface; @@ -113,4 +113,4 @@ private: } // namespace ui -#endif /* MAME_FRONTEND_UI_SWLIST_H */ +#endif // MAME_FRONTEND_UI_SWLIST_H diff --git a/src/frontend/mame/ui/tapectrl.cpp b/src/frontend/mame/ui/tapectrl.cpp index 7881ac420db..aad554982f5 100644 --- a/src/frontend/mame/ui/tapectrl.cpp +++ b/src/frontend/mame/ui/tapectrl.cpp @@ -38,6 +38,7 @@ namespace ui { menu_tape_control::menu_tape_control(mame_ui_manager &mui, render_container &container, cassette_image_device *device) : menu_device_control<cassette_image_device>(mui, container, device) { + set_process_flags(PROCESS_LR_REPEAT); } @@ -116,40 +117,39 @@ void menu_tape_control::populate(float &customtop, float &custombottom) // handle - main tape control menu //------------------------------------------------- -void menu_tape_control::handle() +void menu_tape_control::handle(event const *ev) { // process the menu - const event *event = process(PROCESS_LR_REPEAT); - if (event != nullptr) + if (ev) { - switch (event->iptkey) + switch (ev->iptkey) { case IPT_UI_LEFT: - if (event->itemref == TAPECMD_SLIDER) + if (ev->itemref == TAPECMD_SLIDER) current_device()->seek(-1, SEEK_CUR); - else if (event->itemref == TAPECMD_SELECT) + else if (ev->itemref == TAPECMD_SELECT) previous(); break; case IPT_UI_RIGHT: - if (event->itemref == TAPECMD_SLIDER) + if (ev->itemref == TAPECMD_SLIDER) current_device()->seek(+1, SEEK_CUR); - else if (event->itemref == TAPECMD_SELECT) + else if (ev->itemref == TAPECMD_SELECT) next(); break; case IPT_UI_SELECT: - if (event->itemref == TAPECMD_STOP) + if (ev->itemref == TAPECMD_STOP) current_device()->change_state(CASSETTE_STOPPED, CASSETTE_MASK_UISTATE); - else if (event->itemref == TAPECMD_PLAY) + else if (ev->itemref == TAPECMD_PLAY) current_device()->change_state(CASSETTE_PLAY, CASSETTE_MASK_UISTATE); - else if (event->itemref == TAPECMD_RECORD) + else if (ev->itemref == TAPECMD_RECORD) current_device()->change_state(CASSETTE_RECORD, CASSETTE_MASK_UISTATE); - else if (event->itemref == TAPECMD_REWIND) + else if (ev->itemref == TAPECMD_REWIND) current_device()->seek(-30, SEEK_CUR); - else if (event->itemref == TAPECMD_FAST_FORWARD) + else if (ev->itemref == TAPECMD_FAST_FORWARD) current_device()->seek(30, SEEK_CUR); - else if (event->itemref == TAPECMD_SLIDER) + else if (ev->itemref == TAPECMD_SLIDER) current_device()->seek(0, SEEK_SET); break; } diff --git a/src/frontend/mame/ui/tapectrl.h b/src/frontend/mame/ui/tapectrl.h index 11ac3bbfc7d..1117e88ef5e 100644 --- a/src/frontend/mame/ui/tapectrl.h +++ b/src/frontend/mame/ui/tapectrl.h @@ -8,15 +8,16 @@ ***************************************************************************/ -#pragma once - #ifndef MAME_FRONTEND_UI_TAPECTRL_H #define MAME_FRONTEND_UI_TAPECTRL_H +#pragma once + #include "imagedev/cassette.h" #include "ui/devctrl.h" namespace ui { + class menu_tape_control : public menu_device_control<cassette_image_device> { public: @@ -25,11 +26,11 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; static void get_time_string(std::string &dest, cassette_image_device *cassette, int *curpos, int *endpos); }; } // namespace ui -#endif /* MAME_FRONTEND_UI_TAPECTRL_H */ +#endif // MAME_FRONTEND_UI_TAPECTRL_H diff --git a/src/frontend/mame/ui/textbox.cpp b/src/frontend/mame/ui/textbox.cpp new file mode 100644 index 00000000000..177f39a0f53 --- /dev/null +++ b/src/frontend/mame/ui/textbox.cpp @@ -0,0 +1,237 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ui/textbox.cpp + + Menu that displays a non-interactive text box + +***************************************************************************/ + +#include "emu.h" +#include "textbox.h" + +#include "ui/ui.h" +#include "ui/utils.h" + +#include <string_view> + + +namespace ui { + +//------------------------------------------------- +// constructor +//------------------------------------------------- + +menu_textbox::menu_textbox(mame_ui_manager &mui, render_container &container) + : menu(mui, container) + , m_layout() + , m_layout_width(-1.0f) + , m_desired_width(-1.0f) + , m_desired_lines(-1) + , m_top_line(0) +{ +} + + +//------------------------------------------------- +// destructor +//------------------------------------------------- + +menu_textbox::~menu_textbox() +{ +} + + +//------------------------------------------------- +// reset_layout - force repopulate and scroll to +// top +//------------------------------------------------- + +void menu_textbox::reset_layout() +{ + m_layout = std::nullopt; + m_top_line = 0; +} + + +//------------------------------------------------- +// handle_key - handle basic navigation keys +//------------------------------------------------- + +void menu_textbox::handle_key(int key) +{ + switch (key) + { + case IPT_UI_UP: + --m_top_line; + break; + + case IPT_UI_DOWN: + ++m_top_line; + break; + + case IPT_UI_PAGE_UP: + m_top_line -= m_window_lines - 3; + break; + + case IPT_UI_PAGE_DOWN: + m_top_line += m_window_lines - 3; + break; + + case IPT_UI_HOME: + m_top_line = 0; + break; + + case IPT_UI_END: + m_top_line = m_layout->lines() - m_window_lines; + break; + } +} + + +//------------------------------------------------- +// custom_mouse_scroll - handle scroll events +//------------------------------------------------- + +bool menu_textbox::custom_mouse_scroll(int lines) +{ + m_top_line += lines; + return true; +} + + +//------------------------------------------------- +// draw - draw the menu +//------------------------------------------------- + +void menu_textbox::draw(uint32_t flags) +{ + float const aspect = machine().render().ui_aspect(&container()); + float const line_height = ui().get_line_height(); + float const ud_arrow_width = line_height * aspect; + float const gutter_width = 0.52f * line_height * aspect; + float const visible_width = 1.0f - (2.0f * ui().box_lr_border() * aspect); + float const visible_left = (1.0f - visible_width) * 0.5f; + float const extra_height = 2.0f * line_height; + float const visible_extra_menu_height = get_customtop() + get_custombottom() + extra_height; + + // determine effective positions taking into account the hilighting arrows + float const maximum_width = visible_width - 2.0f * gutter_width; + + draw_background(); + map_mouse(); + + // account for extra space at the top and bottom and the separator/item for closing + float visible_main_menu_height = 1.0f - 2.0f * ui().box_tb_border() - visible_extra_menu_height; + m_window_lines = int(std::trunc(visible_main_menu_height / line_height)); + + // lay out the text if necessary + if (!m_layout || (m_layout_width != maximum_width)) + { + m_desired_width = maximum_width; + populate_text(m_layout, m_desired_width, m_desired_lines); + m_layout_width = maximum_width; + } + m_window_lines = (std::min)(m_desired_lines, m_window_lines); + visible_main_menu_height = float(m_window_lines) * line_height; + + // compute top/left of inner menu area by centering, if the menu is at the bottom of the extra, adjust + float const visible_top = ((1.0f - (visible_main_menu_height + visible_extra_menu_height)) * 0.5f) + get_customtop(); + + // get width required to draw the sole menu item + menu_item const &pitem = item(0); + std::string_view const itemtext = pitem.text; + float const itemwidth = gutter_width + ui().get_string_width(itemtext) + gutter_width; + float const draw_width = std::min(maximum_width, std::max(itemwidth, m_desired_width)); + + // compute text box size + float const x1 = visible_left + ((maximum_width - draw_width) * 0.5f); + float const y1 = visible_top - ui().box_tb_border(); + float const x2 = visible_left + visible_width - ((maximum_width - draw_width) * 0.5f); + float const y2 = visible_top + visible_main_menu_height + ui().box_tb_border() + extra_height; + float const effective_left = x1 + gutter_width; + float const line_x0 = x1 + 0.5f * UI_LINE_WIDTH; + float const line_x1 = x2 - 0.5f * UI_LINE_WIDTH; + float const separator = visible_top + float(m_window_lines) * line_height; + + ui().draw_outlined_box(container(), x1, y1, x2, y2, ui().colors().background_color()); + + int const visible_items = m_layout->lines(); + m_window_lines = (std::min)(visible_items, m_window_lines); + m_top_line = (std::max)(0, m_top_line); + if (m_top_line + m_window_lines >= visible_items) + m_top_line = visible_items - m_window_lines; + + clear_hover(); + if (m_top_line) + { + // if we're on the top line, display the up arrow + rgb_t fgcolor = ui().colors().text_color(); + if (mouse_in_rect(line_x0, visible_top, line_x1, visible_top + line_height)) + { + fgcolor = ui().colors().mouseover_color(); + highlight( + line_x0, visible_top, + line_x1, visible_top + line_height, + ui().colors().mouseover_bg_color()); + set_hover(HOVER_ARROW_UP); + } + draw_arrow( + 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, visible_top + 0.25f * line_height, + 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, visible_top + 0.75f * line_height, + fgcolor, ROT0); + } + if ((m_top_line + m_window_lines) < visible_items) + { + // if we're on the bottom line, display the down arrow + float const line_y = visible_top + float(m_window_lines - 1) * line_height; + rgb_t fgcolor = ui().colors().text_color(); + if (mouse_in_rect(line_x0, line_y, line_x1, line_y + line_height)) + { + fgcolor = ui().colors().mouseover_color(); + highlight( + line_x0, line_y, + line_x1, line_y + line_height, + ui().colors().mouseover_bg_color()); + set_hover(HOVER_ARROW_DOWN); + } + draw_arrow( + 0.5f * (x1 + x2) - 0.5f * ud_arrow_width, line_y + 0.25f * line_height, + 0.5f * (x1 + x2) + 0.5f * ud_arrow_width, line_y + 0.75f * line_height, + fgcolor, ROT0 ^ ORIENTATION_FLIP_Y); + } + + // draw visible lines, minus 1 for top arrow and 1 for bottom arrow + auto const text_lines = m_window_lines - (m_top_line ? 1 : 0) - (m_top_line + m_window_lines != visible_items); + m_layout->emit( + container(), + m_top_line ? (m_top_line + 1) : 0, text_lines, + effective_left, visible_top + (m_top_line ? line_height : 0.0f)); + + // add visual separator before the "return to prevous menu" item + container().add_line( + x1, separator + (0.5f * line_height), + x2, separator + (0.5f * line_height), + UI_LINE_WIDTH, ui().colors().text_color(), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA)); + + float const line_y0 = separator + line_height; + float const line_y1 = line_y0 + line_height; + + if (mouse_in_rect(line_x0, line_y0, line_x1, line_y1) && is_selectable(pitem)) + set_hover(0); + + highlight(line_x0, line_y0, line_x1, line_y1, ui().colors().selected_bg_color()); + ui().draw_text_full( + container(), itemtext, + effective_left, line_y0, draw_width, + text_layout::text_justify::CENTER, text_layout::word_wrapping::TRUNCATE, + mame_ui_manager::NORMAL, + ui().colors().selected_color(), ui().colors().selected_bg_color(), + nullptr, nullptr); + + // if there is something special to add, do it by calling the virtual method + custom_render(get_selection_ref(), get_customtop(), get_custombottom(), x1, y1, x2, y2); +} + +} // namespace ui diff --git a/src/frontend/mame/ui/textbox.h b/src/frontend/mame/ui/textbox.h new file mode 100644 index 00000000000..bdbb63f934a --- /dev/null +++ b/src/frontend/mame/ui/textbox.h @@ -0,0 +1,49 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + ui/textbox.h + + Menu that displays a non-interactive text box + +***************************************************************************/ +#ifndef MAME_FRONTEND_UI_TEXTBOX_H +#define MAME_FRONTEND_UI_TEXTBOX_H + +#include "ui/menu.h" +#include "ui/text.h" + +#include <optional> + + +namespace ui { + +class menu_textbox : public menu +{ +public: + virtual ~menu_textbox() override; + +protected: + menu_textbox(mame_ui_manager &mui, render_container &container); + + void reset_layout(); + void handle_key(int key); + + virtual void populate_text(std::optional<text_layout> &layout, float &width, int &lines) = 0; + + virtual bool custom_mouse_scroll(int lines) override; + +private: + virtual void draw(uint32_t flags) override; + + std::optional<text_layout> m_layout; + float m_layout_width; + float m_desired_width; + int m_desired_lines; + int m_window_lines; + int m_top_line; +}; + +} // namespace ui + +#endif // MAME_FRONTEND_UI_TEXTBOX_H diff --git a/src/frontend/mame/ui/ui.cpp b/src/frontend/mame/ui/ui.cpp index 8c8f44224a8..87e0caadf9d 100644 --- a/src/frontend/mame/ui/ui.cpp +++ b/src/frontend/mame/ui/ui.cpp @@ -42,6 +42,7 @@ #include "../osd/modules/lib/osdobj_common.h" #include <chrono> +#include <functional> #include <type_traits> @@ -166,7 +167,7 @@ static uint32_t const mouse_bitmap[32*32] = mame_ui_manager::mame_ui_manager(running_machine &machine) : ui_manager(machine) , m_font() - , m_handler_callback(nullptr) + , m_handler_callback() , m_handler_callback_type(ui_callback_type::GENERAL) , m_handler_param(0) , m_single_step(false) @@ -199,7 +200,6 @@ void mame_ui_manager::init() ui::system_list::instance().cache_data(options()); // initialize the other UI bits - ui::menu::init(machine(), options()); ui_gfx_init(machine()); m_ui_colors.refresh(options()); @@ -210,11 +210,12 @@ void mame_ui_manager::init() // more initialization set_handler( ui_callback_type::GENERAL, - [this] (render_container &container) -> uint32_t - { - draw_text_box(container, messagebox_text, ui::text_layout::text_justify::LEFT, 0.5f, 0.5f, colors().background_color()); - return 0; - }); + handler_callback_func( + [this] (render_container &container) -> uint32_t + { + draw_text_box(container, messagebox_text, ui::text_layout::text_justify::LEFT, 0.5f, 0.5f, colors().background_color()); + return 0; + })); m_non_char_keys_down = std::make_unique<uint8_t[]>((std::size(non_char_keys) + 7) / 8); m_mouse_show = machine().system().flags & machine_flags::CLICKABLE_ARTWORK ? true : false; @@ -376,7 +377,7 @@ void mame_ui_manager::initialize(running_machine &machine) // pair for the current UI handler //------------------------------------------------- -void mame_ui_manager::set_handler(ui_callback_type callback_type, const std::function<uint32_t (render_container &)> &&callback) +void mame_ui_manager::set_handler(ui_callback_type callback_type, handler_callback_func &&callback) { m_handler_callback = std::move(callback); m_handler_callback_type = callback_type; @@ -427,7 +428,6 @@ void mame_ui_manager::display_startup_screens(bool first_time) #endif // set up event handlers - using namespace std::placeholders; switch_code_poller poller(machine().input()); std::string warning_text; rgb_t warning_color; @@ -457,10 +457,10 @@ void mame_ui_manager::display_startup_screens(bool first_time) return 0; }; - set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_ingame, this, _1)); + set_handler(ui_callback_type::GENERAL, handler_callback_func(&mame_ui_manager::handler_ingame, this)); // loop over states - for (int state = 0; state < maxstate && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(machine()); state++) + for (int state = 0; state < maxstate && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(*this); state++) { // default to standard colors warning_color = colors().background_color(); @@ -475,7 +475,7 @@ void mame_ui_manager::display_startup_screens(bool first_time) if (!warning_text.empty()) { warning_text.append(_("\n\nPress any key to continue")); - set_handler(ui_callback_type::MODAL, handler_messagebox_anykey); + set_handler(ui_callback_type::MODAL, handler_callback_func(handler_messagebox_anykey)); } break; @@ -548,7 +548,7 @@ void mame_ui_manager::display_startup_screens(bool first_time) if (need_warning) { warning_text.append(_("\n\nPress any key to continue")); - set_handler(ui_callback_type::MODAL, handler_messagebox_anykey); + set_handler(ui_callback_type::MODAL, handler_callback_func(handler_messagebox_anykey)); warning_color = machine_info().warnings_color(); } } @@ -579,12 +579,12 @@ void mame_ui_manager::display_startup_screens(bool first_time) config_menu = false; // loop while we have a handler - while (m_handler_callback_type == ui_callback_type::MODAL && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(machine())) + while (m_handler_callback_type == ui_callback_type::MODAL && !machine().scheduled_event_pending() && !ui::menu::stack_has_special_main_menu(*this)) machine().video().frame_update(); } // clear the handler and force an update - set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_ingame, this, _1)); + set_handler(ui_callback_type::GENERAL, handler_callback_func(&mame_ui_manager::handler_ingame, this)); machine().video().frame_update(); } @@ -593,7 +593,7 @@ void mame_ui_manager::display_startup_screens(bool first_time) m_last_launch_time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); // if we're the empty driver, force the menus on - if (ui::menu::stack_has_special_main_menu(machine())) + if (ui::menu::stack_has_special_main_menu(*this)) show_menu(); else if (config_menu) { @@ -642,7 +642,7 @@ void mame_ui_manager::update_and_render(render_container &container) if (machine().phase() >= machine_phase::RESET && (single_step() || machine().paused())) { int alpha = (1.0f - machine().options().pause_brightness()) * 255.0f; - if (ui::menu::stack_has_special_main_menu(machine())) + if (ui::menu::stack_has_special_main_menu(*this)) alpha = 255; if (alpha > 255) alpha = 255; @@ -698,8 +698,7 @@ void mame_ui_manager::update_and_render(render_container &container) // cancel takes us back to the ingame handler if (m_handler_param == UI_HANDLER_CANCEL) { - using namespace std::placeholders; - set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_ingame, this, _1)); + set_handler(ui_callback_type::GENERAL, handler_callback_func(&mame_ui_manager::handler_ingame, this)); } } @@ -994,8 +993,7 @@ bool mame_ui_manager::show_profiler() const void mame_ui_manager::show_menu() { - using namespace std::placeholders; - set_handler(ui_callback_type::MENU, std::bind(&ui::menu::ui_handler, _1, std::ref(*this))); + set_handler(ui_callback_type::MENU, ui::menu::get_ui_handler(*this)); } @@ -1188,9 +1186,8 @@ void mame_ui_manager::draw_profiler(render_container &container) void mame_ui_manager::start_save_state() { - ui::menu::stack_reset(machine()); show_menu(); - ui::menu::stack_push<ui::menu_save_state>(*this, machine().render().ui_container()); + ui::menu::stack_push<ui::menu_save_state>(*this, machine().render().ui_container(), true); } @@ -1200,9 +1197,8 @@ void mame_ui_manager::start_save_state() void mame_ui_manager::start_load_state() { - ui::menu::stack_reset(machine()); show_menu(); - ui::menu::stack_push<ui::menu_load_state>(*this, machine().render().ui_container()); + ui::menu::stack_push<ui::menu_load_state>(*this, machine().render().ui_container(), true); } @@ -1327,10 +1323,10 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) } // if the on-screen display isn't up and the user has toggled it, turn it on - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0 && machine().ui_input().pressed(IPT_UI_ON_SCREEN_DISPLAY)) + if (!(machine().debug_flags & DEBUG_FLAG_ENABLED) && machine().ui_input().pressed(IPT_UI_ON_SCREEN_DISPLAY)) { - using namespace std::placeholders; - set_handler(ui_callback_type::MENU, std::bind(&ui::menu_sliders::ui_handler, _1, std::ref(*this))); + ui::menu::stack_push<ui::menu_sliders>(*this, machine().render().ui_container(), true); + set_handler(ui_callback_type::MENU, ui::menu::get_ui_handler(*this)); return 1; } @@ -1346,7 +1342,13 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) if (!is_paused) machine().pause(); using namespace std::placeholders; - set_handler(ui_callback_type::VIEWER, std::bind(&ui_gfx_ui_handler, _1, std::ref(*this), is_paused)); + set_handler( + ui_callback_type::VIEWER, + handler_callback_func( + [this, is_paused] (render_container &container) -> uint32_t + { + return ui_gfx_ui_handler(container, *this, is_paused); + })); return is_paused ? 1 : 0; } @@ -1458,11 +1460,10 @@ uint32_t mame_ui_manager::handler_ingame(render_container &container) void mame_ui_manager::request_quit() { - using namespace std::placeholders; if (!machine().options().confirm_quit()) machine().schedule_exit(); else - set_handler(ui_callback_type::GENERAL, std::bind(&mame_ui_manager::handler_confirm_quit, this, _1)); + set_handler(ui_callback_type::GENERAL, handler_callback_func(&mame_ui_manager::handler_confirm_quit, this)); } @@ -2256,7 +2257,7 @@ void mame_ui_manager::save_main_option() void mame_ui_manager::menu_reset() { - ui::menu::stack_reset(machine()); + ui::menu::stack_reset(*this); } diff --git a/src/frontend/mame/ui/ui.h b/src/frontend/mame/ui/ui.h index a81278f3333..8374cbac5db 100644 --- a/src/frontend/mame/ui/ui.h +++ b/src/frontend/mame/ui/ui.h @@ -24,7 +24,6 @@ #include <any> #include <cassert> #include <ctime> -#include <functional> #include <map> #include <set> #include <string_view> @@ -66,7 +65,6 @@ class laserdisc_device; ***************************************************************************/ class mame_ui_manager; -typedef uint32_t (*ui_callback)(mame_ui_manager &, render_container &, uint32_t); enum class ui_callback_type { @@ -151,8 +149,6 @@ public: void initialize(running_machine &machine); std::vector<ui::menu_item> slider_init(running_machine &machine); - void set_handler(ui_callback_type callback_type, const std::function<uint32_t (render_container &)> &&callback); - void display_startup_screens(bool first_time); virtual void set_startup_text(const char *text, bool force) override; void update_and_render(render_container &container); @@ -231,7 +227,7 @@ public: std::string get_general_input_setting(ioport_type type, int player = 0, input_seq_type seqtype = SEQ_TYPE_STANDARD); private: - using handler_callback_func = std::function<uint32_t (render_container &)>; + using handler_callback_func = delegate<uint32_t (render_container &)>; using device_feature_set = std::set<std::pair<std::string, std::string> >; using session_data_map = std::map<std::type_index, std::any>; @@ -276,6 +272,7 @@ private: uint32_t handler_confirm_quit(render_container &container); // private methods + void set_handler(ui_callback_type callback_type, handler_callback_func &&callback); void exit(); void config_load(config_type cfg_type, config_level cfg_level, util::xml::data_node const *parentnode); void config_save(config_type cfg_type, util::xml::data_node *parentnode); diff --git a/src/frontend/mame/ui/utils.cpp b/src/frontend/mame/ui/utils.cpp index 35aef723b13..27a27b45678 100644 --- a/src/frontend/mame/ui/utils.cpp +++ b/src/frontend/mame/ui/utils.cpp @@ -385,6 +385,7 @@ private: , m_handler(std::move(handler)) , m_added(false) { + set_process_flags(PROCESS_LR_REPEAT); } virtual ~menu_configure() override { m_handler(m_parent); } @@ -412,7 +413,7 @@ private: }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; bool set_filter_type(unsigned pos, typename Base::type n) { @@ -567,15 +568,14 @@ void composite_filter_impl_base<Impl, Base, Type>::menu_configure::populate(floa } template <class Impl, class Base, typename Base::type Type> -void composite_filter_impl_base<Impl, Base, Type>::menu_configure::handle() +void composite_filter_impl_base<Impl, Base, Type>::menu_configure::handle(event const *ev) { - const event *menu_event = process(PROCESS_LR_REPEAT); - if (menu_event && menu_event->itemref) + if (ev && ev->itemref) { m_added = false; bool changed(false); - uintptr_t const ref(reinterpret_cast<uintptr_t>(menu_event->itemref)); - switch (menu_event->iptkey) + uintptr_t const ref(reinterpret_cast<uintptr_t>(ev->itemref)); + switch (ev->iptkey) { case IPT_UI_LEFT: case IPT_UI_RIGHT: @@ -584,7 +584,7 @@ void composite_filter_impl_base<Impl, Base, Type>::menu_configure::handle() // change filter type unsigned const pos(ref - FILTER_FIRST); typename Base::type const current(m_parent.m_filters[pos]->get_type()); - if (IPT_UI_LEFT == menu_event->iptkey) + if (IPT_UI_LEFT == ev->iptkey) { typename Base::type n(current); while ((Base::FIRST < n) && !changed) @@ -607,7 +607,7 @@ void composite_filter_impl_base<Impl, Base, Type>::menu_configure::handle() { // change filter value Base &pos(*m_parent.m_filters[ref - ADJUST_FIRST]); - changed = (IPT_UI_LEFT == menu_event->iptkey) ? pos.adjust_left() : pos.adjust_right(); + changed = (IPT_UI_LEFT == ev->iptkey) ? pos.adjust_left() : pos.adjust_right(); } break; @@ -971,6 +971,7 @@ private: , m_state(std::make_unique<std::pair<unsigned, bool> []>(mame_machine_manager::instance()->inifile().get_file_count())) , m_ini(parent.m_ini) { + set_process_flags(PROCESS_LR_REPEAT); inifile_manager const &mgr(mame_machine_manager::instance()->inifile()); for (size_t i = 0; mgr.get_file_count() > i; ++i) { @@ -1015,7 +1016,7 @@ private: }; virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; category_machine_filter &m_parent; std::function<void (machine_filter &)> m_handler; @@ -1093,15 +1094,14 @@ void category_machine_filter::menu_configure::populate(float &customtop, float & customtop = ui().get_line_height() + 3.0f * ui().box_tb_border(); } -void category_machine_filter::menu_configure::handle() +void category_machine_filter::menu_configure::handle(event const *ev) { - const event *menu_event = process(PROCESS_LR_REPEAT); - if (menu_event && menu_event->itemref) + if (ev && ev->itemref) { bool changed(false); - uintptr_t const ref(reinterpret_cast<uintptr_t>(menu_event->itemref)); + uintptr_t const ref(reinterpret_cast<uintptr_t>(ev->itemref)); inifile_manager const &mgr(mame_machine_manager::instance()->inifile()); - switch (menu_event->iptkey) + switch (ev->iptkey) { case IPT_UI_LEFT: if ((INI_FILE == ref) && m_ini) diff --git a/src/frontend/mame/ui/videoopt.cpp b/src/frontend/mame/ui/videoopt.cpp index 8d5ccbca88c..60d2b25c66b 100644 --- a/src/frontend/mame/ui/videoopt.cpp +++ b/src/frontend/mame/ui/videoopt.cpp @@ -67,12 +67,11 @@ void menu_video_targets::populate(float &customtop, float &custombottom) menu -------------------------------------------------*/ -void menu_video_targets::handle() +void menu_video_targets::handle(event const *ev) { - event const *const menu_event = process(0); - if (menu_event && (menu_event->iptkey == IPT_UI_SELECT)) + if (ev && (ev->iptkey == IPT_UI_SELECT)) { - render_target *const target = reinterpret_cast<render_target *>(menu_event->itemref); + render_target *const target = reinterpret_cast<render_target *>(ev->itemref); menu::stack_push<menu_video_options>( ui(), container(), @@ -223,25 +222,24 @@ void menu_video_options::populate(float &customtop, float &custombottom) menu -------------------------------------------------*/ -void menu_video_options::handle() +void menu_video_options::handle(event const *ev) { auto const lockout_popup([this] () { machine().popmessage(_("Cannot change options while recording!")); }); bool const snap_lockout(m_snapshot && machine().video().is_recording()); bool changed(false); // process the menu - event const *const menu_event(process(0)); - if (menu_event && uintptr_t(menu_event->itemref)) + if (ev && uintptr_t(ev->itemref)) { - switch (reinterpret_cast<uintptr_t>(menu_event->itemref)) + switch (reinterpret_cast<uintptr_t>(ev->itemref)) { // rotate adds rotation depending on the direction case ITEM_ROTATE: - if (menu_event->iptkey == IPT_UI_LEFT || menu_event->iptkey == IPT_UI_RIGHT) + if (ev->iptkey == IPT_UI_LEFT || ev->iptkey == IPT_UI_RIGHT) { if (snap_lockout) return lockout_popup(); - int const delta((menu_event->iptkey == IPT_UI_LEFT) ? ROT270 : ROT90); + int const delta((ev->iptkey == IPT_UI_LEFT) ? ROT270 : ROT90); m_target.set_orientation(orientation_add(delta, m_target.orientation())); if (m_target.is_ui_target()) { @@ -255,18 +253,18 @@ void menu_video_options::handle() // layer config bitmasks handle left/right keys the same (toggle) case ITEM_ZOOM: - if ((menu_event->iptkey == IPT_UI_LEFT) || (menu_event->iptkey == IPT_UI_RIGHT)) + if ((ev->iptkey == IPT_UI_LEFT) || (ev->iptkey == IPT_UI_RIGHT)) { if (snap_lockout) return lockout_popup(); - m_target.set_zoom_to_screen(menu_event->iptkey == IPT_UI_RIGHT); + m_target.set_zoom_to_screen(ev->iptkey == IPT_UI_RIGHT); changed = true; } break; // non-integer scaling: rotate through options case ITEM_UNEVENSTRETCH: - if (menu_event->iptkey == IPT_UI_LEFT) + if (ev->iptkey == IPT_UI_LEFT) { if (snap_lockout) return lockout_popup(); @@ -294,7 +292,7 @@ void menu_video_options::handle() } changed = true; } - else if (menu_event->iptkey == IPT_UI_RIGHT) + else if (ev->iptkey == IPT_UI_RIGHT) { if (snap_lockout) return lockout_popup(); @@ -326,34 +324,34 @@ void menu_video_options::handle() // keep aspect handles left/right keys the same (toggle) case ITEM_KEEPASPECT: - if ((menu_event->iptkey == IPT_UI_LEFT) || (menu_event->iptkey == IPT_UI_RIGHT)) + if ((ev->iptkey == IPT_UI_LEFT) || (ev->iptkey == IPT_UI_RIGHT)) { if (snap_lockout) return lockout_popup(); - m_target.set_keepaspect(menu_event->iptkey == IPT_UI_RIGHT); + m_target.set_keepaspect(ev->iptkey == IPT_UI_RIGHT); changed = true; } break; // anything else is a view item default: - if (reinterpret_cast<uintptr_t>(menu_event->itemref) >= ITEM_VIEW_FIRST) + if (reinterpret_cast<uintptr_t>(ev->itemref) >= ITEM_VIEW_FIRST) { if (snap_lockout) return lockout_popup(); - if (menu_event->iptkey == IPT_UI_SELECT) + if (ev->iptkey == IPT_UI_SELECT) { - m_target.set_view(reinterpret_cast<uintptr_t>(menu_event->itemref) - ITEM_VIEW_FIRST); + m_target.set_view(reinterpret_cast<uintptr_t>(ev->itemref) - ITEM_VIEW_FIRST); changed = true; } } - else if (reinterpret_cast<uintptr_t>(menu_event->itemref) >= ITEM_TOGGLE_FIRST) + else if (reinterpret_cast<uintptr_t>(ev->itemref) >= ITEM_TOGGLE_FIRST) { if (snap_lockout) return lockout_popup(); - if ((menu_event->iptkey == IPT_UI_LEFT) || (menu_event->iptkey == IPT_UI_RIGHT)) + if ((ev->iptkey == IPT_UI_LEFT) || (ev->iptkey == IPT_UI_RIGHT)) { - m_target.set_visibility_toggle(reinterpret_cast<uintptr_t>(menu_event->itemref) - ITEM_TOGGLE_FIRST, menu_event->iptkey == IPT_UI_RIGHT); + m_target.set_visibility_toggle(reinterpret_cast<uintptr_t>(ev->itemref) - ITEM_TOGGLE_FIRST, ev->iptkey == IPT_UI_RIGHT); changed = true; } } diff --git a/src/frontend/mame/ui/videoopt.h b/src/frontend/mame/ui/videoopt.h index 44a172cf8f5..be539cf4aa0 100644 --- a/src/frontend/mame/ui/videoopt.h +++ b/src/frontend/mame/ui/videoopt.h @@ -25,7 +25,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; }; @@ -38,7 +38,7 @@ public: private: virtual void populate(float &customtop, float &custombottom) override; - virtual void handle() override; + virtual void handle(event const *ev) override; render_target &m_target; std::string const m_title; diff --git a/src/lib/util/language.cpp b/src/lib/util/language.cpp new file mode 100644 index 00000000000..3a00fe80ad7 --- /dev/null +++ b/src/lib/util/language.cpp @@ -0,0 +1,221 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + language.cpp + + Multi-language support. + +***************************************************************************/ + +#include "language.h" + +#include "ioprocs.h" + +#include "osdcore.h" + +#include <cstdint> +#include <cstring> +#include <memory> +#include <new> +#include <unordered_map> +#include <utility> + + +namespace util { + +namespace { + +constexpr std::uint32_t MO_MAGIC = 0x950412de; +constexpr std::uint32_t MO_MAGIC_REVERSED = 0xde120495; + +std::unique_ptr<std::uint32_t []> f_translation_data; +std::unordered_map<std::string_view, std::pair<char const *, std::uint32_t> > f_translation_map; + +} // anonymous namespace + + +void unload_translation() +{ + f_translation_data.reset(); + f_translation_map.clear(); +} + + +void load_translation(random_read &file) +{ + std::unique_ptr<std::uint32_t []> translation_data; + std::unordered_map<std::string_view, std::pair<char const *, std::uint32_t> > translation_map; + + std::uint64_t size = 0; + if (file.length(size) || (20 > size)) + { + osd_printf_error("Error reading translation file: %u-byte file is too small to contain translation data\n", size); + return; + } + + translation_data.reset(new (std::nothrow) std::uint32_t [(size + 3) / 4]); + if (!translation_data) + { + osd_printf_error("Failed to allocate %u bytes to load translation data file\n", size); + return; + } + + std::size_t read; + file.read(translation_data.get(), size, read); + if (read != size) + { + osd_printf_error("Error reading translation file: requested %u bytes but got %u bytes\n", size, read); + translation_data.reset(); + return; + } + + if ((translation_data[0] != MO_MAGIC) && (translation_data[0] != MO_MAGIC_REVERSED)) + { + osd_printf_error("Error reading translation file: unrecognized magic number 0x%08X\n", translation_data[0]); + translation_data.reset(); + return; + } + + auto fetch_word = + [reversed = translation_data[0] == MO_MAGIC_REVERSED, words = translation_data.get()] (size_t offset) + { + return reversed ? swapendian_int32(words[offset]) : words[offset]; + }; + + // FIXME: check major/minor version number + + if ((fetch_word(3) % 4) || (fetch_word(4) % 4)) + { + osd_printf_error("Error reading translation file: table offsets %u and %u are not word-aligned\n", fetch_word(3), fetch_word(4)); + translation_data.reset(); + return; + } + + std::uint32_t const number_of_strings = fetch_word(2); + std::uint32_t const original_table_offset = fetch_word(3) >> 2; + std::uint32_t const translation_table_offset = fetch_word(4) >> 2; + if ((4 * (original_table_offset + (std::uint64_t(number_of_strings) * 2))) > size) + { + osd_printf_error("Error reading translation file: %u-entry original string table at offset %u extends past end of %u-byte file\n", number_of_strings, fetch_word(3), size); + translation_data.reset(); + return; + } + if ((4 * (translation_table_offset + (std::uint64_t(number_of_strings) * 2))) > size) + { + osd_printf_error("Error reading translation file: %u-entry translated string table at offset %u extends past end of %u-byte file\n", number_of_strings, fetch_word(4), size); + translation_data.reset(); + return; + } + osd_printf_verbose("Reading translation file: %u strings, original table at word offset %u, translated table at word offset %u\n", number_of_strings, original_table_offset, translation_table_offset); + + char const *const data = reinterpret_cast<char const *>(translation_data.get()); + for (std::uint32_t i = 1; number_of_strings > i; ++i) + { + std::uint32_t const original_length = fetch_word(original_table_offset + (2 * i)); + std::uint32_t const original_offset = fetch_word(original_table_offset + (2 * i) + 1); + if ((original_length + original_offset) >= size) + { + osd_printf_error("Error reading translation file: %u-byte original string %u at offset %u extends past end of %u-byte file\n", original_length, i, original_offset, size); + continue; + } + if (data[original_length + original_offset]) + { + osd_printf_error("Error reading translation file: %u-byte original string %u at offset %u is not correctly NUL-terminated\n", original_length, i, original_offset); + continue; + } + + std::uint32_t const translation_length = fetch_word(translation_table_offset + (2 * i)); + std::uint32_t const translation_offset = fetch_word(translation_table_offset + (2 * i) + 1); + if ((translation_length + translation_offset) >= size) + { + osd_printf_error("Error reading translation file: %u-byte translated string %u at offset %u extends past end of %u-byte file\n", translation_length, i, translation_offset, size); + continue; + } + if (data[translation_length + translation_offset]) + { + osd_printf_error("Error reading translation file: %u-byte translated string %u at offset %u is not correctly NUL-terminated\n", translation_length, i, translation_offset); + continue; + } + + std::string_view const original(&data[original_offset], original_length); + char const *const translation(&data[translation_offset]); + auto const ins = translation_map.emplace(original, std::make_pair(translation, translation_length)); + if (!ins.second) + { + osd_printf_warning( + "Loading translation file: translation %u '%s'='%s' conflicts with previous translation '%s'='%s'\n", + i, + original, + translation, + ins.first->first, + ins.first->second.first); + } + } + + osd_printf_verbose("Loaded %u translated string from file\n", translation_map.size()); + f_translation_data = std::move(translation_data); + f_translation_map = std::move(translation_map); +} + + +char const *lang_translate(char const *message) +{ + auto const found = f_translation_map.find(message); + if (f_translation_map.end() != found) + return found->second.first; + return message; +} + + +std::string_view lang_translate(std::string_view message) +{ + auto const found = f_translation_map.find(message); + if (f_translation_map.end() != found) + return std::string_view(found->second.first, found->second.second); + return message; +} + + +char const *lang_translate(char const *context, char const *message) +{ + if (!f_translation_map.empty()) + { + auto const ctxlen(std::strlen(context)); + auto const msglen(std::strlen(message)); + std::string key; + key.reserve(ctxlen + 1 + msglen); + key.append(context, ctxlen); + key.append(1, '\004'); + key.append(message, msglen); + auto const found = f_translation_map.find(key); + if (f_translation_map.end() != found) + return found->second.first; + } + return message; +} + + +std::string_view lang_translate(char const *context, std::string_view message) +{ + return lang_translate(std::string_view(context), message); +} + + +std::string_view lang_translate(std::string_view context, std::string_view message) +{ + if (!f_translation_map.empty()) + { + std::string key; + key.reserve(context.length() + 1 + message.length()); + key.append(context); + key.append(1, '\004'); + key.append(message); + auto const found = f_translation_map.find(key); + if (f_translation_map.end() != found) + return std::string_view(found->second.first, found->second.second); + } + return message; +} + +} // namespace util diff --git a/src/lib/util/language.h b/src/lib/util/language.h new file mode 100644 index 00000000000..6e13def02e8 --- /dev/null +++ b/src/lib/util/language.h @@ -0,0 +1,43 @@ +// license:BSD-3-Clause +// copyright-holders:Vas Crabb +/*************************************************************************** + + language.h + + Multi-language support. + +***************************************************************************/ +#ifndef MAME_LIB_UTIL_LANGUAGE_H +#define MAME_LIB_UTIL_LANGUAGE_H + +#pragma once + +#include "utilfwd.h" + +#include <string_view> + + +//************************************************************************** +// LOCALIZATION SUPPORT +//************************************************************************** + +#define _(...) lang_translate(__VA_ARGS__) + +#define N_(msg) (msg) +#define N_p(ctx, msg) (msg) + +namespace util { + +void unload_translation(); +void load_translation(random_read &file); + +char const *lang_translate(char const *message); +std::string_view lang_translate(std::string_view message); + +char const *lang_translate(char const *context, char const *message); +std::string_view lang_translate(char const *context, std::string_view message); +std::string_view lang_translate(std::string_view context, std::string_view message); + +} // namespace util + +#endif // MAME_LIB_UTIL_LANGUAGE_H diff --git a/src/osd/modules/debugger/osx/debugwindowhandler.mm b/src/osd/modules/debugger/osx/debugwindowhandler.mm index 67910f92f99..ec79887e308 100644 --- a/src/osd/modules/debugger/osx/debugwindowhandler.mm +++ b/src/osd/modules/debugger/osx/debugwindowhandler.mm @@ -114,7 +114,7 @@ NSString *const MAMESaveDebuggerConfigurationNotification = @"MAMESaveDebuggerCo keyEquivalent:@"b"]; [newMenu addItemWithTitle:@"Devices Window" action:@selector(debugNewDevicesWindow:) - keyEquivalent:@"D"]; + keyEquivalent:@""]; [menu addItem:[NSMenuItem separatorItem]]; diff --git a/src/osd/modules/debugger/osx/memoryview.mm b/src/osd/modules/debugger/osx/memoryview.mm index 1de39fc6ee8..03055bd7daf 100644 --- a/src/osd/modules/debugger/osx/memoryview.mm +++ b/src/osd/modules/debugger/osx/memoryview.mm @@ -57,14 +57,9 @@ { return (memview->chunks_per_row() + [item tag]) > 0; } - else if (action == @selector(showHexidecimalAddr:)) + else if (action == @selector(showAddressRadix:)) { - [item setState:((memview->address_radix() == 16) ? NSOnState : NSOffState)]; - return YES; - } - else if (action == @selector(showOctalAddr:)) - { - [item setState:((memview->address_radix() == 8) ? NSOnState : NSOffState)]; + [item setState:((memview->address_radix() == [item tag]) ? NSOnState : NSOffState)]; return YES; } else @@ -194,12 +189,8 @@ downcast<debug_view_memory *>(view)->set_physical([sender tag]); } -- (IBAction)showHexidecimalAddr:(id)sender { - downcast<debug_view_memory *>(view)->set_address_radix(16); -} - -- (IBAction)showOctalAddr:(id)sender { - downcast<debug_view_memory *>(view)->set_address_radix(8); +- (IBAction)showAddressRadix:(id)sender { + downcast<debug_view_memory *>(view)->set_address_radix([sender tag]); } - (IBAction)showReverseView:(id)sender { @@ -240,97 +231,104 @@ - (void)insertActionItemsInMenu:(NSMenu *)menu atIndex:(NSInteger)index { NSMenuItem *chunkItem1 = [menu insertItemWithTitle:@"1-byte Chunks (Hex)" - action:@selector(showChunkSize:) - keyEquivalent:@"1" - atIndex:index++]; + action:@selector(showChunkSize:) + keyEquivalent:@"1" + atIndex:index++]; [chunkItem1 setTarget:self]; [chunkItem1 setTag:int(debug_view_memory::data_format::HEX_8BIT)]; NSMenuItem *chunkItem2 = [menu insertItemWithTitle:@"2-byte Chunks (Hex)" - action:@selector(showChunkSize:) - keyEquivalent:@"2" - atIndex:index++]; + action:@selector(showChunkSize:) + keyEquivalent:@"2" + atIndex:index++]; [chunkItem2 setTarget:self]; [chunkItem2 setTag:int(debug_view_memory::data_format::HEX_16BIT)]; NSMenuItem *chunkItem4 = [menu insertItemWithTitle:@"4-byte Chunks (Hex)" - action:@selector(showChunkSize:) - keyEquivalent:@"4" - atIndex:index++]; + action:@selector(showChunkSize:) + keyEquivalent:@"4" + atIndex:index++]; [chunkItem4 setTarget:self]; [chunkItem4 setTag:int(debug_view_memory::data_format::HEX_32BIT)]; NSMenuItem *chunkItem8 = [menu insertItemWithTitle:@"8-byte Chunks (Hex)" - action:@selector(showChunkSize:) - keyEquivalent:@"8" - atIndex:index++]; + action:@selector(showChunkSize:) + keyEquivalent:@"8" + atIndex:index++]; [chunkItem8 setTarget:self]; [chunkItem8 setTag:int(debug_view_memory::data_format::HEX_64BIT)]; NSMenuItem *chunkItem12 = [menu insertItemWithTitle:@"1-byte Chunks (Octal)" - action:@selector(showChunkSize:) - keyEquivalent:@"3" - atIndex:index++]; + action:@selector(showChunkSize:) + keyEquivalent:@"3" + atIndex:index++]; [chunkItem12 setTarget:self]; [chunkItem12 setTag:int(debug_view_memory::data_format::OCTAL_8BIT)]; NSMenuItem *chunkItem13 = [menu insertItemWithTitle:@"2-byte Chunks (Octal)" - action:@selector(showChunkSize:) - keyEquivalent:@"5" - atIndex:index++]; + action:@selector(showChunkSize:) + keyEquivalent:@"5" + atIndex:index++]; [chunkItem13 setTarget:self]; [chunkItem13 setTag:int(debug_view_memory::data_format::OCTAL_16BIT)]; NSMenuItem *chunkItem14 = [menu insertItemWithTitle:@"4-byte Chunks (Octal)" - action:@selector(showChunkSize:) - keyEquivalent:@"7" - atIndex:index++]; + action:@selector(showChunkSize:) + keyEquivalent:@"7" + atIndex:index++]; [chunkItem14 setTarget:self]; [chunkItem14 setTag:int(debug_view_memory::data_format::OCTAL_32BIT)]; NSMenuItem *chunkItem15 = [menu insertItemWithTitle:@"8-byte Chunks (Octal)" - action:@selector(showChunkSize:) - keyEquivalent:@"9" - atIndex:index++]; + action:@selector(showChunkSize:) + keyEquivalent:@"9" + atIndex:index++]; [chunkItem15 setTarget:self]; [chunkItem15 setTag:int(debug_view_memory::data_format::OCTAL_64BIT)]; - NSMenuItem *chunkItem9 = [menu insertItemWithTitle:@"32-bit floats" - action:@selector(showChunkSize:) - keyEquivalent:@"F" - atIndex:index++]; + NSMenuItem *chunkItem9 = [menu insertItemWithTitle:@"32-bit Floating Point" + action:@selector(showChunkSize:) + keyEquivalent:@"F" + atIndex:index++]; [chunkItem9 setTarget:self]; [chunkItem9 setTag:int(debug_view_memory::data_format::FLOAT_32BIT)]; - NSMenuItem *chunkItem10 = [menu insertItemWithTitle:@"64-bit floats" - action:@selector(showChunkSize:) - keyEquivalent:@"D" - atIndex:index++]; + NSMenuItem *chunkItem10 = [menu insertItemWithTitle:@"64-bit Floating Point" + action:@selector(showChunkSize:) + keyEquivalent:@"D" + atIndex:index++]; [chunkItem10 setTarget:self]; [chunkItem10 setTag:int(debug_view_memory::data_format::FLOAT_64BIT)]; - NSMenuItem *chunkItem11 = [menu insertItemWithTitle:@"80-bit floats" - action:@selector(showChunkSize:) - keyEquivalent:@"E" - atIndex:index++]; + NSMenuItem *chunkItem11 = [menu insertItemWithTitle:@"80-bit Floating Point" + action:@selector(showChunkSize:) + keyEquivalent:@"E" + atIndex:index++]; [chunkItem11 setTarget:self]; [chunkItem11 setTag:int(debug_view_memory::data_format::FLOAT_80BIT)]; [menu insertItem:[NSMenuItem separatorItem] atIndex:index++]; - NSMenuItem *hexidecimalItem = [menu insertItemWithTitle:@"Hexidecimal Addresses" - action:@selector(showHexidecimalAddr:) - keyEquivalent:@"H" + NSMenuItem *hexadecimalItem = [menu insertItemWithTitle:@"Hexadecimal Addresses" + action:@selector(showAddressRadix:) + keyEquivalent:@"H" + atIndex:index++]; + [hexadecimalItem setTarget:self]; + [hexadecimalItem setTag:16]; + + NSMenuItem *decimalItem = [menu insertItemWithTitle:@"Decimal Addresses" + action:@selector(showAddressRadix:) + keyEquivalent:@"" atIndex:index++]; - [hexidecimalItem setTarget:self]; - [hexidecimalItem setTag:FALSE]; + [decimalItem setTarget:self]; + [decimalItem setTag:10]; NSMenuItem *octalItem = [menu insertItemWithTitle:@"Octal Addresses" - action:@selector(showOctalAddr:) - keyEquivalent:@"O" - atIndex:index++]; + action:@selector(showAddressRadix:) + keyEquivalent:@"O" + atIndex:index++]; [octalItem setTarget:self]; - [octalItem setTag:TRUE]; + [octalItem setTag:8]; [menu insertItem:[NSMenuItem separatorItem] atIndex:index++]; diff --git a/src/osd/modules/debugger/qt/memorywindow.cpp b/src/osd/modules/debugger/qt/memorywindow.cpp index 4d16806a084..09d13c5d6d4 100644 --- a/src/osd/modules/debugger/qt/memorywindow.cpp +++ b/src/osd/modules/debugger/qt/memorywindow.cpp @@ -124,7 +124,13 @@ MemoryWindow::MemoryWindow(running_machine &machine, QWidget *parent) : formatActTwo->setShortcut(QKeySequence("Ctrl+2")); formatActFour->setShortcut(QKeySequence("Ctrl+4")); formatActEight->setShortcut(QKeySequence("Ctrl+8")); - formatAct32bitFloat->setShortcut(QKeySequence("Ctrl+9")); + formatActOneOctal->setShortcut(QKeySequence("Ctrl+3")); + formatActTwoOctal->setShortcut(QKeySequence("Ctrl+5")); + formatActFourOctal->setShortcut(QKeySequence("Ctrl+7")); + formatActEightOctal->setShortcut(QKeySequence("Ctrl+9")); + formatAct32bitFloat->setShortcut(QKeySequence("Ctrl+Shift+F")); + formatAct64bitFloat->setShortcut(QKeySequence("Ctrl+Shift+D")); + formatAct80bitFloat->setShortcut(QKeySequence("Ctrl+Shift+E")); formatActOne->setChecked(true); connect(dataFormat, &QActionGroup::triggered, this, &MemoryWindow::formatChanged); @@ -157,6 +163,8 @@ MemoryWindow::MemoryWindow(running_machine &machine, QWidget *parent) : radixActHexadecimal->setActionGroup(radixGroup); radixActDecimal->setActionGroup(radixGroup); radixActOctal->setActionGroup(radixGroup); + radixActHexadecimal->setShortcut(QKeySequence("Ctrl+Shift+H")); + radixActOctal->setShortcut(QKeySequence("Ctrl+Shift+O")); radixActHexadecimal->setChecked(true); connect(radixGroup, &QActionGroup::triggered, this, &MemoryWindow::radixChanged); diff --git a/src/osd/modules/debugger/qt/windowqt.cpp b/src/osd/modules/debugger/qt/windowqt.cpp index 13abd470c6f..852d1f5449c 100644 --- a/src/osd/modules/debugger/qt/windowqt.cpp +++ b/src/osd/modules/debugger/qt/windowqt.cpp @@ -48,7 +48,6 @@ WindowQt::WindowQt(running_machine &machine, QWidget *parent) : connect(debugActOpenPoints, &QAction::triggered, this, &WindowQt::debugActOpenPoints); QAction *debugActOpenDevices = new QAction("New D&evices Window", this); - debugActOpenDevices->setShortcut(QKeySequence("Shift+Ctrl+D")); connect(debugActOpenDevices, &QAction::triggered, this, &WindowQt::debugActOpenDevices); QAction *dbgActRun = new QAction("Run", this); diff --git a/src/osd/modules/debugger/win/debugwininfo.h b/src/osd/modules/debugger/win/debugwininfo.h index 80561dd2a05..20cea0d477d 100644 --- a/src/osd/modules/debugger/win/debugwininfo.h +++ b/src/osd/modules/debugger/win/debugwininfo.h @@ -75,13 +75,20 @@ protected: ID_SOFT_RESET, ID_EXIT, - ID_1_BYTE_CHUNKS, - ID_2_BYTE_CHUNKS, - ID_4_BYTE_CHUNKS, - ID_8_BYTE_CHUNKS, - ID_FLOATING_POINT_32BIT, - ID_FLOATING_POINT_64BIT, - ID_FLOATING_POINT_80BIT, + ID_1_BYTE_CHUNKS_HEX, + ID_2_BYTE_CHUNKS_HEX, + ID_4_BYTE_CHUNKS_HEX, + ID_8_BYTE_CHUNKS_HEX, + ID_1_BYTE_CHUNKS_OCT, + ID_2_BYTE_CHUNKS_OCT, + ID_4_BYTE_CHUNKS_OCT, + ID_8_BYTE_CHUNKS_OCT, + ID_FLOAT_32BIT, + ID_FLOAT_64BIT, + ID_FLOAT_80BIT, + ID_HEX_ADDRESSES, + ID_DEC_ADDRESSES, + ID_OCT_ADDRESSES, ID_LOGICAL_ADDRESSES, ID_PHYSICAL_ADDRESSES, ID_REVERSE_VIEW, diff --git a/src/osd/modules/debugger/win/memoryviewinfo.cpp b/src/osd/modules/debugger/win/memoryviewinfo.cpp index 4b6f33bcd85..a8891553987 100644 --- a/src/osd/modules/debugger/win/memoryviewinfo.cpp +++ b/src/osd/modules/debugger/win/memoryviewinfo.cpp @@ -46,6 +46,11 @@ bool memoryview_info::physical() const return view<debug_view_memory>()->physical(); } +int memoryview_info::address_radix() const +{ + return view<debug_view_memory>()->address_radix(); +} + void memoryview_info::set_expression(const std::string &string) { @@ -72,6 +77,11 @@ void memoryview_info::set_physical(bool physical) view<debug_view_memory>()->set_physical(physical); } +void memoryview_info::set_address_radix(int radix) +{ + view<debug_view_memory>()->set_address_radix(radix); +} + void memoryview_info::add_items_to_context_menu(HMENU menu) { diff --git a/src/osd/modules/debugger/win/memoryviewinfo.h b/src/osd/modules/debugger/win/memoryviewinfo.h index 95436e507e6..ccc451acd3e 100644 --- a/src/osd/modules/debugger/win/memoryviewinfo.h +++ b/src/osd/modules/debugger/win/memoryviewinfo.h @@ -28,12 +28,14 @@ public: uint32_t chunks_per_row() const; bool reverse() const; bool physical() const; + int address_radix() const; void set_expression(const std::string &string); void set_data_format(debug_view_memory::data_format dataformat); void set_chunks_per_row(uint32_t rowchunks); void set_reverse(bool reverse); void set_physical(bool physical); + void set_address_radix(int radix); protected: enum diff --git a/src/osd/modules/debugger/win/memorywininfo.cpp b/src/osd/modules/debugger/win/memorywininfo.cpp index a103b3b353b..3ed9b6b9482 100644 --- a/src/osd/modules/debugger/win/memorywininfo.cpp +++ b/src/osd/modules/debugger/win/memorywininfo.cpp @@ -32,21 +32,29 @@ memorywin_info::memorywin_info(debugger_windows_interface &debugger) : // create the options menu HMENU const optionsmenu = CreatePopupMenu(); - AppendMenu(optionsmenu, MF_ENABLED, ID_1_BYTE_CHUNKS, TEXT("1-byte chunks\tCtrl+1")); - AppendMenu(optionsmenu, MF_ENABLED, ID_2_BYTE_CHUNKS, TEXT("2-byte chunks\tCtrl+2")); - AppendMenu(optionsmenu, MF_ENABLED, ID_4_BYTE_CHUNKS, TEXT("4-byte chunks\tCtrl+4")); - AppendMenu(optionsmenu, MF_ENABLED, ID_8_BYTE_CHUNKS, TEXT("8-byte chunks\tCtrl+8")); - AppendMenu(optionsmenu, MF_ENABLED, ID_FLOATING_POINT_32BIT, TEXT("32 bit floating point\tCtrl+9")); - AppendMenu(optionsmenu, MF_ENABLED, ID_FLOATING_POINT_64BIT, TEXT("64 bit floating point")); - AppendMenu(optionsmenu, MF_ENABLED, ID_FLOATING_POINT_80BIT, TEXT("80 bit floating point")); + AppendMenu(optionsmenu, MF_ENABLED, ID_1_BYTE_CHUNKS_HEX, TEXT("1-byte Chunks (Hex)\tCtrl+1")); + AppendMenu(optionsmenu, MF_ENABLED, ID_2_BYTE_CHUNKS_HEX, TEXT("2-byte Chunks (Hex)\tCtrl+2")); + AppendMenu(optionsmenu, MF_ENABLED, ID_4_BYTE_CHUNKS_HEX, TEXT("4-byte Chunks (Hex)\tCtrl+4")); + AppendMenu(optionsmenu, MF_ENABLED, ID_8_BYTE_CHUNKS_HEX, TEXT("8-byte Chunks (Hex)\tCtrl+8")); + AppendMenu(optionsmenu, MF_ENABLED, ID_1_BYTE_CHUNKS_OCT, TEXT("1-byte Chunks (Octal)\tCtrl+3")); + AppendMenu(optionsmenu, MF_ENABLED, ID_2_BYTE_CHUNKS_OCT, TEXT("2-byte Chunks (Octal)\tCtrl+5")); + AppendMenu(optionsmenu, MF_ENABLED, ID_4_BYTE_CHUNKS_OCT, TEXT("4-byte Chunks (Octal)\tCtrl+7")); + AppendMenu(optionsmenu, MF_ENABLED, ID_8_BYTE_CHUNKS_OCT, TEXT("8-byte Chunks (Octal)\tCtrl+9")); + AppendMenu(optionsmenu, MF_ENABLED, ID_FLOAT_32BIT, TEXT("32-bit Floating Point\tCtrl+Shift+F")); + AppendMenu(optionsmenu, MF_ENABLED, ID_FLOAT_64BIT, TEXT("64-bit Floating Point\tCtrl+Shift+D")); + AppendMenu(optionsmenu, MF_ENABLED, ID_FLOAT_80BIT, TEXT("80-bit Floating Point\tCtrl+Shift+E")); + AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); + AppendMenu(optionsmenu, MF_ENABLED, ID_HEX_ADDRESSES, TEXT("Hexadecimal Addresses\tCtrl+Shift+H")); + AppendMenu(optionsmenu, MF_ENABLED, ID_DEC_ADDRESSES, TEXT("Decimal Addresses")); + AppendMenu(optionsmenu, MF_ENABLED, ID_OCT_ADDRESSES, TEXT("Octal Addresses\tCtrl+Shift+O")); AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); AppendMenu(optionsmenu, MF_ENABLED, ID_LOGICAL_ADDRESSES, TEXT("Logical Addresses\tCtrl+L")); AppendMenu(optionsmenu, MF_ENABLED, ID_PHYSICAL_ADDRESSES, TEXT("Physical Addresses\tCtrl+Y")); AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); AppendMenu(optionsmenu, MF_ENABLED, ID_REVERSE_VIEW, TEXT("Reverse View\tCtrl+R")); AppendMenu(optionsmenu, MF_DISABLED | MF_SEPARATOR, 0, TEXT("")); - AppendMenu(optionsmenu, MF_ENABLED, ID_INCREASE_MEM_WIDTH, TEXT("Increase bytes per line\tCtrl+P")); - AppendMenu(optionsmenu, MF_ENABLED, ID_DECREASE_MEM_WIDTH, TEXT("Decrease bytes per line\tCtrl+O")); + AppendMenu(optionsmenu, MF_ENABLED, ID_INCREASE_MEM_WIDTH, TEXT("Increase Bytes Per Line\tCtrl+P")); + AppendMenu(optionsmenu, MF_ENABLED, ID_DECREASE_MEM_WIDTH, TEXT("Decrease Bytes Per Line\tCtrl+O")); AppendMenu(GetMenu(window()), MF_ENABLED | MF_POPUP, (UINT_PTR)optionsmenu, TEXT("Options")); // set up the view to track the initial expression @@ -83,47 +91,87 @@ bool memorywin_info::handle_key(WPARAM wparam, LPARAM lparam) { if (GetAsyncKeyState(VK_CONTROL) & 0x8000) { - switch (wparam) + if (GetAsyncKeyState(VK_SHIFT)) { - case '1': - SendMessage(window(), WM_COMMAND, ID_1_BYTE_CHUNKS, 0); - return true; + switch (wparam) + { + case 'F': + SendMessage(window(), WM_COMMAND, ID_FLOAT_32BIT, 0); + return true; - case '2': - SendMessage(window(), WM_COMMAND, ID_2_BYTE_CHUNKS, 0); - return true; + case 'D': + SendMessage(window(), WM_COMMAND, ID_FLOAT_64BIT, 0); + return true; - case '4': - SendMessage(window(), WM_COMMAND, ID_4_BYTE_CHUNKS, 0); - return true; + case 'E': + SendMessage(window(), WM_COMMAND, ID_FLOAT_80BIT, 0); + return true; - case '8': - SendMessage(window(), WM_COMMAND, ID_8_BYTE_CHUNKS, 0); - return true; + case 'H': + SendMessage(window(), WM_COMMAND, ID_HEX_ADDRESSES, 0); + return true; - case '9': - SendMessage(window(), WM_COMMAND, ID_FLOATING_POINT_32BIT, 0); - return true; + case 'O': + SendMessage(window(), WM_COMMAND, ID_OCT_ADDRESSES, 0); + return true; + } + } + else + { + switch (wparam) + { + case '1': + SendMessage(window(), WM_COMMAND, ID_1_BYTE_CHUNKS_HEX, 0); + return true; - case 'L': - SendMessage(window(), WM_COMMAND, ID_LOGICAL_ADDRESSES, 0); - return true; + case '2': + SendMessage(window(), WM_COMMAND, ID_2_BYTE_CHUNKS_HEX, 0); + return true; - case 'Y': - SendMessage(window(), WM_COMMAND, ID_PHYSICAL_ADDRESSES, 0); - return true; + case '4': + SendMessage(window(), WM_COMMAND, ID_4_BYTE_CHUNKS_HEX, 0); + return true; - case 'R': - SendMessage(window(), WM_COMMAND, ID_REVERSE_VIEW, 0); - return true; + case '8': + SendMessage(window(), WM_COMMAND, ID_8_BYTE_CHUNKS_HEX, 0); + return true; - case 'P': - SendMessage(window(), WM_COMMAND, ID_INCREASE_MEM_WIDTH, 0); - return true; + case '3': + SendMessage(window(), WM_COMMAND, ID_1_BYTE_CHUNKS_OCT, 0); + return true; - case 'O': - SendMessage(window(), WM_COMMAND, ID_DECREASE_MEM_WIDTH, 0); - return true; + case '5': + SendMessage(window(), WM_COMMAND, ID_2_BYTE_CHUNKS_OCT, 0); + return true; + + case '7': + SendMessage(window(), WM_COMMAND, ID_4_BYTE_CHUNKS_OCT, 0); + return true; + + case '9': + SendMessage(window(), WM_COMMAND, ID_8_BYTE_CHUNKS_OCT, 0); + return true; + + case 'L': + SendMessage(window(), WM_COMMAND, ID_LOGICAL_ADDRESSES, 0); + return true; + + case 'Y': + SendMessage(window(), WM_COMMAND, ID_PHYSICAL_ADDRESSES, 0); + return true; + + case 'R': + SendMessage(window(), WM_COMMAND, ID_REVERSE_VIEW, 0); + return true; + + case 'P': + SendMessage(window(), WM_COMMAND, ID_INCREASE_MEM_WIDTH, 0); + return true; + + case 'O': + SendMessage(window(), WM_COMMAND, ID_DECREASE_MEM_WIDTH, 0); + return true; + } } } return editwin_info::handle_key(wparam, lparam); @@ -180,16 +228,28 @@ void memorywin_info::update_menu() auto *const memview = downcast<memoryview_info *>(m_views[0].get()); HMENU const menu = GetMenu(window()); - CheckMenuItem(menu, ID_1_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::HEX_8BIT ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_2_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::HEX_16BIT ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_4_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::HEX_32BIT ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_8_BYTE_CHUNKS, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::HEX_64BIT ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_FLOATING_POINT_32BIT, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::FLOAT_32BIT ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_FLOATING_POINT_64BIT, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::FLOAT_64BIT ? MF_CHECKED : MF_UNCHECKED)); - CheckMenuItem(menu, ID_FLOATING_POINT_80BIT, MF_BYCOMMAND | (memview->data_format() == debug_view_memory::data_format::FLOAT_80BIT ? MF_CHECKED : MF_UNCHECKED)); + + CheckMenuItem(menu, ID_1_BYTE_CHUNKS_HEX, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::HEX_8BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_2_BYTE_CHUNKS_HEX, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::HEX_16BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_4_BYTE_CHUNKS_HEX, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::HEX_32BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_8_BYTE_CHUNKS_HEX, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::HEX_64BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_1_BYTE_CHUNKS_OCT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::OCTAL_8BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_2_BYTE_CHUNKS_OCT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::OCTAL_16BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_4_BYTE_CHUNKS_OCT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::OCTAL_32BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_8_BYTE_CHUNKS_OCT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::OCTAL_64BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_FLOAT_32BIT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::FLOAT_32BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_FLOAT_64BIT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::FLOAT_64BIT) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_FLOAT_80BIT, MF_BYCOMMAND | ((memview->data_format() == debug_view_memory::data_format::FLOAT_80BIT) ? MF_CHECKED : MF_UNCHECKED)); + + CheckMenuItem(menu, ID_HEX_ADDRESSES, MF_BYCOMMAND | ((memview->address_radix() == 16) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_DEC_ADDRESSES, MF_BYCOMMAND | ((memview->address_radix() == 10) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_OCT_ADDRESSES, MF_BYCOMMAND | ((memview->address_radix() == 8) ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_LOGICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_UNCHECKED : MF_CHECKED)); CheckMenuItem(menu, ID_PHYSICAL_ADDRESSES, MF_BYCOMMAND | (memview->physical() ? MF_CHECKED : MF_UNCHECKED)); + CheckMenuItem(menu, ID_REVERSE_VIEW, MF_BYCOMMAND | (memview->reverse() ? MF_CHECKED : MF_UNCHECKED)); + EnableMenuItem(menu, ID_DECREASE_MEM_WIDTH, MF_BYCOMMAND | ((memview->chunks_per_row() > 1) ? MF_ENABLED : MF_GRAYED)); } @@ -219,34 +279,62 @@ bool memorywin_info::handle_command(WPARAM wparam, LPARAM lparam) case 0: switch (LOWORD(wparam)) { - case ID_1_BYTE_CHUNKS: + case ID_1_BYTE_CHUNKS_HEX: memview->set_data_format(debug_view_memory::data_format::HEX_8BIT); return true; - case ID_2_BYTE_CHUNKS: + case ID_2_BYTE_CHUNKS_HEX: memview->set_data_format(debug_view_memory::data_format::HEX_16BIT); return true; - case ID_4_BYTE_CHUNKS: + case ID_4_BYTE_CHUNKS_HEX: memview->set_data_format(debug_view_memory::data_format::HEX_32BIT); return true; - case ID_8_BYTE_CHUNKS: + case ID_8_BYTE_CHUNKS_HEX: memview->set_data_format(debug_view_memory::data_format::HEX_64BIT); return true; - case ID_FLOATING_POINT_32BIT: + case ID_1_BYTE_CHUNKS_OCT: + memview->set_data_format(debug_view_memory::data_format::OCTAL_8BIT); + return true; + + case ID_2_BYTE_CHUNKS_OCT: + memview->set_data_format(debug_view_memory::data_format::OCTAL_16BIT); + return true; + + case ID_4_BYTE_CHUNKS_OCT: + memview->set_data_format(debug_view_memory::data_format::OCTAL_32BIT); + return true; + + case ID_8_BYTE_CHUNKS_OCT: + memview->set_data_format(debug_view_memory::data_format::OCTAL_64BIT); + return true; + + case ID_FLOAT_32BIT: memview->set_data_format(debug_view_memory::data_format::FLOAT_32BIT); return true; - case ID_FLOATING_POINT_64BIT: + case ID_FLOAT_64BIT: memview->set_data_format(debug_view_memory::data_format::FLOAT_64BIT); return true; - case ID_FLOATING_POINT_80BIT: + case ID_FLOAT_80BIT: memview->set_data_format(debug_view_memory::data_format::FLOAT_80BIT); return true; + case ID_HEX_ADDRESSES: + memview->set_address_radix(16); + return true; + + case ID_DEC_ADDRESSES: + memview->set_address_radix(10); + return true; + + case ID_OCT_ADDRESSES: + memview->set_address_radix(8); + return true; + case ID_LOGICAL_ADDRESSES: memview->set_physical(false); return true; diff --git a/src/osd/modules/input/input_sdlcommon.cpp b/src/osd/modules/input/input_sdlcommon.cpp index 9f2b7661379..92e3653e4d1 100644 --- a/src/osd/modules/input/input_sdlcommon.cpp +++ b/src/osd/modules/input/input_sdlcommon.cpp @@ -23,19 +23,26 @@ // MAME headers #include "emu.h" -#include "osdepend.h" + #include "ui/uimain.h" #include "uiinput.h" + #include "window.h" + +#include "util/language.h" + +#include "osdepend.h" #include "strconv.h" #include "../../sdl/osdsdl.h" #include "input_common.h" #include "input_sdlcommon.h" + #define GET_WINDOW(ev) window_from_id((ev)->windowID) //#define GET_WINDOW(ev) ((ev)->windowID) + static std::shared_ptr<sdl_window_info> window_from_id(Uint32 windowID) { SDL_Window *sdl_window = SDL_GetWindowFromID(windowID); @@ -165,16 +172,10 @@ void sdl_osd_interface::customize_input_type_list(std::vector<input_type_entry> break; // alt-enter for fullscreen case IPT_OSD_1: - entry.configure_osd("TOGGLE_FULLSCREEN", "Toggle Fullscreen"); + entry.configure_osd("TOGGLE_FULLSCREEN", N_p("input-name", "Toggle Fullscreen")); entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_ENTER, KEYCODE_LALT); break; - // disable UI_SELECT when LALT is down, this stops selecting - // things in the menu when toggling fullscreen with LALT+ENTER - /* case IPT_UI_SELECT: - entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_ENTER, input_seq::not_code, KEYCODE_LALT); - break;*/ - // page down for fastforward (must be OSD_3 as per src/emu/ui.c) case IPT_UI_FAST_FORWARD: entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_PGDN); @@ -197,13 +198,13 @@ void sdl_osd_interface::customize_input_type_list(std::vector<input_type_entry> // LCTRL-F5 to toggle OpenGL filtering case IPT_OSD_5: - entry.configure_osd("TOGGLE_FILTER", "Toggle Filter"); + entry.configure_osd("TOGGLE_FILTER", N_p("input-name", "Toggle Filter")); entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F5, KEYCODE_LCONTROL); break; // LCTRL-F6 to decrease OpenGL prescaling case IPT_OSD_6: - entry.configure_osd("DECREASE_PRESCALE", "Decrease Prescaling"); + entry.configure_osd("DECREASE_PRESCALE", N_p("input-name", "Decrease Prescaling")); entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F6, KEYCODE_LCONTROL); break; // add a Not lcrtl condition to the toggle cheat key @@ -213,13 +214,13 @@ void sdl_osd_interface::customize_input_type_list(std::vector<input_type_entry> // LCTRL-F7 to increase OpenGL prescaling case IPT_OSD_7: - entry.configure_osd("INCREASE_PRESCALE", "Increase Prescaling"); + entry.configure_osd("INCREASE_PRESCALE", N_p("input-name", "Increase Prescaling")); entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F7, KEYCODE_LCONTROL); break; // lshift-lalt-F12 for fullscreen video (BGFX) case IPT_OSD_8: - entry.configure_osd("RENDER_AVI", "Record Rendered Video"); + entry.configure_osd("RENDER_AVI", N_p("input-name", "Record Rendered Video")); entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, KEYCODE_LSHIFT, KEYCODE_LALT); break; diff --git a/src/osd/modules/input/input_windows.cpp b/src/osd/modules/input/input_windows.cpp index b00d5570ca2..7ed0b2624e1 100644 --- a/src/osd/modules/input/input_windows.cpp +++ b/src/osd/modules/input/input_windows.cpp @@ -12,14 +12,18 @@ // MAME headers #include "emu.h" -#include "osdepend.h" // MAMEOS headers #include "winmain.h" +#include "util/language.h" + +#include "osdepend.h" + #include "input_common.h" #include "input_windows.h" + bool windows_osd_interface::should_hide_mouse() const { bool hidemouse = false; @@ -104,15 +108,16 @@ void windows_osd_interface::customize_input_type_list(std::vector<input_type_ent // alt-enter for fullscreen case IPT_OSD_1: - entry.configure_osd("TOGGLE_FULLSCREEN", "Toggle Fullscreen"); + entry.configure_osd("TOGGLE_FULLSCREEN", N_p("input-name", "Toggle Fullscreen")); entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_ENTER, KEYCODE_LALT, input_seq::or_code, KEYCODE_ENTER, KEYCODE_RALT); break; // lalt-F12 for fullscreen snap (HLSL) case IPT_OSD_2: - entry.configure_osd("RENDER_SNAP", "Take Rendered Snapshot"); + entry.configure_osd("RENDER_SNAP", N_p("input-name", "Take Rendered Snapshot")); entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, KEYCODE_LALT, input_seq::not_code, KEYCODE_LSHIFT); break; + // add a NOT-lalt to our default F12 case IPT_UI_SNAPSHOT: // emu/input.c: input_seq(KEYCODE_F12, input_seq::not_code, KEYCODE_LSHIFT) entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, input_seq::not_code, KEYCODE_LSHIFT, input_seq::not_code, KEYCODE_LALT); @@ -120,7 +125,7 @@ void windows_osd_interface::customize_input_type_list(std::vector<input_type_ent // lshift-lalt-F12 for fullscreen video (HLSL, BGFX) case IPT_OSD_3: - entry.configure_osd("RENDER_AVI", "Record Rendered Video"); + entry.configure_osd("RENDER_AVI", N_p("input-name", "Record Rendered Video")); entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F12, KEYCODE_LSHIFT, KEYCODE_LALT); break; @@ -141,7 +146,7 @@ void windows_osd_interface::customize_input_type_list(std::vector<input_type_ent // lctrl-lalt-F5 to toggle post-processing case IPT_OSD_4: - entry.configure_osd("POST_PROCESS", "Toggle Post-Processing"); + entry.configure_osd("POST_PROCESS", N_p("input-name", "Toggle Post-Processing")); entry.defseq(SEQ_TYPE_STANDARD).set(KEYCODE_F5, KEYCODE_LALT, KEYCODE_LCONTROL); break; |