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