]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/motif/clipbrd.cpp
libpng vulnerability CAN-2004-0421
[wxWidgets.git] / src / motif / clipbrd.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: clipbrd.cpp
3// Purpose: Clipboard functionality
4// Author: Julian Smart
5// Modified by: Mattia Barbon (added support for generic wxDataObjects)
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13#pragma implementation
14#pragma implementation "clipbrd.h"
15#endif
16
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
26#include "wx/defs.h"
27
28#if wxUSE_CLIPBOARD
29
30#include "wx/app.h"
31#include "wx/bitmap.h"
32#include "wx/utils.h"
33#include "wx/clipbrd.h"
34#include "wx/dataobj.h"
35#include "wx/ptr_scpd.h"
36
37#ifdef __VMS__
38#pragma message disable nosimpint
39
40#endif
41#include <Xm/Xm.h>
42#include <Xm/CutPaste.h>
43#ifdef __VMS__
44#pragma message enable nosimpint
45#endif
46
47#include "wx/motif/private.h"
48
49bool wxOpenClipboard()
50{
51 return wxTheClipboard->Open();
52}
53
54bool wxCloseClipboard()
55{
56 wxTheClipboard->Close();
57
58 return true;
59}
60
61bool wxEmptyClipboard()
62{
63 wxTheClipboard->Clear();
64 return true;
65}
66
67bool wxClipboardOpen()
68{
69 return wxTheClipboard->IsOpened();
70}
71
72bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat)
73{
74 return wxTheClipboard->IsSupported( dataFormat );
75}
76
77bool wxSetClipboardData(wxDataFormat dataFormat, wxObject *obj,
78 int WXUNUSED(width), int WXUNUSED(height))
79{
80 wxDataObject* dobj = NULL;
81
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 }
92
93 if( !dobj )
94 return false;
95
96 return wxTheClipboard->SetData( dobj );
97}
98
99wxObject *wxGetClipboardData(wxDataFormat dataFormat, long *len)
100{
101 wxDataObject* dobj = NULL;
102 wxTextDataObject* tobj = NULL;
103 wxBitmapDataObject* bobj = NULL;
104
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 }
113
114 if( !dobj || !wxTheClipboard->GetData( *dobj ) )
115 return NULL;
116
117 if( tobj )
118 {
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() );
129 }
130
131 return NULL; // just in case...
132}
133
134wxDataFormat wxEnumClipboardFormats(wxDataFormat dataFormat)
135{
136 // Only wxDF_TEXT supported
137 if (dataFormat == wxDF_TEXT)
138 return wxDF_TEXT;
139 else
140 return wxDF_INVALID;
141}
142
143wxDataFormat wxRegisterClipboardFormat(char *WXUNUSED(formatName))
144{
145 // Not supported
146 return wxDF_INVALID;
147}
148
149bool wxGetClipboardFormatName(wxDataFormat dataFormat, char *formatName,
150 int maxCount)
151{
152 wxStrncpy( formatName, dataFormat.GetId().c_str(), maxCount );
153
154 return true;
155}
156
157//-----------------------------------------------------------------------------
158// wxClipboard
159//-----------------------------------------------------------------------------
160
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
176#if wxCHECK_LESSTIF()
177static void wxClipboardCallback( Widget widget, int* data_id,
178 int* priv, int* reason );
179#else
180static void wxClipboardCallback( Widget widget, long* data_id,
181 long* priv, int* reason );
182#endif
183
184IMPLEMENT_DYNAMIC_CLASS(wxClipboard,wxObject)
185
186wxClipboard::wxClipboard()
187{
188 m_open = false;
189}
190
191wxClipboard::~wxClipboard()
192{
193 Clear();
194}
195
196void wxClipboard::Clear()
197{
198 wxDataObjectList::compatibility_iterator node = m_data.GetFirst();
199 while (node)
200 {
201 delete node->GetData();
202 node = node->GetNext();
203 }
204 m_data.Clear();
205
206 for( wxDataIdToDataObjectList::compatibility_iterator node2 = m_idToObject.GetFirst();
207 node2; node2 = node2->GetNext() )
208 delete node->GetData();
209 m_idToObject.Clear();
210}
211
212bool wxClipboard::Open()
213{
214 wxCHECK_MSG( !m_open, false, "clipboard already open" );
215
216 m_open = true;
217
218 return true;
219}
220
221bool wxClipboard::SetData( wxDataObject *data )
222{
223 wxCHECK_MSG( data, false, "data is invalid" );
224 wxCHECK_MSG( m_open, false, "clipboard not open" );
225
226 Clear();
227
228 return AddData( data );
229}
230
231wxDECLARE_SCOPED_ARRAY( wxDataFormat, wxDataFormatScopedArray );
232wxDEFINE_SCOPED_ARRAY( wxDataFormat, wxDataFormatScopedArray );
233
234#if wxCHECK_LESSTIF()
235void wxClipboardCallback( Widget xwidget, int* data_id,
236 int* priv, int* reason )
237#else
238void wxClipboardCallback( Widget xwidget, long* data_id,
239 long* priv, int* reason )
240#endif
241{
242 Display* xdisplay = XtDisplay( xwidget );
243 Window xwindow = XtWindow( xwidget );
244 wxDataObject* dobj = NULL;
245 size_t size = 0;
246
247 for( wxDataIdToDataObjectList::compatibility_iterator node2 =
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
275bool wxClipboard::AddData( wxDataObject *data )
276{
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();
283 Widget xwidget = (Widget)wxTheApp->GetTopLevelWidget();
284 Window xwindow = XtWindow( xwidget );
285 wxXmString label( wxTheApp->GetAppName() );
286 Time timestamp = XtLastTimestampProcessed( xdisplay );
287 long itemId;
288
289 int retval;
290
291 while( ( retval = XmClipboardStartCopy( xdisplay, xwindow, label(),
292 timestamp, xwidget,
293 wxClipboardCallback,
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 )
304 {
305 size_t size = data->GetDataSize( dfarr[i] );
306 long data_id;
307 wxString id = dfarr[i].GetId();
308
309 while( ( retval = XmClipboardCopy( xdisplay, xwindow, itemId,
310 wxConstCast(id.c_str(), char),
311 NULL, size, i, &data_id ) )
312 == XmClipboardLocked );
313
314 m_idToObject.Append( new wxDataIdToDataObject( data, data_id, size ) );
315 }
316
317 while( XmClipboardEndCopy( xdisplay, xwindow, itemId )
318 == XmClipboardLocked );
319
320 return true;
321}
322
323void wxClipboard::Close()
324{
325 wxCHECK_RET( m_open, "clipboard not open" );
326
327 m_open = false;
328}
329
330bool wxClipboard::IsSupported(const wxDataFormat& format)
331{
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 )
346 {
347 wxCharBuffer buf( max_name_length + 1 );
348 unsigned long copied;
349
350 for( int i = 0; i < count; ++i )
351 {
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 )
361 {
362 isSupported = true;
363 break;
364 }
365 }
366 }
367
368 XmClipboardUnlock( xdisplay, xwindow, False );
369
370 return isSupported;
371}
372
373class wxClipboardEndRetrieve
374{
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};
387
388bool wxClipboard::GetData( wxDataObject& data )
389{
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 );
415
416 if( XmClipboardInquireCount( xdisplay, xwindow, &count, &max_name_length )
417 == XmClipboardSuccess )
418 {
419 wxCharBuffer buf( max_name_length + 1 );
420 unsigned long copied;
421
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;
429
430 buf.data()[copied] = '\0';
431
432 // try preferred format
433 if( buf == data.GetPreferredFormat( wxDataObject::Set ).GetId() )
434 {
435 chosenFormat = data.GetPreferredFormat( wxDataObject::Set );
436 break;
437 }
438
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 }
446 }
447
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;
479}
480
481#endif // wxUSE_CLIPBOARD