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