Version 7.1.7.1, tag libreoffice-7.1.7.1
[LibreOffice.git] / sfx2 / source / doc / objxtor.cxx
bloba746d1ac89fbfed6864f701dfe007d8025581f49
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <config_features.h>
22 #include <map>
24 #include <cppuhelper/implbase.hxx>
25 #include <cppuhelper/weakref.hxx>
27 #include <com/sun/star/util/XCloseable.hpp>
28 #include <com/sun/star/frame/XComponentLoader.hpp>
29 #include <com/sun/star/frame/Desktop.hpp>
30 #include <com/sun/star/util/XCloseListener.hpp>
31 #include <com/sun/star/beans/XPropertySet.hpp>
32 #include <com/sun/star/frame/XTitle.hpp>
33 #include <osl/file.hxx>
34 #include <rtl/instance.hxx>
35 #include <sal/log.hxx>
36 #include <vcl/weld.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/window.hxx>
39 #include <svl/eitem.hxx>
40 #include <basic/sbstar.hxx>
41 #include <svl/stritem.hxx>
42 #include <unotools/configmgr.hxx>
43 #include <unotools/eventcfg.hxx>
45 #include <sfx2/objsh.hxx>
46 #include <sfx2/signaturestate.hxx>
47 #include <sfx2/sfxmodelfactory.hxx>
49 #include <comphelper/processfactory.hxx>
51 #include <com/sun/star/document/XStorageBasedDocument.hpp>
52 #include <com/sun/star/script/DocumentDialogLibraryContainer.hpp>
53 #include <com/sun/star/script/DocumentScriptLibraryContainer.hpp>
54 #include <com/sun/star/document/XEmbeddedScripts.hpp>
55 #include <com/sun/star/document/XScriptInvocationContext.hpp>
56 #include <com/sun/star/ucb/ContentCreationException.hpp>
57 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
59 #include <unotools/ucbhelper.hxx>
60 #include <tools/diagnose_ex.h>
61 #include <tools/globname.hxx>
62 #include <tools/debug.hxx>
64 #include <sfx2/app.hxx>
65 #include <sfx2/bindings.hxx>
66 #include <sfx2/docfile.hxx>
67 #include <sfx2/event.hxx>
68 #include <sfx2/viewsh.hxx>
69 #include <sfx2/viewfrm.hxx>
70 #include <sfx2/sfxresid.hxx>
71 #include <objshimp.hxx>
72 #include <sfx2/strings.hrc>
73 #include <sfx2/sfxsids.hrc>
74 #include <basic/basmgr.hxx>
75 #include <sfx2/QuerySaveDocument.hxx>
76 #include <appbaslib.hxx>
77 #include <sfx2/sfxbasemodel.hxx>
78 #include <sfx2/sfxuno.hxx>
79 #include <shellimpl.hxx>
80 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
81 #include <sfx2/infobar.hxx>
83 #include <basic/basicmanagerrepository.hxx>
85 using namespace ::com::sun::star;
86 using namespace ::com::sun::star::uno;
87 using namespace ::com::sun::star::script;
88 using namespace ::com::sun::star::frame;
89 using namespace ::com::sun::star::document;
91 using ::basic::BasicManagerRepository;
93 namespace {
95 class theCurrentComponent : public rtl::Static< WeakReference< XInterface >, theCurrentComponent > {};
97 #if HAVE_FEATURE_SCRIPTING
99 // remember all registered components for VBA compatibility, to be able to remove them on disposing the model
100 typedef ::std::map< XInterface*, OUString > VBAConstantNameMap;
101 VBAConstantNameMap s_aRegisteredVBAConstants;
103 OUString lclGetVBAGlobalConstName( const Reference< XInterface >& rxComponent )
105 OSL_ENSURE( rxComponent.is(), "lclGetVBAGlobalConstName - missing component" );
107 VBAConstantNameMap::iterator aIt = s_aRegisteredVBAConstants.find( rxComponent.get() );
108 if( aIt != s_aRegisteredVBAConstants.end() )
109 return aIt->second;
111 uno::Reference< beans::XPropertySet > xProps( rxComponent, uno::UNO_QUERY );
112 if( xProps.is() ) try
114 OUString aConstName;
115 xProps->getPropertyValue("VBAGlobalConstantName") >>= aConstName;
116 return aConstName;
118 catch (const uno::Exception&) // not supported
121 return OUString();
124 #endif
126 class SfxModelListener_Impl : public ::cppu::WeakImplHelper< css::util::XCloseListener >
128 SfxObjectShell* mpDoc;
129 public:
130 explicit SfxModelListener_Impl( SfxObjectShell* pDoc ) : mpDoc(pDoc) {};
131 virtual void SAL_CALL queryClosing( const css::lang::EventObject& aEvent, sal_Bool bDeliverOwnership ) override ;
132 virtual void SAL_CALL notifyClosing( const css::lang::EventObject& aEvent ) override ;
133 virtual void SAL_CALL disposing( const css::lang::EventObject& aEvent ) override ;
137 } // namespace
139 void SAL_CALL SfxModelListener_Impl::queryClosing( const css::lang::EventObject& , sal_Bool )
143 void SAL_CALL SfxModelListener_Impl::notifyClosing( const css::lang::EventObject& )
145 SolarMutexGuard aSolarGuard;
146 mpDoc->Broadcast( SfxHint(SfxHintId::Deinitializing) );
149 void SAL_CALL SfxModelListener_Impl::disposing( const css::lang::EventObject& _rEvent )
151 // am I ThisComponent in AppBasic?
152 SolarMutexGuard aSolarGuard;
153 if ( SfxObjectShell::GetCurrentComponent() == _rEvent.Source )
155 // remove ThisComponent reference from AppBasic
156 SfxObjectShell::SetCurrentComponent( Reference< XInterface >() );
159 #if HAVE_FEATURE_SCRIPTING
160 /* Remove VBA component from AppBasic. As every application registers its
161 own current component, the disposed component may not be the "current
162 component" of the SfxObjectShell. */
163 if ( _rEvent.Source.is() )
165 VBAConstantNameMap::iterator aIt = s_aRegisteredVBAConstants.find( _rEvent.Source.get() );
166 if ( aIt != s_aRegisteredVBAConstants.end() )
168 if ( BasicManager* pAppMgr = SfxApplication::GetBasicManager() )
169 pAppMgr->SetGlobalUNOConstant( aIt->second, Any( Reference< XInterface >() ) );
170 s_aRegisteredVBAConstants.erase( aIt );
173 #endif
175 if ( !mpDoc->Get_Impl()->bClosing )
176 // GCC crashes when already in the destructor, so first query the Flag
177 mpDoc->DoClose();
181 SfxObjectShell_Impl::SfxObjectShell_Impl( SfxObjectShell& _rDocShell )
182 :rDocShell( _rDocShell )
183 ,aMacroMode( *this )
184 ,pProgress( nullptr)
185 ,nTime( DateTime::SYSTEM )
186 ,nVisualDocumentNumber( USHRT_MAX)
187 ,nDocumentSignatureState( SignatureState::UNKNOWN )
188 ,nScriptingSignatureState( SignatureState::UNKNOWN )
189 ,bClosing( false)
190 ,bIsSaving( false)
191 ,bIsNamedVisible( false)
192 ,bIsAbortingImport ( false)
193 ,bInPrepareClose( false )
194 ,bPreparedForClose( false )
195 ,bForbidReload( false )
196 ,bBasicInitialized( false )
197 ,bIsPrintJobCancelable( true )
198 ,bOwnsStorage( true )
199 ,bInitialized( false )
200 ,bModelInitialized( false )
201 ,bPreserveVersions( true )
202 ,m_bMacroSignBroken( false )
203 ,m_bNoBasicCapabilities( false )
204 ,m_bDocRecoverySupport( true )
205 ,bQueryLoadTemplate( true )
206 ,bLoadReadonly( false )
207 ,bUseUserData( true )
208 ,bUseThumbnailSave( true )
209 ,bSaveVersionOnClose( false )
210 ,m_bSharedXMLFlag( false )
211 ,m_bAllowShareControlFileClean( true )
212 ,m_bConfigOptionsChecked( false )
213 ,m_bMacroCallsSeenWhileLoading( false )
214 ,lErr(ERRCODE_NONE)
215 ,nEventId ( SfxEventHintId::NONE )
216 ,nLoadedFlags ( SfxLoadedFlags::ALL )
217 ,nFlagsInProgress( SfxLoadedFlags::NONE )
218 ,bModalMode( false )
219 ,bRunningMacro( false )
220 ,bReadOnlyUI( false )
221 ,nStyleFilter( 0 )
222 ,m_bEnableSetModified( true )
223 ,m_bIsModified( false )
224 ,m_nMapUnit( MapUnit::Map100thMM )
225 ,m_bCreateTempStor( false )
226 ,m_bIsInit( false )
227 ,m_bIncomplEncrWarnShown( false )
228 ,m_nModifyPasswordHash( 0 )
229 ,m_bModifyPasswordEntered( false )
230 ,m_bSavingForSigning( false )
231 ,m_bAllowModifiedBackAfterSigning( false )
233 SfxObjectShell* pDoc = &_rDocShell;
234 SfxObjectShellArr_Impl &rArr = SfxGetpApp()->GetObjectShells_Impl();
235 rArr.push_back( pDoc );
239 SfxObjectShell_Impl::~SfxObjectShell_Impl()
244 SfxObjectShell::SfxObjectShell( const SfxModelFlags i_nCreationFlags )
245 : pImpl(new SfxObjectShell_Impl(*this))
246 , pMedium(nullptr)
247 , eCreateMode(SfxObjectCreateMode::STANDARD)
248 , bHasName(false)
249 , bIsInGenerateThumbnail (false)
250 , mbAvoidRecentDocs(false)
252 if (i_nCreationFlags & SfxModelFlags::EMBEDDED_OBJECT)
253 eCreateMode = SfxObjectCreateMode::EMBEDDED;
254 else if (i_nCreationFlags & SfxModelFlags::EXTERNAL_LINK)
255 eCreateMode = SfxObjectCreateMode::INTERNAL;
257 const bool bScriptSupport = ( i_nCreationFlags & SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS ) == SfxModelFlags::NONE;
258 if ( !bScriptSupport )
259 pImpl->m_bNoBasicCapabilities = true;
261 const bool bDocRecovery = ( i_nCreationFlags & SfxModelFlags::DISABLE_DOCUMENT_RECOVERY ) == SfxModelFlags::NONE;
262 if ( !bDocRecovery )
263 pImpl->m_bDocRecoverySupport = false;
266 /** Constructor of the class SfxObjectShell.
268 @param eMode Purpose, to which the SfxObjectShell is created:
269 SfxObjectCreateMode::EMBEDDED (default) as SO-Server from within another Document
270 SfxObjectCreateMode::STANDARD, as a normal Document open stand-alone
271 SfxObjectCreateMode::ORGANIZER to be displayed in the Organizer, here nothing of the contents is used
273 SfxObjectShell::SfxObjectShell(SfxObjectCreateMode eMode)
274 : pImpl(new SfxObjectShell_Impl(*this))
275 , pMedium(nullptr)
276 , eCreateMode(eMode)
277 , bHasName(false)
278 , bIsInGenerateThumbnail(false)
279 , mbAvoidRecentDocs(false)
283 SfxObjectShell::~SfxObjectShell()
286 if ( IsEnableSetModified() )
287 EnableSetModified( false );
289 SfxObjectShell::CloseInternal();
290 pImpl->pBaseModel.set( nullptr );
292 pImpl->pReloadTimer.reset();
294 SfxApplication *pSfxApp = SfxGetpApp();
295 if ( USHRT_MAX != pImpl->nVisualDocumentNumber && pSfxApp )
296 pSfxApp->ReleaseIndex(pImpl->nVisualDocumentNumber);
298 // Destroy Basic-Manager
299 pImpl->aBasicManager.reset(nullptr);
301 if ( pSfxApp && pSfxApp->GetDdeService() )
302 pSfxApp->RemoveDdeTopic( this );
304 pImpl->pBaseModel.set( nullptr );
306 // don't call GetStorage() here, in case of Load Failure it's possible that a storage was never assigned!
307 if ( pMedium && pMedium->HasStorage_Impl() && pMedium->GetStorage( false ) == pImpl->m_xDocStorage )
308 pMedium->CanDisposeStorage_Impl( false );
310 if ( pImpl->mxObjectContainer )
312 pImpl->mxObjectContainer->CloseEmbeddedObjects();
313 pImpl->mxObjectContainer.reset();
316 if ( pImpl->bOwnsStorage && pImpl->m_xDocStorage.is() )
317 pImpl->m_xDocStorage->dispose();
319 if ( pMedium )
321 pMedium->CloseAndReleaseStreams_Impl();
323 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
324 if (IsDocShared())
325 FreeSharedFile( pMedium->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
326 #endif
327 delete pMedium;
328 pMedium = nullptr;
331 // The removing of the temporary file must be done as the latest step in the document destruction
332 if ( !pImpl->aTempName.isEmpty() )
334 OUString aTmp;
335 osl::FileBase::getFileURLFromSystemPath( pImpl->aTempName, aTmp );
336 ::utl::UCBContentHelper::Kill( aTmp );
341 void SfxObjectShell::Stamp_SetPrintCancelState(bool bState)
343 pImpl->bIsPrintJobCancelable = bState;
347 bool SfxObjectShell::Stamp_GetPrintCancelState() const
349 return pImpl->bIsPrintJobCancelable;
353 // closes the Object and all its views
355 bool SfxObjectShell::Close()
357 SfxObjectShellRef xKeepAlive(this);
358 return CloseInternal();
361 // variant that does not take a reference to itself, so we can call it during object destruction
362 bool SfxObjectShell::CloseInternal()
364 if ( !pImpl->bClosing )
366 // Do not close if a progress is still running
367 if ( GetProgress() )
368 return false;
370 pImpl->bClosing = true;
371 Reference< util::XCloseable > xCloseable( GetBaseModel(), UNO_QUERY );
373 if ( xCloseable.is() )
377 xCloseable->close( true );
379 catch (const Exception&)
381 pImpl->bClosing = false;
385 if ( pImpl->bClosing )
387 // remove from Document list
388 // If there is no App, there is no document to remove
389 // no need to call GetOrCreate here
390 SfxApplication *pSfxApp = SfxApplication::Get();
391 if(pSfxApp)
393 SfxObjectShellArr_Impl &rDocs = pSfxApp->GetObjectShells_Impl();
394 SfxObjectShellArr_Impl::iterator it = std::find( rDocs.begin(), rDocs.end(), this );
395 if ( it != rDocs.end() )
396 rDocs.erase( it );
401 return true;
404 OUString SfxObjectShell::CreateShellID( const SfxObjectShell* pShell )
406 if (!pShell)
407 return OUString();
409 OUString aShellID;
411 SfxMedium* pMedium = pShell->GetMedium();
412 if (pMedium)
413 aShellID = pMedium->GetBaseURL();
415 if (!aShellID.isEmpty())
416 return aShellID;
418 sal_Int64 nShellID = reinterpret_cast<sal_Int64>(pShell);
419 aShellID = "0x" + OUString::number(nShellID, 16);
420 return aShellID;
423 // returns a pointer the first SfxDocument of specified type
425 SfxObjectShell* SfxObjectShell::GetFirst
427 const std::function<bool ( const SfxObjectShell* )>& isObjectShell,
428 bool bOnlyVisible
431 SfxObjectShellArr_Impl &rDocs = SfxGetpApp()->GetObjectShells_Impl();
433 // search for a SfxDocument of the specified type
434 for (SfxObjectShell* pSh : rDocs)
436 if ( bOnlyVisible && pSh->IsPreview() && pSh->IsReadOnly() )
437 continue;
439 if ( (!isObjectShell || isObjectShell( pSh)) &&
440 ( !bOnlyVisible || SfxViewFrame::GetFirst( pSh )))
441 return pSh;
444 return nullptr;
448 // returns a pointer to the next SfxDocument of specified type behind *pDoc
450 SfxObjectShell* SfxObjectShell::GetNext
452 const SfxObjectShell& rPrev,
453 const std::function<bool ( const SfxObjectShell* )>& isObjectShell,
454 bool bOnlyVisible
457 SfxObjectShellArr_Impl &rDocs = SfxGetpApp()->GetObjectShells_Impl();
459 // refind the specified predecessor
460 size_t nPos;
461 for ( nPos = 0; nPos < rDocs.size(); ++nPos )
462 if ( rDocs[nPos] == &rPrev )
463 break;
465 // search for the next SfxDocument of the specified type
466 for ( ++nPos; nPos < rDocs.size(); ++nPos )
468 SfxObjectShell* pSh = rDocs[ nPos ];
469 if ( bOnlyVisible && pSh->IsPreview() && pSh->IsReadOnly() )
470 continue;
472 if ( (!isObjectShell || isObjectShell( pSh)) &&
473 ( !bOnlyVisible || SfxViewFrame::GetFirst( pSh )))
474 return pSh;
476 return nullptr;
480 SfxObjectShell* SfxObjectShell::Current()
482 SfxViewFrame *pFrame = SfxViewFrame::Current();
483 return pFrame ? pFrame->GetObjectShell() : nullptr;
487 bool SfxObjectShell::IsInPrepareClose() const
489 return pImpl->bInPrepareClose;
492 namespace {
494 struct BoolEnv_Impl
496 SfxObjectShell_Impl& rImpl;
497 explicit BoolEnv_Impl( SfxObjectShell_Impl& rImplP) : rImpl( rImplP )
498 { rImplP.bInPrepareClose = true; }
499 ~BoolEnv_Impl() { rImpl.bInPrepareClose = false; }
504 bool SfxObjectShell::PrepareClose
506 bool bUI // true: Dialog and so on is allowed
507 // false: silent-mode
510 if( pImpl->bInPrepareClose || pImpl->bPreparedForClose )
511 return true;
512 BoolEnv_Impl aBoolEnv( *pImpl );
514 // DocModalDialog?
515 if ( IsInModalMode() )
516 return false;
518 SfxViewFrame* pFirst = SfxViewFrame::GetFirst( this );
519 if( pFirst && !pFirst->GetFrame().PrepareClose_Impl( bUI ) )
520 return false;
522 // prepare views for closing
523 for ( SfxViewFrame* pFrm = SfxViewFrame::GetFirst( this );
524 pFrm; pFrm = SfxViewFrame::GetNext( *pFrm, this ) )
526 DBG_ASSERT(pFrm->GetViewShell(),"No Shell");
527 if ( pFrm->GetViewShell() )
529 bool bRet = pFrm->GetViewShell()->PrepareClose( bUI );
530 if ( !bRet )
531 return bRet;
535 SfxApplication *pSfxApp = SfxGetpApp();
536 pSfxApp->NotifyEvent( SfxEventHint(SfxEventHintId::PrepareCloseDoc, GlobalEventConfig::GetEventName(GlobalEventId::PREPARECLOSEDOC), this) );
538 if( GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
540 pImpl->bPreparedForClose = true;
541 return true;
544 // Ask if possible if it should be saved
545 // only ask for the Document in the visible window
546 SfxViewFrame *pFrame = SfxObjectShell::Current() == this
547 ? SfxViewFrame::Current() : SfxViewFrame::GetFirst( this );
549 if ( bUI && IsModified() && pFrame )
551 // restore minimized
552 SfxFrame& rTop = pFrame->GetFrame();
553 SfxViewFrame::SetViewFrame( rTop.GetCurrentViewFrame() );
554 pFrame->GetFrame().Appear();
556 // Ask if to save
557 short nRet = RET_YES;
559 const Reference<XTitle> xTitle(*pImpl->pBaseModel, UNO_QUERY_THROW);
560 const OUString sTitle = xTitle->getTitle ();
561 nRet = ExecuteQuerySaveDocument(pFrame->GetWindow().GetFrameWeld(), sTitle);
563 /*HACK for plugin::destroy()*/
565 if ( RET_YES == nRet )
567 // Save by each Dispatcher
568 const SfxPoolItem *pPoolItem;
569 if ( IsSaveVersionOnClose() )
571 SfxStringItem aItem( SID_DOCINFO_COMMENTS, SfxResId(STR_AUTOMATICVERSION) );
572 SfxBoolItem aWarnItem( SID_FAIL_ON_WARNING, bUI );
573 const SfxPoolItem* ppArgs[] = { &aItem, &aWarnItem, nullptr };
574 pPoolItem = pFrame->GetBindings().ExecuteSynchron( SID_SAVEDOC, ppArgs );
576 else
578 SfxBoolItem aWarnItem( SID_FAIL_ON_WARNING, bUI );
579 const SfxPoolItem* ppArgs[] = { &aWarnItem, nullptr };
580 pPoolItem = pFrame->GetBindings().ExecuteSynchron( SID_SAVEDOC, ppArgs );
583 if ( !pPoolItem || pPoolItem->IsVoidItem() || ( dynamic_cast< const SfxBoolItem *>( pPoolItem ) != nullptr && !static_cast<const SfxBoolItem*>( pPoolItem )->GetValue() ) )
584 return false;
586 else if ( RET_CANCEL == nRet )
587 // Cancelled
588 return false;
591 if ( pFrame )
592 sfx2::SfxNotebookBar::CloseMethod(pFrame->GetBindings());
593 pImpl->bPreparedForClose = true;
594 return true;
598 #if HAVE_FEATURE_SCRIPTING
599 namespace
601 BasicManager* lcl_getBasicManagerForDocument( const SfxObjectShell& _rDocument )
603 if ( !_rDocument.Get_Impl()->m_bNoBasicCapabilities )
605 if ( !_rDocument.Get_Impl()->bBasicInitialized )
606 const_cast< SfxObjectShell& >( _rDocument ).InitBasicManager_Impl();
607 return _rDocument.Get_Impl()->aBasicManager.get();
610 // assume we do not have Basic ourself, but we can refer to another
611 // document which does (by our model's XScriptInvocationContext::getScriptContainer).
612 // In this case, we return the BasicManager of this other document.
614 OSL_ENSURE( !Reference< XEmbeddedScripts >( _rDocument.GetModel(), UNO_QUERY ).is(),
615 "lcl_getBasicManagerForDocument: inconsistency: no Basic, but an XEmbeddedScripts?" );
616 Reference< XModel > xForeignDocument;
617 Reference< XScriptInvocationContext > xContext( _rDocument.GetModel(), UNO_QUERY );
618 if ( xContext.is() )
620 xForeignDocument.set( xContext->getScriptContainer(), UNO_QUERY );
621 OSL_ENSURE( xForeignDocument.is() && xForeignDocument != _rDocument.GetModel(),
622 "lcl_getBasicManagerForDocument: no Basic, but providing ourself as script container?" );
625 BasicManager* pBasMgr = nullptr;
626 if ( xForeignDocument.is() )
627 pBasMgr = ::basic::BasicManagerRepository::getDocumentBasicManager( xForeignDocument );
629 return pBasMgr;
632 #endif
634 BasicManager* SfxObjectShell::GetBasicManager() const
636 BasicManager* pBasMgr = nullptr;
637 #if HAVE_FEATURE_SCRIPTING
640 pBasMgr = lcl_getBasicManagerForDocument( *this );
641 if ( !pBasMgr )
642 pBasMgr = SfxApplication::GetBasicManager();
644 catch (const css::ucb::ContentCreationException&)
646 TOOLS_WARN_EXCEPTION("sfx.doc", "");
648 #endif
649 return pBasMgr;
652 bool SfxObjectShell::HasBasic() const
654 #if !HAVE_FEATURE_SCRIPTING
655 return false;
656 #else
657 if ( pImpl->m_bNoBasicCapabilities )
658 return false;
660 if ( !pImpl->bBasicInitialized )
661 const_cast< SfxObjectShell* >( this )->InitBasicManager_Impl();
663 return pImpl->aBasicManager.isValid();
664 #endif
668 #if HAVE_FEATURE_SCRIPTING
669 namespace
671 const Reference< XLibraryContainer >&
672 lcl_getOrCreateLibraryContainer( bool _bScript, Reference< XLibraryContainer >& _rxContainer,
673 const Reference< XModel >& _rxDocument )
675 if ( !_rxContainer.is() )
679 Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY );
680 const Reference< XComponentContext > xContext(
681 ::comphelper::getProcessComponentContext() );
682 _rxContainer.set ( _bScript
683 ? DocumentScriptLibraryContainer::create(
684 xContext, xStorageDoc )
685 : DocumentDialogLibraryContainer::create(
686 xContext, xStorageDoc )
687 , UNO_QUERY_THROW );
689 catch (const Exception&)
691 DBG_UNHANDLED_EXCEPTION("sfx.doc");
694 return _rxContainer;
697 #endif
699 Reference< XLibraryContainer > SfxObjectShell::GetDialogContainer()
701 #if HAVE_FEATURE_SCRIPTING
704 if ( !pImpl->m_bNoBasicCapabilities )
705 return lcl_getOrCreateLibraryContainer( false, pImpl->xDialogLibraries, GetModel() );
707 BasicManager* pBasMgr = lcl_getBasicManagerForDocument( *this );
708 if ( pBasMgr )
709 return pBasMgr->GetDialogLibraryContainer().get();
711 catch (const css::ucb::ContentCreationException&)
713 TOOLS_WARN_EXCEPTION("sfx.doc", "");
716 SAL_WARN("sfx.doc", "SfxObjectShell::GetDialogContainer: falling back to the application - is this really expected here?");
717 #endif
718 return SfxGetpApp()->GetDialogContainer();
721 Reference< XLibraryContainer > SfxObjectShell::GetBasicContainer()
723 #if HAVE_FEATURE_SCRIPTING
724 if (!utl::ConfigManager::IsFuzzing())
728 if ( !pImpl->m_bNoBasicCapabilities )
729 return lcl_getOrCreateLibraryContainer( true, pImpl->xBasicLibraries, GetModel() );
731 BasicManager* pBasMgr = lcl_getBasicManagerForDocument( *this );
732 if ( pBasMgr )
733 return pBasMgr->GetScriptLibraryContainer().get();
735 catch (const css::ucb::ContentCreationException&)
737 TOOLS_WARN_EXCEPTION("sfx.doc", "");
740 SAL_WARN("sfx.doc", "SfxObjectShell::GetBasicContainer: falling back to the application - is this really expected here?");
741 #endif
742 return SfxGetpApp()->GetBasicContainer();
745 StarBASIC* SfxObjectShell::GetBasic() const
747 #if !HAVE_FEATURE_SCRIPTING
748 return NULL;
749 #else
750 BasicManager * pMan = GetBasicManager();
751 return pMan ? pMan->GetLib(0) : nullptr;
752 #endif
755 void SfxObjectShell::InitBasicManager_Impl()
756 /* [Description]
758 Creates a document's BasicManager and loads it, if we are already based on
759 a storage.
761 [Note]
763 This method has to be called by implementations of <SvPersist::Load()>
764 (with its pStor parameter) and by implementations of <SvPersist::InitNew()>
765 (with pStor = 0).
769 /* #163556# (DR) - Handling of recursive calls while creating the Basic
770 manager.
772 It is possible that (while creating the Basic manager) the code that
773 imports the Basic storage wants to access the Basic manager again.
774 Especially in VBA compatibility mode, there is code that wants to
775 access the "VBA Globals" object which is stored as global UNO constant
776 in the Basic manager.
778 To achieve correct handling of the recursive calls of this function
779 from lcl_getBasicManagerForDocument(), the implementation of the
780 function BasicManagerRepository::getDocumentBasicManager() has been
781 changed to return the Basic manager currently under construction, when
782 called repeatedly.
784 The variable pImpl->bBasicInitialized will be set to sal_True after
785 construction now, to ensure that the recursive call of the function
786 lcl_getBasicManagerForDocument() will be routed into this function too.
788 Calling BasicManagerHolder::reset() twice is not a big problem, as it
789 does not take ownership but stores only the raw pointer. Owner of all
790 Basic managers is the global BasicManagerRepository instance.
792 #if HAVE_FEATURE_SCRIPTING
793 DBG_ASSERT( !pImpl->bBasicInitialized && !pImpl->aBasicManager.isValid(), "Local BasicManager already exists");
796 pImpl->aBasicManager.reset( BasicManagerRepository::getDocumentBasicManager( GetModel() ) );
798 catch (const css::ucb::ContentCreationException&)
800 TOOLS_WARN_EXCEPTION("sfx.doc", "");
802 DBG_ASSERT( pImpl->aBasicManager.isValid(), "SfxObjectShell::InitBasicManager_Impl: did not get a BasicManager!" );
803 pImpl->bBasicInitialized = true;
804 #endif
808 bool SfxObjectShell::DoClose()
810 return Close();
814 SfxObjectShell* SfxObjectShell::GetObjectShell()
816 return this;
820 uno::Sequence< OUString > SfxObjectShell::GetEventNames()
822 static uno::Sequence< OUString > s_EventNameContainer(rtl::Reference<GlobalEventConfig>(new GlobalEventConfig)->getElementNames());
824 return s_EventNameContainer;
828 css::uno::Reference< css::frame::XModel > SfxObjectShell::GetModel() const
830 return GetBaseModel();
833 void SfxObjectShell::SetBaseModel( SfxBaseModel* pModel )
835 OSL_ENSURE( !pImpl->pBaseModel.is() || pModel == nullptr, "Model already set!" );
836 pImpl->pBaseModel.set( pModel );
837 if ( pImpl->pBaseModel.is() )
839 pImpl->pBaseModel->addCloseListener( new SfxModelListener_Impl(this) );
844 css::uno::Reference< css::frame::XModel > SfxObjectShell::GetBaseModel() const
846 return pImpl->pBaseModel.get();
849 void SfxObjectShell::SetAutoStyleFilterIndex(sal_uInt16 nSet)
851 pImpl->nStyleFilter = nSet;
854 sal_uInt16 SfxObjectShell::GetAutoStyleFilterIndex() const
856 return pImpl->nStyleFilter;
860 void SfxObjectShell::SetCurrentComponent( const Reference< XInterface >& _rxComponent )
862 WeakReference< XInterface >& rTheCurrentComponent = theCurrentComponent::get();
864 Reference< XInterface > xOldCurrentComp(rTheCurrentComponent);
865 if ( _rxComponent == xOldCurrentComp )
866 // nothing to do
867 return;
868 // note that "_rxComponent.get() == s_xCurrentComponent.get().get()" is /sufficient/, but not
869 // /required/ for "_rxComponent == s_xCurrentComponent.get()".
870 // In other words, it's still possible that we here do something which is not necessary,
871 // but we should have filtered quite some unnecessary calls already.
873 #if HAVE_FEATURE_SCRIPTING
874 BasicManager* pAppMgr = SfxApplication::GetBasicManager();
875 rTheCurrentComponent = _rxComponent;
876 if ( !pAppMgr )
877 return;
879 // set "ThisComponent" for Basic
880 pAppMgr->SetGlobalUNOConstant( "ThisComponent", Any( _rxComponent ) );
882 // set new current component for VBA compatibility
883 if ( _rxComponent.is() )
885 OUString aVBAConstName = lclGetVBAGlobalConstName( _rxComponent );
886 if ( !aVBAConstName.isEmpty() )
888 pAppMgr->SetGlobalUNOConstant( aVBAConstName, Any( _rxComponent ) );
889 s_aRegisteredVBAConstants[ _rxComponent.get() ] = aVBAConstName;
892 // no new component passed -> remove last registered VBA component
893 else if ( xOldCurrentComp.is() )
895 OUString aVBAConstName = lclGetVBAGlobalConstName( xOldCurrentComp );
896 if ( !aVBAConstName.isEmpty() )
898 pAppMgr->SetGlobalUNOConstant( aVBAConstName, Any( Reference< XInterface >() ) );
899 s_aRegisteredVBAConstants.erase( xOldCurrentComp.get() );
902 #endif
905 Reference< XInterface > SfxObjectShell::GetCurrentComponent()
907 return theCurrentComponent::get();
911 OUString SfxObjectShell::GetServiceNameFromFactory( const OUString& rFact )
913 //! Remove everything behind name!
914 OUString aFact( rFact );
915 OUString aPrefix("private:factory/");
916 if ( aFact.startsWith( aPrefix ) )
917 aFact = aFact.copy( aPrefix.getLength() );
918 sal_Int32 nPos = aFact.indexOf( '?' );
919 if ( nPos != -1 )
921 aFact = aFact.copy( 0, nPos );
923 aFact = aFact.replaceAll("4", "");
924 aFact = aFact.toAsciiLowerCase();
926 // HACK: sometimes a real document service name is given here instead of
927 // a factory short name. Set return value directly to this service name as fallback
928 // in case next lines of code does nothing ...
929 // use rFact instead of normed aFact value !
930 OUString aServiceName = rFact;
932 if ( aFact == "swriter" )
934 aServiceName = "com.sun.star.text.TextDocument";
936 else if ( aFact == "sweb" || aFact == "swriter/web" )
938 aServiceName = "com.sun.star.text.WebDocument";
940 else if ( aFact == "sglobal" || aFact == "swriter/globaldocument" )
942 aServiceName = "com.sun.star.text.GlobalDocument";
944 else if ( aFact == "scalc" )
946 aServiceName = "com.sun.star.sheet.SpreadsheetDocument";
948 else if ( aFact == "sdraw" )
950 aServiceName = "com.sun.star.drawing.DrawingDocument";
952 else if ( aFact == "simpress" )
954 aServiceName = "com.sun.star.presentation.PresentationDocument";
956 else if ( aFact == "schart" )
958 aServiceName = "com.sun.star.chart.ChartDocument";
960 else if ( aFact == "smath" )
962 aServiceName = "com.sun.star.formula.FormulaProperties";
964 #if HAVE_FEATURE_SCRIPTING
965 else if ( aFact == "sbasic" )
967 aServiceName = "com.sun.star.script.BasicIDE";
969 #endif
970 #if HAVE_FEATURE_DBCONNECTIVITY
971 else if ( aFact == "sdatabase" )
973 aServiceName = "com.sun.star.sdb.OfficeDatabaseDocument";
975 #endif
977 return aServiceName;
980 SfxObjectShell* SfxObjectShell::CreateObjectByFactoryName( const OUString& rFact, SfxObjectCreateMode eMode )
982 return CreateObject( GetServiceNameFromFactory( rFact ), eMode );
986 SfxObjectShell* SfxObjectShell::CreateObject( const OUString& rServiceName, SfxObjectCreateMode eCreateMode )
988 if ( !rServiceName.isEmpty() )
990 uno::Reference < frame::XModel > xDoc( ::comphelper::getProcessServiceFactory()->createInstance( rServiceName ), UNO_QUERY );
991 if (SfxObjectShell* pRet = SfxObjectShell::GetShellFromComponent(xDoc))
993 pRet->SetCreateMode_Impl(eCreateMode);
994 return pRet;
998 return nullptr;
1001 Reference<lang::XComponent> SfxObjectShell::CreateAndLoadComponent( const SfxItemSet& rSet )
1003 uno::Sequence < beans::PropertyValue > aProps;
1004 TransformItems( SID_OPENDOC, rSet, aProps );
1005 const SfxStringItem* pFileNameItem = rSet.GetItem<SfxStringItem>(SID_FILE_NAME, false);
1006 const SfxStringItem* pTargetItem = rSet.GetItem<SfxStringItem>(SID_TARGETNAME, false);
1007 OUString aURL;
1008 OUString aTarget("_blank");
1009 if ( pFileNameItem )
1010 aURL = pFileNameItem->GetValue();
1011 if ( pTargetItem )
1012 aTarget = pTargetItem->GetValue();
1014 uno::Reference < frame::XComponentLoader > xLoader =
1015 frame::Desktop::create(comphelper::getProcessComponentContext());
1017 Reference <lang::XComponent> xComp;
1020 xComp = xLoader->loadComponentFromURL(aURL, aTarget, 0, aProps);
1022 catch (const uno::Exception&)
1026 return xComp;
1029 SfxObjectShell* SfxObjectShell::GetShellFromComponent(const Reference<uno::XInterface>& xComp)
1033 Reference<lang::XUnoTunnel> xTunnel(xComp, UNO_QUERY_THROW);
1034 Sequence <sal_Int8> aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
1035 sal_Int64 nHandle = xTunnel->getSomething( aSeq );
1036 if (nHandle)
1037 return reinterpret_cast<SfxObjectShell*>(sal::static_int_cast<sal_IntPtr>(nHandle));
1039 catch (const Exception&)
1043 return nullptr;
1046 SfxObjectShell* SfxObjectShell::GetParentShell(const css::uno::Reference<css::uno::XInterface>& xChild)
1048 SfxObjectShell* pResult = nullptr;
1052 if (css::uno::Reference<css::container::XChild> xChildModel{ xChild, css::uno::UNO_QUERY })
1053 pResult = GetShellFromComponent(xChildModel->getParent());
1055 catch (const Exception&)
1059 return pResult;
1062 void SfxObjectShell::SetInitialized_Impl( const bool i_fromInitNew )
1064 pImpl->bInitialized = true;
1065 if (utl::ConfigManager::IsFuzzing())
1066 return;
1067 if ( i_fromInitNew )
1069 SetActivateEvent_Impl( SfxEventHintId::CreateDoc );
1070 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::DocCreated, GlobalEventConfig::GetEventName(GlobalEventId::DOCCREATED), this ) );
1072 else
1074 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::LoadFinished, GlobalEventConfig::GetEventName(GlobalEventId::LOADFINISHED), this ) );
1079 bool SfxObjectShell::IsChangeRecording() const
1081 // currently this function needs to be overwritten by Writer and Calc only
1082 SAL_WARN( "sfx.doc", "function not implemented" );
1083 return false;
1087 bool SfxObjectShell::HasChangeRecordProtection() const
1089 // currently this function needs to be overwritten by Writer and Calc only
1090 SAL_WARN( "sfx.doc", "function not implemented" );
1091 return false;
1095 void SfxObjectShell::SetChangeRecording( bool /*bActivate*/, bool /*bLockAllViews*/ )
1097 // currently this function needs to be overwritten by Writer and Calc only
1098 SAL_WARN( "sfx.doc", "function not implemented" );
1102 void SfxObjectShell::SetProtectionPassword( const OUString & /*rPassword*/ )
1104 // currently this function needs to be overwritten by Writer and Calc only
1105 SAL_WARN( "sfx.doc", "function not implemented" );
1109 bool SfxObjectShell::GetProtectionHash( /*out*/ css::uno::Sequence< sal_Int8 > & /*rPasswordHash*/ )
1111 // currently this function needs to be overwritten by Writer and Calc only
1112 SAL_WARN( "sfx.doc", "function not implemented" );
1113 return false;
1116 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */