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()
176 if ( IsUsingPrimarySelection() )
187 err
= ClearCurrentScrap();
195 wxLogSysError( wxT("Failed to empty the clipboard.") );
199 bool wxClipboard::Flush()
204 bool wxClipboard::Open()
206 wxCHECK_MSG( !m_open
, false, wxT("clipboard already open") );
213 bool wxClipboard::IsOpened() const
218 bool wxClipboard::SetData( wxDataObject
*data
)
220 if ( IsUsingPrimarySelection() )
223 wxCHECK_MSG( m_open
, false, wxT("clipboard not open") );
224 wxCHECK_MSG( data
, false, wxT("data is invalid") );
228 // as we can only store one wxDataObject,
229 // this is the same in this implementation
230 return AddData( data
);
233 bool wxClipboard::AddData( wxDataObject
*data
)
235 if ( IsUsingPrimarySelection() )
238 wxCHECK_MSG( m_open
, false, wxT("clipboard not open") );
239 wxCHECK_MSG( data
, false, wxT("data is invalid") );
241 // we can only store one wxDataObject
246 // get formats from wxDataObjects
247 wxDataFormat
*array
= new wxDataFormat
[ m_data
->GetFormatCount() ];
248 m_data
->GetAllFormats( array
);
250 for (size_t i
= 0; i
< m_data
->GetFormatCount(); i
++)
252 if (array
[i
].IsStandard())
254 wxLogTrace( TRACE_CLIPBOARD
,
255 wxT("wxClipboard now supports standard atom type %d"),
256 array
[i
].GetType() );
260 wxLogTrace( TRACE_CLIPBOARD
,
261 wxT("wxClipboard now supports atom %s"),
262 array
[i
].GetId().c_str() );
265 size_t sz
= data
->GetDataSize( array
[ i
] );
266 void* buf
= malloc( sz
+ 1 );
269 // empty the buffer because in some case GetDataHere does not fill buf
270 memset( buf
, 0, sz
+ 1 );
271 data
->GetDataHere( array
[ i
], buf
);
273 switch ( array
[i
].GetType() )
277 mactype
= kScrapFlavorTypeText
;
282 case wxDF_UNICODETEXT
:
283 mactype
= kScrapFlavorTypeUnicode
;
288 #if wxUSE_DRAG_AND_DROP
290 mactype
= kScrapFlavorTypePicture
;
296 mactype
= kScrapFlavorTypePicture
;
300 mactype
= (OSType
)(array
[ i
].GetFormatId());
304 UMAPutScrap( sz
, mactype
, buf
);
314 void wxClipboard::Close()
316 wxCHECK_RET( m_open
, wxT("clipboard not open") );
320 // Get rid of cached object.
321 // If this is not done, copying data from
322 // another application will only work once
326 m_data
= (wxDataObject
*) NULL
;
330 bool wxClipboard::IsSupported( const wxDataFormat
&dataFormat
)
332 if ( IsUsingPrimarySelection() )
336 return m_data
->IsSupported( dataFormat
);
338 bool hasData
= false;
341 OSStatus err
= noErr
;
344 err
= GetCurrentScrap( &scrapRef
);
345 if ( err
!= noTypeErr
&& err
!= memFullErr
)
347 ScrapFlavorFlags flavorFlags
;
350 err
= GetScrapFlavorFlags( scrapRef
, dataFormat
.GetFormatId(), &flavorFlags
);
353 err
= GetScrapFlavorSize( scrapRef
, dataFormat
.GetFormatId(), &byteCount
);
357 else if ( dataFormat
.GetType() == wxDF_UNICODETEXT
)
359 err
= GetScrapFlavorFlags( scrapRef
, 'TEXT', &flavorFlags
);
362 err
= GetScrapFlavorSize( scrapRef
, 'TEXT', &byteCount
);
372 Handle datahandle
= NewHandle( 0 );
374 GetScrap( datahandle
, dataFormat
.GetFormatId(), &offset
);
375 HUnlock( datahandle
);
376 hasData
= GetHandleSize( datahandle
) > 0;
377 DisposeHandle( datahandle
);
383 bool wxClipboard::GetData( wxDataObject
& data
)
385 if ( IsUsingPrimarySelection() )
388 wxCHECK_MSG( m_open
, false, wxT("clipboard not open") );
390 size_t formatcount
= data
.GetFormatCount() + 1;
391 wxDataFormat
*array
= new wxDataFormat
[ formatcount
];
392 array
[0] = data
.GetPreferredFormat();
393 data
.GetAllFormats( &array
[1] );
395 bool transferred
= false;
399 for (size_t i
= 0; !transferred
&& i
< formatcount
; i
++)
401 wxDataFormat format
= array
[ i
];
402 if ( m_data
->IsSupported( format
) )
404 int dataSize
= m_data
->GetDataSize( format
);
409 data
.SetData( format
, 0, 0 );
413 char *d
= new char[ dataSize
];
414 m_data
->GetDataHere( format
, (void*)d
);
415 data
.SetData( format
, dataSize
, d
);
422 // get formats from wxDataObjects
425 for (size_t i
= 0; !transferred
&& i
< formatcount
; i
++)
427 wxDataFormat format
= array
[ i
];
429 switch ( format
.GetType() )
431 // NOTE: this is usable for all data types
433 case wxDF_UNICODETEXT
:
440 char* s
= (char*)wxGetClipboardData( format
, &len
);
443 data
.SetData( format
, len
, s
);