]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/clipbrd.cpp
Build fix after wxColourBase introduction.
[wxWidgets.git] / src / mac / carbon / clipbrd.cpp
CommitLineData
e9576ca5 1/////////////////////////////////////////////////////////////////////////////
3e822cd8 2// Name: src/mac/carbon/clipbrd.cpp
e9576ca5 3// Purpose: Clipboard functionality
3e822cd8
DS
4// Author: Stefan Csomor;
5// Generalized clipboard implementation by Matthew Flatt
e9576ca5 6// Modified by:
a31a5f85 7// Created: 1998-01-01
e9576ca5 8// RCS-ID: $Id$
a31a5f85 9// Copyright: (c) Stefan Csomor
65571936 10// Licence: wxWindows licence
e9576ca5
SC
11/////////////////////////////////////////////////////////////////////////////
12
a8e9860d
SC
13#include "wx/wxprec.h"
14
179e085f
RN
15#if wxUSE_CLIPBOARD
16
e9576ca5
SC
17#include "wx/app.h"
18#include "wx/frame.h"
19#include "wx/bitmap.h"
20#include "wx/utils.h"
21#include "wx/metafile.h"
22#include "wx/clipbrd.h"
5fde6fcc 23#include "wx/intl.h"
48d2ab90 24#include "wx/log.h"
e9576ca5 25
66a09d47
SC
26#ifndef __DARWIN__
27#include <Scrap.h>
28#endif
3e822cd8 29
9c3c5849 30#include "wx/mac/uma.h"
76a5e5d2 31
2f1ae414
SC
32#define wxUSE_DATAOBJ 1
33
e9576ca5
SC
34#include <string.h>
35
3e822cd8 36
f0822896
SC
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!)
3e822cd8
DS
40static const wxChar *TRACE_CLIPBOARD = wxT("clipboard");
41
2f1ae414 42
3e822cd8 43void * wxGetClipboardData( wxDataFormat dataFormat, long *len )
e9576ca5 44{
3e822cd8
DS
45 OSStatus err = noErr;
46 void * data = NULL;
e40298d5 47 Size byteCount;
e135f093 48
2f1ae414
SC
49 switch (dataFormat.GetType())
50 {
e40298d5
JS
51 case wxDF_OEMTEXT:
52 dataFormat = wxDF_TEXT;
3e822cd8 53 break;
e135f093 54
e40298d5 55 case wxDF_TEXT:
427ff662
SC
56 case wxDF_UNICODETEXT:
57 break;
3e822cd8
DS
58
59 case wxDF_BITMAP:
60 case wxDF_METAFILE:
61 break;
62
e40298d5 63 default:
21ec3bf9 64 // custom datatype
3e822cd8 65 break;
97af5088 66 }
e135f093 67
97af5088 68#if TARGET_CARBON
ed60b502 69 ScrapRef scrapRef;
e135f093 70
ed60b502 71 err = GetCurrentScrap( &scrapRef );
e135f093 72 if ( err != noTypeErr && err != memFullErr )
ed60b502
RR
73 {
74 ScrapFlavorFlags flavorFlags;
e135f093 75
3e822cd8
DS
76 err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags );
77 if (err == noErr)
ed60b502 78 {
3e822cd8
DS
79 err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount );
80 if (err == noErr)
ed60b502 81 {
3e822cd8 82 Size allocSize = byteCount;
e135f093 83 if ( dataFormat.GetType() == wxDF_TEXT )
3e822cd8 84 allocSize += 1;
e135f093 85 else if ( dataFormat.GetType() == wxDF_UNICODETEXT )
3e822cd8 86 allocSize += 2;
e135f093 87
3e822cd8 88 data = new char[ allocSize ];
e135f093 89
e40298d5
JS
90 if (( err = GetScrapFlavorData( scrapRef, dataFormat.GetFormatId(), &byteCount , data )) == noErr )
91 {
3e822cd8 92 *len = allocSize;
e135f093 93 if ( dataFormat.GetType() == wxDF_TEXT )
3e822cd8 94 ((char*)data)[ byteCount ] = 0;
e135f093 95 if ( dataFormat.GetType() == wxDF_UNICODETEXT )
99b62b5f
KH
96 {
97 // "data" format is UTF16, so 2 bytes = one character
98 // wxChar size depends on platform, so just clear last 2 bytes
3e822cd8
DS
99 ((char*)data)[ byteCount + 0 ] =
100 ((char*)data)[ byteCount + 1 ] = 0;
99b62b5f 101 }
e40298d5
JS
102 }
103 else
104 {
3e822cd8
DS
105 delete [] (char*)data;
106 data = NULL;
e40298d5 107 }
ed60b502
RR
108 }
109 }
110 }
e135f093 111
97af5088 112#else
3e822cd8
DS
113 long offset;
114 Handle datahandle = NewHandle( 0 );
115 HLock( datahandle );
116 err = (OSStatus)GetScrap( datahandle, dataFormat.GetFormatId(), &offset );
117 HUnlock( datahandle );
ed60b502
RR
118 if ( GetHandleSize( datahandle ) > 0 )
119 {
3e822cd8
DS
120 byteCount = GetHandleSize( datahandle );
121 Size allocSize = byteCount;
e135f093 122 if ( dataFormat.GetType() == wxDF_TEXT )
3e822cd8 123 allocSize += 1;
e135f093 124 else if ( dataFormat.GetType() == wxDF_UNICODETEXT )
3e822cd8 125 allocSize += 2;
427ff662 126
3e822cd8 127 data = new char[ allocSize ];
427ff662 128
3e822cd8 129 memcpy( (char*) data, (char*) *datahandle, byteCount );
e135f093 130 if ( dataFormat.GetType() == wxDF_TEXT )
3e822cd8
DS
131 ((char*)data)[ byteCount ] = 0;
132 else if ( dataFormat.GetType() == wxDF_UNICODETEXT )
133 ((wxChar*)data)[ byteCount / 2 ] = 0;
134 *len = byteCount;
ed60b502 135 }
3e822cd8
DS
136
137 DisposeHandle( datahandle );
97af5088 138#endif
3e822cd8
DS
139
140 if (err != noErr)
97af5088 141 {
3e822cd8 142 wxLogSysError(wxT("Failed to get clipboard data."));
e135f093 143
3e822cd8 144 return NULL;
97af5088 145 }
427ff662 146
e542ecc6 147 if (dataFormat.GetType() == wxDF_TEXT)
3e822cd8 148 wxMacConvertNewlines10To13( (char*)data );
427ff662 149
97af5088 150 return data;
2f1ae414
SC
151}
152
528e2293 153IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
7c74e7fe 154
e7549107
SC
155wxClipboard::wxClipboard()
156{
3e822cd8
DS
157 m_open = false;
158 m_data = NULL;
e7549107 159}
e9576ca5 160
e7549107 161wxClipboard::~wxClipboard()
e9576ca5 162{
e542ecc6 163 if (m_data != NULL)
e7549107 164 {
f0822896 165 delete m_data;
e542ecc6 166 m_data = NULL;
e7549107 167 }
e9576ca5
SC
168}
169
e7549107 170void wxClipboard::Clear()
e9576ca5 171{
e542ecc6 172 if (m_data != NULL)
f0822896
SC
173 {
174 delete m_data;
e542ecc6 175 m_data = NULL;
f0822896 176 }
3e822cd8 177
f0822896 178#if TARGET_CARBON
3e822cd8
DS
179 OSStatus err;
180 err = ClearCurrentScrap();
f0822896 181#else
3e822cd8
DS
182 OSErr err;
183 err = ZeroScrap();
f0822896 184#endif
3e822cd8
DS
185
186 if (err != noErr)
ed60b502 187 {
3e822cd8 188 wxLogSysError( wxT("Failed to empty the clipboard.") );
ed60b502 189 }
e9576ca5
SC
190}
191
e7549107 192bool wxClipboard::Flush()
e9576ca5 193{
3dee36ae 194 return false;
e7549107
SC
195}
196
197bool wxClipboard::Open()
198{
3dee36ae 199 wxCHECK_MSG( !m_open, false, wxT("clipboard already open") );
3e822cd8
DS
200
201 m_open = true;
202
203 return true;
e7549107
SC
204}
205
206bool wxClipboard::IsOpened() const
207{
f0822896 208 return m_open;
e9576ca5
SC
209}
210
f0822896 211bool wxClipboard::SetData( wxDataObject *data )
e9576ca5 212{
3dee36ae 213 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
3dee36ae 214 wxCHECK_MSG( data, false, wxT("data is invalid") );
634bafa9
SC
215
216 Clear();
3e822cd8
DS
217
218 // as we can only store one wxDataObject,
219 // this is the same in this implementation
f0822896 220 return AddData( data );
e7549107
SC
221}
222
223bool wxClipboard::AddData( wxDataObject *data )
224{
3dee36ae 225 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
3dee36ae 226 wxCHECK_MSG( data, false, wxT("data is invalid") );
e7549107 227
3e822cd8 228 // we can only store one wxDataObject
f0822896 229 Clear();
e7549107 230
f0822896 231 m_data = data;
e7549107 232
21ec3bf9 233 // get formats from wxDataObjects
f0822896
SC
234 wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ];
235 m_data->GetAllFormats( array );
e7549107 236
f0822896
SC
237 for (size_t i = 0; i < m_data->GetFormatCount(); i++)
238 {
89a3d0f7
RD
239 if (array[i].IsStandard())
240 {
241 wxLogTrace( TRACE_CLIPBOARD,
242 wxT("wxClipboard now supports standard atom type %d"),
243 array[i].GetType() );
244 }
245 else
246 {
247 wxLogTrace( TRACE_CLIPBOARD,
248 wxT("wxClipboard now supports atom %s"),
249 array[i].GetId().c_str() );
250 }
e7549107 251
3e822cd8
DS
252 size_t sz = data->GetDataSize( array[ i ] );
253 void* buf = malloc( sz + 1 );
e542ecc6 254 if ( buf != NULL )
3dee36ae 255 {
99b62b5f 256 // empty the buffer because in some case GetDataHere does not fill buf
e542ecc6
DS
257 memset( buf, 0, sz + 1 );
258 data->GetDataHere( array[ i ], buf );
3e822cd8 259 OSType mactype = 0;
634bafa9
SC
260 switch ( array[i].GetType() )
261 {
3e822cd8
DS
262 case wxDF_TEXT:
263 case wxDF_OEMTEXT:
264 mactype = kScrapFlavorTypeText;
265 sz -= 1;
266 break;
267
268#if wxUSE_UNICODE
269 case wxDF_UNICODETEXT:
270 mactype = kScrapFlavorTypeUnicode;
271 sz -= 2;
272 break;
273#endif
274
275#if wxUSE_DRAG_AND_DROP
634bafa9 276 case wxDF_METAFILE:
3e822cd8
DS
277 mactype = kScrapFlavorTypePicture;
278 break;
279#endif
280
281 case wxDF_BITMAP:
282 case wxDF_DIB:
283 mactype = kScrapFlavorTypePicture;
284 break;
285
286 default:
e542ecc6 287 mactype = (OSType)(array[ i ].GetFormatId());
3e822cd8 288 break;
634bafa9 289 }
3e822cd8
DS
290
291 UMAPutScrap( sz , mactype , buf );
292 free( buf );
634bafa9 293 }
e9576ca5
SC
294 }
295
3e822cd8 296 delete [] array;
e9576ca5 297
3e822cd8 298 return true;
e9576ca5
SC
299}
300
f0822896 301void wxClipboard::Close()
e9576ca5 302{
634bafa9
SC
303 wxCHECK_RET( m_open, wxT("clipboard not open") );
304
3e822cd8 305 m_open = false;
3dee36ae 306
3e822cd8
DS
307 // Get rid of cached object.
308 // If this is not done, copying data from
309 // another application will only work once
89a69c60
SC
310 if (m_data)
311 {
312 delete m_data;
313 m_data = (wxDataObject*) NULL;
3dee36ae 314 }
e9576ca5
SC
315}
316
f0822896 317bool wxClipboard::IsSupported( const wxDataFormat &dataFormat )
e7549107 318{
3dee36ae 319 if ( m_data )
3e822cd8
DS
320 return m_data->IsSupported( dataFormat );
321
e542ecc6
DS
322 bool hasData = false;
323
f0822896 324#if TARGET_CARBON
ed60b502
RR
325 OSStatus err = noErr;
326 ScrapRef scrapRef;
e135f093 327
ed60b502 328 err = GetCurrentScrap( &scrapRef );
e135f093 329 if ( err != noTypeErr && err != memFullErr )
ed60b502 330 {
3e822cd8
DS
331 ScrapFlavorFlags flavorFlags;
332 Size byteCount;
e135f093 333
3e822cd8
DS
334 err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags );
335 if (err == noErr)
ed60b502 336 {
3e822cd8
DS
337 err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount );
338 if (err == noErr)
e542ecc6 339 hasData = true;
ed60b502 340 }
3271d737
SC
341 else if ( dataFormat.GetType() == wxDF_UNICODETEXT )
342 {
343 err = GetScrapFlavorFlags( scrapRef, 'TEXT', &flavorFlags );
344 if (err == noErr)
345 {
346 err = GetScrapFlavorSize( scrapRef, 'TEXT', &byteCount );
347 if (err == noErr)
348 hasData = true;
349 }
350 }
ed60b502 351 }
3e822cd8 352
f0822896 353#else
e542ecc6
DS
354
355 long offset = 0;
3e822cd8
DS
356 Handle datahandle = NewHandle( 0 );
357 HLock( datahandle );
358 GetScrap( datahandle, dataFormat.GetFormatId(), &offset );
359 HUnlock( datahandle );
e542ecc6 360 hasData = GetHandleSize( datahandle ) > 0;
3e822cd8 361 DisposeHandle( datahandle );
e542ecc6 362#endif
3e822cd8
DS
363
364 return hasData;
e9576ca5 365}
f0822896
SC
366
367bool wxClipboard::GetData( wxDataObject& data )
e9576ca5 368{
3dee36ae 369 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
e9576ca5 370
3e822cd8
DS
371 size_t formatcount = data.GetFormatCount() + 1;
372 wxDataFormat *array = new wxDataFormat[ formatcount ];
f0822896
SC
373 array[0] = data.GetPreferredFormat();
374 data.GetAllFormats( &array[1] );
e9576ca5 375
3e822cd8 376 bool transferred = false;
e9576ca5 377
f0822896
SC
378 if ( m_data )
379 {
3e822cd8 380 for (size_t i = 0; !transferred && i < formatcount; i++)
21ec3bf9 381 {
3e822cd8 382 wxDataFormat format = array[ i ];
21ec3bf9 383 if ( m_data->IsSupported( format ) )
f0822896 384 {
3e822cd8
DS
385 int dataSize = m_data->GetDataSize( format );
386 transferred = true;
21ec3bf9 387
3e822cd8 388 if (dataSize == 0)
21ec3bf9 389 {
3e822cd8 390 data.SetData( format, 0, 0 );
21ec3bf9
SC
391 }
392 else
393 {
3e822cd8 394 char *d = new char[ dataSize ];
e542ecc6 395 m_data->GetDataHere( format, (void*)d );
3e822cd8
DS
396 data.SetData( format, dataSize, d );
397 delete [] d;
21ec3bf9 398 }
f0822896 399 }
21ec3bf9 400 }
f0822896 401 }
3e822cd8
DS
402
403 // get formats from wxDataObjects
e135f093 404 if ( !transferred )
f0822896 405 {
3e822cd8 406 for (size_t i = 0; !transferred && i < formatcount; i++)
21ec3bf9 407 {
3e822cd8 408 wxDataFormat format = array[ i ];
21ec3bf9
SC
409
410 switch ( format.GetType() )
411 {
412 // NOTE: this is usable for all data types
3e822cd8 413 case wxDF_TEXT:
21ec3bf9 414 case wxDF_UNICODETEXT:
3e822cd8
DS
415 case wxDF_OEMTEXT:
416 case wxDF_BITMAP:
417 case wxDF_METAFILE:
418 default:
21ec3bf9 419 {
3e822cd8
DS
420 long len;
421 char* s = (char*)wxGetClipboardData( format, &len );
422 if (s != NULL)
21ec3bf9 423 {
3e822cd8 424 data.SetData( format, len, s );
21ec3bf9
SC
425 delete [] s;
426
3e822cd8 427 transferred = true;
21ec3bf9
SC
428 }
429 }
3e822cd8 430 break;
21ec3bf9
SC
431 }
432 }
f0822896 433 }
e9576ca5 434
3e822cd8 435 delete [] array;
e542ecc6 436
3e822cd8 437 return transferred;
f0822896 438}
179e085f
RN
439
440#endif