1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     Clipboard functionality 
   4 // Author:      Julian Smart 
   5 // Modified by: Mattia Barbon (added support for generic wxDataObjects) 
   8 // Copyright:   (c) Julian Smart 
   9 // Licence:     wxWindows licence 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  13 #pragma implementation 
  14 #pragma implementation "clipbrd.h" 
  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 
  31 #include "wx/bitmap.h" 
  33 #include "wx/clipbrd.h" 
  34 #include "wx/dataobj.h" 
  35 #include "wx/ptr_scpd.h" 
  38 #pragma message disable nosimpint 
  42 #include <Xm/CutPaste.h> 
  44 #pragma message enable nosimpint 
  47 #include "wx/motif/private.h" 
  49 bool wxOpenClipboard() 
  51     return wxTheClipboard
->Open(); 
  54 bool wxCloseClipboard() 
  56     wxTheClipboard
->Close(); 
  61 bool wxEmptyClipboard() 
  63     wxTheClipboard
->Clear(); 
  67 bool wxClipboardOpen() 
  69     return wxTheClipboard
->IsOpened(); 
  72 bool wxIsClipboardFormatAvailable(wxDataFormat dataFormat
) 
  74     return wxTheClipboard
->IsSupported( dataFormat 
); 
  77 bool wxSetClipboardData(wxDataFormat dataFormat
, wxObject 
*obj
, 
  78                         int WXUNUSED(width
), int WXUNUSED(height
)) 
  80     wxDataObject
* dobj 
= NULL
; 
  82     if( dataFormat 
== wxDF_TEXT 
) 
  84         wxChar
* data 
= (wxChar
*)obj
; 
  85         dobj 
= new wxTextDataObject( data 
); 
  87     else if( dataFormat 
= wxDF_BITMAP 
) 
  89         wxBitmap
* data 
= (wxBitmap
*)obj
; 
  90         dobj 
= new wxBitmapDataObject( *data 
); 
  96     return wxTheClipboard
->SetData( dobj 
); 
  99 wxObject 
*wxGetClipboardData(wxDataFormat dataFormat
, long *len
) 
 101     wxDataObject
* dobj 
= NULL
; 
 102     wxTextDataObject
* tobj 
= NULL
; 
 103     wxBitmapDataObject
* bobj 
= NULL
; 
 105     if( dataFormat 
== wxDF_TEXT 
) 
 107         dobj 
= tobj 
= new wxTextDataObject
; 
 109     else if( dataFormat 
= wxDF_BITMAP 
) 
 111         dobj 
= bobj 
= new wxBitmapDataObject
; 
 114     if( !dobj 
|| !wxTheClipboard
->GetData( *dobj 
) ) 
 119         wxString text 
= tobj
->GetText(); 
 120         wxChar
* buf 
= new wxChar
[text
.length() + 1]; 
 122         if( len 
) *len 
= text
.length(); 
 123         return (wxObject
*)wxStrcpy( buf
, text
.c_str() ); 
 128         return new wxBitmap( bobj
->GetBitmap() ); 
 131     return NULL
; // just in case... 
 134 wxDataFormat 
wxEnumClipboardFormats(wxDataFormat dataFormat
) 
 136     // Only wxDF_TEXT supported 
 137     if (dataFormat 
== wxDF_TEXT
) 
 143 wxDataFormat 
wxRegisterClipboardFormat(char *WXUNUSED(formatName
)) 
 149 bool wxGetClipboardFormatName(wxDataFormat dataFormat
, char *formatName
, 
 152     wxStrncpy( formatName
, dataFormat
.GetId().c_str(), maxCount 
); 
 157 //----------------------------------------------------------------------------- 
 159 //----------------------------------------------------------------------------- 
 161 struct wxDataIdToDataObject
 
 163     wxDataIdToDataObject( wxDataObject
* o
, long d
, size_t s 
) 
 164         : object( o 
), size( s 
), dataId( d 
) { } 
 166     wxDataObject
* object
; 
 171 #include "wx/listimpl.cpp" 
 173 WX_DEFINE_LIST(wxDataObjectList
); 
 174 WX_DEFINE_LIST(wxDataIdToDataObjectList
); 
 176 #if wxCHECK_LESSTIF() 
 177 static void wxClipboardCallback( Widget widget
, int* data_id
, 
 178                                  int* priv
, int* reason 
); 
 180 static void wxClipboardCallback( Widget widget
, long* data_id
, 
 181                                  long* priv
, int* reason 
); 
 184 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
,wxObject
) 
 186 wxClipboard::wxClipboard() 
 191 wxClipboard::~wxClipboard() 
 196 void wxClipboard::Clear() 
 198     wxDataObjectList::compatibility_iterator node 
