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