diff options
author | 2022-09-02 08:55:16 +1000 | |
---|---|---|
committer | 2022-09-02 08:55:16 +1000 | |
commit | 051c380fd14040c83a0d5b919e6289e70fef9df8 (patch) | |
tree | e247a309f4d1c66c07803c02d67ac89837211bd1 /src/osd/modules | |
parent | 67f129e31518a50a801413f732991972d2c3538a (diff) |
Patched up some gaps in functionality and fixed some bugs.
ui: Added some missing functionality:
* Added an option to copy input device IDs to the relevant menus.
* Added an item for setting the software lists files path (-hashpath) to
the folder setup menu.
* Allow pasting text from clipboard in most places that allow typing
(searching, entering filenames, entering barcodes).
* Changed the software selection menu heading to be a bit less
misleading.
* Made barcode menu less eager to rebuild itself unnecessarily, and
removed some confusing and apparently pointless code.
Exposed more Lua bindings:
* Added low-level palette objects.
* Added indexed bitmap types.
* Added a bitmap method for extracting pixels from a rectangular area as a
packed binary string.
* Changed screen device pixels method to return width and height in
addition to the pixels.
osd: Added some functionality and cleaned up a little:
* Added a function for copying text to the clipboard.
* Moved function for converting Windows error codes to standard error
conditions to winutil.cpp so it can be used from more places.
* Removed duplicate declaration of osd_get_clipboard_text and made the
function noexcept (including fixing implementations).
* Made macOS implementation of osd_get_clipboard_text skip the encoding
conversion if it finds UTF-8 text first.
* Changed the default -uimodekey setting so it doesn't lose the "not
shift" that stops the default from interfering with UI paste.
Various bug fixes:
* util/unicode.cpp: Fixed the version of utf8_from_uchar that returns
std::string blowing up on invalid codepoints.
* util/bitmap.h: Fixed wrapping constructors for indexed bitmaps taking
the wrong parameter type (nothing was using them before).
* util/bitmap.cpp: Fixed potential use-after-free issues with bitmap
palettes.
* emu/input.cpp, emu/inputdev.cpp: Log 1-based device numbers, matching
what's shown in the internal UI and used in tokens in CFG files.
* emu/emumem.cpp: Added the bank tag to a fatal error message where it
was missing.
docs: Reworked and expanded documentation on configuring stable
controller IDs.
For translators, the changes are quite minor:
* There's a menu item for copying a device ID to the clipboard, and
associated success/failure messages.
* There's the menu item for setting the software list file search path.
* One of the lines in the software selection menu heading has changes as
it could be interpreted as implying it showed a software list name.
Diffstat (limited to 'src/osd/modules')
-rw-r--r-- | src/osd/modules/file/winfile.cpp | 88 | ||||
-rw-r--r-- | src/osd/modules/file/winfile.h | 2 | ||||
-rw-r--r-- | src/osd/modules/file/winptty.cpp | 10 | ||||
-rw-r--r-- | src/osd/modules/font/font_dwrite.cpp | 14 | ||||
-rw-r--r-- | src/osd/modules/input/input_sdlcommon.cpp | 34 | ||||
-rw-r--r-- | src/osd/modules/input/input_windows.cpp | 20 | ||||
-rw-r--r-- | src/osd/modules/lib/osdlib.h | 30 | ||||
-rw-r--r-- | src/osd/modules/lib/osdlib_macosx.cpp | 83 | ||||
-rw-r--r-- | src/osd/modules/lib/osdlib_unix.cpp | 48 | ||||
-rw-r--r-- | src/osd/modules/lib/osdlib_win32.cpp | 81 | ||||
-rw-r--r-- | src/osd/modules/lib/osdobj_common.cpp | 2 |
11 files changed, 262 insertions, 150 deletions
diff --git a/src/osd/modules/file/winfile.cpp b/src/osd/modules/file/winfile.cpp index 199537bbdee..173021121f1 100644 --- a/src/osd/modules/file/winfile.cpp +++ b/src/osd/modules/file/winfile.cpp @@ -62,12 +62,12 @@ public: LARGE_INTEGER largeOffset; largeOffset.QuadPart = offset; if (!SetFilePointerEx(m_handle, largeOffset, nullptr, FILE_BEGIN)) - return win_error_to_file_error(GetLastError()); + return win_error_to_error_condition(GetLastError()); // then perform the read DWORD result = 0; if (!ReadFile(m_handle, buffer, length, &result, nullptr)) - return win_error_to_file_error(GetLastError()); + return win_error_to_error_condition(GetLastError()); actual = result; return std::error_condition(); @@ -79,12 +79,12 @@ public: LARGE_INTEGER largeOffset; largeOffset.QuadPart = offset; if (!SetFilePointerEx(m_handle, largeOffset, nullptr, FILE_BEGIN)) - return win_error_to_file_error(GetLastError()); + return win_error_to_error_condition(GetLastError()); // then perform the write DWORD result = 0; if (!WriteFile(m_handle, buffer, length, &result, nullptr)) - return win_error_to_file_error(GetLastError()); + return win_error_to_error_condition(GetLastError()); actual = result; return std::error_condition(); @@ -96,11 +96,11 @@ public: LARGE_INTEGER largeOffset; largeOffset.QuadPart = offset; if (!SetFilePointerEx(m_handle, largeOffset, nullptr, FILE_BEGIN)) - return win_error_to_file_error(GetLastError()); + return win_error_to_error_condition(GetLastError()); // then perform the truncation if (!SetEndOfFile(m_handle)) - return win_error_to_file_error(GetLastError()); + return win_error_to_error_condition(GetLastError()); else return std::error_condition(); } @@ -229,7 +229,7 @@ std::error_condition osd_file::open(std::string const &orig_path, uint32_t openf // if we still failed, clean up and free if (INVALID_HANDLE_VALUE == h) - return win_error_to_file_error(err); + return win_error_to_error_condition(err); } // get the file size @@ -259,7 +259,7 @@ std::error_condition osd_file::open(std::string const &orig_path, uint32_t openf if (NO_ERROR != err) { CloseHandle(h); - return win_error_to_file_error(err); + return win_error_to_error_condition(err); } } @@ -299,7 +299,7 @@ std::error_condition osd_file::remove(std::string const &filename) noexcept std::error_condition filerr; if (!DeleteFile(tempstr.c_str())) - filerr = win_error_to_file_error(GetLastError()); + filerr = win_error_to_error_condition(GetLastError()); return filerr; } @@ -415,12 +415,12 @@ std::error_condition osd_get_full_path(std::string &dst, std::string const &path std::wstring const w_path(osd::text::to_wstring(path)); DWORD const length(GetFullPathNameW(w_path.c_str(), 0, nullptr, nullptr)); if (!length) - return win_error_to_file_error(GetLastError()); + return win_error_to_error_condition(GetLastError()); // allocate a buffer and get the canonical path std::unique_ptr<wchar_t []> buffer(std::make_unique<wchar_t []>(length)); if (!GetFullPathNameW(w_path.c_str(), length, buffer.get(), nullptr)) - return win_error_to_file_error(GetLastError()); + return win_error_to_error_condition(GetLastError()); // convert the result back to UTF-8 osd::text::from_wstring(dst, buffer.get()); @@ -534,69 +534,3 @@ bool osd_is_valid_filepath_char(char32_t uchar) noexcept && !(uchar >= '\x7F' && uchar <= '\x9F') && uchar_isvalid(uchar); } - - - -//============================================================ -// win_error_to_file_error -//============================================================ - -std::error_condition win_error_to_file_error(DWORD error) noexcept -{ - // TODO: work out if there's a better way to do this - switch (error) - { - case ERROR_SUCCESS: - return std::error_condition(); - - case ERROR_INVALID_HANDLE: - return std::errc::bad_file_descriptor; - - case ERROR_OUTOFMEMORY: - return std::errc::not_enough_memory; - - case ERROR_NOT_SUPPORTED: - return std::errc::not_supported; - - case ERROR_FILE_NOT_FOUND: - case ERROR_PATH_NOT_FOUND: - case ERROR_INVALID_NAME: - return std::errc::no_such_file_or_directory; - - case ERROR_FILENAME_EXCED_RANGE: - return std::errc::filename_too_long; - - case ERROR_ACCESS_DENIED: - case ERROR_SHARING_VIOLATION: - return std::errc::permission_denied; - - case ERROR_ALREADY_EXISTS: - return std::errc::file_exists; - - case ERROR_TOO_MANY_OPEN_FILES: - return std::errc::too_many_files_open; - - case ERROR_WRITE_FAULT: - case ERROR_READ_FAULT: - return std::errc::io_error; - - case ERROR_HANDLE_DISK_FULL: - case ERROR_DISK_FULL: - return std::errc::no_space_on_device; - - case ERROR_PATH_BUSY: - case ERROR_BUSY: - return std::errc::device_or_resource_busy; - - case ERROR_FILE_TOO_LARGE: - return std::errc::file_too_large; - - case ERROR_INVALID_ACCESS: - case ERROR_NEGATIVE_SEEK: - case ERROR_BAD_ARGUMENTS: - return std::errc::invalid_argument; - - default: - return std::error_condition(error, std::system_category()); - } -} diff --git a/src/osd/modules/file/winfile.h b/src/osd/modules/file/winfile.h index 83f0814733d..90cf6e69a60 100644 --- a/src/osd/modules/file/winfile.h +++ b/src/osd/modules/file/winfile.h @@ -32,6 +32,4 @@ std::error_condition win_open_socket(std::string const &path, std::uint32_t open bool win_check_ptty_path(std::string const &path) noexcept; std::error_condition win_open_ptty(std::string const &path, std::uint32_t openflags, osd_file::ptr &file, std::uint64_t &filesize) noexcept; -std::error_condition win_error_to_file_error(DWORD error) noexcept; - #endif // MAME_OSD_MODULES_FILE_WINFILE_H diff --git a/src/osd/modules/file/winptty.cpp b/src/osd/modules/file/winptty.cpp index 7feeacce137..9aac0c5a990 100644 --- a/src/osd/modules/file/winptty.cpp +++ b/src/osd/modules/file/winptty.cpp @@ -8,11 +8,11 @@ #include "winutil.h" #include <cassert> - -#include <windows.h> #include <cstdlib> #include <cstring> +#include <windows.h> + namespace { @@ -44,7 +44,7 @@ public: { DWORD bytes_read; if (!ReadFile(m_handle, buffer, count, &bytes_read, nullptr)) - return win_error_to_file_error(GetLastError()); + return win_error_to_error_condition(GetLastError()); actual = bytes_read; return std::error_condition(); @@ -54,7 +54,7 @@ public: { DWORD bytes_written; if (!WriteFile(m_handle, buffer, count, &bytes_written, nullptr)) - return win_error_to_file_error(GetLastError()); + return win_error_to_error_condition(GetLastError()); actual = bytes_written; return std::error_condition(); @@ -99,7 +99,7 @@ std::error_condition win_open_ptty(std::string const &path, std::uint32_t openfl if (openflags & OPEN_FLAG_CREATE) pipe = CreateNamedPipe(t_name.c_str(), PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_NOWAIT, 1, 32, 32, 0, nullptr); if (INVALID_HANDLE_VALUE == pipe) - return win_error_to_file_error(GetLastError()); + return win_error_to_error_condition(GetLastError()); } else { diff --git a/src/osd/modules/font/font_dwrite.cpp b/src/osd/modules/font/font_dwrite.cpp index 70edc24c0f1..47a52dbd197 100644 --- a/src/osd/modules/font/font_dwrite.cpp +++ b/src/osd/modules/font/font_dwrite.cpp @@ -11,12 +11,19 @@ #if defined(OSD_WINDOWS) -#include <windows.h> +#include "corestr.h" + +#include "winutil.h" + +#include "osdcore.h" +#include "strconv.h" #include <cmath> #include <memory> #include <stdexcept> +#include <windows.h> + // Windows Imaging Components #include <wincodec.h> @@ -34,11 +41,6 @@ DEFINE_GUID(GUID_WICPixelFormat8bppAlpha, 0xe6cd0116, 0xeeba, 0x4161, 0xaa, 0x85 #include <wrl/client.h> #undef interface -#include "strconv.h" -#include "corestr.h" -#include "winutil.h" -#include "osdcore.h" - using namespace Microsoft::WRL; //------------------------------------------------- diff --git a/src/osd/modules/input/input_sdlcommon.cpp b/src/osd/modules/input/input_sdlcommon.cpp index 659add8dc79..f0d8a8632f6 100644 --- a/src/osd/modules/input/input_sdlcommon.cpp +++ b/src/osd/modules/input/input_sdlcommon.cpp @@ -139,11 +139,6 @@ void sdl_event_manager::process_window_event(running_machine &machine, SDL_Event void sdl_osd_interface::customize_input_type_list(std::vector<input_type_entry> &typelist) { - input_item_id mameid_code; - input_code ui_code; - const char* uimode; - char fullmode[64]; - // loop over the defaults for (input_type_entry &entry : typelist) { @@ -151,22 +146,27 @@ void sdl_osd_interface::customize_input_type_list(std::vector<input_type_entry> { // configurable UI mode switch case IPT_UI_TOGGLE_UI: - uimode = options().ui_mode_key(); - if (!strcmp(uimode, "auto")) { + char const *const uimode = options().ui_mode_key(); + input_item_id mameid_code = ITEM_ID_INVALID; + if (!uimode || !*uimode || !strcmp(uimode, "auto")) + { #if defined(__APPLE__) && defined(__MACH__) - mameid_code = keyboard_trans_table::instance().lookup_mame_code("ITEM_ID_INSERT"); -#else - mameid_code = keyboard_trans_table::instance().lookup_mame_code("ITEM_ID_SCRLOCK"); + mameid_code = keyboard_trans_table::instance().lookup_mame_code("ITEM_ID_INSERT"); #endif + } + else + { + std::string fullmode("ITEM_ID_"); + fullmode.append(uimode); + mameid_code = keyboard_trans_table::instance().lookup_mame_code(fullmode.c_str()); + } + if (ITEM_ID_INVALID != mameid_code) + { + input_code const ui_code = input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(mameid_code)); + entry.defseq(SEQ_TYPE_STANDARD).set(ui_code); + } } - else - { - snprintf(fullmode, 63, "ITEM_ID_%s", uimode); - mameid_code = keyboard_trans_table::instance().lookup_mame_code(fullmode); - } - ui_code = input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(mameid_code)); - entry.defseq(SEQ_TYPE_STANDARD).set(ui_code); break; // alt-enter for fullscreen case IPT_OSD_1: diff --git a/src/osd/modules/input/input_windows.cpp b/src/osd/modules/input/input_windows.cpp index 60306765f72..3b3765ce19e 100644 --- a/src/osd/modules/input/input_windows.cpp +++ b/src/osd/modules/input/input_windows.cpp @@ -78,8 +78,6 @@ void windows_osd_interface::poll_input(running_machine &machine) const void windows_osd_interface::customize_input_type_list(std::vector<input_type_entry> &typelist) { - const char* uimode; - // loop over the defaults for (input_type_entry &entry : typelist) switch (entry.type()) @@ -91,16 +89,18 @@ void windows_osd_interface::customize_input_type_list(std::vector<input_type_ent break; // configurable UI mode switch case IPT_UI_TOGGLE_UI: - uimode = options().ui_mode_key(); - if (strcmp(uimode, "auto")) { - std::string fullmode = "ITEM_ID_"; - fullmode += uimode; - input_item_id const mameid_code = keyboard_trans_table::instance().lookup_mame_code(fullmode.c_str()); - if (ITEM_ID_INVALID != mameid_code) + char const *const uimode = options().ui_mode_key(); + if (uimode && *uimode && strcmp(uimode, "auto")) { - input_code const ui_code = input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(mameid_code)); - entry.defseq(SEQ_TYPE_STANDARD).set(ui_code); + std::string fullmode("ITEM_ID_"); + fullmode.append(uimode); + input_item_id const mameid_code = keyboard_trans_table::instance().lookup_mame_code(fullmode.c_str()); + if (ITEM_ID_INVALID != mameid_code) + { + input_code const ui_code = input_code(DEVICE_CLASS_KEYBOARD, 0, ITEM_CLASS_SWITCH, ITEM_MODIFIER_NONE, input_item_id(mameid_code)); + entry.defseq(SEQ_TYPE_STANDARD).set(ui_code); + } } } break; diff --git a/src/osd/modules/lib/osdlib.h b/src/osd/modules/lib/osdlib.h index 8ca4762a111..c84901002ad 100644 --- a/src/osd/modules/lib/osdlib.h +++ b/src/osd/modules/lib/osdlib.h @@ -12,16 +12,20 @@ // - osd_ticks // - osd_sleep //============================================================ +#ifndef MAME_OSD_LIB_OSDLIB_H +#define MAME_OSD_LIB_OSDLIB_H -#ifndef __OSDLIB__ -#define __OSDLIB__ +#pragma once #include <initializer_list> #include <string> +#include <string_view> +#include <system_error> #include <type_traits> #include <vector> #include <memory> + /*----------------------------------------------------------------------------- osd_process_kill: kill the current process @@ -54,10 +58,22 @@ void osd_process_kill(); int osd_setenv(const char *name, const char *value, int overwrite); -/*----------------------------------------------------------------------------- - osd_get_clipboard_text: retrieves text from the clipboard ------------------------------------------------------------------------------*/ -std::string osd_get_clipboard_text(); +/// \brief Get clipboard text +/// +/// Gets current clipboard content as UTF-8 text. Returns an empty +/// string if the clipboard contents cannot be converted to plain text. +/// \return Clipboard contents or an empty string. +std::string osd_get_clipboard_text() noexcept; + + +/// \brief Set clipboard text +/// +/// Sets the desktop environment's clipboard contents to the supplied +/// UTF-8 text. The contents of the clipboard may be changed on error. +/// \param [in] text The text to copy to the clipboard. +/// \return An error condition if the operation failed or is +/// unsupported. +std::error_condition osd_set_clipboard_text(std::string_view text) noexcept; namespace osd { @@ -193,4 +209,4 @@ protected: #define OSD_DYNAMIC_CALL(fname, ...) (*m_##fname##_pfn) ( __VA_ARGS__ ) #define OSD_DYNAMIC_API_TEST(fname) (m_##fname##_pfn != nullptr) -#endif /* __OSDLIB__ */ +#endif // MAME_OSD_LIB_OSDLIB_H diff --git a/src/osd/modules/lib/osdlib_macosx.cpp b/src/osd/modules/lib/osdlib_macosx.cpp index 19b228b6369..8f61bb4e998 100644 --- a/src/osd/modules/lib/osdlib_macosx.cpp +++ b/src/osd/modules/lib/osdlib_macosx.cpp @@ -85,7 +85,7 @@ void osd_break_into_debugger(const char *message) // osd_get_clipboard_text //============================================================ -std::string osd_get_clipboard_text() +std::string osd_get_clipboard_text() noexcept { std::string result; bool has_result = false; @@ -121,31 +121,48 @@ std::string osd_get_clipboard_text() CFStringEncoding encoding; if (UTTypeConformsTo(flavor_type, kUTTypeUTF16PlainText)) encoding = kCFStringEncodingUTF16; - else if (UTTypeConformsTo (flavor_type, kUTTypeUTF8PlainText)) + else if (UTTypeConformsTo(flavor_type, kUTTypeUTF8PlainText)) encoding = kCFStringEncodingUTF8; - else if (UTTypeConformsTo (flavor_type, kUTTypePlainText)) + else if (UTTypeConformsTo(flavor_type, kUTTypePlainText)) encoding = kCFStringEncodingMacRoman; else continue; CFDataRef flavor_data; err = PasteboardCopyItemFlavorData(pasteboard_ref, item_id, flavor_type, &flavor_data); + if (err) + continue; - if (!err) + CFDataRef utf8_data; + if (kCFStringEncodingUTF8 == encoding) + { + utf8_data = flavor_data; + } + else { CFStringRef string_ref = CFStringCreateFromExternalRepresentation(kCFAllocatorDefault, flavor_data, encoding); - CFDataRef data_ref = CFStringCreateExternalRepresentation (kCFAllocatorDefault, string_ref, kCFStringEncodingUTF8, '?'); - CFRelease(string_ref); CFRelease(flavor_data); + if (!string_ref) + continue; - CFIndex const length = CFDataGetLength(data_ref); - CFRange const range = CFRangeMake(0, length); - - result.resize(length); - CFDataGetBytes(data_ref, range, reinterpret_cast<unsigned char *>(&result[0])); - has_result = true; + utf8_data = CFStringCreateExternalRepresentation(kCFAllocatorDefault, string_ref, kCFStringEncodingUTF8, '?'); + CFRelease(string_ref); + } - CFRelease(data_ref); + if (utf8_data) + { + CFIndex const length = CFDataGetLength(utf8_data); + CFRange const range = CFRangeMake(0, length); + try + { + result.resize(length); + CFDataGetBytes(utf8_data, range, reinterpret_cast<UInt8 *>(result.data())); + has_result = true; + } + catch (std::bad_alloc const &) + { + } + CFRelease(utf8_data); } } @@ -157,6 +174,46 @@ std::string osd_get_clipboard_text() return result; } + +//============================================================ +// osd_set_clipboard_text +//============================================================ + +std::error_condition osd_set_clipboard_text(std::string_view text) noexcept +{ + // FIXME: better conversion of OSStatus to std::error_condition + OSStatus err; + + CFDataRef const data = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<UInt8 const *>(text.data()), text.length()); + if (!data) + return std::errc::not_enough_memory; + + PasteboardRef pasteboard_ref; + err = PasteboardCreate(kPasteboardClipboard, &pasteboard_ref); + if (err) + { + CFRelease(data); + return std::errc::io_error; + } + + err = PasteboardClear(pasteboard_ref); + if (err) + { + CFRelease(data); + CFRelease(pasteboard_ref); + return std::errc::io_error; + } + + err = PasteboardPutItemFlavor(pasteboard_ref, PasteboardItemID(1), kUTTypeUTF8PlainText, data, kPasteboardFlavorNoFlags); + CFRelease(data); + CFRelease(pasteboard_ref); + if (err) + return std::errc::io_error; + + return std::error_condition(); +} + + //============================================================ // osd_getpid //============================================================ diff --git a/src/osd/modules/lib/osdlib_unix.cpp b/src/osd/modules/lib/osdlib_unix.cpp index 4b091450116..0c6eb8622ab 100644 --- a/src/osd/modules/lib/osdlib_unix.cpp +++ b/src/osd/modules/lib/osdlib_unix.cpp @@ -69,28 +69,66 @@ void osd_break_into_debugger(const char *message) } #ifdef SDLMAME_ANDROID -std::string osd_get_clipboard_text() +std::string osd_get_clipboard_text() noexcept { return std::string(); } + +std::error_condition osd_set_clipboard_text(std::string_view text) noexcept +{ + return std::errc::io_error; // TODO: better error code? +} #else //============================================================ // osd_get_clipboard_text //============================================================ -std::string osd_get_clipboard_text() +std::string osd_get_clipboard_text() noexcept { + // TODO: better error handling std::string result; if (SDL_HasClipboardText()) { - char *temp = SDL_GetClipboardText(); - result.assign(temp); - SDL_free(temp); + char *const temp = SDL_GetClipboardText(); + if (temp) + { + try + { + result.assign(temp); + } + catch (std::bad_alloc const &) + { + } + SDL_free(temp); + } } return result; } + +//============================================================ +// osd_set_clipboard_text +//============================================================ + +std::error_condition osd_set_clipboard_text(std::string_view text) noexcept +{ + try + { + std::string const clip(text); // need to do this to ensure there's a terminating NUL for SDL + if (0 > SDL_SetClipboardText(clip.c_str())) + { + // SDL_GetError returns a message, can't really convert it to an error condition + return std::errc::io_error; // TODO: better error code? + } + + return std::error_condition(); + } + catch (std::bad_alloc const &) + { + return std::errc::not_enough_memory; + } +} #endif //============================================================ diff --git a/src/osd/modules/lib/osdlib_win32.cpp b/src/osd/modules/lib/osdlib_win32.cpp index 174dc769760..d209e98c474 100644 --- a/src/osd/modules/lib/osdlib_win32.cpp +++ b/src/osd/modules/lib/osdlib_win32.cpp @@ -14,10 +14,10 @@ #include "osdcore.h" #include "strconv.h" -#ifdef OSD_WINDOWS #include "winutf8.h" -#endif +#include "winutil.h" +#include <algorithm> #include <cstdio> #include <cstdlib> @@ -168,21 +168,88 @@ static std::string convert_ansi(LPCVOID data) // osd_get_clipboard_text //============================================================ -std::string osd_get_clipboard_text() +std::string osd_get_clipboard_text() noexcept { std::string result; - // try to access unicode text - if (!get_clipboard_text_by_format(result, CF_UNICODETEXT, convert_wide)) + // TODO: better error handling + try + { + // try to access unicode text + if (!get_clipboard_text_by_format(result, CF_UNICODETEXT, convert_wide)) + { + // try to access ANSI text + get_clipboard_text_by_format(result, CF_TEXT, convert_ansi); + } + } + catch (...) { - // try to access ANSI text - get_clipboard_text_by_format(result, CF_TEXT, convert_ansi); } return result; } //============================================================ +// osd_set_clipboard_text +//============================================================ + +std::error_condition osd_set_clipboard_text(std::string_view text) noexcept +{ + try + { + // convert the text to a wide char string and create a moveable global block + std::wstring const wtext = osd::text::to_wstring(text); + HGLOBAL const clip = GlobalAlloc(GMEM_MOVEABLE, (text.length() + 1) * sizeof(wchar_t)); + if (!clip) + return win_error_to_error_condition(GetLastError()); + LPWSTR const lock = reinterpret_cast<LPWSTR>(GlobalLock(clip)); + if (!lock) + { + DWORD const err(GetLastError()); + GlobalFree(clip); + return win_error_to_error_condition(err); + } + + // clear current clipboard contents + if (!OpenClipboard(nullptr)) + { + DWORD const err(GetLastError()); + GlobalUnlock(clip); + GlobalFree(clip); + return win_error_to_error_condition(err); + } + if (!OpenClipboard(nullptr)) + { + DWORD const err(GetLastError()); + CloseClipboard(); + GlobalUnlock(clip); + GlobalFree(clip); + return win_error_to_error_condition(err); + } + + // copy the text (plus NUL terminator) to the moveable block and put it on the clipboard + std::copy_n(wtext.c_str(), wtext.length() + 1, lock); + GlobalUnlock(clip); + if (!SetClipboardData(CF_UNICODETEXT, clip)) + { + DWORD const err(GetLastError()); + CloseClipboard(); + GlobalFree(clip); + return win_error_to_error_condition(err); + } + + // clean up + if (!CloseClipboard()) + return win_error_to_error_condition(GetLastError()); + return std::error_condition(); + } + catch (std::bad_alloc const &) + { + return std::errc::not_enough_memory; + } +} + +//============================================================ // osd_getpid //============================================================ diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp index 1019bc4f766..09254f32042 100644 --- a/src/osd/modules/lib/osdobj_common.cpp +++ b/src/osd/modules/lib/osdobj_common.cpp @@ -32,7 +32,7 @@ const options_entry osd_options::s_option_entries[] = #if defined(SDLMAME_MACOSX) || defined(OSD_MAC) { OSDOPTION_UIMODEKEY, "DEL", core_options::option_type::STRING, "key to enable/disable MAME controls when emulated system has keyboard inputs" }, #else - { OSDOPTION_UIMODEKEY, "SCRLOCK", core_options::option_type::STRING, "key to enable/disable MAME controls when emulated system has keyboard inputs" }, + { OSDOPTION_UIMODEKEY, "auto", core_options::option_type::STRING, "key to enable/disable MAME controls when emulated system has keyboard inputs" }, #endif // SDLMAME_MACOSX { nullptr, nullptr, core_options::option_type::HEADER, "OSD FONT OPTIONS" }, |