| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- /*
- Simple DirectMedia Layer
- Copyright (C) 1997-2024 Sam Lantinga <slouken@libsdl.org>
- This software is provided 'as-is', without any express or implied
- warranty. In no event will the authors be held liable for any damages
- arising from the use of this software.
- Permission is granted to anyone to use this software for any purpose,
- including commercial applications, and to alter it and redistribute it
- freely, subject to the following restrictions:
- 1. The origin of this software must not be misrepresented; you must not
- claim that you wrote the original software. If you use this software
- in a product, an acknowledgment in the product documentation would be
- appreciated but is not required.
- 2. Altered source versions must be plainly marked as such, and must not be
- misrepresented as being the original software.
- 3. This notice may not be removed or altered from any source distribution.
- */
- #include "SDL_internal.h"
- #include "SDL_clipboard_c.h"
- #include "SDL_sysvideo.h"
- #include "../events/SDL_clipboardevents_c.h"
- void SDL_CancelClipboardData(Uint32 sequence)
- {
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- size_t i;
- if (sequence != _this->clipboard_sequence) {
- // This clipboard data was already canceled
- return;
- }
- if (_this->clipboard_cleanup) {
- _this->clipboard_cleanup(_this->clipboard_userdata);
- }
- if (_this->clipboard_mime_types) {
- for (i = 0; i < _this->num_clipboard_mime_types; ++i) {
- SDL_free(_this->clipboard_mime_types[i]);
- }
- SDL_free(_this->clipboard_mime_types);
- _this->clipboard_mime_types = NULL;
- _this->num_clipboard_mime_types = 0;
- }
- _this->clipboard_callback = NULL;
- _this->clipboard_cleanup = NULL;
- _this->clipboard_userdata = NULL;
- }
- SDL_bool SDL_SetClipboardData(SDL_ClipboardDataCallback callback, SDL_ClipboardCleanupCallback cleanup, void *userdata, const char **mime_types, size_t num_mime_types)
- {
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- size_t i;
- if (!_this) {
- return SDL_SetError("Video subsystem must be initialized to set clipboard text");
- }
- // Parameter validation
- if (!((callback && mime_types && num_mime_types > 0) ||
- (!callback && !mime_types && num_mime_types == 0))) {
- return SDL_SetError("Invalid parameters");
- }
- if (!callback && !_this->clipboard_callback) {
- // Nothing to do, don't modify the system clipboard
- return true;
- }
- SDL_CancelClipboardData(_this->clipboard_sequence);
- ++_this->clipboard_sequence;
- if (!_this->clipboard_sequence) {
- _this->clipboard_sequence = 1;
- }
- _this->clipboard_callback = callback;
- _this->clipboard_cleanup = cleanup;
- _this->clipboard_userdata = userdata;
- if (mime_types && num_mime_types > 0) {
- size_t num_allocated = 0;
- _this->clipboard_mime_types = (char **)SDL_malloc(num_mime_types * sizeof(char *));
- if (_this->clipboard_mime_types) {
- for (i = 0; i < num_mime_types; ++i) {
- _this->clipboard_mime_types[i] = SDL_strdup(mime_types[i]);
- if (_this->clipboard_mime_types[i]) {
- ++num_allocated;
- }
- }
- }
- if (num_allocated < num_mime_types) {
- SDL_ClearClipboardData();
- return false;
- }
- _this->num_clipboard_mime_types = num_mime_types;
- }
- if (_this->SetClipboardData) {
- if (!_this->SetClipboardData(_this)) {
- return false;
- }
- } else if (_this->SetClipboardText) {
- char *text = NULL;
- size_t size;
- for (i = 0; i < num_mime_types; ++i) {
- const char *mime_type = _this->clipboard_mime_types[i];
- if (SDL_IsTextMimeType(mime_type)) {
- const void *data = _this->clipboard_callback(_this->clipboard_userdata, mime_type, &size);
- if (data) {
- text = (char *)SDL_malloc(size + 1);
- SDL_memcpy(text, data, size);
- text[size] = '\0';
- if (!_this->SetClipboardText(_this, text)) {
- SDL_free(text);
- return false;
- }
- break;
- }
- }
- }
- if (text) {
- SDL_free(text);
- } else {
- if (!_this->SetClipboardText(_this, "")) {
- return false;
- }
- }
- }
- SDL_SendClipboardUpdate();
- return true;
- }
- SDL_bool SDL_ClearClipboardData(void)
- {
- return SDL_SetClipboardData(NULL, NULL, NULL, NULL, 0);
- }
- void *SDL_GetInternalClipboardData(SDL_VideoDevice *_this, const char *mime_type, size_t *size)
- {
- void *data = NULL;
- if (_this->clipboard_callback) {
- const void *provided_data = _this->clipboard_callback(_this->clipboard_userdata, mime_type, size);
- if (provided_data) {
- // Make a copy of it for the caller and guarantee null termination
- data = SDL_malloc(*size + sizeof(Uint32));
- if (data) {
- SDL_memcpy(data, provided_data, *size);
- SDL_memset((Uint8 *)data + *size, 0, sizeof(Uint32));
- }
- }
- }
- return data;
- }
- void *SDL_GetClipboardData(const char *mime_type, size_t *size)
- {
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- if (!_this) {
- SDL_SetError("Video subsystem must be initialized to get clipboard data");
- return NULL;
- }
- if (!mime_type) {
- SDL_InvalidParamError("mime_type");
- return NULL;
- }
- if (!size) {
- SDL_InvalidParamError("size");
- return NULL;
- }
- // Initialize size to empty, so implementations don't have to worry about it
- *size = 0;
- if (_this->GetClipboardData) {
- return _this->GetClipboardData(_this, mime_type, size);
- } else if (_this->GetClipboardText && SDL_IsTextMimeType(mime_type)) {
- char *text = _this->GetClipboardText(_this);
- if (text && *text == '\0') {
- SDL_free(text);
- text = NULL;
- }
- return text;
- } else {
- return SDL_GetInternalClipboardData(_this, mime_type, size);
- }
- }
- bool SDL_HasInternalClipboardData(SDL_VideoDevice *_this, const char *mime_type)
- {
- size_t i;
- for (i = 0; i < _this->num_clipboard_mime_types; ++i) {
- if (SDL_strcmp(mime_type, _this->clipboard_mime_types[i]) == 0) {
- return true;
- }
- }
- return false;
- }
- SDL_bool SDL_HasClipboardData(const char *mime_type)
- {
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- if (!_this) {
- SDL_SetError("Video subsystem must be initialized to check clipboard data");
- return false;
- }
- if (!mime_type) {
- SDL_InvalidParamError("mime_type");
- return false;
- }
- if (_this->HasClipboardData) {
- return _this->HasClipboardData(_this, mime_type);
- } else if (_this->HasClipboardText && SDL_IsTextMimeType(mime_type)) {
- return _this->HasClipboardText(_this);
- } else {
- return SDL_HasInternalClipboardData(_this, mime_type);
- }
- }
- // Clipboard text
- bool SDL_IsTextMimeType(const char *mime_type)
- {
- return (SDL_strncmp(mime_type, "text", 4) == 0);
- }
- static const char **SDL_GetTextMimeTypes(SDL_VideoDevice *_this, size_t *num_mime_types)
- {
- if (_this->GetTextMimeTypes) {
- return _this->GetTextMimeTypes(_this, num_mime_types);
- } else {
- static const char *text_mime_types[] = {
- "text/plain;charset=utf-8"
- };
- *num_mime_types = SDL_arraysize(text_mime_types);
- return text_mime_types;
- }
- }
- const void * SDLCALL SDL_ClipboardTextCallback(void *userdata, const char *mime_type, size_t *size)
- {
- char *text = (char *)userdata;
- if (text) {
- *size = SDL_strlen(text);
- } else {
- *size = 0;
- }
- return text;
- }
- SDL_bool SDL_SetClipboardText(const char *text)
- {
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- size_t num_mime_types;
- const char **text_mime_types;
- if (!_this) {
- return SDL_SetError("Video subsystem must be initialized to set clipboard text");
- }
- if (text && *text) {
- text_mime_types = SDL_GetTextMimeTypes(_this, &num_mime_types);
- return SDL_SetClipboardData(SDL_ClipboardTextCallback, SDL_free, SDL_strdup(text), text_mime_types, num_mime_types);
- }
- return SDL_ClearClipboardData();
- }
- char *SDL_GetClipboardText(void)
- {
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- size_t i, num_mime_types;
- const char **text_mime_types;
- size_t length;
- char *text = NULL;
- if (!_this) {
- SDL_SetError("Video subsystem must be initialized to get clipboard text");
- return SDL_strdup("");
- }
- text_mime_types = SDL_GetTextMimeTypes(_this, &num_mime_types);
- for (i = 0; i < num_mime_types; ++i) {
- void *clipdata = SDL_GetClipboardData(text_mime_types[i], &length);
- if (clipdata) {
- text = (char *)clipdata;
- break;
- }
- }
- if (!text) {
- text = SDL_strdup("");
- }
- return text;
- }
- SDL_bool SDL_HasClipboardText(void)
- {
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- size_t i, num_mime_types;
- const char **text_mime_types;
- if (!_this) {
- SDL_SetError("Video subsystem must be initialized to check clipboard text");
- return false;
- }
- text_mime_types = SDL_GetTextMimeTypes(_this, &num_mime_types);
- for (i = 0; i < num_mime_types; ++i) {
- if (SDL_HasClipboardData(text_mime_types[i])) {
- return true;
- }
- }
- return false;
- }
- // Primary selection text
- SDL_bool SDL_SetPrimarySelectionText(const char *text)
- {
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- if (!_this) {
- return SDL_SetError("Video subsystem must be initialized to set primary selection text");
- }
- if (!text) {
- text = "";
- }
- if (_this->SetPrimarySelectionText) {
- if (!_this->SetPrimarySelectionText(_this, text)) {
- return false;
- }
- } else {
- SDL_free(_this->primary_selection_text);
- _this->primary_selection_text = SDL_strdup(text);
- }
- SDL_SendClipboardUpdate();
- return true;
- }
- char *SDL_GetPrimarySelectionText(void)
- {
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- if (!_this) {
- SDL_SetError("Video subsystem must be initialized to get primary selection text");
- return SDL_strdup("");
- }
- if (_this->GetPrimarySelectionText) {
- return _this->GetPrimarySelectionText(_this);
- } else {
- const char *text = _this->primary_selection_text;
- if (!text) {
- text = "";
- }
- return SDL_strdup(text);
- }
- }
- SDL_bool SDL_HasPrimarySelectionText(void)
- {
- SDL_VideoDevice *_this = SDL_GetVideoDevice();
- if (!_this) {
- SDL_SetError("Video subsystem must be initialized to check primary selection text");
- return false;
- }
- if (_this->HasPrimarySelectionText) {
- return _this->HasPrimarySelectionText(_this);
- } else {
- if (_this->primary_selection_text && _this->primary_selection_text[0] != '\0') {
- return true;
- } else {
- return false;
- }
- }
- }
|