]> git.saurik.com Git - wxWidgets.git/blob - src/mac/clipbrd.cpp
942a17c6fb9f7ec927d913fe707ee3c5c3f3bb16
[wxWidgets.git] / src / mac / clipbrd.cpp
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!)
38 static const wxChar *TRACE_CLIPBOARD = _T("clipboard");
39
40 void *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
162 IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject)
163
164 wxClipboard::wxClipboard()
165 {
166 m_open = false ;
167 m_data = NULL ;
168 }
169
170 wxClipboard::~wxClipboard()
171 {
172 if (m_data)
173 {
174 delete m_data;
175 m_data = (wxDataObject*) NULL;
176 }
177 }
178
179 void 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
199 bool wxClipboard::Flush()
200 {
201 return FALSE;
202 }
203
204 bool wxClipboard::Open()
205 {
206 wxCHECK_MSG( !m_open, FALSE, wxT("clipboard already open") );
207 m_open = true ;
208 return true ;
209 }
210
211 bool wxClipboard::IsOpened() const
212 {
213 return m_open;
214 }
215
216 bool 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
227 bool 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
313 void wxClipboard::Close()
314 {
315 m_open = false ;
316 }
317
318 bool 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
356 bool 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 }