From 1b9488e1016b78ee15bbc00d7aab02c52d78b003 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Thu, 8 Jul 2010 05:43:34 -0700 Subject: [PATCH] Added Windows clipboard support --- VisualC/SDL/SDL_VS2005.vcproj | 16 +++ VisualC/SDL/SDL_VS2008.vcproj | 19 +++- VisualC/SDLmain/SDLmain_VS2008.vcproj | 3 - src/video/SDL_clipboard.c | 3 + src/video/win32/SDL_win32clipboard.c | 144 ++++++++++++++++++++++++++ src/video/win32/SDL_win32clipboard.h | 33 ++++++ src/video/win32/SDL_win32events.c | 13 --- src/video/win32/SDL_win32events.h | 1 - src/video/win32/SDL_win32video.c | 18 ++++ src/video/win32/SDL_win32video.h | 1 + src/video/win32/SDL_win32window.c | 12 +-- 11 files changed, 235 insertions(+), 28 deletions(-) create mode 100644 src/video/win32/SDL_win32clipboard.c create mode 100644 src/video/win32/SDL_win32clipboard.h diff --git a/VisualC/SDL/SDL_VS2005.vcproj b/VisualC/SDL/SDL_VS2005.vcproj index d58446605..0dfa9b77d 100644 --- a/VisualC/SDL/SDL_VS2005.vcproj +++ b/VisualC/SDL/SDL_VS2005.vcproj @@ -235,6 +235,10 @@ RelativePath="..\..\include\SDL_audio.h" > + + @@ -560,6 +564,10 @@ RelativePath="..\..\src\video\SDL_bmp.c" > + + @@ -940,6 +948,14 @@ RelativePath="..\..\src\audio\SDL_wave.h" > + + + + diff --git a/VisualC/SDL/SDL_VS2008.vcproj b/VisualC/SDL/SDL_VS2008.vcproj index 7cf5d4a1a..d616591fd 100644 --- a/VisualC/SDL/SDL_VS2008.vcproj +++ b/VisualC/SDL/SDL_VS2008.vcproj @@ -5,9 +5,6 @@ Name="SDL" ProjectGUID="{81CE8DAF-EBB2-4761-8E45-B71ABCCA8C68}" RootNamespace="SDL" - SccProjectName="Perforce Project" - SccLocalPath="..\.." - SccProvider="MSSCCI:Perforce SCM" TargetFrameworkVersion="131072" > @@ -385,6 +382,10 @@ RelativePath="..\..\include\SDL_audio.h" > + + @@ -718,6 +719,10 @@ RelativePath="..\..\src\video\SDL_bmp.c" > + + @@ -1098,6 +1103,14 @@ RelativePath="..\..\src\audio\SDL_wave.h" > + + + + diff --git a/VisualC/SDLmain/SDLmain_VS2008.vcproj b/VisualC/SDLmain/SDLmain_VS2008.vcproj index ac482184a..94f4447fd 100644 --- a/VisualC/SDLmain/SDLmain_VS2008.vcproj +++ b/VisualC/SDLmain/SDLmain_VS2008.vcproj @@ -4,9 +4,6 @@ Version="9.00" Name="SDLmain" ProjectGUID="{DA956FD3-E142-46F2-9DD5-C78BEBB56B7A}" - SccProjectName="Perforce Project" - SccLocalPath="..\.." - SccProvider="MSSCCI:Perforce SCM" TargetFrameworkVersion="131072" > diff --git a/src/video/SDL_clipboard.c b/src/video/SDL_clipboard.c index e459f6994..fc7e5fbb6 100644 --- a/src/video/SDL_clipboard.c +++ b/src/video/SDL_clipboard.c @@ -30,6 +30,9 @@ SDL_SetClipboardText(const char *text) { SDL_VideoDevice *_this = SDL_GetVideoDevice(); + if (!text) { + text = ""; + } if (_this->SetClipboardText) { return _this->SetClipboardText(_this, text); } else { diff --git a/src/video/win32/SDL_win32clipboard.c b/src/video/win32/SDL_win32clipboard.c new file mode 100644 index 000000000..950bd444f --- /dev/null +++ b/src/video/win32/SDL_win32clipboard.c @@ -0,0 +1,144 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2010 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#include "SDL_win32video.h" +#include "SDL_win32window.h" + + +#ifdef UNICODE +#define TEXT_FORMAT CF_UNICODETEXT +#else +#define TEXT_FORMAT CF_TEXT +#endif + + +/* Get any application owned window handle for clipboard association */ +static HWND +GetWindowHandle(_THIS) +{ + SDL_VideoDisplay *display; + SDL_Window *window; + + display = _this->displays; + if (display) { + window = display->windows; + if (window) { + return ((SDL_WindowData *) window->driverdata)->hwnd; + } + } + return NULL; +} + +int +WIN_SetClipboardText(_THIS, const char *text) +{ + int result = 0; + + if (OpenClipboard(GetWindowHandle(_this))) { + HANDLE hMem; + LPTSTR tstr; + SIZE_T i, size; + + /* Convert the text from UTF-8 to Windows Unicode */ + tstr = WIN_UTF8ToString(text); + if (!tstr) { + return -1; + } + + /* Find out the size of the data */ + for (size = 0, i = 0; tstr[i]; ++i, ++size) { + if (tstr[i] == '\n' && (i == 0 || tstr[i-1] != '\r')) { + /* We're going to insert a carriage return */ + ++size; + } + } + size = (size+1)*sizeof(*tstr); + + /* Save the data to the clipboard */ + hMem = GlobalAlloc(GMEM_MOVEABLE, size); + if (hMem) { + LPTSTR dst = (LPTSTR)GlobalLock(hMem); + /* Copy the text over, adding carriage returns as necessary */ + for (i = 0; tstr[i]; ++i) { + if (tstr[i] == '\n' && (i == 0 || tstr[i-1] != '\r')) { + *dst++ = '\r'; + } + *dst++ = tstr[i]; + } + *dst = 0; + GlobalUnlock(hMem); + + EmptyClipboard(); + if (!SetClipboardData(TEXT_FORMAT, hMem)) { + WIN_SetError("Couldn't set clipboard data"); + result = -1; + } + } + SDL_free(tstr); + + CloseClipboard(); + } else { + WIN_SetError("Couldn't open clipboard"); + result = -1; + } + return result; +} + +char * +WIN_GetClipboardText(_THIS) +{ + char *text; + + text = NULL; + if (IsClipboardFormatAvailable(TEXT_FORMAT) && + OpenClipboard(GetWindowHandle(_this))) { + HANDLE hMem; + LPTSTR tstr; + + hMem = GetClipboardData(TEXT_FORMAT); + if (hMem) { + tstr = (LPTSTR)GlobalLock(hMem); + text = WIN_StringToUTF8(tstr); + GlobalUnlock(hMem); + } else { + WIN_SetError("Couldn't get clipboard data"); + } + CloseClipboard(); + } + if (!text) { + text = SDL_strdup(""); + } + return text; +} + +SDL_bool +WIN_HasClipboardText(_THIS) +{ + if (IsClipboardFormatAvailable(TEXT_FORMAT)) { + return SDL_TRUE; + } else { + return SDL_FALSE; + } +} + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_win32clipboard.h b/src/video/win32/SDL_win32clipboard.h new file mode 100644 index 000000000..36fb79823 --- /dev/null +++ b/src/video/win32/SDL_win32clipboard.h @@ -0,0 +1,33 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2010 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + Sam Lantinga + slouken@libsdl.org +*/ +#include "SDL_config.h" + +#ifndef _SDL_win32clipboard_h +#define _SDL_win32clipboard_h + +extern int WIN_SetClipboardText(_THIS, const char *text); +extern char *WIN_GetClipboardText(_THIS); +extern SDL_bool WIN_HasClipboardText(_THIS); + +#endif /* _SDL_win32clipboard_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_win32events.c b/src/video/win32/SDL_win32events.c index 1ea7e6c10..98affcc3c 100755 --- a/src/video/win32/SDL_win32events.c +++ b/src/video/win32/SDL_win32events.c @@ -585,17 +585,4 @@ SDL_UnregisterApp() } } -/* Sets an error message based on GetLastError() */ -void -WIN_SetError(const char *prefix) -{ - TCHAR buffer[1024]; - char *message; - FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, - buffer, SDL_arraysize(buffer), NULL); - message = WIN_StringToUTF8(buffer); - SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ": " : "", message); - SDL_free(message); -} - /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/video/win32/SDL_win32events.h b/src/video/win32/SDL_win32events.h index 8ba8e8ab1..18e880bf4 100644 --- a/src/video/win32/SDL_win32events.h +++ b/src/video/win32/SDL_win32events.h @@ -31,7 +31,6 @@ extern HINSTANCE SDL_Instance; extern LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); extern void WIN_PumpEvents(_THIS); -extern void WIN_SetError(const char *prefix); #endif /* _SDL_win32events_h */ diff --git a/src/video/win32/SDL_win32video.c b/src/video/win32/SDL_win32video.c index c93d4f72e..2c93885e2 100644 --- a/src/video/win32/SDL_win32video.c +++ b/src/video/win32/SDL_win32video.c @@ -28,6 +28,7 @@ #include "../SDL_pixels_c.h" #include "SDL_win32video.h" +#include "SDL_win32clipboard.h" #include "SDL_d3drender.h" #include "SDL_gdirender.h" @@ -35,6 +36,19 @@ static int WIN_VideoInit(_THIS); static void WIN_VideoQuit(_THIS); +/* Sets an error message based on GetLastError() */ +void +WIN_SetError(const char *prefix) +{ + TCHAR buffer[1024]; + char *message; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 0, + buffer, SDL_arraysize(buffer), NULL); + message = WIN_StringToUTF8(buffer); + SDL_SetError("%s%s%s", prefix ? prefix : "", prefix ? ": " : "", message); + SDL_free(message); +} + /* WIN32 driver bootstrap functions */ static int @@ -163,6 +177,10 @@ WIN_CreateDevice(int devindex) device->GL_DeleteContext = WIN_GL_DeleteContext; #endif + device->SetClipboardText = WIN_SetClipboardText; + device->GetClipboardText = WIN_GetClipboardText; + device->HasClipboardText = WIN_HasClipboardText; + device->free = WIN_DeleteDevice; return device; diff --git a/src/video/win32/SDL_win32video.h b/src/video/win32/SDL_win32video.h index 3cfb63219..117999dc9 100644 --- a/src/video/win32/SDL_win32video.h +++ b/src/video/win32/SDL_win32video.h @@ -60,6 +60,7 @@ #define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "ASCII", (char *)S, (SDL_strlen(S)+1)) #define WIN_UTF8ToString(S) SDL_iconv_string("ASCII", "UTF-8", (char *)S, SDL_strlen(S)+1) #endif +extern void WIN_SetError(const char *prefix); /* Private display data */ diff --git a/src/video/win32/SDL_win32window.c b/src/video/win32/SDL_win32window.c index c84d91568..0de0bbeb2 100644 --- a/src/video/win32/SDL_win32window.c +++ b/src/video/win32/SDL_win32window.c @@ -633,8 +633,7 @@ SDL_HelperWindowCreate(void) /* Register the class. */ SDL_HelperWindowClass = RegisterClass(&wce); if (SDL_HelperWindowClass == 0) { - SDL_SetError("Unable to create Helper Window Class: error %d.", - GetLastError()); + WIN_SetError("Unable to create Helper Window Class"); return -1; } @@ -652,8 +651,7 @@ SDL_HelperWindowCreate(void) hInstance, NULL); if (SDL_HelperWindow == NULL) { UnregisterClass(SDL_HelperWindowClassName, hInstance); - SDL_SetError("Unable to create Helper Window: error %d.", - GetLastError()); + WIN_SetError("Unable to create Helper Window"); return -1; } @@ -672,8 +670,7 @@ SDL_HelperWindowDestroy(void) /* Destroy the window. */ if (SDL_HelperWindow != NULL) { if (DestroyWindow(SDL_HelperWindow) == 0) { - SDL_SetError("Unable to destroy Helper Window: error %d.", - GetLastError()); + WIN_SetError("Unable to destroy Helper Window"); return; } SDL_HelperWindow = NULL; @@ -682,8 +679,7 @@ SDL_HelperWindowDestroy(void) /* Unregister the class. */ if (SDL_HelperWindowClass != 0) { if ((UnregisterClass(SDL_HelperWindowClassName, hInstance)) == 0) { - SDL_SetError("Unable to destroy Helper Window Class: error %d.", - GetLastError()); + WIN_SetError("Unable to destroy Helper Window Class"); return; } SDL_HelperWindowClass = 0;