]> git.saurik.com Git - wxWidgets.git/blame - src/motif/clipbrd.cpp
libpng vulnerability CAN-2004-0421
[wxWidgets.git] / src / motif / clipbrd.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: clipbrd.cpp
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
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
14f355c2 12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
4bb6408c
JS
13#pragma implementation
14#pragma implementation "clipbrd.h"
15#endif
16
c698eae5
JJ
17#ifdef __VMS
18#include "wx/vms_x_fix.h"
19#define XtWindow XTWINDOW
20#define XtScreen XTSCREEN
21#define XtParent XTPARENT
22#define XtIsRealized XTISREALIZED
23#define XtDisplay XTDISPLAY
24#endif
25
dfe1eee3
VZ
26#include "wx/defs.h"
27
28#if wxUSE_CLIPBOARD
29
4bb6408c 30#include "wx/app.h"
4bb6408c
JS
31#include "wx/bitmap.h"
32#include "wx/utils.h"
4bb6408c 33#include "wx/clipbrd.h"
2d120f83 34#include "wx/dataobj.h"
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
2d120f83 72bool wxIsClipboardFormatAvailable(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
dd38c875 134wxDataFormat wxEnumClipboardFormats(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
dd38c875
MB
149bool wxGetClipboardFormatName(wxDataFormat dataFormat, char *formatName,
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
173WX_DEFINE_LIST(wxDataObjectList);
174WX_DEFINE_LIST(wxDataIdToDataObjectList);
175
f332a5a0
MB
176#if wxCHECK_LESSTIF()
177static void wxClipboardCallback( Widget widget, int* data_id,
178 int* priv, int* reason );
179#else
47be989f
MB
180static void wxClipboardCallback( Widget widget, long* data_id,
181 long* priv, int* reason );
f332a5a0 182#endif
47be989f 183
2d120f83 184IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
4bb6408c 185
4bb6408c
JS
186wxClipboard::wxClipboard()
187{
dd38c875 188 m_open = false;
4bb6408c
JS
189}
190
191wxClipboard::~wxClipboard()
192{
2d120f83 193 Clear();
4bb6408c
JS
194}
195
2d120f83 196void wxClipboard::Clear()
4bb6408c 197{
ac32ba44 198 wxDataObjectList::compatibility_iterator node = m_data.GetFirst();
2d120f83
JS
199 while (node)
200 {
47be989f 201 delete node->GetData();
fd304d98 202 node = node->GetNext();
2d120f83
JS
203 }
204 m_data.Clear();
47be989f 205
ac32ba44 206 for( wxDataIdToDataObjectList::compatibility_iterator node2 = m_idToObject.GetFirst();
47be989f
MB
207 node2; node2 = node2->GetNext() )
208 delete node->GetData();
209 m_idToObject.Clear();
4bb6408c
JS
210}
211
2d120f83 212bool wxClipboard::Open()
4bb6408c 213{
dd38c875 214 wxCHECK_MSG( !m_open, false, "clipboard already open" );
2d120f83 215
dd38c875 216 m_open = true;
4bb6408c 217
dd38c875 218 return true;
2d120f83 219}
4bb6408c 220
2d120f83
JS
221bool wxClipboard::SetData( wxDataObject *data )
222{
dd38c875
MB
223 wxCHECK_MSG( data, false, "data is invalid" );
224 wxCHECK_MSG( m_open, false, "clipboard not open" );
2d120f83 225
12db77ca
VZ
226 Clear();
227
228 return AddData( data );
229}
230
dd38c875
MB
231wxDECLARE_SCOPED_ARRAY( wxDataFormat, wxDataFormatScopedArray );
232wxDEFINE_SCOPED_ARRAY( wxDataFormat, wxDataFormatScopedArray );
233
f332a5a0
MB
234#if wxCHECK_LESSTIF()
235void wxClipboardCallback( Widget xwidget, int* data_id,
236 int* priv, int* reason )
237#else
47be989f
MB
238void wxClipboardCallback( Widget xwidget, long* data_id,
239 long* priv, int* reason )
f332a5a0 240#endif
47be989f
MB
241{
242 Display* xdisplay = XtDisplay( xwidget );
243 Window xwindow = XtWindow( xwidget );
244 wxDataObject* dobj = NULL;
245 size_t size = 0;
246
ac32ba44 247 for( wxDataIdToDataObjectList::compatibility_iterator node2 =
47be989f
MB
248 wxTheClipboard->m_idToObject.GetFirst();
249 node2; node2 = node2->GetNext() )
250 {
251 wxDataIdToDataObject* dido = node2->GetData();
252 if( dido->dataId == *data_id )
253 {
254 dobj = dido->object;
255 size = dido->size;
256 break;
257 }
258 }
259
260 if( !dobj ) return;
261
262 wxCharBuffer buffer(size);
263 size_t count = dobj->GetFormatCount( wxDataObject::Get );
264 wxDataFormatScopedArray dfarr( new wxDataFormat[count] );
265 dobj->GetAllFormats( dfarr.get(), wxDataObject::Get );
266
267 if( !dobj->GetDataHere( dfarr[*priv], buffer.data() ) )
268 return;
269
270 while( XmClipboardCopyByName( xdisplay, xwindow, *data_id,
271 buffer.data(), size, 0 )
272 == XmClipboardLocked );
273}
274
12db77ca
VZ
275bool wxClipboard::AddData( wxDataObject *data )
276{
dd38c875
MB
277 wxCHECK_MSG( data, false, "data is invalid" );
278 wxCHECK_MSG( m_open, false, "clipboard not open" );
279
280 m_data.Append( data );
281
282 Display* xdisplay = wxGlobalDisplay();
47be989f
MB
283 Widget xwidget = (Widget)wxTheApp->GetTopLevelWidget();
284 Window xwindow = XtWindow( xwidget );
dd38c875
MB
285 wxXmString label( wxTheApp->GetAppName() );
286 Time timestamp = XtLastTimestampProcessed( xdisplay );
287 long itemId;
288
289 int retval;
12db77ca 290
dd38c875 291 while( ( retval = XmClipboardStartCopy( xdisplay, xwindow, label(),
47be989f
MB
292 timestamp, xwidget,
293 wxClipboardCallback,
dd38c875
MB
294 &itemId ) )
295 == XmClipboardLocked );
296 if( retval != XmClipboardSuccess )
297 return false;
298
299 size_t count = data->GetFormatCount( wxDataObject::Get );
300 wxDataFormatScopedArray dfarr( new wxDataFormat[count] );
301 data->GetAllFormats( dfarr.get(), wxDataObject::Get );
302
303 for( size_t i = 0; i < count; ++i )
2d120f83 304 {
dd38c875 305 size_t size = data->GetDataSize( dfarr[i] );
47be989f 306 long data_id;
dd38c875
MB
307 wxString id = dfarr[i].GetId();
308
309 while( ( retval = XmClipboardCopy( xdisplay, xwindow, itemId,
310 wxConstCast(id.c_str(), char),
47be989f 311 NULL, size, i, &data_id ) )
dd38c875 312 == XmClipboardLocked );
47be989f
MB
313
314 m_idToObject.Append( new wxDataIdToDataObject( data, data_id, size ) );
2d120f83 315 }
dd38c875
MB
316
317 while( XmClipboardEndCopy( xdisplay, xwindow, itemId )
318 == XmClipboardLocked );
319
320 return true;
2d120f83 321}
4bb6408c 322
2d120f83
JS
323void wxClipboard::Close()
324{
325 wxCHECK_RET( m_open, "clipboard not open" );
326
dd38c875 327 m_open = false;
4bb6408c
JS
328}
329
dd38c875 330bool wxClipboard::IsSupported(const wxDataFormat& format)
4bb6408c 331{
dd38c875
MB
332 Display* xdisplay = wxGlobalDisplay();
333 Window xwindow = XtWindow( (Widget)wxTheApp->GetTopLevelWidget() );
334 bool isSupported = false;
335 int retval, count;
336 unsigned long max_name_length;
337 wxString id = format.GetId();
338
339 while( ( retval = XmClipboardLock( xdisplay, xwindow ) )
340 == XmClipboardLocked );
341 if( retval != XmClipboardSuccess )
342 return false;
343
344 if( XmClipboardInquireCount( xdisplay, xwindow, &count, &max_name_length )
345 == XmClipboardSuccess )
2d120f83 346 {
dd38c875
MB
347 wxCharBuffer buf( max_name_length + 1 );
348 unsigned long copied;
349
350 for( int i = 0; i < count; ++i )
2d120f83 351 {
dd38c875
MB
352 if( XmClipboardInquireFormat( xdisplay, xwindow, i + 1,
353 (XtPointer)buf.data(),
354 max_name_length, &copied )
355 != XmClipboardSuccess )
356 continue;
357
358 buf.data()[copied] = '\0';
359
360 if( buf == id )
2d120f83 361 {
dd38c875
MB
362 isSupported = true;
363 break;
2d120f83 364 }
2d120f83
JS
365 }
366 }
4bb6408c 367
dd38c875 368 XmClipboardUnlock( xdisplay, xwindow, False );
2d120f83 369
dd38c875 370 return isSupported;
2d120f83 371}
4bb6408c 372
dd38c875 373class wxClipboardEndRetrieve
2d120f83 374{
dd38c875
MB
375public:
376 wxClipboardEndRetrieve( Display* display, Window window )
377 : m_display( display ), m_window( window ) { }
378 ~wxClipboardEndRetrieve()
379 {
380 while( XmClipboardEndRetrieve( m_display, m_window )
381 == XmClipboardLocked );
382 }
383private:
384 Display* m_display;
385 Window m_window;
386};
2d120f83 387
dd38c875 388bool wxClipboard::GetData( wxDataObject& data )
4bb6408c 389{
dd38c875
MB
390 wxCHECK_MSG( m_open, false, "clipboard not open" );
391
392 Display* xdisplay = wxGlobalDisplay();
393 Window xwindow = XtWindow( (Widget)wxTheApp->GetTopLevelWidget() );
394 Time timestamp = XtLastTimestampProcessed( xdisplay );
395
396 wxDataFormat chosenFormat;
397 int retval;
398
399 ///////////////////////////////////////////////////////////////////////////
400 // determine if the cliboard holds any format we like
401 ///////////////////////////////////////////////////////////////////////////
402 while( ( retval = XmClipboardStartRetrieve( xdisplay, xwindow,
403 timestamp ) )
404 == XmClipboardLocked );
405 if( retval != XmClipboardSuccess )
406 return false;
407
408 wxClipboardEndRetrieve endRetrieve( xdisplay, xwindow );
409
410 int count;
411 unsigned long max_name_length;
412 size_t dfcount = data.GetFormatCount( wxDataObject::Set );
413 wxDataFormatScopedArray dfarr( new wxDataFormat[dfcount] );
414 data.GetAllFormats( dfarr.get(), wxDataObject::Set );
2d120f83 415
dd38c875
MB
416 if( XmClipboardInquireCount( xdisplay, xwindow, &count, &max_name_length )
417 == XmClipboardSuccess )
418 {
419 wxCharBuffer buf( max_name_length + 1 );
420 unsigned long copied;
4bb6408c 421
dd38c875
MB
422 for( int i = 0; i < count; ++i )
423 {
424 if( XmClipboardInquireFormat( xdisplay, xwindow, i + 1,
425 (XtPointer)buf.data(),
426 max_name_length, &copied )
427 != XmClipboardSuccess )
428 continue;
4bb6408c 429
dd38c875 430 buf.data()[copied] = '\0';
4bb6408c 431
dd38c875
MB
432 // try preferred format
433 if( buf == data.GetPreferredFormat( wxDataObject::Set ).GetId() )
434 {
435 chosenFormat = data.GetPreferredFormat( wxDataObject::Set );
436 break;
437 }
2d120f83 438
dd38c875
MB
439 // try all other formats
440 for( size_t i = 0; i < dfcount; ++i )
441 {
442 if( buf == dfarr[i].GetId() )
443 chosenFormat = dfarr[i];
444 }
445 }
2d120f83 446 }
4bb6408c 447
dd38c875
MB
448 if( chosenFormat == wxDF_INVALID )
449 return false;
450
451 ///////////////////////////////////////////////////////////////////////////
452 // now retrieve the data
453 ///////////////////////////////////////////////////////////////////////////
454 unsigned long length, dummy1;
455 long dummy2;
456 wxString id = chosenFormat.GetId();
457
458 while( ( retval = XmClipboardInquireLength( xdisplay, xwindow,
459 wxConstCast(id.c_str(), char),
460 &length ) )
461 == XmClipboardLocked );
462 if( retval != XmClipboardSuccess )
463 return false;
464
465 wxCharBuffer buf(length);
466
467 while( ( retval = XmClipboardRetrieve( xdisplay, xwindow,
468 wxConstCast(id.c_str(), char),
469 (XtPointer)buf.data(),
470 length, &dummy1, &dummy2 ) )
471 == XmClipboardLocked );
472 if( retval != XmClipboardSuccess )
473 return false;
474
475 if( !data.SetData( chosenFormat, length, buf.data() ) )
476 return false;
477
478 return true;
4bb6408c
JS
479}
480
dfe1eee3 481#endif // wxUSE_CLIPBOARD