= m_data
.GetFirst(); 
 201         delete node
->GetData(); 
 202         node 
= node
->GetNext(); 
 206     for( wxDataIdToDataObjectList::compatibility_iterator node2 
= m_idToObject
.GetFirst(); 
 207          node2
; node2 
= node2
->GetNext() ) 
 208         delete node
->GetData(); 
 209     m_idToObject
.Clear(); 
 212 bool wxClipboard::Open() 
 214     wxCHECK_MSG( !m_open
, false, "clipboard already open" ); 
 221 bool wxClipboard::SetData( wxDataObject 
*data 
) 
 223     wxCHECK_MSG( data
, false, "data is invalid" ); 
 224     wxCHECK_MSG( m_open
, false, "clipboard not open" ); 
 228     return AddData( data 
); 
 231 wxDECLARE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray 
); 
 232 wxDEFINE_SCOPED_ARRAY( wxDataFormat
, wxDataFormatScopedArray 
); 
 234 #if wxCHECK_LESSTIF() 
 235 void wxClipboardCallback( Widget xwidget
, int* data_id
, 
 236                           int* priv
, int* reason 
) 
 238 void wxClipboardCallback( Widget xwidget
, long* data_id
, 
 239                           long* priv
, int* reason 
) 
 242     Display
* xdisplay 
= XtDisplay( xwidget 
); 
 243     Window xwindow 
= XtWindow( xwidget 
); 
 244     wxDataObject
* dobj 
= NULL
; 
 247     for( wxDataIdToDataObjectList::compatibility_iterator node2 
= 
 248              wxTheClipboard
->m_idToObject
.GetFirst(); 
 249          node2
; node2 
= node2
->GetNext() ) 
 251         wxDataIdToDataObject
* dido 
= node2
->GetData(); 
 252         if( dido
->dataId 
== *data_id 
) 
 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 
); 
 267     if( !dobj
->GetDataHere( dfarr
[*priv
], buffer
.data() ) ) 
 270     while( XmClipboardCopyByName( xdisplay
, xwindow
, *data_id
, 
 271                                   buffer
.data(), size
, 0 ) 
 272            == XmClipboardLocked 
); 
 275 bool wxClipboard::AddData( wxDataObject 
*data 
) 
 277     wxCHECK_MSG( data
, false, "data is invalid" ); 
 278     wxCHECK_MSG( m_open
, false, "clipboard not open" ); 
 280     m_data
.Append( data 
); 
 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 
); 
 291     while( ( retval 
= XmClipboardStartCopy( xdisplay
, xwindow
, label(), 
 295            == XmClipboardLocked 
); 
 296     if( retval 
!= XmClipboardSuccess 
) 
 299     size_t count 
= data
->GetFormatCount( wxDataObject::Get 
); 
 300     wxDataFormatScopedArray 
dfarr( new wxDataFormat
[count
] ); 
 301     data
->GetAllFormats( dfarr
.get(), wxDataObject::Get 
); 
 303     for( size_t i 
= 0; i 
< count
; ++i 
) 
 305         size_t size 
= data
->GetDataSize( dfarr
[i
] ); 
 307         wxString id 
= dfarr
[i
].GetId(); 
 309         while( ( retval 
= XmClipboardCopy( xdisplay
, xwindow
, itemId
, 
 310                                            wxConstCast(id
.c_str(), char), 
 311                                            NULL
, size
, i
, &data_id 
) ) 
 312                == XmClipboardLocked 
); 
 314         m_idToObject
.Append( new wxDataIdToDataObject( data
, data_id
, size 
) ); 
 317     while( XmClipboardEndCopy( xdisplay
, xwindow
, itemId 
) 
 318            == XmClipboardLocked 
); 
 323 void wxClipboard::Close() 
 325     wxCHECK_RET( m_open
, "clipboard not open" ); 
 330 bool wxClipboard::IsSupported(const wxDataFormat
& format
) 
 332     Display
* xdisplay 
= wxGlobalDisplay(); 
 333     Window xwindow 
= XtWindow( (Widget
)wxTheApp
->GetTopLevelWidget() ); 
 334     bool isSupported 
= false; 
 336     unsigned long  max_name_length
; 
 337     wxString id 
= format
.GetId(); 
 339     while( ( retval 
= XmClipboardLock( xdisplay
, xwindow 
) ) 
 340            == XmClipboardLocked 
); 
 341     if( retval 
!= XmClipboardSuccess 
) 
 344     if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length 
) 
 345         == XmClipboardSuccess 
) 
 347         wxCharBuffer 
