]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/mac/clipbrd.cpp
extracted duplicated code from src/*/data.cpp in a common file
[wxWidgets.git] / src / mac / clipbrd.cpp
... / ...
CommitLineData
1/////////////////////////////////////////////////////////////////////////////
2// Name: clipbrd.cpp
3// Purpose: Clipboard functionality
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
7// RCS-ID: $Id$
8// Copyright: (c) Stefan Csomor
9// Licence: wxWindows licence
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"
23#include "wx/intl.h"
24#include "wx/log.h"
25
26#ifndef __DARWIN__
27#include <Scrap.h>
28#endif
29#include "wx/mac/uma.h"
30
31#define wxUSE_DATAOBJ 1
32
33#include <string.h>
34
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");
39
40void *wxGetClipboardData(wxDataFormat dataFormat, long *len)
41{
42#if !TARGET_CARBON
43 OSErr err = noErr ;
44#else
45 OSStatus err = noErr ;
46#endif
47 void * data = NULL ;
48 Size byteCount;
49
50 switch (dataFormat.GetType())
51 {
52 case wxDF_OEMTEXT:
53 dataFormat = wxDF_TEXT;
54 // fall through
55
56 case wxDF_TEXT:
57 break;
58 case wxDF_UNICODETEXT:
59 break;
60 case wxDF_BITMAP :
61 case wxDF_METAFILE :
62 break ;
63 default:
64 {
65 wxLogError(_("Unsupported clipboard format."));
66 return NULL;
67 }
68 }
69
70#if TARGET_CARBON
71 ScrapRef scrapRef;
72
73 err = GetCurrentScrap( &scrapRef );
74 if ( err != noTypeErr && err != memFullErr )
75 {
76 ScrapFlavorFlags flavorFlags;
77
78 if (( err = GetScrapFlavorFlags( scrapRef, dataFormat.GetFormatId(), &flavorFlags )) == noErr)
79 {
80 if (( err = GetScrapFlavorSize( scrapRef, dataFormat.GetFormatId(), &byteCount )) == 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 ((wxChar*)data)[byteCount/2] = 0 ;
97 }
98 else
99 {
100 delete[] ((char *)data) ;
101 data = NULL ;
102 }
103 }
104 }
105 }
106
107#else
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 {
115 byteCount = GetHandleSize( datahandle ) ;
116 Size allocSize = byteCount ;
117 if ( dataFormat.GetType() == wxDF_TEXT )
118 allocSize += 1 ;
119 else if ( dataFormat.GetType() == wxDF_UNICODETEXT )
120 allocSize += 2 ;
121
122 data = new char[ allocSize ] ;
123
124 memcpy( (char*) data , (char*) *datahandle , byteCount ) ;
125 if ( dataFormat.GetType() == wxDF_TEXT )
126 ((char*)data)[byteCount] = 0 ;
127 if ( dataFormat.GetType() == wxDF_UNICODETEXT )
128 ((wxChar*)data)[byteCount/2] = 0 ;
129 *len = byteCount ;
130 }
131 DisposeHandle( datahandle ) ;
132#endif
133 if ( err )
134 {
135 wxLogSysError(_("Failed to get clipboard data."));
136
137 return NULL ;
138 }
139
140 if ( dataFormat.GetType() == wxDF_TEXT && wxApp::s_macDefaultEncodingIsPC )
141 {
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 ;
152 }
153
154 return data;
155}
156
157
158/*
159 * Generalized clipboard implementation by Matthew Flatt
160 */
161
162IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
163
164wxClipboard::wxClipboard()
165{
166 m_open = false ;
167 m_data = NULL ;
168}
169
170wxClipboard::~wxClipboard()
171{
172 if (m_data)
173 {
174 delete m_data;
175 m_data = (wxDataObject*) NULL;
176 }
177}
178
179void wxClipboard::Clear()
180{
181 if (m_data)
182 {
183 delete m_data;
184 m_data = (wxDataObject*) NULL;
185 }
186#if TARGET_CARBON
187 OSStatus err ;
188 err = ClearCurrentScrap( );
189#else
190 OSErr err ;
191 err = ZeroScrap( );
192#endif
193 if ( err )
194 {
195 wxLogSysError(_("Failed to empty the clipboard."));
196 }
197}
198
199bool wxClipboard::Flush()
200{
201 return FALSE;
202}
203
204bool wxClipboard::Open()
205{
206 wxCHECK_MSG( !m_open, FALSE, wxT("clipboard already open") );
207 m_open = true ;
208 return true ;
209}
210
211bool wxClipboard::IsOpened() const
212{
213 return m_open;
214}
215
216bool wxClipboard::SetData( wxDataObject *data )
217{
218 wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
219
220 wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
221
222 Clear();
223
224 return AddData( data );
225}
226
227bool wxClipboard::AddData( wxDataObject *data )
228{
229 wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
230
231 wxCHECK_MSG( data, FALSE, wxT("data is invalid") );
232
233 /* we can only store one wxDataObject */
234 Clear();
235
236 m_data = data;
237
238 /* get formats from wxDataObjects */
239 wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ];
240 m_data->GetAllFormats( array );
241
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() );
247
248#if !TARGET_CARBON
249 OSErr err = noErr ;
250#else
251 OSStatus err = noErr ;
252#endif
253
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());
261 wxCharBuffer buf = wxMacStringToCString( str ) ;
262 err = UMAPutScrap( strlen(buf) , kScrapFlavorTypeText , (void*) buf.data() ) ;
263 }
264 break ;
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
274#if wxUSE_DRAG_AND_DROP
275 case wxDF_METAFILE:
276 {
277 wxMetafileDataObject* metaFileDataObject =
278 (wxMetafileDataObject*) data;
279 wxMetafile metaFile = metaFileDataObject->GetMetafile();
280 PicHandle pict = (PicHandle) metaFile.GetHMETAFILE() ;
281 HLock( (Handle) pict ) ;
282 err = UMAPutScrap( GetHandleSize( (Handle) pict ) , kScrapFlavorTypePicture , *pict ) ;
283 HUnlock( (Handle) pict ) ;
284 }
285 break ;
286#endif
287 case wxDF_BITMAP:
288 case wxDF_DIB:
289 {
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 ) ;
297 err = UMAPutScrap( GetHandleSize( (Handle) pict ) , kScrapFlavorTypePicture , *pict ) ;
298 HUnlock( (Handle) pict ) ;
299 if ( created )
300 KillPicture( pict ) ;
301 }
302 default:
303 break ;
304 }
305
306 }
307
308 delete[] array;
309
310 return true ;
311}
312
313void wxClipboard::Close()
314{
315 m_open = false ;
316}
317
318bool wxClipboard::IsSupported( const wxDataFormat &dataFormat )
319{
320 if ( m_data )
321 {
322 return m_data->IsSupported( dataFormat ) ;
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 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
344#else
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 ;
353#endif
354}
355
356bool wxClipboard::GetData( wxDataObject& data )
357{
358 wxCHECK_MSG( m_open, FALSE, wxT("clipboard not open") );
359
360 size_t formatcount = data.GetFormatCount() + 1 ;
361 wxDataFormat *array = new wxDataFormat[ formatcount ];
362 array[0] = data.GetPreferredFormat();
363 data.GetAllFormats( &array[1] );
364
365 bool transferred = false ;
366
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 ;
376
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 {
394 for (size_t i = 0; !transferred && i < formatcount ; i++)
395 {
396 wxDataFormat format = array[i] ;
397
398 switch ( format.GetType() )
399 {
400 case wxDF_TEXT :
401 case wxDF_OEMTEXT :
402 case wxDF_BITMAP :
403 case wxDF_METAFILE :
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 }
415 break ;
416
417 default :
418 break ;
419 }
420 }
421 }
422
423 delete[] array ;
424 return transferred ;
425}