1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/mac/carbon/clipbrd.cpp 
   3 // Purpose:     Clipboard functionality 
   4 // Author:      Stefan Csomor; 
   5 //              Generalized clipboard implementation by Matthew Flatt 
   9 // Copyright:   (c) Stefan Csomor 
  10 // Licence:     wxWindows licence 
  11 ///////////////////////////////////////////////////////////////////////////// 
  13 #include "wx/wxprec.h" 
  17 #include "wx/clipbrd.h" 
  25     #include "wx/bitmap.h" 
  28 #include "wx/metafile.h" 
  34 #include "wx/mac/uma.h" 
  36 #define wxUSE_DATAOBJ 1 
  41 // the trace mask we use with wxLogTrace() - call 
  42 // wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here 
  43 // (there will be a *lot* of them!) 
  44 static const wxChar 
*TRACE_CLIPBOARD 
= wxT("clipboard"); 
  47 void * wxGetClipboardData( wxDataFormat dataFormat
, long *len 
) 
  53     switch (dataFormat
.GetType()) 
  56         dataFormat 
= wxDF_TEXT
; 
  60     case wxDF_UNICODETEXT
: 
  75     err 
= GetCurrentScrap( &scrapRef 
); 
  76     if ( err 
!= noTypeErr 
&& err 
!= memFullErr 
) 
  78         ScrapFlavorFlags    flavorFlags
; 
  80         err 
= GetScrapFlavorFlags( scrapRef
, dataFormat
.GetFormatId(), &flavorFlags 
); 
  83             err 
= GetScrapFlavorSize( scrapRef
, dataFormat
.GetFormatId(), &byteCount 
); 
  86                 Size allocSize 
= byteCount
; 
  87                 if ( dataFormat
.GetType() == wxDF_TEXT 
) 
  89                 else if ( dataFormat
.GetType() == wxDF_UNICODETEXT 
) 
  92                 data 
= new char[ allocSize 
]; 
  94                 if (( err 
= GetScrapFlavorData( scrapRef
, dataFormat
.GetFormatId(), &byteCount 
, data 
)) == noErr 
) 
  97                     if ( dataFormat
.GetType() == wxDF_TEXT 
) 
  98                         ((char*)data
)[ byteCount 
] = 0; 
  99                     if ( dataFormat
.GetType() == wxDF_UNICODETEXT 
) 
 101                         // "data" format is UTF16, so 2 bytes = one character 
 102                         // wxChar size depends on platform, so just clear last 2 bytes 
 103                         ((char*)data
)[ byteCount 
+ 0 ] = 
 104                         ((char*)data
)[ byteCount 
+ 1 ] = 0; 
 109                     delete [] (char*)data
; 
 118     Handle datahandle 
= NewHandle( 0 ); 
 120     err 
= (OSStatus
)GetScrap( datahandle
, dataFormat
.GetFormatId(), &offset 
); 
 121     HUnlock( datahandle 
); 
 122     if ( GetHandleSize( datahandle 
) > 0 ) 
 124         byteCount 
= GetHandleSize( datahandle 
); 
 125         Size allocSize 
= byteCount
; 
 126         if ( dataFormat
.GetType() == wxDF_TEXT 
) 
 128         else if ( dataFormat
.GetType() == wxDF_UNICODETEXT 
) 
 131         data 
= new char[ allocSize 
]; 
 133         memcpy( (char*) data
, (char*) *datahandle
, byteCount 
); 
 134         if ( dataFormat
.GetType() == wxDF_TEXT 
) 
 135             ((char*)data
)[ byteCount 
] = 0; 
 136         else if ( dataFormat
.GetType() == wxDF_UNICODETEXT 
) 
 137             ((wxChar
*)data
)[ byteCount 
/ 2 ] = 0; 
 141     DisposeHandle( datahandle 
); 
 146         wxLogSysError(wxT("Failed to get clipboard data.")); 
 151     if (dataFormat
.GetType() == wxDF_TEXT
) 
 152         wxMacConvertNewlines10To13( (char*)data 
); 
 157 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
, wxObject
) 
 159 wxClipboard::wxClipboard() 
 165 wxClipboard::~wxClipboard() 
 174 void wxClipboard::Clear() 
 184     err 
= ClearCurrentScrap(); 
 192         wxLogSysError( wxT("Failed to empty the clipboard.") ); 
 196 bool wxClipboard::Flush() 
 201 bool wxClipboard::Open() 
 203     wxCHECK_MSG( !m_open
, false, wxT("clipboard already open") ); 
 210 bool wxClipboard::IsOpened() const 
 215 bool wxClipboard::SetData( wxDataObject 
*data 
) 
 217     wxCHECK_MSG( m_open
, false, wxT("clipboard not open") ); 
 218     wxCHECK_MSG( data
, false, wxT("data is invalid") ); 
 222     // as we can only store one wxDataObject, 
 223     // this is the same in this implementation 
 224     return AddData( data 
); 
 227 bool wxClipboard::AddData( wxDataObject 
*data 
) 
 229     wxCHECK_MSG( m_open
, false, wxT("clipboard not open") ); 
 230     wxCHECK_MSG( data
, false, wxT("data is invalid") ); 
 232     // we can only store one wxDataObject 
 237     // get formats from wxDataObjects 
 238     wxDataFormat 
