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