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