xref: /AOO41X/main/svtools/source/misc/transfer.cxx (revision 5980243063f6840bf3a2e60b2243db5da5e78fa6)
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                 if((aSize.Width() > 5000) || (aSize.Height() > 5000))
1871                 {
1872                     rBmpEx.SetPrefMapMode(MAP_PIXEL);
1873                 }
1874             }
1875         }
1876     }
1877 
1878     return bRet;
1879 }
1880 
1881 // -----------------------------------------------------------------------------
1882 
1883 sal_Bool TransferableDataHelper::GetGDIMetaFile( SotFormatStringId nFormat, GDIMetaFile& rMtf )
1884 {
1885     DataFlavor aFlavor;
1886     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetGDIMetaFile( aFlavor, rMtf ) );
1887 }
1888 
1889 // -----------------------------------------------------------------------------
1890 
1891 sal_Bool TransferableDataHelper::GetGDIMetaFile( const DataFlavor& rFlavor, GDIMetaFile& rMtf )
1892 {
1893     SotStorageStreamRef xStm;
1894     DataFlavor          aSubstFlavor;
1895     sal_Bool            bRet = sal_False;
1896 
1897     if( GetSotStorageStream( rFlavor, xStm ) )
1898     {
1899         *xStm >> rMtf;
1900         bRet = ( xStm->GetError() == ERRCODE_NONE );
1901     }
1902 
1903     if( !bRet &&
1904         HasFormat( SOT_FORMATSTR_ID_EMF ) &&
1905         SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_EMF, aSubstFlavor ) &&
1906         GetSotStorageStream( aSubstFlavor, xStm ) )
1907     {
1908         Graphic aGraphic;
1909 
1910         if( GraphicConverter::Import( *xStm, aGraphic ) == ERRCODE_NONE )
1911         {
1912             rMtf = aGraphic.GetGDIMetaFile();
1913             bRet = sal_True;
1914         }
1915     }
1916 
1917     if( !bRet &&
1918         HasFormat( SOT_FORMATSTR_ID_WMF ) &&
1919         SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_WMF, aSubstFlavor ) &&
1920         GetSotStorageStream( aSubstFlavor, xStm ) )
1921     {
1922         Graphic aGraphic;
1923 
1924         if( GraphicConverter::Import( *xStm, aGraphic ) == ERRCODE_NONE )
1925         {
1926             rMtf = aGraphic.GetGDIMetaFile();
1927             bRet = sal_True;
1928         }
1929     }
1930 
1931     return bRet;
1932 }
1933 
1934 // -----------------------------------------------------------------------------
1935 
1936 sal_Bool TransferableDataHelper::GetGraphic( SotFormatStringId nFormat, Graphic& rGraphic )
1937 {
1938     if(FORMAT_BITMAP == nFormat)
1939     {
1940         // try to get PNG first
1941         DataFlavor aFlavor;
1942 
1943         if(SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_PNG, aFlavor))
1944         {
1945             if(GetGraphic(aFlavor, rGraphic))
1946             {
1947                 return true;
1948             }
1949         }
1950     }
1951 
1952     DataFlavor aFlavor;
1953     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetGraphic( aFlavor, rGraphic ) );
1954 }
1955 
1956 // -----------------------------------------------------------------------------
1957 
1958 sal_Bool TransferableDataHelper::GetGraphic( const ::com::sun::star::datatransfer::DataFlavor& rFlavor, Graphic& rGraphic )
1959 {
1960     DataFlavor  aFlavor;
1961     sal_Bool    bRet = sal_False;
1962 
1963     if(SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_PNG, aFlavor) &&
1964         TransferableDataHelper::IsEqual(aFlavor, rFlavor))
1965     {
1966         // try to get PNG first
1967         BitmapEx aBmpEx;
1968 
1969         if( ( bRet = GetBitmapEx( aFlavor, aBmpEx ) ) == sal_True )
1970             rGraphic = aBmpEx;
1971     }
1972     else if(SotExchange::GetFormatDataFlavor( SOT_FORMAT_BITMAP, aFlavor ) &&
1973         TransferableDataHelper::IsEqual( aFlavor, rFlavor ) )
1974     {
1975         BitmapEx aBmpEx;
1976 
1977         if( ( bRet = GetBitmapEx( aFlavor, aBmpEx ) ) == sal_True )
1978             rGraphic = aBmpEx;
1979     }
1980     else if( SotExchange::GetFormatDataFlavor( SOT_FORMAT_GDIMETAFILE, aFlavor ) &&
1981              TransferableDataHelper::IsEqual( aFlavor, rFlavor ) )
1982     {
1983         GDIMetaFile aMtf;
1984 
1985         if( ( bRet = GetGDIMetaFile( aFlavor, aMtf ) ) == sal_True )
1986             rGraphic = aMtf;
1987     }
1988     else
1989     {
1990         SotStorageStreamRef xStm;
1991 
1992         if( GetSotStorageStream( rFlavor, xStm ) )
1993         {
1994             *xStm >> rGraphic;
1995             bRet = ( xStm->GetError() == ERRCODE_NONE );
1996         }
1997     }
1998 
1999     return bRet;
2000 }
2001 
2002 // -----------------------------------------------------------------------------
2003 
2004 sal_Bool TransferableDataHelper::GetImageMap( SotFormatStringId nFormat, ImageMap& rIMap )
2005 {
2006     DataFlavor aFlavor;
2007     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetImageMap( aFlavor, rIMap ) );
2008 }
2009 
2010 // -----------------------------------------------------------------------------
2011 
2012 sal_Bool TransferableDataHelper::GetImageMap( const ::com::sun::star::datatransfer::DataFlavor& rFlavor, ImageMap& rIMap )
2013 {
2014     SotStorageStreamRef xStm;
2015     sal_Bool            bRet = GetSotStorageStream( rFlavor, xStm );
2016 
2017     if( bRet )
2018     {
2019         rIMap.Read( *xStm, String() );
2020         bRet = ( xStm->GetError() == ERRCODE_NONE );
2021     }
2022 
2023     return bRet;
2024 }
2025 
2026 // -----------------------------------------------------------------------------
2027 
2028 sal_Bool TransferableDataHelper::GetTransferableObjectDescriptor( SotFormatStringId nFormat, TransferableObjectDescriptor& rDesc )
2029 {
2030     DataFlavor aFlavor;
2031     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetTransferableObjectDescriptor( aFlavor, rDesc ) );
2032 }
2033 
2034 // -----------------------------------------------------------------------------
2035 
2036 sal_Bool TransferableDataHelper::GetTransferableObjectDescriptor( const ::com::sun::star::datatransfer::DataFlavor&, TransferableObjectDescriptor& rDesc )
2037 {
2038     rDesc = *mpObjDesc;
2039     return true;
2040 }
2041 
2042 // -----------------------------------------------------------------------------
2043 
2044 sal_Bool TransferableDataHelper::GetINetBookmark( SotFormatStringId nFormat, INetBookmark& rBmk )
2045 {
2046     DataFlavor aFlavor;
2047     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetINetBookmark( aFlavor, rBmk ) );
2048 }
2049 
2050 // -----------------------------------------------------------------------------
2051 
2052 sal_Bool TransferableDataHelper::GetINetBookmark( const ::com::sun::star::datatransfer::DataFlavor& rFlavor, INetBookmark& rBmk )
2053 {
2054     sal_Bool bRet = sal_False;
2055     if( HasFormat( rFlavor ))
2056     {
2057     const SotFormatStringId nFormat = SotExchange::GetFormat( rFlavor );
2058     switch( nFormat )
2059     {
2060         case( SOT_FORMATSTR_ID_SOLK ):
2061         case( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ):
2062         {
2063             String aString;
2064             if( GetString( rFlavor, aString ) )
2065             {
2066                 if( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR == nFormat )
2067                 {
2068                     rBmk = INetBookmark( aString, aString );
2069                     bRet = sal_True;
2070                 }
2071                 else
2072                 {
2073                     String      aURL, aDesc;
2074                     sal_uInt16  nStart = aString.Search( '@' ), nLen = (sal_uInt16) aString.ToInt32();
2075 
2076                     if( !nLen && aString.GetChar( 0 ) != '0' )
2077                     {
2078                         DBG_WARNING( "SOLK: 1. len=0" );
2079                     }
2080                     if( nStart == STRING_NOTFOUND || nLen > aString.Len() - nStart - 3 )
2081                     {
2082                         DBG_WARNING( "SOLK: 1. illegal start or wrong len" );
2083                     }
2084                     aURL = aString.Copy( nStart + 1, nLen );
2085 
2086                     aString.Erase( 0, nStart + 1 + nLen );
2087                     nStart = aString.Search( '@' );
2088                     nLen = (sal_uInt16) aString.ToInt32();
2089 
2090                     if( !nLen && aString.GetChar( 0 ) != '0' )
2091                     {
2092                         DBG_WARNING( "SOLK: 2. len=0" );
2093                     }
2094                     if( nStart == STRING_NOTFOUND || nLen > aString.Len() - nStart - 1 )
2095                     {
2096                         DBG_WARNING( "SOLK: 2. illegal start or wrong len" );
2097                     }
2098                     aDesc = aString.Copy( nStart+1, nLen );
2099 
2100                     rBmk = INetBookmark( aURL, aDesc );
2101                     bRet = sal_True;
2102                 }
2103             }
2104         }
2105         break;
2106 
2107         case( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ):
2108         {
2109             Sequence< sal_Int8 > aSeq;
2110 
2111             if( GetSequence( rFlavor, aSeq ) && ( 2048 == aSeq.getLength() ) )
2112             {
2113                 rBmk = INetBookmark( String( reinterpret_cast< const sal_Char* >( aSeq.getConstArray() ), gsl_getSystemTextEncoding() ),
2114                                      String( reinterpret_cast< const sal_Char* >( aSeq.getConstArray() ) + 1024, gsl_getSystemTextEncoding() ) );
2115                 bRet = sal_True;
2116             }
2117         }
2118         break;
2119 
2120 #ifdef WNT
2121         case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR:
2122         {
2123             Sequence< sal_Int8 > aSeq;
2124 
2125             if( GetSequence( rFlavor, aSeq ) && aSeq.getLength() )
2126             {
2127                 FILEGROUPDESCRIPTOR* pFDesc = (FILEGROUPDESCRIPTOR*) aSeq.getConstArray();
2128 
2129                 if( pFDesc->cItems )
2130                 {
2131                     ByteString          aDesc( pFDesc->fgd[ 0 ].cFileName );
2132                     rtl_TextEncoding    eTextEncoding = gsl_getSystemTextEncoding();
2133 
2134                     if( ( aDesc.Len() > 4 ) && aDesc.Copy( aDesc.Len() - 4 ).EqualsIgnoreCaseAscii( ".URL" ) )
2135                     {
2136                         SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( INetURLObject( String( aDesc, eTextEncoding ) ).GetMainURL( INetURLObject::NO_DECODE ),
2137                                                                                   STREAM_STD_READ );
2138 
2139                         if( !pStream || pStream->GetError() )
2140                         {
2141                             DataFlavor aFileContentFlavor;
2142 
2143                             aSeq.realloc( 0 );
2144                             delete pStream;
2145 
2146                             if( SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_FILECONTENT, aFileContentFlavor ) &&
2147                                 GetSequence( aFileContentFlavor, aSeq ) && aSeq.getLength() )
2148                             {
2149                                 pStream = new SvMemoryStream( (sal_Char*) aSeq.getConstArray(), aSeq.getLength(), STREAM_STD_READ );
2150                             }
2151                             else
2152                                 pStream = NULL;
2153                         }
2154 
2155                         if( pStream )
2156                         {
2157                             ByteString  aLine;
2158                             sal_Bool    bSttFnd = sal_False;
2159 
2160                             while( pStream->ReadLine( aLine ) )
2161                             {
2162                                 if( aLine.EqualsIgnoreCaseAscii( "[InternetShortcut]" ) )
2163                                     bSttFnd = sal_True;
2164                                 else if( bSttFnd && aLine.Copy( 0, 4 ).EqualsIgnoreCaseAscii( "URL=" ) )
2165                                 {
2166                                     rBmk = INetBookmark( String( aLine.Erase( 0, 4 ), eTextEncoding ),
2167                                                          String( aDesc.Erase( aDesc.Len() - 4 ), eTextEncoding ) );
2168                                     bRet = sal_True;
2169                                     break;
2170                                 }
2171                             }
2172 
2173                             delete pStream;
2174                         }
2175                     }
2176                 }
2177             }
2178         }
2179         break;
2180 #endif
2181 
2182     }
2183     }
2184     return bRet;
2185 }
2186 
2187 // -----------------------------------------------------------------------------
2188 
2189 sal_Bool TransferableDataHelper::GetINetImage( SotFormatStringId nFormat,
2190                                                 INetImage& rINtImg )
2191 {
2192     DataFlavor aFlavor;
2193     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetINetImage( aFlavor, rINtImg ) );
2194 }
2195 
2196 // -----------------------------------------------------------------------------
2197 
2198 sal_Bool TransferableDataHelper::GetINetImage(
2199         const ::com::sun::star::datatransfer::DataFlavor& rFlavor,
2200         INetImage& rINtImg )
2201 {
2202     SotStorageStreamRef xStm;
2203     sal_Bool bRet = GetSotStorageStream( rFlavor, xStm );
2204 
2205     if( bRet )
2206         bRet = rINtImg.Read( *xStm, SotExchange::GetFormat( rFlavor ) );
2207     return bRet;
2208 }
2209 
2210 // -----------------------------------------------------------------------------
2211 
2212 sal_Bool TransferableDataHelper::GetFileList( SotFormatStringId nFormat,
2213                                                 FileList& rFileList )
2214 {
2215     DataFlavor aFlavor;
2216     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetFileList( aFlavor, rFileList ) );
2217 }
2218 
2219 // -----------------------------------------------------------------------------
2220 
2221 sal_Bool TransferableDataHelper::GetFileList(
2222             const ::com::sun::star::datatransfer::DataFlavor&,
2223             FileList& rFileList )
2224 {
2225     SotStorageStreamRef xStm;
2226     sal_Bool            bRet = sal_False;
2227 
2228     for( sal_uInt32 i = 0, nFormatCount = GetFormatCount(); ( i < nFormatCount ) && !bRet; ++i )
2229     {
2230         if( SOT_FORMAT_FILE_LIST == GetFormat( i ) )
2231         {
2232             const DataFlavor aFlavor( GetFormatDataFlavor( i ) );
2233 
2234             if( GetSotStorageStream( aFlavor, xStm ) )
2235             {
2236                 if( aFlavor.MimeType.indexOf( ::rtl::OUString::createFromAscii( "text/uri-list" ) ) > -1 )
2237                 {
2238                     ByteString aByteString;
2239 
2240                     while( xStm->ReadLine( aByteString ) )
2241                         if( aByteString.Len() && aByteString.GetChar( 0 ) != '#' )
2242                             rFileList.AppendFile( String( aByteString, RTL_TEXTENCODING_UTF8 ) );
2243 
2244                     bRet = sal_True;
2245                  }
2246                  else
2247                     bRet = ( ( *xStm >> rFileList ).GetError() == ERRCODE_NONE );
2248             }
2249         }
2250     }
2251 
2252     return bRet;
2253 }
2254 
2255 // -----------------------------------------------------------------------------
2256 
2257 sal_Bool TransferableDataHelper::GetSequence( SotFormatStringId nFormat, Sequence< sal_Int8 >& rSeq )
2258 {
2259     DataFlavor aFlavor;
2260     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetSequence( aFlavor, rSeq ) );
2261 }
2262 
2263 // -----------------------------------------------------------------------------
2264 
2265 sal_Bool TransferableDataHelper::GetSequence( const DataFlavor& rFlavor, Sequence< sal_Int8 >& rSeq )
2266 {
2267 #ifdef DEBUG
2268     fprintf( stderr, "TransferableDataHelper requests sequence of data\n" );
2269 #endif
2270 
2271     const Any aAny( GetAny( rFlavor ) );
2272     return( aAny.hasValue() && ( aAny >>= rSeq ) );
2273 }
2274 
2275 // -----------------------------------------------------------------------------
2276 
2277 sal_Bool TransferableDataHelper::GetSotStorageStream( SotFormatStringId nFormat, SotStorageStreamRef& rxStream )
2278 {
2279     DataFlavor aFlavor;
2280     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetSotStorageStream( aFlavor, rxStream ) );
2281 }
2282 
2283 // -----------------------------------------------------------------------------
2284 
2285 sal_Bool TransferableDataHelper::GetSotStorageStream( const DataFlavor& rFlavor, SotStorageStreamRef& rxStream )
2286 {
2287     Sequence< sal_Int8 >    aSeq;
2288     sal_Bool                bRet = GetSequence( rFlavor, aSeq );
2289 
2290     if( bRet )
2291     {
2292         rxStream = new SotStorageStream( String() );
2293         rxStream->Write( aSeq.getConstArray(), aSeq.getLength() );
2294         rxStream->Seek( 0 );
2295     }
2296 
2297     return bRet;
2298 }
2299 
2300 sal_Bool TransferableDataHelper::GetInputStream( SotFormatStringId nFormat, Reference < XInputStream >& rxStream )
2301 {
2302     DataFlavor aFlavor;
2303     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetInputStream( aFlavor, rxStream ) );
2304 }
2305 
2306 // -----------------------------------------------------------------------------
2307 
2308 sal_Bool TransferableDataHelper::GetInputStream( const DataFlavor& rFlavor, Reference < XInputStream >& rxStream )
2309 {
2310     Sequence< sal_Int8 >    aSeq;
2311     sal_Bool                bRet = GetSequence( rFlavor, aSeq );
2312 
2313     if( bRet )
2314           rxStream = new ::comphelper::SequenceInputStream( aSeq );
2315 
2316     return bRet;
2317 }
2318 
2319 // -----------------------------------------------------------------------------
2320 
2321 
2322 sal_Bool TransferableDataHelper::GetInterface( SotFormatStringId nFormat, Reference< XInterface >& rIf )
2323 {
2324     DataFlavor aFlavor;
2325     return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetInterface( aFlavor, rIf ) );
2326 }
2327 
2328 // -----------------------------------------------------------------------------
2329 
2330 sal_Bool TransferableDataHelper::GetInterface( const DataFlavor& rFlavor, Reference< XInterface >& rIf )
2331 {
2332     const Any aAny( GetAny( rFlavor ) );
2333     return( aAny.hasValue() && ( aAny >>= rIf ) );
2334 }
2335 
2336 // -----------------------------------------------------------------------------
2337 void TransferableDataHelper::Rebind( const Reference< XTransferable >& _rxNewContent )
2338 {
2339     mxTransfer = _rxNewContent;
2340     InitFormats();
2341 }
2342 
2343 // -----------------------------------------------------------------------------
2344 
2345 sal_Bool TransferableDataHelper::StartClipboardListening( )
2346 {
2347     ::osl::MutexGuard aGuard( mpImpl->maMutex );
2348 
2349     StopClipboardListening( );
2350 
2351     mpImpl->mpClipboardListener = new TransferableClipboardNotifier( mxClipboard, *this, mpImpl->maMutex );
2352     mpImpl->mpClipboardListener->acquire();
2353 
2354     return mpImpl->mpClipboardListener->isListening();
2355 }
2356 
2357 // -----------------------------------------------------------------------------
2358 
2359 void TransferableDataHelper::StopClipboardListening( )
2360 {
2361     ::osl::MutexGuard aGuard( mpImpl->maMutex );
2362 
2363     if ( mpImpl->mpClipboardListener )
2364     {
2365         mpImpl->mpClipboardListener->dispose();
2366         mpImpl->mpClipboardListener->release();
2367         mpImpl->mpClipboardListener = NULL;
2368     }
2369 }
2370 
2371 // -----------------------------------------------------------------------------
2372 
2373 TransferableDataHelper TransferableDataHelper::CreateFromSystemClipboard( Window * pWindow )
2374 {
2375     DBG_ASSERT( pWindow, "Window pointer is NULL" );
2376 
2377     Reference< XClipboard > xClipboard;
2378     TransferableDataHelper  aRet;
2379 
2380     if( pWindow )
2381         xClipboard = pWindow->GetClipboard();
2382 
2383     if( xClipboard.is() )
2384     {
2385         try
2386 
2387         {
2388             Reference< XTransferable > xTransferable( xClipboard->getContents() );
2389 
2390             if( xTransferable.is() )
2391             {
2392                 aRet = TransferableDataHelper( xTransferable );
2393                 aRet.mxClipboard = xClipboard;
2394                     // also copy the clipboard - 99030 - 23.05.2002 - fs@openoffice.org
2395             }
2396         }
2397         catch( const ::com::sun::star::uno::Exception& )
2398         {
2399         }
2400     }
2401 
2402     return aRet;
2403 }
2404 
2405 
2406 // -----------------------------------------------------------------------------
2407 
2408 TransferableDataHelper TransferableDataHelper::CreateFromSelection( Window* pWindow )
2409 {
2410     DBG_ASSERT( pWindow, "Window pointer is NULL" );
2411 
2412     Reference< XClipboard > xSelection;
2413     TransferableDataHelper  aRet;
2414 
2415     if( pWindow )
2416         xSelection = pWindow->GetPrimarySelection();
2417 
2418     if( xSelection.is() )
2419     {
2420         const sal_uInt32 nRef = Application::ReleaseSolarMutex();
2421 
2422         try
2423         {
2424             Reference< XTransferable > xTransferable( xSelection->getContents() );
2425 
2426             if( xTransferable.is() )
2427             {
2428                 aRet = TransferableDataHelper( xTransferable );
2429                 aRet.mxClipboard = xSelection;
2430             }
2431         }
2432         catch( const ::com::sun::star::uno::Exception& )
2433         {
2434         }
2435 
2436         Application::AcquireSolarMutex( nRef );
2437     }
2438 
2439     return aRet;
2440 }
2441 
2442 // -----------------------------------------------------------------------------
2443 sal_Bool TransferableDataHelper::IsEqual( const ::com::sun::star::datatransfer::DataFlavor& rInternalFlavor,
2444                                           const ::com::sun::star::datatransfer::DataFlavor& rRequestFlavor,
2445                                           sal_Bool )
2446 {
2447     Reference< XMultiServiceFactory >       xFact( ::comphelper::getProcessServiceFactory() );
2448     Reference< XMimeContentTypeFactory >    xMimeFact;
2449     sal_Bool                                bRet = sal_False;
2450 
2451     try
2452     {
2453         if( xFact.is() )
2454             xMimeFact = Reference< XMimeContentTypeFactory >( xFact->createInstance( ::rtl::OUString::createFromAscii(
2455                                                               "com.sun.star.datatransfer.MimeContentTypeFactory" ) ),
2456                                                               UNO_QUERY );
2457 
2458         if( xMimeFact.is() )
2459         {
2460             Reference< XMimeContentType > xRequestType1( xMimeFact->createMimeContentType( rInternalFlavor.MimeType ) );
2461             Reference< XMimeContentType > xRequestType2( xMimeFact->createMimeContentType( rRequestFlavor.MimeType ) );
2462 
2463             if( xRequestType1.is() && xRequestType2.is() )
2464             {
2465                 if( xRequestType1->getFullMediaType().equalsIgnoreAsciiCase( xRequestType2->getFullMediaType() ) )
2466                 {
2467                     if( xRequestType1->getFullMediaType().equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "text/plain" ) ) )
2468                     {
2469                         // special handling for text/plain media types
2470                         const ::rtl::OUString aCharsetString( ::rtl::OUString::createFromAscii( "charset" ) );
2471 
2472                         if( !xRequestType2->hasParameter( aCharsetString ) ||
2473                             xRequestType2->getParameterValue( aCharsetString ).equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "utf-16" ) ) ||
2474                             xRequestType2->getParameterValue( aCharsetString ).equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "unicode" ) ) )
2475                         {
2476                             bRet = sal_True;
2477                         }
2478                     }
2479                     else if( xRequestType1->getFullMediaType().equalsIgnoreAsciiCase( ::rtl::OUString::createFromAscii( "application/x-openoffice" ) ) )
2480                     {
2481                         // special handling for application/x-openoffice media types
2482                         const ::rtl::OUString aFormatString( ::rtl::OUString::createFromAscii( "windows_formatname" ) );
2483 
2484                         if( xRequestType1->hasParameter( aFormatString ) &&
2485                             xRequestType2->hasParameter( aFormatString ) &&
2486                             xRequestType1->getParameterValue( aFormatString ).equalsIgnoreAsciiCase( xRequestType2->getParameterValue( aFormatString ) ) )
2487                         {
2488                             bRet = sal_True;
2489                         }
2490                     }
2491                     else
2492                         bRet = sal_True;
2493                 }
2494             }
2495         }
2496     }
2497     catch( const ::com::sun::star::uno::Exception& )
2498     {
2499         bRet = rInternalFlavor.MimeType.equalsIgnoreAsciiCase( rRequestFlavor.MimeType );
2500     }
2501 
2502     return bRet;
2503 }
2504