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