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