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