Update ooo320-m1
[ooovba.git] / dtrans / source / win32 / dtobj / DOTransferable.cxx
blobcc8975baa124b5df3a80c2e202f7a4ff0ddf1b65
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: DOTransferable.cxx,v $
10 * $Revision: 1.26 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_dtrans.hxx"
34 //------------------------------------------------------------------------
35 // includes
36 //------------------------------------------------------------------------
37 #include <sal/types.h>
38 #include <rtl/process.h>
40 #ifndef _DOWRAPPERTRANSFERABLE_HXX_
41 #include "DOTransferable.hxx"
42 #endif
43 #include "..\misc\ImplHelper.hxx"
44 #include "..\misc\WinClip.hxx"
45 #include "DTransHelper.hxx"
46 #include "..\misc\ImplHelper.hxx"
47 #include "TxtCnvtHlp.hxx"
48 #include "MimeAttrib.hxx"
49 #include "FmtFilter.hxx"
50 #include "Fetc.hxx"
53 #if(_MSC_VER < 1300) && !defined(__MINGW32__)
54 #include <olestd.h>
55 #endif
57 #define STR2(x) #x
58 #define STR(x) STR2(x)
59 #define PRAGMA_MSG( msg ) message( __FILE__ "(" STR(__LINE__) "): " #msg )
61 //------------------------------------------------------------------------
62 // namespace directives
63 //------------------------------------------------------------------------
65 using namespace rtl;
66 using namespace std;
67 using namespace osl;
68 using namespace cppu;
69 using namespace com::sun::star::uno;
70 using namespace com::sun::star::datatransfer;
71 using namespace com::sun::star::io;
72 using namespace com::sun::star::lang;
73 using namespace com::sun::star::container;
75 //------------------------------------------------------------------------
76 //
77 //------------------------------------------------------------------------
79 namespace
81 const Type CPPUTYPE_SEQINT8 = getCppuType( ( Sequence< sal_Int8 >* )0 );
82 const Type CPPUTYPE_OUSTRING = getCppuType( (OUString*)0 );
84 inline
85 sal_Bool isValidFlavor( const DataFlavor& aFlavor )
87 return ( aFlavor.MimeType.getLength( ) &&
88 ( ( aFlavor.DataType == CPPUTYPE_SEQINT8 ) ||
89 ( aFlavor.DataType == CPPUTYPE_OUSTRING ) ) );
92 } // end namespace
95 //------------------------------------------------------------------------
96 // ctor
97 //------------------------------------------------------------------------
99 CDOTransferable::CDOTransferable(
100 const Reference< XMultiServiceFactory >& ServiceManager, IDataObjectPtr rDataObject ) :
101 m_rDataObject( rDataObject ),
102 m_SrvMgr( ServiceManager ),
103 m_DataFormatTranslator( m_SrvMgr ),
104 m_bUnicodeRegistered( sal_False ),
105 m_TxtFormatOnClipboard( CF_INVALID )
109 //------------------------------------------------------------------------
111 //------------------------------------------------------------------------
113 Any SAL_CALL CDOTransferable::getTransferData( const DataFlavor& aFlavor )
114 throw( UnsupportedFlavorException, IOException, RuntimeException )
116 OSL_ASSERT( isValidFlavor( aFlavor ) );
118 MutexGuard aGuard( m_aMutex );
120 //------------------------------------------------
121 // convert dataflavor to formatetc
122 //------------------------------------------------
124 CFormatEtc fetc = m_DataFormatTranslator.getFormatEtcFromDataFlavor( aFlavor );
125 OSL_ASSERT( CF_INVALID != fetc.getClipformat() );
127 //------------------------------------------------
128 // get the data from clipboard in a byte stream
129 //------------------------------------------------
131 ByteSequence_t clipDataStream;
135 clipDataStream = getClipboardData( fetc );
137 catch( UnsupportedFlavorException& )
139 if ( m_DataFormatTranslator.isUnicodeTextFormat( fetc.getClipformat( ) ) &&
140 m_bUnicodeRegistered )
142 OUString aUnicodeText = synthesizeUnicodeText( );
143 Any aAny = makeAny( aUnicodeText );
144 return aAny;
146 else
147 throw; // pass through exception
150 //------------------------------------------------
151 // return the data as any
152 //------------------------------------------------
154 return byteStreamToAny( clipDataStream, aFlavor.DataType );
157 //------------------------------------------------------------------------
158 // getTransferDataFlavors
159 //------------------------------------------------------------------------
161 Sequence< DataFlavor > SAL_CALL CDOTransferable::getTransferDataFlavors( )
162 throw( RuntimeException )
164 return m_FlavorList;
167 //------------------------------------------------------------------------
168 // isDataFlavorSupported
169 // returns true if we find a DataFlavor with the same MimeType and
170 // DataType
171 //------------------------------------------------------------------------
173 sal_Bool SAL_CALL CDOTransferable::isDataFlavorSupported( const DataFlavor& aFlavor )
174 throw( RuntimeException )
176 OSL_ASSERT( isValidFlavor( aFlavor ) );
178 for ( sal_Int32 i = 0; i < m_FlavorList.getLength( ); i++ )
179 if ( compareDataFlavors( aFlavor, m_FlavorList[i] ) )
180 return sal_True;
182 return sal_False;
185 //------------------------------------------------------------------------
186 // helper function
187 // the list of datafalvors currently on the clipboard will be initialized
188 // only once; if the client of this Transferable will hold a reference
189 // to it und the underlying clipboard content changes, the client does
190 // possible operate on a invalid list
191 // if there is only text on the clipboard we will also offer unicode text
192 // an synthesize this format on the fly if requested, to accomplish this
193 // we save the first offered text format which we will later use for the
194 // conversion
195 //------------------------------------------------------------------------
197 void SAL_CALL CDOTransferable::initFlavorList( )
199 IEnumFORMATETCPtr pEnumFormatEtc;
200 HRESULT hr = m_rDataObject->EnumFormatEtc( DATADIR_GET, &pEnumFormatEtc );
201 if ( SUCCEEDED( hr ) )
203 pEnumFormatEtc->Reset( );
205 FORMATETC fetc;
206 while ( S_FALSE != pEnumFormatEtc->Next( 1, &fetc, NULL ) )
208 // we use locales only to determine the
209 // charset if there is text on the cliboard
210 // we don't offer this format
211 if ( CF_LOCALE == fetc.cfFormat )
212 continue;
214 DataFlavor aFlavor = formatEtcToDataFlavor( fetc );
216 // if text or oemtext is offered we also pretend to have unicode text
217 if ( m_DataFormatTranslator.isOemOrAnsiTextFormat( fetc.cfFormat ) &&
218 !m_bUnicodeRegistered )
220 addSupportedFlavor( aFlavor );
222 m_TxtFormatOnClipboard = fetc.cfFormat;
223 m_bUnicodeRegistered = sal_True;
225 // register unicode text as accompany format
226 aFlavor = formatEtcToDataFlavor(
227 m_DataFormatTranslator.getFormatEtcForClipformat( CF_UNICODETEXT ) );
228 addSupportedFlavor( aFlavor );
230 else if ( (CF_UNICODETEXT == fetc.cfFormat) && !m_bUnicodeRegistered )
232 addSupportedFlavor( aFlavor );
233 m_bUnicodeRegistered = sal_True;
235 else
236 addSupportedFlavor( aFlavor );
238 // see MSDN IEnumFORMATETC
239 CoTaskMemFree( fetc.ptd );
244 //------------------------------------------------------------------------
246 //------------------------------------------------------------------------
248 inline
249 void SAL_CALL CDOTransferable::addSupportedFlavor( const DataFlavor& aFlavor )
251 // we ignore all formats that couldn't be translated
252 if ( aFlavor.MimeType.getLength( ) )
254 OSL_ASSERT( isValidFlavor( aFlavor ) );
256 m_FlavorList.realloc( m_FlavorList.getLength( ) + 1 );
257 m_FlavorList[m_FlavorList.getLength( ) - 1] = aFlavor;
261 //------------------------------------------------------------------------
262 // helper function
263 //------------------------------------------------------------------------
265 //inline
266 DataFlavor SAL_CALL CDOTransferable::formatEtcToDataFlavor( const FORMATETC& aFormatEtc )
268 DataFlavor aFlavor;
269 LCID lcid = 0;
271 // for non-unicode text format we must provid a locale to get
272 // the character-set of the text, if there is no locale on the
273 // clipboard we assume the text is in a charset appropriate for
274 // the current thread locale
275 if ( (CF_TEXT == aFormatEtc.cfFormat) || (CF_OEMTEXT == aFormatEtc.cfFormat) )
276 lcid = getLocaleFromClipboard( );
278 return m_DataFormatTranslator.getDataFlavorFromFormatEtc( aFormatEtc, lcid );
281 //------------------------------------------------------------------------
282 // returns the current locale on clipboard; if there is no locale on
283 // clipboard the function returns the current thread locale
284 //------------------------------------------------------------------------
286 LCID SAL_CALL CDOTransferable::getLocaleFromClipboard( )
288 LCID lcid = GetThreadLocale( );
292 CFormatEtc fetc = m_DataFormatTranslator.getFormatEtcForClipformat( CF_LOCALE );
293 ByteSequence_t aLCIDSeq = getClipboardData( fetc );
294 lcid = *(reinterpret_cast<LCID*>( aLCIDSeq.getArray( ) ) );
296 // because of a Win95/98 Bug; there the high word
297 // of a locale has the same value as the
298 // low word e.g. 0x07040704 that's not right
299 // correct is 0x00000704
300 lcid &= 0x0000FFFF;
302 catch(...)
304 // we take the default locale
307 return lcid;
310 //------------------------------------------------------------------------
311 // i think it's not necessary to call ReleaseStgMedium
312 // in case of failures because nothing should have been
313 // allocated etc.
314 //------------------------------------------------------------------------
316 CDOTransferable::ByteSequence_t SAL_CALL CDOTransferable::getClipboardData( CFormatEtc& aFormatEtc )
318 STGMEDIUM stgmedium;
319 HRESULT hr = m_rDataObject->GetData( aFormatEtc, &stgmedium );
321 // in case of failure to get a WMF metafile handle, try to get a memory block
322 if( FAILED( hr ) &&
323 ( CF_METAFILEPICT == aFormatEtc.getClipformat() ) &&
324 ( TYMED_MFPICT == aFormatEtc.getTymed() ) )
326 CFormatEtc aTempFormat( aFormatEtc );
327 aTempFormat.setTymed( TYMED_HGLOBAL );
328 hr = m_rDataObject->GetData( aTempFormat, &stgmedium );
331 if ( FAILED( hr ) )
333 OSL_ASSERT( (hr != E_INVALIDARG) &&
334 (hr != DV_E_DVASPECT) &&
335 (hr != DV_E_LINDEX) &&
336 (hr != DV_E_TYMED) );
338 if ( DV_E_FORMATETC == hr )
339 throw UnsupportedFlavorException( );
340 else if ( STG_E_MEDIUMFULL == hr )
341 throw IOException( );
342 else
343 throw RuntimeException( );
346 ByteSequence_t byteStream;
350 if ( CF_ENHMETAFILE == aFormatEtc.getClipformat() )
351 byteStream = WinENHMFPictToOOMFPict( stgmedium.hEnhMetaFile );
352 else if (CF_HDROP == aFormatEtc.getClipformat())
353 byteStream = CF_HDROPToFileList(stgmedium.hGlobal);
354 else
356 clipDataToByteStream( aFormatEtc.getClipformat( ), stgmedium, byteStream );
358 // format conversion if necessary
359 if ( CF_DIB == aFormatEtc.getClipformat() )
360 byteStream = WinDIBToOOBMP( byteStream );
361 else if ( CF_METAFILEPICT == aFormatEtc.getClipformat() )
362 byteStream = WinMFPictToOOMFPict( byteStream );
365 ReleaseStgMedium( &stgmedium );
367 catch( CStgTransferHelper::CStgTransferException& )
369 ReleaseStgMedium( &stgmedium );
370 throw IOException( );
373 return byteStream;
376 //------------------------------------------------------------------------
378 //------------------------------------------------------------------------
380 OUString SAL_CALL CDOTransferable::synthesizeUnicodeText( )
382 ByteSequence_t aTextSequence;
383 CFormatEtc fetc;
384 LCID lcid = getLocaleFromClipboard( );
385 sal_uInt32 cpForTxtCnvt = 0;
387 if ( CF_TEXT == m_TxtFormatOnClipboard )
389 fetc = m_DataFormatTranslator.getFormatEtcForClipformat( CF_TEXT );
390 aTextSequence = getClipboardData( fetc );
392 // determine the codepage used for text conversion
393 cpForTxtCnvt = getWinCPFromLocaleId( lcid, LOCALE_IDEFAULTANSICODEPAGE ).toInt32( );
395 else if ( CF_OEMTEXT == m_TxtFormatOnClipboard )
397 fetc = m_DataFormatTranslator.getFormatEtcForClipformat( CF_OEMTEXT );
398 aTextSequence = getClipboardData( fetc );
400 // determine the codepage used for text conversion
401 cpForTxtCnvt = getWinCPFromLocaleId( lcid, LOCALE_IDEFAULTCODEPAGE ).toInt32( );
403 else
404 OSL_ASSERT( sal_False );
406 CStgTransferHelper stgTransferHelper;
408 // convert the text
409 MultiByteToWideCharEx( cpForTxtCnvt,
410 reinterpret_cast<char*>( aTextSequence.getArray( ) ),
411 sal::static_int_cast<sal_uInt32>(-1), // Huh ?
412 stgTransferHelper,
413 sal_False);
415 CRawHGlobalPtr ptrHGlob(stgTransferHelper);
416 sal_Unicode* pWChar = reinterpret_cast<sal_Unicode*>(ptrHGlob.GetMemPtr());
418 return OUString(pWChar);
421 //------------------------------------------------------------------------
423 //------------------------------------------------------------------------
425 void CDOTransferable::clipDataToByteStream( CLIPFORMAT cf, STGMEDIUM stgmedium, ByteSequence_t& aByteSequence )
427 CStgTransferHelper memTransferHelper;
429 switch( stgmedium.tymed )
431 case TYMED_HGLOBAL:
432 memTransferHelper.init( stgmedium.hGlobal );
433 break;
435 case TYMED_MFPICT:
436 memTransferHelper.init( stgmedium.hMetaFilePict );
437 break;
439 case TYMED_ENHMF:
440 memTransferHelper.init( stgmedium.hEnhMetaFile );
441 break;
443 case TYMED_ISTREAM:
444 #ifdef _MSC_VER
445 #pragma PRAGMA_MSG( Has to be implemented )
446 #endif
447 break;
449 default:
450 throw UnsupportedFlavorException( );
451 break;
454 int nMemSize = memTransferHelper.memSize( cf );
455 aByteSequence.realloc( nMemSize );
456 memTransferHelper.read( aByteSequence.getArray( ), nMemSize );
459 //------------------------------------------------------------------------
461 //------------------------------------------------------------------------
463 inline
464 Any CDOTransferable::byteStreamToAny( ByteSequence_t& aByteStream, const Type& aRequestedDataType )
466 Any aAny;
468 if ( aRequestedDataType == CPPUTYPE_OUSTRING )
470 OUString str = byteStreamToOUString( aByteStream );
471 aAny = makeAny( str );
473 else
474 aAny = makeAny( aByteStream );
476 return aAny;
479 //------------------------------------------------------------------------
481 //------------------------------------------------------------------------
483 inline
484 OUString CDOTransferable::byteStreamToOUString( ByteSequence_t& aByteStream )
486 sal_Int32 nWChars;
487 sal_Int32 nMemSize = aByteStream.getLength( );
489 // if there is a trailing L"\0" substract 1 from length
490 if ( 0 == aByteStream[ aByteStream.getLength( ) - 2 ] &&
491 0 == aByteStream[ aByteStream.getLength( ) - 1 ] )
492 nWChars = static_cast< sal_Int32 >( nMemSize / sizeof( sal_Unicode ) ) - 1;
493 else
494 nWChars = static_cast< sal_Int32 >( nMemSize / sizeof( sal_Unicode ) );
496 return OUString( reinterpret_cast< sal_Unicode* >( aByteStream.getArray( ) ), nWChars );
499 //------------------------------------------------------------------------
501 //------------------------------------------------------------------------
503 sal_Bool SAL_CALL CDOTransferable::compareDataFlavors(
504 const DataFlavor& lhs, const DataFlavor& rhs )
506 if ( !m_rXMimeCntFactory.is( ) )
508 m_rXMimeCntFactory = Reference< XMimeContentTypeFactory >( m_SrvMgr->createInstance(
509 OUString::createFromAscii( "com.sun.star.datatransfer.MimeContentTypeFactory" ) ), UNO_QUERY );
511 OSL_ASSERT( m_rXMimeCntFactory.is( ) );
513 sal_Bool bRet = sal_False;
517 Reference< XMimeContentType > xLhs( m_rXMimeCntFactory->createMimeContentType( lhs.MimeType ) );
518 Reference< XMimeContentType > xRhs( m_rXMimeCntFactory->createMimeContentType( rhs.MimeType ) );
520 if ( cmpFullMediaType( xLhs, xRhs ) )
522 bRet = cmpAllContentTypeParameter( xLhs, xRhs );
525 catch( IllegalArgumentException& )
527 OSL_ENSURE( sal_False, "Invalid content type detected" );
528 bRet = sal_False;
531 return bRet;
534 //------------------------------------------------------------------------
536 //------------------------------------------------------------------------
538 sal_Bool SAL_CALL CDOTransferable::cmpFullMediaType(
539 const Reference< XMimeContentType >& xLhs, const Reference< XMimeContentType >& xRhs ) const
541 return xLhs->getFullMediaType().equalsIgnoreAsciiCase( xRhs->getFullMediaType( ) );
544 //------------------------------------------------------------------------
546 //------------------------------------------------------------------------
548 sal_Bool SAL_CALL CDOTransferable::cmpAllContentTypeParameter(
549 const Reference< XMimeContentType >& xLhs, const Reference< XMimeContentType >& xRhs ) const
551 Sequence< OUString > xLhsFlavors = xLhs->getParameters( );
552 Sequence< OUString > xRhsFlavors = xRhs->getParameters( );
553 sal_Bool bRet = sal_True;
557 if ( xLhsFlavors.getLength( ) == xRhsFlavors.getLength( ) )
559 OUString pLhs;
560 OUString pRhs;
562 for ( sal_Int32 i = 0; i < xLhsFlavors.getLength( ); i++ )
564 pLhs = xLhs->getParameterValue( xLhsFlavors[i] );
565 pRhs = xRhs->getParameterValue( xLhsFlavors[i] );
567 if ( !pLhs.equalsIgnoreAsciiCase( pRhs ) )
569 bRet = sal_False;
570 break;
574 else
575 bRet = sal_False;
577 catch( NoSuchElementException& )
579 bRet = sal_False;
581 catch( IllegalArgumentException& )
583 bRet = sal_False;
586 return bRet;
589 ::com::sun::star::uno::Any SAL_CALL CDOTransferable::getData( const Sequence< sal_Int8>& aProcessId )
590 throw (::com::sun::star::uno::RuntimeException)
592 Any retVal;
594 sal_uInt8 * arProcCaller= (sal_uInt8*)(sal_Int8*) aProcessId.getConstArray();
595 sal_uInt8 arId[16];
596 rtl_getGlobalProcessId(arId);
597 if( ! memcmp( arId, arProcCaller,16))
599 if (m_rDataObject.is())
601 IDataObject* pObj= m_rDataObject.get();
602 pObj->AddRef();
603 retVal.setValue( &pObj, getCppuType((sal_uInt32*)0));
606 return retVal;