]> git.saurik.com Git - wxWidgets.git/blame - src/gtk1/clipbrd.cpp
some very minor changes
[wxWidgets.git] / src / gtk1 / clipbrd.cpp
CommitLineData
dc86cb34
RR
1/////////////////////////////////////////////////////////////////////////////
2// Name: clipbrd.cpp
3// Purpose:
4// Author: Robert Roebling
5// Id: $Id$
6// Copyright: (c) 1998 Robert Roebling
7// Licence: wxWindows licence
8/////////////////////////////////////////////////////////////////////////////
9
10#ifdef __GNUG__
11#pragma implementation "clipbrd.h"
12#endif
13
14#include "wx/clipbrd.h"
15
16//-----------------------------------------------------------------------------
17// data
18//-----------------------------------------------------------------------------
19
20wxClipboard *wxTheClipboard = (wxClipboard*) NULL;
21
fd0eed64
RR
22GdkAtom g_textAtom = 0;
23GdkAtom g_clipboardAtom = 0;
b527aac5 24GdkAtom g_targetsAtom = 0;
fd0eed64 25
dc86cb34 26//-----------------------------------------------------------------------------
b527aac5 27// reminder
dc86cb34
RR
28//-----------------------------------------------------------------------------
29
b527aac5
RR
30/* The contents of a selection are returned in a GtkSelectionData
31 structure. selection/target identify the request.
32 type specifies the type of the return; if length < 0, and
33 the data should be ignored. This structure has object semantics -
34 no fields should be modified directly, they should not be created
35 directly, and pointers to them should not be stored beyond the duration of
36 a callback. (If the last is changed, we'll need to add reference
37 counting)
38
39struct _GtkSelectionData
dc86cb34 40{
b527aac5
RR
41 GdkAtom selection;
42 GdkAtom target;
43 GdkAtom type;
44 gint format;
45 guchar *data;
46 gint length;
47};
48
49*/
dc86cb34 50
b527aac5
RR
51//-----------------------------------------------------------------------------
52// "selection_received" for targets
53//-----------------------------------------------------------------------------
54
55static void
56targets_selection_received( GtkWidget *WXUNUSED(widget),
57 GtkSelectionData *selection_data,
58 wxClipboard *clipboard )
dc86cb34 59{
b527aac5
RR
60 if (!wxTheClipboard) return;
61
62 if (selection_data->length <= 0) return;
63
64 // make sure we got the data in the correct form
65 if (selection_data->type != GDK_SELECTION_TYPE_ATOM) return;
66
67 // the atoms we received, holding a list of targets (= formats)
68 GdkAtom *atoms = (GdkAtom *)selection_data->data;
69
70 for (unsigned int i=0; i<selection_data->length/sizeof(GdkAtom); i++)
71 {
72 if (atoms[i] == clipboard->m_targetRequested)
73 {
74 clipboard->m_formatSupported = TRUE;
75 return;
76 }
77 }
78
79 return;
dc86cb34
RR
80}
81
82//-----------------------------------------------------------------------------
b527aac5 83// "selection_received" for the actual data
dc86cb34
RR
84//-----------------------------------------------------------------------------
85
fd0eed64 86static void
b527aac5
RR
87selection_received( GtkWidget *WXUNUSED(widget),
88 GtkSelectionData *selection_data,
89 wxClipboard *clipboard )
dc86cb34 90{
b527aac5
RR
91 if (!wxTheClipboard) return;
92
93 if (selection_data->length <= 0) return;
94
95 size_t size = (size_t) selection_data->length;
96
97 // make sure we got the data in the correct form
98 if (selection_data->type != GDK_SELECTION_TYPE_STRING) return;
99
100 clipboard->m_receivedSize = size;
101
102 clipboard->m_receivedData = new char[size+1];
103
104 memcpy( clipboard->m_receivedData, selection_data->data, size);
dc86cb34 105}
fd0eed64
RR
106
107//-----------------------------------------------------------------------------
108// "selection_clear"
109//-----------------------------------------------------------------------------
110
111static gint
b527aac5 112selection_clear( GtkWidget *WXUNUSED(widget), GdkEventSelection *WXUNUSED(event) )
fd0eed64 113{
fd0eed64
RR
114 if (!wxTheClipboard) return TRUE;
115
b527aac5
RR
116 /* the clipboard is no longer in our hands. we can delete the
117 * clipboard data. I hope I got that one right... */
118
fd0eed64
RR
119 wxTheClipboard->SetData( (wxDataObject*) NULL );
120
121 return TRUE;
122}
123
124//-----------------------------------------------------------------------------
125// selection handler for supplying data
126//-----------------------------------------------------------------------------
127
128static void
129selection_handler( GtkWidget *WXUNUSED(widget), GtkSelectionData *selection_data, gpointer WXUNUSED(data) )
130{
131 if (!wxTheClipboard) return;
132
133 wxDataObject *data_object = wxTheClipboard->m_data;
134
135 if (!data_object) return;
136
db1b4961
RR
137 if (data_object->GetDataSize() == 0) return;
138
139
fd0eed64
RR
140
141 gint len = data_object->GetDataSize();
142 guchar *bin_data = (guchar*) malloc( len );
143 data_object->GetDataHere( (void*)bin_data );
144
db1b4961 145 if (selection_data->target == GDK_TARGET_STRING)
fd0eed64
RR
146 {
147 gtk_selection_data_set(
148 selection_data, GDK_SELECTION_TYPE_STRING, 8*sizeof(gchar), bin_data, len );
149 }
db1b4961 150/*
fd0eed64
RR
151 else if (selection_data->target == g_textAtom)
152 {
153 gtk_selection_data_set(
154 selection_data, g_textAtom, 8*sizeof(gchar), bin_data, len );
155 }
db1b4961 156*/
fd0eed64
RR
157 free( bin_data );
158}
dc86cb34
RR
159
160//-----------------------------------------------------------------------------
161// wxClipboard
162//-----------------------------------------------------------------------------
163
164IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
165
166wxClipboard::wxClipboard()
167{
fd0eed64 168 m_data = (wxDataObject*) NULL;
fd0eed64 169
99c67c77
RR
170 m_clipboardWidget = gtk_window_new( GTK_WINDOW_POPUP );
171 gtk_widget_realize( m_clipboardWidget );
172
fd0eed64
RR
173 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
174 "selection_clear_event",
175 GTK_SIGNAL_FUNC( selection_clear ),
176 (gpointer) NULL );
177
178 if (!g_clipboardAtom) g_clipboardAtom = gdk_atom_intern( "CLIPBOARD", FALSE );
179 if (!g_textAtom) g_textAtom = gdk_atom_intern( "TEXT", FALSE );
b527aac5
RR
180 if (!g_targetsAtom) g_targetsAtom = gdk_atom_intern ("TARGETS", FALSE);
181
182 m_receivedData = (char*)NULL;
183 m_receivedSize = 0;
184 m_formatSupported = FALSE;
185 m_targetRequested = 0;
dc86cb34
RR
186}
187
188wxClipboard::~wxClipboard()
b527aac5
RR
189{
190 Clear();
191
192 if (m_clipboardWidget) gtk_widget_destroy( m_clipboardWidget );
193}
194
195void wxClipboard::Clear()
dc86cb34 196{
fd0eed64
RR
197 /* As we have data we also own the clipboard. Once we no longer own
198 it, clear_selection is called which will set m_data to zero */
199
200 if (m_data)
201 {
db1b4961
RR
202 if (gdk_selection_owner_get( g_clipboardAtom) == m_clipboardWidget->window)
203 {
204 gtk_selection_owner_set( (GtkWidget*) NULL, g_clipboardAtom, GDK_CURRENT_TIME );
205 }
206
fd0eed64 207 delete m_data;
db1b4961 208 m_data = (wxDataObject*) NULL;
fd0eed64 209 }
b527aac5
RR
210
211 m_receivedSize = 0;
212
213 if (m_receivedData)
214 {
215 delete[] m_receivedData;
216 m_receivedData = (char*) NULL;
217 }
218
219 m_targetRequested = 0;
220
221 m_formatSupported = FALSE;
dc86cb34
RR
222}
223
224void wxClipboard::SetData( wxDataObject *data )
225{
db1b4961
RR
226 Clear();
227
228/*
229 GTK 1.0.X cannot remove a target from a widget so if a widget
230 at first offers text and then a bitmap (and no longer text) to
231 the clipboard, we seem too have to delete it.
232*/
233
234 if (m_clipboardWidget) gtk_widget_destroy( m_clipboardWidget );
235
236 m_clipboardWidget = gtk_window_new( GTK_WINDOW_POPUP );
237 gtk_widget_realize( m_clipboardWidget );
238
dc86cb34
RR
239 if (m_data) delete m_data;
240 m_data = data;
fd0eed64
RR
241 if (!m_data) return;
242
243 if (!gtk_selection_owner_set( m_clipboardWidget,
244 g_clipboardAtom,
245 GDK_CURRENT_TIME))
246 {
247 delete m_data;
248 m_data = (wxDataObject*) NULL;
249 return;
250 }
251
252 switch (m_data->GetPreferredFormat())
253 {
fd0eed64
RR
254 case wxDF_TEXT:
255 gtk_selection_add_handler( m_clipboardWidget,
256 g_clipboardAtom,
db1b4961
RR
257 // g_textAtom,
258 GDK_TARGET_STRING,
fd0eed64
RR
259 selection_handler,
260 NULL );
261 break;
262 default:
263 break;
264 }
dc86cb34
RR
265}
266
b527aac5
RR
267bool wxClipboard::IsSupportedFormat( wxDataFormat format )
268{
269 m_targetRequested = 0;
270
271 if (format == wxDF_TEXT)
272 {
273// m_targetRequested = g_textAtom;
274 m_targetRequested = GDK_TARGET_STRING;
275 }
276
277 if (m_targetRequested == 0) return FALSE;
278
279 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
280 "selection_received",
281 GTK_SIGNAL_FUNC( targets_selection_received ),
282 (gpointer) this );
283
284 m_formatSupported = FALSE;
285
286 gtk_selection_convert( m_clipboardWidget,
287 g_clipboardAtom,
288 g_targetsAtom,
289 GDK_CURRENT_TIME );
290
291 gtk_signal_disconnect_by_func( GTK_OBJECT(m_clipboardWidget),
292 GTK_SIGNAL_FUNC( targets_selection_received ),
293 (gpointer) this );
294
295 if (!m_formatSupported) return FALSE;
296
297 return TRUE;
298}
299
300bool wxClipboard::ObtainData( wxDataFormat format )
dc86cb34 301{
b527aac5
RR
302 m_receivedSize = 0;
303
304 if (m_receivedData)
dc86cb34 305 {
b527aac5
RR
306 delete[] m_receivedData;
307 m_receivedData = (char*) NULL;
dc86cb34 308 }
b527aac5
RR
309
310 m_targetRequested = 0;
311
312 if (format == wxDF_TEXT)
313 {
314// m_targetRequested = g_textAtom;
315 m_targetRequested = GDK_TARGET_STRING;
316 }
317
318 if (m_targetRequested == 0) return FALSE;
319
320 gtk_signal_connect( GTK_OBJECT(m_clipboardWidget),
321 "selection_received",
322 GTK_SIGNAL_FUNC( selection_received ),
323 (gpointer) this );
324
325 gtk_selection_convert( m_clipboardWidget,
326 g_clipboardAtom,
327 m_targetRequested,
328 GDK_CURRENT_TIME );
329
330 gtk_signal_disconnect_by_func( GTK_OBJECT(m_clipboardWidget),
331 GTK_SIGNAL_FUNC( selection_received ),
332 (gpointer) this );
333
334 if (m_receivedSize == 0) return FALSE;
335
336 return TRUE;
337}
338
339size_t wxClipboard::GetDataSize() const
340{
341 return m_receivedSize;
342}
343
344void wxClipboard::GetDataHere( void *data ) const
345{
346 memcpy(data, m_receivedData, m_receivedSize );
dc86cb34
RR
347}
348
b527aac5
RR
349//-----------------------------------------------------------------------------
350// wxClipboardModule
351//-----------------------------------------------------------------------------
352
353IMPLEMENT_DYNAMIC_CLASS(wxClipboardModule,wxModule)
354
355bool wxClipboardModule::OnInit()
356{
357 wxTheClipboard = new wxClipboard();
358
359 return TRUE;
360}
361
362void wxClipboardModule::OnExit()
dc86cb34 363{
b527aac5
RR
364 if (wxTheClipboard) delete wxTheClipboard;
365 wxTheClipboard = (wxClipboard*) NULL;
dc86cb34 366}