ui refactoring [Vas Crabb]

* Make ARRAY_LENGTH cause a compile error if used with a pointer/vector
* Clean up text input code, move common operations to inline templates
* Fix numerous one-byte buffer overruns
* Don't flat-out ignore input beyond the C1 hole
* Fix decoding of SDL text input
This commit is contained in:
Vas Crabb 2016-05-27 16:02:01 +10:00
parent 14ad424448
commit 73153c3387
13 changed files with 449 additions and 375 deletions

View File

@ -96,7 +96,7 @@ void menu_barcode_reader::handle()
const event *event = process(PROCESS_LR_REPEAT);
// process the event
if (event != nullptr)
if (event)
{
// handle selections
switch (event->iptkey)
@ -132,15 +132,17 @@ void menu_barcode_reader::handle()
case IPT_SPECIAL:
if (get_selection() == ITEMREF_NEW_BARCODE)
{
int buflen = strlen(m_barcode_buffer);
auto const buflen = std::strlen(m_barcode_buffer);
// if it's a backspace and we can handle it, do so
if ((event->unichar == 8 || event->unichar == 0x7f) && buflen > 0)
*(char *)utf8_previous_char(&m_barcode_buffer[buflen]) = 0;
else if (event->unichar >= '0' && event->unichar <= '9')
if ((event->unichar == 8) || (event->unichar == 0x7f))
{
buflen += utf8_from_uchar(&m_barcode_buffer[buflen], ARRAY_LENGTH(m_barcode_buffer) - buflen, event->unichar);
m_barcode_buffer[buflen] = 0;
if (0 < buflen)
*const_cast<char *>(utf8_previous_char(&m_barcode_buffer[buflen])) = 0;
}
else if ((event->unichar >= '0') && (event->unichar <= '9'))
{
event->append_char(m_barcode_buffer, buflen);
}
reset(reset_options::REMEMBER_POSITION);
}

View File

@ -955,21 +955,21 @@ void menu_rgb_ui::inkey_special(const event *menu_event)
switch ((FPTR)menu_event->itemref)
{
case RGB_ALPHA:
m_color->set_a(val);
break;
case RGB_ALPHA:
m_color->set_a(val);
break;
case RGB_RED:
m_color->set_r(val);
break;
case RGB_RED:
m_color->set_r(val);
break;
case RGB_GREEN:
m_color->set_g(val);
break;
case RGB_GREEN:
m_color->set_g(val);
break;
case RGB_BLUE:
m_color->set_b(val);
break;
case RGB_BLUE:
m_color->set_b(val);
break;
}
m_search[0] = 0;
@ -984,18 +984,22 @@ void menu_rgb_ui::inkey_special(const event *menu_event)
return;
}
int buflen = strlen(m_search);
// if it's a backspace and we can handle it, do so
if (((menu_event->unichar == 8 || menu_event->unichar == 0x7f) && buflen > 0))
*(char *)utf8_previous_char(&m_search[buflen]) = 0;
auto const buflen = std::strlen(m_search);
if ((menu_event->unichar == 8) || (menu_event->unichar == 0x7f))
{
// if it's a backspace and we can handle it, do so
if (0 < buflen)
*const_cast<char *>(utf8_previous_char(&m_search[buflen])) = 0;
}
else if (buflen >= 3)
{
return;
// if it's any other key and we're not maxed out, update
}
else if ((menu_event->unichar >= '0' && menu_event->unichar <= '9'))
buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, menu_event->unichar);
m_search[buflen] = 0;
{
// if it's any other key and we're not maxed out, update
menu_event->append_char(m_search, buflen);
}
}
menu_palette_sel::palcolor menu_palette_sel::m_palette[] = {

View File

@ -340,31 +340,26 @@ void menu_add_change_folder::handle()
}
// reset the char buffer also in this case
if (m_search[0] != 0)
m_search[0] = '\0';
m_search[0] = '\0';
reset(reset_options::SELECT_FIRST);
}
else if (menu_event->iptkey == IPT_SPECIAL)
{
int buflen = strlen(m_search);
bool update_selected = FALSE;
auto const buflen = std::strlen(m_search);
bool update_selected = false;
// if it's a backspace and we can handle it, do so
if ((menu_event->unichar == 8 || menu_event->unichar == 0x7f) && buflen > 0)
if ((menu_event->unichar == 8) || (menu_event->unichar == 0x7f))
{
*(char *)utf8_previous_char(&m_search[buflen]) = 0;
update_selected = TRUE;
// if it's a backspace and we can handle it, do so
if (0 < buflen)
{
*const_cast<char *>(utf8_previous_char(&m_search[buflen])) = 0;
update_selected = true;
}
}
// if it's any other key and we're not maxed out, update
else if (menu_event->unichar >= ' ' && menu_event->unichar < 0x7f)
{
buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, menu_event->unichar);
m_search[buflen] = 0;
update_selected = TRUE;
}
// Tab key, save current path
else if (menu_event->unichar == 0x09)
{
// Tab key, save current path
std::string error_string;
if (m_change)
{
@ -400,6 +395,12 @@ void menu_add_change_folder::handle()
reset_parent(reset_options::SELECT_FIRST);
menu::stack_pop(machine());
}
else if (menu_event->is_char_printable())
{
// if it's any other key and we're not maxed out, update
if (menu_event->append_char(m_search, buflen))
update_selected = true;
}
// check for entries which matches our search buffer
if (update_selected)

View File

@ -54,18 +54,24 @@ namespace ui {
// into a buffer
//-------------------------------------------------
static void input_character(char *buffer, size_t buffer_length, unicode_char unichar, int (*filter)(unicode_char))
template <std::size_t N, typename F>
static void input_character(char (&buffer)[N], unicode_char unichar, F &&filter)
{
size_t buflen = strlen(buffer);
auto buflen = std::strlen(buffer);
if ((unichar == 8 || unichar == 0x7f) && (buflen > 0))
if ((unichar == 8) || (unichar == 0x7f))
{
*(char *)utf8_previous_char(&buffer[buflen]) = 0;
if (0 < buflen)
*const_cast<char *>(utf8_previous_char(&buffer[buflen])) = 0;
}
else if ((unichar > ' ') && ((filter == nullptr) || (*filter)(unichar)))
else if ((unichar >= ' ') && (!filter || filter(unichar)))
{
buflen += utf8_from_uchar(&buffer[buflen], buffer_length - buflen, unichar);
buffer[buflen] = 0;
auto const chlen = utf8_from_uchar(&buffer[buflen], N - buflen - 1, unichar);
if (0 <= chlen)
{
buflen += chlen;
buffer[buflen] = 0;
}
}
}
@ -140,7 +146,7 @@ void menu_confirm_save_as::handle()
static int is_valid_filename_char(unicode_char unichar)
{
// this should really be in the OSD layer
// this should really be in the OSD layer, and it shouldn't be 7-bit bullshit
static const char valid_filename_char[] =
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00-0f
@ -243,39 +249,35 @@ void menu_file_create::handle()
const event *event = process(0);
// process the event
if (event != nullptr)
if (event)
{
// handle selections
switch(event->iptkey)
switch (event->iptkey)
{
case IPT_UI_SELECT:
if ((event->itemref == ITEMREF_CREATE) || (event->itemref == ITEMREF_NEW_IMAGE_NAME))
case IPT_UI_SELECT:
if ((event->itemref == ITEMREF_CREATE) || (event->itemref == ITEMREF_NEW_IMAGE_NAME))
{
std::string tmp_file(m_filename_buffer);
if (tmp_file.find(".") != -1 && tmp_file.find(".") < tmp_file.length() - 1)
{
std::string tmp_file(m_filename_buffer);
if (tmp_file.find(".") != -1 && tmp_file.find(".") < tmp_file.length() - 1)
{
m_current_file = m_filename_buffer;
menu::stack_pop(machine());
}
else
ui().popup_time(1, "%s", _("Please enter a file extension too"));
m_current_file = m_filename_buffer;
menu::stack_pop(machine());
}
break;
else
ui().popup_time(1, "%s", _("Please enter a file extension too"));
}
break;
case IPT_SPECIAL:
if (get_selection() == ITEMREF_NEW_IMAGE_NAME)
{
input_character(
m_filename_buffer,
ARRAY_LENGTH(m_filename_buffer),
event->unichar,
is_valid_filename_char);
reset(reset_options::REMEMBER_POSITION);
}
break;
case IPT_UI_CANCEL:
*m_ok = false;
break;
case IPT_SPECIAL:
if (get_selection() == ITEMREF_NEW_IMAGE_NAME)
{
input_character(m_filename_buffer,event->unichar, is_valid_filename_char);
reset(reset_options::REMEMBER_POSITION);
}
break;
case IPT_UI_CANCEL:
*m_ok = false;
break;
}
}
}
@ -581,45 +583,45 @@ void menu_file_selector::handle()
if (event->iptkey == IPT_UI_SELECT)
{
entry = (const file_selector_entry *) event->itemref;
switch(entry->type)
switch (entry->type)
{
case SELECTOR_ENTRY_TYPE_EMPTY:
// empty slot - unload
*m_result = R_EMPTY;
menu::stack_pop(machine());
break;
case SELECTOR_ENTRY_TYPE_EMPTY:
// empty slot - unload
*m_result = R_EMPTY;
menu::stack_pop(machine());
break;
case SELECTOR_ENTRY_TYPE_CREATE:
// create
*m_result = R_CREATE;
menu::stack_pop(machine());
break;
case SELECTOR_ENTRY_TYPE_CREATE:
// create
*m_result = R_CREATE;
menu::stack_pop(machine());
break;
case SELECTOR_ENTRY_TYPE_SOFTWARE_LIST:
*m_result = R_SOFTLIST;
menu::stack_pop(machine());
break;
case SELECTOR_ENTRY_TYPE_SOFTWARE_LIST:
*m_result = R_SOFTLIST;
menu::stack_pop(machine());
break;
case SELECTOR_ENTRY_TYPE_DRIVE:
case SELECTOR_ENTRY_TYPE_DIRECTORY:
// drive/directory - first check the path
err = util::zippath_opendir(entry->fullpath, nullptr);
if (err != osd_file::error::NONE)
{
// this path is problematic; present the user with an error and bail
ui().popup_time(1, "Error accessing %s", entry->fullpath);
break;
}
m_current_directory.assign(entry->fullpath);
reset(reset_options::SELECT_FIRST);
case SELECTOR_ENTRY_TYPE_DRIVE:
case SELECTOR_ENTRY_TYPE_DIRECTORY:
// drive/directory - first check the path
err = util::zippath_opendir(entry->fullpath, nullptr);
if (err != osd_file::error::NONE)
{
// this path is problematic; present the user with an error and bail
ui().popup_time(1, "Error accessing %s", entry->fullpath);
break;
}
m_current_directory.assign(entry->fullpath);
reset(reset_options::SELECT_FIRST);
break;
case SELECTOR_ENTRY_TYPE_FILE:
// file
m_current_file.assign(entry->fullpath);
*m_result = R_FILE;
menu::stack_pop(machine());
break;
case SELECTOR_ENTRY_TYPE_FILE:
// file
m_current_file.assign(entry->fullpath);
*m_result = R_FILE;
menu::stack_pop(machine());
break;
}
// reset the char buffer when pressing IPT_UI_SELECT
@ -628,27 +630,29 @@ void menu_file_selector::handle()
}
else if (event->iptkey == IPT_SPECIAL)
{
int buflen = strlen(m_filename_buffer);
auto const buflen = std::strlen(m_filename_buffer);
bool update_selected = FALSE;
// if it's a backspace and we can handle it, do so
if ((event->unichar == 8 || event->unichar == 0x7f) && buflen > 0)
if ((event->unichar == 8) || (event->unichar == 0x7f))
{
*(char *)utf8_previous_char(&m_filename_buffer[buflen]) = 0;
update_selected = TRUE;
// if it's a backspace and we can handle it, do so
if (0 < buflen)
{
*const_cast<char *>(utf8_previous_char(&m_filename_buffer[buflen])) = 0;
update_selected = TRUE;
if (ARRAY_LENGTH(m_filename_buffer) > 0)
ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer);
}
}
// if it's any other key and we're not maxed out, update
else if (event->unichar >= ' ' && event->unichar < 0x7f)
else if (event->is_char_printable())
{
buflen += utf8_from_uchar(&m_filename_buffer[buflen], ARRAY_LENGTH(m_filename_buffer) - buflen, event->unichar);
m_filename_buffer[buflen] = 0;
update_selected = TRUE;
// if it's any other key and we're not maxed out, update
if (event->append_char(m_filename_buffer, buflen))
{
update_selected = TRUE;
if (ARRAY_LENGTH(m_filename_buffer) > 0)
ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer);
}
}
if (update_selected)

View File

@ -9,12 +9,10 @@
*********************************************************************/
#include "emu.h"
#include "rendutil.h"
#include "cheat.h"
#include "mame.h"
#include "uiinput.h"
#include "ui/ui.h"
#include "ui/menu.h"
#include "ui/ui.h"
#include "ui/mainmenu.h"
#include "ui/utils.h"
#include "ui/defimg.h"
@ -22,7 +20,12 @@
#include "ui/icorender.h"
#include "ui/toolbar.h"
#include "ui/miscmenu.h"
#include "cheat.h"
#include "drivenum.h"
#include "mame.h"
#include "rendutil.h"
#include "uiinput.h"
namespace ui {
@ -208,6 +211,7 @@ menu::menu(mame_ui_manager &mui, render_container *_container)
, m_repeat(0)
, m_event()
, m_pool(nullptr)
, m_focus(focused_menu::main)
{
container = _container;

View File

@ -13,11 +13,12 @@
#ifndef MAME_FRONTEND_UI_MENU_H
#define MAME_FRONTEND_UI_MENU_H
#include "render.h"
#include "language.h"
#include "ui/ui.h"
#include "ui/menuitem.h"
#include "language.h"
#include "render.h"
#include <memory>
@ -149,16 +150,6 @@ private:
static void render_triangle(bitmap_argb32 &dest, bitmap_argb32 &source, const rectangle &sbounds, void *param);
public:
// tab navigation
enum class focused_menu
{
main,
left,
righttop,
rightbottom
};
focused_menu m_focus;
void *m_prev_selected;
int visible_items;
@ -215,6 +206,15 @@ protected:
REMEMBER_REF
};
// tab navigation
enum class focused_menu
{
main,
left,
righttop,
rightbottom
};
// menu-related events
struct event
{
@ -223,6 +223,31 @@ protected:
int iptkey; // one of the IPT_* values from inptport.h
unicode_char unichar; // unicode character if iptkey == IPT_SPECIAL
render_bounds mouse; // mouse position if iptkey == IPT_CUSTOM
bool is_char_printable() const
{
return
!(0x0001f >= unichar) && // C0 control
!((0x0007f <= unichar) && (0x0009f >= unichar)) && // DEL and C1 control
!((0x0fdd0 <= unichar) && (0x0fddf >= unichar)) && // noncharacters
!(0x0fffe == (unichar & 0x0ffff)) && // byte-order detection noncharacter
!(0x0ffff == (unichar & 0x0ffff)); // the other noncharacter
}
template <std::size_t N>
bool append_char(char (&buffer)[N], std::size_t offset) const
{
auto const chlen = utf8_from_uchar(&buffer[offset], N - offset - 1, unichar);
if (0 < chlen)
{
buffer[offset + chlen] = '\0';
return true;
}
else
{
return false;
}
}
};
int topline_datsview; // right box top line
@ -243,6 +268,9 @@ protected:
const event *process(UINT32 flags, float x0 = 0.0f, float y0 = 0.0f);
void process_parent() { m_parent->process(PROCESS_NOINPUT); }
bool is_focus(focused_menu focus) const { return m_focus == focus; }
void set_focus(focused_menu focus) { m_focus = focus; }
// draw right box
float draw_right_box_title(float x1, float y1, float x2, float y2);
@ -324,6 +352,7 @@ private:
osd_ticks_t m_repeat;
event m_event; // the UI event that occurred
pool *m_pool; // list of memory pools
focused_menu m_focus;
static std::unique_ptr<menu> menu_stack;
static std::unique_ptr<menu> menu_free;

View File

@ -100,21 +100,21 @@ void menu_selector::handle()
}
else if (menu_event->iptkey == IPT_SPECIAL)
{
int buflen = strlen(m_search);
// if it's a backspace and we can handle it, do so
if ((menu_event->unichar == 8 || menu_event->unichar == 0x7f) && buflen > 0)
auto const buflen = strlen(m_search);
if ((menu_event->unichar == 8) || (menu_event->unichar == 0x7f))
{
*(char *)utf8_previous_char(&m_search[buflen]) = 0;
reset(reset_options::SELECT_FIRST);
// if it's a backspace and we can handle it, do so
if (0 < buflen)
{
*const_cast<char *>(utf8_previous_char(&m_search[buflen])) = 0;
reset(reset_options::SELECT_FIRST);
}
}
// if it's any other key and we're not maxed out, update
else if (menu_event->unichar >= ' ' && menu_event->unichar < 0x7f)
else if (menu_event->is_char_printable())
{
buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, menu_event->unichar);
m_search[buflen] = 0;
reset(reset_options::SELECT_FIRST);
// if it's any other key and we're not maxed out, update
if (menu_event->append_char(m_search, buflen))
reset(reset_options::SELECT_FIRST);
}
}

