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