1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20 #include <config_features.h>
21
22 #include <arrdecl.hxx>
23 #include <map>
24
25 #include <cppuhelper/implbase.hxx>
26 #include <cppuhelper/weakref.hxx>
27
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/XCloseBroadcaster.hpp>
32 #include <com/sun/star/util/XCloseListener.hpp>
33 #include <com/sun/star/util/XModifyBroadcaster.hpp>
34 #include <com/sun/star/beans/XPropertySet.hpp>
35 #include <com/sun/star/frame/XTitle.hpp>
36 #include <osl/file.hxx>
37 #include <rtl/instance.hxx>
38 #include <sal/log.hxx>
39 #include <vcl/weld.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/window.hxx>
42 #include <svl/eitem.hxx>
43 #include <svl/lstner.hxx>
44 #include <sfx2/sfxhelp.hxx>
45 #include <basic/sbstar.hxx>
46 #include <svl/stritem.hxx>
47 #include <basic/sbx.hxx>
48 #include <unotools/configmgr.hxx>
49 #include <unotools/eventcfg.hxx>
50
51 #include <sfx2/objsh.hxx>
52 #include <sfx2/signaturestate.hxx>
53 #include <sfx2/sfxmodelfactory.hxx>
54
55 #include <basic/sbuno.hxx>
56 #include <svtools/sfxecode.hxx>
57 #include <svtools/ehdl.hxx>
58 #include <unotools/printwarningoptions.hxx>
59 #include <comphelper/processfactory.hxx>
60
61 #include <com/sun/star/document/XStorageBasedDocument.hpp>
62 #include <com/sun/star/script/DocumentDialogLibraryContainer.hpp>
63 #include <com/sun/star/script/DocumentScriptLibraryContainer.hpp>
64 #include <com/sun/star/document/XEmbeddedScripts.hpp>
65 #include <com/sun/star/document/XScriptInvocationContext.hpp>
66 #include <com/sun/star/ucb/ContentCreationException.hpp>
67 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
68
69 #include <svl/urihelper.hxx>
70 #include <unotools/pathoptions.hxx>
71 #include <svl/sharecontrolfile.hxx>
72 #include <unotools/ucbhelper.hxx>
73 #include <svtools/asynclink.hxx>
74 #include <tools/diagnose_ex.h>
75 #include <tools/globname.hxx>
76 #include <tools/debug.hxx>
77 #include <comphelper/classids.hxx>
78
79 #include <sfx2/app.hxx>
80 #include <sfx2/docfac.hxx>
81 #include <sfx2/docfile.hxx>
82 #include <sfx2/event.hxx>
83 #include <sfx2/dispatch.hxx>
84 #include <sfx2/viewsh.hxx>
85 #include <sfx2/viewfrm.hxx>
86 #include <sfx2/sfxresid.hxx>
87 #include <objshimp.hxx>
88 #include <sfxtypes.hxx>
89 #include <sfx2/evntconf.hxx>
90 #include <sfx2/request.hxx>
91 #include <sfx2/strings.hrc>
92 #include <appdata.hxx>
93 #include <sfx2/sfxsids.hrc>
94 #include <basic/basmgr.hxx>
95 #include <sfx2/QuerySaveDocument.hxx>
96 #include <sfx2/msg.hxx>
97 #include <appbaslib.hxx>
98 #include <sfx2/sfxbasemodel.hxx>
99 #include <sfx2/sfxuno.hxx>
100 #include <shellimpl.hxx>
101 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
102 #include <sfx2/infobar.hxx>
103
104 #include <basic/basicmanagerrepository.hxx>
105
106 using namespace ::com::sun::star;
107 using namespace ::com::sun::star::uno;
108 using namespace ::com::sun::star::script;
109 using namespace ::com::sun::star::frame;
110 using namespace ::com::sun::star::document;
111
112 using ::basic::BasicManagerRepository;
113 #include <uno/mapping.hxx>
114
115 #include <sfxslots.hxx>
116
117 namespace {
118
119 class theCurrentComponent : public rtl::Static< WeakReference< XInterface >, theCurrentComponent > {};
120
121 #if HAVE_FEATURE_SCRIPTING
122
123 // remember all registered components for VBA compatibility, to be able to remove them on disposing the model
124 typedef ::std::map< XInterface*, OUString > VBAConstantNameMap;
125 static VBAConstantNameMap s_aRegisteredVBAConstants;
126
lclGetVBAGlobalConstName(const Reference<XInterface> & rxComponent)127 OUString lclGetVBAGlobalConstName( const Reference< XInterface >& rxComponent )
128 {
129 OSL_ENSURE( rxComponent.is(), "lclGetVBAGlobalConstName - missing component" );
130
131 VBAConstantNameMap::iterator aIt = s_aRegisteredVBAConstants.find( rxComponent.get() );
132 if( aIt != s_aRegisteredVBAConstants.end() )
133 return aIt->second;
134
135 uno::Reference< beans::XPropertySet > xProps( rxComponent, uno::UNO_QUERY );
136 if( xProps.is() ) try
137 {
138 OUString aConstName;
139 xProps->getPropertyValue("VBAGlobalConstantName") >>= aConstName;
140 return aConstName;
141 }
142 catch (const uno::Exception&) // not supported
143 {
144 }
145 return OUString();
146 }
147
148 #endif
149
150 } // namespace
151
152
153 class SfxModelListener_Impl : public ::cppu::WeakImplHelper< css::util::XCloseListener >
154 {
155 SfxObjectShell* mpDoc;
156 public:
SfxModelListener_Impl(SfxObjectShell * pDoc)157 explicit SfxModelListener_Impl( SfxObjectShell* pDoc ) : mpDoc(pDoc) {};
158 virtual void SAL_CALL queryClosing( const css::lang::EventObject& aEvent, sal_Bool bDeliverOwnership ) override ;
159 virtual void SAL_CALL notifyClosing( const css::lang::EventObject& aEvent ) override ;
160 virtual void SAL_CALL disposing( const css::lang::EventObject& aEvent ) override ;
161
162 };
163
queryClosing(const css::lang::EventObject &,sal_Bool)164 void SAL_CALL SfxModelListener_Impl::queryClosing( const css::lang::EventObject& , sal_Bool )
165 {
166 }
167
notifyClosing(const css::lang::EventObject &)168 void SAL_CALL SfxModelListener_Impl::notifyClosing( const css::lang::EventObject& )
169 {
170 SolarMutexGuard aSolarGuard;
171 mpDoc->Broadcast( SfxHint(SfxHintId::Deinitializing) );
172 }
173
disposing(const css::lang::EventObject & _rEvent)174 void SAL_CALL SfxModelListener_Impl::disposing( const css::lang::EventObject& _rEvent )
175 {
176 // am I ThisComponent in AppBasic?
177 SolarMutexGuard aSolarGuard;
178 if ( SfxObjectShell::GetCurrentComponent() == _rEvent.Source )
179 {
180 // remove ThisComponent reference from AppBasic
181 SfxObjectShell::SetCurrentComponent( Reference< XInterface >() );
182 }
183
184 #if HAVE_FEATURE_SCRIPTING
185 /* Remove VBA component from AppBasic. As every application registers its
186 own current component, the disposed component may not be the "current
187 component" of the SfxObjectShell. */
188 if ( _rEvent.Source.is() )
189 {
190 VBAConstantNameMap::iterator aIt = s_aRegisteredVBAConstants.find( _rEvent.Source.get() );
191 if ( aIt != s_aRegisteredVBAConstants.end() )
192 {
193 if ( BasicManager* pAppMgr = SfxApplication::GetBasicManager() )
194 pAppMgr->SetGlobalUNOConstant( aIt->second, Any( Reference< XInterface >() ) );
195 s_aRegisteredVBAConstants.erase( aIt );
196 }
197 }
198 #endif
199
200 if ( !mpDoc->Get_Impl()->bClosing )
201 // GCC crashes when already in the destructor, so first query the Flag
202 mpDoc->DoClose();
203 }
204
205
SfxObjectShell_Impl(SfxObjectShell & _rDocShell)206 SfxObjectShell_Impl::SfxObjectShell_Impl( SfxObjectShell& _rDocShell )
207 :mpObjectContainer(nullptr)
208 ,rDocShell( _rDocShell )
209 ,aMacroMode( *this )
210 ,pProgress( nullptr)
211 ,nTime( DateTime::SYSTEM )
212 ,nVisualDocumentNumber( USHRT_MAX)
213 ,nDocumentSignatureState( SignatureState::UNKNOWN )
214 ,nScriptingSignatureState( SignatureState::UNKNOWN )
215 ,bClosing( false)
216 ,bIsSaving( false)
217 ,bIsNamedVisible( false)
218 ,bIsAbortingImport ( false)
219 ,bInPrepareClose( false )
220 ,bPreparedForClose( false )
221 ,bForbidReload( false )
222 ,bBasicInitialized( false )
223 ,bIsPrintJobCancelable( true )
224 ,bOwnsStorage( true )
225 ,bInitialized( false )
226 ,bModelInitialized( false )
227 ,bPreserveVersions( true )
228 ,m_bMacroSignBroken( false )
229 ,m_bNoBasicCapabilities( false )
230 ,m_bDocRecoverySupport( true )
231 ,bQueryLoadTemplate( true )
232 ,bLoadReadonly( false )
233 ,bUseUserData( true )
234 ,bUseThumbnailSave( true )
235 ,bSaveVersionOnClose( false )
236 ,m_bSharedXMLFlag( false )
237 ,m_bAllowShareControlFileClean( true )
238 ,m_bConfigOptionsChecked( false )
239 ,m_bMacroCallsSeenWhileLoading( false )
240 ,lErr(ERRCODE_NONE)
241 ,nEventId ( SfxEventHintId::NONE )
242 ,nLoadedFlags ( SfxLoadedFlags::ALL )
243 ,nFlagsInProgress( SfxLoadedFlags::NONE )
244 ,bModalMode( false )
245 ,bRunningMacro( false )
246 ,bReadOnlyUI( false )
247 ,nStyleFilter( 0 )
248 ,m_bEnableSetModified( true )
249 ,m_bIsModified( false )
250 ,m_nMapUnit( MapUnit::Map100thMM )
251 ,m_bCreateTempStor( false )
252 ,m_bIsInit( false )
253 ,m_bIncomplEncrWarnShown( false )
254 ,m_nModifyPasswordHash( 0 )
255 ,m_bModifyPasswordEntered( false )
256 ,m_bSavingForSigning( false )
257 ,m_bAllowModifiedBackAfterSigning( false )
258 {
259 SfxObjectShell* pDoc = &_rDocShell;
260 SfxObjectShellArr_Impl &rArr = SfxGetpApp()->GetObjectShells_Impl();
261 rArr.push_back( pDoc );
262 }
263
264
~SfxObjectShell_Impl()265 SfxObjectShell_Impl::~SfxObjectShell_Impl()
266 {
267 }
268
269
SfxObjectShell(const SfxModelFlags i_nCreationFlags)270 SfxObjectShell::SfxObjectShell( const SfxModelFlags i_nCreationFlags )
271 : pImpl(new SfxObjectShell_Impl(*this))
272 , pMedium(nullptr)
273 , eCreateMode(SfxObjectCreateMode::STANDARD)
274 , bHasName(false)
275 , bIsInGenerateThumbnail (false)
276 , mbAvoidRecentDocs(false)
277 {
278 if (i_nCreationFlags & SfxModelFlags::EMBEDDED_OBJECT)
279 eCreateMode = SfxObjectCreateMode::EMBEDDED;
280 else if (i_nCreationFlags & SfxModelFlags::EXTERNAL_LINK)
281 eCreateMode = SfxObjectCreateMode::INTERNAL;
282
283 const bool bScriptSupport = ( i_nCreationFlags & SfxModelFlags::DISABLE_EMBEDDED_SCRIPTS ) == SfxModelFlags::NONE;
284 if ( !bScriptSupport )
285 pImpl->m_bNoBasicCapabilities = true;
286
287 const bool bDocRecovery = ( i_nCreationFlags & SfxModelFlags::DISABLE_DOCUMENT_RECOVERY ) == SfxModelFlags::NONE;
288 if ( !bDocRecovery )
289 pImpl->m_bDocRecoverySupport = false;
290 }
291
292 /** Constructor of the class SfxObjectShell.
293
294 @param eMode Purpose, to which the SfxObjectShell is created:
295 SfxObjectCreateMode::EMBEDDED (default) as SO-Server from within another Document
296 SfxObjectCreateMode::STANDARD, as a normal Document open stand-alone
297 SfxObjectCreateMode::ORGANIZER to be displayed in the Organizer, here nothing of the contents is used
298 */
SfxObjectShell(SfxObjectCreateMode eMode)299 SfxObjectShell::SfxObjectShell(SfxObjectCreateMode eMode)
300 : pImpl(new SfxObjectShell_Impl(*this))
301 , pMedium(nullptr)
302 , eCreateMode(eMode)
303 , bHasName(false)
304 , bIsInGenerateThumbnail(false)
305 , mbAvoidRecentDocs(false)
306 {
307 }
308
~SfxObjectShell()309 SfxObjectShell::~SfxObjectShell()
310 {
311
312 if ( IsEnableSetModified() )
313 EnableSetModified( false );
314
315 SfxObjectShell::CloseInternal();
316 pImpl->pBaseModel.set( nullptr );
317
318 pImpl->pReloadTimer.reset();
319
320 SfxApplication *pSfxApp = SfxGetpApp();
321 if ( USHRT_MAX != pImpl->nVisualDocumentNumber && pSfxApp )
322 pSfxApp->ReleaseIndex(pImpl->nVisualDocumentNumber);
323
324 // Destroy Basic-Manager
325 pImpl->aBasicManager.reset(nullptr);
326
327 if ( pSfxApp && pSfxApp->GetDdeService() )
328 pSfxApp->RemoveDdeTopic( this );
329
330 pImpl->pBaseModel.set( nullptr );
331
332 // don't call GetStorage() here, in case of Load Failure it's possible that a storage was never assigned!
333 if ( pMedium && pMedium->HasStorage_Impl() && pMedium->GetStorage( false ) == pImpl->m_xDocStorage )
334 pMedium->CanDisposeStorage_Impl( false );
335
336 if ( pImpl->mpObjectContainer )
337 {
338 pImpl->mpObjectContainer->CloseEmbeddedObjects();
339 delete pImpl->mpObjectContainer;
340 }
341
342 if ( pImpl->bOwnsStorage && pImpl->m_xDocStorage.is() )
343 pImpl->m_xDocStorage->dispose();
344
345 if ( pMedium )
346 {
347 pMedium->CloseAndReleaseStreams_Impl();
348
349 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
350 if (IsDocShared())
351 FreeSharedFile( pMedium->GetURLObject().GetMainURL( INetURLObject::DecodeMechanism::NONE ) );
352 #endif
353 DELETEZ( pMedium );
354 }
355
356 // The removing of the temporary file must be done as the latest step in the document destruction
357 if ( !pImpl->aTempName.isEmpty() )
358 {
359 OUString aTmp;
360 osl::FileBase::getFileURLFromSystemPath( pImpl->aTempName, aTmp );
361 ::utl::UCBContentHelper::Kill( aTmp );
362 }
363 }
364
365
Stamp_SetPrintCancelState(bool bState)366 void SfxObjectShell::Stamp_SetPrintCancelState(bool bState)
367 {
368 pImpl->bIsPrintJobCancelable = bState;
369 }
370
371
Stamp_GetPrintCancelState() const372 bool SfxObjectShell::Stamp_GetPrintCancelState() const
373 {
374 return pImpl->bIsPrintJobCancelable;
375 }
376
377
378 // closes the Object and all its views
379
Close()380 bool SfxObjectShell::Close()
381 {
382 SfxObjectShellRef aRef(this);
383 return CloseInternal();
384 }
385
386 // variant that does not take a reference to itself, so we can call it during object destruction
CloseInternal()387 bool SfxObjectShell::CloseInternal()
388 {
389 if ( !pImpl->bClosing )
390 {
391 // Do not close if a progress is still running
392 if ( GetProgress() )
393 return false;
394
395 pImpl->bClosing = true;
396 Reference< util::XCloseable > xCloseable( GetBaseModel(), UNO_QUERY );
397
398 if ( xCloseable.is() )
399 {
400 try
401 {
402 xCloseable->close( true );
403 }
404 catch (const Exception&)
405 {
406 pImpl->bClosing = false;
407 }
408 }
409
410 if ( pImpl->bClosing )
411 {
412 // remove from Document list
413 // If there is no App, there is no document to remove
414 // no need to call GetOrCreate here
415 SfxApplication *pSfxApp = SfxApplication::Get();
416 if(pSfxApp)
417 {
418 SfxObjectShellArr_Impl &rDocs = pSfxApp->GetObjectShells_Impl();
419 SfxObjectShellArr_Impl::iterator it = std::find( rDocs.begin(), rDocs.end(), this );
420 if ( it != rDocs.end() )
421 rDocs.erase( it );
422 }
423 }
424 }
425
426 return true;
427 }
428
CreateShellID(const SfxObjectShell * pShell)429 OUString SfxObjectShell::CreateShellID( const SfxObjectShell* pShell )
430 {
431 if (!pShell)
432 return OUString();
433
434 OUString aShellID;
435
436 SfxMedium* pMedium = pShell->GetMedium();
437 if (pMedium)
438 aShellID = pMedium->GetBaseURL();
439
440 if (!aShellID.isEmpty())
441 return aShellID;
442
443 sal_Int64 nShellID = reinterpret_cast<sal_Int64>(pShell);
444 aShellID = "0x" + OUString::number(nShellID, 16);
445 return aShellID;
446 }
447
448 // returns a pointer the first SfxDocument of specified type
449
GetFirst(const std::function<bool (const SfxObjectShell *)> & isObjectShell,bool bOnlyVisible)450 SfxObjectShell* SfxObjectShell::GetFirst
451 (
452 const std::function<bool ( const SfxObjectShell* )>& isObjectShell,
453 bool bOnlyVisible
454 )
455 {
456 SfxObjectShellArr_Impl &rDocs = SfxGetpApp()->GetObjectShells_Impl();
457
458 // search for a SfxDocument of the specified type
459 for (SfxObjectShell* pSh : rDocs)
460 {
461 if ( bOnlyVisible && pSh->IsPreview() && pSh->IsReadOnly() )
462 continue;
463
464 if ( (!isObjectShell || isObjectShell( pSh)) &&
465 ( !bOnlyVisible || SfxViewFrame::GetFirst( pSh )))
466 return pSh;
467 }
468
469 return nullptr;
470 }
471
472
473 // returns a pointer to the next SfxDocument of specified type behind *pDoc
474
GetNext(const SfxObjectShell & rPrev,const std::function<bool (const SfxObjectShell *)> & isObjectShell,bool bOnlyVisible)475 SfxObjectShell* SfxObjectShell::GetNext
476 (
477 const SfxObjectShell& rPrev,
478 const std::function<bool ( const SfxObjectShell* )>& isObjectShell,
479 bool bOnlyVisible
480 )
481 {
482 SfxObjectShellArr_Impl &rDocs = SfxGetpApp()->GetObjectShells_Impl();
483
484 // refind the specified predecessor
485 size_t nPos;
486 for ( nPos = 0; nPos < rDocs.size(); ++nPos )
487 if ( rDocs[nPos] == &rPrev )
488 break;
489
490 // search for the next SfxDocument of the specified type
491 for ( ++nPos; nPos < rDocs.size(); ++nPos )
492 {
493 SfxObjectShell* pSh = rDocs[ nPos ];
494 if ( bOnlyVisible && pSh->IsPreview() && pSh->IsReadOnly() )
495 continue;
496
497 if ( (!isObjectShell || isObjectShell( pSh)) &&
498 ( !bOnlyVisible || SfxViewFrame::GetFirst( pSh )))
499 return pSh;
500 }
501 return nullptr;
502 }
503
504
Current()505 SfxObjectShell* SfxObjectShell::Current()
506 {
507 SfxViewFrame *pFrame = SfxViewFrame::Current();
508 return pFrame ? pFrame->GetObjectShell() : nullptr;
509 }
510
511
IsInPrepareClose() const512 bool SfxObjectShell::IsInPrepareClose() const
513 {
514 return pImpl->bInPrepareClose;
515 }
516
517
518 struct BoolEnv_Impl
519 {
520 SfxObjectShell_Impl& rImpl;
BoolEnv_ImplBoolEnv_Impl521 explicit BoolEnv_Impl( SfxObjectShell_Impl& rImplP) : rImpl( rImplP )
522 { rImplP.bInPrepareClose = true; }
~BoolEnv_ImplBoolEnv_Impl523 ~BoolEnv_Impl() { rImpl.bInPrepareClose = false; }
524 };
525
526
PrepareClose(bool bUI)527 bool SfxObjectShell::PrepareClose
528 (
529 bool bUI // true: Dialog and so on is allowed
530 // false: silent-mode
531 )
532 {
533 if( pImpl->bInPrepareClose || pImpl->bPreparedForClose )
534 return true;
535 BoolEnv_Impl aBoolEnv( *pImpl );
536
537 // DocModalDialog?
538 if ( IsInModalMode() )
539 return false;
540
541 SfxViewFrame* pFirst = SfxViewFrame::GetFirst( this );
542 if( pFirst && !pFirst->GetFrame().PrepareClose_Impl( bUI ) )
543 return false;
544
545 // prepare views for closing
546 for ( SfxViewFrame* pFrm = SfxViewFrame::GetFirst( this );
547 pFrm; pFrm = SfxViewFrame::GetNext( *pFrm, this ) )
548 {
549 DBG_ASSERT(pFrm->GetViewShell(),"No Shell");
550 if ( pFrm->GetViewShell() )
551 {
552 bool bRet = pFrm->GetViewShell()->PrepareClose( bUI );
553 if ( !bRet )
554 return bRet;
555 }
556 }
557
558 SfxApplication *pSfxApp = SfxGetpApp();
559 pSfxApp->NotifyEvent( SfxEventHint(SfxEventHintId::PrepareCloseDoc, GlobalEventConfig::GetEventName(GlobalEventId::PREPARECLOSEDOC), this) );
560
561 if( GetCreateMode() == SfxObjectCreateMode::EMBEDDED )
562 {
563 pImpl->bPreparedForClose = true;
564 return true;
565 }
566
567 // Ask if possible if it should be saved
568 // only ask for the Document in the visible window
569 SfxViewFrame *pFrame = SfxObjectShell::Current() == this
570 ? SfxViewFrame::Current() : SfxViewFrame::GetFirst( this );
571
572 if ( bUI && IsModified() && pFrame )
573 {
574 // restore minimized
575 SfxFrame& rTop = pFrame->GetFrame();
576 SfxViewFrame::SetViewFrame( rTop.GetCurrentViewFrame() );
577 pFrame->GetFrame().Appear();
578
579 // Ask if to save
580 short nRet = RET_YES;
581 {
582 const Reference<XTitle> xTitle(*pImpl->pBaseModel, UNO_QUERY_THROW);
583 const OUString sTitle = xTitle->getTitle ();
584 nRet = ExecuteQuerySaveDocument(pFrame->GetWindow().GetFrameWeld(), sTitle);
585 }
586 /*HACK for plugin::destroy()*/
587
588 if ( RET_YES == nRet )
589 {
590 // Save by each Dispatcher
591 const SfxPoolItem *pPoolItem;
592 if ( IsSaveVersionOnClose() )
593 {
594 SfxStringItem aItem( SID_DOCINFO_COMMENTS, SfxResId(STR_AUTOMATICVERSION) );
595 SfxBoolItem aWarnItem( SID_FAIL_ON_WARNING, bUI );
596 const SfxPoolItem* ppArgs[] = { &aItem, &aWarnItem, nullptr };
597 pPoolItem = pFrame->GetBindings().ExecuteSynchron( SID_SAVEDOC, ppArgs );
598 }
599 else
600 {
601 SfxBoolItem aWarnItem( SID_FAIL_ON_WARNING, bUI );
602 const SfxPoolItem* ppArgs[] = { &aWarnItem, nullptr };
603 pPoolItem = pFrame->GetBindings().ExecuteSynchron( SID_SAVEDOC, ppArgs );
604 }
605
606 if ( !pPoolItem || pPoolItem->IsVoidItem() || ( dynamic_cast< const SfxBoolItem *>( pPoolItem ) != nullptr && !static_cast<const SfxBoolItem*>( pPoolItem )->GetValue() ) )
607 return false;
608 }
609 else if ( RET_CANCEL == nRet )
610 // Cancelled
611 return false;
612 }
613
614 if ( pFrame )
615 sfx2::SfxNotebookBar::CloseMethod(pFrame->GetBindings());
616 pImpl->bPreparedForClose = true;
617 return true;
618 }
619
620
621 #if HAVE_FEATURE_SCRIPTING
622 namespace
623 {
lcl_getBasicManagerForDocument(const SfxObjectShell & _rDocument)624 BasicManager* lcl_getBasicManagerForDocument( const SfxObjectShell& _rDocument )
625 {
626 if ( !_rDocument.Get_Impl()->m_bNoBasicCapabilities )
627 {
628 if ( !_rDocument.Get_Impl()->bBasicInitialized )
629 const_cast< SfxObjectShell& >( _rDocument ).InitBasicManager_Impl();
630 return _rDocument.Get_Impl()->aBasicManager.get();
631 }
632
633 // assume we do not have Basic ourself, but we can refer to another
634 // document which does (by our model's XScriptInvocationContext::getScriptContainer).
635 // In this case, we return the BasicManager of this other document.
636
637 OSL_ENSURE( !Reference< XEmbeddedScripts >( _rDocument.GetModel(), UNO_QUERY ).is(),
638 "lcl_getBasicManagerForDocument: inconsistency: no Basic, but an XEmbeddedScripts?" );
639 Reference< XModel > xForeignDocument;
640 Reference< XScriptInvocationContext > xContext( _rDocument.GetModel(), UNO_QUERY );
641 if ( xContext.is() )
642 {
643 xForeignDocument.set( xContext->getScriptContainer(), UNO_QUERY );
644 OSL_ENSURE( xForeignDocument.is() && xForeignDocument != _rDocument.GetModel(),
645 "lcl_getBasicManagerForDocument: no Basic, but providing ourself as script container?" );
646 }
647
648 BasicManager* pBasMgr = nullptr;
649 if ( xForeignDocument.is() )
650 pBasMgr = ::basic::BasicManagerRepository::getDocumentBasicManager( xForeignDocument );
651
652 return pBasMgr;
653 }
654 }
655 #endif
656
GetBasicManager() const657 BasicManager* SfxObjectShell::GetBasicManager() const
658 {
659 BasicManager* pBasMgr = nullptr;
660 #if HAVE_FEATURE_SCRIPTING
661 try
662 {
663 pBasMgr = lcl_getBasicManagerForDocument( *this );
664 if ( !pBasMgr )
665 pBasMgr = SfxApplication::GetBasicManager();
666 }
667 catch (const css::ucb::ContentCreationException&)
668 {
669 TOOLS_WARN_EXCEPTION("sfx.doc", "");
670 }
671 #endif
672 return pBasMgr;
673 }
674
HasBasic() const675 bool SfxObjectShell::HasBasic() const
676 {
677 #if !HAVE_FEATURE_SCRIPTING
678 return false;
679 #else
680 if ( pImpl->m_bNoBasicCapabilities )
681 return false;
682
683 if ( !pImpl->bBasicInitialized )
684 const_cast< SfxObjectShell* >( this )->InitBasicManager_Impl();
685
686 return pImpl->aBasicManager.isValid();
687 #endif
688 }
689
690
691 #if HAVE_FEATURE_SCRIPTING
692 namespace
693 {
694 const Reference< XLibraryContainer >&
lcl_getOrCreateLibraryContainer(bool _bScript,Reference<XLibraryContainer> & _rxContainer,const Reference<XModel> & _rxDocument)695 lcl_getOrCreateLibraryContainer( bool _bScript, Reference< XLibraryContainer >& _rxContainer,
696 const Reference< XModel >& _rxDocument )
697 {
698 if ( !_rxContainer.is() )
699 {
700 try
701 {
702 Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY );
703 const Reference< XComponentContext > xContext(
704 ::comphelper::getProcessComponentContext() );
705 _rxContainer.set ( _bScript
706 ? DocumentScriptLibraryContainer::create(
707 xContext, xStorageDoc )
708 : DocumentDialogLibraryContainer::create(
709 xContext, xStorageDoc )
710 , UNO_QUERY_THROW );
711 }
712 catch (const Exception&)
713 {
714 DBG_UNHANDLED_EXCEPTION("sfx.doc");
715 }
716 }
717 return _rxContainer;
718 }
719 }
720 #endif
721
GetDialogContainer()722 Reference< XLibraryContainer > SfxObjectShell::GetDialogContainer()
723 {
724 #if HAVE_FEATURE_SCRIPTING
725 try
726 {
727 if ( !pImpl->m_bNoBasicCapabilities )
728 return lcl_getOrCreateLibraryContainer( false, pImpl->xDialogLibraries, GetModel() );
729
730 BasicManager* pBasMgr = lcl_getBasicManagerForDocument( *this );
731 if ( pBasMgr )
732 return pBasMgr->GetDialogLibraryContainer().get();
733 }
734 catch (const css::ucb::ContentCreationException&)
735 {
736 TOOLS_WARN_EXCEPTION("sfx.doc", "");
737 }
738
739 SAL_WARN("sfx.doc", "SfxObjectShell::GetDialogContainer: falling back to the application - is this really expected here?");
740 #endif
741 return SfxGetpApp()->GetDialogContainer();
742 }
743
GetBasicContainer()744 Reference< XLibraryContainer > SfxObjectShell::GetBasicContainer()
745 {
746 #if HAVE_FEATURE_SCRIPTING
747 if (!utl::ConfigManager::IsFuzzing())
748 {
749 try
750 {
751 if ( !pImpl->m_bNoBasicCapabilities )
752 return lcl_getOrCreateLibraryContainer( true, pImpl->xBasicLibraries, GetModel() );
753
754 BasicManager* pBasMgr = lcl_getBasicManagerForDocument( *this );
755 if ( pBasMgr )
756 return pBasMgr->GetScriptLibraryContainer().get();
757 }
758 catch (const css::ucb::ContentCreationException&)
759 {
760 TOOLS_WARN_EXCEPTION("sfx.doc", "");
761 }
762 }
763 SAL_WARN("sfx.doc", "SfxObjectShell::GetBasicContainer: falling back to the application - is this really expected here?");
764 #endif
765 return SfxGetpApp()->GetBasicContainer();
766 }
767
GetBasic() const768 StarBASIC* SfxObjectShell::GetBasic() const
769 {
770 #if !HAVE_FEATURE_SCRIPTING
771 return NULL;
772 #else
773 BasicManager * pMan = GetBasicManager();
774 return pMan ? pMan->GetLib(0) : nullptr;
775 #endif
776 }
777
InitBasicManager_Impl()778 void SfxObjectShell::InitBasicManager_Impl()
779 /* [Description]
780
781 Creates a document's BasicManager and loads it, if we are already based on
782 a storage.
783
784 [Note]
785
786 This method has to be called by implementations of <SvPersist::Load()>
787 (with its pStor parameter) and by implementations of <SvPersist::InitNew()>
788 (with pStor = 0).
789 */
790
791 {
792 /* #163556# (DR) - Handling of recursive calls while creating the Basic
793 manager.
794
795 It is possible that (while creating the Basic manager) the code that
796 imports the Basic storage wants to access the Basic manager again.
797 Especially in VBA compatibility mode, there is code that wants to
798 access the "VBA Globals" object which is stored as global UNO constant
799 in the Basic manager.
800
801 To achieve correct handling of the recursive calls of this function
802 from lcl_getBasicManagerForDocument(), the implementation of the
803 function BasicManagerRepository::getDocumentBasicManager() has been
804 changed to return the Basic manager currently under construction, when
805 called repeatedly.
806
807 The variable pImpl->bBasicInitialized will be set to sal_True after
808 construction now, to ensure that the recursive call of the function
809 lcl_getBasicManagerForDocument() will be routed into this function too.
810
811 Calling BasicManagerHolder::reset() twice is not a big problem, as it
812 does not take ownership but stores only the raw pointer. Owner of all
813 Basic managers is the global BasicManagerRepository instance.
814 */
815 #if HAVE_FEATURE_SCRIPTING
816 DBG_ASSERT( !pImpl->bBasicInitialized && !pImpl->aBasicManager.isValid(), "Local BasicManager already exists");
817 try
818 {
819 pImpl->aBasicManager.reset( BasicManagerRepository::getDocumentBasicManager( GetModel() ) );
820 }
821 catch (const css::ucb::ContentCreationException&)
822 {
823 TOOLS_WARN_EXCEPTION("sfx.doc", "");
824 }
825 DBG_ASSERT( pImpl->aBasicManager.isValid(), "SfxObjectShell::InitBasicManager_Impl: did not get a BasicManager!" );
826 pImpl->bBasicInitialized = true;
827 #endif
828 }
829
830
DoClose()831 bool SfxObjectShell::DoClose()
832 {
833 return Close();
834 }
835
836
GetObjectShell()837 SfxObjectShell* SfxObjectShell::GetObjectShell()
838 {
839 return this;
840 }
841
842
GetEventNames()843 uno::Sequence< OUString > SfxObjectShell::GetEventNames()
844 {
845 static uno::Sequence< OUString > s_EventNameContainer(rtl::Reference<GlobalEventConfig>(new GlobalEventConfig)->getElementNames());
846
847 return s_EventNameContainer;
848 }
849
850
GetModel() const851 css::uno::Reference< css::frame::XModel > SfxObjectShell::GetModel() const
852 {
853 return GetBaseModel();
854 }
855
SetBaseModel(SfxBaseModel * pModel)856 void SfxObjectShell::SetBaseModel( SfxBaseModel* pModel )
857 {
858 OSL_ENSURE( !pImpl->pBaseModel.is() || pModel == nullptr, "Model already set!" );
859 pImpl->pBaseModel.set( pModel );
860 if ( pImpl->pBaseModel.is() )
861 {
862 pImpl->pBaseModel->addCloseListener( new SfxModelListener_Impl(this) );
863 }
864 }
865
866
GetBaseModel() const867 css::uno::Reference< css::frame::XModel > SfxObjectShell::GetBaseModel() const
868 {
869 return pImpl->pBaseModel.get();
870 }
871
SetAutoStyleFilterIndex(sal_uInt16 nSet)872 void SfxObjectShell::SetAutoStyleFilterIndex(sal_uInt16 nSet)
873 {
874 pImpl->nStyleFilter = nSet;
875 }
876
GetAutoStyleFilterIndex() const877 sal_uInt16 SfxObjectShell::GetAutoStyleFilterIndex() const
878 {
879 return pImpl->nStyleFilter;
880 }
881
882
SetCurrentComponent(const Reference<XInterface> & _rxComponent)883 void SfxObjectShell::SetCurrentComponent( const Reference< XInterface >& _rxComponent )
884 {
885 WeakReference< XInterface >& rTheCurrentComponent = theCurrentComponent::get();
886
887 Reference< XInterface > xOldCurrentComp(rTheCurrentComponent);
888 if ( _rxComponent == xOldCurrentComp )
889 // nothing to do
890 return;
891 // note that "_rxComponent.get() == s_xCurrentComponent.get().get()" is /sufficient/, but not
892 // /required/ for "_rxComponent == s_xCurrentComponent.get()".
893 // In other words, it's still possible that we here do something which is not necessary,
894 // but we should have filtered quite some unnecessary calls already.
895
896 #if HAVE_FEATURE_SCRIPTING
897 BasicManager* pAppMgr = SfxApplication::GetBasicManager();
898 rTheCurrentComponent = _rxComponent;
899 if ( !pAppMgr )
900 return;
901
902 // set "ThisComponent" for Basic
903 pAppMgr->SetGlobalUNOConstant( "ThisComponent", Any( _rxComponent ) );
904
905 // set new current component for VBA compatibility
906 if ( _rxComponent.is() )
907 {
908 OUString aVBAConstName = lclGetVBAGlobalConstName( _rxComponent );
909 if ( !aVBAConstName.isEmpty() )
910 {
911 pAppMgr->SetGlobalUNOConstant( aVBAConstName, Any( _rxComponent ) );
912 s_aRegisteredVBAConstants[ _rxComponent.get() ] = aVBAConstName;
913 }
914 }
915 // no new component passed -> remove last registered VBA component
916 else if ( xOldCurrentComp.is() )
917 {
918 OUString aVBAConstName = lclGetVBAGlobalConstName( xOldCurrentComp );
919 if ( !aVBAConstName.isEmpty() )
920 {
921 pAppMgr->SetGlobalUNOConstant( aVBAConstName, Any( Reference< XInterface >() ) );
922 s_aRegisteredVBAConstants.erase( xOldCurrentComp.get() );
923 }
924 }
925 #endif
926 }
927
GetCurrentComponent()928 Reference< XInterface > SfxObjectShell::GetCurrentComponent()
929 {
930 return theCurrentComponent::get();
931 }
932
933
GetServiceNameFromFactory(const OUString & rFact)934 OUString SfxObjectShell::GetServiceNameFromFactory( const OUString& rFact )
935 {
936 //! Remove everything behind name!
937 OUString aFact( rFact );
938 OUString aPrefix("private:factory/");
939 if ( aFact.startsWith( aPrefix ) )
940 aFact = aFact.copy( aPrefix.getLength() );
941 sal_Int32 nPos = aFact.indexOf( '?' );
942 OUString aParam;
943 if ( nPos != -1 )
944 {
945 aParam = aFact.copy( nPos );
946 aFact = aFact.copy( 0, nPos );
947 aParam = aParam.copy(1);
948 }
949 aFact = aFact.replaceAll("4", "");
950 aFact = aFact.toAsciiLowerCase();
951
952 // HACK: sometimes a real document service name is given here instead of
953 // a factory short name. Set return value directly to this service name as fallback
954 // in case next lines of code does nothing ...
955 // use rFact instead of normed aFact value !
956 OUString aServiceName = rFact;
957
958 if ( aFact == "swriter" )
959 {
960 aServiceName = "com.sun.star.text.TextDocument";
961 }
962 else if ( aFact == "sweb" || aFact == "swriter/web" )
963 {
964 aServiceName = "com.sun.star.text.WebDocument";
965 }
966 else if ( aFact == "sglobal" || aFact == "swriter/globaldocument" )
967 {
968 aServiceName = "com.sun.star.text.GlobalDocument";
969 }
970 else if ( aFact == "scalc" )
971 {
972 aServiceName = "com.sun.star.sheet.SpreadsheetDocument";
973 }
974 else if ( aFact == "sdraw" )
975 {
976 aServiceName = "com.sun.star.drawing.DrawingDocument";
977 }
978 else if ( aFact == "simpress" )
979 {
980 aServiceName = "com.sun.star.presentation.PresentationDocument";
981 }
982 else if ( aFact == "schart" )
983 {
984 aServiceName = "com.sun.star.chart.ChartDocument";
985 }
986 else if ( aFact == "smath" )
987 {
988 aServiceName = "com.sun.star.formula.FormulaProperties";
989 }
990 #if HAVE_FEATURE_SCRIPTING
991 else if ( aFact == "sbasic" )
992 {
993 aServiceName = "com.sun.star.script.BasicIDE";
994 }
995 #endif
996 #if HAVE_FEATURE_DBCONNECTIVITY
997 else if ( aFact == "sdatabase" )
998 {
999 aServiceName = "com.sun.star.sdb.OfficeDatabaseDocument";
1000 }
1001 #endif
1002
1003 return aServiceName;
1004 }
1005
CreateObjectByFactoryName(const OUString & rFact,SfxObjectCreateMode eMode)1006 SfxObjectShell* SfxObjectShell::CreateObjectByFactoryName( const OUString& rFact, SfxObjectCreateMode eMode )
1007 {
1008 return CreateObject( GetServiceNameFromFactory( rFact ), eMode );
1009 }
1010
1011
CreateObject(const OUString & rServiceName,SfxObjectCreateMode eCreateMode)1012 SfxObjectShell* SfxObjectShell::CreateObject( const OUString& rServiceName, SfxObjectCreateMode eCreateMode )
1013 {
1014 if ( !rServiceName.isEmpty() )
1015 {
1016 uno::Reference < frame::XModel > xDoc( ::comphelper::getProcessServiceFactory()->createInstance( rServiceName ), UNO_QUERY );
1017 if ( xDoc.is() )
1018 {
1019 uno::Reference < lang::XUnoTunnel > xObj( xDoc, UNO_QUERY );
1020 uno::Sequence < sal_Int8 > aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
1021 sal_Int64 nHandle = xObj->getSomething( aSeq );
1022 if ( nHandle )
1023 {
1024 SfxObjectShell* pRet = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle ));
1025 pRet->SetCreateMode_Impl( eCreateMode );
1026 return pRet;
1027 }
1028 }
1029 }
1030
1031 return nullptr;
1032 }
1033
CreateAndLoadComponent(const SfxItemSet & rSet)1034 Reference<lang::XComponent> SfxObjectShell::CreateAndLoadComponent( const SfxItemSet& rSet )
1035 {
1036 uno::Sequence < beans::PropertyValue > aProps;
1037 TransformItems( SID_OPENDOC, rSet, aProps );
1038 const SfxStringItem* pFileNameItem = rSet.GetItem<SfxStringItem>(SID_FILE_NAME, false);
1039 const SfxStringItem* pTargetItem = rSet.GetItem<SfxStringItem>(SID_TARGETNAME, false);
1040 OUString aURL;
1041 OUString aTarget("_blank");
1042 if ( pFileNameItem )
1043 aURL = pFileNameItem->GetValue();
1044 if ( pTargetItem )
1045 aTarget = pTargetItem->GetValue();
1046
1047 uno::Reference < frame::XComponentLoader > xLoader =
1048 frame::Desktop::create(comphelper::getProcessComponentContext());
1049
1050 Reference <lang::XComponent> xComp;
1051 try
1052 {
1053 xComp = xLoader->loadComponentFromURL(aURL, aTarget, 0, aProps);
1054 }
1055 catch (const uno::Exception&)
1056 {
1057 }
1058
1059 return xComp;
1060 }
1061
GetShellFromComponent(const Reference<lang::XComponent> & xComp)1062 SfxObjectShell* SfxObjectShell::GetShellFromComponent( const Reference<lang::XComponent>& xComp )
1063 {
1064 try
1065 {
1066 Reference<lang::XUnoTunnel> xTunnel(xComp, UNO_QUERY_THROW);
1067 Sequence <sal_Int8> aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
1068 sal_Int64 nHandle = xTunnel->getSomething( aSeq );
1069 if (!nHandle)
1070 return nullptr;
1071
1072 return reinterpret_cast< SfxObjectShell* >(sal::static_int_cast< sal_IntPtr >( nHandle ));
1073 }
1074 catch (const Exception&)
1075 {
1076 }
1077
1078 return nullptr;
1079 }
1080
SetInitialized_Impl(const bool i_fromInitNew)1081 void SfxObjectShell::SetInitialized_Impl( const bool i_fromInitNew )
1082 {
1083 pImpl->bInitialized = true;
1084 if (utl::ConfigManager::IsFuzzing())
1085 return;
1086 if ( i_fromInitNew )
1087 {
1088 SetActivateEvent_Impl( SfxEventHintId::CreateDoc );
1089 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::DocCreated, GlobalEventConfig::GetEventName(GlobalEventId::DOCCREATED), this ) );
1090 }
1091 else
1092 {
1093 SfxGetpApp()->NotifyEvent( SfxEventHint( SfxEventHintId::LoadFinished, GlobalEventConfig::GetEventName(GlobalEventId::LOADFINISHED), this ) );
1094 }
1095 }
1096
1097
IsChangeRecording() const1098 bool SfxObjectShell::IsChangeRecording() const
1099 {
1100 // currently this function needs to be overwritten by Writer and Calc only
1101 SAL_WARN( "sfx.doc", "function not implemented" );
1102 return false;
1103 }
1104
1105
HasChangeRecordProtection() const1106 bool SfxObjectShell::HasChangeRecordProtection() const
1107 {
1108 // currently this function needs to be overwritten by Writer and Calc only
1109 SAL_WARN( "sfx.doc", "function not implemented" );
1110 return false;
1111 }
1112
1113
SetChangeRecording(bool)1114 void SfxObjectShell::SetChangeRecording( bool /*bActivate*/ )
1115 {
1116 // currently this function needs to be overwritten by Writer and Calc only
1117 SAL_WARN( "sfx.doc", "function not implemented" );
1118 }
1119
1120
SetProtectionPassword(const OUString &)1121 void SfxObjectShell::SetProtectionPassword( const OUString & /*rPassword*/ )
1122 {
1123 // currently this function needs to be overwritten by Writer and Calc only
1124 SAL_WARN( "sfx.doc", "function not implemented" );
1125 }
1126
1127
GetProtectionHash(css::uno::Sequence<sal_Int8> &)1128 bool SfxObjectShell::GetProtectionHash( /*out*/ css::uno::Sequence< sal_Int8 > & /*rPasswordHash*/ )
1129 {
1130 // currently this function needs to be overwritten by Writer and Calc only
1131 SAL_WARN( "sfx.doc", "function not implemented" );
1132 return false;
1133 }
1134
1135 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1136