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"
19 #include "wx/bitmap.h"
21 #include "wx/metafile.h"
22 #include "wx/clipbrd.h"
30 #include "wx/mac/uma.h"
32 #define wxUSE_DATAOBJ 1
37 // the trace mask we use with wxLogTrace() - call
38 // wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here
39 // (there will be a *lot* of them!)
40 static const wxChar
*TRACE_CLIPBOARD
= wxT("clipboard");
43 void * wxGetClipboardData( wxDataFormat dataFormat
, long *len
)
49 switch (dataFormat
.GetType())
52 dataFormat
= wxDF_TEXT
;
56 case wxDF_UNICODETEXT
:
71 err
= GetCurrentScrap( &scrapRef
);
72 if ( err
!= noTypeErr
&& err
!= memFullErr
)
74 ScrapFlavorFlags flavorFlags
;
76 err
= GetScrapFlavorFlags( scrapRef
, dataFormat
.GetFormatId(), &flavorFlags
);
79 err
= GetScrapFlavorSize( scrapRef
, dataFormat
.GetFormatId(), &byteCount
);
82 Size allocSize
= byteCount
;
83 if ( dataFormat
.GetType() == wxDF_TEXT
)
85 else if ( dataFormat
.GetType() == wxDF_UNICODETEXT
)
88 data
= new char[ allocSize
];
90 if (( err
= GetScrapFlavorData( scrapRef
, dataFormat
.GetFormatId(), &byteCount
, data
)) == noErr
)
93 if ( dataFormat
.GetType() == wxDF_TEXT
)
94 ((char*)data
)[ byteCount
] = 0;
95 if ( dataFormat
.GetType() == wxDF_UNICODETEXT
)
97 // "data" format is UTF16, so 2 bytes = one character
98 // wxChar size depends on platform, so just clear last 2 bytes
99 ((char*)data
)[ byteCount
+ 0 ] =
100 ((char*)data
)[ byteCount
+ 1 ] = 0;
105 delete [] (char*)data
;
114 Handle datahandle
= NewHandle( 0 );
116 err
= (OSStatus
)GetScrap( datahandle
, dataFormat
.GetFormatId(), &offset
);
117 HUnlock( datahandle
);
118 if ( GetHandleSize( datahandle
) > 0 )
120 byteCount
= GetHandleSize( datahandle
);
121 Size allocSize
= byteCount
;
122 if ( dataFormat
.GetType() == wxDF_TEXT
)
124 else if ( dataFormat
.GetType() == wxDF_UNICODETEXT
)
127 data
= new char[ allocSize
];
129 memcpy( (char*) data
, (char*) *datahandle
, byteCount
);
130 if ( dataFormat
.GetType() == wxDF_TEXT
)
131 ((char*)data
)[ byteCount
] = 0;
132 else if ( dataFormat
.GetType() == wxDF_UNICODETEXT
)
133 ((wxChar
*)data
)[ byteCount
/ 2 ] = 0;
137 DisposeHandle( datahandle
);
142 wxLogSysError(wxT("Failed to get clipboard data."));
147 if ( dataFormat
.GetType() == wxDF_TEXT
)
148 wxMacConvertNewlines10To13( (char*)data
);
153 IMPLEMENT_DYNAMIC_CLASS(wxClipboard
, wxObject
)
155 wxClipboard::wxClipboard()
161 wxClipboard::~wxClipboard()
166 m_data
= (wxDataObject
*)NULL
;
170 void wxClipboard::Clear()
175 m_data
= (wxDataObject
*)NULL
;
180 err
= ClearCurrentScrap();
188 wxLogSysError( wxT("Failed to empty the clipboard.") );
192 bool wxClipboard::Flush()
197 bool wxClipboard::Open()
199 wxCHECK_MSG( !m_open
, false, wxT("clipboard already open") );
206 bool wxClipboard::IsOpened() const
211 bool wxClipboard::SetData( wxDataObject
*data
)
213 wxCHECK_MSG( m_open
, false, wxT("clipboard not open") );
214 wxCHECK_MSG( data
, false, wxT("data is invalid") );
218 // as we can only store one wxDataObject,
219 // this is the same in this implementation
220 return AddData( data
);
223 bool wxClipboard::AddData( wxDataObject
*data
)
225 wxCHECK_MSG( m_open
, false, wxT("clipboard not open") );
226 wxCHECK_MSG( data
, false, wxT("data is invalid") );
228 // we can only store one wxDataObject
233 // get formats from wxDataObjects
234 wxDataFormat
*array
= new wxDataFormat
[ m_data
->GetFormatCount() ];
235 m_data
->GetAllFormats( array
);
237 for (size_t i
= 0; i
< m_data
->GetFormatCount(); i
++)
239 wxLogTrace( TRACE_CLIPBOARD
,
240 wxT("wxClipboard now supports atom %s"),
241 array
[i
].GetId().c_str() );
243 size_t sz
= data
->GetDataSize( array
[ i
] );
244 void* buf
= malloc( sz
+ 1 );
247 // empty the buffer because in some case GetDataHere does not fill buf
248 memset(buf
, 0, sz
+ 1);
249 data
->GetDataHere( array
[ i
] , buf
);
251 switch ( array
[i
].GetType() )
255 mactype
= kScrapFlavorTypeText
;
260 case wxDF_UNICODETEXT
:
261 mactype
= kScrapFlavorTypeUnicode
;
266 #if wxUSE_DRAG_AND_DROP
268 mactype
= kScrapFlavorTypePicture
;
274 mactype
= kScrapFlavorTypePicture
;
278 mactype
= (OSType
)(array
[i
].GetFormatId());
282 UMAPutScrap( sz
, mactype
, buf
);
292 void wxClipboard::Close()
294 wxCHECK_RET( m_open
, wxT("clipboard not open") );
298 // Get rid of cached object.
299 // If this is not done, copying data from
300 // another application will only work once
304 m_data
= (wxDataObject
*) NULL
;
308 bool wxClipboard::IsSupported( const wxDataFormat
&dataFormat
)
311 return m_data
->IsSupported( dataFormat
);
314 OSStatus err
= noErr
;
317 err
= GetCurrentScrap( &scrapRef
);
318 if ( err
!= noTypeErr
&& err
!= memFullErr
)
320 ScrapFlavorFlags flavorFlags
;
323 err
= GetScrapFlavorFlags( scrapRef
, dataFormat
.GetFormatId(), &flavorFlags
);
326 err
= GetScrapFlavorSize( scrapRef
, dataFormat
.GetFormatId(), &byteCount
);
336 Handle datahandle
= NewHandle( 0 );
338 GetScrap( datahandle
, dataFormat
.GetFormatId(), &offset
);
339 HUnlock( datahandle
);
340 bool hasData
= GetHandleSize( datahandle
) > 0;
341 DisposeHandle( datahandle
);
347 bool wxClipboard::GetData( wxDataObject
& data
)
349 wxCHECK_MSG( m_open
, false, wxT("clipboard not open") );
351 size_t formatcount
= data
.GetFormatCount() + 1;
352 wxDataFormat
*array
= new wxDataFormat
[ formatcount
];
353 array
[0] = data
.GetPreferredFormat();
354 data
.GetAllFormats( &array
[1] );
356 bool transferred
= false;
360 for (size_t i
= 0; !transferred
&& i
< formatcount
; i
++)
362 wxDataFormat format
= array
[ i
];
363 if ( m_data
->IsSupported( format
) )
365 int dataSize
= m_data
->GetDataSize( format
);
370 data
.SetData( format
, 0, 0 );
374 char *d
= new char[ dataSize
];
375 m_data
->GetDataHere( format
, (void*) d
);
376 data
.SetData( format
, dataSize
, d
);
383 // get formats from wxDataObjects
386 for (size_t i
= 0; !transferred
&& i
< formatcount
; i
++)
388 wxDataFormat format
= array
[ i
];
390 switch ( format
.GetType() )
392 // NOTE: this is usable for all data types
394 case wxDF_UNICODETEXT
:
401 char* s
= (char*)wxGetClipboardData( format
, &len
);
404 data
.SetData( format
, len
, s
);