]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/clipbrd.cpp
Include wx/dynarray.h according to precompiled headers of wx/wx.h (with other minor...
[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 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 }
251
252 size_t sz = data->GetDataSize( array[ i ] );
253 void* buf = malloc( sz + 1 );
254 if ( buf != NULL )
255 {
256 // empty the buffer because in some case GetDataHere does not fill buf
257 memset( buf, 0, sz + 1 );
258 data->GetDataHere( array[ i ], buf );
259 OSType mactype = 0;
260 switch ( array[i].GetType() )
261 {
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
276 case wxDF_METAFILE:
277 mactype = kScrapFlavorTypePicture;
278 break;
279 #endif
280
281 case wxDF_BITMAP:
282 case wxDF_DIB:
283 mactype = kScrapFlavorTypePicture;
284 break;
285
286 default:
287 mactype = (OSType)(array[ i ].GetFormatId());
288 break;
289 }
290
291 UMAPutScrap( sz , mactype , buf );
292 free( buf );
293 }
294 }
295
296 delete [] array;
297
298 return true;
299 }
300
301 void wxClipboard::Close()
302 {
303 wxCHECK_RET( m_open, wxT("clipboard not open") );
304
305 m_open = false;
306
307 // Get rid of cached object.
308 // If this is not done, copying data from
309 // another application will only work once
310 if (m_data)
311 {
312 delete m_data;
313 m_data = (wxDataObject*) NULL;
314 }
315 }
316
317 bool wxClipboard::IsSupported( const wxDataFormat &dataFormat )
318 {
319 if ( m_data )
320 return m_data->IsSupported( dataFormat );
321
322 bool hasData = false;
323
324 #if TARGET_CARBON
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 err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags );
335 if (err == noErr)
336 {
337 err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount );
338 if (err == noErr)
339 hasData = true;
340 }
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 }
351 }
352
353 #else
354
355 long offset = 0;
356 Handle datahandle = NewHandle( 0 );
357 HLock( datahandle );
358 GetScrap( datahandle, dataFormat.GetFormatId(), &offset );
359 HUnlock( datahandle );
360 hasData = GetHandleSize( datahandle ) > 0;
361 DisposeHandle( datahandle );
362 #endif
363
364 return hasData;
365 }
366
367 bool wxClipboard::GetData( wxDataObject& data )
368 {
369 wxCHECK_MSG( m_open, false, wxT("clipboard not open") );
370
371 size_t formatcount = data.GetFormatCount() + 1;
372 wxDataFormat *array = new wxDataFormat[ formatcount ];
373 array[0] = data.GetPreferredFormat();
374 data.GetAllFormats( &array[1] );
375
376 bool transferred = false;
377
378 if ( m_data )
379 {
380 for (size_t i = 0; !transferred && i < formatcount; i++)
381 {
382 wxDataFormat format = array[ i ];
383 if ( m_data->IsSupported( format ) )
384 {
385 int dataSize = m_data->GetDataSize( format );
386 transferred = true;
387
388 if (dataSize == 0)
389 {
390 data.SetData( format, 0, 0 );
391 }
392 else
393 {
394 char *d = new char[ dataSize ];
395 m_data->GetDataHere( format, (void*)d );
396 data.SetData( format, dataSize, d );
397 delete [] d;
398 }
399 }
400 }
401 }
402
403 // get formats from wxDataObjects
404 if ( !transferred )
405 {
406 for (size_t i = 0; !transferred && i < formatcount; i++)
407 {
408 wxDataFormat format = array[ i ];
409
410 switch ( format.GetType() )
411 {
412 // NOTE: this is usable for all data types
413 case wxDF_TEXT:
414 case wxDF_UNICODETEXT:
415 case wxDF_OEMTEXT:
416 case wxDF_BITMAP:
417 case wxDF_METAFILE:
418 default:
419 {
420 long len;
421 char* s = (char*)wxGetClipboardData( format, &len );
422 if (s != NULL)
423 {
424 data.SetData( format, len, s );
425 delete [] s;
426
427 transferred = true;
428 }
429 }
430 break;
431 }
432 }
433 }
434
435 delete [] array;
436
437 return transferred;
438 }
439
440 #endif