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