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