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_svx.hxx" 30 31 #include <unotools/streamwrap.hxx> 32 #include <unotools/ucbstreamhelper.hxx> 33 #include <unotools/processfactory.hxx> 34 #include <ucbhelper/content.hxx> 35 #include <tools/resmgr.hxx> 36 #include <tools/urlobj.hxx> 37 #include <svl/solar.hrc> 38 #include <svl/urihelper.hxx> 39 #include <svtools/filter.hxx> 40 #include <svl/itempool.hxx> 41 #include <sfx2/docfile.hxx> 42 #include <avmedia/mediawindow.hxx> 43 #include <vcl/svapp.hxx> 44 45 #include "svtools/filter.hxx" 46 #include <svx/svdpage.hxx> 47 #include <svx/svdograf.hxx> 48 #include <svx/fmmodel.hxx> 49 #include <svx/fmview.hxx> 50 #include <svx/unomodel.hxx> 51 #include "codec.hxx" 52 #include "gallery.hrc" 53 #include "svx/gallery1.hxx" 54 #include "svx/galtheme.hxx" 55 #include "svx/galmisc.hxx" 56 #include <com/sun/star/sdbc/XResultSet.hpp> 57 #include <com/sun/star/ucb/XContentAccess.hpp> 58 #include <com/sun/star/ucb/TransferInfo.hpp> 59 #include <com/sun/star/ucb/NameClash.hpp> 60 61 // -------------- 62 // - Namespaces - 63 // -------------- 64 65 using namespace ::rtl; 66 using namespace ::com::sun::star; 67 68 // ---------- 69 // - ResMgr - 70 // ---------- 71 72 ResMgr* GetGalleryResMgr() 73 { 74 static ResMgr* pGalleryResMgr = NULL; 75 76 if( !pGalleryResMgr ) 77 { 78 ByteString aResMgrName( "gal" ); 79 pGalleryResMgr = ResMgr::CreateResMgr( 80 aResMgrName.GetBuffer(), Application::GetSettings().GetUILocale() ); 81 } 82 83 return pGalleryResMgr; 84 } 85 86 // ------------------------- 87 // - GalleryResGetBitmapEx - 88 // ------------------------- 89 90 BitmapEx GalleryResGetBitmapEx( sal_uInt32 nId ) 91 { 92 BitmapEx aBmpEx( GAL_RESID( nId ) ); 93 94 if( !aBmpEx.IsTransparent() ) 95 aBmpEx = BitmapEx( aBmpEx.GetBitmap(), COL_LIGHTMAGENTA ); 96 97 return aBmpEx; 98 } 99 100 // ---------------------- 101 // - SgaUserDataFactory - 102 // ---------------------- 103 104 IMPL_LINK( SgaUserDataFactory, MakeUserData, SdrObjFactory*, pObjFactory ) 105 { 106 if ( pObjFactory->nInventor == IV_IMAPINFO && pObjFactory->nIdentifier == ID_IMAPINFO ) 107 pObjFactory->pNewData = new SgaIMapInfo; 108 109 return 0L; 110 } 111 112 // ------------------------ 113 // - GalleryGraphicImport - 114 // ------------------------ 115 116 sal_uInt16 GalleryGraphicImport( const INetURLObject& rURL, Graphic& rGraphic, 117 String& rFilterName, sal_Bool bShowProgress ) 118 { 119 sal_uInt16 nRet = SGA_IMPORT_NONE; 120 SfxMedium aMedium( rURL.GetMainURL( INetURLObject::NO_DECODE ), STREAM_READ, sal_True ); 121 String aFilterName; 122 123 aMedium.DownLoad(); 124 125 SvStream* pIStm = aMedium.GetInStream(); 126 127 if( pIStm ) 128 { 129 GraphicFilter* pGraphicFilter = GraphicFilter::GetGraphicFilter(); 130 GalleryProgress* pProgress = bShowProgress ? new GalleryProgress( pGraphicFilter ) : NULL; 131 sal_uInt16 nFormat; 132 133 if( !pGraphicFilter->ImportGraphic( rGraphic, rURL.GetMainURL( INetURLObject::NO_DECODE ), *pIStm, GRFILTER_FORMAT_DONTKNOW, &nFormat ) ) 134 { 135 rFilterName = pGraphicFilter->GetImportFormatName( nFormat ); 136 nRet = SGA_IMPORT_FILE; 137 } 138 139 delete pProgress; 140 } 141 142 return nRet; 143 } 144 145 // ----------------------- 146 // - GallerySvDrawImport - 147 // ----------------------- 148 149 sal_Bool GallerySvDrawImport( SvStream& rIStm, SdrModel& rModel ) 150 { 151 sal_uInt32 nVersion; 152 sal_Bool bRet = sal_False; 153 154 if( GalleryCodec::IsCoded( rIStm, nVersion ) ) 155 { 156 SvMemoryStream aMemStm( 65535, 65535 ); 157 GalleryCodec aCodec( rIStm ); 158 159 aCodec.Read( aMemStm ); 160 aMemStm.Seek( 0UL ); 161 162 if( 1 == nVersion ) 163 { 164 DBG_ERROR( "staroffice binary file formats are no longer supported inside the gallery!" ); 165 bRet = false; 166 } 167 else if( 2 == nVersion ) 168 { 169 // recall to read as XML 170 bRet = GallerySvDrawImport( aMemStm, rModel ); 171 } 172 } 173 else 174 { 175 // read as XML 176 uno::Reference< io::XInputStream > xInputStream( new utl::OInputStreamWrapper( rIStm ) ); 177 178 rModel.GetItemPool().SetDefaultMetric( SFX_MAPUNIT_100TH_MM ); 179 uno::Reference< lang::XComponent > xComponent; 180 181 bRet = SvxDrawingLayerImport( &rModel, xInputStream, xComponent, "com.sun.star.comp.Draw.XMLOasisImporter" ); 182 if( !bRet || (rModel.GetPageCount() == 0) ) 183 { 184 rIStm.Seek(0); 185 bRet = SvxDrawingLayerImport( &rModel, xInputStream, xComponent, "com.sun.star.comp.Draw.XMLImporter" ); 186 } 187 188 } 189 190 return bRet; 191 } 192 193 // --------------------- 194 // - CreateIMapGraphic - 195 // --------------------- 196 197 sal_Bool CreateIMapGraphic( const FmFormModel& rModel, Graphic& rGraphic, ImageMap& rImageMap ) 198 { 199 sal_Bool bRet = sal_False; 200 201 if ( rModel.GetPageCount() ) 202 { 203 const SdrPage* pPage = rModel.GetPage( 0 ); 204 const SdrObject* pObj = pPage->GetObj( 0 ); 205 206 if ( pPage->GetObjCount() == 1 && pObj->ISA( SdrGrafObj ) ) 207 { 208 const sal_uInt16 nCount = pObj->GetUserDataCount(); 209 210 // gibt es in den User-Daten eine IMap-Information? 211 for ( sal_uInt16 i = 0; i < nCount; i++ ) 212 { 213 const SdrObjUserData* pUserData = pObj->GetUserData( i ); 214 215 if ( ( pUserData->GetInventor() == IV_IMAPINFO ) && ( pUserData->GetId() == ID_IMAPINFO ) ) 216 { 217 rGraphic = ( (SdrGrafObj*) pObj )->GetGraphic(); 218 rImageMap = ( (SgaIMapInfo*) pUserData )->GetImageMap(); 219 bRet = sal_True; 220 break; 221 } 222 } 223 } 224 } 225 226 return bRet; 227 } 228 229 // -------------------- 230 // - GetReducedString - 231 // -------------------- 232 233 String GetReducedString( const INetURLObject& rURL, sal_uIntPtr nMaxLen ) 234 { 235 String aReduced( rURL.GetMainURL( INetURLObject::DECODE_UNAMBIGUOUS ) ); 236 237 aReduced = aReduced.GetToken( aReduced.GetTokenCount( '/' ) - 1, '/' ); 238 239 if( INET_PROT_PRIV_SOFFICE != rURL.GetProtocol() ) 240 { 241 sal_Unicode aDelimiter; 242 const String aPath( rURL.getFSysPath( INetURLObject::FSYS_DETECT, &aDelimiter ) ); 243 const String aName( aReduced ); 244 245 if( aPath.Len() > nMaxLen ) 246 { 247 aReduced = aPath.Copy( 0, (sal_uInt16)( nMaxLen - aName.Len() - 4 ) ); 248 aReduced += String( RTL_CONSTASCII_USTRINGPARAM( "..." ) ); 249 aReduced += aDelimiter; 250 aReduced += aName; 251 } 252 else 253 aReduced = aPath; 254 } 255 256 return aReduced; 257 } 258 259 // ----------------------------------------------------------------------------- 260 261 String GetSvDrawStreamNameFromURL( const INetURLObject& rSvDrawObjURL ) 262 { 263 String aRet; 264 265 if( rSvDrawObjURL.GetProtocol() == INET_PROT_PRIV_SOFFICE && 266 String(rSvDrawObjURL.GetMainURL( INetURLObject::NO_DECODE )).GetTokenCount( '/' ) == 3 ) 267 { 268 aRet = String(rSvDrawObjURL.GetMainURL( INetURLObject::NO_DECODE )).GetToken( 2, '/' ); 269 } 270 271 return aRet; 272 } 273 274 // ----------------------------------------------------------------------------- 275 276 sal_Bool FileExists( const INetURLObject& rURL ) 277 { 278 sal_Bool bRet = sal_False; 279 280 if( rURL.GetProtocol() != INET_PROT_NOT_VALID ) 281 { 282 try 283 { 284 ::ucbhelper::Content aCnt( rURL.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ucb::XCommandEnvironment >() ); 285 OUString aTitle; 286 287 aCnt.getPropertyValue( OUString::createFromAscii( "Title" ) ) >>= aTitle; 288 bRet = ( aTitle.getLength() > 0 ); 289 } 290 catch( const ucb::ContentCreationException& ) 291 { 292 } 293 catch( const uno::RuntimeException& ) 294 { 295 } 296 catch( const uno::Exception& ) 297 { 298 } 299 } 300 301 return bRet; 302 } 303 304 // ----------------------------------------------------------------------------- 305 306 sal_Bool CreateDir( const INetURLObject& rURL ) 307 { 308 sal_Bool bRet = FileExists( rURL ); 309 310 if( !bRet ) 311 { 312 try 313 { 314 uno::Reference< ucb::XCommandEnvironment > aCmdEnv; 315 INetURLObject aNewFolderURL( rURL ); 316 INetURLObject aParentURL( aNewFolderURL ); aParentURL.removeSegment(); 317 ::ucbhelper::Content aParent( aParentURL.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv ); 318 uno::Sequence< OUString > aProps( 1 ); 319 uno::Sequence< uno::Any > aValues( 1 ); 320 321 aProps.getArray()[ 0 ] = OUString::createFromAscii( "Title" ); 322 aValues.getArray()[ 0 ] = uno::makeAny( OUString( aNewFolderURL.GetName() ) ); 323 324 ::ucbhelper::Content aContent( aNewFolderURL.GetMainURL( INetURLObject::NO_DECODE ), aCmdEnv ); 325 bRet = aParent.insertNewContent( OUString::createFromAscii( "application/vnd.sun.staroffice.fsys-folder" ), aProps, aValues, aContent ); 326 } 327 catch( const ucb::ContentCreationException& ) 328 { 329 } 330 catch( const uno::RuntimeException& ) 331 { 332 } 333 catch( const uno::Exception& ) 334 { 335 } 336 } 337 338 return bRet; 339 } 340 341 // ----------------------------------------------------------------------------- 342 343 sal_Bool CopyFile( const INetURLObject& rSrcURL, const INetURLObject& rDstURL ) 344 { 345 sal_Bool bRet = sal_False; 346 347 try 348 { 349 ::ucbhelper::Content aDestPath( rDstURL.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ucb::XCommandEnvironment >() ); 350 351 aDestPath.executeCommand( OUString::createFromAscii( "transfer" ), 352 uno::makeAny( ucb::TransferInfo( sal_False, rSrcURL.GetMainURL( INetURLObject::NO_DECODE ), 353 rDstURL.GetName(), ucb::NameClash::OVERWRITE ) ) ); 354 bRet = sal_True; 355 } 356 catch( const ucb::ContentCreationException& ) 357 { 358 } 359 catch( const uno::RuntimeException& ) 360 { 361 } 362 catch( const uno::Exception& ) 363 { 364 } 365 366 return bRet; 367 } 368 369 // ----------------------------------------------------------------------------- 370 371 sal_Bool KillFile( const INetURLObject& rURL ) 372 { 373 sal_Bool bRet = FileExists( rURL ); 374 375 if( bRet ) 376 { 377 try 378 { 379 ::ucbhelper::Content aCnt( rURL.GetMainURL( INetURLObject::NO_DECODE ), uno::Reference< ucb::XCommandEnvironment >() ); 380 aCnt.executeCommand( OUString::createFromAscii( "delete" ), uno::makeAny( sal_Bool( sal_True ) ) ); 381 } 382 catch( const ucb::ContentCreationException& ) 383 { 384 bRet = sal_False; 385 } 386 catch( const uno::RuntimeException& ) 387 { 388 bRet = sal_False; 389 } 390 catch( const uno::Exception& ) 391 { 392 bRet = sal_False; 393 } 394 } 395 396 return bRet; 397 } 398 399 // ------------------- 400 // - GalleryProgress - 401 // ------------------- 402 DBG_NAME(GalleryProgress) 403 404 GalleryProgress::GalleryProgress( GraphicFilter* pFilter ) : 405 mpFilter( pFilter ) 406 { 407 DBG_CTOR(GalleryProgress,NULL); 408 409 uno::Reference< lang::XMultiServiceFactory > xMgr( ::utl::getProcessServiceFactory() ); 410 411 if( xMgr.is() ) 412 { 413 uno::Reference< awt::XProgressMonitor > xMonitor( xMgr->createInstance( 414 ::rtl::OUString::createFromAscii( "com.sun.star.awt.XProgressMonitor" ) ), 415 uno::UNO_QUERY ); 416 417 if ( xMonitor.is() ) 418 { 419 mxProgressBar = uno::Reference< awt::XProgressBar >( xMonitor, uno::UNO_QUERY ); 420 421 if( mxProgressBar.is() ) 422 { 423 String aProgressText; 424 425 if( mpFilter ) 426 { 427 aProgressText = String( GAL_RESID( RID_SVXSTR_GALLERY_FILTER ) ); 428 // mpFilter->SetUpdatePercentHdl( LINK( this, GalleryProgress, Update ) ); // sj: progress wasn't working up from SO7 at all 429 // // so I am removing this. The gallery progress should 430 // // be changed to use the XStatusIndicator instead of XProgressMonitor 431 } 432 else 433 aProgressText = String( RTL_CONSTASCII_USTRINGPARAM( "Gallery" ) ); 434 435 xMonitor->addText( String( RTL_CONSTASCII_USTRINGPARAM( "Gallery" ) ), aProgressText, sal_False ) ; 436 mxProgressBar->setRange( 0, GALLERY_PROGRESS_RANGE ); 437 } 438 } 439 } 440 } 441 442 // ------------------------------------------------------------------------ 443 444 GalleryProgress::~GalleryProgress() 445 { 446 // if( mpFilter ) 447 // mpFilter->SetUpdatePercentHdl( Link() ); 448 449 DBG_DTOR(GalleryProgress,NULL); 450 } 451 452 // ------------------------------------------------------------------------ 453 454 void GalleryProgress::Update( sal_uIntPtr nVal, sal_uIntPtr nMaxVal ) 455 { 456 if( mxProgressBar.is() && nMaxVal ) 457 mxProgressBar->setValue( Min( (sal_uIntPtr)( (double) nVal / nMaxVal * GALLERY_PROGRESS_RANGE ), (sal_uIntPtr) GALLERY_PROGRESS_RANGE ) ); 458 } 459 460 // ----------------------- 461 // - GalleryTransferable - 462 // ----------------------- 463 DBG_NAME(GalleryTransferable) 464 465 GalleryTransferable::GalleryTransferable( GalleryTheme* pTheme, sal_uIntPtr nObjectPos, bool bLazy ) : 466 mpTheme( pTheme ), 467 meObjectKind( mpTheme->GetObjectKind( nObjectPos ) ), 468 mnObjectPos( nObjectPos ), 469 mpGraphicObject( NULL ), 470 mpImageMap( NULL ), 471 mpURL( NULL ) 472 { 473 DBG_CTOR(GalleryTransferable,NULL); 474 475 InitData( bLazy ); 476 } 477 478 // ------------------------------------------------------------------------ 479 480 GalleryTransferable::~GalleryTransferable() 481 { 482 483 DBG_DTOR(GalleryTransferable,NULL); 484 } 485 486 // ------------------------------------------------------------------------ 487 488 void GalleryTransferable::InitData( bool bLazy ) 489 { 490 switch( meObjectKind ) 491 { 492 case( SGA_OBJ_SVDRAW ): 493 { 494 if( !bLazy ) 495 { 496 if( !mpGraphicObject ) 497 { 498 Graphic aGraphic; 499 500 if( mpTheme->GetGraphic( mnObjectPos, aGraphic ) ) 501 mpGraphicObject = new GraphicObject( aGraphic ); 502 } 503 504 if( !mxModelStream.Is() ) 505 { 506 mxModelStream = new SotStorageStream( String() ); 507 mxModelStream->SetBufferSize( 16348 ); 508 509 if( !mpTheme->GetModelStream( mnObjectPos, mxModelStream ) ) 510 mxModelStream.Clear(); 511 else 512 mxModelStream->Seek( 0 ); 513 } 514 } 515 } 516 break; 517 518 case( SGA_OBJ_ANIM ): 519 case( SGA_OBJ_BMP ): 520 case( SGA_OBJ_INET ): 521 case( SGA_OBJ_SOUND ): 522 { 523 if( !mpURL ) 524 { 525 mpURL = new INetURLObject; 526 527 if( !mpTheme->GetURL( mnObjectPos, *mpURL ) ) 528 delete mpURL, mpURL = NULL; 529 } 530 531 if( ( SGA_OBJ_SOUND != meObjectKind ) && !mpGraphicObject ) 532 { 533 Graphic aGraphic; 534 535 if( mpTheme->GetGraphic( mnObjectPos, aGraphic ) ) 536 mpGraphicObject = new GraphicObject( aGraphic ); 537 } 538 } 539 break; 540 541 default: 542 DBG_ERROR( "GalleryTransferable::GalleryTransferable: invalid object type" ); 543 break; 544 } 545 } 546 547 // ------------------------------------------------------------------------ 548 549 void GalleryTransferable::AddSupportedFormats() 550 { 551 if( SGA_OBJ_SVDRAW == meObjectKind ) 552 { 553 AddFormat( SOT_FORMATSTR_ID_DRAWING ); 554 AddFormat( SOT_FORMATSTR_ID_SVXB ); 555 AddFormat( FORMAT_GDIMETAFILE ); 556 AddFormat( FORMAT_BITMAP ); 557 } 558 else 559 { 560 if( mpURL ) 561 AddFormat( FORMAT_FILE ); 562 563 if( mpGraphicObject ) 564 { 565 AddFormat( SOT_FORMATSTR_ID_SVXB ); 566 567 if( mpGraphicObject->GetType() == GRAPHIC_GDIMETAFILE ) 568 { 569 AddFormat( FORMAT_GDIMETAFILE ); 570 AddFormat( FORMAT_BITMAP ); 571 } 572 else 573 { 574 AddFormat( FORMAT_BITMAP ); 575 AddFormat( FORMAT_GDIMETAFILE ); 576 } 577 } 578 } 579 } 580 581 // ------------------------------------------------------------------------ 582 583 sal_Bool GalleryTransferable::GetData( const datatransfer::DataFlavor& rFlavor ) 584 { 585 sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor ); 586 sal_Bool bRet = sal_False; 587 588 InitData( false ); 589 590 if( ( SOT_FORMATSTR_ID_DRAWING == nFormat ) && ( SGA_OBJ_SVDRAW == meObjectKind ) ) 591 { 592 bRet = ( mxModelStream.Is() && SetObject( &mxModelStream, 0, rFlavor ) ); 593 } 594 else if( ( SOT_FORMATSTR_ID_SVIM == nFormat ) && mpImageMap ) 595 { 596 // TODO/MBA: do we need a BaseURL here?! 597 bRet = SetImageMap( *mpImageMap, rFlavor ); 598 } 599 else if( ( FORMAT_FILE == nFormat ) && mpURL ) 600 { 601 bRet = SetString( mpURL->GetMainURL( INetURLObject::NO_DECODE ), rFlavor ); 602 } 603 else if( ( SOT_FORMATSTR_ID_SVXB == nFormat ) && mpGraphicObject ) 604 { 605 bRet = SetGraphic( mpGraphicObject->GetGraphic(), rFlavor ); 606 } 607 else if( ( FORMAT_GDIMETAFILE == nFormat ) && mpGraphicObject ) 608 { 609 bRet = SetGDIMetaFile( mpGraphicObject->GetGraphic().GetGDIMetaFile(), rFlavor ); 610 } 611 else if( ( FORMAT_BITMAP == nFormat ) && mpGraphicObject ) 612 { 613 bRet = SetBitmap( mpGraphicObject->GetGraphic().GetBitmap(), rFlavor ); 614 } 615 616 return bRet; 617 } 618 619 // ------------------------------------------------------------------------ 620 621 sal_Bool GalleryTransferable::WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, 622 sal_uInt32, const datatransfer::DataFlavor& ) 623 { 624 sal_Bool bRet = sal_False; 625 626 if( pUserObject ) 627 { 628 *rxOStm << *static_cast< SotStorageStream* >( pUserObject ); 629 bRet = ( rxOStm->GetError() == ERRCODE_NONE ); 630 } 631 632 return bRet; 633 } 634 635 // ------------------------------------------------------------------------ 636 637 void GalleryTransferable::DragFinished( sal_Int8 nDropAction ) 638 { 639 mpTheme->SetDragging( sal_False ); 640 mpTheme->SetDragPos( 0 ); 641 if ( nDropAction ) 642 { 643 Window *pFocusWindow = Application::GetFocusWindow(); 644 if ( pFocusWindow ) 645 pFocusWindow->GrabFocusToDocument(); 646 } 647 } 648 649 // ------------------------------------------------------------------------ 650 651 void GalleryTransferable::ObjectReleased() 652 { 653 mxModelStream.Clear(); 654 delete mpGraphicObject, mpGraphicObject = NULL; 655 delete mpImageMap, mpImageMap = NULL; 656 delete mpURL, mpURL = NULL; 657 } 658 659 // ------------------------------------------------------------------------ 660 661 void GalleryTransferable::CopyToClipboard( Window* pWindow ) 662 { 663 TransferableHelper::CopyToClipboard( pWindow ); 664 } 665 666 // ------------------------------------------------------------------------ 667 668 void GalleryTransferable::StartDrag( Window* pWindow, sal_Int8 nDragSourceActions, 669 sal_Int32 nDragPointer, sal_Int32 nDragImage ) 670 { 671 INetURLObject aURL; 672 673 if( mpTheme->GetURL( mnObjectPos, aURL ) && ( aURL.GetProtocol() != INET_PROT_NOT_VALID ) ) 674 { 675 mpTheme->SetDragging( sal_True ); 676 mpTheme->SetDragPos( mnObjectPos ); 677 TransferableHelper::StartDrag( pWindow, nDragSourceActions, nDragPointer, nDragImage ); 678 } 679 } 680