View File

@ -58,7 +58,7 @@ int menu_select_game::m_isabios = 0;
menu_select_game::menu_select_game(mame_ui_manager &mui, render_container *container, const char *gamename) : menu(mui, container)
{
m_focus = focused_menu::main;
set_focus(focused_menu::main);
highlight = 0;
std::string error_string, last_filter, sub_filter;
ui_options &moptions = mui.options();
@ -206,54 +206,51 @@ void menu_select_game::handle()
// process the menu
const event *menu_event = process(PROCESS_LR_REPEAT);
if (menu_event != nullptr && menu_event->itemref != nullptr)
if (menu_event && menu_event->itemref)
{
// reset the error on any future menu_event
if (ui_error)
{
// reset the error on any future menu_event
ui_error = false;
machine().ui_input().reset();
}
// handle selections
else if (menu_event->iptkey == IPT_UI_SELECT)
{
if (m_focus == focused_menu::main)
// handle selections
if (is_focus(focused_menu::main))
{
if (isfavorite())
inkey_select_favorite(menu_event);
else
inkey_select(menu_event);
}
else if (m_focus == focused_menu::left)
else if (is_focus(focused_menu::left))
{
l_hover = highlight;
check_filter = true;
m_prev_selected = nullptr;
}
}
// handle IPT_CUSTOM (mouse right click)
else if (menu_event->iptkey == IPT_CUSTOM)
{
// handle IPT_CUSTOM (mouse right click)
if (!isfavorite())
menu::stack_push<menu_machine_configure>(ui(), container, (const game_driver *)m_prev_selected, menu_event->mouse.x0, menu_event->mouse.y0);
}
// handle UI_LEFT
else if (menu_event->iptkey == IPT_UI_LEFT)
{
// Images
// handle UI_LEFT
if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view > FIRST_VIEW)
{
// Images
ui_globals::curimage_view--;
ui_globals::switch_image = true;
ui_globals::default_image = false;
}
// Infos
else if (ui_globals::rpanel == RP_INFOS)
{
// Infos
if (!isfavorite())
{
const game_driver *drv = (const game_driver *)menu_event->itemref;
@ -279,21 +276,19 @@ void menu_select_game::handle()
}
}
}
// handle UI_RIGHT
else if (menu_event->iptkey == IPT_UI_RIGHT)
{
// Images
// handle UI_RIGHT
if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view < LAST_VIEW)
{
// Images
ui_globals::curimage_view++;
ui_globals::switch_image = true;
ui_globals::default_image = false;
}
// Infos
else if (ui_globals::rpanel == RP_INFOS)
{
// Infos
if (!isfavorite())
{
const game_driver *drv = (const game_driver *)menu_event->itemref;
@ -319,37 +314,35 @@ void menu_select_game::handle()
}
}
}
// handle UI_UP_FILTER
else if (menu_event->iptkey == IPT_UI_UP_FILTER && highlight > FILTER_FIRST)
{
// handle UI_UP_FILTER
highlight--;
}
// handle UI_DOWN_FILTER
else if (menu_event->iptkey == IPT_UI_DOWN_FILTER && highlight < FILTER_LAST)
{
// handle UI_DOWN_FILTER
highlight++;
}
// handle UI_LEFT_PANEL
else if (menu_event->iptkey == IPT_UI_LEFT_PANEL)
{
// handle UI_LEFT_PANEL
ui_globals::rpanel = RP_IMAGES;
// handle UI_RIGHT_PANEL
}
else if (menu_event->iptkey == IPT_UI_RIGHT_PANEL)
{
// handle UI_RIGHT_PANEL
ui_globals::rpanel = RP_INFOS;
// escape pressed with non-empty text clears the text
}
else if (menu_event->iptkey == IPT_UI_CANCEL && m_search[0] != 0)
{
// escape pressed with non-empty text clears the text
m_search[0] = '\0';
reset(reset_options::SELECT_FIRST);
}
// handle UI_DATS
else if (menu_event->iptkey == IPT_UI_DATS && enabled_dats)
{
// handle UI_DATS
if (!isfavorite())
{
const game_driver *driver = (const game_driver *)menu_event->itemref;
@ -370,10 +363,9 @@ void menu_select_game::handle()
}
}
}
// handle UI_FAVORITES
else if (menu_event->iptkey == IPT_UI_FAVORITES)
{
// handle UI_FAVORITES
if (!isfavorite())
{
const game_driver *driver = (const game_driver *)menu_event->itemref;
@ -404,23 +396,26 @@ void menu_select_game::handle()
}
}
}
// handle UI_EXPORT
else if (menu_event->iptkey == IPT_UI_EXPORT && !isfavorite())
{
// handle UI_EXPORT
inkey_export();
// handle UI_AUDIT_FAST
}
else if (menu_event->iptkey == IPT_UI_AUDIT_FAST && !m_unavailsortedlist.empty())
{
// handle UI_AUDIT_FAST
menu::stack_push<menu_audit>(ui(), container, m_availsortedlist, m_unavailsortedlist, 1);
// handle UI_AUDIT_ALL
}
else if (menu_event->iptkey == IPT_UI_AUDIT_ALL)
{
// handle UI_AUDIT_ALL
menu::stack_push<menu_audit>(ui(), container, m_availsortedlist, m_unavailsortedlist, 2);
// typed characters append to the buffer
}
else if (menu_event->iptkey == IPT_SPECIAL)
{
// typed characters append to the buffer
inkey_special(menu_event);
}
else if (menu_event->iptkey == IPT_UI_CONFIGURE)
inkey_configure(menu_event);
@ -432,28 +427,31 @@ void menu_select_game::handle()
}
}
if (menu_event != nullptr && menu_event->itemref == nullptr)
if (menu_event && !menu_event->itemref)
{
if (menu_event->iptkey == IPT_SPECIAL)
{
inkey_special(menu_event);
}
else if (menu_event->iptkey == IPT_UI_CONFIGURE)
{
inkey_configure(menu_event);
}
else if (menu_event->iptkey == IPT_OTHER)
{
m_focus = focused_menu::left;
set_focus(focused_menu::left);
m_prev_selected = nullptr;
l_hover = highlight;
check_filter = true;
}
// handle UI_UP_FILTER
else if (menu_event->iptkey == IPT_UI_UP_FILTER && highlight > FILTER_FIRST)
{
// handle UI_UP_FILTER
highlight--;
}
// handle UI_DOWN_FILTER
else if (menu_event->iptkey == IPT_UI_DOWN_FILTER && highlight < FILTER_LAST)
{
// handle UI_DOWN_FILTER
highlight++;
}
}
@ -931,6 +929,7 @@ void menu_select_game::custom_render(void *selectedref, float top, float bottom,
{
std::string copyright(emulator_info::get_copyright());
size_t found = copyright.find("\n");
tempbuf[0].clear();
tempbuf[1] = string_format(_("%1$s %2$s"), emulator_info::get_appname(), build_version);
tempbuf[2] = copyright.substr(0, found);
@ -1152,7 +1151,9 @@ void menu_select_game::inkey_select_favorite(const event *menu_event)
drv.next();
software_list_device *swlist = software_list_device::find_by_name(drv.config(), ui_swinfo->listname.c_str());
software_info *swinfo = swlist->find(ui_swinfo->shortname.c_str());
media_auditor::summary summary = auditor.audit_software(swlist->list_name(), swinfo, AUDIT_VALIDATE_FAST);
if (summary == media_auditor::CORRECT || summary == media_auditor::BEST_AVAILABLE || summary == media_auditor::NONE_NEEDED)
{
s_bios biosname;
@ -1190,6 +1191,7 @@ void menu_select_game::inkey_select_favorite(const event *menu_event)
machine().schedule_hard_reset();
menu::stack_reset(machine());
}
// otherwise, display an error
else
{
@ -1214,52 +1216,64 @@ inline bool menu_select_game::isfavorite()
void menu_select_game::inkey_special(const event *menu_event)
{
int buflen = strlen(m_search);
if (!isfavorite())
{
auto const buflen = std::strlen(m_search);
// if it's a backspace and we can handle it, do so
if (((menu_event->unichar == 8 || menu_event->unichar == 0x7f) && buflen > 0) && !isfavorite())
{
*(char *)utf8_previous_char(&m_search[buflen]) = 0;
reset(reset_options::SELECT_FIRST);
}
else if ((menu_event->unichar >= ' ' && menu_event->unichar < 0x7f) && !isfavorite())
{
// if it's any other key and we're not maxed out, update
buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, menu_event->unichar);
m_search[buflen] = 0;
reset(reset_options::SELECT_FIRST);
if ((menu_event->unichar == 8) || (menu_event->unichar == 0x7f))
{
// if it's a backspace and we can handle it, do so
if (0 < buflen)
{
*const_cast<char *>(utf8_previous_char(&m_search[buflen])) = 0;
reset(reset_options::SELECT_FIRST);
}
}
else if (menu_event->is_char_printable())
{
// if it's any other key and we're not maxed out, update
if (menu_event->append_char(m_search, buflen))
reset(reset_options::SELECT_FIRST);
}
}
}
void menu_select_game::inkey_configure(const event *menu_event)
{
if (selected <= visible_items && m_focus == focused_menu::main)
if (is_focus(focused_menu::main))
{
m_prev_selected = item[selected].ref;
selected = visible_items + 1;
}
else if (selected > visible_items && m_focus == focused_menu::main)
{
if (ui_globals::panels_status != HIDE_LEFT_PANEL)
m_focus = focused_menu::left;
else if (ui_globals::panels_status == HIDE_BOTH)
if (selected <= visible_items)
{
for (int x = 0; x < item.size(); ++x)
if (item[x].ref == m_prev_selected)
selected = x;
m_prev_selected = item[selected].ref;
selected = visible_items + 1;
}
else
m_focus = focused_menu::righttop;
{
if (ui_globals::panels_status != HIDE_LEFT_PANEL)
set_focus(focused_menu::left);
else if (ui_globals::panels_status == HIDE_BOTH)
{
for (int x = 0; x < item.size(); ++x)
if (item[x].ref == m_prev_selected)
selected = x;
}
else
{
set_focus(focused_menu::righttop);
}
}
}
else if (m_focus == focused_menu::left)
else if (is_focus(focused_menu::left))
{
if (ui_globals::panels_status != HIDE_RIGHT_PANEL)
m_focus = focused_menu::righttop;
{
set_focus(focused_menu::righttop);
}
else
{
m_focus = focused_menu::main;
set_focus(focused_menu::main);
if (m_prev_selected == nullptr)
{
selected = 0;
@ -1271,11 +1285,13 @@ void menu_select_game::inkey_configure(const event *menu_event)
selected = x;
}
}
else if (m_focus == focused_menu::righttop)
m_focus = focused_menu::rightbottom;
else if (m_focus == focused_menu::rightbottom)
else if (is_focus(focused_menu::righttop))
{
m_focus = focused_menu::main;
set_focus(focused_menu::rightbottom);
}
else if (is_focus(focused_menu::rightbottom))
{
set_focus(focused_menu::main);
if (m_prev_selected == nullptr)
{
selected = 0;
@ -1844,7 +1860,7 @@ float menu_select_game::draw_left_panel(float x1, float y1, float x2, float y2)
menu::highlight(container, x1, y1, x2, y1+ line_height_max, bgcolor);
}
if (highlight == filter && m_focus == focused_menu::left)
if (highlight == filter && is_focus(focused_menu::left))
{
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
@ -1999,7 +2015,7 @@ void menu_select_game::infos_render(void *selectedref, float origx1, float origy
rgb_t fgcolor = UI_TEXT_COLOR;
rgb_t bgcolor = UI_TEXT_BG_COLOR;
if (m_focus == focused_menu::rightbottom)
if (is_focus(focused_menu::rightbottom))
{
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
@ -2178,7 +2194,7 @@ void menu_select_game::infos_render(void *selectedref, float origx1, float origy
rgb_t fgcolor = UI_TEXT_COLOR;
rgb_t bgcolor = UI_TEXT_BG_COLOR;
if (m_focus == focused_menu::rightbottom)
if (is_focus(focused_menu::rightbottom))
{
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
@ -2461,7 +2477,7 @@ void menu_select_game::arts_render(void *selectedref, float origx1, float origy1
if (!tmp_bitmap->valid())
{
// Second attempt from driver name + part name
pathname.assign(soft->driver->name).append(soft->part.c_str());
pathname.assign(soft->driver->name).append(soft->part);
fullname.assign(soft->shortname).append(".png");
render_load_png(*tmp_bitmap, snapfile, pathname.c_str(), fullname.c_str());

View File

@ -173,83 +173,75 @@ void menu_select_software::handle()
// process the menu
const event *menu_event = process(PROCESS_LR_REPEAT);
if (menu_event != nullptr && menu_event->itemref != nullptr)
if (menu_event && menu_event->itemref)
{
// reset the error on any future event
if (ui_error)
{
// reset the error on any future event
ui_error = false;
machine().ui_input().reset();
}
// handle selections
else if (menu_event->iptkey == IPT_UI_SELECT)
{
if (m_focus == focused_menu::main)
// handle selections
if (is_focus(focused_menu::main))
{
inkey_select(menu_event);
}
else if (m_focus == focused_menu::left)
else if (is_focus(focused_menu::left))
{
l_sw_hover = highlight;
check_filter = true;
m_prev_selected = nullptr;
}
}
// handle UI_LEFT
else if (menu_event->iptkey == IPT_UI_LEFT)
{
// Images
// handle UI_LEFT
if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view > FIRST_VIEW)
{
// Images
ui_globals::curimage_view--;
ui_globals::switch_image = true;
ui_globals::default_image = false;
}
// Infos
else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view > 0)
{
// Infos
ui_globals::cur_sw_dats_view--;
topline_datsview = 0;
}
}
// handle UI_RIGHT
else if (menu_event->iptkey == IPT_UI_RIGHT)
{
// Images
// handle UI_RIGHT
if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view < LAST_VIEW)
{
// Images
ui_globals::curimage_view++;
ui_globals::switch_image = true;
ui_globals::default_image = false;
}
// Infos
else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view < 1)
{
// Infos
ui_globals::cur_sw_dats_view++;
topline_datsview = 0;
}
}
// handle UI_UP_FILTER
else if (menu_event->iptkey == IPT_UI_UP_FILTER && highlight > UI_SW_FIRST)
{
// handle UI_UP_FILTER
highlight--;
}
// handle UI_DOWN_FILTER
else if (menu_event->iptkey == IPT_UI_DOWN_FILTER && highlight < UI_SW_LAST)
{
// handle UI_DOWN_FILTER
highlight++;
}
// handle UI_DATS
else if (menu_event->iptkey == IPT_UI_DATS && ui().options().enabled_dats())
{
// handle UI_DATS
ui_software_info *ui_swinfo = (ui_software_info *)menu_event->itemref;
datfile_manager &mdat = mame_machine_manager::instance()->datfile();
@ -258,25 +250,25 @@ void menu_select_software::handle()
else if (mdat.has_software(ui_swinfo->listname, ui_swinfo->shortname, ui_swinfo->parentname) || !ui_swinfo->usage.empty())
menu::stack_push<menu_dats_view>(ui(), container, ui_swinfo);
}
// handle UI_LEFT_PANEL
else if (menu_event->iptkey == IPT_UI_LEFT_PANEL)
{
// handle UI_LEFT_PANEL
ui_globals::rpanel = RP_IMAGES;
// handle UI_RIGHT_PANEL
}
else if (menu_event->iptkey == IPT_UI_RIGHT_PANEL)
{
// handle UI_RIGHT_PANEL
ui_globals::rpanel = RP_INFOS;
// escape pressed with non-empty text clears the text
}
else if (menu_event->iptkey == IPT_UI_CANCEL && m_search[0] != 0)
{
// escape pressed with non-empty text clears the text
m_search[0] = '\0';
reset(reset_options::SELECT_FIRST);
}
// handle UI_FAVORITES
else if (menu_event->iptkey == IPT_UI_FAVORITES)
{
// handle UI_FAVORITES
ui_software_info *swinfo = (ui_software_info *)menu_event->itemref;
if ((FPTR)swinfo > 2)
@ -295,11 +287,11 @@ void menu_select_software::handle()
}
}
}
// typed characters append to the buffer
else if (menu_event->iptkey == IPT_SPECIAL)
{
// typed characters append to the buffer
inkey_special(menu_event);
}
else if (menu_event->iptkey == IPT_OTHER)
{
highlight = l_sw_hover;
@ -314,72 +306,69 @@ void menu_select_software::handle()
if (menu_event && !menu_event->itemref)
{
if (menu_event->iptkey == IPT_UI_CONFIGURE)
{
inkey_configure(menu_event);
// handle UI_LEFT
}
else if (menu_event->iptkey == IPT_UI_LEFT)
{
// Images
// handle UI_LEFT
if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view > FIRST_VIEW)
{
// Images
ui_globals::curimage_view--;
ui_globals::switch_image = true;
ui_globals::default_image = false;
}
// Infos
else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view > 0)
{
// Infos
ui_globals::cur_sw_dats_view--;
topline_datsview = 0;
}
}
// handle UI_RIGHT
else if (menu_event->iptkey == IPT_UI_RIGHT)
{
// Images
// handle UI_RIGHT
if (ui_globals::rpanel == RP_IMAGES && ui_globals::curimage_view < LAST_VIEW)
{
// Images
ui_globals::curimage_view++;
ui_globals::switch_image = true;
ui_globals::default_image = false;
}
// Infos
else if (ui_globals::rpanel == RP_INFOS && ui_globals::cur_sw_dats_view < 1)
{
// Infos
ui_globals::cur_sw_dats_view++;
topline_datsview = 0;
}
}
// handle UI_LEFT_PANEL
else if (menu_event->iptkey == IPT_UI_LEFT_PANEL)
{
// handle UI_LEFT_PANEL
ui_globals::rpanel = RP_IMAGES;
// handle UI_RIGHT_PANEL
}
else if (menu_event->iptkey == IPT_UI_RIGHT_PANEL)
{
// handle UI_RIGHT_PANEL
ui_globals::rpanel = RP_INFOS;
// handle UI_UP_FILTER
}
else if (menu_event->iptkey == IPT_UI_UP_FILTER && highlight > UI_SW_FIRST)
{
// handle UI_UP_FILTER
highlight--;
}
// handle UI_DOWN_FILTER
else if (menu_event->iptkey == IPT_UI_DOWN_FILTER && highlight < UI_SW_LAST)
{
// handle UI_DOWN_FILTER
highlight++;
}
else if (menu_event->iptkey == IPT_OTHER && m_focus == focused_menu::left)
else if (menu_event->iptkey == IPT_OTHER && is_focus(focused_menu::left))
{
l_sw_hover = highlight;
check_filter = true;
m_prev_selected = nullptr;
}
}
// if we're in an error state, overlay an error message
@ -784,7 +773,6 @@ void menu_select_software::custom_render(void *selectedref, float top, float bot
if ((driver->flags & (MACHINE_NOT_WORKING | MACHINE_UNEMULATED_PROTECTION)) != 0)
color = UI_RED_COLOR;
}
else if (swinfo != nullptr)
@ -823,7 +811,6 @@ void menu_select_software::custom_render(void *selectedref, float top, float bot
// last line is romset name
tempbuf[4] = string_format(_("romset: %1$-.100s"), swinfo->shortname.c_str());
}
else
{
std::string copyright(emulator_info::get_copyright());
@ -950,6 +937,7 @@ void menu_select_software::inkey_select(const event *menu_event)
menu::stack_push<software_parts>(ui(), container, parts, ui_swinfo);
return;
}
std::string error_string;
std::string string_list = std::string(ui_swinfo->listname).append(":").append(ui_swinfo->shortname).append(":").append(ui_swinfo->part).append(":").append(ui_swinfo->instance);
machine().options().set_value(OPTION_SOFTWARENAME, string_list.c_str(), OPTION_PRIORITY_CMDLINE, error_string);
@ -979,52 +967,61 @@ void menu_select_software::inkey_select(const event *menu_event)
void menu_select_software::inkey_special(const event *menu_event)
{
int buflen = strlen(m_search);
auto const buflen = std::strlen(m_search);
// if it's a backspace and we can handle it, do so
if ((menu_event->unichar == 8 || menu_event->unichar == 0x7f) && buflen > 0)
if ((menu_event->unichar == 8) || (menu_event->unichar == 0x7f))
{
*(char *)utf8_previous_char(&m_search[buflen]) = 0;
reset(reset_options::SELECT_FIRST);
// if it's a backspace and we can handle it, do so
if (0 < buflen)
{
*const_cast<char *>(utf8_previous_char(&m_search[buflen])) = 0;
reset(reset_options::SELECT_FIRST);
}
}
// if it's any other key and we're not maxed out, update
else if (menu_event->unichar >= ' ' && menu_event->unichar < 0x7f)
else if (menu_event->is_char_printable())
{
buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, menu_event->unichar);
m_search[buflen] = 0;
reset(reset_options::SELECT_FIRST);
// if it's any other key and we're not maxed out, update
if (menu_event->append_char(m_search, buflen))
reset(reset_options::SELECT_FIRST);
}
}
void menu_select_software::inkey_configure(const event *menu_event)
{
if (selected <= visible_items && m_focus == focused_menu::main)
if (is_focus(focused_menu::main))
{
m_prev_selected = item[selected].ref;
selected = visible_items + 1;
}
else if (selected > visible_items && m_focus == focused_menu::main)
{
if (ui_globals::panels_status != HIDE_LEFT_PANEL)
m_focus = focused_menu::left;
else if (ui_globals::panels_status == HIDE_BOTH)
if (selected <= visible_items)
{
for (int x = 0; x < item.size(); ++x)
if (item[x].ref == m_prev_selected)
selected = x;
m_prev_selected = item[selected].ref;
selected = visible_items + 1;
}
else
m_focus = focused_menu::righttop;
{
if (ui_globals::panels_status != HIDE_LEFT_PANEL)
set_focus(focused_menu::left);
else if (ui_globals::panels_status == HIDE_BOTH)
{
for (int x = 0; x < item.size(); ++x)
if (item[x].ref == m_prev_selected)
selected = x;
}
else
{
set_focus(focused_menu::righttop);
}
}
}
else if (m_focus == focused_menu::left)
else if (is_focus(focused_menu::left))
{
if (ui_globals::panels_status != HIDE_RIGHT_PANEL)
m_focus = focused_menu::righttop;
{
set_focus(focused_menu::righttop);
}
else
{
m_focus = focused_menu::main;
set_focus(focused_menu::main);
if (m_prev_selected == nullptr)
{
selected = 0;
@ -1036,11 +1033,13 @@ void menu_select_software::inkey_configure(const event *menu_event)
selected = x;
}
}
else if (m_focus == focused_menu::righttop)
m_focus = focused_menu::rightbottom;
else if (m_focus == focused_menu::rightbottom)
else if (is_focus(focused_menu::righttop))
{
m_focus = focused_menu::main;
set_focus(focused_menu::rightbottom);
}
else if (is_focus(focused_menu::rightbottom))
{
set_focus(focused_menu::main);
if (m_prev_selected == nullptr)
{
selected = 0;
@ -1447,7 +1446,7 @@ float menu_select_software::draw_left_panel(float x1, float y1, float x2, float
hover = phover + filter;
}
if (highlight == filter && m_focus == focused_menu::left)
if (highlight == filter && is_focus(focused_menu::left))
{
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
@ -1488,7 +1487,7 @@ float menu_select_software::draw_left_panel(float x1, float y1, float x2, float
}
ui().draw_text_full(container, str.c_str(), x1t, y1, x2 - x1, JUSTIFY_LEFT, WRAP_NEVER,
DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size);
DRAW_NORMAL, fgcolor, bgcolor, nullptr, nullptr, text_size);
y1 += line_height;
}
@ -1572,7 +1571,7 @@ void menu_select_software::infos_render(void *selectedref, float origx1, float o
rgb_t fgcolor = UI_TEXT_COLOR;
rgb_t bgcolor = UI_TEXT_BG_COLOR;
if (m_focus == focused_menu::rightbottom)
if (is_focus(focused_menu::rightbottom))
{
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
@ -1606,7 +1605,7 @@ void menu_select_software::infos_render(void *selectedref, float origx1, float o
rgb_t fgcolor = UI_TEXT_COLOR;
rgb_t bgcolor = UI_TEXT_BG_COLOR;
if (m_focus == focused_menu::rightbottom)
if (is_focus(focused_menu::rightbottom))
{
fgcolor = rgb_t(0xff, 0xff, 0xff, 0x00);
bgcolor = rgb_t(0xff, 0xff, 0xff, 0xff);
@ -1787,6 +1786,7 @@ void menu_select_software::arts_render(void *selectedref, float origx1, float or
else if (soft != nullptr)
{
std::string fullname, pathname;
if (ui_globals::default_image)
(soft->startempty == 0) ? ui_globals::curimage_view = SNAPSHOT_VIEW : ui_globals::curimage_view = CABINETS_VIEW;

View File

@ -105,29 +105,28 @@ void simple_menu_select_game::handle()
// process the menu
const event *menu_event = process(0);
if (menu_event != nullptr && menu_event->itemref != nullptr)
if (menu_event && menu_event->itemref)
{
// reset the error on any future menu_event
if (m_error)
{
// reset the error on any future menu_event
m_error = false;
machine().ui_input().reset();
}
// handle selections
else
{
// handle selections
switch(menu_event->iptkey)
{
case IPT_UI_SELECT:
inkey_select(menu_event);
break;
case IPT_UI_CANCEL:
inkey_cancel(menu_event);
break;
case IPT_SPECIAL:
inkey_special(menu_event);
break;
case IPT_UI_SELECT:
inkey_select(menu_event);
break;
case IPT_UI_CANCEL:
inkey_cancel(menu_event);
break;
case IPT_SPECIAL:
inkey_special(menu_event);
break;
}
}
}
@ -201,22 +200,23 @@ void simple_menu_select_game::inkey_cancel(const event *menu_event)
void simple_menu_select_game::inkey_special(const event *menu_event)
{
// typed characters append to the buffer
int buflen = strlen(m_search);
auto const buflen = std::strlen(m_search);
// if it's a backspace and we can handle it, do so
if ((menu_event->unichar == 8 || menu_event->unichar == 0x7f) && buflen > 0)
if ((menu_event->unichar == 8) || (menu_event->unichar == 0x7f))
{
*(char *)utf8_previous_char(&m_search[buflen]) = 0;
m_rerandomize = true;
reset(reset_options::SELECT_FIRST);
// if it's a backspace and we can handle it, do so
if (0 < buflen)
{
*const_cast<char *>(utf8_previous_char(&m_search[buflen])) = 0;
m_rerandomize = true;
reset(reset_options::SELECT_FIRST);
}
}
// if it's any other key and we're not maxed out, update
else if (menu_event->unichar >= ' ' && menu_event->unichar < 0x7f)
else if (menu_event->is_char_printable())
{
buflen += utf8_from_uchar(&m_search[buflen], ARRAY_LENGTH(m_search) - buflen, menu_event->unichar);
m_search[buflen] = 0;
reset(reset_options::SELECT_FIRST);
// if it's any other key and we're not maxed out, update
if (menu_event->append_char(m_search, buflen))
reset(reset_options::SELECT_FIRST);
}
}

View File

@ -256,7 +256,7 @@ void menu_software_list::handle()
// process the menu
const event *event = process(0);
if (event != nullptr && event->itemref != nullptr)
if (event && event->itemref)
{
if ((FPTR)event->itemref == 1 && event->iptkey == IPT_UI_SELECT)
{
@ -279,27 +279,29 @@ void menu_software_list::handle()
}
else if (event->iptkey == IPT_SPECIAL)
{
int buflen = strlen(m_filename_buffer);
auto const buflen = std::strlen(m_filename_buffer);
bool update_selected = false;
// if it's a backspace and we can handle it, do so
if ((event->unichar == 8 || event->unichar == 0x7f) && buflen > 0)
if ((event->unichar == 8) || (event->unichar == 0x7f))
{
*(char *)utf8_previous_char(&m_filename_buffer[buflen]) = 0;
update_selected = true;
// if it's a backspace and we can handle it, do so
if (0 < buflen)
{
*const_cast<char *>(utf8_previous_char(&m_filename_buffer[buflen])) = 0;
update_selected = true;
if (ARRAY_LENGTH(m_filename_buffer) > 0)
ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer);
}
}
// if it's any other key and we're not maxed out, update
else if (event->unichar >= ' ' && event->unichar < 0x7f)
else if (event->is_char_printable())
{
buflen += utf8_from_uchar(&m_filename_buffer[buflen], ARRAY_LENGTH(m_filename_buffer) - buflen, event->unichar);
m_filename_buffer[buflen] = 0;
update_selected = true;
// if it's any other key and we're not maxed out, update
if (event->append_char(m_filename_buffer, buflen))
{
update_selected = true;
if (ARRAY_LENGTH(m_filename_buffer) > 0)
ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer);
}
}
if (update_selected)

View File

@ -156,11 +156,23 @@ public:
{
auto window = GET_FOCUS_WINDOW(&event.text);
//printf("Focus window is %p - wl %p\n", window, sdl_window_list);
unicode_char result;
if (window != nullptr)
{
osd_uchar_from_osdchar(&result, sdlevent.text.text, 1);
machine().ui_input().push_char_event(window->target(), result);
auto ptr = sdlevent.text.text;
auto len = std::strlen(sdlevent.text.text);
while (len)
{
unicode_char ch;
auto chlen = uchar_from_utf8(&ch, ptr, len);
if (0 > chlen)
{
ch = 0x0fffd;
chlen = 1;
}
ptr += chlen;
len -= chlen;
machine().ui_input().push_char_event(window->target(), ch);
}
}
}
break;

View File

@ -11,8 +11,8 @@
#pragma once
#ifndef __OSDCOMM_H__
#define __OSDCOMM_H__
#ifndef MAME_OSD_OSDCOMM_H
#define MAME_OSD_OSDCOMM_H
#include <stdio.h>
#include <string.h>
@ -128,8 +128,8 @@ using FPTR = uintptr_t;
#define EXTRACT_64HI(val) ((UINT32)((val) >> 32))
#define EXTRACT_64LO(val) ((UINT32)(val))
/* Highly useful macro for compile-time knowledge of an array size */
#define ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
// Highly useful template for compile-time knowledge of an array size
template <typename T, size_t N> constexpr inline std::size_t ARRAY_LENGTH(T (&)[N]) { return N;}
/* Macros for normalizing data into big or little endian formats */
@ -184,4 +184,4 @@ typedef ptrdiff_t ssize_t;
#endif
#endif
#endif /* __OSDCOMM_H__ */
#endif /* MAME_OSD_OSDCOMM_H */