diff --git a/src/frontend/mame/ui/filesel.cpp b/src/frontend/mame/ui/filesel.cpp index deaef81c3d0..87429ac7218 100644 --- a/src/frontend/mame/ui/filesel.cpp +++ b/src/frontend/mame/ui/filesel.cpp @@ -53,24 +53,25 @@ namespace ui { // into a buffer //------------------------------------------------- -template -static void input_character(char (&buffer)[N], unicode_char unichar, F &&filter) +template +static void input_character(std::string &buffer, unicode_char unichar, F &&filter) { - auto buflen = std::strlen(buffer); + auto buflen = buffer.size(); if ((unichar == 8) || (unichar == 0x7f)) { + // backspace if (0 < buflen) - *const_cast(utf8_previous_char(&buffer[buflen])) = 0; + { + auto buffer_oldend = buffer.c_str() + buflen; + auto buffer_newend = utf8_previous_char(buffer_oldend); + buffer.resize(buffer_newend - buffer.c_str()); + } } else if ((unichar >= ' ') && (!filter || filter(unichar))) { - auto const chlen = utf8_from_uchar(&buffer[buflen], N - buflen - 1, unichar); - if (0 <= chlen) - { - buflen += chlen; - buffer[buflen] = 0; - } + // append this character + buffer += utf8_from_uchar(unichar); } } @@ -175,7 +176,11 @@ menu_file_create::menu_file_create(mame_ui_manager &mui, render_container *conta m_ok = ok; *m_ok = true; auto const sep = current_file.rfind(PATH_SEPARATOR); - std::strncpy(m_filename_buffer, current_file.c_str() + ((std::string::npos == sep) ? 0 : (sep + 1)), sizeof(m_filename_buffer)); + + m_filename.reserve(1024); + m_filename = sep != std::string::npos + ? current_file.substr(sep + strlen(PATH_SEPARATOR), current_file.size() - sep - strlen(PATH_SEPARATOR)) + : current_file; } @@ -208,19 +213,19 @@ void menu_file_create::populate() { std::string buffer; const image_device_format *format; - const char *new_image_name; + const std::string *new_image_name; // append the "New Image Name" item if (get_selection() == ITEMREF_NEW_IMAGE_NAME) { - buffer.append(m_filename_buffer).append("_"); - new_image_name = buffer.c_str(); + buffer = m_filename + "_"; + new_image_name = &buffer; } else { - new_image_name = m_filename_buffer; + new_image_name = &m_filename; } - item_append(_("New Image Name:"), new_image_name, 0, ITEMREF_NEW_IMAGE_NAME); + item_append(_("New Image Name:"), *new_image_name, 0, ITEMREF_NEW_IMAGE_NAME); // do we support multiple formats? if (ENABLE_FORMATS) format = m_image->formatlist().front().get(); @@ -256,10 +261,10 @@ void menu_file_create::handle() case IPT_UI_SELECT: if ((event->itemref == ITEMREF_CREATE) || (event->itemref == ITEMREF_NEW_IMAGE_NAME)) { - std::string tmp_file(m_filename_buffer); + std::string tmp_file(m_filename); if (tmp_file.find(".") != -1 && tmp_file.find(".") < tmp_file.length() - 1) { - m_current_file = m_filename_buffer; + m_current_file = m_filename; menu::stack_pop(machine()); } else @@ -270,7 +275,7 @@ void menu_file_create::handle() case IPT_SPECIAL: if (get_selection() == ITEMREF_NEW_IMAGE_NAME) { - input_character(m_filename_buffer,event->unichar, &is_valid_filename_char); + input_character(m_filename, event->unichar, &is_valid_filename_char); reset(reset_options::REMEMBER_POSITION); } break; @@ -340,7 +345,7 @@ void menu_file_selector::custom_render(void *selectedref, float top, float botto // we're hovering over a directory! highlight it auto target_dir_start = m_current_directory.rfind(PATH_SEPARATOR, hit_start) + 1; auto target_dir_end = m_current_directory.find(PATH_SEPARATOR, hit_start + hit_span); - m_hover_directory = m_current_directory.substr(0, target_dir_end); + m_hover_directory = m_current_directory.substr(0, target_dir_end + strlen(PATH_SEPARATOR)); // highlight the text in question rgb_t fgcolor = UI_MOUSEOVER_COLOR; @@ -674,34 +679,33 @@ void menu_file_selector::handle() } // reset the char buffer when pressing IPT_UI_SELECT - if (m_filename_buffer[0] != '\0') - memset(m_filename_buffer, '\0', ARRAY_LENGTH(m_filename_buffer)); + m_filename.clear(); } else if (event->iptkey == IPT_SPECIAL) { - auto const buflen = std::strlen(m_filename_buffer); - bool update_selected = FALSE; + bool update_selected = false; if ((event->unichar == 8) || (event->unichar == 0x7f)) { // if it's a backspace and we can handle it, do so + auto const buflen = m_filename.size(); if (0 < buflen) { - *const_cast(utf8_previous_char(&m_filename_buffer[buflen])) = 0; - update_selected = TRUE; + auto buffer_oldend = m_filename.c_str() + buflen; + auto buffer_newend = utf8_previous_char(buffer_oldend); + m_filename.resize(buffer_newend - m_filename.c_str()); + update_selected = true; - ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer); + ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename.c_str()); } } else if (event->is_char_printable()) { // if it's any other key and we're not maxed out, update - if (event->append_char(m_filename_buffer, buflen)) - { - update_selected = TRUE; + m_filename += utf8_from_uchar(event->unichar); + update_selected = true; - ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename_buffer); - } + ui().popup_time(ERROR_MESSAGE_TIME, "%s", m_filename.c_str()); } if (update_selected) @@ -714,9 +718,9 @@ void menu_file_selector::handle() if (cur_selected != &entry) { int match = 0; - for (int i = 0; i < ARRAY_LENGTH(m_filename_buffer); i++) + for (int i = 0; i < m_filename.size(); i++) { - if (core_strnicmp(entry.basename.c_str(), m_filename_buffer, i) == 0) + if (core_strnicmp(entry.basename.c_str(), m_filename.c_str(), i) == 0) match = i; } @@ -738,8 +742,7 @@ void menu_file_selector::handle() else if (event->iptkey == IPT_UI_CANCEL) { // reset the char buffer also in this case - if (m_filename_buffer[0] != '\0') - memset(m_filename_buffer, '\0', ARRAY_LENGTH(m_filename_buffer)); + m_filename.clear(); } } } diff --git a/src/frontend/mame/ui/filesel.h b/src/frontend/mame/ui/filesel.h index 2960c6a6b5b..c18af7fecba 100644 --- a/src/frontend/mame/ui/filesel.h +++ b/src/frontend/mame/ui/filesel.h @@ -49,7 +49,7 @@ private: std::string & m_current_directory; std::string & m_current_file; const image_device_format * m_current_format; - char m_filename_buffer[1024]; + std::string m_filename; protected: bool * m_ok; @@ -99,7 +99,7 @@ private: int * m_result; std::vector m_entrylist; std::string m_hover_directory; - char m_filename_buffer[1024]; + std::string m_filename; // methods int compare_entries(const file_selector_entry *e1, const file_selector_entry *e2); diff --git a/src/lib/util/unicode.cpp b/src/lib/util/unicode.cpp index e2c3956cedb..0390576ae9a 100644 --- a/src/lib/util/unicode.cpp +++ b/src/lib/util/unicode.cpp @@ -11,21 +11,21 @@ #include "unicode.h" -/*------------------------------------------------- - uchar_isvalid - return true if a given - character is a legitimate unicode character --------------------------------------------------*/ +//------------------------------------------------- +// uchar_isvalid - return true if a given +// character is a legitimate unicode character +//------------------------------------------------- -int uchar_isvalid(unicode_char uchar) +bool uchar_isvalid(unicode_char uchar) { return (uchar < 0x110000) && !((uchar >= 0xd800) && (uchar <= 0xdfff)); } -/*------------------------------------------------- - uchar_from_utf8 - convert a UTF-8 sequence - into a unicode character --------------------------------------------------*/ +//------------------------------------------------- +// uchar_from_utf8 - convert a UTF-8 sequence +// into a unicode character +//----------------------------------------------- int uchar_from_utf8(unicode_char *uchar, const char *utf8char, size_t count) { @@ -33,74 +33,74 @@ int uchar_from_utf8(unicode_char *uchar, const char *utf8char, size_t count) int auxlen, i; char auxchar; - /* validate parameters */ + // validate parameters if (utf8char == nullptr || count == 0) return 0; - /* start with the first byte */ + // start with the first byte c = (unsigned char) *utf8char; count--; utf8char++; - /* based on that, determine how many additional bytes we need */ + // based on that, determine how many additional bytes we need if (c < 0x80) { - /* unicode char 0x00000000 - 0x0000007F */ + // unicode char 0x00000000 - 0x0000007F c &= 0x7f; auxlen = 0; minchar = 0x00000000; } else if (c >= 0xc0 && c < 0xe0) { - /* unicode char 0x00000080 - 0x000007FF */ + // unicode char 0x00000080 - 0x000007FF c &= 0x1f; auxlen = 1; minchar = 0x00000080; } else if (c >= 0xe0 && c < 0xf0) { - /* unicode char 0x00000800 - 0x0000FFFF */ + // unicode char 0x00000800 - 0x0000FFFF c &= 0x0f; auxlen = 2; minchar = 0x00000800; } else if (c >= 0xf0 && c < 0xf8) { - /* unicode char 0x00010000 - 0x001FFFFF */ + // unicode char 0x00010000 - 0x001FFFFF c &= 0x07; auxlen = 3; minchar = 0x00010000; } else if (c >= 0xf8 && c < 0xfc) { - /* unicode char 0x00200000 - 0x03FFFFFF */ + // unicode char 0x00200000 - 0x03FFFFFF c &= 0x03; auxlen = 4; minchar = 0x00200000; } else if (c >= 0xfc && c < 0xfe) { - /* unicode char 0x04000000 - 0x7FFFFFFF */ + // unicode char 0x04000000 - 0x7FFFFFFF c &= 0x01; auxlen = 5; minchar = 0x04000000; } else { - /* invalid */ + // invalid return -1; } - /* exceeds the count? */ + // exceeds the count? if (auxlen > count) return -1; - /* we now know how long the char is, now compute it */ + // we now know how long the char is, now compute it for (i = 0; i < auxlen; i++) { auxchar = utf8char[i]; - /* all auxillary chars must be between 0x80-0xbf */ + // all auxillary chars must be between 0x80-0xbf if ((auxchar & 0xc0) != 0x80) return -1; @@ -108,7 +108,7 @@ int uchar_from_utf8(unicode_char *uchar, const char *utf8char, size_t count) c |= auxchar & 0x3f; } - /* make sure that this char is above the minimum */ + // make sure that this char is above the minimum if (c < minchar) return -1; @@ -117,20 +117,20 @@ int uchar_from_utf8(unicode_char *uchar, const char *utf8char, size_t count) } -/*------------------------------------------------- - uchar_from_utf16 - convert a UTF-16 sequence - into a unicode character --------------------------------------------------*/ +//------------------------------------------------- +// uchar_from_utf16 - convert a UTF-16 sequence +// into a unicode character +//------------------------------------------------- int uchar_from_utf16(unicode_char *uchar, const utf16_char *utf16char, size_t count) { int rc = -1; - /* validate parameters */ + // validate parameters if (utf16char == nullptr || count == 0) return 0; - /* handle the two-byte case */ + // handle the two-byte case if (utf16char[0] >= 0xd800 && utf16char[0] <= 0xdbff) { if (count > 1 && utf16char[1] >= 0xdc00 && utf16char[1] <= 0xdfff) @@ -140,7 +140,7 @@ int uchar_from_utf16(unicode_char *uchar, const utf16_char *utf16char, size_t co } } - /* handle the one-byte case */ + // handle the one-byte case else if (utf16char[0] < 0xdc00 || utf16char[0] > 0xdfff) { *uchar = utf16char[0]; @@ -151,11 +151,11 @@ int uchar_from_utf16(unicode_char *uchar, const utf16_char *utf16char, size_t co } -/*------------------------------------------------- - uchar_from_utf16f - convert a UTF-16 sequence - into a unicode character from a flipped - byte order --------------------------------------------------*/ +//------------------------------------------------- +// uchar_from_utf16f - convert a UTF-16 sequence +// into a unicode character from a flipped +// byte order +//------------------------------------------------- int uchar_from_utf16f(unicode_char *uchar, const utf16_char *utf16char, size_t count) { @@ -168,30 +168,30 @@ int uchar_from_utf16f(unicode_char *uchar, const utf16_char *utf16char, size_t c } -/*------------------------------------------------- - utf8_from_uchar - convert a unicode character - into a UTF-8 sequence --------------------------------------------------*/ +//------------------------------------------------- +// utf8_from_uchar - convert a unicode character +// into a UTF-8 sequence +//------------------------------------------------- int utf8_from_uchar(char *utf8string, size_t count, unicode_char uchar) { int rc = 0; - /* error on invalid characters */ + // error on invalid characters if (!uchar_isvalid(uchar)) return -1; - /* based on the value, output the appropriate number of bytes */ + // based on the value, output the appropriate number of bytes if (uchar < 0x80) { - /* unicode char 0x00000000 - 0x0000007F */ + // unicode char 0x00000000 - 0x0000007F if (count < 1) return -1; utf8string[rc++] = (char) uchar; } else if (uchar < 0x800) { - /* unicode char 0x00000080 - 0x000007FF */ + // unicode char 0x00000080 - 0x000007FF if (count < 2) return -1; utf8string[rc++] = ((char) (uchar >> 6)) | 0xC0; @@ -199,7 +199,7 @@ int utf8_from_uchar(char *utf8string, size_t count, unicode_char uchar) } else if (uchar < 0x10000) { - /* unicode char 0x00000800 - 0x0000FFFF */ + // unicode char 0x00000800 - 0x0000FFFF if (count < 3) return -1; utf8string[rc++] = ((char) (uchar >> 12)) | 0xE0; @@ -208,7 +208,7 @@ int utf8_from_uchar(char *utf8string, size_t count, unicode_char uchar) } else if (uchar < 0x00200000) { - /* unicode char 0x00010000 - 0x001FFFFF */ + // unicode char 0x00010000 - 0x001FFFFF if (count < 4) return -1; utf8string[rc++] = ((char) (uchar >> 18)) | 0xF0; @@ -218,7 +218,7 @@ int utf8_from_uchar(char *utf8string, size_t count, unicode_char uchar) } else if (uchar < 0x04000000) { - /* unicode char 0x00200000 - 0x03FFFFFF */ + // unicode char 0x00200000 - 0x03FFFFFF if (count < 5) return -1; utf8string[rc++] = ((char) (uchar >> 24)) | 0xF8; @@ -229,7 +229,7 @@ int utf8_from_uchar(char *utf8string, size_t count, unicode_char uchar) } else if (uchar < 0x80000000) { - /* unicode char 0x04000000 - 0x7FFFFFFF */ + // unicode char 0x04000000 - 0x7FFFFFFF if (count < 6) return -1; utf8string[rc++] = ((char) (uchar >> 30)) | 0xFC; @@ -246,20 +246,33 @@ int utf8_from_uchar(char *utf8string, size_t count, unicode_char uchar) } -/*------------------------------------------------- - utf16_from_uchar - convert a unicode character - into a UTF-16 sequence --------------------------------------------------*/ +//------------------------------------------------- +// utf8_from_uchar - convert a unicode character +// into a UTF-8 sequence +//------------------------------------------------- + +std::string utf8_from_uchar(unicode_char uchar) +{ + char buffer[UTF8_CHAR_MAX]; + auto len = utf8_from_uchar(buffer, ARRAY_LENGTH(buffer), uchar); + return std::string(buffer, len); +} + + +//------------------------------------------------- +// utf16_from_uchar - convert a unicode character +// into a UTF-16 sequence +//------------------------------------------------- int utf16_from_uchar(utf16_char *utf16string, size_t count, unicode_char uchar) { int rc; - /* error on invalid characters */ + // error on invalid characters if (!uchar_isvalid(uchar)) return -1; - /* single word case */ + // single word case if (uchar < 0x10000) { if (count < 1) @@ -268,7 +281,7 @@ int utf16_from_uchar(utf16_char *utf16string, size_t count, unicode_char uchar) rc = 1; } - /* double word case */ + // double word case else if (uchar < 0x100000) { if (count < 2) @@ -283,10 +296,10 @@ int utf16_from_uchar(utf16_char *utf16string, size_t count, unicode_char uchar) } -/*------------------------------------------------- - utf16_from_uchar - convert a unicode character - into a UTF-16 sequence with flipped endianness --------------------------------------------------*/ +//------------------------------------------------- +// utf16_from_uchar - convert a unicode character +// into a UTF-16 sequence with flipped endianness +//------------------------------------------------- int utf16f_from_uchar(utf16_char *utf16string, size_t count, unicode_char uchar) { @@ -303,10 +316,10 @@ int utf16f_from_uchar(utf16_char *utf16string, size_t count, unicode_char uchar) } -/*------------------------------------------------- - utf8_previous_char - return a pointer to the - previous character in a string --------------------------------------------------*/ +//------------------------------------------------- +// utf8_previous_char - return a pointer to the +// previous character in a string +//------------------------------------------------- /** * @fn const char *utf8_previous_char(const char *utf8string) @@ -326,11 +339,11 @@ const char *utf8_previous_char(const char *utf8string) } -/*------------------------------------------------- - utf8_is_valid_string - return true if the - given string is a properly formed sequence of - UTF-8 characters --------------------------------------------------*/ +//------------------------------------------------- +// utf8_is_valid_string - return true if the +// given string is a properly formed sequence of +// UTF-8 characters +//------------------------------------------------- /** * @fn int utf8_is_valid_string(const char *utf8string) @@ -342,7 +355,7 @@ const char *utf8_previous_char(const char *utf8string) * @return An int. */ -int utf8_is_valid_string(const char *utf8string) +bool utf8_is_valid_string(const char *utf8string) { int remaining_length = strlen(utf8string); @@ -351,15 +364,15 @@ int utf8_is_valid_string(const char *utf8string) unicode_char uchar = 0; int charlen; - /* extract the current character and verify it */ + // extract the current character and verify it charlen = uchar_from_utf8(&uchar, utf8string, remaining_length); if (charlen <= 0 || uchar == 0 || !uchar_isvalid(uchar)) - return FALSE; + return false; - /* advance */ + // advance utf8string += charlen; remaining_length -= charlen; } - return TRUE; + return true; } diff --git a/src/lib/util/unicode.h b/src/lib/util/unicode.h index b062b1a0702..579ce53e665 100644 --- a/src/lib/util/unicode.h +++ b/src/lib/util/unicode.h @@ -29,12 +29,12 @@ CONSTANTS ***************************************************************************/ -/* these defines specify the maximum size of different types of Unicode - * character encodings */ +// these defines specify the maximum size of different types of Unicode +// character encodings #define UTF8_CHAR_MAX 6 #define UTF16_CHAR_MAX 2 -/* these are UTF-8 encoded strings for common characters */ +// these are UTF-8 encoded strings for common characters #define UTF8_NBSP "\xc2\xa0" /* non-breaking space */ #define UTF8_MULTIPLY "\xc3\x97" /* multiplication sign */ @@ -87,22 +87,23 @@ typedef UINT32 unicode_char; FUNCTION PROTOTYPES ***************************************************************************/ -/* tests to see if a unicode char is a valid code point */ -int uchar_isvalid(unicode_char uchar); +// tests to see if a unicode char is a valid code point +bool uchar_isvalid(unicode_char uchar); -/* converting strings to 32-bit Unicode chars */ +// converting strings to 32-bit Unicode chars int uchar_from_utf8(unicode_char *uchar, const char *utf8char, size_t count); int uchar_from_utf16(unicode_char *uchar, const utf16_char *utf16char, size_t count); int uchar_from_utf16f(unicode_char *uchar, const utf16_char *utf16char, size_t count); -/* converting 32-bit Unicode chars to strings */ +// converting 32-bit Unicode chars to strings int utf8_from_uchar(char *utf8string, size_t count, unicode_char uchar); +std::string utf8_from_uchar(unicode_char uchar); int utf16_from_uchar(utf16_char *utf16string, size_t count, unicode_char uchar); int utf16f_from_uchar(utf16_char *utf16string, size_t count, unicode_char uchar); -/* misc UTF-8 helpers */ +// misc UTF-8 helpers const char *utf8_previous_char(const char *utf8string); -int utf8_is_valid_string(const char *utf8string); +bool utf8_is_valid_string(const char *utf8string);