/* Copyright (C) 2001-2006, William Joseph. All Rights Reserved. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant 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 General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "clipboard.h" #include "stream/memstream.h" #include "stream/textstream.h" /// \file /// \brief Platform-independent GTK clipboard support. /// \todo Using GDK_SELECTION_CLIPBOARD fails on win32, so we use the win32 API directly for now. #if defined(WIN32) const char* c_clipboard_format = "RadiantClippings"; #include void clipboard_copy(ClipboardCopyFunc copy) { BufferOutputStream ostream; copy(ostream); bool bClipped = false; UINT nClipboard = ::RegisterClipboardFormat(c_clipboard_format); if (nClipboard > 0) { if (::OpenClipboard(0)) { EmptyClipboard(); std::size_t length = ostream.size(); HANDLE h = ::GlobalAlloc(GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, length + sizeof(std::size_t)); if (h != 0) { char *buffer = reinterpret_cast(::GlobalLock(h)); *reinterpret_cast(buffer) = length; buffer += sizeof(std::size_t); memcpy(buffer, ostream.data(), length); ::GlobalUnlock(h); ::SetClipboardData(nClipboard, h); ::CloseClipboard(); bClipped = true; } } } if (!bClipped) { globalOutputStream() << "Unable to register Windows clipboard formats, copy/paste between editors will not be possible\n"; } } void clipboard_paste(ClipboardPasteFunc paste) { UINT nClipboard = ::RegisterClipboardFormat(c_clipboard_format); if (nClipboard > 0 && ::OpenClipboard(0)) { if(IsClipboardFormatAvailable(nClipboard)) { HANDLE h = ::GetClipboardData(nClipboard); if(h) { const char *buffer = reinterpret_cast(::GlobalLock(h)); std::size_t length = *reinterpret_cast(buffer); buffer += sizeof(std::size_t); BufferInputStream istream(buffer, length); paste(istream); ::GlobalUnlock(h); } } ::CloseClipboard(); } } #else #include enum { RADIANT_CLIPPINGS = 23, }; static const GtkTargetEntry clipboard_targets[] = { { "RADIANT_CLIPPINGS", 0, RADIANT_CLIPPINGS, }, }; static void clipboard_get (GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data) { std::size_t len = *reinterpret_cast(data); const char* buffer = (len != 0) ? reinterpret_cast(data) + sizeof(std::size_t) : 0; GdkAtom type = GDK_NONE; if(info == clipboard_targets[0].info) { type = gdk_atom_intern(clipboard_targets[0].target, FALSE); } gtk_selection_data_set (selection_data, type, 8, reinterpret_cast(buffer), static_cast(len)); } static void clipboard_clear (GtkClipboard *clipboard, gpointer data) { delete [] reinterpret_cast(data); } static void clipboard_received (GtkClipboard *clipboard, GtkSelectionData *data, gpointer user_data) { if (data->length < 0) { globalErrorStream() << "Error retrieving selection\n"; } else if(strcmp(gdk_atom_name(data->type), clipboard_targets[0].target) == 0) { BufferInputStream istream(reinterpret_cast(data->data), data->length); (*reinterpret_cast(user_data))(istream); } } void clipboard_copy(ClipboardCopyFunc copy) { GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); BufferOutputStream ostream; copy(ostream); std::size_t length = ostream.size(); char* data = new char[length + sizeof(std::size_t)]; *reinterpret_cast(data) = length; memcpy(data + sizeof(std::size_t), ostream.data(), length); gtk_clipboard_set_with_data (clipboard, clipboard_targets, 1, clipboard_get, clipboard_clear, data); } ClipboardPasteFunc g_clipboardPasteFunc = 0; void clipboard_paste(ClipboardPasteFunc paste) { GtkClipboard* clipboard = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); g_clipboardPasteFunc = paste; gtk_clipboard_request_contents (clipboard, gdk_atom_intern(clipboard_targets[0].target, FALSE), clipboard_received, &g_clipboardPasteFunc); } #endif