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 2 : static OUString ImplGetParameterString( const TransferableObjectDescriptor& rObjDesc )
113 : {
114 2 : const OUString aChar( "\"" );
115 4 : const OUString aClassName( rObjDesc.maClassName.GetHexName() );
116 2 : OUString aParams;
117 :
118 2 : if( !aClassName.isEmpty() )
119 : {
120 2 : aParams += OUString( ";classname=\"" );
121 2 : aParams += aClassName;
122 2 : aParams += aChar;
123 : }
124 :
125 2 : if( !rObjDesc.maTypeName.isEmpty() )
126 : {
127 2 : aParams += OUString( ";typename=\"" );
128 2 : aParams += rObjDesc.maTypeName;
129 2 : aParams += aChar;
130 : }
131 :
132 2 : 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 258 : for ( sal_Int32 nBInd = 0; nBInd < 128; nBInd++ )
138 256 : pToAccept[nBInd] = sal_False;
139 :
140 : const char aQuotedParamChars[] =
141 2 : "()<>@,;:/[]?=!#$&'*+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`abcdefghijklmnopqrstuvwxyz{|}~. ";
142 :
143 186 : for ( sal_Int32 nInd = 0; nInd < RTL_CONSTASCII_LENGTH(aQuotedParamChars); ++nInd )
144 : {
145 184 : sal_Unicode nChar = aQuotedParamChars[nInd];
146 184 : if ( nChar < 128 )
147 184 : pToAccept[nChar] = sal_True;
148 : }
149 :
150 2 : aParams += OUString( ";displayname=\"" );
151 2 : aParams += ::rtl::Uri::encode( rObjDesc.maDisplayName, pToAccept, rtl_UriEncodeIgnoreEscapes, RTL_TEXTENCODING_UTF8 );
152 2 : aParams += aChar;
153 : }
154 :
155 2 : aParams += OUString( ";viewaspect=\"" );
156 2 : aParams += OUString::number( rObjDesc.mnViewAspect );
157 2 : aParams += aChar;
158 :
159 2 : aParams += OUString( ";width=\"" );
160 2 : aParams += OUString::number( rObjDesc.maSize.Width() );
161 2 : aParams += aChar;
162 :
163 2 : aParams += OUString( ";height=\"" );
164 2 : aParams += OUString::number( rObjDesc.maSize.Height() );
165 2 : aParams += aChar;
166 :
167 2 : aParams += OUString( ";posx=\"" );
168 2 : aParams += OUString::number( rObjDesc.maDragStartPos.X() );
169 2 : aParams += aChar;
170 :
171 2 : aParams += OUString( ";posy=\"" );
172 2 : aParams += OUString::number( rObjDesc.maDragStartPos.X() );
173 2 : aParams += aChar;
174 :
175 4 : 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 90 : TransferableHelper::TerminateListener::TerminateListener( TransferableHelper& rTransferableHelper ) :
254 90 : mrParent( rTransferableHelper )
255 : {
256 90 : }
257 :
258 :
259 :
260 176 : TransferableHelper::TerminateListener::~TerminateListener()
261 : {
262 176 : }
263 :
264 :
265 :
266 2 : void SAL_CALL TransferableHelper::TerminateListener::disposing( const EventObject& ) throw( RuntimeException, std::exception )
267 : {
268 2 : }
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 432 : TransferableHelper::TransferableHelper() :
288 432 : mpFormats( new DataFlavorExVector ),
289 864 : mpObjDesc( NULL )
290 : {
291 432 : }
292 :
293 :
294 :
295 860 : TransferableHelper::~TransferableHelper()
296 : {
297 430 : delete mpObjDesc;
298 430 : delete mpFormats;
299 430 : }
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( FORMAT_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(SOT_FORMATSTR_ID_BMP, aSubstFlavor )
335 0 : && TransferableDataHelper::IsEqual( aSubstFlavor, rFlavor )
336 0 : && SotExchange::GetFormatDataFlavor(FORMAT_BITMAP, aSubstFlavor))
337 : {
338 0 : GetData(aSubstFlavor, rDestDoc);
339 0 : bDone = true;
340 : }
341 0 : else if( SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_EMF, aSubstFlavor ) &&
342 0 : TransferableDataHelper::IsEqual( aSubstFlavor, rFlavor ) &&
343 0 : SotExchange::GetFormatDataFlavor( FORMAT_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( (char*) aSeq.getConstArray(), aSeq.getLength(), STREAM_WRITE | STREAM_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, CVT_EMF ) == ERRCODE_NONE )
363 : {
364 0 : maAny <<= ( aSeq = Sequence< sal_Int8 >( reinterpret_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( SOT_FORMATSTR_ID_WMF, aSubstFlavor ) &&
372 0 : TransferableDataHelper::IsEqual( aSubstFlavor, rFlavor ) &&
373 0 : SotExchange::GetFormatDataFlavor( FORMAT_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( (char*) aSeq.getConstArray(), aSeq.getLength(), STREAM_WRITE | STREAM_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 >( reinterpret_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 2 : Sequence< DataFlavor > SAL_CALL TransferableHelper::getTransferDataFlavors() throw( RuntimeException, std::exception )
429 : {
430 2 : const SolarMutexGuard aGuard;
431 :
432 : try
433 : {
434 2 : if( !mpFormats->size() )
435 0 : AddSupportedFormats();
436 : }
437 0 : catch( const ::com::sun::star::uno::Exception& )
438 : {
439 : }
440 :
441 2 : Sequence< DataFlavor > aRet( mpFormats->size() );
442 2 : DataFlavorExVector::iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
443 2 : sal_uInt32 nCurPos = 0;
444 :
445 16 : while( aIter != aEnd )
446 : {
447 12 : aRet[ nCurPos++ ] = *aIter++;
448 : }
449 :
450 2 : 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 88 : void SAL_CALL TransferableHelper::lostOwnership( const Reference< XClipboard >&, const Reference< XTransferable >& ) throw( RuntimeException, std::exception )
484 : {
485 88 : const SolarMutexGuard aGuard;
486 :
487 : try
488 : {
489 88 : if( mxTerminateListener.is() )
490 : {
491 88 : Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
492 88 : xDesktop->removeTerminateListener( mxTerminateListener );
493 :
494 88 : mxTerminateListener.clear();
495 : }
496 :
497 88 : ObjectReleased();
498 : }
499 0 : catch( const ::com::sun::star::uno::Exception& )
500 : {
501 88 : }
502 88 : }
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 : const sal_uInt32 nRef = Application::ReleaseSolarMutex();
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 : }
585 :
586 0 : Application::AcquireSolarMutex( nRef );
587 : }
588 0 : }
589 :
590 :
591 :
592 12 : void TransferableHelper::AddFormat( SotFormatStringId nFormat )
593 : {
594 12 : DataFlavor aFlavor;
595 :
596 12 : if( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) )
597 12 : AddFormat( aFlavor );
598 12 : }
599 :
600 :
601 :
602 12 : void TransferableHelper::AddFormat( const DataFlavor& rFlavor )
603 : {
604 12 : bool bAdd = true;
605 :
606 42 : for (DataFlavorExVector::iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() ); aIter != aEnd ; ++aIter)
607 : {
608 30 : if( TransferableDataHelper::IsEqual( *aIter, rFlavor ) )
609 : {
610 : // update MimeType for SOT_FORMATSTR_ID_OBJECTDESCRIPTOR in every case
611 0 : if( ( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR == aIter->mnSotId ) && mpObjDesc )
612 : {
613 0 : DataFlavor aObjDescFlavor;
614 :
615 0 : SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDescFlavor );
616 0 : aIter->MimeType = aObjDescFlavor.MimeType;
617 0 : aIter->MimeType += ::ImplGetParameterString( *mpObjDesc );
618 :
619 : #ifdef DEBUG
620 : fprintf( stderr, "TransferableHelper exchanged objectdescriptor [ %s ]\n",
621 : OUStringToOString(aIter->MimeType, RTL_TEXTENCODING_ASCII_US).getStr() );
622 : #endif
623 : }
624 :
625 0 : bAdd = false;
626 0 : break;
627 : }
628 : }
629 :
630 12 : if( bAdd )
631 : {
632 12 : DataFlavorEx aFlavorEx;
633 24 : DataFlavor aObjDescFlavor;
634 :
635 12 : aFlavorEx.MimeType = rFlavor.MimeType;
636 12 : aFlavorEx.HumanPresentableName = rFlavor.HumanPresentableName;
637 12 : aFlavorEx.DataType = rFlavor.DataType;
638 12 : aFlavorEx.mnSotId = SotExchange::RegisterFormat( rFlavor );
639 :
640 12 : if( ( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR == aFlavorEx.mnSotId ) && mpObjDesc )
641 2 : aFlavorEx.MimeType += ::ImplGetParameterString( *mpObjDesc );
642 :
643 12 : mpFormats->push_back( aFlavorEx );
644 :
645 12 : if( FORMAT_BITMAP == aFlavorEx.mnSotId )
646 : {
647 0 : AddFormat( SOT_FORMATSTR_ID_PNG );
648 0 : AddFormat( SOT_FORMATSTR_ID_BMP );
649 : }
650 12 : else if( FORMAT_GDIMETAFILE == aFlavorEx.mnSotId )
651 : {
652 0 : AddFormat( SOT_FORMATSTR_ID_EMF );
653 0 : AddFormat( SOT_FORMATSTR_ID_WMF );
654 12 : }
655 : }
656 12 : }
657 :
658 :
659 :
660 0 : void TransferableHelper::RemoveFormat( SotFormatStringId nFormat )
661 : {
662 0 : DataFlavor aFlavor;
663 :
664 0 : if( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) )
665 0 : RemoveFormat( aFlavor );
666 0 : }
667 :
668 :
669 :
670 0 : void TransferableHelper::RemoveFormat( const DataFlavor& rFlavor )
671 : {
672 0 : DataFlavorExVector::iterator aIter( mpFormats->begin() );
673 :
674 0 : while (aIter != mpFormats->end())
675 : {
676 0 : if( TransferableDataHelper::IsEqual( *aIter, rFlavor ) )
677 0 : aIter = mpFormats->erase( aIter );
678 : else
679 0 : ++aIter;
680 : }
681 0 : }
682 :
683 :
684 :
685 74 : bool TransferableHelper::HasFormat( SotFormatStringId nFormat )
686 : {
687 74 : bool bRet = false;
688 :
689 84 : for (DataFlavorExVector::const_iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() ); aIter != aEnd ; ++aIter)
690 : {
691 10 : if( nFormat == (*aIter).mnSotId )
692 : {
693 0 : bRet = true;
694 0 : break;
695 : }
696 : }
697 :
698 74 : return bRet;
699 : }
700 :
701 :
702 :
703 0 : void TransferableHelper::ClearFormats()
704 : {
705 0 : mpFormats->clear();
706 0 : maAny.clear();
707 0 : }
708 :
709 :
710 :
711 0 : bool TransferableHelper::SetAny( const Any& rAny, const DataFlavor& )
712 : {
713 0 : maAny = rAny;
714 0 : return( maAny.hasValue() );
715 : }
716 :
717 :
718 :
719 0 : bool TransferableHelper::SetString( const OUString& rString, const DataFlavor& rFlavor )
720 : {
721 0 : DataFlavor aFileFlavor;
722 :
723 0 : if( !rString.isEmpty() &&
724 0 : SotExchange::GetFormatDataFlavor( FORMAT_FILE, aFileFlavor ) &&
725 0 : TransferableDataHelper::IsEqual( aFileFlavor, rFlavor ) )
726 : {
727 0 : const OString aByteStr(OUStringToOString(rString, osl_getThreadTextEncoding()));
728 0 : Sequence< sal_Int8 > aSeq( aByteStr.getLength() + 1 );
729 :
730 0 : memcpy( aSeq.getArray(), aByteStr.getStr(), aByteStr.getLength() );
731 0 : aSeq[ aByteStr.getLength() ] = 0;
732 0 : maAny <<= aSeq;
733 : }
734 : else
735 0 : maAny <<= rString;
736 :
737 0 : return( maAny.hasValue() );
738 : }
739 :
740 :
741 :
742 0 : bool TransferableHelper::SetBitmapEx( const BitmapEx& rBitmapEx, const DataFlavor& rFlavor )
743 : {
744 0 : if( !rBitmapEx.IsEmpty() )
745 : {
746 0 : SvMemoryStream aMemStm( 65535, 65535 );
747 :
748 0 : if(rFlavor.MimeType.equalsIgnoreAsciiCase("image/png"))
749 : {
750 : // write a PNG
751 0 : ::vcl::PNGWriter aPNGWriter(rBitmapEx);
752 :
753 0 : aPNGWriter.Write(aMemStm);
754 : }
755 : else
756 : {
757 0 : const Bitmap aBitmap(rBitmapEx.GetBitmap());
758 :
759 : // #i124085# take out DIBV5 for writing to the clipboard
760 : //if(rBitmapEx.IsTransparent())
761 : //{
762 : // const Bitmap aMask(rBitmapEx.GetAlpha().GetBitmap());
763 :
764 : // // explicitely use Bitmap::Write with bCompressed = sal_False and bFileHeader = sal_True
765 : // WriteDIBV5(aBitmap, aMask, aMemStm);
766 : //}
767 : //else
768 : //{
769 : // explicitely use Bitmap::Write with bCompressed = sal_False and bFileHeader = sal_True
770 0 : WriteDIB(aBitmap, aMemStm, false, true);
771 : //}
772 : }
773 :
774 0 : maAny <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Seek( STREAM_SEEK_TO_END ) );
775 : }
776 :
777 0 : return( maAny.hasValue() );
778 : }
779 :
780 :
781 :
782 0 : bool TransferableHelper::SetGDIMetaFile( const GDIMetaFile& rMtf, const DataFlavor& )
783 : {
784 0 : if( rMtf.GetActionSize() )
785 : {
786 0 : SvMemoryStream aMemStm( 65535, 65535 );
787 :
788 0 : ( (GDIMetaFile&) rMtf ).Write( aMemStm );
789 0 : maAny <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Seek( STREAM_SEEK_TO_END ) );
790 : }
791 :
792 0 : return( maAny.hasValue() );
793 : }
794 :
795 :
796 :
797 0 : bool TransferableHelper::SetGraphic( const Graphic& rGraphic, const DataFlavor& )
798 : {
799 0 : if( rGraphic.GetType() != GRAPHIC_NONE )
800 : {
801 0 : SvMemoryStream aMemStm( 65535, 65535 );
802 :
803 0 : aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
804 0 : aMemStm.SetCompressMode( COMPRESSMODE_NATIVE );
805 0 : WriteGraphic( aMemStm, rGraphic );
806 0 : maAny <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Seek( STREAM_SEEK_TO_END ) );
807 : }
808 :
809 0 : return( maAny.hasValue() );
810 : }
811 :
812 :
813 :
814 0 : bool TransferableHelper::SetImageMap( const ImageMap& rIMap, const ::com::sun::star::datatransfer::DataFlavor& )
815 : {
816 0 : SvMemoryStream aMemStm( 8192, 8192 );
817 :
818 0 : aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
819 0 : rIMap.Write( aMemStm, OUString() );
820 0 : maAny <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Seek( STREAM_SEEK_TO_END ) );
821 :
822 0 : return( maAny.hasValue() );
823 : }
824 :
825 :
826 :
827 0 : bool TransferableHelper::SetTransferableObjectDescriptor( const TransferableObjectDescriptor& rDesc,
828 : const ::com::sun::star::datatransfer::DataFlavor& )
829 : {
830 0 : PrepareOLE( rDesc );
831 :
832 0 : SvMemoryStream aMemStm( 1024, 1024 );
833 :
834 0 : WriteTransferableObjectDescriptor( aMemStm, rDesc );
835 0 : maAny <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Tell() );
836 :
837 0 : return( maAny.hasValue() );
838 : }
839 :
840 :
841 :
842 0 : bool TransferableHelper::SetINetBookmark( const INetBookmark& rBmk,
843 : const ::com::sun::star::datatransfer::DataFlavor& rFlavor )
844 : {
845 0 : rtl_TextEncoding eSysCSet = osl_getThreadTextEncoding();
846 :
847 0 : switch( SotExchange::GetFormat( rFlavor ) )
848 : {
849 : case( SOT_FORMATSTR_ID_SOLK ):
850 : {
851 0 : OString sURL(OUStringToOString(rBmk.GetURL(), eSysCSet));
852 0 : OString sDesc(OUStringToOString(rBmk.GetDescription(), eSysCSet));
853 0 : OStringBuffer sOut;
854 0 : sOut.append(sURL.getLength());
855 0 : sOut.append('@').append(sURL);
856 0 : sOut.append(sDesc.getLength());
857 0 : sOut.append('@').append(sDesc);
858 :
859 0 : Sequence< sal_Int8 > aSeq(sOut.getLength());
860 0 : memcpy(aSeq.getArray(), sOut.getStr(), sOut.getLength());
861 0 : maAny <<= aSeq;
862 : }
863 0 : break;
864 :
865 : case( FORMAT_STRING ):
866 0 : maAny <<= OUString( rBmk.GetURL() );
867 0 : break;
868 :
869 : case( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ):
870 : {
871 0 : OString sURL(OUStringToOString(rBmk.GetURL(), eSysCSet));
872 0 : Sequence< sal_Int8 > aSeq( sURL.getLength() );
873 0 : memcpy( aSeq.getArray(), sURL.getStr(), sURL.getLength() );
874 0 : maAny <<= aSeq;
875 : }
876 0 : break;
877 :
878 : case( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ):
879 : {
880 0 : Sequence< sal_Int8 > aSeq( 2048 );
881 :
882 0 : memset( aSeq.getArray(), 0, 2048 );
883 0 : strcpy( reinterpret_cast< char* >( aSeq.getArray() ), OUStringToOString(rBmk.GetURL(), eSysCSet).getStr() );
884 0 : strcpy( reinterpret_cast< char* >( aSeq.getArray() ) + 1024, OUStringToOString(rBmk.GetDescription(), eSysCSet).getStr() );
885 :
886 0 : maAny <<= aSeq;
887 : }
888 0 : break;
889 :
890 : #ifdef WNT
891 : case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR:
892 : {
893 : Sequence< sal_Int8 > aSeq( sizeof( FILEGROUPDESCRIPTOR ) );
894 : FILEGROUPDESCRIPTOR* pFDesc = (FILEGROUPDESCRIPTOR*) aSeq.getArray();
895 : FILEDESCRIPTOR& rFDesc1 = pFDesc->fgd[ 0 ];
896 :
897 : pFDesc->cItems = 1;
898 : memset( &rFDesc1, 0, sizeof( FILEDESCRIPTOR ) );
899 : rFDesc1.dwFlags = FD_LINKUI;
900 :
901 : OStringBuffer aStr(OUStringToOString(
902 : rBmk.GetDescription(), eSysCSet));
903 : for( sal_uInt16 nChar = 0; nChar < aStr.getLength(); ++nChar )
904 : if( strchr( "\\/:*?\"<>|", aStr[nChar] ) )
905 : aStr.remove(nChar--, 1);
906 :
907 : aStr.insert(0, "Shortcut to ");
908 : aStr.append(".URL");
909 : strcpy( rFDesc1.cFileName, aStr.getStr() );
910 :
911 : maAny <<= aSeq;
912 : }
913 : break;
914 :
915 : case SOT_FORMATSTR_ID_FILECONTENT:
916 : {
917 : OUString aStr( "[InternetShortcut]\x0aURL=" );
918 : maAny <<= ( aStr += rBmk.GetURL() );
919 : }
920 : break;
921 : #endif
922 :
923 : default:
924 0 : break;
925 : }
926 :
927 0 : return( maAny.hasValue() );
928 : }
929 :
930 :
931 :
932 0 : bool TransferableHelper::SetINetImage( const INetImage& rINtImg,
933 : const ::com::sun::star::datatransfer::DataFlavor& rFlavor )
934 : {
935 0 : SvMemoryStream aMemStm( 1024, 1024 );
936 :
937 0 : aMemStm.SetVersion( SOFFICE_FILEFORMAT_50 );
938 0 : rINtImg.Write( aMemStm, SotExchange::GetFormat( rFlavor ) );
939 :
940 0 : maAny <<= Sequence< sal_Int8 >( reinterpret_cast< const sal_Int8* >( aMemStm.GetData() ), aMemStm.Seek( STREAM_SEEK_TO_END ) );
941 :
942 0 : return( maAny.hasValue() );
943 : }
944 :
945 :
946 :
947 0 : bool TransferableHelper::SetObject( void* pUserObject, sal_uInt32 nUserObjectId, const DataFlavor& rFlavor )
948 : {
949 0 : SotStorageStreamRef xStm( new SotStorageStream( OUString() ) );
950 :
951 0 : xStm->SetVersion( SOFFICE_FILEFORMAT_50 );
952 :
953 0 : if( pUserObject && WriteObject( xStm, pUserObject, nUserObjectId, rFlavor ) )
954 : {
955 0 : const sal_uInt32 nLen = xStm->Seek( STREAM_SEEK_TO_END );
956 0 : Sequence< sal_Int8 > aSeq( nLen );
957 :
958 0 : xStm->Seek( STREAM_SEEK_TO_BEGIN );
959 0 : xStm->Read( aSeq.getArray(), nLen );
960 :
961 0 : if( nLen && ( SotExchange::GetFormat( rFlavor ) == SOT_FORMAT_STRING ) )
962 : {
963 : //JP 24.7.2001: as I know was this only for the writer application and this
964 : // writes now UTF16 format into the stream
965 : //JP 6.8.2001: and now it writes UTF8 because then exist no problem with
966 : // little / big endians! - Bug 88121
967 0 : maAny <<= OUString( reinterpret_cast< const sal_Char* >( aSeq.getConstArray() ), nLen - 1, RTL_TEXTENCODING_UTF8 );
968 : }
969 : else
970 0 : maAny <<= aSeq;
971 : }
972 :
973 0 : return( maAny.hasValue() );
974 : }
975 :
976 :
977 :
978 0 : bool TransferableHelper::WriteObject( SotStorageStreamRef&, void*, sal_uInt32, const DataFlavor& )
979 : {
980 : OSL_FAIL( "TransferableHelper::WriteObject( ... ) not implemented" );
981 0 : return false;
982 : }
983 :
984 :
985 :
986 0 : void TransferableHelper::DragFinished( sal_Int8 )
987 : {
988 0 : }
989 :
990 :
991 :
992 40 : void TransferableHelper::ObjectReleased()
993 : {
994 40 : }
995 :
996 :
997 :
998 74 : void TransferableHelper::PrepareOLE( const TransferableObjectDescriptor& rObjDesc )
999 : {
1000 74 : delete mpObjDesc;
1001 74 : mpObjDesc = new TransferableObjectDescriptor( rObjDesc );
1002 :
1003 74 : if( HasFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR ) )
1004 0 : AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
1005 74 : }
1006 :
1007 :
1008 :
1009 24 : void TransferableHelper::CopyToClipboard( vcl::Window *pWindow ) const
1010 : {
1011 : DBG_ASSERT( pWindow, "Window pointer is NULL" );
1012 24 : Reference< XClipboard > xClipboard;
1013 :
1014 24 : if( pWindow )
1015 24 : xClipboard = pWindow->GetClipboard();
1016 :
1017 24 : if( xClipboard.is() )
1018 2 : mxClipboard = xClipboard;
1019 :
1020 24 : if( mxClipboard.is() && !mxTerminateListener.is() )
1021 : {
1022 2 : const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1023 :
1024 : try
1025 : {
1026 2 : TransferableHelper* pThis = const_cast< TransferableHelper* >( this );
1027 2 : Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
1028 2 : xDesktop->addTerminateListener( pThis->mxTerminateListener = new TerminateListener( *pThis ) );
1029 :
1030 2 : mxClipboard->setContents( pThis, pThis );
1031 : }
1032 0 : catch( const ::com::sun::star::uno::Exception& )
1033 : {
1034 : }
1035 :
1036 2 : Application::AcquireSolarMutex( nRef );
1037 24 : }
1038 24 : }
1039 :
1040 :
1041 :
1042 408 : void TransferableHelper::CopyToSelection( vcl::Window *pWindow ) const
1043 : {
1044 : DBG_ASSERT( pWindow, "Window pointer is NULL" );
1045 408 : Reference< XClipboard > xSelection;
1046 :
1047 408 : if( pWindow )
1048 408 : xSelection = pWindow->GetPrimarySelection();
1049 :
1050 408 : if( xSelection.is() && !mxTerminateListener.is() )
1051 : {
1052 88 : const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1053 :
1054 : try
1055 : {
1056 88 : TransferableHelper* pThis = const_cast< TransferableHelper* >( this );
1057 88 : Reference< XDesktop2 > xDesktop = Desktop::create( ::comphelper::getProcessComponentContext() );
1058 88 : xDesktop->addTerminateListener( pThis->mxTerminateListener = new TerminateListener( *pThis ) );
1059 :
1060 88 : xSelection->setContents( pThis, pThis );
1061 : }
1062 0 : catch( const ::com::sun::star::uno::Exception& )
1063 : {
1064 : }
1065 :
1066 88 : Application::AcquireSolarMutex( nRef );
1067 408 : }
1068 408 : }
1069 :
1070 :
1071 :
1072 0 : void TransferableHelper::StartDrag( vcl::Window* pWindow, sal_Int8 nDnDSourceActions,
1073 : sal_Int32 nDnDPointer, sal_Int32 nDnDImage )
1074 :
1075 : {
1076 : DBG_ASSERT( pWindow, "Window pointer is NULL" );
1077 0 : Reference< XDragSource > xDragSource( pWindow->GetDragSource() );
1078 :
1079 0 : if( xDragSource.is() )
1080 : {
1081 : /*
1082 : * #96792# release mouse before actually starting DnD.
1083 : * This is necessary for the X11 DnD implementation to work.
1084 : */
1085 0 : if( pWindow->IsMouseCaptured() )
1086 0 : pWindow->ReleaseMouse();
1087 :
1088 0 : const Point aPt( pWindow->GetPointerPosPixel() );
1089 :
1090 : // On Mac OS X we are forced to execute 'startDrag' synchronously
1091 : // contrary to the XDragSource interface specification because
1092 : // we can receive drag events from the system only in the main
1093 : // thread
1094 : #if !defined(MACOSX)
1095 0 : const sal_uInt32 nRef = Application::ReleaseSolarMutex();
1096 : #endif
1097 :
1098 : try
1099 : {
1100 0 : DragGestureEvent aEvt;
1101 0 : aEvt.DragAction = DNDConstants::ACTION_COPY;
1102 0 : aEvt.DragOriginX = aPt.X();
1103 0 : aEvt.DragOriginY = aPt.Y();
1104 0 : aEvt.DragSource = xDragSource;
1105 :
1106 0 : xDragSource->startDrag( aEvt, nDnDSourceActions, nDnDPointer, nDnDImage, this, this );
1107 : }
1108 0 : catch( const ::com::sun::star::uno::Exception& )
1109 : {
1110 : }
1111 :
1112 : // See above for the reason of this define
1113 : #if !defined(MACOSX)
1114 0 : Application::AcquireSolarMutex( nRef );
1115 : #endif
1116 0 : }
1117 0 : }
1118 :
1119 :
1120 :
1121 82 : void TransferableHelper::ClearSelection( vcl::Window *pWindow )
1122 : {
1123 : DBG_ASSERT( pWindow, "Window pointer is NULL" );
1124 82 : Reference< XClipboard > xSelection( pWindow->GetPrimarySelection() );
1125 :
1126 82 : if( xSelection.is() )
1127 82 : xSelection->setContents( NULL, NULL );
1128 82 : }
1129 :
1130 :
1131 :
1132 0 : Reference< XClipboard> TransferableHelper::GetSystemClipboard()
1133 : {
1134 0 : vcl::Window *pFocusWindow = Application::GetFocusWindow();
1135 :
1136 0 : if( pFocusWindow )
1137 0 : return pFocusWindow->GetClipboard();
1138 :
1139 0 : return Reference< XClipboard > ();
1140 : }
1141 :
1142 : namespace
1143 : {
1144 : class theTransferableHelperUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theTransferableHelperUnoTunnelId > {};
1145 : }
1146 :
1147 0 : const Sequence< sal_Int8 >& TransferableHelper::getUnoTunnelId()
1148 : {
1149 0 : return theTransferableHelperUnoTunnelId::get().getSeq();
1150 : }
1151 :
1152 :
1153 : // - TransferableClipboardNotifier -
1154 :
1155 :
1156 28 : class TransferableClipboardNotifier : public ::cppu::WeakImplHelper1< XClipboardListener >
1157 : {
1158 : private:
1159 : ::osl::Mutex& mrMutex;
1160 : Reference< XClipboardNotifier > mxNotifier;
1161 : TransferableDataHelper* mpListener;
1162 :
1163 : protected:
1164 : // XClipboardListener
1165 : virtual void SAL_CALL changedContents( const clipboard::ClipboardEvent& event ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
1166 :
1167 : // XEventListener
1168 : virtual void SAL_CALL disposing( const EventObject& Source ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
1169 :
1170 : public:
1171 : TransferableClipboardNotifier( const Reference< XClipboard >& _rxClipboard, TransferableDataHelper& _rListener, ::osl::Mutex& _rMutex );
1172 :
1173 : /// determines whether we're currently listening
1174 18 : inline bool isListening() const { return !isDisposed(); }
1175 :
1176 : /// determines whether the instance is disposed
1177 18 : inline bool isDisposed() const { return mpListener == NULL; }
1178 :
1179 : /// makes the instance non-functional
1180 : void dispose();
1181 : };
1182 :
1183 :
1184 :
1185 18 : TransferableClipboardNotifier::TransferableClipboardNotifier( const Reference< XClipboard >& _rxClipboard, TransferableDataHelper& _rListener, ::osl::Mutex& _rMutex )
1186 : :mrMutex( _rMutex )
1187 : ,mxNotifier( _rxClipboard, UNO_QUERY )
1188 18 : ,mpListener( &_rListener )
1189 : {
1190 18 : osl_atomic_increment( &m_refCount );
1191 : {
1192 18 : if ( mxNotifier.is() )
1193 0 : mxNotifier->addClipboardListener( this );
1194 : else
1195 : // born dead
1196 18 : mpListener = NULL;
1197 : }
1198 18 : osl_atomic_decrement( &m_refCount );
1199 18 : }
1200 :
1201 :
1202 :
1203 0 : void SAL_CALL TransferableClipboardNotifier::changedContents( const clipboard::ClipboardEvent& event ) throw (RuntimeException, std::exception)
1204 : {
1205 0 : SolarMutexGuard aSolarGuard;
1206 : // the SolarMutex here is necessary, since
1207 : // - we cannot call mpListener without our own mutex locked
1208 : // - Rebind respectively InitFormats (called by Rebind) will
1209 : // try to lock the SolarMutex, too
1210 0 : ::osl::MutexGuard aGuard( mrMutex );
1211 0 : if( mpListener )
1212 0 : mpListener->Rebind( event.Contents );
1213 0 : }
1214 :
1215 :
1216 :
1217 0 : void SAL_CALL TransferableClipboardNotifier::disposing( const EventObject& ) throw (RuntimeException, std::exception)
1218 : {
1219 : // clipboard is being disposed. Hmm. Okay, become disfunctional myself.
1220 0 : dispose();
1221 0 : }
1222 :
1223 :
1224 :
1225 14 : void TransferableClipboardNotifier::dispose()
1226 : {
1227 14 : ::osl::MutexGuard aGuard( mrMutex );
1228 :
1229 28 : Reference< XClipboardListener > xKeepMeAlive( this );
1230 :
1231 14 : if ( mxNotifier.is() )
1232 0 : mxNotifier->removeClipboardListener( this );
1233 14 : mxNotifier.clear();
1234 :
1235 28 : mpListener = NULL;
1236 14 : }
1237 :
1238 :
1239 : // - TransferableDataHelper_Impl -
1240 :
1241 :
1242 2321 : struct TransferableDataHelper_Impl
1243 : {
1244 : ::osl::Mutex maMutex;
1245 : TransferableClipboardNotifier* mpClipboardListener;
1246 :
1247 2327 : TransferableDataHelper_Impl()
1248 2327 : :mpClipboardListener( NULL )
1249 : {
1250 2327 : }
1251 : };
1252 :
1253 :
1254 : // - TransferableDataHelper -
1255 :
1256 :
1257 2325 : TransferableDataHelper::TransferableDataHelper() :
1258 2325 : mpFormats( new DataFlavorExVector ),
1259 2325 : mpObjDesc( new TransferableObjectDescriptor ),
1260 6975 : mpImpl( new TransferableDataHelper_Impl )
1261 : {
1262 2325 : }
1263 :
1264 :
1265 :
1266 2 : TransferableDataHelper::TransferableDataHelper( const Reference< ::com::sun::star::datatransfer::XTransferable >& rxTransferable ) :
1267 : mxTransfer( rxTransferable ),
1268 2 : mpFormats( new DataFlavorExVector ),
1269 2 : mpObjDesc( new TransferableObjectDescriptor ),
1270 6 : mpImpl( new TransferableDataHelper_Impl )
1271 : {
1272 2 : InitFormats();
1273 2 : }
1274 :
1275 :
1276 :
1277 0 : TransferableDataHelper::TransferableDataHelper( const TransferableDataHelper& rDataHelper ) :
1278 : mxTransfer( rDataHelper.mxTransfer ),
1279 : mxClipboard( rDataHelper.mxClipboard ),
1280 0 : mpFormats( new DataFlavorExVector( *rDataHelper.mpFormats ) ),
1281 0 : mpObjDesc( new TransferableObjectDescriptor( *rDataHelper.mpObjDesc ) ),
1282 0 : mpImpl( new TransferableDataHelper_Impl )
1283 : {
1284 0 : }
1285 :
1286 :
1287 :
1288 20 : TransferableDataHelper& TransferableDataHelper::operator=( const TransferableDataHelper& rDataHelper )
1289 : {
1290 20 : if ( this != &rDataHelper )
1291 : {
1292 20 : ::osl::MutexGuard aGuard( mpImpl->maMutex );
1293 :
1294 20 : bool bWasClipboardListening = ( NULL != mpImpl->mpClipboardListener );
1295 :
1296 20 : if ( bWasClipboardListening )
1297 0 : StopClipboardListening();
1298 :
1299 20 : mxTransfer = rDataHelper.mxTransfer;
1300 20 : delete mpFormats, mpFormats = new DataFlavorExVector( *rDataHelper.mpFormats );
1301 20 : delete mpObjDesc, mpObjDesc = new TransferableObjectDescriptor( *rDataHelper.mpObjDesc );
1302 20 : mxClipboard = rDataHelper.mxClipboard;
1303 :
1304 20 : if ( bWasClipboardListening )
1305 0 : StartClipboardListening();
1306 : }
1307 :
1308 20 : return *this;
1309 : }
1310 :
1311 :
1312 :
1313 4642 : TransferableDataHelper::~TransferableDataHelper()
1314 : {
1315 2321 : StopClipboardListening( );
1316 : {
1317 2321 : ::osl::MutexGuard aGuard( mpImpl->maMutex );
1318 2321 : delete mpFormats, mpFormats = NULL;
1319 2321 : delete mpObjDesc, mpObjDesc = NULL;
1320 : }
1321 2321 : delete mpImpl;
1322 2321 : }
1323 :
1324 :
1325 :
1326 2 : void TransferableDataHelper::FillDataFlavorExVector( const Sequence< DataFlavor >& rDataFlavorSeq,
1327 : DataFlavorExVector& rDataFlavorExVector )
1328 : {
1329 : try
1330 : {
1331 2 : Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
1332 2 : Reference< XMimeContentTypeFactory > xMimeFact = MimeContentTypeFactory::create( xContext );
1333 0 : DataFlavorEx aFlavorEx;
1334 0 : const OUString aCharsetStr( "charset" );
1335 :
1336 :
1337 0 : for( sal_Int32 i = 0; i < rDataFlavorSeq.getLength(); i++ )
1338 : {
1339 0 : const DataFlavor& rFlavor = rDataFlavorSeq[ i ];
1340 0 : Reference< XMimeContentType > xMimeType;
1341 :
1342 : try
1343 : {
1344 0 : if( !rFlavor.MimeType.isEmpty() )
1345 0 : xMimeType = xMimeFact->createMimeContentType( rFlavor.MimeType );
1346 : }
1347 0 : catch( const ::com::sun::star::uno::Exception& )
1348 : {
1349 :
1350 : }
1351 :
1352 0 : aFlavorEx.MimeType = rFlavor.MimeType;
1353 0 : aFlavorEx.HumanPresentableName = rFlavor.HumanPresentableName;
1354 0 : aFlavorEx.DataType = rFlavor.DataType;
1355 0 : aFlavorEx.mnSotId = SotExchange::RegisterFormat( rFlavor );
1356 :
1357 0 : rDataFlavorExVector.push_back( aFlavorEx );
1358 :
1359 : // add additional formats for special mime types
1360 0 : if(SOT_FORMATSTR_ID_BMP == aFlavorEx.mnSotId || SOT_FORMATSTR_ID_PNG == aFlavorEx.mnSotId)
1361 : {
1362 0 : if( SotExchange::GetFormatDataFlavor( SOT_FORMAT_BITMAP, aFlavorEx ) )
1363 : {
1364 0 : aFlavorEx.mnSotId = SOT_FORMAT_BITMAP;
1365 0 : rDataFlavorExVector.push_back( aFlavorEx );
1366 : }
1367 : }
1368 0 : else if( SOT_FORMATSTR_ID_WMF == aFlavorEx.mnSotId || SOT_FORMATSTR_ID_EMF == aFlavorEx.mnSotId )
1369 : {
1370 0 : if( SotExchange::GetFormatDataFlavor( SOT_FORMAT_GDIMETAFILE, aFlavorEx ) )
1371 : {
1372 0 : aFlavorEx.mnSotId = SOT_FORMAT_GDIMETAFILE;
1373 0 : rDataFlavorExVector.push_back( aFlavorEx );
1374 : }
1375 : }
1376 0 : else if ( SOT_FORMATSTR_ID_HTML_SIMPLE == aFlavorEx.mnSotId )
1377 : {
1378 : // #104735# HTML_SIMPLE may also be inserted without comments
1379 0 : aFlavorEx.mnSotId = SOT_FORMATSTR_ID_HTML_NO_COMMENT;
1380 0 : rDataFlavorExVector.push_back( aFlavorEx );
1381 : }
1382 0 : else if( xMimeType.is() && xMimeType->getFullMediaType().equalsIgnoreAsciiCase( "text/plain" ) )
1383 : {
1384 : // add, if it is a UTF-8 byte buffer
1385 0 : if( xMimeType->hasParameter( aCharsetStr ) )
1386 : {
1387 0 : if( xMimeType->getParameterValue( aCharsetStr ).equalsIgnoreAsciiCase( "unicode" ) ||
1388 0 : xMimeType->getParameterValue( aCharsetStr ).equalsIgnoreAsciiCase( "utf-16" ) )
1389 : {
1390 0 : rDataFlavorExVector[ rDataFlavorExVector.size() - 1 ].mnSotId = FORMAT_STRING;
1391 :
1392 : }
1393 : }
1394 : }
1395 0 : else if( xMimeType.is() && xMimeType->getFullMediaType().equalsIgnoreAsciiCase( "text/rtf" ) )
1396 : {
1397 0 : rDataFlavorExVector[ rDataFlavorExVector.size() - 1 ].mnSotId = FORMAT_RTF;
1398 : }
1399 0 : else if( xMimeType.is() && xMimeType->getFullMediaType().equalsIgnoreAsciiCase( "text/html" ) )
1400 :
1401 : {
1402 0 : rDataFlavorExVector[ rDataFlavorExVector.size() - 1 ].mnSotId = SOT_FORMATSTR_ID_HTML;
1403 : }
1404 0 : else if( xMimeType.is() && xMimeType->getFullMediaType().equalsIgnoreAsciiCase( "text/uri-list" ) )
1405 : {
1406 0 : rDataFlavorExVector[ rDataFlavorExVector.size() - 1 ].mnSotId = SOT_FORMAT_FILE_LIST;
1407 : }
1408 0 : else if( xMimeType.is() && xMimeType->getFullMediaType().equalsIgnoreAsciiCase( "application/x-openoffice-objectdescriptor-xml" ) )
1409 : {
1410 0 : rDataFlavorExVector[ rDataFlavorExVector.size() - 1 ].mnSotId = SOT_FORMATSTR_ID_OBJECTDESCRIPTOR;
1411 : }
1412 2 : }
1413 : }
1414 2 : catch( const ::com::sun::star::uno::Exception& )
1415 : {
1416 : }
1417 2 : }
1418 :
1419 :
1420 :
1421 2 : void TransferableDataHelper::InitFormats()
1422 : {
1423 2 : SolarMutexGuard aSolarGuard;
1424 4 : ::osl::MutexGuard aGuard( mpImpl->maMutex );
1425 :
1426 2 : mpFormats->clear();
1427 2 : delete mpObjDesc, mpObjDesc = new TransferableObjectDescriptor;
1428 :
1429 2 : if( mxTransfer.is() )
1430 : {
1431 2 : TransferableDataHelper::FillDataFlavorExVector( mxTransfer->getTransferDataFlavors(), *mpFormats );
1432 :
1433 2 : for (DataFlavorExVector::const_iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() ); aIter != aEnd ; ++aIter)
1434 : {
1435 0 : if( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR == aIter->mnSotId )
1436 : {
1437 0 : ImplSetParameterString( *mpObjDesc, *aIter );
1438 0 : break;
1439 : }
1440 : }
1441 2 : }
1442 2 : }
1443 :
1444 :
1445 :
1446 25757 : bool TransferableDataHelper::HasFormat( SotFormatStringId nFormat ) const
1447 : {
1448 25757 : ::osl::MutexGuard aGuard( mpImpl->maMutex );
1449 :
1450 25757 : DataFlavorExVector::iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
1451 25757 : bool bRet = false;
1452 :
1453 51514 : while( aIter != aEnd )
1454 : {
1455 0 : if( nFormat == (*aIter++).mnSotId )
1456 : {
1457 0 : aIter = aEnd;
1458 0 : bRet = true;
1459 : }
1460 : }
1461 :
1462 25757 : return bRet;
1463 : }
1464 :
1465 :
1466 :
1467 0 : bool TransferableDataHelper::HasFormat( const DataFlavor& rFlavor ) const
1468 : {
1469 0 : ::osl::MutexGuard aGuard( mpImpl->maMutex );
1470 :
1471 0 : DataFlavorExVector::iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() );
1472 0 : bool bRet = false;
1473 :
1474 0 : while( aIter != aEnd )
1475 : {
1476 0 : if( TransferableDataHelper::IsEqual( rFlavor, *aIter++ ) )
1477 : {
1478 0 : aIter = aEnd;
1479 0 : bRet = true;
1480 : }
1481 : }
1482 :
1483 0 : return bRet;
1484 : }
1485 :
1486 :
1487 :
1488 111 : sal_uInt32 TransferableDataHelper::GetFormatCount() const
1489 : {
1490 111 : ::osl::MutexGuard aGuard( mpImpl->maMutex );
1491 111 : return mpFormats->size();
1492 : }
1493 :
1494 :
1495 :
1496 :
1497 0 : SotFormatStringId TransferableDataHelper::GetFormat( sal_uInt32 nFormat ) const
1498 : {
1499 0 : ::osl::MutexGuard aGuard( mpImpl->maMutex );
1500 : DBG_ASSERT( nFormat < mpFormats->size(), "TransferableDataHelper::GetFormat: invalid format index" );
1501 0 : return( ( nFormat < mpFormats->size() ) ? (*mpFormats)[ nFormat ].mnSotId : 0 );
1502 : }
1503 :
1504 :
1505 :
1506 0 : DataFlavor TransferableDataHelper::GetFormatDataFlavor( sal_uInt32 nFormat ) const
1507 : {
1508 0 : ::osl::MutexGuard aGuard( mpImpl->maMutex );
1509 : DBG_ASSERT( nFormat < mpFormats->size(), "TransferableDataHelper::GetFormat: invalid format index" );
1510 :
1511 0 : DataFlavor aRet;
1512 :
1513 0 : if( nFormat < mpFormats->size() )
1514 0 : aRet = (*mpFormats)[ nFormat ];
1515 :
1516 0 : return aRet;
1517 : }
1518 :
1519 :
1520 :
1521 714 : Reference< XTransferable > TransferableDataHelper::GetXTransferable() const
1522 : {
1523 714 : Reference< XTransferable > xRet;
1524 :
1525 714 : if( mxTransfer.is() )
1526 : {
1527 : try
1528 : {
1529 0 : xRet = mxTransfer;
1530 :
1531 : // do a dummy call to check, if this interface is valid (nasty)
1532 0 : xRet->getTransferDataFlavors();
1533 :
1534 : }
1535 0 : catch( const ::com::sun::star::uno::Exception& )
1536 : {
1537 0 : xRet.clear();
1538 : }
1539 : }
1540 :
1541 714 : return xRet;
1542 : }
1543 :
1544 :
1545 :
1546 0 : Any TransferableDataHelper::GetAny( SotFormatStringId nFormat, const OUString& rDestDoc ) const
1547 : {
1548 0 : Any aReturn;
1549 :
1550 0 : DataFlavor aFlavor;
1551 0 : if ( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) )
1552 0 : aReturn = GetAny(aFlavor, rDestDoc);
1553 :
1554 0 : return aReturn;
1555 : }
1556 :
1557 :
1558 :
1559 :
1560 0 : Any TransferableDataHelper::GetAny( const DataFlavor& rFlavor, const OUString& rDestDoc ) const
1561 : {
1562 0 : ::osl::MutexGuard aGuard( mpImpl->maMutex );
1563 0 : Any aRet;
1564 :
1565 : try
1566 : {
1567 0 : if( mxTransfer.is() )
1568 : {
1569 0 : const SotFormatStringId nRequestFormat = SotExchange::GetFormat( rFlavor );
1570 :
1571 0 : Reference<css::datatransfer::XTransferable2> xTransfer2(mxTransfer, UNO_QUERY);
1572 :
1573 0 : if( nRequestFormat )
1574 : {
1575 : // try to get alien format first
1576 0 : for (DataFlavorExVector::const_iterator aIter( mpFormats->begin() ), aEnd( mpFormats->end() ); aIter != aEnd ; ++aIter)
1577 : {
1578 0 : if( ( nRequestFormat == (*aIter).mnSotId ) && !rFlavor.MimeType.equalsIgnoreAsciiCase( (*aIter).MimeType ) )
1579 : {
1580 0 : if (xTransfer2.is())
1581 0 : aRet = xTransfer2->getTransferData2(*aIter, rDestDoc);
1582 : else
1583 0 : aRet = mxTransfer->getTransferData(*aIter);
1584 : }
1585 :
1586 0 : if( aRet.hasValue() )
1587 0 : break;
1588 : }
1589 : }
1590 :
1591 0 : if( !aRet.hasValue() )
1592 : {
1593 0 : if (xTransfer2.is())
1594 0 : aRet = xTransfer2->getTransferData2(rFlavor, rDestDoc);
1595 : else
1596 0 : aRet = mxTransfer->getTransferData(rFlavor);
1597 0 : }
1598 : }
1599 : }
1600 0 : catch( const ::com::sun::star::uno::Exception& )
1601 : {
1602 : }
1603 :
1604 0 : return aRet;
1605 : }
1606 :
1607 :
1608 :
1609 0 : bool TransferableDataHelper::GetString( SotFormatStringId nFormat, OUString& rStr )
1610 : {
1611 0 : DataFlavor aFlavor;
1612 0 : return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetString( aFlavor, rStr ) );
1613 : }
1614 :
1615 :
1616 :
1617 0 : bool TransferableDataHelper::GetString( const DataFlavor& rFlavor, OUString& rStr )
1618 : {
1619 0 : Any aAny = GetAny(rFlavor, OUString());
1620 0 : bool bRet = false;
1621 :
1622 0 : if( aAny.hasValue() )
1623 : {
1624 0 : OUString aOUString;
1625 0 : Sequence< sal_Int8 > aSeq;
1626 :
1627 0 : if( aAny >>= aOUString )
1628 : {
1629 0 : rStr = aOUString;
1630 0 : bRet = true;
1631 : }
1632 0 : else if( aAny >>= aSeq )
1633 : {
1634 :
1635 0 : const sal_Char* pChars = reinterpret_cast< const sal_Char* >( aSeq.getConstArray() );
1636 0 : sal_Int32 nLen = aSeq.getLength();
1637 :
1638 : //JP 10.10.2001: 92930 - don't copy the last zero characterinto the string.
1639 : //DVO 2002-05-27: strip _all_ trailing zeros
1640 0 : while( nLen && ( 0 == *( pChars + nLen - 1 ) ) )
1641 0 : --nLen;
1642 :
1643 0 : rStr = OUString( pChars, nLen, osl_getThreadTextEncoding() );
1644 0 : bRet = true;
1645 0 : }
1646 : }
1647 :
1648 0 : return bRet;
1649 : }
1650 :
1651 :
1652 :
1653 0 : bool TransferableDataHelper::GetBitmapEx( SotFormatStringId nFormat, BitmapEx& rBmpEx )
1654 : {
1655 0 : if(FORMAT_BITMAP == nFormat)
1656 : {
1657 : // try to get PNG first
1658 0 : DataFlavor aFlavor;
1659 :
1660 0 : if(SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_PNG, aFlavor))
1661 : {
1662 0 : if(GetBitmapEx(aFlavor, rBmpEx))
1663 : {
1664 0 : return true;
1665 : }
1666 0 : }
1667 : }
1668 :
1669 0 : DataFlavor aFlavor;
1670 0 : return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetBitmapEx( aFlavor, rBmpEx ) );
1671 : }
1672 :
1673 :
1674 :
1675 0 : bool TransferableDataHelper::GetBitmapEx( const DataFlavor& rFlavor, BitmapEx& rBmpEx )
1676 : {
1677 0 : SotStorageStreamRef xStm;
1678 0 : DataFlavor aSubstFlavor;
1679 0 : bool bRet(GetSotStorageStream(rFlavor, xStm));
1680 0 : bool bSuppressPNG(false); // #122982# If PNG stream not accessed, but BMP one, suppress trying to load PNG
1681 :
1682 0 : if(!bRet && HasFormat(SOT_FORMATSTR_ID_PNG) && SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_PNG, aSubstFlavor))
1683 : {
1684 : // when no direct success, try if PNG is available
1685 0 : bRet = GetSotStorageStream(aSubstFlavor, xStm);
1686 : }
1687 :
1688 0 : if(!bRet && HasFormat(SOT_FORMATSTR_ID_BMP) && SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_BMP, aSubstFlavor))
1689 : {
1690 : // when no direct success, try if BMP is available
1691 0 : bRet = GetSotStorageStream(aSubstFlavor, xStm);
1692 0 : bSuppressPNG = bRet;
1693 : }
1694 :
1695 0 : if(bRet)
1696 : {
1697 0 : if(!bSuppressPNG && rFlavor.MimeType.equalsIgnoreAsciiCase("image/png"))
1698 : {
1699 : // it's a PNG, import to BitmapEx
1700 0 : ::vcl::PNGReader aPNGReader(*xStm);
1701 :
1702 0 : rBmpEx = aPNGReader.Read();
1703 : }
1704 :
1705 0 : if(rBmpEx.IsEmpty())
1706 : {
1707 0 : Bitmap aBitmap;
1708 0 : Bitmap aMask;
1709 :
1710 : // explicitely use Bitmap::Read with bFileHeader = sal_True
1711 : // #i124085# keep DIBV5 for read from clipboard, but should not happen
1712 0 : ReadDIBV5(aBitmap, aMask, *xStm);
1713 :
1714 0 : if(aMask.IsEmpty())
1715 : {
1716 0 : rBmpEx = aBitmap;
1717 : }
1718 : else
1719 : {
1720 0 : rBmpEx = BitmapEx(aBitmap, aMask);
1721 0 : }
1722 : }
1723 :
1724 0 : bRet = (ERRCODE_NONE == xStm->GetError() && !rBmpEx.IsEmpty());
1725 :
1726 : /* SJ: #110748# At the moment we are having problems with DDB inserted as DIB. The
1727 : problem is, that some graphics are inserted much too big because the nXPelsPerMeter
1728 : and nYPelsPerMeter of the bitmap fileheader isn't including the correct value.
1729 : Due to this reason the following code assumes that bitmaps with a logical size
1730 : greater than 50 cm aren't having the correct mapmode set.
1731 :
1732 : The following code should be removed if DDBs and DIBs are supported via clipboard
1733 : properly.
1734 : */
1735 0 : if(bRet)
1736 : {
1737 0 : const MapMode aMapMode(rBmpEx.GetPrefMapMode());
1738 :
1739 0 : if(MAP_PIXEL != aMapMode.GetMapUnit())
1740 : {
1741 0 : const Size aSize(OutputDevice::LogicToLogic(rBmpEx.GetPrefSize(), aMapMode, MAP_100TH_MM));
1742 :
1743 : // #i122388# This wrongly corrects in the given case; changing from 5000 100th mm to
1744 : // the described 50 cm (which is 50000 100th mm)
1745 0 : if((aSize.Width() > 50000) || (aSize.Height() > 50000))
1746 : {
1747 0 : rBmpEx.SetPrefMapMode(MAP_PIXEL);
1748 :
1749 : // #i122388# also adapt size by applying the mew MapMode
1750 0 : const Size aNewSize(OutputDevice::LogicToLogic(aSize, MAP_100TH_MM, MAP_PIXEL));
1751 0 : rBmpEx.SetPrefSize(aNewSize);
1752 : }
1753 0 : }
1754 : }
1755 : }
1756 :
1757 0 : return bRet;
1758 : }
1759 :
1760 :
1761 :
1762 0 : bool TransferableDataHelper::GetGDIMetaFile(SotFormatStringId nFormat, GDIMetaFile& rMtf, size_t nMaxActions)
1763 : {
1764 0 : DataFlavor aFlavor;
1765 0 : return SotExchange::GetFormatDataFlavor(nFormat, aFlavor) &&
1766 0 : GetGDIMetaFile(aFlavor, rMtf) &&
1767 0 : (nMaxActions == 0 || rMtf.GetActionSize() < nMaxActions);
1768 : }
1769 :
1770 :
1771 :
1772 0 : bool TransferableDataHelper::GetGDIMetaFile( const DataFlavor& rFlavor, GDIMetaFile& rMtf )
1773 : {
1774 0 : SotStorageStreamRef xStm;
1775 0 : DataFlavor aSubstFlavor;
1776 0 : bool bRet = false;
1777 :
1778 0 : if( GetSotStorageStream( rFlavor, xStm ) )
1779 : {
1780 0 : ReadGDIMetaFile( *xStm, rMtf );
1781 0 : bRet = ( xStm->GetError() == ERRCODE_NONE );
1782 : }
1783 :
1784 0 : if( !bRet &&
1785 0 : HasFormat( SOT_FORMATSTR_ID_EMF ) &&
1786 0 : SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_EMF, aSubstFlavor ) &&
1787 0 : GetSotStorageStream( aSubstFlavor, xStm ) )
1788 : {
1789 0 : Graphic aGraphic;
1790 :
1791 0 : if( GraphicConverter::Import( *xStm, aGraphic ) == ERRCODE_NONE )
1792 : {
1793 0 : rMtf = aGraphic.GetGDIMetaFile();
1794 0 : bRet = true;
1795 0 : }
1796 : }
1797 :
1798 0 : if( !bRet &&
1799 0 : HasFormat( SOT_FORMATSTR_ID_WMF ) &&
1800 0 : SotExchange::GetFormatDataFlavor( SOT_FORMATSTR_ID_WMF, aSubstFlavor ) &&
1801 0 : GetSotStorageStream( aSubstFlavor, xStm ) )
1802 : {
1803 0 : Graphic aGraphic;
1804 :
1805 0 : if( GraphicConverter::Import( *xStm, aGraphic ) == ERRCODE_NONE )
1806 : {
1807 0 : rMtf = aGraphic.GetGDIMetaFile();
1808 0 : bRet = true;
1809 0 : }
1810 : }
1811 :
1812 0 : return bRet;
1813 : }
1814 :
1815 :
1816 :
1817 0 : bool TransferableDataHelper::GetGraphic( SotFormatStringId nFormat, Graphic& rGraphic )
1818 : {
1819 0 : if(FORMAT_BITMAP == nFormat)
1820 : {
1821 : // try to get PNG first
1822 0 : DataFlavor aFlavor;
1823 :
1824 0 : if(SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_PNG, aFlavor))
1825 : {
1826 0 : if(GetGraphic(aFlavor, rGraphic))
1827 : {
1828 0 : return true;
1829 : }
1830 0 : }
1831 : }
1832 :
1833 0 : DataFlavor aFlavor;
1834 0 : return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetGraphic( aFlavor, rGraphic ) );
1835 : }
1836 :
1837 :
1838 :
1839 0 : bool TransferableDataHelper::GetGraphic( const ::com::sun::star::datatransfer::DataFlavor& rFlavor, Graphic& rGraphic )
1840 : {
1841 0 : DataFlavor aFlavor;
1842 0 : bool bRet = false;
1843 :
1844 0 : if(SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_PNG, aFlavor) &&
1845 0 : TransferableDataHelper::IsEqual(aFlavor, rFlavor))
1846 : {
1847 : // try to get PNG first
1848 0 : BitmapEx aBmpEx;
1849 :
1850 0 : if( ( bRet = GetBitmapEx( aFlavor, aBmpEx ) ) )
1851 0 : rGraphic = aBmpEx;
1852 : }
1853 0 : else if(SotExchange::GetFormatDataFlavor( SOT_FORMAT_BITMAP, aFlavor ) &&
1854 0 : TransferableDataHelper::IsEqual( aFlavor, rFlavor ) )
1855 : {
1856 0 : BitmapEx aBmpEx;
1857 :
1858 0 : if( ( bRet = GetBitmapEx( aFlavor, aBmpEx ) ) )
1859 0 : rGraphic = aBmpEx;
1860 : }
1861 0 : else if( SotExchange::GetFormatDataFlavor( SOT_FORMAT_GDIMETAFILE, aFlavor ) &&
1862 0 : TransferableDataHelper::IsEqual( aFlavor, rFlavor ) )
1863 : {
1864 0 : GDIMetaFile aMtf;
1865 :
1866 0 : if( ( bRet = GetGDIMetaFile( aFlavor, aMtf ) ) )
1867 0 : rGraphic = aMtf;
1868 : }
1869 : else
1870 : {
1871 0 : SotStorageStreamRef xStm;
1872 :
1873 0 : if( GetSotStorageStream( rFlavor, xStm ) )
1874 : {
1875 0 : ReadGraphic( *xStm, rGraphic );
1876 0 : bRet = ( xStm->GetError() == ERRCODE_NONE );
1877 0 : }
1878 : }
1879 :
1880 0 : return bRet;
1881 : }
1882 :
1883 :
1884 :
1885 0 : bool TransferableDataHelper::GetImageMap( SotFormatStringId nFormat, ImageMap& rIMap )
1886 : {
1887 0 : DataFlavor aFlavor;
1888 0 : return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetImageMap( aFlavor, rIMap ) );
1889 : }
1890 :
1891 :
1892 :
1893 0 : bool TransferableDataHelper::GetImageMap( const ::com::sun::star::datatransfer::DataFlavor& rFlavor, ImageMap& rIMap )
1894 : {
1895 0 : SotStorageStreamRef xStm;
1896 0 : bool bRet = GetSotStorageStream( rFlavor, xStm );
1897 :
1898 0 : if( bRet )
1899 : {
1900 0 : rIMap.Read( *xStm, OUString() );
1901 0 : bRet = ( xStm->GetError() == ERRCODE_NONE );
1902 : }
1903 :
1904 0 : return bRet;
1905 : }
1906 :
1907 :
1908 :
1909 0 : bool TransferableDataHelper::GetTransferableObjectDescriptor( SotFormatStringId nFormat, TransferableObjectDescriptor& rDesc )
1910 : {
1911 0 : DataFlavor aFlavor;
1912 0 : return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetTransferableObjectDescriptor( aFlavor, rDesc ) );
1913 : }
1914 :
1915 :
1916 :
1917 0 : bool TransferableDataHelper::GetTransferableObjectDescriptor( const ::com::sun::star::datatransfer::DataFlavor&, TransferableObjectDescriptor& rDesc )
1918 : {
1919 0 : rDesc = *mpObjDesc;
1920 0 : return true;
1921 : }
1922 :
1923 :
1924 :
1925 0 : bool TransferableDataHelper::GetINetBookmark( SotFormatStringId nFormat, INetBookmark& rBmk )
1926 : {
1927 0 : DataFlavor aFlavor;
1928 0 : return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetINetBookmark( aFlavor, rBmk ) );
1929 : }
1930 :
1931 :
1932 :
1933 0 : bool TransferableDataHelper::GetINetBookmark( const ::com::sun::star::datatransfer::DataFlavor& rFlavor, INetBookmark& rBmk )
1934 : {
1935 0 : bool bRet = false;
1936 0 : if( HasFormat( rFlavor ))
1937 : {
1938 0 : const SotFormatStringId nFormat = SotExchange::GetFormat( rFlavor );
1939 0 : switch( nFormat )
1940 : {
1941 : case( SOT_FORMATSTR_ID_SOLK ):
1942 : case( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR ):
1943 : {
1944 0 : OUString aString;
1945 0 : if( GetString( rFlavor, aString ) )
1946 : {
1947 0 : if( SOT_FORMATSTR_ID_UNIFORMRESOURCELOCATOR == nFormat )
1948 : {
1949 0 : rBmk = INetBookmark( aString, aString );
1950 0 : bRet = true;
1951 : }
1952 : else
1953 : {
1954 0 : OUString aURL, aDesc;
1955 0 : sal_Int32 nStart = aString.indexOf( '@' ), nLen = aString.toInt32();
1956 :
1957 0 : if( !nLen && aString[ 0 ] != '0' )
1958 : {
1959 : DBG_WARNING( "SOLK: 1. len=0" );
1960 : }
1961 0 : if( nStart == -1 || nLen > aString.getLength() - nStart - 3 )
1962 : {
1963 : DBG_WARNING( "SOLK: 1. illegal start or wrong len" );
1964 : }
1965 0 : aURL = aString.copy( nStart + 1, nLen );
1966 :
1967 0 : aString = aString.replaceAt( 0, nStart + 1 + nLen, "" );
1968 0 : nStart = aString.indexOf( '@' );
1969 0 : nLen = aString.toInt32();
1970 :
1971 0 : if( !nLen && aString[ 0 ] != '0' )
1972 : {
1973 : DBG_WARNING( "SOLK: 2. len=0" );
1974 : }
1975 0 : if( nStart == -1 || nLen > aString.getLength() - nStart - 1 )
1976 : {
1977 : DBG_WARNING( "SOLK: 2. illegal start or wrong len" );
1978 : }
1979 0 : aDesc = aString.copy( nStart+1, nLen );
1980 :
1981 0 : rBmk = INetBookmark( aURL, aDesc );
1982 0 : bRet = true;
1983 : }
1984 0 : }
1985 : }
1986 0 : break;
1987 :
1988 : case( SOT_FORMATSTR_ID_NETSCAPE_BOOKMARK ):
1989 : {
1990 0 : Sequence<sal_Int8> aSeq = GetSequence(rFlavor, OUString());
1991 :
1992 0 : if (2048 == aSeq.getLength())
1993 : {
1994 0 : const sal_Char* p1 = reinterpret_cast< const sal_Char* >( aSeq.getConstArray() );
1995 0 : const sal_Char* p2 = reinterpret_cast< const sal_Char* >( aSeq.getConstArray() ) + 1024;
1996 0 : rBmk = INetBookmark( OUString( p1, strlen(p1), osl_getThreadTextEncoding() ),
1997 0 : OUString( p2, strlen(p2), osl_getThreadTextEncoding() ) );
1998 0 : bRet = true;
1999 0 : }
2000 : }
2001 0 : break;
2002 :
2003 : #ifdef WNT
2004 : case SOT_FORMATSTR_ID_FILEGRPDESCRIPTOR:
2005 : {
2006 : Sequence<sal_Int8> aSeq = GetSequence(rFlavor, OUString());
2007 :
2008 : if (aSeq.getLength())
2009 : {
2010 : FILEGROUPDESCRIPTOR* pFDesc = (FILEGROUPDESCRIPTOR*) aSeq.getConstArray();
2011 :
2012 : if( pFDesc->cItems )
2013 : {
2014 : OString aDesc( pFDesc->fgd[ 0 ].cFileName );
2015 : rtl_TextEncoding eTextEncoding = osl_getThreadTextEncoding();
2016 :
2017 : if( ( aDesc.getLength() > 4 ) && aDesc.copy(aDesc.getLength() - 4).equalsIgnoreAsciiCase(".URL") )
2018 : {
2019 : boost::scoped_ptr<SvStream> pStream(::utl::UcbStreamHelper::CreateStream( INetURLObject( OStringToOUString(aDesc, eTextEncoding) ).GetMainURL( INetURLObject::NO_DECODE ),
2020 : STREAM_STD_READ ));
2021 :
2022 : if( !pStream || pStream->GetError() )
2023 : {
2024 : DataFlavor aFileContentFlavor;
2025 :
2026 : aSeq.realloc( 0 );
2027 : pStream.reset();
2028 :
2029 : if (SotExchange::GetFormatDataFlavor(SOT_FORMATSTR_ID_FILECONTENT, aFileContentFlavor))
2030 : {
2031 : aSeq = GetSequence(aFileContentFlavor, OUString());
2032 : if (aSeq.getLength())
2033 : pStream.reset(new SvMemoryStream( (sal_Char*) aSeq.getConstArray(), aSeq.getLength(), STREAM_STD_READ ));
2034 : }
2035 : }
2036 :
2037 : if( pStream )
2038 : {
2039 : OString aLine;
2040 : bool bSttFnd = false;
2041 :
2042 : while( pStream->ReadLine( aLine ) )
2043 : {
2044 : if (aLine.equalsIgnoreAsciiCase("[InternetShortcut]"))
2045 : bSttFnd = true;
2046 : else if (bSttFnd && aLine.copy(0, 4).equalsIgnoreAsciiCase("URL="))
2047 : {
2048 : rBmk = INetBookmark( OStringToOUString(aLine.copy(4), eTextEncoding),
2049 : OStringToOUString(aDesc.copy(0, aDesc.getLength() - 4), eTextEncoding) );
2050 : bRet = true;
2051 : break;
2052 : }
2053 : }
2054 : }
2055 : }
2056 : }
2057 : }
2058 : }
2059 : break;
2060 : #endif
2061 :
2062 : }
2063 : }
2064 0 : return bRet;
2065 : }
2066 :
2067 :
2068 :
2069 0 : bool TransferableDataHelper::GetINetImage( SotFormatStringId nFormat,
2070 : INetImage& rINtImg )
2071 : {
2072 0 : DataFlavor aFlavor;
2073 0 : return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetINetImage( aFlavor, rINtImg ) );
2074 : }
2075 :
2076 :
2077 :
2078 0 : bool TransferableDataHelper::GetINetImage(
2079 : const ::com::sun::star::datatransfer::DataFlavor& rFlavor,
2080 : INetImage& rINtImg )
2081 : {
2082 0 : SotStorageStreamRef xStm;
2083 0 : bool bRet = GetSotStorageStream( rFlavor, xStm );
2084 :
2085 0 : if( bRet )
2086 0 : bRet = rINtImg.Read( *xStm, SotExchange::GetFormat( rFlavor ) );
2087 0 : return bRet;
2088 : }
2089 :
2090 :
2091 :
2092 0 : bool TransferableDataHelper::GetFileList( SotFormatStringId nFormat,
2093 : FileList& rFileList )
2094 : {
2095 0 : DataFlavor aFlavor;
2096 0 : return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetFileList( aFlavor, rFileList ) );
2097 : }
2098 :
2099 :
2100 :
2101 0 : bool TransferableDataHelper::GetFileList(
2102 : const ::com::sun::star::datatransfer::DataFlavor&,
2103 : FileList& rFileList )
2104 : {
2105 0 : SotStorageStreamRef xStm;
2106 0 : bool bRet = false;
2107 :
2108 0 : for( sal_uInt32 i = 0, nFormatCount = GetFormatCount(); ( i < nFormatCount ) && !bRet; ++i )
2109 : {
2110 0 : if( SOT_FORMAT_FILE_LIST == GetFormat( i ) )
2111 : {
2112 0 : const DataFlavor aFlavor( GetFormatDataFlavor( i ) );
2113 :
2114 0 : if( GetSotStorageStream( aFlavor, xStm ) )
2115 : {
2116 0 : if( aFlavor.MimeType.indexOf( "text/uri-list" ) > -1 )
2117 : {
2118 0 : OString aDiskString;
2119 :
2120 0 : while( xStm->ReadLine( aDiskString ) )
2121 0 : if( !aDiskString.isEmpty() && aDiskString[0] != '#' )
2122 0 : rFileList.AppendFile( OStringToOUString(aDiskString, RTL_TEXTENCODING_UTF8) );
2123 :
2124 0 : bRet = true;
2125 : }
2126 : else
2127 0 : bRet = ( ( ReadFileList( *xStm, rFileList ) ).GetError() == ERRCODE_NONE );
2128 0 : }
2129 : }
2130 : }
2131 :
2132 0 : return bRet;
2133 : }
2134 :
2135 :
2136 :
2137 0 : Sequence<sal_Int8> TransferableDataHelper::GetSequence( SotFormatStringId nFormat, const OUString& rDestDoc )
2138 : {
2139 0 : DataFlavor aFlavor;
2140 0 : if (!SotExchange::GetFormatDataFlavor(nFormat, aFlavor))
2141 0 : return Sequence<sal_Int8>();
2142 :
2143 0 : return GetSequence(aFlavor, rDestDoc);
2144 : }
2145 :
2146 0 : Sequence<sal_Int8> TransferableDataHelper::GetSequence( const DataFlavor& rFlavor, const OUString& rDestDoc )
2147 : {
2148 : #ifdef DEBUG
2149 : fprintf( stderr, "TransferableDataHelper requests sequence of data\n" );
2150 : #endif
2151 :
2152 0 : const Any aAny = GetAny(rFlavor, rDestDoc);
2153 0 : Sequence<sal_Int8> aSeq;
2154 0 : if (aAny.hasValue())
2155 0 : aAny >>= aSeq;
2156 :
2157 0 : return aSeq;
2158 : }
2159 :
2160 :
2161 :
2162 0 : bool TransferableDataHelper::GetSotStorageStream( SotFormatStringId nFormat, SotStorageStreamRef& rxStream )
2163 : {
2164 0 : DataFlavor aFlavor;
2165 0 : return( SotExchange::GetFormatDataFlavor( nFormat, aFlavor ) && GetSotStorageStream( aFlavor, rxStream ) );
2166 : }
2167 :
2168 :
2169 :
2170 0 : bool TransferableDataHelper::GetSotStorageStream( const DataFlavor& rFlavor, SotStorageStreamRef& rxStream )
2171 : {
2172 0 : Sequence<sal_Int8> aSeq = GetSequence(rFlavor, OUString());
2173 :
2174 0 : if (aSeq.getLength())
2175 : {
2176 0 : rxStream = new SotStorageStream( "" );
2177 0 : rxStream->Write( aSeq.getConstArray(), aSeq.getLength() );
2178 0 : rxStream->Seek( 0 );
2179 : }
2180 :
2181 0 : return aSeq.getLength();
2182 : }
2183 :
2184 0 : Reference<XInputStream> TransferableDataHelper::GetInputStream( SotFormatStringId nFormat, const OUString& rDestDoc )
2185 : {
2186 0 : DataFlavor aFlavor;
2187 0 : if (!SotExchange::GetFormatDataFlavor(nFormat, aFlavor))
2188 0 : return Reference<XInputStream>();
2189 :
2190 0 : return GetInputStream(aFlavor, rDestDoc);
2191 : }
2192 :
2193 0 : Reference<XInputStream> TransferableDataHelper::GetInputStream( const DataFlavor& rFlavor, const OUString& rDestDoc )
2194 : {
2195 0 : Sequence<sal_Int8> aSeq = GetSequence(rFlavor, rDestDoc);
2196 :
2197 0 : if (!aSeq.getLength())
2198 0 : return Reference<XInputStream>();
2199 :
2200 0 : Reference<XInputStream> xStream(new comphelper::SequenceInputStream(aSeq));
2201 0 : return xStream;
2202 : }
2203 :
2204 0 : void TransferableDataHelper::Rebind( const Reference< XTransferable >& _rxNewContent )
2205 : {
2206 0 : mxTransfer = _rxNewContent;
2207 0 : InitFormats();
2208 0 : }
2209 :
2210 :
2211 :
2212 18 : bool TransferableDataHelper::StartClipboardListening( )
2213 : {
2214 18 : ::osl::MutexGuard aGuard( mpImpl->maMutex );
2215 :
2216 18 : StopClipboardListening( );
2217 :
2218 18 : mpImpl->mpClipboardListener = new TransferableClipboardNotifier( mxClipboard, *this, mpImpl->maMutex );
2219 18 : mpImpl->mpClipboardListener->acquire();
2220 :
2221 18 : return mpImpl->mpClipboardListener->isListening();
2222 : }
2223 :
2224 :
2225 :
2226 2339 : void TransferableDataHelper::StopClipboardListening( )
2227 : {
2228 2339 : ::osl::MutexGuard aGuard( mpImpl->maMutex );
2229 :
2230 2339 : if ( mpImpl->mpClipboardListener )
2231 : {
2232 14 : mpImpl->mpClipboardListener->dispose();
2233 14 : mpImpl->mpClipboardListener->release();
2234 14 : mpImpl->mpClipboardListener = NULL;
2235 2339 : }
2236 2339 : }
2237 :
2238 :
2239 :
2240 2235 : TransferableDataHelper TransferableDataHelper::CreateFromSystemClipboard( vcl::Window * pWindow )
2241 : {
2242 : DBG_ASSERT( pWindow, "Window pointer is NULL" );
2243 :
2244 2235 : Reference< XClipboard > xClipboard;
2245 2235 : TransferableDataHelper aRet;
2246 :
2247 2235 : if( pWindow )
2248 2235 : xClipboard = pWindow->GetClipboard();
2249 :
2250 2235 : if( xClipboard.is() )
2251 : {
2252 : try
2253 : {
2254 2215 : Reference< XTransferable > xTransferable( xClipboard->getContents() );
2255 :
2256 2215 : if( xTransferable.is() )
2257 : {
2258 2 : aRet = TransferableDataHelper( xTransferable );
2259 : // also copy the clipboard
2260 2 : aRet.mxClipboard = xClipboard;
2261 2215 : }
2262 : }
2263 0 : catch( const ::com::sun::star::uno::Exception& )
2264 : {
2265 : }
2266 : }
2267 :
2268 2235 : return aRet;
2269 : }
2270 :
2271 :
2272 :
2273 :
2274 0 : TransferableDataHelper TransferableDataHelper::CreateFromSelection( vcl::Window* pWindow )
2275 : {
2276 : DBG_ASSERT( pWindow, "Window pointer is NULL" );
2277 :
2278 0 : Reference< XClipboard > xSelection;
2279 0 : TransferableDataHelper aRet;
2280 :
2281 0 : if( pWindow )
2282 0 : xSelection = pWindow->GetPrimarySelection();
2283 :
2284 0 : if( xSelection.is() )
2285 : {
2286 0 : const sal_uInt32 nRef = Application::ReleaseSolarMutex();
2287 :
2288 : try
2289 : {
2290 0 : Reference< XTransferable > xTransferable( xSelection->getContents() );
2291 :
2292 0 : if( xTransferable.is() )
2293 : {
2294 0 : aRet = TransferableDataHelper( xTransferable );
2295 0 : aRet.mxClipboard = xSelection;
2296 0 : }
2297 : }
2298 0 : catch( const ::com::sun::star::uno::Exception& )
2299 : {
2300 : }
2301 :
2302 0 : Application::AcquireSolarMutex( nRef );
2303 : }
2304 :
2305 0 : return aRet;
2306 : }
2307 :
2308 :
2309 30 : bool TransferableDataHelper::IsEqual( const ::com::sun::star::datatransfer::DataFlavor& rInternalFlavor,
2310 : const ::com::sun::star::datatransfer::DataFlavor& rRequestFlavor,
2311 : bool )
2312 : {
2313 30 : Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
2314 30 : bool bRet = false;
2315 :
2316 : try
2317 : {
2318 30 : Reference< XMimeContentTypeFactory > xMimeFact = MimeContentTypeFactory::create( xContext );
2319 :
2320 0 : Reference< XMimeContentType > xRequestType1( xMimeFact->createMimeContentType( rInternalFlavor.MimeType ) );
2321 0 : Reference< XMimeContentType > xRequestType2( xMimeFact->createMimeContentType( rRequestFlavor.MimeType ) );
2322 :
2323 0 : if( xRequestType1.is() && xRequestType2.is() )
2324 : {
2325 0 : if( xRequestType1->getFullMediaType().equalsIgnoreAsciiCase( xRequestType2->getFullMediaType() ) )
2326 : {
2327 0 : if( xRequestType1->getFullMediaType().equalsIgnoreAsciiCase( "text/plain" ) )
2328 : {
2329 : // special handling for text/plain media types
2330 0 : const OUString aCharsetString( "charset" );
2331 :
2332 0 : if( !xRequestType2->hasParameter( aCharsetString ) ||
2333 0 : xRequestType2->getParameterValue( aCharsetString ).equalsIgnoreAsciiCase( "utf-16" ) ||
2334 0 : xRequestType2->getParameterValue( aCharsetString ).equalsIgnoreAsciiCase( "unicode" ) )
2335 : {
2336 0 : bRet = true;
2337 0 : }
2338 : }
2339 0 : else if( xRequestType1->getFullMediaType().equalsIgnoreAsciiCase( "application/x-openoffice" ) )
2340 : {
2341 : // special handling for application/x-openoffice media types
2342 0 : const OUString aFormatString( "windows_formatname" );
2343 :
2344 0 : if( xRequestType1->hasParameter( aFormatString ) &&
2345 0 : xRequestType2->hasParameter( aFormatString ) &&
2346 0 : xRequestType1->getParameterValue( aFormatString ).equalsIgnoreAsciiCase( xRequestType2->getParameterValue( aFormatString ) ) )
2347 : {
2348 0 : bRet = true;
2349 0 : }
2350 : }
2351 : else
2352 0 : bRet = true;
2353 : }
2354 0 : }
2355 : }
2356 60 : catch( const ::com::sun::star::uno::Exception& )
2357 : {
2358 30 : bRet = rInternalFlavor.MimeType.equalsIgnoreAsciiCase( rRequestFlavor.MimeType );
2359 : }
2360 :
2361 30 : return bRet;
2362 1227 : }
2363 :
2364 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|