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
);