1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ndole.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
34 #include <com/sun/star/container/XChild.hpp>
35 #include <com/sun/star/embed/XEmbedPersist.hpp>
36 #include <com/sun/star/embed/XLinkageSupport.hpp>
37 #include <com/sun/star/embed/Aspects.hpp>
38 #include <com/sun/star/embed/EmbedMisc.hpp>
39 #include <com/sun/star/embed/EmbedStates.hpp>
40 #include <com/sun/star/util/XCloseable.hpp>
41 #include <com/sun/star/util/XModifiable.hpp>
42 #include <com/sun/star/document/XEventBroadcaster.hpp>
43 #include <cppuhelper/implbase1.hxx>
45 #include <cppuhelper/implbase2.hxx>
46 #include <toolkit/helper/vclunohelper.hxx>
47 #include <hintids.hxx>
48 #include <tools/urlobj.hxx>
49 #include <sfx2/docfile.hxx>
50 #include <sfx2/app.hxx>
51 #include <svx/linkmgr.hxx>
52 #include <unotools/configitem.hxx>
53 #ifndef _OUTDEV_HXX //autogen
54 #include <vcl/outdev.hxx>
56 #include <fmtanchr.hxx>
61 #include <section.hxx>
69 #include <comphelper/classids.hxx>
70 #include <vcl/graph.hxx>
71 #include <sot/formats.hxx>
72 #include <unotools/ucbstreamhelper.hxx>
73 #include <svtools/filter.hxx>
75 #include <comcore.hrc>
80 using namespace com::sun::star::uno
;
81 using namespace com::sun::star
;
83 class SwOLELRUCache
: private SvPtrarr
, private utl::ConfigItem
85 sal_uInt16 nLRU_InitSize
;
87 uno::Sequence
< rtl::OUString
> GetPropertyNames();
92 virtual void Notify( const uno::Sequence
<
93 rtl::OUString
>& aPropertyNames
);
94 virtual void Commit();
97 void SetInUnload( BOOL bFlag
) { bInUnload
= bFlag
; }
98 using SvPtrarr::Count
;
100 void InsertObj( SwOLEObj
& rObj
);
101 void RemoveObj( SwOLEObj
& rObj
);
103 void RemovePtr( SwOLEObj
* pObj
)
105 USHORT nPos
= SvPtrarr::GetPos( pObj
);
106 if( USHRT_MAX
!= nPos
)
107 SvPtrarr::Remove( nPos
);
111 SwOLELRUCache
* pOLELRU_Cache
= 0;
113 class SwOLEListener_Impl
: public ::cppu::WeakImplHelper1
< embed::XStateChangeListener
>
117 SwOLEListener_Impl( SwOLEObj
* pObj
);
119 virtual void SAL_CALL
changingState( const lang::EventObject
& aEvent
, ::sal_Int32 nOldState
, ::sal_Int32 nNewState
) throw (embed::WrongStateException
, uno::RuntimeException
);
120 virtual void SAL_CALL
stateChanged( const lang::EventObject
& aEvent
, ::sal_Int32 nOldState
, ::sal_Int32 nNewState
) throw (uno::RuntimeException
);
121 virtual void SAL_CALL
disposing( const lang::EventObject
& aEvent
) throw (uno::RuntimeException
);
124 SwOLEListener_Impl::SwOLEListener_Impl( SwOLEObj
* pObj
)
127 if ( mpObj
->IsOleRef() && mpObj
->GetOleRef()->getCurrentState() == embed::EmbedStates::RUNNING
)
129 pOLELRU_Cache
->InsertObj( *mpObj
);
133 void SAL_CALL
SwOLEListener_Impl::changingState( const lang::EventObject
&, ::sal_Int32
, ::sal_Int32
) throw (embed::WrongStateException
, uno::RuntimeException
)
137 void SAL_CALL
SwOLEListener_Impl::stateChanged( const lang::EventObject
&, ::sal_Int32 nOldState
, ::sal_Int32 nNewState
) throw (uno::RuntimeException
)
139 if ( mpObj
&& nOldState
== embed::EmbedStates::LOADED
&& nNewState
== embed::EmbedStates::RUNNING
)
142 pOLELRU_Cache
= new SwOLELRUCache
;
143 pOLELRU_Cache
->InsertObj( *mpObj
);
145 else if ( mpObj
&& nNewState
== embed::EmbedStates::LOADED
&& nOldState
== embed::EmbedStates::RUNNING
)
148 pOLELRU_Cache
->RemoveObj( *mpObj
);
152 void SwOLEListener_Impl::Release()
154 if ( mpObj
&& pOLELRU_Cache
)
155 pOLELRU_Cache
->RemoveObj( *mpObj
);
160 void SAL_CALL
SwOLEListener_Impl::disposing( const lang::EventObject
& ) throw (uno::RuntimeException
)
162 if ( mpObj
&& pOLELRU_Cache
)
163 pOLELRU_Cache
->RemoveObj( *mpObj
);
166 // --------------------
168 // --------------------
169 // TODO/LATER: actually SwEmbedObjectLink should be used here, but because different objects are used to control
170 // embedded object different link objects with the same functionality had to be implemented
172 class SwEmbedObjectLink
: public sfx2::SvBaseLink
177 SwEmbedObjectLink(SwOLENode
* pNode
);
178 virtual ~SwEmbedObjectLink();
180 virtual void Closed();
181 virtual void DataChanged( const String
& rMimeType
,
182 const uno::Any
& rValue
);
184 sal_Bool
Connect() { return GetRealObject() != NULL
; }
187 // -----------------------------------------------------------------------------
189 SwEmbedObjectLink::SwEmbedObjectLink(SwOLENode
* pNode
):
190 ::sfx2::SvBaseLink( ::sfx2::LINKUPDATE_ONCALL
, SOT_FORMATSTR_ID_SVXB
),
193 SetSynchron( FALSE
);
196 // -----------------------------------------------------------------------------
198 SwEmbedObjectLink::~SwEmbedObjectLink()
202 // -----------------------------------------------------------------------------
204 void SwEmbedObjectLink::DataChanged( const String
& ,
207 if ( !pOleNode
->UpdateLinkURL_Impl() )
209 // the link URL was not changed
210 uno::Reference
< embed::XEmbeddedObject
> xObject
= pOleNode
->GetOLEObj().GetOleRef();
211 OSL_ENSURE( xObject
.is(), "The object must exist always!\n" );
214 // let the object reload the link
215 // TODO/LATER: reload call could be used for this case
219 sal_Int32 nState
= xObject
->getCurrentState();
220 if ( nState
!= embed::EmbedStates::LOADED
)
222 // in some cases the linked file probably is not locked so it could be changed
223 xObject
->changeState( embed::EmbedStates::LOADED
);
224 xObject
->changeState( nState
);
227 catch ( uno::Exception
& )
233 pOleNode
->GetNewReplacement();
234 // Initiate repainting
235 // pObj->SetChanged();
238 // -----------------------------------------------------------------------------
240 void SwEmbedObjectLink::Closed()
242 pOleNode
->BreakFileLink_Impl();
243 SvBaseLink::Closed();
247 // --------------------
249 // --------------------
251 SwOLENode::SwOLENode( const SwNodeIndex
&rWhere
,
252 const svt::EmbeddedObjectRef
& xObj
,
253 SwGrfFmtColl
*pGrfColl
,
254 SwAttrSet
* pAutoAttr
) :
255 SwNoTxtNode( rWhere
, ND_OLENODE
, pGrfColl
, pAutoAttr
),
258 bOLESizeInvalid( FALSE
),
261 aOLEObj
.SetNode( this );
264 SwOLENode::SwOLENode( const SwNodeIndex
&rWhere
,
265 const String
&rString
,
267 SwGrfFmtColl
*pGrfColl
,
268 SwAttrSet
* pAutoAttr
) :
269 SwNoTxtNode( rWhere
, ND_OLENODE
, pGrfColl
, pAutoAttr
),
270 aOLEObj( rString
, nAspect
),
272 bOLESizeInvalid( FALSE
),
275 aOLEObj
.SetNode( this );
278 SwOLENode::~SwOLENode()
280 DisconnectFileLink_Impl();
284 Graphic
* SwOLENode::GetGraphic()
286 if ( aOLEObj
.GetOleRef().is() )
287 return aOLEObj
.xOLERef
.GetGraphic();
291 Graphic
* SwOLENode::GetHCGraphic()
293 return aOLEObj
.xOLERef
.GetHCGraphic();
296 SwCntntNode
*SwOLENode::SplitCntntNode( const SwPosition
& )
298 // OLE-Objecte vervielfaeltigen ??
299 ASSERT( FALSE
, "OleNode: can't split." );
303 // Laden eines in den Undo-Bereich verschobenen OLE-Objekts
305 BOOL
SwOLENode::RestorePersistentData()
307 DBG_ASSERT( aOLEObj
.GetOleRef().is(), "No object to restore!" );
308 if ( aOLEObj
.xOLERef
.is() )
310 // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese
311 SfxObjectShell
* p
= GetDoc()->GetPersist();
314 // TODO/LATER: reicht hier nicht ein EmbeddedObjectContainer? Was passiert mit
316 ASSERT( !this, "warum wird hier eine DocShell angelegt?" );
317 p
= new SwDocShell( GetDoc(), SFX_CREATE_MODE_INTERNAL
);
318 p
->DoInitNew( NULL
);
321 uno::Reference
< container::XChild
> xChild( aOLEObj
.xOLERef
.GetObject(), uno::UNO_QUERY
);
323 xChild
->setParent( p
->GetModel() );
325 DBG_ASSERT( aOLEObj
.aName
.Len(), "No object name!" );
326 ::rtl::OUString aObjName
;
327 if ( !p
->GetEmbeddedObjectContainer().InsertEmbeddedObject( aOLEObj
.xOLERef
.GetObject(), aObjName
) )
330 xChild
->setParent( 0 );
331 DBG_ERROR( "InsertObject failed" );
335 aOLEObj
.aName
= aObjName
;
336 aOLEObj
.xOLERef
.AssignToContainer( &p
->GetEmbeddedObjectContainer(), aObjName
);
337 CheckFileLink_Impl();
344 // OLE object is transported into UNDO area
345 BOOL
SwOLENode::SavePersistentData()
347 if( aOLEObj
.xOLERef
.is() )
349 comphelper::EmbeddedObjectContainer
* pCnt
= aOLEObj
.xOLERef
.GetContainer();
351 #if OSL_DEBUG_LEVEL > 0
352 SfxObjectShell
* p
= GetDoc()->GetPersist();
353 DBG_ASSERT( p
, "No document!" );
356 comphelper::EmbeddedObjectContainer
& rCnt
= p
->GetEmbeddedObjectContainer();
357 OSL_ENSURE( !pCnt
|| &rCnt
== pCnt
, "The helper is assigned to unexpected container!\n" );
361 if ( pCnt
&& pCnt
->HasEmbeddedObject( aOLEObj
.aName
) )
363 uno::Reference
< container::XChild
> xChild( aOLEObj
.xOLERef
.GetObject(), uno::UNO_QUERY
);
365 xChild
->setParent( 0 );
367 pCnt
->RemoveEmbeddedObject( aOLEObj
.aName
, sal_False
);
369 // TODO/LATER: aOLEObj.aName has no meaning here, since the undo container contains the object
370 // by different name, in future it might makes sence that the name is transported here.
371 aOLEObj
.xOLERef
.AssignToContainer( 0, aOLEObj
.aName
);
375 aOLEObj
.xOLERef
->changeState( embed::EmbedStates::LOADED
);
377 catch ( uno::Exception
& )
383 DisconnectFileLink_Impl();
389 SwOLENode
* SwNodes::MakeOLENode( const SwNodeIndex
& rWhere
,
390 const svt::EmbeddedObjectRef
& xObj
,
391 SwGrfFmtColl
* pGrfColl
,
392 SwAttrSet
* pAutoAttr
)
394 ASSERT( pGrfColl
,"SwNodes::MakeOLENode: Formatpointer ist 0." );
397 new SwOLENode( rWhere
, xObj
, pGrfColl
, pAutoAttr
);
399 // set parent if XChild is supported
400 //!! needed to supply Math objects with a valid reference device
401 uno::Reference
< container::XChild
> xChild( pNode
->GetOLEObj().GetObject().GetObject(), UNO_QUERY
);
404 SwDocShell
*pDocSh
= GetDoc()->GetDocShell();
406 xChild
->setParent( pDocSh
->GetModel() );
413 SwOLENode
* SwNodes::MakeOLENode( const SwNodeIndex
& rWhere
,
414 const String
&rName
, sal_Int64 nAspect
, SwGrfFmtColl
* pGrfColl
, SwAttrSet
* pAutoAttr
)
416 ASSERT( pGrfColl
,"SwNodes::MakeOLENode: Formatpointer ist 0." );
419 new SwOLENode( rWhere
, rName
, nAspect
, pGrfColl
, pAutoAttr
);
421 // set parent if XChild is supported
422 //!! needed to supply Math objects with a valid reference device
423 uno::Reference
< container::XChild
> xChild( pNode
->GetOLEObj().GetObject().GetObject(), UNO_QUERY
);
426 SwDocShell
*pDocSh
= GetDoc()->GetDocShell();
428 xChild
->setParent( pDocSh
->GetModel() );
434 Size
SwOLENode::GetTwipSize() const
436 MapMode
aMapMode( MAP_TWIP
);
437 return ((SwOLENode
*)this)->aOLEObj
.GetObject().GetSize( &aMapMode
);
440 SwCntntNode
* SwOLENode::MakeCopy( SwDoc
* pDoc
, const SwNodeIndex
& rIdx
) const
442 // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese
443 SfxObjectShell
* p
= pDoc
->GetPersist();
446 // TODO/LATER: reicht hier nicht ein EmbeddedObjectContainer? Was passiert mit
448 ASSERT( pDoc
->GetRefForDocShell(),
449 "wo ist die Ref-Klasse fuer die DocShell?")
450 p
= new SwDocShell( pDoc
, SFX_CREATE_MODE_INTERNAL
);
451 *pDoc
->GetRefForDocShell() = p
;
452 p
->DoInitNew( NULL
);
455 // Wir hauen das Ding auf SvPersist-Ebene rein
456 // TODO/LATER: check if using the same naming scheme for all apps works here
457 ::rtl::OUString aNewName
/*( Sw3Io::UniqueName( p->GetStorage(), "Obj" ) )*/;
458 SfxObjectShell
* pSrc
= GetDoc()->GetPersist();
460 p
->GetEmbeddedObjectContainer().CopyAndGetEmbeddedObject(
461 pSrc
->GetEmbeddedObjectContainer(),
462 pSrc
->GetEmbeddedObjectContainer().GetEmbeddedObject( aOLEObj
.aName
),
465 SwOLENode
* pOLENd
= pDoc
->GetNodes().MakeOLENode( rIdx
, aNewName
, GetAspect(),
466 (SwGrfFmtColl
*)pDoc
->GetDfltGrfFmtColl(),
467 (SwAttrSet
*)GetpSwAttrSet() );
469 pOLENd
->SetChartTblName( GetChartTblName() );
470 pOLENd
->SetTitle( GetTitle() );
471 pOLENd
->SetDescription( GetDescription() );
472 pOLENd
->SetContour( HasContour(), HasAutomaticContour() );
473 pOLENd
->SetAspect( GetAspect() ); // the replacement image must be already copied
475 pOLENd
->SetOLESizeInvalid( TRUE
);
476 pDoc
->SetOLEPrtNotifyPending();
481 BOOL
SwOLENode::IsInGlobalDocSection() const
483 // suche den "Body Anchor"
484 ULONG nEndExtraIdx
= GetNodes().GetEndOfExtras().GetIndex();
485 const SwNode
* pAnchorNd
= this;
487 SwFrmFmt
* pFlyFmt
= pAnchorNd
->GetFlyFmt();
491 const SwFmtAnchor
& rAnchor
= pFlyFmt
->GetAnchor();
492 if( !rAnchor
.GetCntntAnchor() )
495 pAnchorNd
= &rAnchor
.GetCntntAnchor()->nNode
.GetNode();
496 } while( pAnchorNd
->GetIndex() < nEndExtraIdx
);
498 const SwSectionNode
* pSectNd
= pAnchorNd
->FindSectionNode();
505 pSectNd
= pAnchorNd
->StartOfSectionNode()->FindSectionNode();
508 // in pAnchorNd steht der zuletzt gefundene Section Node. Der muss
509 // jetzt die Bedingung fuers GlobalDoc erfuellen.
510 pSectNd
= (SwSectionNode
*)pAnchorNd
;
511 return FILE_LINK_SECTION
== pSectNd
->GetSection().GetType() &&
512 pSectNd
->GetIndex() > nEndExtraIdx
;
515 BOOL
SwOLENode::IsOLEObjectDeleted() const
518 if( aOLEObj
.xOLERef
.is() )
520 SfxObjectShell
* p
= GetDoc()->GetPersist();
521 if( p
) // muss da sein
523 return !p
->GetEmbeddedObjectContainer().HasEmbeddedObject( aOLEObj
.aName
);
524 //SvInfoObjectRef aRef( p->Find( aOLEObj.aName ) );
526 // bRet = aRef->IsDeleted();
532 void SwOLENode::GetNewReplacement()
534 if ( aOLEObj
.xOLERef
.is() )
535 aOLEObj
.xOLERef
.UpdateReplacement();
538 sal_Bool
SwOLENode::UpdateLinkURL_Impl()
540 sal_Bool bResult
= sal_False
;
545 GetDoc()->GetLinkManager().GetDisplayNames( mpObjectLink
, 0, &aNewLinkURL
, 0, 0 );
546 if ( !aNewLinkURL
.EqualsIgnoreCaseAscii( maLinkURL
) )
548 if ( !aOLEObj
.xOLERef
.is() )
551 uno::Reference
< embed::XEmbeddedObject
> xObj
= aOLEObj
.xOLERef
.GetObject();
552 uno::Reference
< embed::XCommonEmbedPersist
> xPersObj( xObj
, uno::UNO_QUERY
);
553 OSL_ENSURE( xPersObj
.is(), "The object must exist!\n" );
558 sal_Int32 nCurState
= xObj
->getCurrentState();
559 if ( nCurState
!= embed::EmbedStates::LOADED
)
560 xObj
->changeState( embed::EmbedStates::LOADED
);
562 // TODO/LATER: there should be possible to get current mediadescriptor settings from the object
563 uno::Sequence
< beans::PropertyValue
> aArgs( 1 );
564 aArgs
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) );
565 aArgs
[0].Value
<<= ::rtl::OUString( aNewLinkURL
);
566 xPersObj
->reload( aArgs
, uno::Sequence
< beans::PropertyValue
>() );
568 maLinkURL
= aNewLinkURL
;
571 if ( nCurState
!= embed::EmbedStates::LOADED
)
572 xObj
->changeState( nCurState
);
574 catch( uno::Exception
& )
580 // TODO/LATER: return the old name to the link manager, is it possible?
588 void SwOLENode::BreakFileLink_Impl()
590 SfxObjectShell
* pPers
= GetDoc()->GetPersist();
594 uno::Reference
< embed::XStorage
> xStorage
= pPers
->GetStorage();
599 uno::Reference
< embed::XLinkageSupport
> xLinkSupport( aOLEObj
.GetOleRef(), uno::UNO_QUERY_THROW
);
600 xLinkSupport
->breakLink( xStorage
, aOLEObj
.GetCurrentPersistName() );
601 DisconnectFileLink_Impl();
602 maLinkURL
= String();
604 catch( uno::Exception
& )
611 void SwOLENode::DisconnectFileLink_Impl()
615 GetDoc()->GetLinkManager().Remove( mpObjectLink
);
620 void SwOLENode::CheckFileLink_Impl()
622 if ( aOLEObj
.xOLERef
.GetObject().is() && !mpObjectLink
)
626 uno::Reference
< embed::XLinkageSupport
> xLinkSupport( aOLEObj
.xOLERef
.GetObject(), uno::UNO_QUERY_THROW
);
627 if ( xLinkSupport
->isLink() )
629 String aLinkURL
= xLinkSupport
->getLinkURL();
630 if ( aLinkURL
.Len() )
632 // this is a file link so the model link manager should handle it
633 mpObjectLink
= new SwEmbedObjectLink( this );
634 maLinkURL
= aLinkURL
;
635 GetDoc()->GetLinkManager().InsertFileLink( *mpObjectLink
, OBJECT_CLIENT_OLE
, aLinkURL
, NULL
, NULL
);
636 mpObjectLink
->Connect();
640 catch( uno::Exception
& )
646 // --> OD 2009-03-05 #i99665#
647 bool SwOLENode::IsChart() const
649 bool bIsChart( false );
651 const uno::Reference
< embed::XEmbeddedObject
> xEmbObj
=
652 const_cast<SwOLEObj
&>(GetOLEObj()).GetOleRef();
655 SvGlobalName
aClassID( xEmbObj
->getClassID() );
656 bIsChart
= SotExchange::IsChart( aClassID
);
663 SwOLEObj::SwOLEObj( const svt::EmbeddedObjectRef
& xObj
) :
668 xOLERef
.Lock( TRUE
);
671 pListener
= new SwOLEListener_Impl( this );
672 pListener
->acquire();
673 xObj
->addStateChangeListener( pListener
);
678 SwOLEObj::SwOLEObj( const String
&rString
, sal_Int64 nAspect
) :
683 xOLERef
.Lock( TRUE
);
684 xOLERef
.SetViewAspect( nAspect
);
688 SwOLEObj::~SwOLEObj()
693 xOLERef
->removeStateChangeListener( pListener
);
694 pListener
->Release();
697 if( pOLENd
&& !pOLENd
->GetDoc()->IsInDtor() )
699 // if the model is not currently in destruction it means that this object should be removed from the model
700 comphelper::EmbeddedObjectContainer
* pCnt
= xOLERef
.GetContainer();
702 #if OSL_DEBUG_LEVEL > 0
703 SfxObjectShell
* p
= pOLENd
->GetDoc()->GetPersist();
704 DBG_ASSERT( p
, "No document!" );
707 comphelper::EmbeddedObjectContainer
& rCnt
= p
->GetEmbeddedObjectContainer();
708 OSL_ENSURE( !pCnt
|| &rCnt
== pCnt
, "The helper is assigned to unexpected container!\n" );
712 if ( pCnt
&& pCnt
->HasEmbeddedObject( aName
) )
714 uno::Reference
< container::XChild
> xChild( xOLERef
.GetObject(), uno::UNO_QUERY
);
716 xChild
->setParent( 0 );
718 // not already removed by deleting the object
719 xOLERef
.AssignToContainer( 0, aName
);
721 // unlock object so that object can be closed in RemoveEmbeddedObject
722 // successful closing of the object will automatically clear the reference then
725 // Always remove object from conteiner it is connected to
728 pCnt
->RemoveEmbeddedObject( aName
);
730 catch ( uno::Exception
& )
738 // in case the object wasn't closed: release it
739 // in case the object was not in the container: it's still locked, try to close
744 void SwOLEObj::SetNode( SwOLENode
* pNode
)
749 SwDoc
* pDoc
= pNode
->GetDoc();
751 // Falls bereits eine SvPersist-Instanz existiert, nehmen wir diese
752 SfxObjectShell
* p
= pDoc
->GetPersist();
755 // TODO/LATER: reicht hier nicht ein EmbeddedObjectContainer? Was passiert mit
757 ASSERT( !this, "warum wird hier eine DocShell angelegt?" );
758 p
= new SwDocShell( pDoc
, SFX_CREATE_MODE_INTERNAL
);
759 p
->DoInitNew( NULL
);
762 ::rtl::OUString aObjName
;
763 uno::Reference
< container::XChild
> xChild( xOLERef
.GetObject(), uno::UNO_QUERY
);
764 if ( xChild
.is() && xChild
->getParent() != p
->GetModel() )
765 // it is possible that the parent was set already
766 xChild
->setParent( p
->GetModel() );
767 if (!p
->GetEmbeddedObjectContainer().InsertEmbeddedObject( xOLERef
.GetObject(), aObjName
) )
769 DBG_ERROR( "InsertObject failed" );
771 xChild
->setParent( 0 );
774 xOLERef
.AssignToContainer( &p
->GetEmbeddedObjectContainer(), aObjName
);
776 ( (SwOLENode
*)pOLENd
)->CheckFileLink_Impl(); // for this notification nonconst access is required
782 BOOL
SwOLEObj::IsOleRef() const
787 uno::Reference
< embed::XEmbeddedObject
> SwOLEObj::GetOleRef()
791 SfxObjectShell
* p
= pOLENd
->GetDoc()->GetPersist();
792 ASSERT( p
, "kein SvPersist vorhanden" );
794 uno::Reference
< embed::XEmbeddedObject
> xObj
= p
->GetEmbeddedObjectContainer().GetEmbeddedObject( aName
);
795 ASSERT( !xOLERef
.is(), "rekursiver Aufruf von GetOleRef() ist nicht erlaubt" )
799 //Das Teil konnte nicht geladen werden (wahrsch. Kaputt).
801 SwFrm
*pFrm
= pOLENd
->GetFrm();
804 Size
aSz( pFrm
->Frm().SSize() );
805 const MapMode
aSrc ( MAP_TWIP
);
806 const MapMode
aDest( MAP_100TH_MM
);
807 aSz
= OutputDevice::LogicToLogic( aSz
, aSrc
, aDest
);
808 aArea
.SetSize( aSz
);
811 aArea
.SetSize( Size( 5000, 5000 ) );
812 // TODO/LATER: set replacement graphic for dead object
813 // It looks as if it should work even without the object, because the replace will be generated automatically
814 ::rtl::OUString aTmpName
;
815 xObj
= p
->GetEmbeddedObjectContainer().CreateEmbeddedObject( SvGlobalName( SO3_DUMMY_CLASSID
).GetByteSequence(), aTmpName
);
819 xOLERef
.Assign( xObj
, xOLERef
.GetViewAspect() );
820 xOLERef
.AssignToContainer( &p
->GetEmbeddedObjectContainer(), aName
);
821 pListener
= new SwOLEListener_Impl( this );
822 pListener
->acquire();
823 xObj
->addStateChangeListener( pListener
);
826 ( (SwOLENode
*)pOLENd
)->CheckFileLink_Impl(); // for this notification nonconst access is required
828 else if ( xOLERef
->getCurrentState() == embed::EmbedStates::RUNNING
)
830 // move object to first position in cache
832 pOLELRU_Cache
= new SwOLELRUCache
;
833 pOLELRU_Cache
->InsertObj( *this );
836 return xOLERef
.GetObject();
839 svt::EmbeddedObjectRef
& SwOLEObj::GetObject()
845 BOOL
SwOLEObj::UnloadObject()
848 //Nicht notwendig im Doc DTor (MM)
849 //ASSERT( pOLERef && pOLERef->Is() && 1 < (*pOLERef)->GetRefCount(),
850 // "Falscher RefCount fuers Unload" );
853 const SwDoc
* pDoc
= pOLENd
->GetDoc();
854 bRet
= UnloadObject( xOLERef
.GetObject(), pDoc
, xOLERef
.GetViewAspect() );
860 BOOL
SwOLEObj::UnloadObject( uno::Reference
< embed::XEmbeddedObject
> xObj
, const SwDoc
* pDoc
, sal_Int64 nAspect
)
866 sal_Int32 nState
= xObj
.is() ? xObj
->getCurrentState() : embed::EmbedStates::LOADED
;
867 BOOL bIsActive
= ( nState
!= embed::EmbedStates::LOADED
&& nState
!= embed::EmbedStates::RUNNING
);
868 sal_Int64 nMiscStatus
= xObj
->getStatus( nAspect
);
870 if( nState
!= embed::EmbedStates::LOADED
&& !pDoc
->IsInDtor() && !bIsActive
&&
871 embed::EmbedMisc::MS_EMBED_ALWAYSRUN
!= ( nMiscStatus
& embed::EmbedMisc::MS_EMBED_ALWAYSRUN
) &&
872 embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY
!= ( nMiscStatus
& embed::EmbedMisc::EMBED_ACTIVATEIMMEDIATELY
) )
874 SfxObjectShell
* p
= pDoc
->GetPersist();
877 if( pDoc
->get(IDocumentSettingAccess::PURGE_OLE
) )
881 uno::Reference
< util::XModifiable
> xMod( xObj
->getComponent(), uno::UNO_QUERY
);
882 if( xMod
.is() && xMod
->isModified() )
884 uno::Reference
< embed::XEmbedPersist
> xPers( xObj
, uno::UNO_QUERY
);
888 DBG_ERROR("Modified object without persistance in cache!");
892 // setting object to loaded state will remove it from cache
893 xObj
->changeState( embed::EmbedStates::LOADED
);
895 catch ( uno::Exception
& )
908 String
SwOLEObj::GetDescription()
911 uno::Reference
< embed::XEmbeddedObject
> xEmbObj
= GetOleRef();
914 SvGlobalName
aClassID( xEmbObj
->getClassID() );
915 if ( SotExchange::IsMath( aClassID
) )
916 aResult
= SW_RES(STR_MATH_FORMULA
);
917 else if ( SotExchange::IsChart( aClassID
) )
918 aResult
= SW_RES(STR_CHART
);
920 aResult
= SW_RES(STR_OLE
);
927 SwOLELRUCache::SwOLELRUCache()
928 : SvPtrarr( 64, 16 ),
929 utl::ConfigItem( OUString::createFromAscii( "Office.Common/Cache" )),
931 bInUnload( sal_False
)
933 EnableNotification( GetPropertyNames() );
937 uno::Sequence
< rtl::OUString
> SwOLELRUCache::GetPropertyNames()
939 Sequence
< OUString
> aNames( 1 );
940 OUString
* pNames
= aNames
.getArray();
941 pNames
[0] = OUString::createFromAscii( "Writer/OLE_Objects" );
945 void SwOLELRUCache::Notify( const uno::Sequence
< rtl::OUString
>& )
950 void SwOLELRUCache::Commit()
954 void SwOLELRUCache::Load()
956 Sequence
< OUString
> aNames( GetPropertyNames() );
957 Sequence
< Any
> aValues
= GetProperties( aNames
);
958 const Any
* pValues
= aValues
.getConstArray();
959 DBG_ASSERT( aValues
.getLength() == aNames
.getLength(), "GetProperties failed" );
960 if( aValues
.getLength() == aNames
.getLength() && pValues
->hasValue() )
968 if( nVal
< nLRU_InitSize
)
970 // size of cache has been changed
971 USHORT nCount
= SvPtrarr::Count();
972 USHORT nPos
= nCount
;
974 // try to remove the last entries until new maximum size is reached
975 while( nCount
> nVal
)
977 SwOLEObj
* pObj
= (SwOLEObj
*) SvPtrarr::GetObject( --nPos
);
978 if ( pObj
->UnloadObject() )
986 nLRU_InitSize
= (USHORT
)nVal
;
990 void SwOLELRUCache::InsertObj( SwOLEObj
& rObj
)
992 SwOLEObj
* pObj
= &rObj
;
993 USHORT nPos
= SvPtrarr::GetPos( pObj
);
996 // object is currently not the first in cache
997 if( USHRT_MAX
!= nPos
)
998 SvPtrarr::Remove( nPos
);
1000 SvPtrarr::Insert( pObj
, 0 );
1002 // try to remove objects if necessary (of course not the freshly inserted one at nPos=0)
1003 USHORT nCount
= SvPtrarr::Count();
1005 while( nPos
&& nCount
> nLRU_InitSize
)
1007 pObj
= (SwOLEObj
*) SvPtrarr::GetObject( nPos
-- );
1008 if ( pObj
->UnloadObject() )
1014 void SwOLELRUCache::RemoveObj( SwOLEObj
& rObj
)
1016 USHORT nPos
= SvPtrarr::GetPos( &rObj
);
1017 if ( nPos
!= 0xFFFF )
1018 SvPtrarr::Remove( nPos
);
1020 DELETEZ( pOLELRU_Cache
);