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