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