support copy/paste from system clipboard

develop
Myk Taylor 2023-07-02 18:04:06 -07:00
parent b5fd877b84
commit 175c249d29
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
6 changed files with 80 additions and 0 deletions

@ -38,6 +38,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
## Fixes
## Misc Improvements
- ``widgets.EditField``: DFHack edit fields now support cut/copy/paste with the system clipboard with Ctrl-X/Ctrl-C/Ctrl-V
## Documentation

@ -2815,6 +2815,14 @@ and are only documented here for completeness:
Returns 0 if the address is not found.
Requires a heap snapshot.
* ``dfhack.internal.getClipboardText()``
Gets the system clipboard text (converted to CP437 encoding).
* ``dfhack.internal.setClipboardText(text)``
Converts the given text from CP437 to UTF-8 and sets the system clipboard
text.
.. _lua-core-context:
@ -4688,6 +4696,12 @@ following keyboard hotkeys:
- Ctrl-B/Ctrl-F: move the cursor one word back or forward.
- Ctrl-A/Ctrl-E: move the cursor to the beginning/end of the text.
The widget also supports integration with the system clipboard:
- Ctrl-C: copy current text to the system clipboard
- Ctrl-X: copy current text to the system clipboard and clear text in widget
- Ctrl-V: paste text from the system clipboard (text is converted to cp437)
The ``EditField`` class also provides the following functions:
* ``editfield:setCursor([cursor_pos])``

@ -47,6 +47,7 @@ distribution.
#include "modules/Burrows.h"
#include "modules/Constructions.h"
#include "modules/Designations.h"
#include "modules/DFSDL.h"
#include "modules/Filesystem.h"
#include "modules/Gui.h"
#include "modules/Items.h"
@ -2999,6 +3000,9 @@ static int msize_address(uintptr_t ptr)
return -1;
}
static std::string getClipboardText() { return DFSDL::DFSDL_GetClipboardTextCp437(); }
static void setClipboardText(std::string s) { DFSDL::DFSDL_SetClipboardTextCp437(s); }
static const LuaWrapper::FunctionReg dfhack_internal_module[] = {
WRAP(getImageBase),
WRAP(getRebaseDelta),
@ -3013,6 +3017,8 @@ static const LuaWrapper::FunctionReg dfhack_internal_module[] = {
WRAPN(getAddressSizeInHeap, get_address_size_in_heap),
WRAPN(getRootAddressOfHeapObject, get_root_address_of_heap_object),
WRAPN(msizeAddress, msize_address),
WRAP(getClipboardText),
WRAP(setClipboardText),
{ NULL, NULL }
};

@ -48,6 +48,14 @@ DFHACK_EXPORT void DFSDL_FreeSurface(SDL_Surface *surface);
// DFHACK_EXPORT int DFSDL_SemPost(SDL_sem *sem);
DFHACK_EXPORT int DFSDL_PushEvent(SDL_Event *event);
// System clipboard
DFHACK_EXPORT std::string DFSDL_GetClipboardTextUtf8();
DFHACK_EXPORT std::string DFSDL_GetClipboardTextCp437();
DFHACK_EXPORT bool DFSDL_SetClipboardTextUtf8(const char *text);
DFHACK_EXPORT bool DFSDL_SetClipboardTextUtf8(const std::string &text);
DFHACK_EXPORT bool DFSDL_SetClipboardTextCp437(const char *text);
DFHACK_EXPORT bool DFSDL_SetClipboardTextCp437(const std::string &text);
}
}

@ -772,6 +772,16 @@ function EditField:onInput(keys)
elseif keys.CUSTOM_CTRL_E then -- end
self:setCursor()
return true
elseif keys.CUSTOM_CTRL_C then
dfhack.internal.setClipboardText(self.text)
return true
elseif keys.CUSTOM_CTRL_X then
dfhack.internal.setClipboardText(self.text)
self:setText('')
return true
elseif keys.CUSTOM_CTRL_V then
self:insert(dfhack.internal.getClipboardText())
return true
end
-- if we're modal, then unconditionally eat all the input

@ -3,8 +3,11 @@
#include "modules/DFSDL.h"
#include "Debug.h"
#include "MiscUtils.h"
#include "PluginManager.h"
#include <SDL.h>
namespace DFHack {
DBG_DECLARE(core, dfsdl, DebugCategory::LINFO);
}
@ -35,6 +38,10 @@ void (*g_SDL_FreeSurface)(SDL_Surface *) = nullptr;
// int (*g_SDL_SemWait)(DFSDL_sem *) = nullptr;
// int (*g_SDL_SemPost)(DFSDL_sem *) = nullptr;
int (*g_SDL_PushEvent)(SDL_Event *) = nullptr;
SDL_bool (*g_SDL_HasClipboardText)();
int (*g_SDL_SetClipboardText)(const char *text);
char * (*g_SDL_GetClipboardText)();
void (*g_SDL_free)(void *);
bool DFSDL::init(color_ostream &out) {
for (auto &lib_str : SDL_LIBS) {
@ -71,6 +78,10 @@ bool DFSDL::init(color_ostream &out) {
// bind(g_sdl_handle, SDL_SemWait);
// bind(g_sdl_handle, SDL_SemPost);
bind(g_sdl_handle, SDL_PushEvent);
bind(g_sdl_handle, SDL_HasClipboardText);
bind(g_sdl_handle, SDL_SetClipboardText);
bind(g_sdl_handle, SDL_GetClipboardText);
bind(g_sdl_handle, SDL_free);
#undef bind
DEBUG(dfsdl,out).print("sdl successfully loaded\n");
@ -124,3 +135,33 @@ void DFSDL::DFSDL_FreeSurface(SDL_Surface *surface) {
int DFSDL::DFSDL_PushEvent(SDL_Event *event) {
return g_SDL_PushEvent(event);
}
std::string DFSDL::DFSDL_GetClipboardTextUtf8() {
if (g_SDL_HasClipboardText() != SDL_TRUE)
return "";
char *text = g_SDL_GetClipboardText();
std::string ret = text;
g_SDL_free(text);
return ret;
}
std::string DFSDL::DFSDL_GetClipboardTextCp437() {
std::string utf8text = DFSDL_GetClipboardTextUtf8();
return UTF2DF(utf8text);
}
bool DFSDL::DFSDL_SetClipboardTextUtf8(const char *text) {
return g_SDL_SetClipboardText(text) == 0;
}
bool DFSDL::DFSDL_SetClipboardTextUtf8(const std::string &text) {
return DFSDL_SetClipboardTextUtf8(text.c_str());
}
bool DFSDL::DFSDL_SetClipboardTextCp437(const char *text) {
return DFSDL_SetClipboardTextUtf8(DF2UTF(text));
}
bool DFSDL::DFSDL_SetClipboardTextCp437(const std::string &text) {
return DFSDL_SetClipboardTextUtf8(DF2UTF(text));
}