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