1///////////////////////////////////////////////////////////////////////////// 2// Name: src/mac/carbon/clipbrd.cpp 3// Purpose: Clipboard functionality 4// Author: Stefan Csomor; 5// Generalized clipboard implementation by Matthew Flatt 6// Modified by: 7// Created: 1998-01-01 8// RCS-ID: $Id: clipbrd.cpp 46161 2007-05-22 06:02:49Z SC $ 9// Copyright: (c) Stefan Csomor 10// Licence: wxWindows licence 11///////////////////////////////////////////////////////////////////////////// 12 13#include "wx/wxprec.h" 14 15#if wxUSE_CLIPBOARD 16 17#include "wx/clipbrd.h" 18 19#ifndef WX_PRECOMP 20 #include "wx/intl.h" 21 #include "wx/log.h" 22 #include "wx/app.h" 23 #include "wx/utils.h" 24 #include "wx/frame.h" 25 #include "wx/bitmap.h" 26#endif 27 28#include "wx/metafile.h" 29 30#include "wx/mac/uma.h" 31 32#define wxUSE_DATAOBJ 1 33 34#include <string.h> 35 36 37// the trace mask we use with wxLogTrace() - call 38// wxLog::AddTraceMask(TRACE_CLIPBOARD) to enable the trace messages from here 39// (there will be a *lot* of them!) 40static const wxChar *TRACE_CLIPBOARD = wxT("clipboard"); 41 42IMPLEMENT_DYNAMIC_CLASS(wxClipboard, wxObject) 43 44// in order to keep the binary interface the same this class 45// serves just to have a few additional member variables inside 46// the clipboard class 47 48class wxMacBinaryCompatHelper : public wxDataObject 49{ 50public : 51 wxMacBinaryCompatHelper() 52 { 53 m_trueData = NULL; 54 } 55 56 ~wxMacBinaryCompatHelper() 57 { 58 if (m_trueData != NULL) 59 { 60 delete m_trueData; 61 m_trueData = NULL; 62 } 63 } 64 65 virtual wxDataFormat GetPreferredFormat(Direction dir = Get) const 66 { 67 return wxDataFormat(); 68 } 69 70 virtual size_t GetFormatCount(Direction dir = Get) const 71 { 72 return 0; 73 } 74 75 virtual void GetAllFormats(wxDataFormat *formats, 76 Direction dir = Get) const 77 { 78 } 79 80 virtual size_t GetDataSize(const wxDataFormat& format) const 81 { 82 return 0; 83 } 84 85 virtual bool GetDataHere(const wxDataFormat& format, void *buf) const 86 { 87 return false; 88 } 89 90 // only relevant from here on 91 92 wxDataObject* m_trueData; 93 wxCFRef<PasteboardRef> m_pasteboard; 94}; 95 96#define M_CLIPBOARD ((wxMacBinaryCompatHelper*)m_data) 97 98wxClipboard::wxClipboard() 99{ 100 m_open = false; 101 m_data = new wxMacBinaryCompatHelper() ; 102 PasteboardRef clipboard = 0; 103 OSStatus err = PasteboardCreate( kPasteboardClipboard, &clipboard ); 104 if (err != noErr) 105 { 106 wxLogSysError( wxT("Failed to create the clipboard.") ); 107 } 108 M_CLIPBOARD->m_pasteboard.reset(clipboard); 109} 110 111wxClipboard::~wxClipboard() 112{ 113 M_CLIPBOARD->m_pasteboard.reset((PasteboardRef)0); 114 delete m_data; 115} 116 117void wxClipboard::Clear() 118{ 119 if (M_CLIPBOARD->m_trueData != NULL) 120 { 121 delete M_CLIPBOARD->m_trueData; 122 M_CLIPBOARD->m_trueData = NULL; 123 } 124 125 OSStatus err = PasteboardClear( M_CLIPBOARD->m_pasteboard ); 126 if (err != noErr) 127 { 128 wxLogSysError( wxT("Failed to empty the clipboard.") ); 129 } 130} 131 132bool wxClipboard::Flush() 133{ 134 return false; 135} 136 137bool wxClipboard::Open() 138{ 139 wxCHECK_MSG( !m_open, false, wxT("clipboard already open") ); 140 141 m_open = true; 142 143 return true; 144} 145 146bool wxClipboard::IsOpened() const 147{ 148 return m_open; 149} 150 151bool wxClipboard::SetData( wxDataObject *data ) 152{ 153 wxCHECK_MSG( m_open, false, wxT("clipboard not open") ); 154 wxCHECK_MSG( data, false, wxT("data is invalid") ); 155 156 Clear(); 157 158 // as we can only store one wxDataObject, 159 // this is the same in this implementation 160 return AddData( data ); 161} 162 163bool wxClipboard::AddData( wxDataObject *data ) 164{ 165 wxCHECK_MSG( m_open, false, wxT("clipboard not open") ); 166 wxCHECK_MSG( data, false, wxT("data is invalid") ); 167 168 // we can only store one wxDataObject 169 Clear(); 170 171 PasteboardSyncFlags syncFlags = PasteboardSynchronize( M_CLIPBOARD->m_pasteboard ); 172 wxCHECK_MSG( !(syncFlags&kPasteboardModified), false, wxT("clipboard modified after clear") ); 173 wxCHECK_MSG( (syncFlags&kPasteboardClientIsOwner), false, wxT("client couldn't own clipboard") ); 174 175 M_CLIPBOARD->m_trueData = data; 176 177 data->AddToPasteboard( M_CLIPBOARD->m_pasteboard, 1 ); 178 179 return true; 180} 181 182void wxClipboard::Close() 183{ 184 wxCHECK_RET( m_open, wxT("clipboard not open") ); 185 186 m_open = false; 187 188 // Get rid of cached object. 189 // If this is not done, copying data from 190 // another application will only work once 191 if (M_CLIPBOARD->m_trueData) 192 { 193 delete M_CLIPBOARD->m_trueData; 194 M_CLIPBOARD->m_trueData = (wxDataObject*) NULL; 195 } 196} 197 198bool wxClipboard::IsSupported( const wxDataFormat &dataFormat ) 199{ 200 if ( M_CLIPBOARD->m_trueData ) 201 return M_CLIPBOARD->m_trueData->IsSupported( dataFormat ); 202 return wxDataObject::IsFormatInPasteboard( M_CLIPBOARD->m_pasteboard, dataFormat ); 203} 204 205bool wxClipboard::GetData( wxDataObject& data ) 206{ 207 wxCHECK_MSG( m_open, false, wxT("clipboard not open") ); 208 209 size_t formatcount = data.GetFormatCount() + 1; 210 wxDataFormat *array = new wxDataFormat[ formatcount ]; 211 array[0] = data.GetPreferredFormat(); 212 data.GetAllFormats( &array[1] ); 213 214 bool transferred = false; 215 216 if ( M_CLIPBOARD->m_trueData ) 217 { 218 for (size_t i = 0; !transferred && i < formatcount; i++) 219 { 220 wxDataFormat format = array[ i ]; 221 if ( M_CLIPBOARD->m_trueData->IsSupported( format ) ) 222 { 223 int dataSize = M_CLIPBOARD->m_trueData->GetDataSize( format ); 224 transferred = true; 225 226 if (dataSize == 0) 227 { 228 data.SetData( format, 0, 0 ); 229 } 230 else 231 { 232 char *d = new char[ dataSize ]; 233 M_CLIPBOARD->m_trueData->GetDataHere( format, (void*)d ); 234 data.SetData( format, dataSize, d ); 235 delete [] d; 236 } 237 } 238 } 239 } 240 241 // get formats from wxDataObjects 242 if ( !transferred ) 243 { 244 transferred = data.GetFromPasteboard( M_CLIPBOARD->m_pasteboard ) ; 245 } 246 247 delete [] array; 248 249 return transferred; 250} 251 252#endif 253