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