tdf#130857 qt weld: Support mail merge "Server Auth" dialog
[LibreOffice.git] / sfx2 / source / doc / objxtor.cxx
blobe7f62a14dca2c222eb2d0368754975a5cf5ec619
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>
21 #include <config_fuzzers.h>
23 #include <map>
25 #include <cppuhelper/implbase.hxx>
26 #include <cppuhelper/weakref.hxx>
28 #include <com/sun/star/util/XCloseable.hpp>
29 #include <com/sun/star/frame/XComponentLoader.hpp>
30 #include <com/sun/star/frame/Desktop.hpp>
31 #include <com/sun/star/util/CloseVetoException.hpp>
32 #include <com/sun/star/util/XCloseListener.hpp>
33 #include <com/sun/star/beans/XPropertySet.hpp>
34 #include <com/sun/star/frame/XTitle.hpp>
35 #include <osl/file.hxx>
36 #include <sal/log.hxx>
37 #include <vcl/weld.hxx>
38 #include <vcl/svapp.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/configuration.hxx>
50 #include <comphelper/processfactory.hxx>
51 #include <comphelper/servicehelper.hxx>
53 #include <com/sun/star/document/XStorageBasedDocument.hpp>
54 #include <com/sun/star/script/DocumentDialogLibraryContainer.hpp>
55 #include <com/sun/star/script/DocumentScriptLibraryContainer.hpp>
56 #include <com/sun/star/document/XEmbeddedScripts.hpp>
57 #include <com/sun/star/document/XScriptInvocationContext.hpp>
58 #include <com/sun/star/ucb/ContentCreationException.hpp>
59 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
61 #include <unotools/ucbhelper.hxx>
62 #include <comphelper/diagnose_ex.hxx>
63 #include <tools/globname.hxx>
64 #include <tools/debug.hxx>
66 #include <sfx2/app.hxx>
67 #include <sfx2/bindings.hxx>
68 #include <sfx2/docfile.hxx>
69 #include <sfx2/event.hxx>
70 #include <sfx2/viewsh.hxx>
71 #include <sfx2/viewfrm.hxx>
72 #include <sfx2/sfxresid.hxx>
73 #include <objshimp.hxx>
74 #include <sfx2/strings.hrc>
75 #include <sfx2/sfxsids.hrc>
76 #include <basic/basmgr.hxx>
77 #include <sfx2/QuerySaveDocument.hxx>
78 #include <appbaslib.hxx>
79 #include <sfx2/sfxbasemodel.hxx>
80 #include <sfx2/sfxuno.hxx>
81 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
82 #include <sfx2/infobar.hxx>
83 #include <svtools/svparser.hxx>
85 #include <basic/basicmanagerrepository.hxx>
87 using namespace ::com::sun::star;
88 using namespace ::com::sun::star::uno;
89 using namespace ::com::sun::star::script;
90 using namespace ::com::sun::star::frame;
91 using namespace ::com::sun::star::document;
93 using ::basic::BasicManagerRepository;
95 namespace {
97 WeakReference< XInterface > theCurrentComponent;
99 #if HAVE_FEATURE_SCRIPTING
101 // remember all registered components for VBA compatibility, to be able to remove them on disposing the model
102 typedef ::std::map< XInterface*, OUString > VBAConstantNameMap;
103 VBAConstantNameMap s_aRegisteredVBAConstants;
105 OUString lclGetVBAGlobalConstName( const Reference< XInterface >& rxComponent )
107 OSL_ENSURE( rxComponent.is(), "lclGetVBAGlobalConstName - missing component" );
109 VBAConstantNameMap::iterator aIt = s_aRegisteredVBAConstants.find( rxComponent.get() );
110 if( aIt != s_aRegisteredVBAConstants.end() )
111 return aIt->second;
113 uno::Reference< beans::XPropertySet > xProps( rxComponent, uno::UNO_QUERY );
114 if( xProps.is() ) try
116 OUString aConstName;
117 xProps->getPropertyValue(u"VBAGlobalConstantName"_ustr) >>= aConstName;
118 return aConstName;
120 catch (const uno::Exception&) // not supported
123 return OUString();
126 #endif
128 class SfxModelListener_Impl : public ::cppu::WeakImplHelper< css::util::XCloseListener >
130 SfxObjectShell* mpDoc;
131 public:
132 explicit SfxModelListener_Impl( SfxObjectShell* pDoc ) : mpDoc(pDoc) {};
133 virtual void SAL_CALL queryClosing( const css::lang::EventObject& aEvent, sal_Bool bDeliverOwnership ) override ;
134 virtual void SAL_CALL notifyClosing( const css::lang::EventObject& aEvent ) override ;
135 virtual void SAL_CALL disposing( const css::lang::EventObject& aEvent ) override ;
139 } // namespace
141 void SAL_CALL SfxModelListener_Impl::queryClosing( const css::lang::EventObject& , sal_Bool bDeliverOwnership)
143 if (mpDoc->Get_Impl()->m_nClosingLockLevel)
145 if (bDeliverOwnership)
146 mpDoc->Get_Impl()->m_bCloseModelScheduled = true;
147 throw util::CloseVetoException(u"Closing document is blocked"_ustr, getXWeak());
151 void SAL_CALL SfxModelListener_Impl::notifyClosing( const css::lang::EventObject& )
153 SolarMutexGuard aSolarGuard;
154 mpDoc->Broadcast( SfxHint(SfxHintId::Deinitializing) );
157 void SAL_CALL SfxModelListener_Impl::disposing( const css::lang::EventObject& _rEvent )
159 // am I ThisComponent in AppBasic?
160 SolarMutexGuard aSolarGuard;
161 if ( SfxObjectShell::GetCurrentComponent() == _rEvent.Source )
163 // remove ThisComponent reference from AppBasic
164 SfxObjectShell::SetCurrentComponent( Reference< XInterface >() );
167 #if HAVE_FEATURE_SCRIPTING
168 /* Remove VBA component from AppBasic. As every application registers its
169 own current component, the disposed component may not be the "current
170 component" of the SfxObjectShell. */
171 if ( _rEvent.Source.is() )
173 VBAConstantNameMap::iterator aIt = s_aRegisteredVBAConstants.find( _rEvent.Source.get() );
174 if ( aIt != s_aRegisteredVBAConstants.end() )
176 if ( BasicManager* pAppMgr = SfxApplication::GetBasicManager() )
177 pAppMgr->SetGlobalUNOConstant( aIt->second, Any( Reference< XInterface >() ) );
178 s_aRegisteredVBAConstants.erase( aIt );
181 #endif
183 if ( !mpDoc->Get_Impl()->bClosing )
184 // GCC crashes when already in the destructor, so first query the Flag
185 mpDoc->DoClose();
189 SfxObjectShell_Impl::SfxObjectShell_Impl( SfxObjectShell& _rDocShell )
190 :rDocShell( _rDocShell )
191 ,aMacroMode( *this )
192 ,pProgress( nullptr)
193 ,nTime( DateTime::SYSTEM )
194 ,nVisualDocumentNumber( USHRT_MAX)
195 ,nDocumentSignatureState( SignatureState::UNKNOWN )
196 ,nScriptingSignatureState( SignatureState::UNKNOWN )
197 ,bClosing( false)
198 ,bIsSaving( false)
199 ,bIsNamedVisible( false)
200 ,bIsAbortingImport ( false)
201 ,bInPrepareClose( false )
202 ,bPreparedForClose( false )
203 ,bForbidReload( false )
204 ,bBasicInitialized( false )
205 ,bIsPrintJobCancelable( true )
206 ,bOwnsStorage( true )
207 ,bInitialized( false )
208 ,bModelInitialized( false )
209 ,bPreserveVersions( true )
210 ,m_bMacroSignBroken( false )
211 ,m_bNoBasicCapabilities( false )
212 ,m_bDocRecoverySupport( true )
213 ,bQueryLoadTemplate( true )
214 ,bLoadReadonly( false )
215 ,bUseUserData( true )
216 ,bUseThumbnailSave( true )
217 ,bSaveVersionOnClose( false )
218 ,m_bSharedXMLFlag( false )
219 ,m_bAllowShareControlFileClean( true )
220 ,m_bConfigOptionsChecked( false )
221 ,m_bMacroCallsSeenWhileLoading( false )
222 ,m_bHadCheckedMacrosOnLoad( false )
223 ,lErr(ERRCODE_NONE)
224 ,nEventId ( SfxEventHintId::NONE )
225 ,nLoadedFlags ( SfxLoadedFlags::ALL )
226 ,nFlagsInProgress( SfxLoadedFlags::NONE )
227 ,bModalMode( false )
228 ,bRunningMacro( false )
229 ,bReadOnlyUI( false )
230 ,nStyleFilter( 0 )
231 ,m_bEnableSetModified( true )
232 ,m_bIsModified( false )
233 ,m_nMapUnit( MapUnit::Map100thMM )
234 ,m_bCreateTempStor( false )
235 ,m_bIsInit( false )
236 ,m_bIncomplEncrWarnShown( false )
237 ,m_nModifyPasswordHash( 0 )
238 ,m_bModifyPasswordEntered( false )
239 ,m_bSavingForSigning( false )
240 ,m_bAllowModifiedBackAfterSigning( false )
242 SfxObjectShell* pDoc = &_rDocShell;
243 std::vector<SfxObjectShell*> &rArr = SfxGetpApp()->GetObjectShells_Impl();
244 rArr.push_back( pDoc );
248 SfxObjectShell_Impl::~SfxObjectShell_Impl()
253 SfxObjectShell::SfxObjectShell( const SfxModelFlags i_nCreationFlags )
254 : pImpl(new SfxObjectShell_Impl(*this))
255 , pMedium(nullptr)
256 , eCreateMode(SfxObjectCreateMode::STANDARD)
257 , bHasName(false)
258 , bIsInGenerateThumbnail (false)
259 , mbAvoidRecentDocs(false)
260 , bRememberSignature(false)
262 if (i_nCreationFlags & SfxModelFlags::EMBEDDED_OBJECT)
263 eCreateMode = SfxObjectCreateMode::EMBEDDED;
264 else if (i_nCreationFlags & SfxModelFlags::EXTERNAL_LINK)
265 eCreateMode = SfxObjectCreateMode::INTERNAL;
267 const bool bScriptSupport = ( i_nCreationFlags & SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS ) == SfxModelFlags::NONE;
268 if ( !bScriptSupport )
269 pImpl->m_bNoBasicCapabilities = true;
271 const bool bDocRecovery = ( i_nCreationFlags & SfxModelFlags::DISABLE_DOCUMENT_RECOVERY ) == SfxModelFlags::NONE;
272 if ( !bDocRecovery )
273 pImpl->m_bDocRecoverySupport = false;
276 /** Constructor of the class SfxObjectShell.
278 @param eMode Purpose, to which the SfxObjectShell is created:
279 SfxObjectCreateMode::EMBEDDED (default) as SO-Server from within another Document
280 SfxObjectCreateMode::STANDARD, as a normal Document open stand-alone
281 SfxObjectCreateMode::ORGANIZER to be displayed in the Organizer, here nothing of the contents is used
283 SfxObjectShell::SfxObjectShell(SfxObjectCreateMode eMode)
284 : pImpl(new SfxObjectShell_Impl(*this))
285 , pMedium(nullptr)
286 , eCreateMode(eMode)
287 , bHasName(false)
288 , bIsInGenerateThumbnail(false)
289 , mbAvoidRecentDocs(false)
290 , bRememberSignature(false)
294 SfxObjectShell::~SfxObjectShell()
297 if ( IsEnableSetModified() )
298 EnableSetModified( false );
300 SfxObjectShell::CloseInternal();
301 pImpl->pBaseModel.clear();
303 pImpl->pReloadTimer.reset();
305 SfxApplication *pSfxApp = SfxGetpApp();
306 if ( USHRT_MAX != pImpl->nVisualDocumentNumber && pSfxApp )
307 pSfxApp->ReleaseIndex(pImpl->nVisualDocumentNumber);
309 // Destroy Basic-Manager
310 pImpl->aBasicManager.reset(nullptr);
312 if ( pSfxApp && pSfxApp->GetDdeService() )
313 pSfxApp->RemoveDdeTopic( this );
315 InternalCloseAndRemoveFiles();
318 void SfxObjectShell::InternalCloseAndRemoveFiles()
320 // don't call GetStorage() here, in case of Load Failure it's possible that a storage was never assigned!
321 if ( pMedium && pMedium->HasStorage_Impl() && pMedium->GetStorage( false ) == pImpl->m_xDocStorage )
322 pMedium->CanDisposeStorage_Impl( false );
324 if ( pImpl->mxObjectContainer )
326 pImpl->mxObjectContainer->CloseEmbeddedObjects();
327 pImpl->mxObjectContainer.reset();
330 if ( pImpl->bOwnsStorage && pImpl->m_xDocStorage.is() )
331 pImpl->m_xDocStorage->dispose();
333 if ( pMedium )
335 pMedium->CloseAndReleaseStreams_Impl();
337 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
338 if (IsDocShared())
339 FreeSharedFile( pMedium->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
340 #endif
341 delete pMedium;
342 pMedium = nullptr;
345 // The removing of the temporary file must be done as the latest step in the document destruction
346 if ( !pImpl->aTempName.isEmpty() )
348 OUString aTmp;
349 osl::FileBase::getFileURLFromSystemPath( pImpl->aTempName, aTmp );
350 ::utl::UCBContentHelper::Kill( aTmp );
354 SfxCloseVetoLock::SfxCloseVetoLock(const SfxObjectShell* pDocShell)
355 : mpDocShell(pDocShell)
357 if (mpDocShell)
358 osl_atomic_increment(&mpDocShell->Get_Impl()->m_nClosingLockLevel);
361 SfxCloseVetoLock::~SfxCloseVetoLock()
363 if (mpDocShell && osl_atomic_decrement(&mpDocShell->Get_Impl()->m_nClosingLockLevel) == 0)
365 if (mpDocShell->Get_Impl()->m_bCloseModelScheduled)
367 mpDocShell->Get_Impl()->m_bCloseModelScheduled = false; // pass ownership
368 if (rtl::Reference model = static_cast<SfxBaseModel*>(mpDocShell->GetBaseModel().get()))
372 model->close(true);
374 catch (const util::CloseVetoException&)
376 DBG_UNHANDLED_EXCEPTION("sfx.doc");
383 void SfxObjectShell::Stamp_SetPrintCancelState(bool bState)
385 pImpl->bIsPrintJobCancelable = bState;
389 bool SfxObjectShell::Stamp_GetPrintCancelState() const
391 return pImpl->bIsPrintJobCancelable;
395 // closes the Object and all its views
397 bool SfxObjectShell::Close()
399 SfxObjectShellRef xKeepAlive(this);
400 return CloseInternal();
403 // variant that does not take a reference to itself, so we can call it during object destruction
404 bool SfxObjectShell::CloseInternal()
406 if ( !pImpl->bClosing )
408 // Do not close if a progress is still running
409 if ( GetProgress() )
410 return false;
412 pImpl->bClosing = true;
413 Reference< util::XCloseable > xCloseable( GetBaseModel(), UNO_QUERY );
415 if ( xCloseable.is() )
419 xCloseable->close( true );
421 catch (const Exception&)
423 pImpl->bClosing = false;
427 if ( pImpl->bClosing )
429 // remove from Document list
430 // If there is no App, there is no document to remove
431 // no need to call GetOrCreate here
432 SfxApplication *pSfxApp = SfxApplication::Get();
433 if(pSfxApp)
435 std::vector<SfxObjectShell*> &rDocs = pSfxApp->GetObjectShells_Impl();
436 auto it = std::find( rDocs.begin(), rDocs.end(), this );
437 if ( it != rDocs.end() )
438 rDocs.erase( it );
443 return true;
446 OUString SfxObjectShell::CreateShellID( const SfxObjectShell* pShell )
448 if (!pShell)
449 return OUString();
451 OUString aShellID;
453 SfxMedium* pMedium = pShell->GetMedium();
454 if (pMedium)
455 aShellID = pMedium->GetBaseURL();
457 if (!aShellID.isEmpty())
458 return aShellID;
460 sal_Int64 nShellID = reinterpret_cast<sal_Int64>(pShell);
461 aShellID = "0x" + OUString::number(nShellID, 16);
462 return aShellID;
465 // returns a pointer the first SfxDocument of specified type
467 SfxObjectShell* SfxObjectShell::GetFirst
469 const std::function<bool ( const SfxObjectShell* )>& isObjectShell,
470 bool bOnlyVisible
473 std::vector<SfxObjectShell*> &rDocs = SfxGetpApp()->GetObjectShells_Impl();
475 // search for a SfxDocument of the specified type
476 for (SfxObjectShell* pSh : rDocs)
478 if ( bOnlyVisible && pSh->IsPreview() && pSh->IsReadOnly() )
479 continue;
481 if ( (!isObjectShell || isObjectShell( pSh)) &&
482 ( !bOnlyVisible || SfxViewFrame::GetFirst( pSh )))
483 return pSh;
486 return nullptr;
490 // returns a pointer to the next SfxDocument of specified type behind *pDoc
492 SfxObjectShell* SfxObjectShell::GetNext
494 const SfxObjectShell& rPrev,
495 const std::function<bool ( const SfxObjectShell* )>& isObjectShell,
496 bool bOnlyVisible
499 std::vector<SfxObjectShell*> &rDocs = SfxGetpApp()->GetObjectShells_Impl();
501 // refind the specified predecessor
502 size_t nPos;
503 for ( nPos = 0; nPos < rDocs.size(); ++nPos )
504 if ( rDocs[nPos] == &rPrev )
505 break;
507 // search for the next SfxDocument of the specified type
508 for ( ++nPos; nPos < rDocs.size(); ++nPos )
510 SfxObjectShell* pSh = rDocs[ nPos ];
511 if ( bOnlyVisible && pSh->IsPreview() && pSh->IsReadOnly() )
512 continue;
514 if ( (!isObjectShell || isObjectShell( pSh)) &&
515 ( !bOnlyVisible || SfxViewFrame::GetFirst( pSh )))
516 return pSh;
518 return nullptr;
521 SfxObjectShell* SfxObjectShell::Current()
523 SfxViewFrame *pFrame = SfxViewFrame::Current();
524 return pFrame ? pFrame->GetObjectShell() : nullptr;
527 bool SfxObjectShell::IsInPrepareClose() const
529 return pImpl->bInPrepareClose;
532 namespace {
534 struct BoolEnv_Impl
536 SfxObjectShell_Impl& rImpl;
537 explicit BoolEnv_Impl( SfxObjectShell_Impl& rImplP) : rImpl( rImplP )
538 { rImplP.bInPrepareClose = true; }
539 ~BoolEnv_Impl() { rImpl.bInPrepareClose = false; }
544 bool SfxObjectShell::PrepareClose
546 bool bUI // true: Dialog and so on is allowed
547 // false: silent-mode
550 if( pImpl->bInPrepareClose || pImpl->bPreparedForClose )
551 return true;
552 BoolEnv_Impl aBoolEnv( *pImpl );
554 // DocModalDialog?
555 if ( IsInModalMode() )
556 return false;
558 SfxViewFrame* pFirst = SfxViewFrame::GetFirst( this );
559 if( pFirst && !pFirst->GetFrame().PrepareClose_Impl( bUI ) )
560 return false;
562 // prepare views for closing
563 for ( SfxViewFrame* pFrm = SfxViewFrame::GetFirst( this );
564 pFrm; pFrm = SfxViewFrame::GetNext( *pFrm, this ) )
566 DBG_ASSERT(pFrm->GetViewShell(),"No Shell");
567 if ( pFrm->GetViewShell() )
569 bool bRet = pFrm->GetViewShell()->PrepareClose( bUI );
570 if ( !bRet )
571 return bRet;
575 SfxApplication *pSfxApp = SfxGetpApp();
576 pSfxApp->NotifyEvent( SfxEventHint(SfxEventHintId::PrepareCloseDoc, GlobalEventConfig::GetEventName(GlobalEventId::PREPARECLOSEDOC), this) );
578 if( GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
580 pImpl->bPreparedForClose = true;
581 return true;
584 // Ask if possible if it should be saved
585 // only ask for the Document in the visible window
586 SfxViewFrame *pFrame = SfxObjectShell::Current() == this
587 ? SfxViewFrame::Current() : SfxViewFrame::GetFirst( this );
589 if ( bUI && IsModified() && pFrame )
591 // restore minimized
592 SfxFrame& rTop = pFrame->GetFrame();
593 SfxViewFrame::SetViewFrame( rTop.GetCurrentViewFrame() );
594 pFrame->GetFrame().Appear();
596 // Ask if to save
597 short nRet = RET_YES;
599 const Reference<XTitle> xTitle(*pImpl->pBaseModel, UNO_QUERY_THROW);
600 const OUString sTitle = xTitle->getTitle ();
601 nRet = ExecuteQuerySaveDocument(pFrame->GetFrameWeld(), sTitle);
603 /*HACK for plugin::destroy()*/
605 if ( RET_YES == nRet )
607 // Save by each Dispatcher
608 SfxPoolItemHolder aPoolItem;
609 if (IsReadOnly())
611 SfxBoolItem aWarnItem( SID_FAIL_ON_WARNING, bUI );
612 const SfxPoolItem* ppArgs[] = { &aWarnItem, nullptr };
613 aPoolItem = pFrame->GetBindings().ExecuteSynchron(SID_SAVEASDOC, ppArgs);
615 else if (IsSaveVersionOnClose())
617 SfxStringItem aItem( SID_DOCINFO_COMMENTS, SfxResId(STR_AUTOMATICVERSION) );
618 SfxBoolItem aWarnItem( SID_FAIL_ON_WARNING, bUI );
619 const SfxPoolItem* ppArgs[] = { &aItem, &aWarnItem, nullptr };
620 aPoolItem = pFrame->GetBindings().ExecuteSynchron( SID_SAVEDOC, ppArgs );
622 else
624 SfxBoolItem aWarnItem( SID_FAIL_ON_WARNING, bUI );
625 const SfxPoolItem* ppArgs[] = { &aWarnItem, nullptr };
626 aPoolItem = pFrame->GetBindings().ExecuteSynchron( SID_SAVEDOC, ppArgs );
629 if (!aPoolItem || IsDisabledItem(aPoolItem.getItem()) )
630 return false;
631 if ( auto pBoolItem = dynamic_cast< const SfxBoolItem *>( aPoolItem.getItem() ) )
632 if ( !pBoolItem->GetValue() )
633 return false;
635 else if ( RET_CANCEL == nRet )
636 // Cancelled
637 return false;
640 if ( pFrame )
641 sfx2::SfxNotebookBar::CloseMethod(pFrame->GetBindings());
642 pImpl->bPreparedForClose = true;
643 return true;
647 #if HAVE_FEATURE_SCRIPTING
648 namespace
650 BasicManager* lcl_getBasicManagerForDocument( const SfxObjectShell& _rDocument )
652 if ( !_rDocument.Get_Impl()->m_bNoBasicCapabilities )
654 if ( !_rDocument.Get_Impl()->bBasicInitialized )
655 const_cast< SfxObjectShell& >( _rDocument ).InitBasicManager_Impl();
656 return _rDocument.Get_Impl()->aBasicManager.get();
659 // assume we do not have Basic ourself, but we can refer to another
660 // document which does (by our model's XScriptInvocationContext::getScriptContainer).
661 // In this case, we return the BasicManager of this other document.
663 OSL_ENSURE( !Reference< XEmbeddedScripts >( _rDocument.GetModel(), UNO_QUERY ).is(),
664 "lcl_getBasicManagerForDocument: inconsistency: no Basic, but an XEmbeddedScripts?" );
665 Reference< XModel > xForeignDocument;
666 Reference< XScriptInvocationContext > xContext( _rDocument.GetModel(), UNO_QUERY );
667 if ( xContext.is() )
669 xForeignDocument.set( xContext->getScriptContainer(), UNO_QUERY );
670 OSL_ENSURE( xForeignDocument.is() && xForeignDocument != _rDocument.GetModel(),
671 "lcl_getBasicManagerForDocument: no Basic, but providing ourself as script container?" );
674 BasicManager* pBasMgr = nullptr;
675 if ( xForeignDocument.is() )
676 pBasMgr = ::basic::BasicManagerRepository::getDocumentBasicManager( xForeignDocument );
678 return pBasMgr;
681 #endif
683 BasicManager* SfxObjectShell::GetBasicManager() const
685 BasicManager* pBasMgr = nullptr;
686 #if HAVE_FEATURE_SCRIPTING
689 pBasMgr = lcl_getBasicManagerForDocument( *this );
690 if ( !pBasMgr )
691 pBasMgr = SfxApplication::GetBasicManager();
693 catch (const css::ucb::ContentCreationException&)
695 TOOLS_WARN_EXCEPTION("sfx.doc", "");
697 #endif
698 return pBasMgr;
701 bool SfxObjectShell::HasBasic() const
703 #if !HAVE_FEATURE_SCRIPTING
704 return false;
705 #else
706 if ( pImpl->m_bNoBasicCapabilities )
707 return false;
709 if ( !pImpl->bBasicInitialized )
710 const_cast< SfxObjectShell* >( this )->InitBasicManager_Impl();
712 return pImpl->aBasicManager.isValid();
713 #endif
717 #if HAVE_FEATURE_SCRIPTING
718 namespace
720 const Reference< XLibraryContainer >&
721 lcl_getOrCreateLibraryContainer( bool _bScript, Reference< XLibraryContainer >& _rxContainer,
722 const Reference< XModel >& _rxDocument )
724 if ( !_rxContainer.is() )
728 Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY );
729 const Reference< XComponentContext >& xContext(
730 ::comphelper::getProcessComponentContext() );
731 _rxContainer.set ( _bScript
732 ? DocumentScriptLibraryContainer::create(
733 xContext, xStorageDoc )
734 : DocumentDialogLibraryContainer::create(
735 xContext, xStorageDoc )
736 , UNO_QUERY_THROW );
738 catch (const Exception&)
740 DBG_UNHANDLED_EXCEPTION("sfx.doc");
743 return _rxContainer;
746 #endif
748 Reference< XLibraryContainer > SfxObjectShell::GetDialogContainer()
750 #if HAVE_FEATURE_SCRIPTING
753 if ( !pImpl->m_bNoBasicCapabilities )
754 return lcl_getOrCreateLibraryContainer( false, pImpl->xDialogLibraries, GetModel() );
756 BasicManager* pBasMgr = lcl_getBasicManagerForDocument( *this );
757 if ( pBasMgr )
758 return pBasMgr->GetDialogLibraryContainer();
760 catch (const css::ucb::ContentCreationException&)
762 TOOLS_WARN_EXCEPTION("sfx.doc", "");
765 SAL_WARN("sfx.doc", "SfxObjectShell::GetDialogContainer: falling back to the application - is this really expected here?");
766 #endif
767 return SfxGetpApp()->GetDialogContainer();
770 Reference< XLibraryContainer > SfxObjectShell::GetBasicContainer()
772 #if HAVE_FEATURE_SCRIPTING
773 if (!comphelper::IsFuzzing())
777 if ( !pImpl->m_bNoBasicCapabilities )
778 return lcl_getOrCreateLibraryContainer( true, pImpl->xBasicLibraries, GetModel() );
780 BasicManager* pBasMgr = lcl_getBasicManagerForDocument( *this );
781 if ( pBasMgr )
782 return pBasMgr->GetScriptLibraryContainer();
784 catch (const css::ucb::ContentCreationException&)
786 TOOLS_WARN_EXCEPTION("sfx.doc", "");
789 SAL_WARN("sfx.doc", "SfxObjectShell::GetBasicContainer: falling back to the application - is this really expected here?");
790 #endif
791 return SfxGetpApp()->GetBasicContainer();
794 StarBASIC* SfxObjectShell::GetBasic() const
796 #if !HAVE_FEATURE_SCRIPTING
797 return nullptr;
798 #else
799 BasicManager * pMan = GetBasicManager();
800 return pMan ? pMan->GetLib(0) : nullptr;
801 #endif
804 void SfxObjectShell::InitBasicManager_Impl()
805 /* [Description]
807 Creates a document's BasicManager and loads it, if we are already based on
808 a storage.
810 [Note]
812 This method has to be called by implementations of <SvPersist::Load()>
813 (with its pStor parameter) and by implementations of <SvPersist::InitNew()>
814 (with pStor = 0).
818 /* #163556# (DR) - Handling of recursive calls while creating the Basic
819 manager.
821 It is possible that (while creating the Basic manager) the code that
822 imports the Basic storage wants to access the Basic manager again.
823 Especially in VBA compatibility mode, there is code that wants to
824 access the "VBA Globals" object which is stored as global UNO constant
825 in the Basic manager.
827 To achieve correct handling of the recursive calls of this function
828 from lcl_getBasicManagerForDocument(), the implementation of the
829 function BasicManagerRepository::getDocumentBasicManager() has been
830 changed to return the Basic manager currently under construction, when
831 called repeatedly.
833 The variable pImpl->bBasicInitialized will be set to sal_True after
834 construction now, to ensure that the recursive call of the function
835 lcl_getBasicManagerForDocument() will be routed into this function too.
837 Calling BasicManagerHolder::reset() twice is not a big problem, as it
838 does not take ownership but stores only the raw pointer. Owner of all
839 Basic managers is the global BasicManagerRepository instance.
841 #if HAVE_FEATURE_SCRIPTING
842 DBG_ASSERT( !pImpl->bBasicInitialized && !pImpl->aBasicManager.isValid(), "Local BasicManager already exists");
845 pImpl->aBasicManager.reset( BasicManagerRepository::getDocumentBasicManager( GetModel() ) );
847 catch (const css::ucb::ContentCreationException&)
849 TOOLS_WARN_EXCEPTION("sfx.doc", "");
851 DBG_ASSERT( pImpl->aBasicManager.isValid(), "SfxObjectShell::InitBasicManager_Impl: did not get a BasicManager!" );
852 pImpl->bBasicInitialized = true;
853 #endif
857 bool SfxObjectShell::DoClose()
859 return Close();
863 SfxObjectShell* SfxObjectShell::GetObjectShell()
865 return this;
869 uno::Sequence< OUString > SfxObjectShell::GetEventNames()
871 static uno::Sequence< OUString > s_EventNameContainer(rtl::Reference<GlobalEventConfig>(new GlobalEventConfig)->getElementNames());
873 return s_EventNameContainer;
877 css::uno::Reference< css::frame::XModel3 > SfxObjectShell::GetModel() const
879 return GetBaseModel();
882 void SfxObjectShell::SetBaseModel( SfxBaseModel* pModel )
884 OSL_ENSURE( !pImpl->pBaseModel.is() || pModel == nullptr, "Model already set!" );
885 pImpl->pBaseModel.set( pModel );
886 if ( pImpl->pBaseModel.is() )
888 pImpl->pBaseModel->addCloseListener( new SfxModelListener_Impl(this) );
893 css::uno::Reference< css::frame::XModel3 > SfxObjectShell::GetBaseModel() const
895 return pImpl->pBaseModel;
898 void SfxObjectShell::SetAutoStyleFilterIndex(sal_uInt16 nSet)
900 pImpl->nStyleFilter = nSet;
903 sal_uInt16 SfxObjectShell::GetAutoStyleFilterIndex() const
905 return pImpl->nStyleFilter;
909 void SfxObjectShell::SetCurrentComponent( const Reference< XInterface >& _rxComponent )
911 WeakReference< XInterface >& rTheCurrentComponent = theCurrentComponent;
913 Reference< XInterface > xOldCurrentComp(rTheCurrentComponent);
914 if ( _rxComponent == xOldCurrentComp )
915 // nothing to do
916 return;
917 // note that "_rxComponent.get() == s_xCurrentComponent.get().get()" is /sufficient/, but not
918 // /required/ for "_rxComponent == s_xCurrentComponent.get()".
919 // In other words, it's still possible that we here do something which is not necessary,
920 // but we should have filtered quite some unnecessary calls already.
922 #if HAVE_FEATURE_SCRIPTING
923 BasicManager* pAppMgr = SfxApplication::GetBasicManager();
924 rTheCurrentComponent = _rxComponent;
925 if ( !pAppMgr )
926 return;
928 // set "ThisComponent" for Basic
929 pAppMgr->SetGlobalUNOConstant( u"ThisComponent"_ustr, Any( _rxComponent ) );
931 // set new current component for VBA compatibility
932 if ( _rxComponent.is() )
934 OUString aVBAConstName = lclGetVBAGlobalConstName( _rxComponent );
935 if ( !aVBAConstName.isEmpty() )
937 pAppMgr->SetGlobalUNOConstant( aVBAConstName, Any( _rxComponent ) );
938 s_aRegisteredVBAConstants[ _rxComponent.get() ] = aVBAConstName;
941 // no new component passed -> remove last registered VBA component
942 else if ( xOldCurrentComp.is() )
944 OUString aVBAConstName = lclGetVBAGlobalConstName( xOldCurrentComp );
945 if ( !aVBAConstName.isEmpty() )
947 pAppMgr->SetGlobalUNOConstant( aVBAConstName, Any( Reference< XInterface >() ) );
948 s_aRegisteredVBAConstants.erase( xOldCurrentComp.get() );
951 #endif
954 Reference< XInterface > SfxObjectShell::GetCurrentComponent()
956 return theCurrentComponent;
960 OUString SfxObjectShell::GetServiceNameFromFactory( const OUString& rFact )
962 //! Remove everything behind name!
963 OUString aFact( rFact );
964 OUString aPrefix(u"private:factory/"_ustr);
965 if ( aFact.startsWith( aPrefix ) )
966 aFact = aFact.copy( aPrefix.getLength() );
967 sal_Int32 nPos = aFact.indexOf( '?' );
968 if ( nPos != -1 )
970 aFact = aFact.copy( 0, nPos );
972 aFact = aFact.replaceAll("4", "");
973 aFact = aFact.toAsciiLowerCase();
975 // HACK: sometimes a real document service name is given here instead of
976 // a factory short name. Set return value directly to this service name as fallback
977 // in case next lines of code does nothing ...
978 // use rFact instead of normed aFact value !
979 OUString aServiceName = rFact;
981 if ( aFact == "swriter" )
983 aServiceName = "com.sun.star.text.TextDocument";
985 else if ( aFact == "sweb" || aFact == "swriter/web" )
987 aServiceName = "com.sun.star.text.WebDocument";
989 else if ( aFact == "sglobal" || aFact == "swriter/globaldocument" )
991 aServiceName = "com.sun.star.text.GlobalDocument";
993 else if ( aFact == "scalc" )
995 aServiceName = "com.sun.star.sheet.SpreadsheetDocument";
997 else if ( aFact == "sdraw" )
999 aServiceName = "com.sun.star.drawing.DrawingDocument";
1001 else if ( aFact == "simpress" )
1003 aServiceName = "com.sun.star.presentation.PresentationDocument";
1005 else if ( aFact == "schart" )
1007 aServiceName = "com.sun.star.chart.ChartDocument";
1009 else if ( aFact == "smath" )
1011 aServiceName = "com.sun.star.formula.FormulaProperties";
1013 #if HAVE_FEATURE_SCRIPTING
1014 else if ( aFact == "sbasic" )
1016 aServiceName = "com.sun.star.script.BasicIDE";
1018 #endif
1019 #if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS
1020 else if ( aFact == "sdatabase" )
1022 aServiceName = "com.sun.star.sdb.OfficeDatabaseDocument";
1024 #endif
1026 return aServiceName;
1029 SfxObjectShell* SfxObjectShell::CreateObjectByFactoryName( const OUString& rFact, SfxObjectCreateMode eMode )
1031 return CreateObject( GetServiceNameFromFactory( rFact ), eMode );
1035 SfxObjectShell* SfxObjectShell::CreateObject( const OUString& rServiceName, SfxObjectCreateMode eCreateMode )
1037 if ( !rServiceName.isEmpty() )
1039 uno::Reference < frame::XModel > xDoc( ::comphelper::getProcessServiceFactory()->createInstance( rServiceName ), UNO_QUERY );
1040 if (SfxObjectShell* pRet = SfxObjectShell::GetShellFromComponent(xDoc))
1042 pRet->SetCreateMode_Impl(eCreateMode);
1043 return pRet;
1047 return nullptr;
1050 Reference<lang::XComponent> SfxObjectShell::CreateAndLoadComponent( const SfxItemSet& rSet )
1052 uno::Sequence < beans::PropertyValue > aProps;
1053 TransformItems( SID_OPENDOC, rSet, aProps );
1054 const SfxStringItem* pFileNameItem = rSet.GetItem<SfxStringItem>(SID_FILE_NAME, false);
1055 const SfxStringItem* pTargetItem = rSet.GetItem<SfxStringItem>(SID_TARGETNAME, false);
1056 OUString aURL;
1057 OUString aTarget(u"_blank"_ustr);
1058 if ( pFileNameItem )
1059 aURL = pFileNameItem->GetValue();
1060 if ( pTargetItem )
1061 aTarget = pTargetItem->GetValue();
1063 uno::Reference < frame::XComponentLoader > xLoader =
1064 frame::Desktop::create(comphelper::getProcessComponentContext());
1066 Reference <lang::XComponent> xComp;
1069 xComp = xLoader->loadComponentFromURL(aURL, aTarget, 0, aProps);
1071 catch (const uno::Exception&)
1075 return xComp;
1078 SfxObjectShell* SfxObjectShell::GetShellFromComponent(const Reference<uno::XInterface>& xComp)
1082 Reference<lang::XUnoTunnel> xTunnel(xComp, UNO_QUERY);
1083 if (!xTunnel)
1084 return nullptr;
1085 static const Sequence <sal_Int8> aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
1086 return comphelper::getSomething_cast<SfxObjectShell>(xTunnel->getSomething(aSeq));
1088 catch (const Exception&)
1092 return nullptr;
1095 SfxObjectShell* SfxObjectShell::GetParentShell(const css::uno::Reference<css::uno::XInterface>& xChild)
1097 SfxObjectShell* pResult = nullptr;
1101 if (css::uno::Reference<css::container::XChild> xChildModel{ xChild, css::uno::UNO_QUERY })
1102 pResult = GetShellFromComponent(xChildModel->getParent());
1104 catch (const Exception&)
1108 return pResult;
1111 void SfxObjectShell::SetInitialized_Impl( const bool i_fromInitNew )
1113 pImpl->bInitialized = true;
1114 if (comphelper::IsFuzzing())
1115 return;
1116 if ( i_fromInitNew )
1118 SetActivateEvent_Impl( SfxEventHintId::CreateDoc );
1119 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::DocCreated, GlobalEventConfig::GetEventName(GlobalEventId::DOCCREATED), this ) );
1121 else
1123 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::LoadFinished, GlobalEventConfig::GetEventName(GlobalEventId::LOADFINISHED), this ) );
1128 bool SfxObjectShell::IsChangeRecording() const
1130 // currently this function needs to be overwritten by Writer and Calc only
1131 SAL_WARN( "sfx.doc", "function not implemented" );
1132 return false;
1136 bool SfxObjectShell::HasChangeRecordProtection() const
1138 // currently this function needs to be overwritten by Writer and Calc only
1139 SAL_WARN( "sfx.doc", "function not implemented" );
1140 return false;
1144 void SfxObjectShell::SetChangeRecording( bool /*bActivate*/, bool /*bLockAllViews*/ )
1146 // currently this function needs to be overwritten by Writer and Calc only
1147 SAL_WARN( "sfx.doc", "function not implemented" );
1151 void SfxObjectShell::SetProtectionPassword( const OUString & /*rPassword*/ )
1153 // currently this function needs to be overwritten by Writer and Calc only
1154 SAL_WARN( "sfx.doc", "function not implemented" );
1158 bool SfxObjectShell::GetProtectionHash( /*out*/ css::uno::Sequence< sal_Int8 > & /*rPasswordHash*/ )
1160 // currently this function needs to be overwritten by Writer and Calc only
1161 SAL_WARN( "sfx.doc", "function not implemented" );
1162 return false;
1165 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */