]> git.saurik.com Git - wxWidgets.git/blame - src/motif/clipbrd.cpp
fixed memory leak in RestoreState
[wxWidgets.git] / src / motif / clipbrd.cpp
CommitLineData
4bb6408c 1/////////////////////////////////////////////////////////////////////////////
55034339 2// Name: src/motif/clipbrd.cpp
4bb6408c
JS
3// Purpose: Clipboard functionality
4// Author: Julian Smart
dd38c875 5// Modified by: Mattia Barbon (added support for generic wxDataObjects)
4bb6408c
JS
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
55034339 9// Licence: wxWindows licence
4bb6408c
JS
10/////////////////////////////////////////////////////////////////////////////
11
1248b41f
MB
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
14
c698eae5
JJ
15#ifdef __VMS
16#include "wx/vms_x_fix.h"
17#define XtWindow XTWINDOW
18#define XtScreen XTSCREEN
19#define XtParent XTPARENT
20#define XtIsRealized XTISREALIZED
21#define XtDisplay XTDISPLAY
22#endif
23
dfe1eee3
VZ
24#if wxUSE_CLIPBOARD
25
670f9935
WS
26#include "wx/clipbrd.h"
27
28#ifndef WX_PRECOMP
29 #include "wx/app.h"
de6185e2 30 #include "wx/utils.h"
0bca0373 31 #include "wx/bitmap.h"
28f92d74 32 #include "wx/dataobj.h"
670f9935
WS
33#endif
34
dd38c875 35#include "wx/ptr_scpd.h"
2d120f83 36
338dd992
JJ
37#ifdef __VMS__
38#pragma message disable nosimpint
c698eae5 39
338dd992 40#endif
2d120f83
JS
41#include <Xm/Xm.h>
42#include <Xm/CutPaste.h>
338dd992
JJ
43#ifdef __VMS__
44#pragma message enable nosimpint
45#endif
4bb6408c 46
dd38c875 47#include "wx/motif/private.h"
2d120f83 48
4bb6408c
JS
49bool wxOpenClipboard()
50{
dd38c875 51 return wxTheClipboard->Open();
4bb6408c
JS
52}
53
54bool wxCloseClipboard()
55{
dd38c875
MB
56 wxTheClipboard->Close();
57
58 return true;
4bb6408c
JS
59}
60
61bool wxEmptyClipboard()
62{
dd38c875
MB
63 wxTheClipboard->Clear();
64 return true;
4bb6408c
JS
65}
66
67bool wxClipboardOpen()
68{
dd38c875 69 return wxTheClipboard->IsOpened();
4bb6408c
JS
70}
71
fbfb8bcc 72bool wxIsClipboardFormatAvailable(const wxDataFormat& dataFormat)
4bb6408c 73{
dd38c875
MB
74 return wxTheClipboard->IsSupported( dataFormat );
75}
2d120f83 76
dd38c875
MB
77bool wxSetClipboardData(wxDataFormat dataFormat, wxObject *obj,
78 int WXUNUSED(width), int WXUNUSED(height))
79{
80 wxDataObject* dobj = NULL;
2d120f83 81
dd38c875
MB
82 if( dataFormat == wxDF_TEXT )
83 {
84 wxChar* data = (wxChar*)obj;
85 dobj = new wxTextDataObject( data );
86 }
87 else if( dataFormat = wxDF_BITMAP )
88 {
89 wxBitmap* data = (wxBitmap*)obj;
90 dobj = new wxBitmapDataObject( *data );
91 }
2d120f83 92
dd38c875
MB
93 if( !dobj )
94 return false;
4bb6408c 95
dd38c875 96 return wxTheClipboard->SetData( dobj );
4bb6408c
JS
97}
98
2d120f83 99wxObject *wxGetClipboardData(wxDataFormat dataFormat, long *len)
4bb6408c 100{
dd38c875
MB
101 wxDataObject* dobj = NULL;
102 wxTextDataObject* tobj = NULL;
103 wxBitmapDataObject* bobj = NULL;
2d120f83 104
dd38c875
MB
105 if( dataFormat == wxDF_TEXT )
106 {
107 dobj = tobj = new wxTextDataObject;
108 }
109 else if( dataFormat = wxDF_BITMAP )
110 {
111 dobj = bobj = new wxBitmapDataObject;
112 }
2d120f83 113
dd38c875
MB
114 if( !dobj || !wxTheClipboard->GetData( *dobj ) )
115 return NULL;
2d120f83 116
dd38c875 117 if( tobj )
2d120f83 118 {
dd38c875
MB
119 wxString text = tobj->GetText();
120 wxChar* buf = new wxChar[text.length() + 1];
121
122 if( len ) *len = text.length();
123 return (wxObject*)wxStrcpy( buf, text.c_str() );
124 }
125 else if( bobj )
126 {
127 if( len ) *len = 0;
128 return new wxBitmap( bobj->GetBitmap() );
2d120f83
JS
129 }
130
dd38c875 131 return NULL; // just in case...
4bb6408c
JS
132}
133
fbfb8bcc 134wxDataFormat wxEnumClipboardFormats(const wxDataFormat& dataFormat)
4bb6408c 135{
2d120f83 136 // Only wxDF_TEXT supported
da175b2c 137 if (dataFormat == wxDF_TEXT)
2d120f83
JS
138 return wxDF_TEXT;
139 else
da175b2c 140 return wxDF_INVALID;
4bb6408c
JS
141}
142
dd38c875 143wxDataFormat wxRegisterClipboardFormat(char *WXUNUSED(formatName))
4bb6408c 144{
2d120f83 145 // Not supported
dd38c875 146 return wxDF_INVALID;
4bb6408c
JS
147}
148
fbfb8bcc 149bool wxGetClipboardFormatName(const wxDataFormat& dataFormat, char *formatName,
dd38c875 150 int maxCount)
4bb6408c 151{
dd38c875
MB
152 wxStrncpy( formatName, dataFormat.GetId().c_str(), maxCount );
153
154 return true;
4bb6408c
JS
155}
156
2d120f83
JS
157//-----------------------------------------------------------------------------
158// wxClipboard
159//-----------------------------------------------------------------------------
4bb6408c 160
47be989f
MB
161struct wxDataIdToDataObject
162{
163 wxDataIdToDataObject( wxDataObject* o, long d, size_t s )
164 : object( o ), size( s ), dataId( d ) { }
165
166 wxDataObject* object;
167 size_t size;
168 long dataId;
169};
170
171#include "wx/listimpl.cpp"
172
e933b5bc
VZ
173WX_DEFINE_LIST(wxDataObjectList)
174WX_DEFINE_LIST(wxDataIdToDataObjectList)
47be989f 175
a13acfd8
VZ
176extern "C"
177{
f332a5a0
MB
178#if wxCHECK_LESSTIF()
179static void wxClipboardCallback( Widget widget, int* data_id,
180 int* priv, int* reason );
a13acfd8 181#else // Motif
47be989f
MB
182static void wxClipboardCallback( Widget widget, long* data_id,
183 long* priv, int* reason );
a13acfd8
VZ
184#endif // Less/Motif
185}
47be989f 186
2d120f83 187IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
4bb6408c 188
4bb6408c
JS
189wxClipboard::wxClipboard()
190{
dd38c875 191 m_open = false;
4bb6408c
JS
192}
193
194wxClipboard::~wxClipboard()
195{
55034339 196 Clear();
4bb6408c
JS
197}
198
2d120f83 199void wxClipboard::Clear()
4bb6408c 200{
ac32ba44 201 wxDataObjectList::compatibility_iterator node = m_data.GetFirst();
2d120f83
JS
202 while (node)
203 {
47be989f 204 delete node->GetData();
fd304d98 205 node = node->GetNext();
2d120f83
JS
206 }
207 m_data.Clear();
47be989f 208
ac32ba44 209 for( wxDataIdToDataObjectList::compatibility_iterator node2 = m_idToObject.GetFirst();
47be989f 210 node2; node2 = node2->GetNext() )
fa41b170
MB
211 {
212 delete node2->GetData();
213 }
47be989f 214 m_idToObject.Clear();
4bb6408c
JS
215}
216
2d120f83 217bool wxClipboard::Open()
4bb6408c 218{
dd38c875 219 wxCHECK_MSG( !m_open, false, "clipboard already open" );
55034339 220
dd38c875 221 m_open = true;
4bb6408c 222
dd38c875 223 return true;
2d120f83 224}
4bb6408c 225
2d120f83
JS
226bool wxClipboard::SetData( wxDataObject *data )
227{
dd38c875
MB
228 wxCHECK_MSG( data, false, "data is invalid" );
229 wxCHECK_MSG( m_open, false, "clipboard not open" );
2d120f83 230
12db77ca
VZ
231 Clear();
232
233 return AddData( data );
234}
235
e933b5bc
VZ
236wxDECLARE_SCOPED_ARRAY( wxDataFormat, wxDataFormatScopedArray )
237wxDEFINE_SCOPED_ARRAY( wxDataFormat, wxDataFormatScopedArray )
dd38c875 238
f332a5a0
MB
239#if wxCHECK_LESSTIF()
240void wxClipboardCallback( Widget xwidget, int* data_id,
55034339 241 int* priv, int* WXUNUSED(reason) )
f332a5a0 242#else
47be989f 243void wxClipboardCallback( Widget xwidget, long* data_id,
55034339 244 long* priv, int* WXUNUSED(reason) )
f332a5a0 245#endif
47be989f
MB
246{
247 Display* xdisplay = XtDisplay( xwidget );
248 Window xwindow = XtWindow( xwidget );
249 wxDataObject* dobj = NULL;
250 size_t size = 0;
251
ac32ba44 252 for( wxDataIdToDataObjectList::compatibility_iterator node2 =
47be989f
MB
253 wxTheClipboard->m_idToObject.GetFirst();
254 node2; node2 = node2->GetNext() )
255 {
256 wxDataIdToDataObject* dido = node2->GetData();
257 if( dido->dataId == *data_id )
258 {
259 dobj = dido->object;
260 size = dido->size;
261 break;
262 }
263 }
264
265 if( !dobj ) return;
266
267 wxCharBuffer buffer(size);
268 size_t count = dobj->GetFormatCount( wxDataObject::Get );
269 wxDataFormatScopedArray dfarr( new wxDataFormat[count] );
270 dobj->GetAllFormats( dfarr.get(), wxDataObject::Get );
271
272 if( !dobj->GetDataHere( dfarr[*priv], buffer.data() ) )
273 return;
274
275 while( XmClipboardCopyByName( xdisplay, xwindow, *data_id,
276 buffer.data(), size, 0 )
277 == XmClipboardLocked );
278}
279
12db77ca
VZ
280bool wxClipboard::AddData( wxDataObject *data )
281{
dd38c875
MB
282 wxCHECK_MSG( data, false, "data is invalid" );
283 wxCHECK_MSG( m_open, false, "clipboard not open" );
284
285 m_data.Append( data );
286
287 Display* xdisplay = wxGlobalDisplay();
5a2e3d8c 288 Widget xwidget = (Widget)wxTheApp->GetTopLevelRealizedWidget();
47be989f 289 Window xwindow = XtWindow( xwidget );
dd38c875
MB
290 wxXmString label( wxTheApp->GetAppName() );
291 Time timestamp = XtLastTimestampProcessed( xdisplay );
292 long itemId;
293
294 int retval;
12db77ca 295
dd38c875 296 while( ( retval = XmClipboardStartCopy( xdisplay, xwindow, label(),
47be989f
MB
297 timestamp, xwidget,
298 wxClipboardCallback,
dd38c875
MB
299 &itemId ) )
300 == XmClipboardLocked );
301 if( retval != XmClipboardSuccess )
302 return false;
303
304 size_t count = data->GetFormatCount( wxDataObject::Get );
305 wxDataFormatScopedArray dfarr( new wxDataFormat[count] );
306 data->GetAllFormats( dfarr.get(), wxDataObject::Get );
307
308 for( size_t i = 0; i < count; ++i )
2d120f83 309 {
dd38c875 310 size_t size = data->GetDataSize( dfarr[i] );
47be989f 311 long data_id;
dd38c875
MB
312 wxString id = dfarr[i].GetId();
313
314 while( ( retval = XmClipboardCopy( xdisplay, xwindow, itemId,
6991087b 315 id.char_str(),
47be989f 316 NULL, size, i, &data_id ) )
dd38c875 317 == XmClipboardLocked );
47be989f
MB
318
319 m_idToObject.Append( new wxDataIdToDataObject( data, data_id, size ) );
2d120f83 320 }
dd38c875
MB
321
322 while( XmClipboardEndCopy( xdisplay, xwindow, itemId )
323 == XmClipboardLocked );
324
325 return true;
2d120f83 326}
4bb6408c 327
2d120f83
JS
328void wxClipboard::Close()
329{
330 wxCHECK_RET( m_open, "clipboard not open" );
55034339 331
dd38c875 332 m_open = false;
4bb6408c
JS
333}
334
dd38c875 335bool wxClipboard::IsSupported(const wxDataFormat& format)
4bb6408c 336{
dd38c875 337 Display* xdisplay = wxGlobalDisplay();
5a2e3d8c 338 Window xwindow = XtWindow( (Widget)wxTheApp->GetTopLevelRealizedWidget() );
dd38c875
MB
339 bool isSupported = false;
340 int retval, count;
341 unsigned long max_name_length;
342 wxString id = format.GetId();
343
344 while( ( retval = XmClipboardLock( xdisplay, xwindow ) )
345 == XmClipboardLocked );
346 if( retval != XmClipboardSuccess )
347 return false;
348
349 if( XmClipboardInquireCount( xdisplay, xwindow, &count, &max_name_length )
350 == XmClipboardSuccess )
2d120f83 351 {
dd38c875
MB
352 wxCharBuffer buf( max_name_length + 1 );
353 unsigned long copied;
354
355 for( int i = 0; i < count; ++i )
2d120f83 356 {
dd38c875
MB
357 if( XmClipboardInquireFormat( xdisplay, xwindow, i + 1,
358 (XtPointer)buf.data(),
359 max_name_length, &copied )
360 != XmClipboardSuccess )
361 continue;
362
363 buf.data()[copied] = '\0';
364
365 if( buf == id )
2d120f83 366 {
dd38c875
MB
367 isSupported = true;
368 break;
2d120f83 369 }
2d120f83
JS
370 }
371 }
4bb6408c 372
dd38c875 373 XmClipboardUnlock( xdisplay, xwindow, False );
2d120f83 374
dd38c875 375 return isSupported;
2d120f83 376}
4bb6408c 377
dd38c875 378class wxClipboardEndRetrieve
2d120f83 379{
dd38c875
MB
380public:
381 wxClipboardEndRetrieve( Display* display, Window window )
382 : m_display( display ), m_window( window ) { }
383 ~wxClipboardEndRetrieve()
384 {
385 while( XmClipboardEndRetrieve( m_display, m_window )
386 == XmClipboardLocked );
387 }
388private:
389 Display* m_display;
390 Window m_window;
391};
2d120f83 392
dd38c875 393bool wxClipboard::GetData( wxDataObject& data )
4bb6408c 394{
dd38c875
MB
395 wxCHECK_MSG( m_open, false, "clipboard not open" );
396
397 Display* xdisplay = wxGlobalDisplay();
5a2e3d8c 398 Window xwindow = XtWindow( (Widget)wxTheApp->GetTopLevelRealizedWidget() );
dd38c875
MB
399 Time timestamp = XtLastTimestampProcessed( xdisplay );
400
401 wxDataFormat chosenFormat;
402 int retval;
403
404 ///////////////////////////////////////////////////////////////////////////
405 // determine if the cliboard holds any format we like
406 ///////////////////////////////////////////////////////////////////////////
407 while( ( retval = XmClipboardStartRetrieve( xdisplay, xwindow,
408 timestamp ) )
409 == XmClipboardLocked );
410 if( retval != XmClipboardSuccess )
411 return false;
412
413 wxClipboardEndRetrieve endRetrieve( xdisplay, xwindow );
414
415 int count;
416 unsigned long max_name_length;
417 size_t dfcount = data.GetFormatCount( wxDataObject::Set );
418 wxDataFormatScopedArray dfarr( new wxDataFormat[dfcount] );
419 data.GetAllFormats( dfarr.get(), wxDataObject::Set );
55034339 420
dd38c875
MB
421 if( XmClipboardInquireCount( xdisplay, xwindow, &count, &max_name_length )
422 == XmClipboardSuccess )
423 {
424 wxCharBuffer buf( max_name_length + 1 );
425 unsigned long copied;
4bb6408c 426
dd38c875
MB
427 for( int i = 0; i < count; ++i )
428 {
429 if( XmClipboardInquireFormat( xdisplay, xwindow, i + 1,
430 (XtPointer)buf.data(),
431 max_name_length, &copied )
432 != XmClipboardSuccess )
433 continue;
4bb6408c 434
dd38c875 435 buf.data()[copied] = '\0';
4bb6408c 436
dd38c875
MB
437 // try preferred format
438 if( buf == data.GetPreferredFormat( wxDataObject::Set ).GetId() )
439 {
440 chosenFormat = data.GetPreferredFormat( wxDataObject::Set );
441 break;
442 }
2d120f83 443
dd38c875
MB
444 // try all other formats
445 for( size_t i = 0; i < dfcount; ++i )
446 {
447 if( buf == dfarr[i].GetId() )
448 chosenFormat = dfarr[i];
449 }
450 }
2d120f83 451 }
4bb6408c 452
dd38c875
MB
453 if( chosenFormat == wxDF_INVALID )
454 return false;
455
456 ///////////////////////////////////////////////////////////////////////////
457 // now retrieve the data
458 ///////////////////////////////////////////////////////////////////////////
459 unsigned long length, dummy1;
460 long dummy2;
461 wxString id = chosenFormat.GetId();
462
463 while( ( retval = XmClipboardInquireLength( xdisplay, xwindow,
6991087b 464 id.char_str(),
dd38c875
MB
465 &length ) )
466 == XmClipboardLocked );
467 if( retval != XmClipboardSuccess )
468 return false;
469
470 wxCharBuffer buf(length);
471
472 while( ( retval = XmClipboardRetrieve( xdisplay, xwindow,
6991087b 473 id.char_str(),
dd38c875
MB
474 (XtPointer)buf.data(),
475 length, &dummy1, &dummy2 ) )
476 == XmClipboardLocked );
477 if( retval != XmClipboardSuccess )
478 return false;
479
480 if( !data.SetData( chosenFormat, length, buf.data() ) )
481 return false;
482
483 return true;
4bb6408c
JS
484}
485
dfe1eee3 486#endif // wxUSE_CLIPBOARD