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