summaryrefslogtreecommitdiffstatshomepage
path: root/src/osd
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2022-09-02 08:55:16 +1000
committer Vas Crabb <vas@vastheman.com>2022-09-02 08:55:16 +1000
commit051c380fd14040c83a0d5b919e6289e70fef9df8 (patch)
treee247a309f4d1c66c07803c02d67ac89837211bd1 /src/osd
parent67f129e31518a50a801413f732991972d2c3538a (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')
-rw-r--r--src/osd/modules/file/winfile.cpp88
-rw-r--r--src/osd/modules/file/winfile.h2
-rw-r--r--src/osd/modules/file/winptty.cpp10
-rw-r--r--src/osd/modules/font/font_dwrite.cpp14
-rw-r--r--src/osd/modules/input/input_sdlcommon.cpp34
-rw-r--r--src/osd/modules/input/input_windows.cpp20
-rw-r--r--src/osd/modules/lib/osdlib.h30
-rw-r--r--src/osd/modules/lib/osdlib_macosx.cpp83
-rw-r--r--src/osd/modules/lib/osdlib_unix.cpp48
-rw-r--r--src/osd/modules/lib/osdlib_win32.cpp81
-rw-r--r--src/osd/modules/lib/osdobj_common.cpp2
-rw-r--r--src/osd/osdcore.h9
-rw-r--r--src/osd/windows/winutil.cpp65
-rw-r--r--src/osd/windows/winutil.h4
14 files changed, 331 insertions, 159 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" },
diff --git a/src/osd/osdcore.h b/src/osd/osdcore.h
index d9f61c22a5a..489343f35b4 100644
--- a/src/osd/osdcore.h
+++ b/src/osd/osdcore.h
@@ -11,7 +11,6 @@
#pragma once
-
#include "osdcomm.h"
#include "strformat.h"
@@ -19,6 +18,7 @@
#include <cstdint>
#include <iosfwd>
#include <string>
+#include <string_view>
#include <utility>
#include <vector>
@@ -350,13 +350,6 @@ void osd_work_item_release(osd_work_item *item);
void osd_break_into_debugger(const char *message);
-/// \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();
-
/***************************************************************************
UNCATEGORIZED INTERFACES
diff --git a/src/osd/windows/winutil.cpp b/src/osd/windows/winutil.cpp
index 3a344386a12..3ee4ffde376 100644
--- a/src/osd/windows/winutil.cpp
+++ b/src/osd/windows/winutil.cpp
@@ -129,3 +129,68 @@ HMODULE WINAPI GetModuleHandleUni()
VirtualQuery((LPCVOID)GetModuleHandleUni, &mbi, sizeof(mbi));
return (HMODULE)mbi.AllocationBase;
}
+
+
+//============================================================
+// win_error_to_error_condition
+//============================================================
+
+std::error_condition win_error_to_error_condition(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/windows/winutil.h b/src/osd/windows/winutil.h
index 0a5952b5279..85393b6b930 100644
--- a/src/osd/windows/winutil.h
+++ b/src/osd/windows/winutil.h
@@ -13,8 +13,8 @@
#include "osdfile.h"
-#include <algorithm>
#include <chrono>
+#include <system_error>
#include <windows.h>
@@ -25,4 +25,6 @@ std::chrono::system_clock::time_point win_time_point_from_filetime(LPFILETIME fi
BOOL win_is_gui_application();
HMODULE WINAPI GetModuleHandleUni();
+std::error_condition win_error_to_error_condition(DWORD error) noexcept;
+
#endif // MAME_OSD_WINDOWS_WINUTIL_H