buf( max_name_length 
+ 1 ); 
 348         unsigned long copied
; 
 350         for( int i 
= 0; i 
< count
; ++i 
) 
 352             if( XmClipboardInquireFormat( xdisplay
, xwindow
, i 
+ 1, 
 353                                           (XtPointer
)buf
.data(), 
 354                                           max_name_length
, &copied 
) 
 355                 != XmClipboardSuccess 
) 
 358             buf
.data()[copied
] = '\0'; 
 368     XmClipboardUnlock( xdisplay
, xwindow
, False 
); 
 373 class wxClipboardEndRetrieve
 
 376     wxClipboardEndRetrieve( Display
* display
, Window window 
) 
 377         : m_display( display 
), m_window( window 
) { } 
 378     ~wxClipboardEndRetrieve() 
 380         while( XmClipboardEndRetrieve( m_display
, m_window 
) 
 381                == XmClipboardLocked 
); 
 388 bool wxClipboard::GetData( wxDataObject
& data 
) 
 390     wxCHECK_MSG( m_open
, false, "clipboard not open" ); 
 392     Display
* xdisplay 
= wxGlobalDisplay(); 
 393     Window xwindow 
= XtWindow( (Widget
)wxTheApp
->GetTopLevelWidget() ); 
 394     Time timestamp 
= XtLastTimestampProcessed( xdisplay 
); 
 396     wxDataFormat chosenFormat
; 
 399     /////////////////////////////////////////////////////////////////////////// 
 400     // determine if the cliboard holds any format we like 
 401     /////////////////////////////////////////////////////////////////////////// 
 402     while( ( retval 
= XmClipboardStartRetrieve( xdisplay
, xwindow
, 
 404            == XmClipboardLocked 
); 
 405     if( retval 
!= XmClipboardSuccess 
) 
 408     wxClipboardEndRetrieve 
endRetrieve( xdisplay
, xwindow 
); 
 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 
); 
 416     if( XmClipboardInquireCount( xdisplay
, xwindow
, &count
, &max_name_length 
) 
 417         == XmClipboardSuccess 
) 
 419         wxCharBuffer 
buf( max_name_length 
+ 1 ); 
 420         unsigned long copied
; 
 422         for( int i 
= 0; i 
< count
; ++i 
) 
 424             if( XmClipboardInquireFormat( xdisplay
, xwindow
, i 
+ 1, 
 425                                           (XtPointer
)buf
.data(), 
 426                                           max_name_length
, &copied 
) 
 427                 != XmClipboardSuccess 
) 
 430             buf
.data()[copied
] = '\0'; 
 432             // try preferred format 
 433             if( buf 
== data
.GetPreferredFormat( wxDataObject::Set 
).GetId() ) 
 435                 chosenFormat 
= data
.GetPreferredFormat( wxDataObject::Set 
); 
 439             // try all other formats 
 440             for( size_t i 
= 0; i 
< dfcount
; ++i 
) 
 442                 if( buf 
== dfarr
[i
].GetId() ) 
 443                     chosenFormat 
= dfarr
[i
]; 
 448     if( chosenFormat 
== wxDF_INVALID 
) 
 451     /////////////////////////////////////////////////////////////////////////// 
 452     // now retrieve the data 
 453     /////////////////////////////////////////////////////////////////////////// 
 454     unsigned long length
, dummy1
; 
 456     wxString id 
= chosenFormat
.GetId(); 
 458     while( ( retval 
= XmClipboardInquireLength( xdisplay
, xwindow
, 
 459                                                 wxConstCast(id
.c_str(), char), 
 461            == XmClipboardLocked 
); 
 462     if( retval 
!= XmClipboardSuccess 
) 
 465     wxCharBuffer 
buf(length
); 
 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 
) 
 475     if( !data
.SetData( chosenFormat
, length
, buf
.data() ) ) 
 481 #endif // wxUSE_CLIPBOARD