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