xref: /aoo42x/main/svtools/source/misc/transfer.cxx (revision 8809675e)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_svtools.hxx"
24 #ifdef WNT
25 #include <tools/prewin.h>
26 #if defined _MSC_VER
27 #pragma warning(push, 1)
28 #pragma warning(disable: 4917)
29 #endif
30 #include <shlobj.h>
31 #if defined _MSC_VER
32 #pragma warning(pop)
33 #endif
34 #include <tools/postwin.h>
35 #endif
36 #include <vos/mutex.hxx>
37 #include <rtl/memory.h>
38 #include <rtl/uuid.h>
39 #include <rtl/uri.hxx>
40 #include <tools/debug.hxx>
41 #include <tools/urlobj.hxx>
42 #include <unotools/ucbstreamhelper.hxx>
43 #include <sot/exchange.hxx>
44 #include <sot/storage.hxx>
45 #include <vcl/bitmap.hxx>
46 #include <vcl/gdimtf.hxx>
47 #include <vcl/graph.hxx>
48 #include <vcl/cvtgrf.hxx>
49 #include <vcl/svapp.hxx>
50 #include <vcl/window.hxx>
51 #include <comphelper/processfactory.hxx>
52 #include <sot/filelist.hxx>
53 #include <cppuhelper/implbase1.hxx>
54 
55 #include <comphelper/seqstream.hxx>
56 #include <com/sun/star/datatransfer/clipboard/XClipboardNotifier.hpp>
57 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
58 #include <com/sun/star/datatransfer/XMimeContentTypeFactory.hpp>
59 #include <com/sun/star/datatransfer/XMimeContentType.hpp>
60 #include <com/sun/star/frame/XDesktop.hpp>
61 #include <com/sun/star/lang/XInitialization.hpp>
62 
63 #include "svl/urlbmk.hxx"
64 #include "inetimg.hxx"
65 #include <svtools/wmf.hxx>
66 #include <svtools/imap.hxx>
67 #include <svtools/transfer.hxx>
68 #include <cstdio>
69 #include <vcl/dibtools.hxx>
70 #include <vcl/pngread.hxx>
71 #include <vcl/pngwrite.hxx>
72 
73 // --------------
74 // - Namespaces -
75 // --------------
76 
77 using namespace ::com::sun::star::uno;
78 using namespace ::com::sun::star::lang;
79 using namespace ::com::sun::star::frame;
80 using namespace ::com::sun::star::io;
81 using namespace ::com::sun::star::datatransfer;
82 using namespace ::com::sun::star::datatransfer::clipboard;
83 using namespace ::com::sun::star::datatransfer::dnd;
84 
85 // --------------------------------
86 // - TransferableObjectDescriptor -
87 // --------------------------------
88 
89 #define TOD_SIG1 0x01234567
90 #define TOD_SIG2 0x89abcdef
91 
operator >>(SvStream & rIStm,TransferableObjectDescriptor & rObjDesc)92 SvStream& operator>>( SvStream& rIStm, TransferableObjectDescriptor& rObjDesc )
93 {
94 	sal_uInt32  nSize, nViewAspect, nSig1, nSig2;
95 
96 	rIStm >> nSize;
97 	rIStm >> rObjDesc.maClassName;
98 	rIStm >> nViewAspect;
99 	rIStm >> rObjDesc.maSize.Width();
100     rIStm >> rObjDesc.maSize.Height();
101 	rIStm >> rObjDesc.maDragStartPos.X();
102 	rIStm >> rObjDesc.maDragStartPos.Y();
103 	rIStm.ReadByteString( rObjDesc.maTypeName, gsl_getSystemTextEncoding() );
104 	rIStm.ReadByteString( rObjDesc.maDisplayName, gsl_getSystemTextEncoding() );
105     rIStm >> nSig1 >> nSig2;
106 
107     rObjDesc.mnViewAspect = static_cast< sal_uInt16 >( nViewAspect );
108 
109     // don't use width/height info from external objects
110     if( ( TOD_SIG1 != nSig1 ) || ( TOD_SIG2 != nSig2 ) )
111     {
112         rObjDesc.maSize.Width() = 0;
113         rObjDesc.maSize.Height() = 0;
114     }
115 
116 	return rIStm;
117 }
118 
119 // -----------------------------------------------------------------------------
120 
operator <<(SvStream & rOStm,const TransferableObjectDescriptor & rObjDesc)121 SvStream& operator<<( SvStream& rOStm, const TransferableObjectDescriptor& rObjDesc )
122 {
123 	const sal_uInt32    nFirstPos = rOStm.Tell(), nViewAspect = rObjDesc.mnViewAspect;
124 	const sal_uInt32    nSig1 = TOD_SIG1, nSig2 = TOD_SIG2;
125 
126 	rOStm.SeekRel( 4 );
127 	rOStm << rObjDesc.maClassName;
128 	rOStm << nViewAspect;
129 	rOStm << rObjDesc.maSize.Width();
130 	rOStm << rObjDesc.maSize.Height();
131 	rOStm << rObjDesc.maDragStartPos.X();
132 	rOStm << rObjDesc.maDragStartPos.Y();
133 	rOStm.WriteByteString( rObjDesc.maTypeName, gsl_getSystemTextEncoding() );
134 	rOStm.WriteByteString( rObjDesc.maDisplayName, gsl_getSystemTextEncoding() );
135 	rOStm << nSig1 << nSig2;
136 
137 	const sal_uInt32 nLastPos = rOStm.Tell();
138 
139 	rOStm.Seek( nFirstPos );
140 	rOStm << ( nLastPos - nFirstPos );
141 	rOStm.Seek( nLastPos );
142 
143 	return rOStm;
144 }
145 
146 // -----------------------------------------------------------------------------
147 // the reading of the parameter is done using the special service ::com::sun::star::datatransfer::MimeContentType,
148 // a similar approach should be implemented for creation of the mimetype string;
149 // for now the set of acceptable characters has to be hardcoded, in future it should be part of the service that creates the mimetype
150 const ::rtl::OUString aQuotedParamChars = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "()<>@,;:/[]?=!#$&'*+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~. " ) );
151 
ImplGetParameterString(const TransferableObjectDescriptor & rObjDesc)152 static ::rtl::OUString ImplGetParameterString( const TransferableObjectDescriptor& rObjDesc )
153 {
154     const ::rtl::OUString   aChar( ::rtl::OUString::createFromAscii( "\"" ) );
155     const ::rtl::OUString   aClassName( rObjDesc.maClassName.GetHexName() );
156     ::rtl::OUString         aParams;
157 
158     if( aClassName.getLength() )
159     {
160         aParams += ::rtl::OUString::createFromAscii( ";classname=\"" );
161         aParams += aClassName;
162         aParams += aChar;
163     }
164 
165     if( rObjDesc.maTypeName.Len() )
166     {
167         aParams += ::rtl::OUString::createFromAscii( ";typename=\"" );
168         aParams += rObjDesc.maTypeName;
169         aParams += aChar;
170     }
171 
172     if( rObjDesc.maDisplayName.Len() )
173     {
174         // the display name might contain unacceptable characters, encode all of them
175         // this seems to be the only parameter currently that might contain such characters
176         sal_Bool pToAccept[128];
177         for ( sal_Int32 nBInd = 0; nBInd < 128; nBInd++ )
178             pToAccept[nBInd] = sal_False;
179 
180         for ( sal_Int32 nInd = 0; nInd < aQuotedParamChars.getLength(); nInd++ )
181         {
182             sal_Unicode nChar = aQuotedParamChars.getStr()[nInd];
183             if ( nChar < 128 )
184                 pToAccept[nChar] = sal_True;
185         }
186 
187         aParams += ::rtl::OUString::createFromAscii( ";displayname=\"" );
188         aParams += ::rtl::Uri::encode( rObjDesc.maDisplayName, pToAccept, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8 );
189         aParams += aChar;
190     }
191 
192     aParams += ::rtl::OUString::createFromAscii( ";viewaspect=\"" );
193     aParams += ::rtl::OUString::valueOf( static_cast< sal_Int32 >( rObjDesc.mnViewAspect ) );
194     aParams += aChar;
195 
196     aParams += ::rtl::OUString::createFromAscii( ";width=\"" );
197     aParams += ::rtl::OUString::valueOf( rObjDesc.maSize.Width() );
198     aParams += aChar;
199 
200     aParams += ::rtl::OUString::createFromAscii( ";height=\"" );
201     aParams += ::rtl::OUString::valueOf( rObjDesc.maSize.Height() );
202     aParams += aChar;
203 
204     aParams += ::rtl::OUString::createFromAscii( ";posx=\"" );
205     aParams += ::rtl::OUString::valueOf( rObjDesc.maDragStartPos.X() );
206     aParams += aChar;
207 
208     aParams += ::rtl::OUString::createFromAscii( ";posy=\"" );
209     aParams += ::rtl::OUString::valueOf( rObjDesc.maDragStartPos.X() );
210     aParams += aChar;
211 
212     return aParams;
213 }
214 
215 // -----------------------------------------------------------------------------
216 
ImplSetParameterString(TransferableObjectDescriptor & rObjDesc,const DataFlavorEx & rFlavorEx)217 static void ImplSetParameterString( TransferableObjectDescriptor& rObjDesc, const DataFlavorEx& rFlavorEx )
218 {
219     Reference< XMultiServiceFactory >       xFact( ::comphelper::getProcessServiceFactory() );
220     Reference< XMimeContentTypeFactory >    xMimeFact;
221 
222     try
223     {
224         if( xFact.is() )
225         {
226             xMimeFact = Reference< XMimeContentTypeFactory >( xFact->createInstance( ::rtl::OUString::createFromAscii(
227                                                               "com.sun.star.datatransfer.MimeContentTypeFactory" ) ),
228                                                               UNO_QUERY );
229         }
230 
231         if( xMimeFact.is() )
232         {
233             Reference< XMimeContentType > xMimeType( xMimeFact->createMimeContentType( rFlavorEx.MimeType ) );
234 
235             if( xMimeType.is() )
236             {
237                 const ::rtl::OUString aClassNameString( ::rtl::OUString::createFromAscii( "classname" ) );
238                 const ::rtl::OUString aTypeNameString( ::rtl::OUString::createFromAscii( "typename" ) );
239                 const ::rtl::OUString aDisplayNameString( ::rtl::OUString::createFromAscii( "displayname" ) );
240                 const ::rtl::OUString aViewAspectString( ::rtl::OUString::createFromAscii( "viewaspect" ) );
241                 const ::rtl::OUString aWidthString( ::rtl::OUString::createFromAscii( "width" ) );
242                 const ::rtl::OUString aHeightString( ::rtl::OUString::createFromAscii( "height" ) );
243                 const ::rtl::OUString aPosXString( ::rtl::OUString::createFromAscii( "posx" ) );
244                 const ::rtl::OUString aPosYString( ::rtl::OUString::createFromAscii( "posy" ) );
245 
246                 if( xMimeType->hasParameter( aClassNameString ) )
247                 {
248                     rObjDesc.maClassName.MakeId( xMimeType->getParameterValue( aClassNameString ) );
249                 }
250 
251                 if( xMimeType->hasParameter( aTypeNameString ) )
252                 {
253                     rObjDesc.maTypeName = xMimeType->getParameterValue( aTypeNameString );
254                 }
255 
256                 if( xMimeType->hasParameter( aDisplayNameString ) )
257                 {
258                     // the display name might contain unacceptable characters, in this case they should be encoded
259                     // this seems to be the only parameter currently that might contain such characters
260                     rObjDesc.maDisplayName = ::rtl::Uri::decode( xMimeType->getParameterValue( aDisplayNameString ), rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
261                 }
262 
263                 if( xMimeType->hasParameter( aViewAspectString ) )
264                 {
265                     rObjDesc.mnViewAspect = static_cast< sal_uInt16 >( xMimeType->getParameterValue( aViewAspectString ).toInt32() );
266                 }
267 
268                 if( xMimeType->hasParameter( aWidthString ) )
269                 {
270                     rObjDesc.maSize.Width() = xMimeType->getParameterValue( aWidthString ).toInt32();
271                 }
272 
273                 if( xMimeType->hasParameter( aHeightString ) )
274                 {
275                     rObjDesc.maSize.Height() = xMimeType->getParameterValue( aHeightString ).toInt32();
276                 }
277 
278                 if( xMimeType->hasParameter( aPosXString ) )
279                 {
280                     rObjDesc.maDragStartPos.X() = xMimeType->getParameterValue( aPosXString ).toInt32();
281                 }
282 
283                 if( xMimeType->hasParameter( aPosYString ) )
284                 {
285                     rObjDesc.maDragStartPos.Y() = xMimeType->getParameterValue( aPosYString ).toInt32();
286                 }
287             }
288         }
289     }
290     catch( const ::com::sun::star::uno::Exception& )
291     {
292     }
293 }
294 
295 // -----------------------------------------
296 // - TransferableHelper::TerminateListener -
297 // -----------------------------------------
298 
TerminateListener(TransferableHelper & rTransferableHelper)299 TransferableHelper::TerminateListener::TerminateListener( TransferableHelper& rTransferableHelper ) :
300 	mrParent( rTransferableHelper )
301 {
302 }
303 
304 // -----------------------------------------------------------------------------
305 
~TerminateListener()306 TransferableHelper::TerminateListener::~TerminateListener()
307 {
308 }
309 
310 // -----------------------------------------------------------------------------
311 
disposing(const EventObject &)312 void SAL_CALL TransferableHelper::TerminateListener::disposing( const EventObject& ) throw( RuntimeException )
313 {
314 }
315 
316 // -----------------------------------------------------------------------------
317 
queryTermination(const EventObject &)318 void SAL_CALL TransferableHelper::TerminateListener::queryTermination( const EventObject& ) throw( TerminationVetoException, RuntimeException )
319 {
320 }
321 
322 // -----------------------------------------------------------------------------
323 
notifyTermination(const EventObject &)324 void SAL_CALL TransferableHelper::TerminateListener::notifyTermination( const EventObject& ) throw( RuntimeException )
325 {
326 	mrParent.ImplFlush();
327 }
328 
329 // ----------------------
330 // - TransferableHelper -
331 // ----------------------
332 
TransferableHelper()333 TransferableHelper::TransferableHelper() :
334 	mpFormats( new DataFlavorExVector ),
335     mpObjDesc( NULL )
336 {
337 }
338 
339 // -----------------------------------------------------------------------------
340 
~TransferableHelper()341 TransferableHelper::~TransferableHelper()
342 {
343     delete mpObjDesc;
344 	delete mpFormats;
345 }
346 
347 // -----------------------------------------------------------------------------
348 
getTransferData(const DataFlavor & rFlavor)349 Any SAL_CALL TransferableHelper::getTransferData( const DataFlavor& rFlavor ) throw( UnsupportedFlavorException, IOException, RuntimeException )
350 {
351 	if( !maAny.hasValue() || !mpFormats->size() || ( maLastFormat != rFlavor.MimeType ) )
352 	{
353 		const ::vos::OGuard aGuard( Application::GetSolarMutex() );
354 
355 		maLastFormat = rFlavor.MimeType;
356 		maAny = Any();
357 
358 		try
359 		{
360     	    DataFlavor  aSubstFlavor;
361             sal_Bool    bDone = sal_False;
362 
363 			// add formats if not already done
364             if( !mpFormats->size() )
365 				AddSupportedFormats();
366 
367 	        // check alien formats first and try to get a substitution format
368             if( SotExchange::GetFormatDataFlavor( FORMAT_STRING, aSubstFlavor ) &&
369                 TransferableDataHelper::IsEqual( aSubstFlavor, rFlavor ) )
370             {
371 			    GetData( aSubstFlavor );
372                 bDone = maAny.hasValue();
373             }
374             else if(SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_BMP, aSubstFlavor )
375                 && TransferableDataHelper::IsEqual( aSubstFlavor, rFlavor )
376                 && SotExchange::GetFormatDataFlavor(FORMAT_BITMAP, aSubstFlavor))
377             {
378 			    GetData( aSubstFlavor );
379                 bDone = sal_True;
380             }
381             else if( SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_EMF, aSubstFlavor ) &&
382                      TransferableDataHelper::IsEqual( aSubstFlavor, rFlavor ) &&
383                      SotExchange::GetFormatDataFlavor( FORMAT_GDIMETAFILE, aSubstFlavor ) )
384             {
385 			    GetData( aSubstFlavor );
386 
387 			    if( maAny.hasValue() )
388 			    {
389 				    Sequence< sal_Int8 > aSeq;
390 
391 				    if( maAny >>= aSeq )
392 				    {
393 					    SvMemoryStream*	pSrcStm = new SvMemoryStream( (char*) aSeq.getConstArray(), aSeq.getLength(), STREAM_WRITE | STREAM_TRUNC );
394 					    GDIMetaFile		aMtf;
395 
396 					    *pSrcStm >> aMtf;
397 					    delete pSrcStm;
398 
399 					    Graphic			aGraphic( aMtf );
400 					    SvMemoryStream	aDstStm( 65535, 65535 );
401 
402 					    if( GraphicConverter::Export( aDstStm, aGraphic, CVT_EMF ) == ERRCODE_NONE )
403                         {
404 						    maAny <<= ( aSeq = Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aDstStm.GetData() ),
405                                                                      aDstStm.Seek( STREAM_SEEK_TO_END ) ) );
406                             bDone = sal_True;
407                         }
408 				    }
409 			    }
410             }
411             else if( SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_WMF, aSubstFlavor ) &&
412                      TransferableDataHelper::IsEqual( aSubstFlavor, rFlavor ) &&
413                      SotExchange::GetFormatDataFlavor( FORMAT_GDIMETAFILE, aSubstFlavor ) )
414             {
415 			    GetData( aSubstFlavor );
416 
417 			    if( maAny.hasValue() )
418 			    {
419 				    Sequence< sal_Int8 > aSeq;
420 
421 				    if( maAny >>= aSeq )
422 				    {
423 					    SvMemoryStream*	pSrcStm = new SvMemoryStream( (char*) aSeq.getConstArray(), aSeq.getLength(), STREAM_WRITE | STREAM_TRUNC );
424 					    GDIMetaFile		aMtf;
425 
426 					    *pSrcStm >> aMtf;
427 					    delete pSrcStm;
428 
429 					    SvMemoryStream	aDstStm( 65535, 65535 );
430 
431 						// taking wmf without file header
432 						if ( ConvertGDIMetaFileToWMF( aMtf, aDstStm, NULL, sal_False ) )
433                         {
434 						    maAny <<= ( aSeq = Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aDstStm.GetData() ),
435                                                                      aDstStm.Seek( STREAM_SEEK_TO_END ) ) );
436                             bDone = sal_True;
437                         }
438 				    }
439 			    }
440             }
441             else if( SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_SVG, aSubstFlavor ) &&
442                      TransferableDataHelper::IsEqual( aSubstFlavor, rFlavor ) &&
443                      SotExchange::GetFormatDataFlavor( FORMAT_GDIMETAFILE, aSubstFlavor ) )
444             {
445                 GetData( aSubstFlavor );
446 
447                 if( maAny.hasValue() )
448                 {
449                     Sequence< sal_Int8 > aSeq;
450 
451                     if( maAny >>= aSeq )
452                     {
453                         SvMemoryStream* pSrcStm = new SvMemoryStream( (char*) aSeq.getConstArray(), aSeq.getLength(), STREAM_WRITE | STREAM_TRUNC );
454                         GDIMetaFile     aMtf;
455 
456                         *pSrcStm >> aMtf;
457                         delete pSrcStm;
458 
459                         Graphic         aGraphic( aMtf );
460                         SvMemoryStream  aDstStm( 65535, 65535 );
461 
462                         if( GraphicConverter::Export( aDstStm, aGraphic, CVT_SVG ) == ERRCODE_NONE )
463                         {
464                             maAny <<= ( aSeq = Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aDstStm.GetData() ),
465                                                                      aDstStm.Seek( STREAM_SEEK_TO_END ) ) );
466                             bDone = sal_True;
467                         }
468                     }
469                 }
470             }
471 
472             // reset Any if substitute doesn't work
473             if( !bDone && maAny.hasValue() )
474                 maAny = Any();
475 
476             // if any is not yet filled, use standard format
477             if( !maAny.hasValue() )
478                 GetData( rFlavor );
479 
480 #ifdef DEBUG
481             if( maAny.hasValue() && ::com::sun::star::uno::TypeClass_STRING != maAny.getValueType().getTypeClass() )
482                 fprintf( stderr, "TransferableHelper delivers sequence of data [ %s ]\n", ByteString( String( rFlavor.MimeType), RTL_TEXTENCODING_ASCII_US ).GetBuffer() );
483 #endif
484         }
485 		catch( const ::com::sun::star::uno::Exception& )
486 		{
487 		}
488 
489 		if( !maAny.hasValue() )
490 			throw UnsupportedFlavorException();
491 	}
492 
493 	return maAny;
494 }
495 
496 // -----------------------------------------------------------------------------
497 
getTransferDataFlavors()498 Sequence< DataFlavor > SAL_CALL TransferableHelper::getTransferDataFlavors() throw( RuntimeException )
499 {
500 	const ::vos::OGuard aGuard( Application::GetSolarMutex() );
501 
502 	try
503 	{
504 		if( !mpFormats->size() )
505 			AddSupportedFormats();
506 	}
507 	catch( const ::com::sun::star::uno::Exception& )
508 	{
509 	}
510 
511 	Sequence< DataFlavor >			aRet( mpFormats->size() );
512 	DataFlavorExVector::iterator	aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
513 	sal_uInt32						nCurPos = 0;
514 
515     while( aIter != aEnd )
516     {
517     	aRet[ nCurPos++ ] = *aIter++;
518     }
519 
520 	return aRet;
521 }
522 
523 // -----------------------------------------------------------------------------
524 
isDataFlavorSupported(const DataFlavor & rFlavor)525 sal_Bool SAL_CALL TransferableHelper::isDataFlavorSupported( const DataFlavor& rFlavor ) throw( RuntimeException )
526 {
527 	const ::vos::OGuard aGuard( Application::GetSolarMutex() );
528 	sal_Bool			bRet = sal_False;
529 
530 	try
531 	{
532 		if( !mpFormats->size() )
533 			AddSupportedFormats();
534 	}
535 	catch( const ::com::sun::star::uno::Exception& )
536 	{
537 	}
538 
539 	DataFlavorExVector::iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
540 
541 	while( aIter != aEnd )
542 	{
543         if( TransferableDataHelper::IsEqual( *aIter, rFlavor ) )
544         {
545             aIter = aEnd;
546             bRet = sal_True;
547         }
548         else
549             aIter++;
550     }
551 
552 	return bRet;
553 }
554 
555 // -----------------------------------------------------------------------------
556 
lostOwnership(const Reference<XClipboard> &,const Reference<XTransferable> &)557 void SAL_CALL TransferableHelper::lostOwnership( const Reference< XClipboard >&, const Reference< XTransferable >& ) throw( RuntimeException )
558 {
559 	const ::vos::OGuard aGuard( Application::GetSolarMutex() );
560 
561 	try
562 	{
563 		if( mxTerminateListener.is() )
564 		{
565 			Reference< XMultiServiceFactory > xFact( ::comphelper::getProcessServiceFactory() );
566 
567 			if( xFact.is() )
568 			{
569 				Reference< XDesktop > xDesktop( xFact->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), UNO_QUERY );
570 
571 				if( xDesktop.is() )
572 					xDesktop->removeTerminateListener( mxTerminateListener );
573 			}
574 
575 			mxTerminateListener = Reference< XTerminateListener >();
576 		}
577 
578 		ObjectReleased();
579 	}
580 	catch( const ::com::sun::star::uno::Exception& )
581 	{
582 	}
583 }
584 
585 // -----------------------------------------------------------------------------
586 
disposing(const EventObject &)587 void SAL_CALL TransferableHelper::disposing( const EventObject& ) throw( RuntimeException )
588 {
589 }
590 
591 // -----------------------------------------------------------------------------
592 
dragDropEnd(const DragSourceDropEvent & rDSDE)593 void SAL_CALL TransferableHelper::dragDropEnd( const DragSourceDropEvent& rDSDE ) throw( RuntimeException )
594 {
595 	const ::vos::OGuard aGuard( Application::GetSolarMutex() );
596 
597 	try
598 	{
599 		DragFinished( rDSDE.DropSuccess ? ( rDSDE.DropAction & ~DNDConstants::ACTION_DEFAULT ) : DNDConstants::ACTION_NONE );
600 		ObjectReleased();
601 	}
602 	catch( const ::com::sun::star::uno::Exception& )
603 	{
604 	}
605 }
606 
607 // -----------------------------------------------------------------------------
608 
dragEnter(const DragSourceDragEvent &)609 void SAL_CALL TransferableHelper::dragEnter( const DragSourceDragEvent& ) throw( RuntimeException )
610 {
611 }
612 
613 // -----------------------------------------------------------------------------
614 
dragExit(const DragSourceEvent &)615 void SAL_CALL TransferableHelper::dragExit( const DragSourceEvent& ) throw( RuntimeException )
616 {
617 }
618 
619 // -----------------------------------------------------------------------------
620 
dragOver(const DragSourceDragEvent &)621 void SAL_CALL TransferableHelper::dragOver( const DragSourceDragEvent& ) throw( RuntimeException )
622 {
623 }
624 
625 // -----------------------------------------------------------------------------
626 
dropActionChanged(const DragSourceDragEvent &)627 void SAL_CALL TransferableHelper::dropActionChanged( const DragSourceDragEvent& ) throw( RuntimeException )
628 {
629 }
630 
631 // -----------------------------------------------------------------------------
632 
getSomething(const Sequence<sal_Int8> & rId)633 sal_Int64 SAL_CALL TransferableHelper::getSomething( const Sequence< sal_Int8 >& rId ) throw( RuntimeException )
634 {
635     sal_Int64 nRet;
636 
637     if( ( rId.getLength() == 16 ) &&
638         ( 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
639     {
640         nRet = sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
641     }
642     else
643         nRet = 0;
644 
645 	return nRet;
646 }
647 
648 // -----------------------------------------------------------------------------
649 
ImplFlush()650 void TransferableHelper::ImplFlush()
651 {
652 	if( mxClipboard.is() )
653 	{
654 		Reference< XFlushableClipboard >	xFlushableClipboard( mxClipboard, UNO_QUERY );
655 		const sal_uInt32					nRef = Application::ReleaseSolarMutex();
656 
657 		try
658 		{
659 			if( xFlushableClipboard.is() )
660 			 	xFlushableClipboard->flushClipboard();
661 		}
662 		catch( const ::com::sun::star::uno::Exception& )
663 		{
664 			DBG_ERROR( "Could not flush clipboard" );
665 		}
666 
667 		Application::AcquireSolarMutex( nRef );
668 	}
669 }
670 
671 // -----------------------------------------------------------------------------
672 
AddFormat(SotFormatStringId nFormat)673 void TransferableHelper::AddFormat( SotFormatStringId nFormat )
674 {
675     DataFlavor aFlavor;
676 
677     if( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) )
678         AddFormat( aFlavor );
679 }
680 
681 // -----------------------------------------------------------------------------
682 
AddFormat(const DataFlavor & rFlavor)683 void TransferableHelper::AddFormat( const DataFlavor& rFlavor )
684 {
685 	DataFlavorExVector::iterator    aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
686     sal_Bool                        bAdd = sal_True;
687 
688 	while( aIter != aEnd )
689 	{
690         if( TransferableDataHelper::IsEqual( *aIter, rFlavor ) )
691         {
692             // update MimeType for SOT_FORMATSTR_ID_OBJECTDESCRIPTOR in every case
693             if( ( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR == aIter->mnSotId ) && mpObjDesc )
694             {
695                 DataFlavor aObjDescFlavor;
696 
697                 SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDescFlavor );
698                 aIter->MimeType = aObjDescFlavor.MimeType;
699                 aIter->MimeType += ::ImplGetParameterString( *mpObjDesc );
700 
701 #ifdef DEBUG
702                 fprintf( stderr, "TransferableHelper exchanged objectdescriptor [ %s ]\n",
703                          ByteString( String( aIter->MimeType), RTL_TEXTENCODING_ASCII_US ).GetBuffer() );
704 #endif
705             }
706 
707             aIter = aEnd;
708             bAdd = sal_False;
709         }
710         else
711             aIter++;
712     }
713 
714     if( bAdd )
715     {
716     	DataFlavorEx   aFlavorEx;
717         DataFlavor     aObjDescFlavor;
718 
719 		aFlavorEx.MimeType = rFlavor.MimeType;
720 		aFlavorEx.HumanPresentableName = rFlavor.HumanPresentableName;
721 		aFlavorEx.DataType = rFlavor.DataType;
722 		aFlavorEx.mnSotId = SotExchange::RegisterFormat( rFlavor );
723 
724         if( ( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR == aFlavorEx.mnSotId ) && mpObjDesc )
725             aFlavorEx.MimeType += ::ImplGetParameterString( *mpObjDesc );
726 
727 		mpFormats->push_back( aFlavorEx );
728 
729 		if( FORMAT_BITMAP == aFlavorEx.mnSotId )
730 		{
731 			AddFormat( SOT_FORMATSTR_ID_PNG );
732 			AddFormat( SOT_FORMATSTR_ID_BMP );
733 		}
734 		else if( FORMAT_GDIMETAFILE == aFlavorEx.mnSotId )
735 		{
736 			AddFormat( SOT_FORMATSTR_ID_EMF );
737 			AddFormat( SOT_FORMATSTR_ID_WMF );
738 			AddFormat( SOT_FORMATSTR_ID_SVG );
739 		}
740     }
741 }
742 
743 // -----------------------------------------------------------------------------
744 
RemoveFormat(SotFormatStringId nFormat)745 void TransferableHelper::RemoveFormat( SotFormatStringId nFormat )
746 {
747     DataFlavor aFlavor;
748 
749     if( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) )
750         RemoveFormat( aFlavor );
751 }
752 
753 // -----------------------------------------------------------------------------
754 
RemoveFormat(const DataFlavor & rFlavor)755 void TransferableHelper::RemoveFormat( const DataFlavor& rFlavor )
756 {
757 	DataFlavorExVector::iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
758 
759 	while( aIter != aEnd )
760 	{
761 		if( TransferableDataHelper::IsEqual( *aIter, rFlavor ) )
762 		{
763 			aIter = mpFormats->erase( aIter );
764 			aEnd = mpFormats->end();
765 		}
766 		else
767 			++aIter;
768 	}
769 }
770 
771 // -----------------------------------------------------------------------------
772 
HasFormat(SotFormatStringId nFormat)773 sal_Bool TransferableHelper::HasFormat( SotFormatStringId nFormat )
774 {
775 	DataFlavorExVector::iterator	aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
776 	sal_Bool						bRet = sal_False;
777 
778 	while( aIter != aEnd )
779 	{
780 		if( nFormat == (*aIter).mnSotId )
781 		{
782 			aIter = aEnd;
783 			bRet = sal_True;
784 		}
785 		else
786 			++aIter;
787 	}
788 
789 	return bRet;
790 }
791 
792 // -----------------------------------------------------------------------------
793 
ClearFormats()794 void TransferableHelper::ClearFormats()
795 {
796 	mpFormats->clear();
797     maAny.clear();
798 }
799 
800 // -----------------------------------------------------------------------------
801 
SetAny(const Any & rAny,const DataFlavor &)802 sal_Bool TransferableHelper::SetAny( const Any& rAny, const DataFlavor& )
803 {
804 	maAny = rAny;
805 	return( maAny.hasValue() );
806 }
807 
808 // -----------------------------------------------------------------------------
809 
SetString(const::rtl::OUString & rString,const DataFlavor & rFlavor)810 sal_Bool TransferableHelper::SetString( const ::rtl::OUString& rString, const DataFlavor& rFlavor )
811 {
812 	DataFlavor aFileFlavor;
813 
814 	if( rString.getLength() &&
815 		SotExchange::GetFormatDataFlavor( FORMAT_FILE, aFileFlavor ) &&
816 		TransferableDataHelper::IsEqual( aFileFlavor, rFlavor ) )
817 	{
818 		const String			aString( rString );
819 		const ByteString		aByteStr( aString, gsl_getSystemTextEncoding() );
820 		Sequence< sal_Int8 >	aSeq( aByteStr.Len() + 1 );
821 
822 		rtl_copyMemory( aSeq.getArray(), aByteStr.GetBuffer(), aByteStr.Len() );
823 		aSeq[ aByteStr.Len() ] = 0;
824 		maAny <<= aSeq;
825 	}
826 	else
827 		maAny <<= rString;
828 
829 	return( maAny.hasValue() );
830 }
831 
832 // -----------------------------------------------------------------------------
833 
SetBitmapEx(const BitmapEx & rBitmapEx,const DataFlavor & rFlavor)834 sal_Bool TransferableHelper::SetBitmapEx( const BitmapEx& rBitmapEx, const DataFlavor& rFlavor )
835 {
836 	if( !rBitmapEx.IsEmpty() )
837 	{
838         SvMemoryStream aMemStm( 65535, 65535 );
839 
840         if(rFlavor.MimeType.equalsIgnoreAsciiCase(::rtl::OUString::createFromAscii("image/png")))
841         {
842             // write a PNG
843             ::vcl::PNGWriter aPNGWriter(rBitmapEx);
844 
845             aPNGWriter.Write(aMemStm);
846         }
847         else
848         {
849             const Bitmap aBitmap(rBitmapEx.GetBitmap());
850 
851             // #124085# take out DIBV5 for writing to the clipboard
852             //if(rBitmapEx.IsTransparent())
853             //{
854             //    const Bitmap aMask(rBitmapEx.GetAlpha().GetBitmap());
855             //
856             //    // explicitly use Bitmap::Write with bCompressed = sal_False and bFileHeader = sal_True
857             //    WriteDIBV5(aBitmap, aMask, aMemStm);
858             //}
859             //else
860             //{
861                 // explicitly use Bitmap::Write with bCompressed = sal_False and bFileHeader = sal_True
862                 WriteDIB(aBitmap, aMemStm, false, true);
863             //}
864         }
865 
866         maAny <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Seek( STREAM_SEEK_TO_END ) );
867 	}
868 
869 	return( maAny.hasValue() );
870 }
871 
872 // -----------------------------------------------------------------------------
873 
SetGDIMetaFile(const GDIMetaFile & rMtf,const DataFlavor &)874 sal_Bool TransferableHelper::SetGDIMetaFile( const GDIMetaFile& rMtf, const DataFlavor& )
875 {
876 	if( rMtf.GetActionCount() )
877 	{
878 		SvMemoryStream aMemStm( 65535, 65535 );
879 
880 		( (GDIMetaFile&) rMtf ).Write( aMemStm );
881 		maAny <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Seek( STREAM_SEEK_TO_END ) );
882 	}
883 
884 	return( maAny.hasValue() );
885 }
886 
887 // -----------------------------------------------------------------------------
888 
SetGraphic(const Graphic & rGraphic,const DataFlavor &)889 sal_Bool TransferableHelper::SetGraphic( const Graphic& rGraphic, const DataFlavor& )
890 {
891 	if( rGraphic.GetType() != GRAPHIC_NONE )
892 	{
893 		SvMemoryStream aMemStm( 65535, 65535 );
894 
895         aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
896         aMemStm.SetCompressMode( COMPRESSMODE_NATIVE );
897 		aMemStm << rGraphic;
898 		maAny <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Seek( STREAM_SEEK_TO_END ) );
899 	}
900 
901 	return( maAny.hasValue() );
902 }
903 
904 // -----------------------------------------------------------------------------
905 
SetImageMap(const ImageMap & rIMap,const::com::sun::star::datatransfer::DataFlavor &)906 sal_Bool TransferableHelper::SetImageMap( const ImageMap& rIMap, const ::com::sun::star::datatransfer::DataFlavor& )
907 {
908 	SvMemoryStream aMemStm( 8192, 8192 );
909 
910     aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
911     rIMap.Write( aMemStm, String() );
912 	maAny <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Seek( STREAM_SEEK_TO_END ) );
913 
914 	return( maAny.hasValue() );
915 }
916 
917 // -----------------------------------------------------------------------------
918 
SetTransferableObjectDescriptor(const TransferableObjectDescriptor & rDesc,const::com::sun::star::datatransfer::DataFlavor &)919 sal_Bool TransferableHelper::SetTransferableObjectDescriptor( const TransferableObjectDescriptor& rDesc,
920 															  const ::com::sun::star::datatransfer::DataFlavor& )
921 {
922     PrepareOLE( rDesc );
923 
924 	SvMemoryStream aMemStm( 1024, 1024 );
925 
926 	aMemStm << rDesc;
927 	maAny <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Tell() );
928 
929 	return( maAny.hasValue() );
930  }
931 
932 // -----------------------------------------------------------------------------
933 
SetINetBookmark(const INetBookmark & rBmk,const::com::sun::star::datatransfer::DataFlavor & rFlavor)934 sal_Bool TransferableHelper::SetINetBookmark( const INetBookmark& rBmk,
935 											  const ::com::sun::star::datatransfer::DataFlavor& rFlavor )
936 {
937 	rtl_TextEncoding eSysCSet = gsl_getSystemTextEncoding();
938 
939 	switch( SotExchange::GetFormat( rFlavor ) )
940 	{
941 		case( SOT_FORMATSTR_ID_SOLK ):
942 		{
943 			ByteString sURL( rBmk.GetURL(), eSysCSet ),
944 					   sDesc( rBmk.GetDescription(), eSysCSet );
945 			ByteString sOut( ByteString::CreateFromInt32( sURL.Len() ));
946 			( sOut += '@' ) += sURL;
947 			sOut += ByteString::CreateFromInt32( sDesc.Len() );
948 			( sOut += '@' ) += sDesc;
949 
950 			Sequence< sal_Int8 > aSeq( sOut.Len() );
951 			memcpy( aSeq.getArray(), sOut.GetBuffer(), sOut.Len() );
952 			maAny <<= aSeq;
953 		}
954 		break;
955 
956 		case( FORMAT_STRING ):
957 			maAny <<= ::rtl::OUString( rBmk.GetURL() );
958 			break;
959 
960 		case( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ):
961 		{
962 			ByteString sURL( rBmk.GetURL(), eSysCSet );
963 			Sequence< sal_Int8 > aSeq( sURL.Len() );
964 			memcpy( aSeq.getArray(), sURL.GetBuffer(), sURL.Len() );
965 			maAny <<= aSeq;
966 		}
967 		break;
968 
969 		case( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ):
970 		{
971 			Sequence< sal_Int8 > aSeq( 2048 );
972 
973 			memset( aSeq.getArray(), 0, 2048 );
974 			strcpy( reinterpret_cast< char* >( aSeq.getArray() ), ByteString( rBmk.GetURL(), eSysCSet).GetBuffer() );
975 			strcpy( reinterpret_cast< char* >( aSeq.getArray() ) + 1024, ByteString( rBmk.GetDescription(), eSysCSet ).GetBuffer() );
976 
977 			maAny <<= aSeq;
978 		}
979 		break;
980 
981 #ifdef WNT
982 		case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR:
983 		{
984 			Sequence< sal_Int8 >	aSeq( sizeof( FILEGROUPDESCRIPTOR ) );
985 			FILEGROUPDESCRIPTOR*	pFDesc = (FILEGROUPDESCRIPTOR*) aSeq.getArray();
986 			FILEDESCRIPTOR&			rFDesc1 = pFDesc->fgd[ 0 ];
987 
988 			pFDesc->cItems = 1;
989 			memset( &rFDesc1, 0, sizeof( FILEDESCRIPTOR ) );
990 			rFDesc1.dwFlags = FD_LINKUI;
991 
992 			ByteString aStr( rBmk.GetDescription(), eSysCSet );
993 			for( sal_uInt16 nChar = 0; nChar < aStr.Len(); ++nChar )
994 				if( strchr( "\\/:*?\"<>|", aStr.GetChar( nChar ) ) )
995 					aStr.Erase( nChar--, 1 );
996 
997 			aStr.Insert( "Shortcut to ", 0 );
998 			aStr += ".URL";
999 			strcpy( rFDesc1.cFileName, aStr.GetBuffer() );
1000 
1001 			maAny <<= aSeq;
1002 		}
1003 		break;
1004 
1005 		case SOT_FORMATSTR_ID_FILECONTENT:
1006 		{
1007 			String aStr( RTL_CONSTASCII_STRINGPARAM( "[InternetShortcut]\x0aURL=" ) );
1008 			maAny <<= ::rtl::OUString( aStr += rBmk.GetURL() );
1009 		}
1010 		break;
1011 #endif
1012 
1013 		default:
1014 		break;
1015 	}
1016 
1017 	return( maAny.hasValue() );
1018 }
1019 
1020 // -----------------------------------------------------------------------------
1021 
SetINetImage(const INetImage & rINtImg,const::com::sun::star::datatransfer::DataFlavor & rFlavor)1022 sal_Bool TransferableHelper::SetINetImage( const INetImage& rINtImg,
1023 										   const ::com::sun::star::datatransfer::DataFlavor& rFlavor )
1024 {
1025 	SvMemoryStream aMemStm( 1024, 1024 );
1026 
1027     aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
1028 	rINtImg.Write( aMemStm, SotExchange::GetFormat( rFlavor ) );
1029 
1030 	maAny <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Seek( STREAM_SEEK_TO_END ) );
1031 
1032 	return( maAny.hasValue() );
1033 }
1034 
1035 // -----------------------------------------------------------------------------
1036 
SetFileList(const FileList & rFileList,const::com::sun::star::datatransfer::DataFlavor &)1037 sal_Bool TransferableHelper::SetFileList( const FileList& rFileList,
1038 										  const ::com::sun::star::datatransfer::DataFlavor& )
1039 {
1040 	SvMemoryStream aMemStm( 4096, 4096 );
1041 
1042     aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
1043 	aMemStm << rFileList;
1044 
1045 	maAny <<= Sequence< sal_Int8 >( static_cast< const sal_Int8* >( aMemStm.GetData() ),
1046                                        aMemStm.Seek( STREAM_SEEK_TO_END ) );
1047 
1048 	return( maAny.hasValue() );
1049 }
1050 
1051 // -----------------------------------------------------------------------------
1052 
SetObject(void * pUserObject,sal_uInt32 nUserObjectId,const DataFlavor & rFlavor)1053 sal_Bool TransferableHelper::SetObject( void* pUserObject, sal_uInt32 nUserObjectId, const DataFlavor& rFlavor )
1054 {
1055 	SotStorageStreamRef xStm( new SotStorageStream( String() ) );
1056 
1057     xStm->SetVersion( SOFFICE_FILEFORMAT_50 );
1058 
1059 	if( pUserObject && WriteObject( xStm, pUserObject, nUserObjectId, rFlavor ) )
1060 	{
1061 		const sal_uInt32		nLen = xStm->Seek( STREAM_SEEK_TO_END );
1062 		Sequence< sal_Int8 >	aSeq( nLen );
1063 
1064 		xStm->Seek( STREAM_SEEK_TO_BEGIN );
1065 		xStm->Read( aSeq.getArray(),  nLen );
1066 
1067 		if( nLen && ( SotExchange::GetFormat( rFlavor ) == SOT_FORMAT_STRING ) )
1068         {
1069             //JP 24.7.2001: as I know was this only for the writer application and this
1070             //		        writes now UTF16 format into the stream
1071             //JP 6.8.2001:  and now it writes UTF8 because then exist no problem with
1072             //		        little / big endians! - Bug 88121
1073 			maAny <<= ::rtl::OUString( reinterpret_cast< const sal_Char* >( aSeq.getConstArray() ), nLen - 1, RTL_TEXTENCODING_UTF8 );
1074         }
1075 		else
1076 			maAny <<= aSeq;
1077 	}
1078 
1079 	return( maAny.hasValue() );
1080 }
1081 
1082 // -----------------------------------------------------------------------------
1083 
SetInterface(const::com::sun::star::uno::Reference<::com::sun::star::uno::XInterface> & rIf,const::com::sun::star::datatransfer::DataFlavor &)1084 sal_Bool TransferableHelper::SetInterface( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rIf,
1085 										   const ::com::sun::star::datatransfer::DataFlavor& )
1086 {
1087 	maAny <<= rIf;
1088 	return( maAny.hasValue() );
1089 }
1090 
1091 // -----------------------------------------------------------------------------
1092 
WriteObject(SotStorageStreamRef &,void *,sal_uInt32,const DataFlavor &)1093 sal_Bool TransferableHelper::WriteObject( SotStorageStreamRef&, void*, sal_uInt32, const DataFlavor& )
1094 {
1095 	DBG_ERROR( "TransferableHelper::WriteObject( ... ) not implemented" );
1096 	return sal_False;
1097 }
1098 
1099 // -----------------------------------------------------------------------------
1100 
DragFinished(sal_Int8)1101 void TransferableHelper::DragFinished( sal_Int8 )
1102 {
1103 }
1104 
1105 // -----------------------------------------------------------------------------
1106 
ObjectReleased()1107 void TransferableHelper::ObjectReleased()
1108 {
1109 }
1110 
1111 // -----------------------------------------------------------------------------
1112 
PrepareOLE(const TransferableObjectDescriptor & rObjDesc)1113 void TransferableHelper::PrepareOLE( const TransferableObjectDescriptor& rObjDesc )
1114 {
1115     delete mpObjDesc;
1116     mpObjDesc = new TransferableObjectDescriptor( rObjDesc );
1117 
1118     if( HasFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) )
1119         AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
1120 }
1121 
1122 // -----------------------------------------------------------------------------
1123 
CopyToClipboard(Window * pWindow) const1124 void TransferableHelper::CopyToClipboard( Window *pWindow ) const
1125 {
1126 	DBG_ASSERT( pWindow, "Window pointer is NULL" );
1127     Reference< XClipboard > xClipboard;
1128 
1129     if( pWindow )
1130         xClipboard = pWindow->GetClipboard();
1131 
1132     if( xClipboard.is() )
1133         mxClipboard = xClipboard;
1134 
1135 	if( mxClipboard.is() && !mxTerminateListener.is() )
1136 	{
1137 		const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1138 
1139 		try
1140 		{
1141             TransferableHelper*                 pThis = const_cast< TransferableHelper* >( this );
1142 			Reference< XMultiServiceFactory >   xFact( ::comphelper::getProcessServiceFactory() );
1143 
1144 			if( xFact.is() )
1145 			{
1146 				Reference< XDesktop > xDesktop( xFact->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), UNO_QUERY );
1147 
1148 				if( xDesktop.is() )
1149 					xDesktop->addTerminateListener( pThis->mxTerminateListener = new TerminateListener( *pThis ) );
1150 			}
1151 
1152 			mxClipboard->setContents( pThis, pThis );
1153 		}
1154 		catch( const ::com::sun::star::uno::Exception& )
1155 		{
1156 		}
1157 
1158 		Application::AcquireSolarMutex( nRef );
1159 	}
1160 }
1161 
1162 // -----------------------------------------------------------------------------
1163 
CopyToSelection(Window * pWindow) const1164 void TransferableHelper::CopyToSelection( Window *pWindow ) const
1165 {
1166 	DBG_ASSERT( pWindow, "Window pointer is NULL" );
1167     Reference< XClipboard > xSelection;
1168 
1169     if( pWindow )
1170         xSelection = pWindow->GetPrimarySelection();
1171 
1172 	if( xSelection.is() && !mxTerminateListener.is() )
1173 	{
1174 		const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1175 
1176 		try
1177 		{
1178             TransferableHelper*                 pThis = const_cast< TransferableHelper* >( this );
1179 			Reference< XMultiServiceFactory >   xFact( ::comphelper::getProcessServiceFactory() );
1180 
1181 			if( xFact.is() )
1182 			{
1183 				Reference< XDesktop > xDesktop( xFact->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.frame.Desktop" ) ), UNO_QUERY );
1184 
1185 				if( xDesktop.is() )
1186 					xDesktop->addTerminateListener( pThis->mxTerminateListener = new TerminateListener( *pThis ) );
1187 			}
1188 
1189 			xSelection->setContents( pThis, pThis );
1190 		}
1191 		catch( const ::com::sun::star::uno::Exception& )
1192 		{
1193 		}
1194 
1195 		Application::AcquireSolarMutex( nRef );
1196 	}
1197 }
1198 
1199 // -----------------------------------------------------------------------------
1200 
StartDrag(Window * pWindow,sal_Int8 nDnDSourceActions,sal_Int32 nDnDPointer,sal_Int32 nDnDImage)1201 void TransferableHelper::StartDrag( Window* pWindow, sal_Int8 nDnDSourceActions,
1202 									sal_Int32 nDnDPointer, sal_Int32 nDnDImage )
1203 
1204 {
1205 	DBG_ASSERT( pWindow, "Window pointer is NULL" );
1206     Reference< XDragSource > xDragSource( pWindow->GetDragSource() );
1207 
1208 	if( xDragSource.is() )
1209 	{
1210         /*
1211          *    #96792# release mouse before actually starting DnD.
1212          *    This is necessary for the X11 DnD implementation to work.
1213          */
1214         if( pWindow->IsMouseCaptured() )
1215             pWindow->ReleaseMouse();
1216 
1217         const Point	aPt( pWindow->GetPointerPosPixel() );
1218 
1219 		// On Mac OS X we are forced to execute 'startDrag' synchronously
1220 		// contrary to the XDragSource interface specification because
1221 		// we can receive drag events from the system only in the main
1222 		// thread
1223 #if !defined(QUARTZ)
1224 		const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1225 #endif
1226 
1227 		try
1228 		{
1229 			DragGestureEvent	aEvt;
1230 			aEvt.DragAction = DNDConstants::ACTION_COPY;
1231 			aEvt.DragOriginX = aPt.X();
1232 			aEvt.DragOriginY = aPt.Y();
1233 			aEvt.DragSource = xDragSource;
1234 
1235 			xDragSource->startDrag( aEvt, nDnDSourceActions, nDnDPointer, nDnDImage, this, this );
1236 		}
1237 		catch( const ::com::sun::star::uno::Exception& )
1238 		{
1239 		}
1240 
1241 		// See above for the reason of this define
1242 #if !defined(QUARTZ)
1243 		Application::AcquireSolarMutex( nRef );
1244 #endif
1245 	}
1246 }
1247 
1248 // -----------------------------------------------------------------------------
1249 
ClearSelection(Window * pWindow)1250 void TransferableHelper::ClearSelection( Window *pWindow )
1251 {
1252 	DBG_ASSERT( pWindow, "Window pointer is NULL" );
1253     Reference< XClipboard > xSelection( pWindow->GetPrimarySelection() );
1254 
1255 	if( xSelection.is() )
1256         xSelection->setContents( NULL, NULL );
1257 }
1258 
1259 // -----------------------------------------------------------------------------
1260 
GetSystemClipboard()1261 Reference< XClipboard> TransferableHelper::GetSystemClipboard()
1262 {
1263     Window *pFocusWindow = Application::GetFocusWindow();
1264 
1265     if( pFocusWindow )
1266         return pFocusWindow->GetClipboard();
1267 
1268 	return 	Reference< XClipboard > ();
1269 }
1270 
1271 // -----------------------------------------------------------------------------
1272 
getUnoTunnelId()1273 const Sequence< sal_Int8 >& TransferableHelper::getUnoTunnelId()
1274 {
1275     static Sequence< sal_Int8 > aSeq;
1276 
1277 	if( !aSeq.getLength() )
1278 	{
1279 		static osl::Mutex           aCreateMutex;
1280     	osl::Guard< osl::Mutex >    aGuard( aCreateMutex );
1281 
1282 		aSeq.realloc( 16 );
1283     	rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
1284 	}
1285 
1286 
1287     return aSeq;
1288 }
1289 
1290 // ---------------------------------
1291 // - TransferableClipboardNotifier -
1292 // ---------------------------------
1293 
1294 class TransferableClipboardNotifier : public ::cppu::WeakImplHelper1< XClipboardListener >
1295 {
1296 private:
1297     ::osl::Mutex&                   mrMutex;
1298     Reference< XClipboardNotifier > mxNotifier;
1299 	TransferableDataHelper*		    mpListener;
1300 
1301 protected:
1302 	// XClipboardListener
1303     virtual void SAL_CALL changedContents( const clipboard::ClipboardEvent& event ) throw (RuntimeException);
1304 
1305     // XEventListener
1306     virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException);
1307 
1308 public:
1309     TransferableClipboardNotifier( const Reference< XClipboard >& _rxClipboard, TransferableDataHelper& _rListener, ::osl::Mutex& _rMutex );
1310 
1311     /// determines whether we're currently listening
isListening() const1312     inline bool isListening() const { return !isDisposed(); }
1313 
1314     /// determines whether the instance is disposed
isDisposed() const1315     inline bool isDisposed() const { return mpListener == NULL; }
1316 
1317     /// makes the instance non-functional
1318     void    dispose();
1319 };
1320 
1321 // -----------------------------------------------------------------------------
1322 
TransferableClipboardNotifier(const Reference<XClipboard> & _rxClipboard,TransferableDataHelper & _rListener,::osl::Mutex & _rMutex)1323 TransferableClipboardNotifier::TransferableClipboardNotifier( const Reference< XClipboard >& _rxClipboard, TransferableDataHelper& _rListener, ::osl::Mutex& _rMutex )
1324     :mrMutex( _rMutex )
1325     ,mxNotifier( _rxClipboard, UNO_QUERY )
1326     ,mpListener( &_rListener )
1327 {
1328     osl_incrementInterlockedCount( &m_refCount );
1329     {
1330         if ( mxNotifier.is() )
1331 		    mxNotifier->addClipboardListener( this );
1332         else
1333             // born dead
1334             mpListener = NULL;
1335     }
1336     osl_decrementInterlockedCount( &m_refCount );
1337 }
1338 
1339 // -----------------------------------------------------------------------------
1340 
changedContents(const clipboard::ClipboardEvent & event)1341 void SAL_CALL TransferableClipboardNotifier::changedContents( const clipboard::ClipboardEvent& event ) throw (RuntimeException)
1342 {
1343 	::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1344         // the SolarMutex here is necessary, since
1345         // - we cannot call mpListener without our own mutex locked
1346         // - Rebind respectively InitFormats (called by Rebind) will
1347         // try to lock the SolarMutex, too
1348     ::osl::MutexGuard aGuard( mrMutex );
1349 	if( mpListener )
1350 		mpListener->Rebind( event.Contents );
1351 }
1352 
1353 // -----------------------------------------------------------------------------
1354 
disposing(const EventObject &)1355 void SAL_CALL TransferableClipboardNotifier::disposing( const EventObject& ) throw (RuntimeException)
1356 {
1357     // clipboard is being disposed. Hmm. Okay, become disfunctional myself.
1358 	dispose();
1359 }
1360 
1361 // -----------------------------------------------------------------------------
1362 
dispose()1363 void TransferableClipboardNotifier::dispose()
1364 {
1365     ::osl::MutexGuard aGuard( mrMutex );
1366 
1367     Reference< XClipboardListener > xKeepMeAlive( this );
1368 
1369     if ( mxNotifier.is() )
1370 		mxNotifier->removeClipboardListener( this );
1371     mxNotifier.clear();
1372 
1373     mpListener = NULL;
1374 }
1375 
1376 // -------------------------------
1377 // - TransferableDataHelper_Impl -
1378 // -------------------------------
1379 
1380 struct TransferableDataHelper_Impl
1381 {
1382     ::osl::Mutex                    maMutex;
1383     TransferableClipboardNotifier*  mpClipboardListener;
1384 
TransferableDataHelper_ImplTransferableDataHelper_Impl1385     TransferableDataHelper_Impl()
1386         :mpClipboardListener( NULL )
1387     {
1388     }
1389 };
1390 
1391 // --------------------------
1392 // - TransferableDataHelper -
1393 // --------------------------
1394 
TransferableDataHelper()1395 TransferableDataHelper::TransferableDataHelper() :
1396     mpFormats( new DataFlavorExVector ),
1397     mpObjDesc( new TransferableObjectDescriptor ),
1398     mpImpl( new TransferableDataHelper_Impl )
1399 {
1400 }
1401 
1402 // -----------------------------------------------------------------------------
1403 
TransferableDataHelper(const Reference<::com::sun::star::datatransfer::XTransferable> & rxTransferable)1404 TransferableDataHelper::TransferableDataHelper( const Reference< ::com::sun::star::datatransfer::XTransferable >& rxTransferable ) :
1405     mxTransfer( rxTransferable ),
1406     mpFormats( new DataFlavorExVector ),
1407     mpObjDesc( new TransferableObjectDescriptor ),
1408     mpImpl( new TransferableDataHelper_Impl )
1409 {
1410 	InitFormats();
1411 }
1412 
1413 // -----------------------------------------------------------------------------
1414 
TransferableDataHelper(const TransferableDataHelper & rDataHelper)1415 TransferableDataHelper::TransferableDataHelper( const TransferableDataHelper& rDataHelper ) :
1416     mxTransfer( rDataHelper.mxTransfer ),
1417     mxClipboard( rDataHelper.mxClipboard ),
1418 	mpFormats( new DataFlavorExVector( *rDataHelper.mpFormats ) ),
1419     mpObjDesc( new TransferableObjectDescriptor( *rDataHelper.mpObjDesc ) ),
1420     mpImpl( new TransferableDataHelper_Impl )
1421 {
1422 }
1423 
1424 // -----------------------------------------------------------------------------
1425 
operator =(const TransferableDataHelper & rDataHelper)1426 TransferableDataHelper& TransferableDataHelper::operator=( const TransferableDataHelper& rDataHelper )
1427 {
1428 	if ( this != &rDataHelper )
1429 	{
1430         ::osl::MutexGuard aGuard( mpImpl->maMutex );
1431 
1432         bool bWasClipboardListening = ( NULL != mpImpl->mpClipboardListener );
1433 
1434         if ( bWasClipboardListening )
1435             StopClipboardListening();
1436 
1437         mxTransfer = rDataHelper.mxTransfer;
1438 		delete mpFormats, mpFormats = new DataFlavorExVector( *rDataHelper.mpFormats );
1439         delete mpObjDesc, mpObjDesc = new TransferableObjectDescriptor( *rDataHelper.mpObjDesc );
1440 		mxClipboard = rDataHelper.mxClipboard;
1441 
1442         if ( bWasClipboardListening )
1443             StartClipboardListening();
1444 	}
1445 
1446 	return *this;
1447 }
1448 
1449 // -----------------------------------------------------------------------------
1450 
~TransferableDataHelper()1451 TransferableDataHelper::~TransferableDataHelper()
1452 {
1453 	StopClipboardListening( );
1454     {
1455         ::osl::MutexGuard aGuard( mpImpl->maMutex );
1456 	    delete mpFormats, mpFormats = NULL;
1457         delete mpObjDesc, mpObjDesc = NULL;
1458     }
1459     delete mpImpl;
1460 }
1461 
1462 // -----------------------------------------------------------------------------
1463 
FillDataFlavorExVector(const Sequence<DataFlavor> & rDataFlavorSeq,DataFlavorExVector & rDataFlavorExVector)1464 void TransferableDataHelper::FillDataFlavorExVector( const Sequence< DataFlavor >& rDataFlavorSeq,
1465                                                      DataFlavorExVector& rDataFlavorExVector )
1466 {
1467     try
1468     {
1469 	    Reference< XMultiServiceFactory >       xFact( ::comphelper::getProcessServiceFactory() );
1470         Reference< XMimeContentTypeFactory >    xMimeFact;
1471 	    DataFlavorEx		                    aFlavorEx;
1472         const ::rtl::OUString                   aCharsetStr( ::rtl::OUString::createFromAscii( "charset" ) );
1473 
1474 	    if( xFact.is() )
1475 		    xMimeFact = Reference< XMimeContentTypeFactory >( xFact->createInstance( ::rtl::OUString::createFromAscii(
1476                                                               "com.sun.star.datatransfer.MimeContentTypeFactory" ) ),
1477                                                               UNO_QUERY );
1478 
1479 	    for( sal_Int32 i = 0; i < rDataFlavorSeq.getLength(); i++ )
1480 	    {
1481 		    const DataFlavor&	            rFlavor = rDataFlavorSeq[ i ];
1482             Reference< XMimeContentType >   xMimeType;
1483 
1484             try
1485             {
1486                 if( xMimeFact.is() && rFlavor.MimeType.getLength() )
1487                     xMimeType = xMimeFact->createMimeContentType( rFlavor.MimeType );
1488             }
1489             catch( const ::com::sun::star::uno::Exception& )
1490 	        {
1491 
1492 	        }
1493 
1494 		    aFlavorEx.MimeType = rFlavor.MimeType;
1495 		    aFlavorEx.HumanPresentableName = rFlavor.HumanPresentableName;
1496 		    aFlavorEx.DataType = rFlavor.DataType;
1497 		    aFlavorEx.mnSotId = SotExchange::RegisterFormat( rFlavor );
1498 
1499 		    rDataFlavorExVector.push_back( aFlavorEx );
1500 
1501             // add additional formats for special mime types
1502             if(SOT_FORMATSTR_ID_BMP == aFlavorEx.mnSotId || SOT_FORMATSTR_ID_PNG == aFlavorEx.mnSotId)
1503 		    {
1504 			    if( SotExchange::GetFormatDataFlavor( SOT_FORMAT_BITMAP, aFlavorEx ) )
1505 			    {
1506 				    aFlavorEx.mnSotId = SOT_FORMAT_BITMAP;
1507 				    rDataFlavorExVector.push_back( aFlavorEx );
1508 			    }
1509 		    }
1510             else if( SOT_FORMATSTR_ID_WMF == aFlavorEx.mnSotId || SOT_FORMATSTR_ID_EMF == aFlavorEx.mnSotId || SOT_FORMATSTR_ID_SVG == aFlavorEx.mnSotId )
1511 		    {
1512 			    if( SotExchange::GetFormatDataFlavor( SOT_FORMAT_GDIMETAFILE, aFlavorEx ) )
1513 			    {
1514 				    aFlavorEx.mnSotId = SOT_FORMAT_GDIMETAFILE;
1515 				    rDataFlavorExVector.push_back( aFlavorEx );
1516 			    }
1517 		    }
1518             else if ( SOT_FORMATSTR_ID_HTML_SIMPLE == aFlavorEx.mnSotId  )
1519             {
1520                 // #104735# HTML_SIMPLE may also be inserted without comments
1521                 aFlavorEx.mnSotId = SOT_FORMATSTR_ID_HTML_NO_COMMENT;
1522                 rDataFlavorExVector.push_back( aFlavorEx );
1523             }
1524             else if( xMimeType.is() && xMimeType->getFullMediaType().equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "text/plain" ) ) )
1525             {
1526                 // add, if it is a UTF-8 byte buffer
1527                 if( xMimeType->hasParameter( aCharsetStr ) )
1528                 {
1529                     const ::rtl::OUString aCharset( xMimeType->getParameterValue( aCharsetStr ) );
1530 
1531                     if( xMimeType->getParameterValue( aCharsetStr ).equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "unicode" ) ) ||
1532 					    xMimeType->getParameterValue( aCharsetStr ).equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "utf-16" ) ) )
1533                     {
1534                         rDataFlavorExVector[ rDataFlavorExVector.size() - 1 ].mnSotId = FORMAT_STRING;
1535 
1536                     }
1537                 }
1538             }
1539             else if( xMimeType.is() && xMimeType->getFullMediaType().equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "text/rtf" ) ) )
1540             {
1541                 rDataFlavorExVector[ rDataFlavorExVector.size() - 1 ].mnSotId = FORMAT_RTF;
1542             }
1543             else if( xMimeType.is() && xMimeType->getFullMediaType().equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "text/html" ) ) )
1544 
1545             {
1546                 rDataFlavorExVector[ rDataFlavorExVector.size() - 1 ].mnSotId = SOT_FORMATSTR_ID_HTML;
1547             }
1548             else if( xMimeType.is() && xMimeType->getFullMediaType().equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "text/uri-list" ) ) )
1549             {
1550                 rDataFlavorExVector[ rDataFlavorExVector.size() - 1 ].mnSotId = SOT_FORMAT_FILE_LIST;
1551             }
1552             else if( xMimeType.is() && xMimeType->getFullMediaType().equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "application/x-openoffice-objectdescriptor-xml" ) ) )
1553             {
1554                 rDataFlavorExVector[ rDataFlavorExVector.size() - 1 ].mnSotId = SOT_FORMATSTR_ID_OBJECTDESCRIPTOR;
1555             }
1556 	    }
1557     }
1558 	catch( const ::com::sun::star::uno::Exception& )
1559 	{
1560 	}
1561 }
1562 
1563 // -----------------------------------------------------------------------------
1564 
InitFormats()1565 void TransferableDataHelper::InitFormats()
1566 {
1567 	::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1568     ::osl::MutexGuard aGuard( mpImpl->maMutex );
1569 
1570     mpFormats->clear();
1571     delete mpObjDesc, mpObjDesc = new TransferableObjectDescriptor;
1572 
1573     if( mxTransfer.is() )
1574     {
1575         TransferableDataHelper::FillDataFlavorExVector( mxTransfer->getTransferDataFlavors(), *mpFormats );
1576 
1577         DataFlavorExVector::iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
1578 
1579         while( aIter != aEnd )
1580         {
1581             if( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR == aIter->mnSotId )
1582             {
1583                 ImplSetParameterString( *mpObjDesc, *aIter );
1584                 aIter = aEnd;
1585             }
1586             else
1587                 ++aIter;
1588         }
1589     }
1590 }
1591 
1592 // -----------------------------------------------------------------------------
1593 
HasFormat(SotFormatStringId nFormat) const1594 sal_Bool TransferableDataHelper::HasFormat( SotFormatStringId nFormat ) const
1595 {
1596     ::osl::MutexGuard aGuard( mpImpl->maMutex );
1597 
1598 	DataFlavorExVector::iterator	aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
1599 	sal_Bool						bRet = sal_False;
1600 
1601 	while( aIter != aEnd )
1602 	{
1603 		if( nFormat == (*aIter++).mnSotId )
1604 		{
1605 			aIter = aEnd;
1606 			bRet = sal_True;
1607 		}
1608 	}
1609 
1610 	return bRet;
1611 }
1612 
1613 // -----------------------------------------------------------------------------
1614 
HasFormat(const DataFlavor & rFlavor) const1615 sal_Bool TransferableDataHelper::HasFormat( const DataFlavor& rFlavor ) const
1616 {
1617     ::osl::MutexGuard aGuard( mpImpl->maMutex );
1618 
1619     DataFlavorExVector::iterator	aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
1620 	sal_Bool						bRet = sal_False;
1621 
1622 	while( aIter != aEnd )
1623 	{
1624 		if( TransferableDataHelper::IsEqual( rFlavor, *aIter++ ) )
1625 		{
1626 			aIter = aEnd;
1627 			bRet = sal_True;
1628 		}
1629 	}
1630 
1631 	return bRet;
1632 }
1633 
1634 // -----------------------------------------------------------------------------
1635 
GetFormatCount() const1636 sal_uInt32 TransferableDataHelper::GetFormatCount() const
1637 {
1638     ::osl::MutexGuard aGuard( mpImpl->maMutex );
1639 	return mpFormats->size();
1640 }
1641 
1642 // -----------------------------------------------------------------------------
1643 
1644 
GetFormat(sal_uInt32 nFormat) const1645 SotFormatStringId TransferableDataHelper::GetFormat( sal_uInt32 nFormat ) const
1646 {
1647     ::osl::MutexGuard aGuard( mpImpl->maMutex );
1648 	DBG_ASSERT( nFormat < mpFormats->size(), "TransferableDataHelper::GetFormat: invalid format index" );
1649 	return( ( nFormat < mpFormats->size() ) ? (*mpFormats)[ nFormat ].mnSotId : 0 );
1650 }
1651 
1652 // -----------------------------------------------------------------------------
1653 
GetFormatDataFlavor(sal_uInt32 nFormat) const1654 DataFlavor TransferableDataHelper::GetFormatDataFlavor( sal_uInt32 nFormat ) const
1655 {
1656     ::osl::MutexGuard aGuard( mpImpl->maMutex );
1657 	DBG_ASSERT( nFormat < mpFormats->size(), "TransferableDataHelper::GetFormat: invalid format index" );
1658 
1659     DataFlavor aRet;
1660 
1661 	if( nFormat < mpFormats->size() )
1662 		aRet = (*mpFormats)[ nFormat ];
1663 
1664 	return aRet;
1665 }
1666 
1667 // -----------------------------------------------------------------------------
1668 
GetXTransferable() const1669 Reference< XTransferable > TransferableDataHelper::GetXTransferable() const
1670 {
1671 	Reference< XTransferable > xRet;
1672 
1673 	if( mxTransfer.is() )
1674 	{
1675 		try
1676 		{
1677 			xRet = mxTransfer;
1678 
1679 			// do a dummy call to check, if this interface is valid (nasty)
1680 			Sequence< DataFlavor > aTestSeq( xRet->getTransferDataFlavors() );
1681 
1682 		}
1683 		catch( const ::com::sun::star::uno::Exception& )
1684 		{
1685 			xRet = Reference< XTransferable >();
1686 		}
1687 	}
1688 
1689 	return xRet;
1690 }
1691 
1692 // -----------------------------------------------------------------------------
1693 
GetAny(SotFormatStringId nFormat) const1694 Any	TransferableDataHelper::GetAny( SotFormatStringId nFormat ) const
1695 {
1696 	Any aReturn;
1697 
1698 	DataFlavor aFlavor;
1699 	if ( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) )
1700 		aReturn = GetAny( aFlavor );
1701 
1702 	return aReturn;
1703 }
1704 
1705 
1706 // -----------------------------------------------------------------------------
1707 
GetAny(const DataFlavor & rFlavor) const1708 Any TransferableDataHelper::GetAny( const DataFlavor& rFlavor ) const
1709 {
1710     ::osl::MutexGuard aGuard( mpImpl->maMutex );
1711 	Any aRet;
1712 
1713 	try
1714 	{
1715 		if( mxTransfer.is() )
1716         {
1717             DataFlavorExVector::iterator    aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
1718             const SotFormatStringId         nRequestFormat = SotExchange::GetFormat( rFlavor );
1719 
1720             if( nRequestFormat )
1721             {
1722     	        // try to get alien format first
1723 	            while( aIter != aEnd )
1724 	            {
1725                     if( ( nRequestFormat == (*aIter).mnSotId ) && !rFlavor.MimeType.equalsIgnoreAsciiCase( (*aIter).MimeType ) )
1726             			aRet = mxTransfer->getTransferData( *aIter );
1727 
1728                     if( aRet.hasValue() )
1729                         aIter = aEnd;
1730                     else
1731                         aIter++;
1732 	            }
1733             }
1734 
1735             if( !aRet.hasValue() )
1736     			aRet = mxTransfer->getTransferData( rFlavor );
1737         }
1738 	}
1739 	catch( const ::com::sun::star::uno::Exception& )
1740 	{
1741 	}
1742 
1743 	return aRet;
1744 }
1745 
1746 // -----------------------------------------------------------------------------
1747 
GetString(SotFormatStringId nFormat,String & rStr)1748 sal_Bool TransferableDataHelper::GetString( SotFormatStringId nFormat, String& rStr )
1749 {
1750     ::rtl::OUString aOUString;
1751     sal_Bool        bRet = GetString( nFormat, aOUString );
1752 
1753     rStr = aOUString;
1754 
1755     return bRet;
1756 }
1757 
1758 // -----------------------------------------------------------------------------
1759 
GetString(const DataFlavor & rFlavor,String & rStr)1760 sal_Bool TransferableDataHelper::GetString( const DataFlavor& rFlavor, String& rStr )
1761 {
1762     ::rtl::OUString aOUString;
1763     sal_Bool        bRet = GetString( rFlavor, aOUString );
1764 
1765     rStr = aOUString;
1766 
1767     return bRet;
1768 }
1769 
1770 // -----------------------------------------------------------------------------
1771 
GetString(SotFormatStringId nFormat,::rtl::OUString & rStr)1772 sal_Bool TransferableDataHelper::GetString( SotFormatStringId nFormat, ::rtl::OUString& rStr )
1773 {
1774 	DataFlavor aFlavor;
1775 	return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetString( aFlavor, rStr ) );
1776 }
1777 
1778 // -----------------------------------------------------------------------------
1779 
GetString(const DataFlavor & rFlavor,::rtl::OUString & rStr)1780 sal_Bool TransferableDataHelper::GetString( const DataFlavor& rFlavor, ::rtl::OUString& rStr )
1781 {
1782 	Any         aAny( GetAny( rFlavor ) );
1783     sal_Bool    bRet = sal_False;
1784 
1785     if( aAny.hasValue() )
1786 	{
1787 		::rtl::OUString         aOUString;
1788 		Sequence< sal_Int8 >    aSeq;
1789 
1790         if( aAny >>= aOUString )
1791         {
1792 			rStr = aOUString;
1793             bRet = sal_True;
1794         }
1795 		else if( aAny >>= aSeq )
1796 		{
1797 
1798 			const sal_Char* pChars = reinterpret_cast< const sal_Char* >( aSeq.getConstArray() );
1799 			sal_Int32       nLen = aSeq.getLength();
1800 
1801             //JP 10.10.2001: 92930 - don't copy the last zero characterinto the string.
1802             //DVO 2002-05-27: strip _all_ trailing zeros
1803 			while( nLen && ( 0 == *( pChars + nLen - 1 ) ) )
1804 				--nLen;
1805 
1806 			rStr = ::rtl::OUString( pChars, nLen, gsl_getSystemTextEncoding() );
1807             bRet = sal_True;
1808 		}
1809 	}
1810 
1811     return bRet;
1812 }
1813 
1814 // -----------------------------------------------------------------------------
1815 
GetBitmapEx(SotFormatStringId nFormat,BitmapEx & rBmpEx)1816 sal_Bool TransferableDataHelper::GetBitmapEx( SotFormatStringId nFormat, BitmapEx& rBmpEx )
1817 {
1818     if(FORMAT_BITMAP == nFormat)
1819     {
1820         // try to get PNG first
1821         DataFlavor aFlavor;
1822 
1823         if(SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_PNG, aFlavor))
1824         {
1825             if(GetBitmapEx(aFlavor, rBmpEx))
1826             {
1827                 return true;
1828             }
1829         }
1830     }
1831 
1832     DataFlavor aFlavor;
1833     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetBitmapEx( aFlavor, rBmpEx ) );
1834 }
1835 
1836 // -----------------------------------------------------------------------------
1837 
GetBitmapEx(const DataFlavor & rFlavor,BitmapEx & rBmpEx)1838 sal_Bool TransferableDataHelper::GetBitmapEx( const DataFlavor& rFlavor, BitmapEx& rBmpEx )
1839 {
1840     SotStorageStreamRef xStm;
1841     DataFlavor aSubstFlavor;
1842     bool bRet(GetSotStorageStream(rFlavor, xStm));
1843     bool bSuppressPNG(false); // #122982# If PNG stream not accessed, but BMP one, suppress trying to load PNG
1844 
1845     if(!bRet && HasFormat(SOT_FORMATSTR_ID_PNG) && SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_PNG, aSubstFlavor))
1846     {
1847         // when no direct success, try if PNG is available
1848         bRet = GetSotStorageStream(aSubstFlavor, xStm);
1849     }
1850 
1851     if(!bRet && HasFormat(SOT_FORMATSTR_ID_BMP) && SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_BMP, aSubstFlavor))
1852     {
1853         // when no direct success, try if BMP is available
1854         bRet = GetSotStorageStream(aSubstFlavor, xStm);
1855         bSuppressPNG = bRet;
1856     }
1857 
1858     if(bRet)
1859     {
1860         if(!bSuppressPNG && rFlavor.MimeType.equalsIgnoreAsciiCase(::rtl::OUString::createFromAscii("image/png")))
1861         {
1862             // it's a PNG, import to BitmapEx
1863             ::vcl::PNGReader aPNGReader(*xStm);
1864 
1865             rBmpEx = aPNGReader.Read();
1866         }
1867 
1868         if(rBmpEx.IsEmpty())
1869         {
1870             Bitmap aBitmap;
1871             Bitmap aMask;
1872 
1873             // explicitly use Bitmap::Read with bFileHeader = sal_True
1874             // #124085# keep DIBV5 for read from clipboard, but should not happen
1875             ReadDIBV5(aBitmap, aMask, *xStm);
1876 
1877             if(aMask.IsEmpty())
1878             {
1879                 rBmpEx = aBitmap;
1880             }
1881             else
1882             {
1883                 rBmpEx = BitmapEx(aBitmap, aMask);
1884             }
1885         }
1886 
1887         bRet = (ERRCODE_NONE == xStm->GetError() && !rBmpEx.IsEmpty());
1888 
1889         /* SJ: #110748# At the moment we are having problems with DDB inserted as DIB. The
1890            problem is, that some graphics are inserted much too big because the nXPelsPerMeter
1891            and nYPelsPerMeter of the bitmap fileheader isn't including the correct value.
1892            Due to this reason the following code assumes that bitmaps with a logical size
1893            greater than 50 cm aren't having the correct mapmode set.
1894 
1895            The following code should be removed if DDBs and DIBs are supported via clipboard
1896            properly.
1897         */
1898         if(bRet)
1899         {
1900             const MapMode aMapMode(rBmpEx.GetPrefMapMode());
1901 
1902             if(MAP_PIXEL != aMapMode.GetMapUnit())
1903             {
1904                 const Size aSize(OutputDevice::LogicToLogic(rBmpEx.GetPrefSize(), aMapMode, MAP_100TH_MM));
1905 
1906                 // #122388# This wrongly corrects in the given case; changing from 5000 100th mm to
1907                 // the described 50 cm (which is 50000 100th mm)
1908                 if((aSize.Width() > 50000) || (aSize.Height() > 50000))
1909                 {
1910                     rBmpEx.SetPrefMapMode(MAP_PIXEL);
1911 
1912                     // #122388# also adapt size by applying the mew MapMode
1913                     const Size aNewSize(OutputDevice::LogicToLogic(aSize, MAP_100TH_MM, MAP_PIXEL));
1914                     rBmpEx.SetPrefSize(aNewSize);
1915                 }
1916             }
1917         }
1918     }
1919 
1920     return bRet;
1921 }
1922 
1923 // -----------------------------------------------------------------------------
1924 
GetGDIMetaFile(SotFormatStringId nFormat,GDIMetaFile & rMtf)1925 sal_Bool TransferableDataHelper::GetGDIMetaFile( SotFormatStringId nFormat, GDIMetaFile& rMtf )
1926 {
1927 	DataFlavor aFlavor;
1928 	return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetGDIMetaFile( aFlavor, rMtf ) );
1929 }
1930 
1931 // -----------------------------------------------------------------------------
1932 
GetGDIMetaFile(const DataFlavor & rFlavor,GDIMetaFile & rMtf)1933 sal_Bool TransferableDataHelper::GetGDIMetaFile( const DataFlavor& rFlavor, GDIMetaFile& rMtf )
1934 {
1935 	SotStorageStreamRef xStm;
1936 	DataFlavor			aSubstFlavor;
1937 	sal_Bool			bRet = sal_False;
1938 
1939 	if( GetSotStorageStream( rFlavor, xStm ) )
1940 	{
1941 		*xStm >> rMtf;
1942 		bRet = ( xStm->GetError() == ERRCODE_NONE );
1943 	}
1944 
1945 	if( !bRet &&
1946 		HasFormat( SOT_FORMATSTR_ID_EMF ) &&
1947 		SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_EMF, aSubstFlavor ) &&
1948 		GetSotStorageStream( aSubstFlavor, xStm ) )
1949 	{
1950 		Graphic aGraphic;
1951 
1952 		if( GraphicConverter::Import( *xStm, aGraphic ) == ERRCODE_NONE )
1953 		{
1954 			rMtf = aGraphic.GetGDIMetaFile();
1955 			bRet = sal_True;
1956 		}
1957 	}
1958 
1959 	if( !bRet &&
1960 		HasFormat( SOT_FORMATSTR_ID_WMF ) &&
1961 		SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_WMF, aSubstFlavor ) &&
1962 		GetSotStorageStream( aSubstFlavor, xStm ) )
1963 	{
1964 		Graphic aGraphic;
1965 
1966 		if( GraphicConverter::Import( *xStm, aGraphic ) == ERRCODE_NONE )
1967 		{
1968 			rMtf = aGraphic.GetGDIMetaFile();
1969 			bRet = sal_True;
1970 		}
1971 	}
1972 
1973 	if( !bRet &&
1974 		HasFormat( SOT_FORMATSTR_ID_SVG ) &&
1975 		SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_SVG, aSubstFlavor ) &&
1976 		GetSotStorageStream( aSubstFlavor, xStm ) )
1977 	{
1978 		Graphic aGraphic;
1979 
1980 		if( GraphicConverter::Import( *xStm, aGraphic ) == ERRCODE_NONE )
1981 		{
1982 			rMtf = aGraphic.GetGDIMetaFile();
1983 			bRet = sal_True;
1984 		}
1985 	}
1986 
1987 	return bRet;
1988 }
1989 
1990 // -----------------------------------------------------------------------------
1991 
GetGraphic(SotFormatStringId nFormat,Graphic & rGraphic)1992 sal_Bool TransferableDataHelper::GetGraphic( SotFormatStringId nFormat, Graphic& rGraphic )
1993 {
1994     if(FORMAT_BITMAP == nFormat)
1995     {
1996         // try to get PNG first
1997         DataFlavor aFlavor;
1998 
1999         if(SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_PNG, aFlavor))
2000         {
2001             if(GetGraphic(aFlavor, rGraphic))
2002             {
2003                 return true;
2004             }
2005         }
2006     }
2007 
2008     DataFlavor aFlavor;
2009     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetGraphic( aFlavor, rGraphic ) );
2010 }
2011 
2012 // -----------------------------------------------------------------------------
2013 
GetGraphic(const::com::sun::star::datatransfer::DataFlavor & rFlavor,Graphic & rGraphic)2014 sal_Bool TransferableDataHelper::GetGraphic( const ::com::sun::star::datatransfer::DataFlavor& rFlavor, Graphic& rGraphic )
2015 {
2016 	DataFlavor	aFlavor;
2017 	sal_Bool	bRet = sal_False;
2018 
2019     if(SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_PNG, aFlavor) &&
2020         TransferableDataHelper::IsEqual(aFlavor, rFlavor))
2021 	{
2022         // try to get PNG first
2023 		BitmapEx aBmpEx;
2024 
2025 		if( ( bRet = GetBitmapEx( aFlavor, aBmpEx ) ) == sal_True )
2026 			rGraphic = aBmpEx;
2027 	}
2028 	else if(SotExchange::GetFormatDataFlavor( SOT_FORMAT_BITMAP, aFlavor ) &&
2029 		TransferableDataHelper::IsEqual( aFlavor, rFlavor ) )
2030 	{
2031 		BitmapEx aBmpEx;
2032 
2033 		if( ( bRet = GetBitmapEx( aFlavor, aBmpEx ) ) == sal_True )
2034 			rGraphic = aBmpEx;
2035 	}
2036 	else if( SotExchange::GetFormatDataFlavor( SOT_FORMAT_GDIMETAFILE, aFlavor ) &&
2037 			 TransferableDataHelper::IsEqual( aFlavor, rFlavor ) )
2038 	{
2039 		GDIMetaFile aMtf;
2040 
2041 		if( ( bRet = GetGDIMetaFile( aFlavor, aMtf ) ) == sal_True )
2042 			rGraphic = aMtf;
2043 	}
2044 	else
2045 	{
2046 		SotStorageStreamRef xStm;
2047 
2048 		if( GetSotStorageStream( rFlavor, xStm ) )
2049 		{
2050 			*xStm >> rGraphic;
2051 			bRet = ( xStm->GetError() == ERRCODE_NONE );
2052 		}
2053 	}
2054 
2055 	return bRet;
2056 }
2057 
2058 // -----------------------------------------------------------------------------
2059 
GetImageMap(SotFormatStringId nFormat,ImageMap & rIMap)2060 sal_Bool TransferableDataHelper::GetImageMap( SotFormatStringId nFormat, ImageMap& rIMap )
2061 {
2062 	DataFlavor aFlavor;
2063     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetImageMap( aFlavor, rIMap ) );
2064 }
2065 
2066 // -----------------------------------------------------------------------------
2067 
GetImageMap(const::com::sun::star::datatransfer::DataFlavor & rFlavor,ImageMap & rIMap)2068 sal_Bool TransferableDataHelper::GetImageMap( const ::com::sun::star::datatransfer::DataFlavor& rFlavor, ImageMap& rIMap )
2069 {
2070 	SotStorageStreamRef xStm;
2071 	sal_Bool			bRet = GetSotStorageStream( rFlavor, xStm );
2072 
2073 	if( bRet )
2074 	{
2075         rIMap.Read( *xStm, String() );
2076 		bRet = ( xStm->GetError() == ERRCODE_NONE );
2077 	}
2078 
2079 	return bRet;
2080 }
2081 
2082 // -----------------------------------------------------------------------------
2083 
GetTransferableObjectDescriptor(SotFormatStringId nFormat,TransferableObjectDescriptor & rDesc)2084 sal_Bool TransferableDataHelper::GetTransferableObjectDescriptor( SotFormatStringId nFormat, TransferableObjectDescriptor& rDesc )
2085 {
2086 	DataFlavor aFlavor;
2087 	return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetTransferableObjectDescriptor( aFlavor, rDesc ) );
2088 }
2089 
2090 // -----------------------------------------------------------------------------
2091 
GetTransferableObjectDescriptor(const::com::sun::star::datatransfer::DataFlavor &,TransferableObjectDescriptor & rDesc)2092 sal_Bool TransferableDataHelper::GetTransferableObjectDescriptor( const ::com::sun::star::datatransfer::DataFlavor&, TransferableObjectDescriptor& rDesc )
2093 {
2094     rDesc = *mpObjDesc;
2095     return true;
2096 }
2097 
2098 // -----------------------------------------------------------------------------
2099 
GetINetBookmark(SotFormatStringId nFormat,INetBookmark & rBmk)2100 sal_Bool TransferableDataHelper::GetINetBookmark( SotFormatStringId nFormat, INetBookmark& rBmk )
2101 {
2102 	DataFlavor aFlavor;
2103 	return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetINetBookmark( aFlavor, rBmk ) );
2104 }
2105 
2106 // -----------------------------------------------------------------------------
2107 
GetINetBookmark(const::com::sun::star::datatransfer::DataFlavor & rFlavor,INetBookmark & rBmk)2108 sal_Bool TransferableDataHelper::GetINetBookmark( const ::com::sun::star::datatransfer::DataFlavor& rFlavor, INetBookmark& rBmk )
2109 {
2110 	sal_Bool bRet = sal_False;
2111 	if( HasFormat( rFlavor ))
2112 	{
2113 	const SotFormatStringId nFormat = SotExchange::GetFormat( rFlavor );
2114 	switch( nFormat )
2115 	{
2116 		case( SOT_FORMATSTR_ID_SOLK ):
2117 		case( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ):
2118 		{
2119 			String aString;
2120 			if( GetString( rFlavor, aString ) )
2121 			{
2122 				if( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR == nFormat )
2123 				{
2124 					rBmk = INetBookmark( aString, aString );
2125 					bRet = sal_True;
2126 				}
2127 				else
2128 				{
2129 					String		aURL, aDesc;
2130 					sal_uInt16	nStart = aString.Search( '@' ), nLen = (sal_uInt16) aString.ToInt32();
2131 
2132 					if( !nLen && aString.GetChar( 0 ) != '0' )
2133 					{
2134 						DBG_WARNING( "SOLK: 1. len=0" );
2135 					}
2136 					if( nStart == STRING_NOTFOUND || nLen > aString.Len() - nStart - 3 )
2137 					{
2138 						DBG_WARNING( "SOLK: 1. illegal start or wrong len" );
2139 					}
2140 					aURL = aString.Copy( nStart + 1, nLen );
2141 
2142 					aString.Erase( 0, nStart + 1 + nLen );
2143 					nStart = aString.Search( '@' );
2144 					nLen = (sal_uInt16) aString.ToInt32();
2145 
2146 					if( !nLen && aString.GetChar( 0 ) != '0' )
2147 					{
2148 						DBG_WARNING( "SOLK: 2. len=0" );
2149 					}
2150 					if( nStart == STRING_NOTFOUND || nLen > aString.Len() - nStart - 1 )
2151 					{
2152 						DBG_WARNING( "SOLK: 2. illegal start or wrong len" );
2153 					}
2154 					aDesc = aString.Copy( nStart+1, nLen );
2155 
2156 					rBmk = INetBookmark( aURL, aDesc );
2157 					bRet = sal_True;
2158 				}
2159 			}
2160 		}
2161 		break;
2162 
2163 		case( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ):
2164 		{
2165 			Sequence< sal_Int8 > aSeq;
2166 
2167 			if( GetSequence( rFlavor, aSeq ) && ( 2048 == aSeq.getLength() ) )
2168 			{
2169 				rBmk = INetBookmark( String( reinterpret_cast< const sal_Char* >( aSeq.getConstArray() ), gsl_getSystemTextEncoding() ),
2170 									 String( reinterpret_cast< const sal_Char* >( aSeq.getConstArray() ) + 1024, gsl_getSystemTextEncoding() ) );
2171 				bRet = sal_True;
2172 			}
2173 		}
2174 		break;
2175 
2176 #ifdef WNT
2177 		case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR:
2178 		{
2179 			Sequence< sal_Int8 > aSeq;
2180 
2181 			if( GetSequence( rFlavor, aSeq ) && aSeq.getLength() )
2182 			{
2183 				FILEGROUPDESCRIPTOR* pFDesc = (FILEGROUPDESCRIPTOR*) aSeq.getConstArray();
2184 
2185 				if( pFDesc->cItems )
2186 				{
2187 					ByteString			aDesc( pFDesc->fgd[ 0 ].cFileName );
2188 					rtl_TextEncoding	eTextEncoding = gsl_getSystemTextEncoding();
2189 
2190 					if( ( aDesc.Len() > 4 ) && aDesc.Copy( aDesc.Len() - 4 ).EqualsIgnoreCaseAscii( ".URL" ) )
2191 					{
2192 						SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( INetURLObject( String( aDesc, eTextEncoding ) ).GetMainURL( INetURLObject::NO_DECODE ),
2193                                                                                   STREAM_STD_READ );
2194 
2195 						if( !pStream || pStream->GetError() )
2196 						{
2197 							DataFlavor aFileContentFlavor;
2198 
2199 							aSeq.realloc( 0 );
2200 							delete pStream;
2201 
2202 							if( SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_FILECONTENT, aFileContentFlavor ) &&
2203 								GetSequence( aFileContentFlavor, aSeq ) && aSeq.getLength() )
2204 							{
2205 								pStream = new SvMemoryStream( (sal_Char*) aSeq.getConstArray(), aSeq.getLength(), STREAM_STD_READ );
2206 							}
2207 							else
2208 								pStream = NULL;
2209 						}
2210 
2211 						if( pStream )
2212 						{
2213 							ByteString	aLine;
2214 							sal_Bool	bSttFnd = sal_False;
2215 
2216 							while( pStream->ReadLine( aLine ) )
2217 							{
2218 								if( aLine.EqualsIgnoreCaseAscii( "[InternetShortcut]" ) )
2219 									bSttFnd = sal_True;
2220 								else if( bSttFnd && aLine.Copy( 0, 4 ).EqualsIgnoreCaseAscii( "URL=" ) )
2221 								{
2222 									rBmk = INetBookmark( String( aLine.Erase( 0, 4 ), eTextEncoding ),
2223 														 String( aDesc.Erase( aDesc.Len() - 4 ), eTextEncoding ) );
2224 									bRet = sal_True;
2225 									break;
2226 								}
2227 							}
2228 
2229 							delete pStream;
2230 						}
2231 					}
2232 				}
2233 			}
2234 		}
2235 		break;
2236 #endif
2237 
2238 	}
2239 	}
2240 	return bRet;
2241 }
2242 
2243 // -----------------------------------------------------------------------------
2244 
GetINetImage(SotFormatStringId nFormat,INetImage & rINtImg)2245 sal_Bool TransferableDataHelper::GetINetImage( SotFormatStringId nFormat,
2246 												INetImage& rINtImg )
2247 {
2248 	DataFlavor aFlavor;
2249 	return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetINetImage( aFlavor, rINtImg ) );
2250 }
2251 
2252 // -----------------------------------------------------------------------------
2253 
GetINetImage(const::com::sun::star::datatransfer::DataFlavor & rFlavor,INetImage & rINtImg)2254 sal_Bool TransferableDataHelper::GetINetImage(
2255 		const ::com::sun::star::datatransfer::DataFlavor& rFlavor,
2256 		INetImage& rINtImg )
2257 {
2258 	SotStorageStreamRef xStm;
2259 	sal_Bool bRet = GetSotStorageStream( rFlavor, xStm );
2260 
2261 	if( bRet )
2262 		bRet = rINtImg.Read( *xStm, SotExchange::GetFormat( rFlavor ) );
2263 	return bRet;
2264 }
2265 
2266 // -----------------------------------------------------------------------------
2267 
GetFileList(SotFormatStringId nFormat,FileList & rFileList)2268 sal_Bool TransferableDataHelper::GetFileList( SotFormatStringId nFormat,
2269 												FileList& rFileList )
2270 {
2271 	DataFlavor aFlavor;
2272 	return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetFileList( aFlavor, rFileList ) );
2273 }
2274 
2275 // -----------------------------------------------------------------------------
2276 
GetFileList(const::com::sun::star::datatransfer::DataFlavor &,FileList & rFileList)2277 sal_Bool TransferableDataHelper::GetFileList(
2278 			const ::com::sun::star::datatransfer::DataFlavor&,
2279 			FileList& rFileList )
2280 {
2281 	SotStorageStreamRef xStm;
2282     sal_Bool            bRet = sal_False;
2283 
2284     for( sal_uInt32 i = 0, nFormatCount = GetFormatCount(); ( i < nFormatCount ) && !bRet; ++i )
2285     {
2286         if( SOT_FORMAT_FILE_LIST == GetFormat( i ) )
2287         {
2288             const DataFlavor aFlavor( GetFormatDataFlavor( i ) );
2289 
2290             if( GetSotStorageStream( aFlavor, xStm ) )
2291             {
2292                 if( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( "text/uri-list" ) ) > -1 )
2293                 {
2294                     ByteString aByteString;
2295 
2296                     while( xStm->ReadLine( aByteString ) )
2297                         if( aByteString.Len() && aByteString.GetChar( 0 ) != '#' )
2298                             rFileList.AppendFile( String( aByteString, RTL_TEXTENCODING_UTF8 ) );
2299 
2300                     bRet = sal_True;
2301                  }
2302                  else
2303                     bRet = ( ( *xStm >> rFileList ).GetError() == ERRCODE_NONE );
2304             }
2305         }
2306     }
2307 
2308     return bRet;
2309 }
2310 
2311 // -----------------------------------------------------------------------------
2312 
GetSequence(SotFormatStringId nFormat,Sequence<sal_Int8> & rSeq)2313 sal_Bool TransferableDataHelper::GetSequence( SotFormatStringId nFormat, Sequence< sal_Int8 >& rSeq )
2314 {
2315 	DataFlavor aFlavor;
2316 	return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetSequence( aFlavor, rSeq ) );
2317 }
2318 
2319 // -----------------------------------------------------------------------------
2320 
GetSequence(const DataFlavor & rFlavor,Sequence<sal_Int8> & rSeq)2321 sal_Bool TransferableDataHelper::GetSequence( const DataFlavor& rFlavor, Sequence< sal_Int8 >& rSeq )
2322 {
2323 #ifdef DEBUG
2324     fprintf( stderr, "TransferableDataHelper requests sequence of data\n" );
2325 #endif
2326 
2327     const Any aAny( GetAny( rFlavor ) );
2328 	return( aAny.hasValue() && ( aAny >>= rSeq ) );
2329 }
2330 
2331 // -----------------------------------------------------------------------------
2332 
GetSotStorageStream(SotFormatStringId nFormat,SotStorageStreamRef & rxStream)2333 sal_Bool TransferableDataHelper::GetSotStorageStream( SotFormatStringId nFormat, SotStorageStreamRef& rxStream )
2334 {
2335     DataFlavor aFlavor;
2336 	return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetSotStorageStream( aFlavor, rxStream ) );
2337 }
2338 
2339 // -----------------------------------------------------------------------------
2340 
GetSotStorageStream(const DataFlavor & rFlavor,SotStorageStreamRef & rxStream)2341 sal_Bool TransferableDataHelper::GetSotStorageStream( const DataFlavor& rFlavor, SotStorageStreamRef& rxStream )
2342 {
2343 	Sequence< sal_Int8 >	aSeq;
2344 	sal_Bool				bRet = GetSequence( rFlavor, aSeq );
2345 
2346 	if( bRet )
2347 	{
2348 		rxStream = new SotStorageStream( String() );
2349 		rxStream->Write( aSeq.getConstArray(), aSeq.getLength() );
2350 		rxStream->Seek( 0 );
2351 	}
2352 
2353 	return bRet;
2354 }
2355 
GetInputStream(SotFormatStringId nFormat,Reference<XInputStream> & rxStream)2356 sal_Bool TransferableDataHelper::GetInputStream( SotFormatStringId nFormat, Reference < XInputStream >& rxStream )
2357 {
2358 	DataFlavor aFlavor;
2359     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetInputStream( aFlavor, rxStream ) );
2360 }
2361 
2362 // -----------------------------------------------------------------------------
2363 
GetInputStream(const DataFlavor & rFlavor,Reference<XInputStream> & rxStream)2364 sal_Bool TransferableDataHelper::GetInputStream( const DataFlavor& rFlavor, Reference < XInputStream >& rxStream )
2365 {
2366 	Sequence< sal_Int8 >	aSeq;
2367 	sal_Bool				bRet = GetSequence( rFlavor, aSeq );
2368 
2369 	if( bRet )
2370           rxStream = new ::comphelper::SequenceInputStream( aSeq );
2371 
2372 	return bRet;
2373 }
2374 
2375 // -----------------------------------------------------------------------------
2376 
2377 
GetInterface(SotFormatStringId nFormat,Reference<XInterface> & rIf)2378 sal_Bool TransferableDataHelper::GetInterface( SotFormatStringId nFormat, Reference< XInterface >& rIf )
2379 {
2380 	DataFlavor aFlavor;
2381 	return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetInterface( aFlavor, rIf ) );
2382 }
2383 
2384 // -----------------------------------------------------------------------------
2385 
GetInterface(const DataFlavor & rFlavor,Reference<XInterface> & rIf)2386 sal_Bool TransferableDataHelper::GetInterface( const DataFlavor& rFlavor, Reference< XInterface >& rIf )
2387 {
2388 	const Any aAny( GetAny( rFlavor ) );
2389 	return( aAny.hasValue() && ( aAny >>= rIf ) );
2390 }
2391 
2392 // -----------------------------------------------------------------------------
Rebind(const Reference<XTransferable> & _rxNewContent)2393 void TransferableDataHelper::Rebind( const Reference< XTransferable >& _rxNewContent )
2394 {
2395 	mxTransfer = _rxNewContent;
2396 	InitFormats();
2397 }
2398 
2399 // -----------------------------------------------------------------------------
2400 
StartClipboardListening()2401 sal_Bool TransferableDataHelper::StartClipboardListening( )
2402 {
2403     ::osl::MutexGuard aGuard( mpImpl->maMutex );
2404 
2405     StopClipboardListening( );
2406 
2407 	mpImpl->mpClipboardListener = new TransferableClipboardNotifier( mxClipboard, *this, mpImpl->maMutex );
2408     mpImpl->mpClipboardListener->acquire();
2409 
2410 	return mpImpl->mpClipboardListener->isListening();
2411 }
2412 
2413 // -----------------------------------------------------------------------------
2414 
StopClipboardListening()2415 void TransferableDataHelper::StopClipboardListening( )
2416 {
2417     ::osl::MutexGuard aGuard( mpImpl->maMutex );
2418 
2419 	if ( mpImpl->mpClipboardListener )
2420     {
2421         mpImpl->mpClipboardListener->dispose();
2422         mpImpl->mpClipboardListener->release();
2423         mpImpl->mpClipboardListener = NULL;
2424     }
2425 }
2426 
2427 // -----------------------------------------------------------------------------
2428 
CreateFromSystemClipboard(Window * pWindow)2429 TransferableDataHelper TransferableDataHelper::CreateFromSystemClipboard( Window * pWindow )
2430 {
2431 	DBG_ASSERT( pWindow, "Window pointer is NULL" );
2432 
2433     Reference< XClipboard >	xClipboard;
2434    	TransferableDataHelper	aRet;
2435 
2436     if( pWindow )
2437         xClipboard = pWindow->GetClipboard();
2438 
2439     if( xClipboard.is() )
2440    	{
2441    		try
2442 
2443     	{
2444 	    	Reference< XTransferable > xTransferable( xClipboard->getContents() );
2445 
2446 		    if( xTransferable.is() )
2447 			{
2448     			aRet = TransferableDataHelper( xTransferable );
2449    				aRet.mxClipboard = xClipboard;
2450 					// also copy the clipboard - 99030 - 23.05.2002 - fs@openoffice.org
2451 			}
2452    		}
2453     	catch( const ::com::sun::star::uno::Exception& )
2454 	    {
2455    		}
2456     }
2457 
2458 	return aRet;
2459 }
2460 
2461 
2462 // -----------------------------------------------------------------------------
2463 
CreateFromSelection(Window * pWindow)2464 TransferableDataHelper TransferableDataHelper::CreateFromSelection( Window* pWindow )
2465 {
2466 	DBG_ASSERT( pWindow, "Window pointer is NULL" );
2467 
2468     Reference< XClipboard >	xSelection;
2469    	TransferableDataHelper	aRet;
2470 
2471     if( pWindow )
2472         xSelection = pWindow->GetPrimarySelection();
2473 
2474     if( xSelection.is() )
2475    	{
2476         const sal_uInt32 nRef = Application::ReleaseSolarMutex();
2477 
2478   		try
2479     	{
2480 	    	Reference< XTransferable > xTransferable( xSelection->getContents() );
2481 
2482 		    if( xTransferable.is() )
2483    			{
2484     			aRet = TransferableDataHelper( xTransferable );
2485    				aRet.mxClipboard = xSelection;
2486 		    }
2487    		}
2488     	catch( const ::com::sun::star::uno::Exception& )
2489 	    {
2490    		}
2491 
2492         Application::AcquireSolarMutex( nRef );
2493     }
2494 
2495 	return aRet;
2496 }
2497 
2498 // -----------------------------------------------------------------------------
IsEqual(const::com::sun::star::datatransfer::DataFlavor & rInternalFlavor,const::com::sun::star::datatransfer::DataFlavor & rRequestFlavor,sal_Bool)2499 sal_Bool TransferableDataHelper::IsEqual( const ::com::sun::star::datatransfer::DataFlavor& rInternalFlavor,
2500 										  const ::com::sun::star::datatransfer::DataFlavor& rRequestFlavor,
2501                                           sal_Bool )
2502 {
2503     Reference< XMultiServiceFactory >       xFact( ::comphelper::getProcessServiceFactory() );
2504     Reference< XMimeContentTypeFactory >    xMimeFact;
2505 	sal_Bool								bRet = sal_False;
2506 
2507     try
2508     {
2509 		if( xFact.is() )
2510     	    xMimeFact = Reference< XMimeContentTypeFactory >( xFact->createInstance( ::rtl::OUString::createFromAscii(
2511                                                               "com.sun.star.datatransfer.MimeContentTypeFactory" ) ),
2512                                                               UNO_QUERY );
2513 
2514         if( xMimeFact.is() )
2515 		{
2516             Reference< XMimeContentType > xRequestType1( xMimeFact->createMimeContentType( rInternalFlavor.MimeType ) );
2517             Reference< XMimeContentType > xRequestType2( xMimeFact->createMimeContentType( rRequestFlavor.MimeType ) );
2518 
2519 			if( xRequestType1.is() && xRequestType2.is() )
2520             {
2521                 if( xRequestType1->getFullMediaType().equalsIgnoreAsciiCase( xRequestType2->getFullMediaType() ) )
2522 			    {
2523                     if( xRequestType1->getFullMediaType().equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "text/plain" ) ) )
2524                     {
2525                         // special handling for text/plain media types
2526                         const ::rtl::OUString aCharsetString( ::rtl::OUString::createFromAscii( "charset" ) );
2527 
2528                         if( !xRequestType2->hasParameter( aCharsetString ) ||
2529 						    xRequestType2->getParameterValue( aCharsetString ).equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "utf-16" ) ) ||
2530 						    xRequestType2->getParameterValue( aCharsetString ).equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "unicode" ) ) )
2531                         {
2532                             bRet = sal_True;
2533                         }
2534                     }
2535                     else if( xRequestType1->getFullMediaType().equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "application/x-openoffice" ) ) )
2536                     {
2537                         // special handling for application/x-openoffice media types
2538                         const ::rtl::OUString aFormatString( ::rtl::OUString::createFromAscii( "windows_formatname" ) );
2539 
2540                         if( xRequestType1->hasParameter( aFormatString ) &&
2541                             xRequestType2->hasParameter( aFormatString ) &&
2542                             xRequestType1->getParameterValue( aFormatString ).equalsIgnoreAsciiCase( xRequestType2->getParameterValue( aFormatString ) ) )
2543                         {
2544                             bRet = sal_True;
2545                         }
2546                     }
2547                     else
2548                         bRet = sal_True;
2549 			    }
2550             }
2551 		}
2552     }
2553     catch( const ::com::sun::star::uno::Exception& )
2554 	{
2555         bRet = rInternalFlavor.MimeType.equalsIgnoreAsciiCase( rRequestFlavor.MimeType );
2556 	}
2557 
2558     return bRet;
2559 }
2560