*array 
= new wxDataFormat
[ m_data
->GetFormatCount() ]; 
 239     m_data
->GetAllFormats( array 
); 
 241     for (size_t i 
= 0; i 
< m_data
->GetFormatCount(); i
++) 
 243         if (array
[i
].IsStandard()) 
 245             wxLogTrace( TRACE_CLIPBOARD
, 
 246                         wxT("wxClipboard now supports standard atom type %d"), 
 247                         array
[i
].GetType() ); 
 251             wxLogTrace( TRACE_CLIPBOARD
, 
 252                         wxT("wxClipboard now supports atom %s"), 
 253                         array
[i
].GetId().c_str() ); 
 256         size_t sz 
= data
->GetDataSize( array
[ i 
] ); 
 257         void* buf 
= malloc( sz 
+ 1 ); 
 260             // empty the buffer because in some case GetDataHere does not fill buf 
 261             memset( buf
, 0, sz 
+ 1 ); 
 262             data
->GetDataHere( array
[ i 
], buf 
); 
 264             switch ( array
[i
].GetType() ) 
 268                 mactype 
= kScrapFlavorTypeText
; 
 273             case wxDF_UNICODETEXT
: 
 274                 mactype 
= kScrapFlavorTypeUnicode
; 
 279 #if wxUSE_DRAG_AND_DROP 
 281                 mactype 
= kScrapFlavorTypePicture
; 
 287                 mactype 
= kScrapFlavorTypePicture
; 
 291                 mactype 
= (OSType
)(array
[ i 
].GetFormatId()); 
 295             UMAPutScrap( sz 
, mactype 
, buf 
); 
 305 void wxClipboard::Close() 
 307     wxCHECK_RET( m_open
, wxT("clipboard not open") ); 
 311     // Get rid of cached object. 
 312     // If this is not done, copying data from 
 313     // another application will only work once 
 317         m_data 
= (wxDataObject
*) NULL
; 
 321 bool wxClipboard::IsSupported( const wxDataFormat 
&dataFormat 
) 
 324         return m_data
->IsSupported( dataFormat 
); 
 326     bool hasData 
= false; 
 329     OSStatus err 
= noErr
; 
 332     err 
= GetCurrentScrap( &scrapRef 
); 
 333     if ( err 
!= noTypeErr 
&& err 
!= memFullErr 
) 
 335         ScrapFlavorFlags flavorFlags
; 
 338         err 
= GetScrapFlavorFlags( scrapRef
, dataFormat
.GetFormatId(), &flavorFlags 
); 
 341             err 
= GetScrapFlavorSize( scrapRef
, dataFormat
.GetFormatId(), &byteCount 
); 
 345         else if ( dataFormat
.GetType() == wxDF_UNICODETEXT 
) 
 347             err 
= GetScrapFlavorFlags( scrapRef
, 'TEXT', &flavorFlags 
); 
 350                 err 
= GetScrapFlavorSize( scrapRef
, 'TEXT', &byteCount 
); 
 360     Handle datahandle 
= NewHandle( 0 ); 
 362     GetScrap( datahandle
, dataFormat
.GetFormatId(), &offset 
); 
 363     HUnlock( datahandle 
); 
 364     hasData 
= GetHandleSize( datahandle 
) > 0; 
 365     DisposeHandle( datahandle 
); 
 371 bool wxClipboard::GetData( wxDataObject
& data 
) 
 373     wxCHECK_MSG( m_open
, false, wxT("clipboard not open") ); 
 375     size_t formatcount 
= data
.GetFormatCount() + 1; 
 376     wxDataFormat 
*array 
= new wxDataFormat
[ formatcount 
]; 
 377     array
[0] = data
.GetPreferredFormat(); 
 378     data
.GetAllFormats( &array
[1] ); 
 380     bool transferred 
= false; 
 384         for (size_t i 
= 0; !transferred 
&& i 
< formatcount
; i
++) 
 386             wxDataFormat format 
= array
[ i 
]; 
 387             if ( m_data
->IsSupported( format 
) ) 
 389                 int dataSize 
= m_data
->GetDataSize( format 
); 
 394                     data
.SetData( format
, 0, 0 ); 
 398                     char *d 
= new char[ dataSize 
]; 
 399                     m_data
->GetDataHere( format
, (void*)d 
); 
 400                     data
.SetData( format
, dataSize
, d 
); 
 407     // get formats from wxDataObjects 
 410         for (size_t i 
= 0; !transferred 
&& i 
< formatcount
; i
++) 
 412             wxDataFormat format 
= array
[ i 
]; 
 414             switch ( format
.GetType() ) 
 416                 // NOTE: this is usable for all data types 
 418                 case wxDF_UNICODETEXT
: 
 425                     char* s 
= (char*)wxGetClipboardData( format
, &len 
); 
 428                         data
.SetData( format
, len
, s 
);