]> git.xonotic.org Git - xonotic/netradiant.git/blob - libs/gtkutil/clipboard.cpp
Revert partially (auto) "reformat code! now the code is only ugly on the *inside*"
[xonotic/netradiant.git] / libs / gtkutil / clipboard.cpp
1 /*
2    Copyright (C) 2001-2006, William Joseph.
3    All Rights Reserved.
4
5    This file is part of GtkRadiant.
6
7    GtkRadiant is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2 of the License, or
10    (at your option) any later version.
11
12    GtkRadiant is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GtkRadiant; if not, write to the Free Software
19    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20  */
21
22 #include "clipboard.h"
23
24 #include "globaldefs.h"
25 #include "stream/memstream.h"
26 #include "stream/textstream.h"
27
28
29 /// \file
30 /// \brief Platform-independent GTK clipboard support.
31 /// \todo Using GDK_SELECTION_CLIPBOARD fails on win32, so we use the win32 API directly for now.
32 #if GDEF_OS_WINDOWS
33
34 const char* c_clipboard_format = "RadiantClippings";
35
36 #include <windows.h>
37
38 void clipboard_copy( ClipboardCopyFunc copy ){
39         BufferOutputStream ostream;
40         copy( ostream );
41
42         bool bClipped = false;
43         UINT nClipboard = ::RegisterClipboardFormat( c_clipboard_format );
44         if ( nClipboard > 0 ) {
45                 if ( ::OpenClipboard( 0 ) ) {
46                         EmptyClipboard();
47                         std::size_t length = ostream.size();
48                         HANDLE h = ::GlobalAlloc( GMEM_ZEROINIT | GMEM_MOVEABLE | GMEM_DDESHARE, length + sizeof( std::size_t ) );
49                         if ( h != 0 ) {
50                                 char *buffer = reinterpret_cast<char*>( ::GlobalLock( h ) );
51                                 *reinterpret_cast<std::size_t*>( buffer ) = length;
52                                 buffer += sizeof( std::size_t );
53                                 memcpy( buffer, ostream.data(), length );
54                                 ::GlobalUnlock( h );
55                                 ::SetClipboardData( nClipboard, h );
56                                 ::CloseClipboard();
57                                 bClipped = true;
58                         }
59                 }
60         }
61
62         if ( !bClipped ) {
63                 globalOutputStream() << "Unable to register Windows clipboard formats, copy/paste between editors will not be possible\n";
64         }
65 }
66
67 void clipboard_paste( ClipboardPasteFunc paste ){
68         UINT nClipboard = ::RegisterClipboardFormat( c_clipboard_format );
69         if ( nClipboard > 0 && ::OpenClipboard( 0 ) ) {
70                 if ( IsClipboardFormatAvailable( nClipboard ) ) {
71                         HANDLE h = ::GetClipboardData( nClipboard );
72                         if ( h ) {
73                                 const char *buffer = reinterpret_cast<const char*>( ::GlobalLock( h ) );
74                                 std::size_t length = *reinterpret_cast<const std::size_t*>( buffer );
75                                 buffer += sizeof( std::size_t );
76                                 BufferInputStream istream( buffer, length );
77                                 paste( istream );
78                                 ::GlobalUnlock( h );
79                         }
80                 }
81                 ::CloseClipboard();
82         }
83 }
84
85 #else
86
87 #include <gtk/gtk.h>
88
89 enum
90 {
91         RADIANT_CLIPPINGS = 23,
92 };
93
94 static char RADIANT_CLIPPINGS_STR[] = "RADIANT_CLIPPINGS";
95
96 static const GtkTargetEntry clipboard_targets[] = {
97         {RADIANT_CLIPPINGS_STR, 0, RADIANT_CLIPPINGS, },
98 };
99
100 static void clipboard_get( GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer data ){
101         std::size_t len = *reinterpret_cast<std::size_t*>( data );
102         const char* buffer = ( len != 0 ) ? reinterpret_cast<const char*>( data ) + sizeof( std::size_t ) : 0;
103
104         GdkAtom type = GDK_NONE;
105         if ( info == clipboard_targets[0].info ) {
106                 type = gdk_atom_intern( clipboard_targets[0].target, FALSE );
107         }
108
109         gtk_selection_data_set( selection_data, type, 8, reinterpret_cast<const guchar*>( buffer ), static_cast<gint>( len ) );
110 }
111
112 static void clipboard_clear( GtkClipboard *clipboard, gpointer data ){
113         delete [] reinterpret_cast<const char*>( data );
114 }
115
116 static void clipboard_received( GtkClipboard *clipboard, GtkSelectionData *data, gpointer user_data ){
117         if ( gtk_selection_data_get_length(data) < 0 ) {
118                 globalErrorStream() << "Error retrieving selection\n";
119         }
120         else if ( strcmp( gdk_atom_name( gtk_selection_data_get_data_type(data) ), clipboard_targets[0].target ) == 0 ) {
121                 BufferInputStream istream( reinterpret_cast<const char*>( gtk_selection_data_get_data(data) ), gtk_selection_data_get_length(data) );
122                 ( *reinterpret_cast<ClipboardPasteFunc*>( user_data ) )( istream );
123         }
124 }
125
126 void clipboard_copy( ClipboardCopyFunc copy ){
127         GtkClipboard* clipboard = gtk_clipboard_get( GDK_SELECTION_CLIPBOARD );
128
129         BufferOutputStream ostream;
130         copy( ostream );
131         std::size_t length = ostream.size();
132         char* data = new char[length + sizeof( std::size_t )];
133         *reinterpret_cast<std::size_t*>( data ) = length;
134         memcpy( data + sizeof( std::size_t ), ostream.data(), length );
135
136         gtk_clipboard_set_with_data( clipboard, clipboard_targets, 1, clipboard_get, clipboard_clear, data );
137 }
138
139 ClipboardPasteFunc g_clipboardPasteFunc = 0;
140 void clipboard_paste( ClipboardPasteFunc paste ){
141         GtkClipboard* clipboard = gtk_clipboard_get( GDK_SELECTION_CLIPBOARD );
142
143         g_clipboardPasteFunc = paste;
144         gtk_clipboard_request_contents( clipboard, gdk_atom_intern( clipboard_targets[0].target, FALSE ), clipboard_received, &g_clipboardPasteFunc );
145 }
146
147
148 #endif