]> git.saurik.com Git - wxWidgets.git/blame - src/mac/carbon/clipbrd.cpp
no message
[wxWidgets.git] / src / mac / carbon / clipbrd.cpp
CommitLineData
e9576ca5
SC
1/////////////////////////////////////////////////////////////////////////////
2// Name: clipbrd.cpp
3// Purpose: Clipboard functionality
a31a5f85 4// Author: Stefan Csomor
e9576ca5 5// Modified by:
a31a5f85 6// Created: 1998-01-01
e9576ca5 7// RCS-ID: $Id$
a31a5f85 8// Copyright: (c) Stefan Csomor
ed60b502 9// Licence: wxWindows licence
e9576ca5
SC
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation
14#pragma implementation "clipbrd.h"
15#endif
16
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
9c3c5849 29#include "wx/mac/uma.h"
76a5e5d2 30
2f1ae414
SC
31#define wxUSE_DATAOBJ 1
32
e9576ca5
SC
33#include <string.h>
34
f0822896
SC
35// the trace mask we use with wxLogTrace() - call
36// wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here
37// (there will be a *lot* of them!)
38static const wxChar *TRACE_CLIPBOARD = _T("clipboard");
2f1ae414 39
f0822896 40void *wxGetClipboardData(wxDataFormat dataFormat, long *len)
e9576ca5 41{
2f1ae414 42#if !TARGET_CARBON
ed60b502 43 OSErr err = noErr ;
2f1ae414 44#else
ed60b502 45 OSStatus err = noErr ;
2f1ae414 46#endif
e40298d5
JS
47 void * data = NULL ;
48 Size byteCount;
ed60b502 49
2f1ae414
SC
50 switch (dataFormat.GetType())
51 {
e40298d5
JS
52 case wxDF_OEMTEXT:
53 dataFormat = wxDF_TEXT;
54 // fall through
55
56 case wxDF_TEXT:
57 break;
427ff662
SC
58 case wxDF_UNICODETEXT:
59 break;
e40298d5
JS
60 case wxDF_BITMAP :
61 case wxDF_METAFILE :
62 break ;
63 default:
64 {
65 wxLogError(_("Unsupported clipboard format."));
66 return NULL;
67 }
97af5088 68 }
e40298d5 69
97af5088 70#if TARGET_CARBON
ed60b502
RR
71 ScrapRef scrapRef;
72
73 err = GetCurrentScrap( &scrapRef );
74 if ( err != noTypeErr && err != memFullErr )
75 {
76 ScrapFlavorFlags flavorFlags;
ed60b502
RR
77
78 if (( err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags )) == noErr)
79 {
80 if (( err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount )) == noErr)
81 {
427ff662
SC
82 Size allocSize = byteCount ;
83 if ( dataFormat.GetType() == wxDF_TEXT )
84 allocSize += 1 ;
85 else if ( dataFormat.GetType() == wxDF_UNICODETEXT )
86 allocSize += 2 ;
ed60b502 87
427ff662
SC
88 data = new char[ allocSize ] ;
89
e40298d5
JS
90 if (( err = GetScrapFlavorData( scrapRef, dataFormat.GetFormatId(), &byteCount , data )) == noErr )
91 {
427ff662 92 *len = allocSize ;
e40298d5
JS
93 if ( dataFormat.GetType() == wxDF_TEXT )
94 ((char*)data)[byteCount] = 0 ;
427ff662
SC
95 if ( dataFormat.GetType() == wxDF_UNICODETEXT )
96 ((wxChar*)data)[byteCount/2] = 0 ;
e40298d5
JS
97 }
98 else
99 {
100 delete[] ((char *)data) ;
101 data = NULL ;
102 }
ed60b502
RR
103 }
104 }
105 }
106
97af5088 107#else
ed60b502
RR
108 long offset ;
109 Handle datahandle = NewHandle(0) ;
110 HLock( datahandle ) ;
111 GetScrap( datahandle , dataFormat.GetFormatId() , &offset ) ;
112 HUnlock( datahandle ) ;
113 if ( GetHandleSize( datahandle ) > 0 )
114 {
e40298d5 115 byteCount = GetHandleSize( datahandle ) ;
427ff662 116 Size allocSize = byteCount ;
e40298d5 117 if ( dataFormat.GetType() == wxDF_TEXT )
427ff662
SC
118 allocSize += 1 ;
119 else if ( dataFormat.GetType() == wxDF_UNICODETEXT )
120 allocSize += 2 ;
121
122 data = new char[ allocSize ] ;
123
e40298d5
JS
124 memcpy( (char*) data , (char*) *datahandle , byteCount ) ;
125 if ( dataFormat.GetType() == wxDF_TEXT )
126 ((char*)data)[byteCount] = 0 ;
427ff662
SC
127 if ( dataFormat.GetType() == wxDF_UNICODETEXT )
128 ((wxChar*)data)[byteCount/2] = 0 ;
e40298d5 129 *len = byteCount ;
ed60b502
RR
130 }
131 DisposeHandle( datahandle ) ;
97af5088
SC
132#endif
133 if ( err )
134 {
135 wxLogSysError(_("Failed to get clipboard data."));
e40298d5 136
97af5088
SC
137 return NULL ;
138 }
427ff662 139
97af5088
SC
140 if ( dataFormat.GetType() == wxDF_TEXT && wxApp::s_macDefaultEncodingIsPC )
141 {
427ff662
SC
142 wxString st = wxMacMakeStringFromCString( (char*) data ) ;
143#if wxUSE_UNICODE
144 wxCharBuffer buf = st.ToAscii() ;
145#else
146 char* buf = st ;
147#endif
148 char* newdata = new char[strlen(buf)+1] ;
149 memcpy( newdata , buf , strlen(buf)+1 ) ;
150 delete[] ((char*) data ) ;
151 data = newdata ;
97af5088 152 }
427ff662 153
97af5088 154 return data;
2f1ae414
SC
155}
156
157
e9576ca5
SC
158/*
159 * Generalized clipboard implementation by Matthew Flatt
160 */
161
528e2293 162IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
7c74e7fe 163
e7549107
SC
164wxClipboard::wxClipboard()
165{
e40298d5
JS
166 m_open = false ;
167 m_data = NULL ;
e7549107 168}
e9576ca5 169
e7549107 170wxClipboard::~wxClipboard()
e9576ca5 171{
f0822896 172 if (m_data)
e7549107 173 {
f0822896
SC
174 delete m_data;
175 m_data = (wxDataObject*) NULL;
e7549107 176 }
e9576ca5
SC
177}
178
e7549107 179void wxClipboard::Clear()
e9576ca5 180{
f0822896
SC
181 if (m_data)
182 {
183 delete m_data;
184 m_data = (wxDataObject*) NULL;
185 }
186#if TARGET_CARBON
ed60b502
RR
187 OSStatus err ;
188 err = ClearCurrentScrap( );
f0822896 189#else
ed60b502
RR
190 OSErr err ;
191 err = ZeroScrap( );
f0822896 192#endif
ed60b502
RR
193 if ( err )
194 {
f0822896 195 wxLogSysError(_("Failed to empty the clipboard."));
ed60b502 196 }
e9576ca5
SC
197}
198
e7549107 199bool wxClipboard::Flush()
e9576ca5 200{
e7549107
SC
201 return FALSE;
202}
203
204bool wxClipboard::Open()
205{
f0822896
SC
206 wxCHECK_MSG( !m_open, FALSE, wxT("clipboard already open") );
207 m_open = true ;
208 return true ;
e7549107
SC
209}
210
211bool wxClipboard::IsOpened() const
212{
f0822896 213 return m_open;
e9576ca5
SC
214}
215
f0822896 216bool wxClipboard::SetData( wxDataObject *data )
e9576ca5 217{
f0822896 218 wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
e9576ca5 219
f0822896 220 wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
e9576ca5 221
f0822896 222 Clear();
e7549107 223
f0822896 224 return AddData( data );
e7549107
SC
225}
226
227bool wxClipboard::AddData( wxDataObject *data )
228{
f0822896 229 wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
e7549107 230
f0822896 231 wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
e7549107 232
f0822896
SC
233 /* we can only store one wxDataObject */
234 Clear();
e7549107 235
f0822896 236 m_data = data;
e7549107 237
f0822896
SC
238 /* get formats from wxDataObjects */
239 wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ];
240 m_data->GetAllFormats( array );
e7549107 241
f0822896
SC
242 for (size_t i = 0; i < m_data->GetFormatCount(); i++)
243 {
244 wxLogTrace( TRACE_CLIPBOARD,
245 wxT("wxClipboard now supports atom %s"),
246 array[i].GetId().c_str() );
e7549107 247
f0822896 248#if !TARGET_CARBON
0cd51b2d 249 OSErr err = noErr ;
f0822896 250#else
0cd51b2d 251 OSStatus err = noErr ;
f0822896 252#endif
e7549107 253
f0822896
SC
254 switch ( array[i].GetType() )
255 {
256 case wxDF_TEXT:
257 case wxDF_OEMTEXT:
258 {
259 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
260 wxString str(textDataObject->GetText());
427ff662
SC
261 wxCharBuffer buf = wxMacStringToCString( str ) ;
262 err = UMAPutScrap( strlen(buf) , kScrapFlavorTypeText , (void*) buf.data() ) ;
f0822896 263 }
d1171566 264 break ;
427ff662
SC
265#if wxUSE_UNICODE
266 case wxDF_UNICODETEXT :
267 {
268 wxTextDataObject* textDataObject = (wxTextDataObject*) data;
269 wxString str(textDataObject->GetText());
270 err = UMAPutScrap( str.Length() * sizeof(wxChar) , kScrapFlavorTypeUnicode , (void*) str.wc_str() ) ;
271 }
272 break ;
273#endif
f0822896 274#if wxUSE_DRAG_AND_DROP
e7549107 275 case wxDF_METAFILE:
f0822896 276 {
e40298d5 277 wxMetafileDataObject* metaFileDataObject =
f0822896 278 (wxMetafileDataObject*) data;
e40298d5
JS
279 wxMetafile metaFile = metaFileDataObject->GetMetafile();
280 PicHandle pict = (PicHandle) metaFile.GetHMETAFILE() ;
281 HLock( (Handle) pict ) ;
427ff662 282 err = UMAPutScrap( GetHandleSize( (Handle) pict ) , kScrapFlavorTypePicture , *pict ) ;
e40298d5 283 HUnlock( (Handle) pict ) ;
f0822896 284 }
d1171566 285 break ;
e7549107 286#endif
f0822896
SC
287 case wxDF_BITMAP:
288 case wxDF_DIB:
9c3c5849 289 {
e40298d5
JS
290 bool created = false ;
291 PicHandle pict = NULL ;
292
293 wxBitmapDataObject* bitmapDataObject = (wxBitmapDataObject*) data ;
294 pict = (PicHandle) bitmapDataObject->GetBitmap().GetPict( &created ) ;
295
296 HLock( (Handle) pict ) ;
427ff662 297 err = UMAPutScrap( GetHandleSize( (Handle) pict ) , kScrapFlavorTypePicture , *pict ) ;
e40298d5
JS
298 HUnlock( (Handle) pict ) ;
299 if ( created )
300 KillPicture( pict ) ;
9c3c5849 301 }
f0822896 302 default:
ed60b502 303 break ;
f0822896 304 }
e9576ca5 305
e9576ca5
SC
306 }
307
f0822896 308 delete[] array;
e9576ca5 309
f0822896 310 return true ;
e9576ca5
SC
311}
312
f0822896 313void wxClipboard::Close()
e9576ca5 314{
f0822896 315 m_open = false ;
e9576ca5
SC
316}
317
f0822896 318bool wxClipboard::IsSupported( const wxDataFormat &dataFormat )
e7549107 319{
f0822896
SC
320 if ( m_data )
321 {
322 return m_data->IsSupported( dataFormat ) ;
e9576ca5 323 }
f0822896 324#if TARGET_CARBON
ed60b502
RR
325 OSStatus err = noErr;
326 ScrapRef scrapRef;
327
328 err = GetCurrentScrap( &scrapRef );
329 if ( err != noTypeErr && err != memFullErr )
330 {
331 ScrapFlavorFlags flavorFlags;
332 Size byteCount;
333
334 if (( err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags )) == noErr)
335 {
336 if (( err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount )) == noErr)
337 {
338 return TRUE ;
339 }
340 }
341 }
342 return FALSE;
343
f0822896 344#else
ed60b502
RR
345 long offset ;
346 Handle datahandle = NewHandle(0) ;
347 HLock( datahandle ) ;
348 GetScrap( datahandle , dataFormat.GetFormatId() , &offset ) ;
349 HUnlock( datahandle ) ;
350 bool hasData = GetHandleSize( datahandle ) > 0 ;
351 DisposeHandle( datahandle ) ;
352 return hasData ;
f0822896 353#endif
e9576ca5 354}
f0822896
SC
355
356bool wxClipboard::GetData( wxDataObject& data )
e9576ca5 357{
f0822896 358 wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
e9576ca5 359
3340066a 360 size_t formatcount = data.GetFormatCount() + 1 ;
f0822896
SC
361 wxDataFormat *array = new wxDataFormat[ formatcount ];
362 array[0] = data.GetPreferredFormat();
363 data.GetAllFormats( &array[1] );
e9576ca5 364
f0822896 365 bool transferred = false ;
e9576ca5 366
f0822896
SC
367 if ( m_data )
368 {
369 for (size_t i = 0; !transferred && i < formatcount ; i++)
370 {
371 wxDataFormat format = array[i] ;
372 if ( m_data->IsSupported( format ) )
373 {
374 int size = m_data->GetDataSize( format );
375 transferred = true ;
e7549107 376
f0822896
SC
377 if (size == 0)
378 {
379 data.SetData(format , 0 , 0 ) ;
380 }
381 else
382 {
383 char *d = new char[size];
384 m_data->GetDataHere( format , (void*) d );
385 data.SetData( format , size , d ) ;
386 delete[] d ;
387 }
388 }
389 }
390 }
391 /* get formats from wxDataObjects */
392 if ( !transferred )
393 {
f0822896
SC
394 for (size_t i = 0; !transferred && i < formatcount ; i++)
395 {
396 wxDataFormat format = array[i] ;
397
398 switch ( format.GetType() )
399 {
9c3c5849
SC
400 case wxDF_TEXT :
401 case wxDF_OEMTEXT :
402 case wxDF_BITMAP :
403 case wxDF_METAFILE :
f0822896
SC
404 {
405 long len ;
406 char* s = (char*)wxGetClipboardData(format, &len );
407 if ( s )
408 {
409 data.SetData( format , len , s ) ;
410 delete [] s;
411
412 transferred = true ;
413 }
414 }
e40298d5 415 break ;
d1171566 416
f0822896
SC
417 default :
418 break ;
419 }
420 }
421 }
e9576ca5 422
f0822896
SC
423 delete[] array ;
424 return transferred ;
425}