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