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