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