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_sw.hxx" 26 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp> 27 #include <com/sun/star/container/XChild.hpp> 28 #include <com/sun/star/embed/XEmbedPersist.hpp> 29 #include <com/sun/star/embed/XLinkageSupport.hpp> 30 #include <com/sun/star/embed/Aspects.hpp> 31 #include <com/sun/star/embed/EmbedMisc.hpp> 32 #include <com/sun/star/embed/EmbedStates.hpp> 33 #include <com/sun/star/util/XCloseable.hpp> 34 #include <com/sun/star/util/XModifiable.hpp> 35 #include <com/sun/star/document/XEventBroadcaster.hpp> 36 #include <cppuhelper/implbase1.hxx> 37 38 #include <cppuhelper/implbase2.hxx> 39 #include <toolkit/helper/vclunohelper.hxx> 40 #include <hintids.hxx> 41 #include <tools/urlobj.hxx> 42 #include <sfx2/docfile.hxx> 43 #include <sfx2/app.hxx> 44 #include <sfx2/linkmgr.hxx> 45 #include <unotools/configitem.hxx> 46 #ifndef _OUTDEV_HXX //autogen 47 #include <vcl/outdev.hxx> 48 #endif 49 #include <fmtanchr.hxx> 50 #include <frmfmt.hxx> 51 #include <doc.hxx> 52 #include <docsh.hxx> 53 #include <pam.hxx> 54 #include <section.hxx> 55 #include <cntfrm.hxx> 56 #include <frmatr.hxx> 57 #ifndef _DOCSH_HXX 58 #include <docsh.hxx> 59 #endif 60 #include <ndole.hxx> 61 62 #include <comphelper/classids.hxx> 63 #include <vcl/graph.hxx> 64 #include <sot/formats.hxx> 65 #include <unotools/ucbstreamhelper.hxx> 66 #include <svtools/filter.hxx> 67 #ifndef _COMCORE_HRC 68 #include <comcore.hrc> 69 #endif 70 71 using rtl::OUString; 72 using namespace utl; 73 using namespace com::sun::star::uno; 74 using namespace com::sun::star; 75 76 class SwOLELRUCache : private SvPtrarr, private utl::ConfigItem 77 { 78 sal_uInt16 nLRU_InitSize; 79 sal_Bool bInUnload; 80 uno::Sequence< rtl::OUString > GetPropertyNames(); 81 82 public: 83 SwOLELRUCache(); 84 85 virtual void Notify( const uno::Sequence< 86 rtl::OUString>& aPropertyNames ); 87 virtual void Commit(); 88 void Load(); 89 90 void SetInUnload( sal_Bool bFlag ) { bInUnload = bFlag; } 91 using SvPtrarr::Count; 92 93 void InsertObj( SwOLEObj& rObj ); 94 void RemoveObj( SwOLEObj& rObj ); 95 96 void RemovePtr( SwOLEObj* pObj ) 97 { 98 sal_uInt16 nPos = SvPtrarr::GetPos( pObj ); 99 if( USHRT_MAX != nPos ) 100 SvPtrarr::Remove( nPos ); 101 } 102 }; 103 104 SwOLELRUCache* pOLELRU_Cache = 0; 105 106 class SwOLEListener_Impl : public ::cppu::WeakImplHelper1< embed::XStateChangeListener > 107 { 108 SwOLEObj* mpObj; 109 public: 110 SwOLEListener_Impl( SwOLEObj* pObj ); 111 void Release(); 112 virtual void SAL_CALL changingState( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (embed::WrongStateException, uno::RuntimeException); 113 virtual void SAL_CALL stateChanged( const lang::EventObject& aEvent, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (uno::RuntimeException); 114 virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw (uno::RuntimeException); 115 }; 116 117 SwOLEListener_Impl::SwOLEListener_Impl( SwOLEObj* pObj ) 118 : mpObj( pObj ) 119 { 120 if ( mpObj->IsOleRef() && mpObj->GetOleRef()->getCurrentState() == embed::EmbedStates::RUNNING ) 121 { 122 pOLELRU_Cache->InsertObj( *mpObj ); 123 } 124 } 125 126 void SAL_CALL SwOLEListener_Impl::changingState( const lang::EventObject&, ::sal_Int32 , ::sal_Int32 ) throw (embed::WrongStateException, uno::RuntimeException) 127 { 128 } 129 130 void SAL_CALL SwOLEListener_Impl::stateChanged( const lang::EventObject&, ::sal_Int32 nOldState, ::sal_Int32 nNewState ) throw (uno::RuntimeException) 131 { 132 if ( mpObj && nOldState == embed::EmbedStates::LOADED && nNewState == embed::EmbedStates::RUNNING ) 133 { 134 if( !pOLELRU_Cache ) 135 pOLELRU_Cache = new SwOLELRUCache; 136 pOLELRU_Cache->InsertObj( *mpObj ); 137 } 138 else if ( mpObj && nNewState == embed::EmbedStates::LOADED && nOldState == embed::EmbedStates::RUNNING ) 139 { 140 if ( pOLELRU_Cache ) 141 pOLELRU_Cache->RemoveObj( *mpObj ); 142 } 143 } 144 145 void SwOLEListener_Impl::Release() 146 { 147 if ( mpObj && pOLELRU_Cache ) 148 pOLELRU_Cache->RemoveObj( *mpObj ); 149 mpObj=0; 150 release(); 151 } 152 153 void SAL_CALL SwOLEListener_Impl::disposing( const lang::EventObject& ) throw (uno::RuntimeException) 154 { 155 if ( mpObj && pOLELRU_Cache ) 156 pOLELRU_Cache->RemoveObj( *mpObj ); 157 } 158 159 // -------------------- 160 // SwEmbedObjectLink 161 // -------------------- 162 // TODO/LATER: actually SwEmbedObjectLink should be used here, but because different objects are used to control 163 // embedded object different link objects with the same functionality had to be implemented 164 165 class SwEmbedObjectLink : public sfx2::SvBaseLink 166 { 167 SwOLENode* pOleNode; 168 169 public: 170 SwEmbedObjectLink(SwOLENode* pNode); 171 virtual ~SwEmbedObjectLink(); 172 173 virtual void Closed(); 174 virtual void DataChanged( const String& rMimeType, 175 const uno::Any & rValue ); 176 177 sal_Bool Connect() { return GetRealObject() != NULL; } 178 }; 179 180 // ----------------------------------------------------------------------------- 181 182 SwEmbedObjectLink::SwEmbedObjectLink(SwOLENode* pNode): 183 ::sfx2::SvBaseLink( ::sfx2::LINKUPDATE_ONCALL, SOT_FORMATSTR_ID_SVXB ), 184 pOleNode(pNode) 185 { 186 SetSynchron( sal_False ); 187 } 188 189 // ----------------------------------------------------------------------------- 190 191 SwEmbedObjectLink::~SwEmbedObjectLink() 192 { 193 } 194 195 // ----------------------------------------------------------------------------- 196 197 void SwEmbedObjectLink::DataChanged( const String& , 198 const uno::Any & ) 199 { 200 if ( !pOleNode->UpdateLinkURL_Impl() ) 201 { 202 // the link URL was not changed 203 uno::Reference< embed::XEmbeddedObject > xObject = pOleNode->GetOLEObj().GetOleRef(); 204 OSL_ENSURE( xObject.is(), "The object must exist always!\n" ); 205 if ( xObject.is() ) 206 { 207 // let the object reload the link 208 // TODO/LATER: reload call could be used for this case 209 210 try 211 { 212 sal_Int32 nState = xObject->getCurrentState(); 213 if ( nState != embed::EmbedStates::LOADED ) 214 { 215 // in some cases the linked file probably is not locked so it could be changed 216 xObject->changeState( embed::EmbedStates::LOADED ); 217 xObject->changeState( nState ); 218 } 219 } 220 catch ( uno::Exception& ) 221 { 222 } 223 } 224 } 225 226 pOleNode->GetNewReplacement(); 227 // Initiate repainting 228 // pObj->SetChanged(); 229 } 230 231 // ----------------------------------------------------------------------------- 232 233 void SwEmbedObjectLink::Closed() 234 { 235 pOleNode->BreakFileLink_Impl(); 236 SvBaseLink::Closed(); 237 } 238 239 240 // -------------------- 241 // SwOLENode 242 // -------------------- 243 244 SwOLENode::SwOLENode( const SwNodeIndex &rWhere, 245 const svt::EmbeddedObjectRef& xObj, 246 SwGrfFmtColl *pGrfColl, 247 SwAttrSet* pAutoAttr ) : 248 SwNoTxtNode( rWhere, ND_OLENODE, pGrfColl, pAutoAttr ), 249 aOLEObj( xObj ), 250 pGraphic(0), 251 bOLESizeInvalid( sal_False ), 252 mpObjectLink( NULL ) 253 { 254 aOLEObj.SetNode( this ); 255 } 256 257 SwOLENode::SwOLENode( const SwNodeIndex &rWhere, 258 const String &rString, 259 sal_Int64 nAspect, 260 SwGrfFmtColl *pGrfColl, 261 SwAttrSet* pAutoAttr ) : 262 SwNoTxtNode( rWhere, ND_OLENODE, pGrfColl, pAutoAttr ), 263 aOLEObj( rString, nAspect ), 264 pGraphic(0), 265 bOLESizeInvalid( sal_False ), 266 mpObjectLink( NULL ) 267 { 268 aOLEObj.SetNode( this ); 269 } 270 271 SwOLENode::~SwOLENode() 272 { 273 DisconnectFileLink_Impl(); 274 delete pGraphic; 275 } 276 277 Graphic* SwOLENode::GetGraphic() 278 { 279 if ( aOLEObj.GetOleRef().is() ) 280 return aOLEObj.xOLERef.GetGraphic(); 281 return pGraphic; 282 } 283 284 Graphic* SwOLENode::GetHCGraphic() 285 { 286 return aOLEObj.xOLERef.GetHCGraphic(); 287 } 288 289 SwCntntNode *SwOLENode::SplitCntntNode( const SwPosition & ) 290 { 291 // OLE-Objecte vervielfaeltigen ?? 292 ASSERT( sal_False, "OleNode: can't split." ); 293 return this; 294 } 295 296 // Laden eines in den Undo-Bereich verschobenen OLE-Objekts 297 298 sal_Bool SwOLENode::RestorePersistentData() 299 { 300 DBG_ASSERT( aOLEObj.GetOleRef().is(), "No object to restore!" ); 301 if ( aOLEObj.xOLERef.is() ) 302 { 303 // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese 304 SfxObjectShell* p = GetDoc()->GetPersist(); 305 if( !p ) 306 { 307 // TODO/LATER: reicht hier nicht ein EmbeddedObjectContainer? Was passiert mit 308 // diesem Dokument? 309 ASSERT( !this, "warum wird hier eine DocShell angelegt?" ); 310 p = new SwDocShell( GetDoc(), SFX_CREATE_MODE_INTERNAL ); 311 p->DoInitNew( NULL ); 312 } 313 314 uno::Reference < container::XChild > xChild( aOLEObj.xOLERef.GetObject(), uno::UNO_QUERY ); 315 if ( xChild.is() ) 316 xChild->setParent( p->GetModel() ); 317 318 DBG_ASSERT( aOLEObj.aName.Len(), "No object name!" ); 319 ::rtl::OUString aObjName; 320 if ( !p->GetEmbeddedObjectContainer().InsertEmbeddedObject( aOLEObj.xOLERef.GetObject(), aObjName ) ) 321 { 322 if ( xChild.is() ) 323 xChild->setParent( 0 ); 324 DBG_ERROR( "InsertObject failed" ); 325 } 326 else 327 { 328 aOLEObj.aName = aObjName; 329 aOLEObj.xOLERef.AssignToContainer( &p->GetEmbeddedObjectContainer(), aObjName ); 330 CheckFileLink_Impl(); 331 } 332 } 333 334 return sal_True; 335 } 336 337 // OLE object is transported into UNDO area 338 sal_Bool SwOLENode::SavePersistentData() 339 { 340 if( aOLEObj.xOLERef.is() ) 341 { 342 comphelper::EmbeddedObjectContainer* pCnt = aOLEObj.xOLERef.GetContainer(); 343 344 #if OSL_DEBUG_LEVEL > 0 345 SfxObjectShell* p = GetDoc()->GetPersist(); 346 DBG_ASSERT( p, "No document!" ); 347 if( p ) 348 { 349 comphelper::EmbeddedObjectContainer& rCnt = p->GetEmbeddedObjectContainer(); 350 OSL_ENSURE( !pCnt || &rCnt == pCnt, "The helper is assigned to unexpected container!\n" ); 351 } 352 #endif 353 354 if ( pCnt && pCnt->HasEmbeddedObject( aOLEObj.aName ) ) 355 { 356 uno::Reference < container::XChild > xChild( aOLEObj.xOLERef.GetObject(), uno::UNO_QUERY ); 357 if ( xChild.is() ) 358 xChild->setParent( 0 ); 359 360 pCnt->RemoveEmbeddedObject( aOLEObj.aName, sal_False ); 361 362 // TODO/LATER: aOLEObj.aName has no meaning here, since the undo container contains the object 363 // by different name, in future it might makes sence that the name is transported here. 364 aOLEObj.xOLERef.AssignToContainer( 0, aOLEObj.aName ); 365 try 366 { 367 // "unload" object 368 aOLEObj.xOLERef->changeState( embed::EmbedStates::LOADED ); 369 } 370 catch ( uno::Exception& ) 371 { 372 } 373 } 374 } 375 376 DisconnectFileLink_Impl(); 377 378 return sal_True; 379 } 380 381 382 SwOLENode * SwNodes::MakeOLENode( const SwNodeIndex & rWhere, 383 const svt::EmbeddedObjectRef& xObj, 384 SwGrfFmtColl* pGrfColl, 385 SwAttrSet* pAutoAttr ) 386 { 387 ASSERT( pGrfColl,"SwNodes::MakeOLENode: Formatpointer ist 0." ); 388 389 SwOLENode *pNode = 390 new SwOLENode( rWhere, xObj, pGrfColl, pAutoAttr ); 391 392 // set parent if XChild is supported 393 //!! needed to supply Math objects with a valid reference device 394 uno::Reference< container::XChild > xChild( pNode->GetOLEObj().GetObject().GetObject(), UNO_QUERY ); 395 if (xChild.is()) 396 { 397 SwDocShell *pDocSh = GetDoc()->GetDocShell(); 398 if (pDocSh) 399 xChild->setParent( pDocSh->GetModel() ); 400 } 401 402 return pNode; 403 } 404 405 406 SwOLENode * SwNodes::MakeOLENode( const SwNodeIndex & rWhere, 407 const String &rName, sal_Int64 nAspect, SwGrfFmtColl* pGrfColl, SwAttrSet* pAutoAttr ) 408 { 409 ASSERT( pGrfColl,"SwNodes::MakeOLENode: Formatpointer ist 0." ); 410 411 SwOLENode *pNode = 412 new SwOLENode( rWhere, rName, nAspect, pGrfColl, pAutoAttr ); 413 414 // set parent if XChild is supported 415 //!! needed to supply Math objects with a valid reference device 416 uno::Reference< container::XChild > xChild( pNode->GetOLEObj().GetObject().GetObject(), UNO_QUERY ); 417 if (xChild.is()) 418 { 419 SwDocShell *pDocSh= GetDoc()->GetDocShell(); 420 if (pDocSh) 421 xChild->setParent( pDocSh->GetModel() ); 422 } 423 424 return pNode; 425 } 426 427 Size SwOLENode::GetTwipSize() const 428 { 429 MapMode aMapMode( MAP_TWIP ); 430 return ((SwOLENode*)this)->aOLEObj.GetObject().GetSize( &aMapMode ); 431 } 432 433 SwCntntNode* SwOLENode::MakeCopy( SwDoc* pDoc, const SwNodeIndex& rIdx ) const 434 { 435 // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese 436 SfxObjectShell* pPersistShell = pDoc->GetPersist(); 437 if( !pPersistShell ) 438 { 439 // TODO/LATER: is EmbeddedObjectContainer not enough? 440 // the created document will be closed by pDoc ( should use SfxObjectShellLock ) 441 pPersistShell = new SwDocShell( pDoc, SFX_CREATE_MODE_INTERNAL ); 442 pDoc->SetTmpDocShell( pPersistShell ); 443 pPersistShell->DoInitNew( NULL ); 444 } 445 446 // Wir hauen das Ding auf SvPersist-Ebene rein 447 // TODO/LATER: check if using the same naming scheme for all apps works here 448 ::rtl::OUString aNewName/*( Sw3Io::UniqueName( p->GetStorage(), "Obj" ) )*/; 449 SfxObjectShell* pSrc = GetDoc()->GetPersist(); 450 451 pPersistShell->GetEmbeddedObjectContainer().CopyAndGetEmbeddedObject( 452 pSrc->GetEmbeddedObjectContainer(), 453 pSrc->GetEmbeddedObjectContainer().GetEmbeddedObject( aOLEObj.aName ), 454 aNewName ); 455 456 SwOLENode* pOLENd = pDoc->GetNodes().MakeOLENode( rIdx, aNewName, GetAspect(), 457 (SwGrfFmtColl*)pDoc->GetDfltGrfFmtColl(), 458 (SwAttrSet*)GetpSwAttrSet() ); 459 460 pOLENd->SetChartTblName( GetChartTblName() ); 461 pOLENd->SetTitle( GetTitle() ); 462 pOLENd->SetDescription( GetDescription() ); 463 pOLENd->SetContour( HasContour(), HasAutomaticContour() ); 464 pOLENd->SetAspect( GetAspect() ); // the replacement image must be already copied 465 466 pOLENd->SetOLESizeInvalid( sal_True ); 467 pDoc->SetOLEPrtNotifyPending(); 468 469 return pOLENd; 470 } 471 472 sal_Bool SwOLENode::IsInGlobalDocSection() const 473 { 474 // suche den "Body Anchor" 475 sal_uLong nEndExtraIdx = GetNodes().GetEndOfExtras().GetIndex(); 476 const SwNode* pAnchorNd = this; 477 do { 478 SwFrmFmt* pFlyFmt = pAnchorNd->GetFlyFmt(); 479 if( !pFlyFmt ) 480 return sal_False; 481 482 const SwFmtAnchor& rAnchor = pFlyFmt->GetAnchor(); 483 if( !rAnchor.GetCntntAnchor() ) 484 return sal_False; 485 486 pAnchorNd = &rAnchor.GetCntntAnchor()->nNode.GetNode(); 487 } while( pAnchorNd->GetIndex() < nEndExtraIdx ); 488 489 const SwSectionNode* pSectNd = pAnchorNd->FindSectionNode(); 490 if( !pSectNd ) 491 return sal_False; 492 493 while( pSectNd ) 494 { 495 pAnchorNd = pSectNd; 496 pSectNd = pAnchorNd->StartOfSectionNode()->FindSectionNode(); 497 } 498 499 // in pAnchorNd steht der zuletzt gefundene Section Node. Der muss 500 // jetzt die Bedingung fuers GlobalDoc erfuellen. 501 pSectNd = (SwSectionNode*)pAnchorNd; 502 return FILE_LINK_SECTION == pSectNd->GetSection().GetType() && 503 pSectNd->GetIndex() > nEndExtraIdx; 504 } 505 506 sal_Bool SwOLENode::IsOLEObjectDeleted() const 507 { 508 sal_Bool bRet = sal_False; 509 if( aOLEObj.xOLERef.is() ) 510 { 511 SfxObjectShell* p = GetDoc()->GetPersist(); 512 if( p ) // muss da sein 513 { 514 return !p->GetEmbeddedObjectContainer().HasEmbeddedObject( aOLEObj.aName ); 515 //SvInfoObjectRef aRef( p->Find( aOLEObj.aName ) ); 516 //if( aRef.Is() ) 517 // bRet = aRef->IsDeleted(); 518 } 519 } 520 return bRet; 521 } 522 523 void SwOLENode::GetNewReplacement() 524 { 525 if ( aOLEObj.xOLERef.is() ) 526 aOLEObj.xOLERef.UpdateReplacement(); 527 } 528 529 sal_Bool SwOLENode::UpdateLinkURL_Impl() 530 { 531 sal_Bool bResult = sal_False; 532 533 if ( mpObjectLink ) 534 { 535 String aNewLinkURL; 536 GetDoc()->GetLinkManager().GetDisplayNames( mpObjectLink, 0, &aNewLinkURL, 0, 0 ); 537 if ( !aNewLinkURL.EqualsIgnoreCaseAscii( maLinkURL ) ) 538 { 539 if ( !aOLEObj.xOLERef.is() ) 540 aOLEObj.GetOleRef(); 541 542 uno::Reference< embed::XEmbeddedObject > xObj = aOLEObj.xOLERef.GetObject(); 543 uno::Reference< embed::XCommonEmbedPersist > xPersObj( xObj, uno::UNO_QUERY ); 544 OSL_ENSURE( xPersObj.is(), "The object must exist!\n" ); 545 if ( xPersObj.is() ) 546 { 547 try 548 { 549 sal_Int32 nCurState = xObj->getCurrentState(); 550 if ( nCurState != embed::EmbedStates::LOADED ) 551 xObj->changeState( embed::EmbedStates::LOADED ); 552 553 // TODO/LATER: there should be possible to get current mediadescriptor settings from the object 554 uno::Sequence< beans::PropertyValue > aArgs( 1 ); 555 aArgs[0].Name = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ); 556 aArgs[0].Value <<= ::rtl::OUString( aNewLinkURL ); 557 xPersObj->reload( aArgs, uno::Sequence< beans::PropertyValue >() ); 558 559 maLinkURL = aNewLinkURL; 560 bResult = sal_True; 561 562 if ( nCurState != embed::EmbedStates::LOADED ) 563 xObj->changeState( nCurState ); 564 } 565 catch( uno::Exception& ) 566 {} 567 } 568 569 if ( !bResult ) 570 { 571 // TODO/LATER: return the old name to the link manager, is it possible? 572 } 573 } 574 } 575 576 return bResult; 577 } 578 579 void SwOLENode::BreakFileLink_Impl() 580 { 581 SfxObjectShell* pPers = GetDoc()->GetPersist(); 582 583 if ( pPers ) 584 { 585 uno::Reference< embed::XStorage > xStorage = pPers->GetStorage(); 586 if ( xStorage.is() ) 587 { 588 try 589 { 590 uno::Reference< embed::XLinkageSupport > xLinkSupport( aOLEObj.GetOleRef(), uno::UNO_QUERY_THROW ); 591 xLinkSupport->breakLink( xStorage, aOLEObj.GetCurrentPersistName() ); 592 DisconnectFileLink_Impl(); 593 maLinkURL = String(); 594 } 595 catch( uno::Exception& ) 596 { 597 } 598 } 599 } 600 } 601 602 void SwOLENode::DisconnectFileLink_Impl() 603 { 604 if ( mpObjectLink ) 605 { 606 GetDoc()->GetLinkManager().Remove( mpObjectLink ); 607 mpObjectLink = NULL; 608 } 609 } 610 611 void SwOLENode::CheckFileLink_Impl() 612 { 613 if ( aOLEObj.xOLERef.GetObject().is() && !mpObjectLink ) 614 { 615 try 616 { 617 uno::Reference< embed::XLinkageSupport > xLinkSupport( aOLEObj.xOLERef.GetObject(), uno::UNO_QUERY_THROW ); 618 if ( xLinkSupport->isLink() ) 619 { 620 String aLinkURL = xLinkSupport->getLinkURL(); 621 if ( aLinkURL.Len() ) 622 { 623 // this is a file link so the model link manager should handle it 624 mpObjectLink = new SwEmbedObjectLink( this ); 625 maLinkURL = aLinkURL; 626 GetDoc()->GetLinkManager().InsertFileLink( *mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL, NULL, NULL ); 627 mpObjectLink->Connect(); 628 } 629 } 630 } 631 catch( uno::Exception& ) 632 { 633 } 634 } 635 } 636 637 // --> OD 2009-03-05 #i99665# 638 bool SwOLENode::IsChart() const 639 { 640 bool bIsChart( false ); 641 642 const uno::Reference< embed::XEmbeddedObject > xEmbObj = 643 const_cast<SwOLEObj&>(GetOLEObj()).GetOleRef(); 644 if ( xEmbObj.is() ) 645 { 646 SvGlobalName aClassID( xEmbObj->getClassID() ); 647 bIsChart = SotExchange::IsChart( aClassID ); 648 } 649 650 return bIsChart; 651 } 652 // <-- 653 654 SwOLEObj::SwOLEObj( const svt::EmbeddedObjectRef& xObj ) : 655 pOLENd( 0 ), 656 pListener( 0 ), 657 xOLERef( xObj ) 658 { 659 xOLERef.Lock( sal_True ); 660 if ( xObj.is() ) 661 { 662 pListener = new SwOLEListener_Impl( this ); 663 pListener->acquire(); 664 xObj->addStateChangeListener( pListener ); 665 } 666 } 667 668 669 SwOLEObj::SwOLEObj( const String &rString, sal_Int64 nAspect ) : 670 pOLENd( 0 ), 671 pListener( 0 ), 672 aName( rString ) 673 { 674 xOLERef.Lock( sal_True ); 675 xOLERef.SetViewAspect( nAspect ); 676 } 677 678 679 SwOLEObj::~SwOLEObj() 680 { 681 if( pListener ) 682 { 683 if ( xOLERef.is() ) 684 xOLERef->removeStateChangeListener( pListener ); 685 pListener->Release(); 686 } 687 688 if( pOLENd && !pOLENd->GetDoc()->IsInDtor() ) 689 { 690 // if the model is not currently in destruction it means that this object should be removed from the model 691 comphelper::EmbeddedObjectContainer* pCnt = xOLERef.GetContainer(); 692 693 #if OSL_DEBUG_LEVEL > 0 694 SfxObjectShell* p = pOLENd->GetDoc()->GetPersist(); 695 DBG_ASSERT( p, "No document!" ); 696 if( p ) 697 { 698 comphelper::EmbeddedObjectContainer& rCnt = p->GetEmbeddedObjectContainer(); 699 OSL_ENSURE( !pCnt || &rCnt == pCnt, "The helper is assigned to unexpected container!\n" ); 700 } 701 #endif 702 703 if ( pCnt && pCnt->HasEmbeddedObject( aName ) ) 704 { 705 uno::Reference < container::XChild > xChild( xOLERef.GetObject(), uno::UNO_QUERY ); 706 if ( xChild.is() ) 707 xChild->setParent( 0 ); 708 709 // not already removed by deleting the object 710 xOLERef.AssignToContainer( 0, aName ); 711 712 // unlock object so that object can be closed in RemoveEmbeddedObject 713 // successful closing of the object will automatically clear the reference then 714 xOLERef.Lock(sal_False); 715 716 // Always remove object from conteiner it is connected to 717 try 718 { 719 pCnt->RemoveEmbeddedObject( aName ); 720 } 721 catch ( uno::Exception& ) 722 { 723 } 724 } 725 726 } 727 728 if ( xOLERef.is() ) 729 // in case the object wasn't closed: release it 730 // in case the object was not in the container: it's still locked, try to close 731 xOLERef.Clear(); 732 } 733 734 735 void SwOLEObj::SetNode( SwOLENode* pNode ) 736 { 737 pOLENd = pNode; 738 if ( !aName.Len() ) 739 { 740 SwDoc* pDoc = pNode->GetDoc(); 741 742 // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese 743 SfxObjectShell* p = pDoc->GetPersist(); 744 if( !p ) 745 { 746 // TODO/LATER: reicht hier nicht ein EmbeddedObjectContainer? Was passiert mit 747 // diesem Dokument? 748 ASSERT( !this, "warum wird hier eine DocShell angelegt?" ); 749 p = new SwDocShell( pDoc, SFX_CREATE_MODE_INTERNAL ); 750 p->DoInitNew( NULL ); 751 } 752 753 ::rtl::OUString aObjName; 754 uno::Reference < container::XChild > xChild( xOLERef.GetObject(), uno::UNO_QUERY ); 755 if ( xChild.is() && xChild->getParent() != p->GetModel() ) 756 // it is possible that the parent was set already 757 xChild->setParent( p->GetModel() ); 758 if (!p->GetEmbeddedObjectContainer().InsertEmbeddedObject( xOLERef.GetObject(), aObjName ) ) 759 { 760 DBG_ERROR( "InsertObject failed" ); 761 if ( xChild.is() ) 762 xChild->setParent( 0 ); 763 } 764 else 765 xOLERef.AssignToContainer( &p->GetEmbeddedObjectContainer(), aObjName ); 766 767 ( (SwOLENode*)pOLENd )->CheckFileLink_Impl(); // for this notification nonconst access is required 768 769 aName = aObjName; 770 } 771 } 772 773 sal_Bool SwOLEObj::IsOleRef() const 774 { 775 return xOLERef.is(); 776 } 777 778 const uno::Reference < embed::XEmbeddedObject > SwOLEObj::GetOleRef() 779 { 780 if( !xOLERef.is() ) 781 { 782 SfxObjectShell* p = pOLENd->GetDoc()->GetPersist(); 783 ASSERT( p, "kein SvPersist vorhanden" ); 784 785 uno::Reference < embed::XEmbeddedObject > xObj = p->GetEmbeddedObjectContainer().GetEmbeddedObject( aName ); 786 ASSERT( !xOLERef.is(), "rekursiver Aufruf von GetOleRef() ist nicht erlaubt" ) 787 788 if ( !xObj.is() ) 789 { 790 //Das Teil konnte nicht geladen werden (wahrsch. Kaputt). 791 Rectangle aArea; 792 SwFrm *pFrm = pOLENd->getLayoutFrm(0); 793 if ( pFrm ) 794 { 795 Size aSz( pFrm->Frm().SSize() ); 796 const MapMode aSrc ( MAP_TWIP ); 797 const MapMode aDest( MAP_100TH_MM ); 798 aSz = OutputDevice::LogicToLogic( aSz, aSrc, aDest ); 799 aArea.SetSize( aSz ); 800 } 801 else 802 aArea.SetSize( Size( 5000, 5000 ) ); 803 // TODO/LATER: set replacement graphic for dead object 804 // It looks as if it should work even without the object, because the replace will be generated automatically 805 ::rtl::OUString aTmpName; 806 xObj = p->GetEmbeddedObjectContainer().CreateEmbeddedObject( SvGlobalName( SO3_DUMMY_CLASSID ).GetByteSequence(), aTmpName ); 807 } 808 // else 809 { 810 xOLERef.Assign( xObj, xOLERef.GetViewAspect() ); 811 xOLERef.AssignToContainer( &p->GetEmbeddedObjectContainer(), aName ); 812 pListener = new SwOLEListener_Impl( this ); 813 pListener->acquire(); 814 xObj->addStateChangeListener( pListener ); 815 } 816 817 ( (SwOLENode*)pOLENd )->CheckFileLink_Impl(); // for this notification nonconst access is required 818 } 819 else if ( xOLERef->getCurrentState() == embed::EmbedStates::RUNNING ) 820 { 821 // move object to first position in cache 822 if( !pOLELRU_Cache ) 823 pOLELRU_Cache = new SwOLELRUCache; 824 pOLELRU_Cache->InsertObj( *this ); 825 } 826 827 return xOLERef.GetObject(); 828 } 829 830 svt::EmbeddedObjectRef& SwOLEObj::GetObject() 831 { 832 GetOleRef(); 833 return xOLERef; 834 } 835 836 sal_Bool SwOLEObj::UnloadObject() 837 { 838 sal_Bool bRet = sal_True; 839 //Nicht notwendig im Doc DTor (MM) 840 //ASSERT( pOLERef && pOLERef->Is() && 1 < (*pOLERef)->GetRefCount(), 841 // "Falscher RefCount fuers Unload" ); 842 if ( pOLENd ) 843 { 844 const SwDoc* pDoc = pOLENd->GetDoc(); 845 bRet = UnloadObject( xOLERef.GetObject(), pDoc, xOLERef.GetViewAspect() ); 846 } 847 848 return bRet; 849 } 850 851 sal_Bool SwOLEObj::UnloadObject( uno::Reference< embed::XEmbeddedObject > xObj, const SwDoc* pDoc, sal_Int64 nAspect ) 852 { 853 if ( !pDoc ) 854 return sal_False; 855 856 sal_Bool bRet = sal_True; 857 sal_Int32 nState = xObj.is() ? xObj->getCurrentState() : embed::EmbedStates::LOADED; 858 sal_Bool bIsActive = ( nState != embed::EmbedStates::LOADED && nState != embed::EmbedStates::RUNNING ); 859 sal_Int64 nMiscStatus = xObj->getStatus( nAspect ); 860 861 if( nState != embed::EmbedStates::LOADED && !pDoc->IsInDtor() && !bIsActive && 862 embed::EmbedMisc::MS_EMBED_ALWAYSRUN != ( nMiscStatus & embed::EmbedMisc::MS_EMBED_ALWAYSRUN ) && 863 embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY != ( nMiscStatus & embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY ) ) 864 { 865 SfxObjectShell* p = pDoc->GetPersist(); 866 if( p ) 867 { 868 if( pDoc->get(IDocumentSettingAccess::PURGE_OLE) ) 869 { 870 try 871 { 872 uno::Reference < util::XModifiable > xMod( xObj->getComponent(), uno::UNO_QUERY ); 873 if( xMod.is() && xMod->isModified() ) 874 { 875 uno::Reference < embed::XEmbedPersist > xPers( xObj, uno::UNO_QUERY ); 876 if ( xPers.is() ) 877 xPers->storeOwn(); 878 else { 879 DBG_ERROR("Modified object without persistance in cache!"); 880 } 881 } 882 883 // setting object to loaded state will remove it from cache 884 xObj->changeState( embed::EmbedStates::LOADED ); 885 } 886 catch ( uno::Exception& ) 887 { 888 bRet = sal_False; 889 } 890 } 891 else 892 bRet = sal_False; 893 } 894 } 895 896 return bRet; 897 } 898 899 String SwOLEObj::GetDescription() 900 { 901 String aResult; 902 uno::Reference< embed::XEmbeddedObject > xEmbObj = GetOleRef(); 903 if ( xEmbObj.is() ) 904 { 905 SvGlobalName aClassID( xEmbObj->getClassID() ); 906 if ( SotExchange::IsMath( aClassID ) ) 907 aResult = SW_RES(STR_MATH_FORMULA); 908 else if ( SotExchange::IsChart( aClassID ) ) 909 aResult = SW_RES(STR_CHART); 910 else 911 aResult = SW_RES(STR_OLE); 912 } 913 914 return aResult; 915 } 916 917 918 SwOLELRUCache::SwOLELRUCache() 919 : SvPtrarr( 64, 16 ), 920 utl::ConfigItem( OUString::createFromAscii( "Office.Common/Cache" )), 921 nLRU_InitSize( 20 ), 922 bInUnload( sal_False ) 923 { 924 EnableNotification( GetPropertyNames() ); 925 Load(); 926 } 927 928 uno::Sequence< rtl::OUString > SwOLELRUCache::GetPropertyNames() 929 { 930 Sequence< OUString > aNames( 1 ); 931 OUString* pNames = aNames.getArray(); 932 pNames[0] = OUString::createFromAscii( "Writer/OLE_Objects" ); 933 return aNames; 934 } 935 936 void SwOLELRUCache::Notify( const uno::Sequence< rtl::OUString>& ) 937 { 938 Load(); 939 } 940 941 void SwOLELRUCache::Commit() 942 { 943 } 944 945 void SwOLELRUCache::Load() 946 { 947 Sequence< OUString > aNames( GetPropertyNames() ); 948 Sequence< Any > aValues = GetProperties( aNames ); 949 const Any* pValues = aValues.getConstArray(); 950 DBG_ASSERT( aValues.getLength() == aNames.getLength(), "GetProperties failed" ); 951 if( aValues.getLength() == aNames.getLength() && pValues->hasValue() ) 952 { 953 sal_Int32 nVal = 0; 954 *pValues >>= nVal; 955 //if( 20 > nVal ) 956 // nVal = 20; 957 958 { 959 if( nVal < nLRU_InitSize ) 960 { 961 // size of cache has been changed 962 sal_uInt16 nCount = SvPtrarr::Count(); 963 sal_uInt16 nPos = nCount; 964 965 // try to remove the last entries until new maximum size is reached 966 while( nCount > nVal ) 967 { 968 SwOLEObj* pObj = (SwOLEObj*) SvPtrarr::GetObject( --nPos ); 969 if ( pObj->UnloadObject() ) 970 nCount--; 971 if ( !nPos ) 972 break; 973 } 974 } 975 } 976 977 nLRU_InitSize = (sal_uInt16)nVal; 978 } 979 } 980 981 void SwOLELRUCache::InsertObj( SwOLEObj& rObj ) 982 { 983 SwOLEObj* pObj = &rObj; 984 sal_uInt16 nPos = SvPtrarr::GetPos( pObj ); 985 if( nPos ) 986 { 987 // object is currently not the first in cache 988 if( USHRT_MAX != nPos ) 989 SvPtrarr::Remove( nPos ); 990 991 SvPtrarr::Insert( pObj, 0 ); 992 993 // try to remove objects if necessary (of course not the freshly inserted one at nPos=0) 994 sal_uInt16 nCount = SvPtrarr::Count(); 995 nPos = nCount-1; 996 while( nPos && nCount > nLRU_InitSize ) 997 { 998 pObj = (SwOLEObj*) SvPtrarr::GetObject( nPos-- ); 999 if ( pObj->UnloadObject() ) 1000 nCount--; 1001 } 1002 } 1003 } 1004 1005 void SwOLELRUCache::RemoveObj( SwOLEObj& rObj ) 1006 { 1007 sal_uInt16 nPos = SvPtrarr::GetPos( &rObj ); 1008 if ( nPos != 0xFFFF ) 1009 SvPtrarr::Remove( nPos ); 1010 if( !Count() ) 1011 DELETEZ( pOLELRU_Cache ); 1012 } 1013 1014