xref: /trunk/main/sfx2/source/doc/objxtor.cxx (revision a8f4084d6b7f6b81120bc1c1c03b9d6b30a8af98)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sfx2.hxx"
26 
27 #include "arrdecl.hxx"
28 #include <map>
29 
30 #include <cppuhelper/implbase1.hxx>
31 
32 #include <com/sun/star/util/XCloseable.hpp>
33 #include <com/sun/star/frame/XComponentLoader.hpp>
34 #include <com/sun/star/util/XCloseBroadcaster.hpp>
35 #include <com/sun/star/util/XCloseListener.hpp>
36 #include <com/sun/star/util/XModifyBroadcaster.hpp>
37 #include <com/sun/star/beans/XPropertySet.hpp>
38 #include <com/sun/star/frame/XTitle.hpp>
39 #include <vos/mutex.hxx>
40 
41 #include <tools/resary.hxx>
42 #include <vcl/msgbox.hxx>
43 #include <vcl/wrkwin.hxx>
44 #include <vcl/svapp.hxx>
45 #include <svl/eitem.hxx>
46 #include <tools/rtti.hxx>
47 #include <svl/lstner.hxx>
48 #include <sfx2/sfxhelp.hxx>
49 #include <basic/sbstar.hxx>
50 #include <svl/stritem.hxx>
51 #include <basic/sbx.hxx>
52 #include <unotools/eventcfg.hxx>
53 
54 #include <sfx2/objsh.hxx>
55 #include <sfx2/signaturestate.hxx>
56 #include <sfx2/sfxmodelfactory.hxx>
57 
58 #include <basic/sbuno.hxx>
59 #include <svtools/sfxecode.hxx>
60 #include <svtools/ehdl.hxx>
61 #include <unotools/printwarningoptions.hxx>
62 #include <comphelper/processfactory.hxx>
63 
64 #include <com/sun/star/document/XStorageBasedDocument.hpp>
65 #include <com/sun/star/script/DocumentDialogLibraryContainer.hpp>
66 #include <com/sun/star/script/DocumentScriptLibraryContainer.hpp>
67 #include <com/sun/star/document/XEmbeddedScripts.hpp>
68 #include <com/sun/star/document/XScriptInvocationContext.hpp>
69 
70 #include <svl/urihelper.hxx>
71 #include <unotools/pathoptions.hxx>
72 #include <svl/sharecontrolfile.hxx>
73 #include <unotools/localfilehelper.hxx>
74 #include <unotools/ucbhelper.hxx>
75 #include <svtools/asynclink.hxx>
76 #include <tools/diagnose_ex.h>
77 #include <sot/clsids.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 "appbas.hxx"
89 #include "sfxtypes.hxx"
90 #include <sfx2/evntconf.hxx>
91 #include <sfx2/request.hxx>
92 #include "doc.hrc"
93 #include "sfxlocal.hrc"
94 #include "appdata.hxx"
95 #include <sfx2/appuno.hxx>
96 #include <sfx2/sfxsids.hrc>
97 #include "sfx2/basmgr.hxx"
98 #include "sfx2/QuerySaveDocument.hxx"
99 #include "helpid.hrc"
100 #include <sfx2/msg.hxx>
101 #include "appbaslib.hxx"
102 #include <sfx2/sfxbasemodel.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 //====================================================================
116 
117 DBG_NAME(SfxObjectShell)
118 
119 #define DocumentInfo
120 #include "sfxslots.hxx"
121 
122 namespace {
123 
124 static WeakReference< XInterface > s_xCurrentComponent;
125 
126 // remember all registered components for VBA compatibility, to be able to remove them on disposing the model
127 typedef ::std::map< XInterface*, ::rtl::OString > VBAConstantNameMap;
128 static VBAConstantNameMap s_aRegisteredVBAConstants;
129 
130 ::rtl::OString lclGetVBAGlobalConstName( const Reference< XInterface >& rxComponent )
131 {
132     OSL_ENSURE( rxComponent.is(), "lclGetVBAGlobalConstName - missing component" );
133 
134     VBAConstantNameMap::iterator aIt = s_aRegisteredVBAConstants.find( rxComponent.get() );
135     if( aIt != s_aRegisteredVBAConstants.end() )
136         return aIt->second;
137 
138     uno::Reference< beans::XPropertySet > xProps( rxComponent, uno::UNO_QUERY );
139     if( xProps.is() ) try
140     {
141         ::rtl::OUString aConstName;
142         xProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "VBAGlobalConstantName" ) ) ) >>= aConstName;
143         return ::rtl::OUStringToOString( aConstName, RTL_TEXTENCODING_ASCII_US );
144     }
145     catch( uno::Exception& ) // not supported
146     {
147     }
148     return ::rtl::OString();
149 }
150 
151 } // namespace
152 
153 //=========================================================================
154 
155 
156 //=========================================================================
157 
158 class SfxModelListener_Impl : public ::cppu::WeakImplHelper1< ::com::sun::star::util::XCloseListener >
159 {
160     SfxObjectShell* mpDoc;
161 public:
162     SfxModelListener_Impl( SfxObjectShell* pDoc ) : mpDoc(pDoc) {};
163     virtual void SAL_CALL queryClosing( const com::sun::star::lang::EventObject& aEvent, sal_Bool bDeliverOwnership )
164         throw ( com::sun::star::uno::RuntimeException, com::sun::star::util::CloseVetoException) ;
165     virtual void SAL_CALL notifyClosing( const com::sun::star::lang::EventObject& aEvent ) throw ( com::sun::star::uno::RuntimeException ) ;
166     virtual void SAL_CALL disposing( const com::sun::star::lang::EventObject& aEvent ) throw ( com::sun::star::uno::RuntimeException ) ;
167 
168 };
169 
170 void SAL_CALL SfxModelListener_Impl::queryClosing( const com::sun::star::lang::EventObject& , sal_Bool )
171     throw ( com::sun::star::uno::RuntimeException, com::sun::star::util::CloseVetoException)
172 {
173 }
174 
175 void SAL_CALL SfxModelListener_Impl::notifyClosing( const com::sun::star::lang::EventObject& ) throw ( com::sun::star::uno::RuntimeException )
176 {
177     ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
178     mpDoc->Broadcast( SfxSimpleHint(SFX_HINT_DEINITIALIZING) );
179 }
180 
181 void SAL_CALL SfxModelListener_Impl::disposing( const com::sun::star::lang::EventObject& _rEvent ) throw ( com::sun::star::uno::RuntimeException )
182 {
183     ::vos::OGuard aSolarGuard( Application::GetSolarMutex() );
184 
185     // am I ThisComponent in AppBasic?
186     if ( SfxObjectShell::GetCurrentComponent() == _rEvent.Source )
187     {
188         // remove ThisComponent reference from AppBasic
189         SfxObjectShell::SetCurrentComponent( Reference< XInterface >() );
190     }
191 
192     /*  Remove VBA component from AppBasic. As every application registers its
193         own current component, the disposed component may not be the "current
194         component" of the SfxObjectShell. */
195     if ( _rEvent.Source.is() )
196     {
197         VBAConstantNameMap::iterator aIt = s_aRegisteredVBAConstants.find( _rEvent.Source.get() );
198         if ( aIt != s_aRegisteredVBAConstants.end() )
199         {
200             if ( BasicManager* pAppMgr = SFX_APP()->GetBasicManager() )
201                 pAppMgr->SetGlobalUNOConstant( aIt->second.getStr(), Any( Reference< XInterface >() ) );
202             s_aRegisteredVBAConstants.erase( aIt );
203         }
204     }
205 
206     if ( !mpDoc->Get_Impl()->bClosing )
207         // GCC stuerzt ab, wenn schon im dtor, also vorher Flag abfragen
208         // check flag before entering dtor in order to avoid crash of GCC
209         mpDoc->DoClose();
210 }
211 
212 TYPEINIT1(SfxObjectShell, SfxShell);
213 
214 //--------------------------------------------------------------------
215 SfxObjectShell_Impl::SfxObjectShell_Impl( SfxObjectShell& _rDocShell )
216     :mpObjectContainer(0)
217     ,pBasicManager( new SfxBasicManagerHolder )
218     ,rDocShell( _rDocShell )
219     ,aMacroMode( *this )
220     ,pProgress( 0)
221     ,nTime()
222     ,nVisualDocumentNumber( USHRT_MAX)
223     ,nDocumentSignatureState( SIGNATURESTATE_UNKNOWN )
224     ,nScriptingSignatureState( SIGNATURESTATE_UNKNOWN )
225     ,bInList( sal_False)
226     ,bClosing( sal_False)
227     ,bIsSaving( sal_False)
228     ,bPasswd( sal_False)
229     ,bIsTmp( sal_False)
230     ,bIsNamedVisible( sal_False)
231     ,bIsTemplate(sal_False)
232     ,bIsAbortingImport ( sal_False)
233     ,bImportDone ( sal_False)
234     ,bInPrepareClose( sal_False )
235     ,bPreparedForClose( sal_False )
236     ,bWaitingForPicklist( sal_True )
237     ,bForbidReload( sal_False )
238     ,bBasicInitialized( sal_False )
239     ,bIsPrintJobCancelable( sal_True )
240     ,bOwnsStorage( sal_True )
241     ,bNoBaseURL( sal_False )
242     ,bInitialized( sal_False )
243     ,bSignatureErrorIsShown( sal_False )
244     ,bModelInitialized( sal_False )
245     ,bPreserveVersions( sal_True )
246     ,m_bMacroSignBroken( sal_False )
247     ,m_bNoBasicCapabilities( sal_False )
248     ,m_bDocRecoverySupport( sal_True )
249     ,bQueryLoadTemplate( sal_True )
250     ,bLoadReadonly( sal_False )
251     ,bUseUserData( sal_True )
252     ,bSaveVersionOnClose( sal_False )
253     ,m_bSharedXMLFlag( sal_False )
254     ,m_bAllowShareControlFileClean( sal_True )
255     ,lErr(ERRCODE_NONE)
256     ,nEventId ( 0)
257     ,pReloadTimer ( 0)
258     ,pMarkData( 0 )
259     ,nLoadedFlags ( SFX_LOADED_ALL )
260     ,nFlagsInProgress( 0 )
261     ,bModalMode( sal_False )
262     ,bRunningMacro( sal_False )
263     ,bReloadAvailable( sal_False )
264     ,nAutoLoadLocks( 0 )
265     ,pModule( 0 )
266     ,eFlags( SFXOBJECTSHELL_UNDEFINED )
267     ,bReadOnlyUI( sal_False )
268     ,bHiddenLockedByAPI( sal_False )
269     ,nStyleFilter( 0 )
270     ,bDisposing( sal_False )
271     ,m_bEnableSetModified( sal_True )
272     ,m_bIsModified( sal_False )
273     ,m_nMapUnit( MAP_100TH_MM )
274     ,m_bCreateTempStor( sal_False )
275     ,m_bIsInit( sal_False )
276     ,m_bIncomplEncrWarnShown( sal_False )
277     ,m_nModifyPasswordHash( 0 )
278     ,m_bModifyPasswordEntered( sal_False )
279 {
280     SfxObjectShell* pDoc = &_rDocShell;
281     SfxObjectShellArr_Impl &rArr = SFX_APP()->GetObjectShells_Impl();
282     rArr.C40_INSERT( SfxObjectShell, pDoc, rArr.Count() );
283     bInList = sal_True;
284 }
285 
286 //--------------------------------------------------------------------
287 
288 SfxObjectShell_Impl::~SfxObjectShell_Impl()
289 {
290     delete pBasicManager;
291 }
292 
293 //--------------------------------------------------------------------
294 
295 SfxObjectShell::SfxObjectShell( const sal_uInt64 i_nCreationFlags )
296     :   pImp( new SfxObjectShell_Impl( *this ) )
297     ,   pMedium(0)
298     ,   pStyleSheetPool(0)
299     ,   eCreateMode( ( i_nCreationFlags & SFXMODEL_EMBEDDED_OBJECT ) ? SFX_CREATE_MODE_EMBEDDED : SFX_CREATE_MODE_STANDARD )
300     ,   bHasName( sal_False )
301 {
302     DBG_CTOR(SfxObjectShell, 0);
303 
304     const bool bScriptSupport = ( i_nCreationFlags & SFXMODEL_DISABLE_EMBEDDED_SCRIPTS ) == 0;
305     if ( !bScriptSupport )
306         SetHasNoBasic();
307 
308     const bool bDocRecovery = ( i_nCreationFlags & SFXMODEL_DISABLE_DOCUMENT_RECOVERY ) == 0;
309     if ( !bDocRecovery )
310         pImp->m_bDocRecoverySupport = sal_False;
311 }
312 
313 //--------------------------------------------------------------------
314 
315 // initializes a document from a file-description
316 
317 SfxObjectShell::SfxObjectShell
318 (
319     SfxObjectCreateMode eMode   /*  purpose to generate SfxObjectShel:
320 
321                                     SFX_CREATE_MODE_EMBEDDED (default)
322                                         as SO-Server from a different document
323 
324                                     SFX_CREATE_MODE_STANDARD,
325                                         as normal, self opening document
326 
327                                     SFX_CREATE_MODE_PREVIEW
328                                         in order to create a preview, possible
329                                         less data is needed
330 
331                                     SFX_CREATE_MODE_ORGANIZER
332                                         as a representation in an Organiser
333                                         no data needed
334                                */
335 )
336 
337 /*  [Description]
338 
339     class constructor SfxObjectShell.
340 */
341 
342 :   pImp( new SfxObjectShell_Impl( *this ) ),
343     pMedium(0),
344     pStyleSheetPool(0),
345     eCreateMode(eMode),
346     bHasName( sal_False )
347 {
348     DBG_CTOR(SfxObjectShell, 0);
349 }
350 
351 //--------------------------------------------------------------------
352 
353 // virtual dtor of typical base-class SfxObjectShell
354 
355 SfxObjectShell::~SfxObjectShell()
356 {
357     DBG_DTOR(SfxObjectShell, 0);
358 
359     if ( IsEnableSetModified() )
360         EnableSetModified( sal_False );
361 
362     // do not call GetInPlaceObject(). Access to the inheritage path of SfxInternObject
363     // is not allowed because of a bug in the compiler
364     SfxObjectShell::Close();
365     pImp->pBaseModel.set( NULL );
366 
367     DELETEX(pImp->pReloadTimer );
368 
369     SfxApplication *pSfxApp = SFX_APP();
370     if ( USHRT_MAX != pImp->nVisualDocumentNumber )
371         pSfxApp->ReleaseIndex(pImp->nVisualDocumentNumber);
372 
373     // destroy BasicManager
374     pImp->pBasicManager->reset( NULL );
375 
376     if ( pSfxApp->GetDdeService() )
377         pSfxApp->RemoveDdeTopic( this );
378 
379     pImp->pBaseModel.set( NULL );
380 
381     // don't call GetStorage() here, in case of Load Failure it's possible that a storage was never assigned!
382     if ( pMedium && pMedium->HasStorage_Impl() && pMedium->GetStorage( sal_False ) == pImp->m_xDocStorage )
383         pMedium->CanDisposeStorage_Impl( sal_False );
384 
385     if ( pImp->mpObjectContainer )
386     {
387         pImp->mpObjectContainer->CloseEmbeddedObjects();
388         delete pImp->mpObjectContainer;
389     }
390 
391     if ( pImp->bOwnsStorage && pImp->m_xDocStorage.is() )
392         pImp->m_xDocStorage->dispose();
393 
394     if ( pMedium )
395     {
396         pMedium->CloseAndReleaseStreams_Impl();
397 
398         if ( IsDocShared() )
399             FreeSharedFile();
400 
401         DELETEX( pMedium );
402     }
403 
404     // The removing of the temporary file must be done as the latest step in the document destruction
405     if ( pImp->aTempName.Len() )
406     {
407         String aTmp;
408         ::utl::LocalFileHelper::ConvertPhysicalNameToURL( pImp->aTempName, aTmp );
409         ::utl::UCBContentHelper::Kill( aTmp );
410     }
411 
412     delete pImp;
413 }
414 
415 //--------------------------------------------------------------------
416 
417 void SfxObjectShell::Stamp_SetPrintCancelState(sal_Bool bState)
418 {
419     pImp->bIsPrintJobCancelable = bState;
420 }
421 
422 //--------------------------------------------------------------------
423 
424 sal_Bool SfxObjectShell::Stamp_GetPrintCancelState() const
425 {
426     return pImp->bIsPrintJobCancelable;
427 }
428 
429 //--------------------------------------------------------------------
430 
431 void SfxObjectShell::ViewAssigned()
432 
433 /*  [Description]
434 
435     This module is called, when a view is assigned
436 */
437 
438 {
439 }
440 
441 //--------------------------------------------------------------------
442 // closes the Object and all its views
443 
444 sal_Bool SfxObjectShell::Close()
445 {
446     {DBG_CHKTHIS(SfxObjectShell, 0);}
447     SfxObjectShellRef aRef(this);
448     if ( !pImp->bClosing )
449     {
450         // if a process is still running -> dont close
451         if ( !pImp->bDisposing && GetProgress() )
452             return sal_False;
453 
454         pImp->bClosing = sal_True;
455         Reference< util::XCloseable > xCloseable( GetBaseModel(), UNO_QUERY );
456 
457         if ( xCloseable.is() )
458         {
459             try
460             {
461                 xCloseable->close( sal_True );
462             }
463             catch( Exception& )
464             {
465                 pImp->bClosing = sal_False;
466             }
467         }
468 
469         if ( pImp->bClosing )
470         {
471             // remove from Document-List
472             SfxApplication *pSfxApp = SFX_APP();
473             SfxObjectShellArr_Impl &rDocs = pSfxApp->GetObjectShells_Impl();
474             const SfxObjectShell *pThis = this;
475             sal_uInt16 nPos = rDocs.GetPos(pThis);
476             if ( nPos < rDocs.Count() )
477                 rDocs.Remove( nPos );
478             pImp->bInList = sal_False;
479         }
480     }
481 
482     return sal_True;
483 }
484 
485 //--------------------------------------------------------------------
486 
487 // returns a pointer the first SfxDocument of specified type
488 
489 SfxObjectShell* SfxObjectShell::GetFirst
490 (
491     const TypeId* pType ,
492     sal_Bool            bOnlyVisible
493 )
494 {
495     SfxObjectShellArr_Impl &rDocs = SFX_APP()->GetObjectShells_Impl();
496 
497     // search for a SfxDocument of the specified type
498     for ( sal_uInt16 nPos = 0; nPos < rDocs.Count(); ++nPos )
499     {
500         SfxObjectShell* pSh = rDocs.GetObject( nPos );
501         if ( bOnlyVisible && pSh->IsPreview() && pSh->IsReadOnly() )
502             continue;
503 
504         if ( ( !pType || pSh->IsA(*pType) ) &&
505              ( !bOnlyVisible || SfxViewFrame::GetFirst( pSh, sal_True )))
506             return pSh;
507     }
508 
509     return 0;
510 }
511 //--------------------------------------------------------------------
512 
513 // returns a pointer to the next SfxDocument of specified type behind *pDoc
514 
515 SfxObjectShell* SfxObjectShell::GetNext
516 (
517     const SfxObjectShell&   rPrev,
518     const TypeId*           pType,
519     sal_Bool                    bOnlyVisible
520 )
521 {
522     SfxObjectShellArr_Impl &rDocs = SFX_APP()->GetObjectShells_Impl();
523 
524     // refind the specified predecessor
525     sal_uInt16 nPos;
526     for ( nPos = 0; nPos < rDocs.Count(); ++nPos )
527         if ( rDocs.GetObject(nPos) == &rPrev )
528             break;
529 
530     // search for the next SfxDocument of the specified type
531     for ( ++nPos; nPos < rDocs.Count(); ++nPos )
532     {
533         SfxObjectShell* pSh = rDocs.GetObject( nPos );
534         if ( bOnlyVisible && pSh->IsPreview() && pSh->IsReadOnly() )
535             continue;
536 
537         if ( ( !pType || pSh->IsA(*pType) ) &&
538              ( !bOnlyVisible || SfxViewFrame::GetFirst( pSh, sal_True )))
539             return pSh;
540     }
541     return 0;
542 }
543 
544 //--------------------------------------------------------------------
545 
546 SfxObjectShell* SfxObjectShell::Current()
547 {
548     SfxViewFrame *pFrame = SfxViewFrame::Current();
549     return pFrame ? pFrame->GetObjectShell() : 0;
550 }
551 
552 //-------------------------------------------------------------------------
553 
554 sal_Bool SfxObjectShell::IsInPrepareClose() const
555 {
556     return pImp->bInPrepareClose;
557 }
558 
559 //------------------------------------------------------------------------
560 
561 struct BoolEnv_Impl
562 {
563     SfxObjectShell_Impl* pImp;
564     BoolEnv_Impl( SfxObjectShell_Impl* pImpP) : pImp( pImpP )
565     { pImpP->bInPrepareClose = sal_True; }
566     ~BoolEnv_Impl() { pImp->bInPrepareClose = sal_False; }
567 };
568 
569 
570 sal_uInt16 SfxObjectShell::PrepareClose
571 (
572     sal_Bool    bUI,        // sal_True: Dialoge etc. erlaubt, sal_False: silent-mode
573     sal_Bool    bForBrowsing
574 )
575 {
576     if( pImp->bInPrepareClose || pImp->bPreparedForClose )
577         return sal_True;
578     BoolEnv_Impl aBoolEnv( pImp );
579 
580     // DocModalDialog?
581     if ( IsInModalMode() )
582         return sal_False;
583 
584     SfxViewFrame* pFirst = SfxViewFrame::GetFirst( this );
585     if( pFirst && !pFirst->GetFrame().PrepareClose_Impl( bUI, bForBrowsing ) )
586         return sal_False;
587 
588     // prepare views for closing
589     for ( SfxViewFrame* pFrm = SfxViewFrame::GetFirst( this );
590           pFrm; pFrm = SfxViewFrame::GetNext( *pFrm, this ) )
591     {
592         DBG_ASSERT(pFrm->GetViewShell(),"KeineShell");
593         if ( pFrm->GetViewShell() )
594         {
595             sal_uInt16 nRet = pFrm->GetViewShell()->PrepareClose( bUI, bForBrowsing );
596             if ( nRet != sal_True )
597                 return nRet;
598         }
599     }
600 
601     SfxApplication *pSfxApp = SFX_APP();
602     pSfxApp->NotifyEvent( SfxEventHint(SFX_EVENT_PREPARECLOSEDOC, GlobalEventConfig::GetEventName(STR_EVENT_PREPARECLOSEDOC), this) );
603 
604     if( GetCreateMode() == SFX_CREATE_MODE_EMBEDDED )
605     {
606         pImp->bPreparedForClose = sal_True;
607         return sal_True;
608     }
609 
610     // if applicable ask if save should be executed
611     // ask only for visible documents
612     SfxViewFrame *pFrame = SfxObjectShell::Current() == this
613         ? SfxViewFrame::Current() : SfxViewFrame::GetFirst( this );
614 
615     sal_Bool bClose = sal_False;
616     if ( bUI && IsModified() && pFrame )
617     {
618         //restore minimized
619         SfxFrame& rTop = pFrame->GetTopFrame();
620         SfxViewFrame::SetViewFrame( rTop.GetCurrentViewFrame() );
621         pFrame->GetFrame().Appear();
622 
623         // ask for save
624         short nRet = RET_YES;
625         //TODO/CLEANUP
626         //do we still need UI=2 ?
627         //if( SfxApplication::IsPlugin() == sal_False || bUI == 2 )
628         {
629             //initiate help agent to inform about "print modifies the document"
630             SvtPrintWarningOptions aPrintOptions;
631             if (aPrintOptions.IsModifyDocumentOnPrintingAllowed() &&
632                 HasName() && getDocProperties()->getPrintDate().Month > 0)
633             {
634                 SfxHelp::OpenHelpAgent( &pFirst->GetFrame(), HID_CLOSE_WARNING );
635             }
636             const Reference< XTitle > xTitle( *pImp->pBaseModel.get(), UNO_QUERY_THROW );
637             const ::rtl::OUString     sTitle = xTitle->getTitle ();
638             nRet = ExecuteQuerySaveDocument(&pFrame->GetWindow(),sTitle);
639         }
640         /*HACK for plugin::destroy()*/
641 
642         if ( RET_YES == nRet )
643         {
644             // save by Dispatcher
645             const SfxPoolItem *pPoolItem;
646             if ( IsSaveVersionOnClose() )
647             {
648                 SfxStringItem aItem( SID_DOCINFO_COMMENTS, String( SfxResId( STR_AUTOMATICVERSION ) ) );
649                 SfxBoolItem aWarnItem( SID_FAIL_ON_WARNING, bUI );
650                 const SfxPoolItem* ppArgs[] = { &aItem, &aWarnItem, 0 };
651                 pPoolItem = pFrame->GetBindings().ExecuteSynchron( SID_SAVEDOC, ppArgs );
652             }
653             else
654             {
655                 SfxBoolItem aWarnItem( SID_FAIL_ON_WARNING, bUI );
656                 const SfxPoolItem* ppArgs[] = { &aWarnItem, 0 };
657                 pPoolItem = pFrame->GetBindings().ExecuteSynchron( SID_SAVEDOC, ppArgs );
658             }
659 
660             if ( !pPoolItem || pPoolItem->ISA(SfxVoidItem) || ( pPoolItem->ISA(SfxBoolItem) && !( (const SfxBoolItem*) pPoolItem )->GetValue() ) )
661                 return sal_False;
662             else
663                 bClose = sal_True;
664         }
665         else if ( RET_CANCEL == nRet )
666             // canceled
667             return sal_False;
668         else if ( RET_NEWTASK == nRet )
669         {
670             return RET_NEWTASK;
671         }
672         else
673         {
674             // At No selection don't loose information
675             bClose = sal_True;
676         }
677     }
678 
679     pImp->bPreparedForClose = sal_True;
680     return sal_True;
681 }
682 
683 //--------------------------------------------------------------------
684 namespace
685 {
686     static BasicManager* lcl_getBasicManagerForDocument( const SfxObjectShell& _rDocument )
687     {
688         if ( !_rDocument.Get_Impl()->m_bNoBasicCapabilities )
689         {
690             if ( !_rDocument.Get_Impl()->bBasicInitialized )
691                 const_cast< SfxObjectShell& >( _rDocument ).InitBasicManager_Impl();
692             return _rDocument.Get_Impl()->pBasicManager->get();
693         }
694 
695         // assume we do not have Basic ourself, but we can refer to another
696         // document which does (by our model's XScriptInvocationContext::getScriptContainer).
697         // In this case, we return the BasicManager of this other document.
698 
699         OSL_ENSURE( !Reference< XEmbeddedScripts >( _rDocument.GetModel(), UNO_QUERY ).is(),
700             "lcl_getBasicManagerForDocument: inconsistency: no Basic, but an XEmbeddedScripts?" );
701         Reference< XModel > xForeignDocument;
702         Reference< XScriptInvocationContext > xContext( _rDocument.GetModel(), UNO_QUERY );
703         if ( xContext.is() )
704         {
705             xForeignDocument.set( xContext->getScriptContainer(), UNO_QUERY );
706             OSL_ENSURE( xForeignDocument.is() && xForeignDocument != _rDocument.GetModel(),
707                 "lcl_getBasicManagerForDocument: no Basic, but providing ourself as script container?" );
708         }
709 
710         BasicManager* pBasMgr = NULL;
711         if ( xForeignDocument.is() )
712             pBasMgr = ::basic::BasicManagerRepository::getDocumentBasicManager( xForeignDocument );
713 
714         return pBasMgr;
715     }
716 }
717 
718 //--------------------------------------------------------------------
719 
720 BasicManager* SfxObjectShell::GetBasicManager() const
721 {
722     BasicManager* pBasMgr = lcl_getBasicManagerForDocument( *this );
723     if ( !pBasMgr )
724         pBasMgr = SFX_APP()->GetBasicManager();
725     return pBasMgr;
726 }
727 
728 //--------------------------------------------------------------------
729 
730 void SfxObjectShell::SetHasNoBasic()
731 {
732     pImp->m_bNoBasicCapabilities = sal_True;
733 }
734 
735 //--------------------------------------------------------------------
736 
737 sal_Bool SfxObjectShell::HasBasic() const
738 {
739     if ( pImp->m_bNoBasicCapabilities )
740         return sal_False;
741 
742     if ( !pImp->bBasicInitialized )
743         const_cast< SfxObjectShell* >( this )->InitBasicManager_Impl();
744 
745     return pImp->pBasicManager->isValid();
746 }
747 
748 //--------------------------------------------------------------------
749 namespace
750 {
751     const Reference< XLibraryContainer >&
752     lcl_getOrCreateLibraryContainer( bool _bScript, Reference< XLibraryContainer >& _rxContainer,
753         const Reference< XModel >& _rxDocument )
754     {
755         if ( !_rxContainer.is() )
756         {
757             try
758             {
759                 Reference< XStorageBasedDocument > xStorageDoc( _rxDocument, UNO_QUERY );
760                 const Reference< XComponentContext > xContext(
761                     ::comphelper::getProcessComponentContext() );
762                 _rxContainer.set (   _bScript
763                                 ?   DocumentScriptLibraryContainer::create(
764                                         xContext, xStorageDoc )
765                                 :   DocumentDialogLibraryContainer::create(
766                                         xContext, xStorageDoc )
767                                 ,   UNO_QUERY_THROW );
768             }
769             catch( const Exception& )
770             {
771                 DBG_UNHANDLED_EXCEPTION();
772             }
773         }
774         return _rxContainer;
775     }
776 }
777 
778 //--------------------------------------------------------------------
779 
780 Reference< XLibraryContainer > SfxObjectShell::GetDialogContainer()
781 {
782     if ( !pImp->m_bNoBasicCapabilities )
783         return lcl_getOrCreateLibraryContainer( false, pImp->xDialogLibraries, GetModel() );
784 
785     BasicManager* pBasMgr = lcl_getBasicManagerForDocument( *this );
786     if ( pBasMgr )
787         return pBasMgr->GetDialogLibraryContainer().get();
788 
789     OSL_ENSURE( false, "SfxObjectShell::GetDialogContainer: falling back to the application - is this really expected here?" );
790     return SFX_APP()->GetDialogContainer();
791 }
792 
793 //--------------------------------------------------------------------
794 
795 Reference< XLibraryContainer > SfxObjectShell::GetBasicContainer()
796 {
797     if ( !pImp->m_bNoBasicCapabilities )
798         return lcl_getOrCreateLibraryContainer( true, pImp->xBasicLibraries, GetModel() );
799 
800     BasicManager* pBasMgr = lcl_getBasicManagerForDocument( *this );
801     if ( pBasMgr )
802         return pBasMgr->GetScriptLibraryContainer().get();
803 
804     OSL_ENSURE( false, "SfxObjectShell::GetBasicContainer: falling back to the application - is this really expected here?" );
805     return SFX_APP()->GetBasicContainer();
806 }
807 
808 //--------------------------------------------------------------------
809 
810 StarBASIC* SfxObjectShell::GetBasic() const
811 {
812     return GetBasicManager()->GetLib(0);
813 }
814 
815 //--------------------------------------------------------------------
816 
817 void SfxObjectShell::InitBasicManager_Impl()
818 /*  [Description]
819 
820     creates a document's BasicManager and loads it, if we are already based on
821     a storage.
822 
823     [Note]
824 
825     This method must be called with overloaded
826         <SvPersist::Load()>    (with pStor from Parameter from Load())
827     and <SvPersist::InitNew()> (with pStor = 0)
828 */
829 
830 {
831     /*  #163556# (DR) - Handling of recursive calls while creating the Bacic (shouldn't that be Basic?)
832         manager.
833 
834         It is possible that (while creating the Basic manager) the code that
835         imports the Basic storage wants to access the Basic manager again.
836         Especially in VBA compatibility mode, there is code that wants to
837         access the "VBA Globals" object which is stored as global UNO constant
838         in the Basic manager.
839 
840         To achieve correct handling of the recursive calls of this function
841         from lcl_getBasicManagerForDocument(), the implementation of the
842         function BasicManagerRepository::getDocumentBasicManager() has been
843         changed to return the Basic manager currently under construction, when
844         called repeatedly.
845 
846         The variable pImp->bBasicInitialized will be set to sal_True after
847         construction now, to ensure that the recursive call of the function
848         lcl_getBasicManagerForDocument() will be routed into this function too.
849 
850         Calling BasicManagerHolder::reset() twice is not a big problem, as it
851         does not take ownership but stores only the raw pointer. Owner of all
852         Basic managers is the global BasicManagerRepository instance.
853      */
854     DBG_ASSERT( !pImp->bBasicInitialized && !pImp->pBasicManager->isValid(), "Lokaler BasicManager bereits vorhanden");
855     pImp->pBasicManager->reset( BasicManagerRepository::getDocumentBasicManager( GetModel() ) );
856     DBG_ASSERT( pImp->pBasicManager->isValid(), "SfxObjectShell::InitBasicManager_Impl: did not get a BasicManager!" );
857     pImp->bBasicInitialized = sal_True;
858 }
859 
860 //--------------------------------------------------------------------
861 
862 sal_uInt16 SfxObjectShell::Count()
863 {
864     return SFX_APP()->GetObjectShells_Impl().Count();
865 }
866 
867 //--------------------------------------------------------------------
868 
869 sal_Bool SfxObjectShell::DoClose()
870 {
871     return Close();
872 }
873 
874 //--------------------------------------------------------------------
875 
876 SfxObjectShell* SfxObjectShell::GetObjectShell()
877 {
878     return this;
879 }
880 
881 //--------------------------------------------------------------------
882 
883 uno::Sequence< ::rtl::OUString > SfxObjectShell::GetEventNames()
884 {
885     static uno::Sequence< ::rtl::OUString >* pEventNameContainer = NULL;
886 
887     if ( !pEventNameContainer )
888     {
889         ::vos::OGuard aGuard( Application::GetSolarMutex() );
890         if ( !pEventNameContainer )
891         {
892             static uno::Sequence< ::rtl::OUString > aEventNameContainer = GlobalEventConfig().getElementNames();
893             pEventNameContainer = &aEventNameContainer;
894         }
895     }
896 
897     return *pEventNameContainer;
898 }
899 
900 //--------------------------------------------------------------------
901 
902 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > SfxObjectShell::GetModel() const
903 {
904     return GetBaseModel();
905 }
906 
907 void SfxObjectShell::SetBaseModel( SfxBaseModel* pModel )
908 {
909     OSL_ENSURE( !pImp->pBaseModel.is() || pModel == NULL, "Model already set!" );
910     pImp->pBaseModel.set( pModel );
911     if ( pImp->pBaseModel.is() )
912     {
913         pImp->pBaseModel->addCloseListener( new SfxModelListener_Impl(this) );
914     }
915 }
916 
917 //--------------------------------------------------------------------
918 
919 ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel > SfxObjectShell::GetBaseModel() const
920 {
921     return pImp->pBaseModel.get();
922 }
923 /* -----------------------------10.09.2001 15:56------------------------------
924 
925  ---------------------------------------------------------------------------*/
926 void SfxObjectShell::SetAutoStyleFilterIndex(sal_uInt16 nSet)
927 {
928     pImp->nStyleFilter = nSet;
929 }
930 
931 sal_uInt16 SfxObjectShell::GetAutoStyleFilterIndex()
932 {
933     return pImp->nStyleFilter;
934 }
935 
936 
937 void SfxObjectShell::SetCurrentComponent( const Reference< XInterface >& _rxComponent )
938 {
939     Reference< XInterface > xOldCurrentComp(s_xCurrentComponent);
940     if ( _rxComponent == xOldCurrentComp )
941         // nothing to do
942         return;
943     // note that "_rxComponent.get() == s_xCurrentComponent.get().get()" is /sufficient/, but not
944     // /required/ for "_rxComponent == s_xCurrentComponent.get()".
945     // In other words, it's still possible that we here do something which is not necessary,
946     // but we should have filtered quite some unnecessary calls already.
947 
948     BasicManager* pAppMgr = SFX_APP()->GetBasicManager();
949     s_xCurrentComponent = _rxComponent;
950     if ( pAppMgr )
951     {
952         // set "ThisComponent" for Basic
953         pAppMgr->SetGlobalUNOConstant( "ThisComponent", Any( _rxComponent ) );
954 
955         // set new current component for VBA compatibility
956         if ( _rxComponent.is() )
957         {
958             ::rtl::OString aVBAConstName = lclGetVBAGlobalConstName( _rxComponent );
959             if ( aVBAConstName.getLength() > 0 )
960             {
961                 pAppMgr->SetGlobalUNOConstant( aVBAConstName.getStr(), Any( _rxComponent ) );
962                 s_aRegisteredVBAConstants[ _rxComponent.get() ] = aVBAConstName;
963             }
964         }
965         // no new component passed -> remove last registered VBA component
966         else if ( xOldCurrentComp.is() )
967         {
968             ::rtl::OString aVBAConstName = lclGetVBAGlobalConstName( xOldCurrentComp );
969             if ( aVBAConstName.getLength() > 0 )
970             {
971                 pAppMgr->SetGlobalUNOConstant( aVBAConstName.getStr(), Any( Reference< XInterface >() ) );
972                 s_aRegisteredVBAConstants.erase( xOldCurrentComp.get() );
973             }
974         }
975     }
976 }
977 
978 Reference< XInterface > SfxObjectShell::GetCurrentComponent()
979 {
980     return s_xCurrentComponent;
981 }
982 
983 
984 String SfxObjectShell::GetServiceNameFromFactory( const String& rFact )
985 {
986     //! Remove everything behind name!
987     String aFact( rFact );
988     String aPrefix = String::CreateFromAscii( "private:factory/" );
989     if ( aPrefix.Len() == aFact.Match( aPrefix ) )
990         aFact.Erase( 0, aPrefix.Len() );
991     sal_uInt16 nPos = aFact.Search( '?' );
992     String aParam;
993     if ( nPos != STRING_NOTFOUND )
994     {
995         aParam = aFact.Copy( nPos, aFact.Len() );
996         aFact.Erase( nPos, aFact.Len() );
997         aParam.Erase(0,1);
998     }
999     aFact.EraseAllChars('4').ToLowerAscii();
1000 
1001     // HACK: sometimes a real document service name is given here instead of
1002     // a factory short name. Set return value directly to this service name as fallback
1003     // in case next lines of code does nothing ...
1004     // use rFact instead of normed aFact value !
1005     ::rtl::OUString aServiceName = rFact;
1006 
1007     if ( aFact.EqualsAscii("swriter") )
1008     {
1009         aServiceName = ::rtl::OUString::createFromAscii("com.sun.star.text.TextDocument");
1010     }
1011     else if ( aFact.EqualsAscii("sweb") || aFact.EqualsAscii("swriter/web") )
1012     {
1013         aServiceName = ::rtl::OUString::createFromAscii("com.sun.star.text.WebDocument");
1014     }
1015     else if ( aFact.EqualsAscii("sglobal") || aFact.EqualsAscii("swriter/globaldocument") )
1016     {
1017         aServiceName = ::rtl::OUString::createFromAscii("com.sun.star.text.GlobalDocument");
1018     }
1019     else if ( aFact.EqualsAscii("scalc") )
1020     {
1021         aServiceName = ::rtl::OUString::createFromAscii("com.sun.star.sheet.SpreadsheetDocument");
1022     }
1023     else if ( aFact.EqualsAscii("sdraw") )
1024     {
1025         aServiceName = ::rtl::OUString::createFromAscii("com.sun.star.drawing.DrawingDocument");
1026     }
1027     else if ( aFact.EqualsAscii("simpress") )
1028     {
1029         aServiceName = ::rtl::OUString::createFromAscii("com.sun.star.presentation.PresentationDocument");
1030     }
1031     else if ( aFact.EqualsAscii("schart") )
1032     {
1033         aServiceName = ::rtl::OUString::createFromAscii("com.sun.star.chart.ChartDocument");
1034     }
1035     else if ( aFact.EqualsAscii("smath") )
1036     {
1037         aServiceName = ::rtl::OUString::createFromAscii("com.sun.star.formula.FormulaProperties");
1038     }
1039     else if ( aFact.EqualsAscii("sbasic") )
1040     {
1041         aServiceName = ::rtl::OUString::createFromAscii("com.sun.star.script.BasicIDE");
1042     }
1043     else if ( aFact.EqualsAscii("sdatabase") )
1044     {
1045         aServiceName = ::rtl::OUString::createFromAscii("com.sun.star.sdb.OfficeDatabaseDocument");
1046     }
1047 
1048     return aServiceName;
1049 }
1050 
1051 SfxObjectShell* SfxObjectShell::CreateObjectByFactoryName( const String& rFact, SfxObjectCreateMode eMode )
1052 {
1053     return CreateObject( GetServiceNameFromFactory( rFact ), eMode );
1054 }
1055 
1056 
1057 SfxObjectShell* SfxObjectShell::CreateObject( const String& rServiceName, SfxObjectCreateMode eCreateMode )
1058 {
1059     if ( rServiceName.Len() )
1060     {
1061         ::com::sun::star::uno::Reference < ::com::sun::star::frame::XModel > xDoc(
1062         ::comphelper::getProcessServiceFactory()->createInstance( rServiceName ), UNO_QUERY );
1063         if ( xDoc.is() )
1064         {
1065             ::com::sun::star::uno::Reference < ::com::sun::star::lang::XUnoTunnel > xObj( xDoc, UNO_QUERY );
1066             ::com::sun::star::uno::Sequence < sal_Int8 > aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
1067             sal_Int64 nHandle = xObj->getSomething( aSeq );
1068             if ( nHandle )
1069             {
1070                 SfxObjectShell* pRet = reinterpret_cast< SfxObjectShell* >( sal::static_int_cast< sal_IntPtr >( nHandle ));
1071                 pRet->SetCreateMode_Impl( eCreateMode );
1072                 return pRet;
1073             }
1074         }
1075     }
1076 
1077     return 0;
1078 }
1079 
1080 SfxObjectShell* SfxObjectShell::CreateAndLoadObject( const SfxItemSet& rSet, SfxFrame* pFrame )
1081 {
1082     uno::Sequence < beans::PropertyValue > aProps;
1083     TransformItems( SID_OPENDOC, rSet, aProps );
1084     SFX_ITEMSET_ARG(&rSet, pFileNameItem, SfxStringItem, SID_FILE_NAME, sal_False);
1085     SFX_ITEMSET_ARG(&rSet, pTargetItem, SfxStringItem, SID_TARGETNAME, sal_False);
1086     ::rtl::OUString aURL;
1087     ::rtl::OUString aTarget = rtl::OUString::createFromAscii("_blank");
1088     if ( pFileNameItem )
1089         aURL = pFileNameItem->GetValue();
1090     if ( pTargetItem )
1091         aTarget = pTargetItem->GetValue();
1092 
1093     uno::Reference < frame::XComponentLoader > xLoader;
1094     if ( pFrame )
1095     {
1096         xLoader = uno::Reference < frame::XComponentLoader >( pFrame->GetFrameInterface(), uno::UNO_QUERY );
1097     }
1098     else
1099         xLoader = uno::Reference < frame::XComponentLoader >( comphelper::getProcessServiceFactory()->createInstance(
1100             ::rtl::OUString::createFromAscii("com.sun.star.frame.Desktop") ), uno::UNO_QUERY );
1101 
1102     uno::Reference < lang::XUnoTunnel > xObj;
1103     try
1104     {
1105         xObj = uno::Reference< lang::XUnoTunnel >( xLoader->loadComponentFromURL( aURL, aTarget, 0, aProps ), uno::UNO_QUERY );
1106     }
1107     catch( uno::Exception& )
1108     {}
1109 
1110     if ( xObj.is() )
1111     {
1112         ::com::sun::star::uno::Sequence < sal_Int8 > aSeq( SvGlobalName( SFX_GLOBAL_CLASSID ).GetByteSequence() );
1113         sal_Int64 nHandle = xObj->getSomething( aSeq );
1114         if ( nHandle )
1115             return reinterpret_cast< SfxObjectShell* >(sal::static_int_cast< sal_IntPtr >(  nHandle ));
1116     }
1117 
1118     return NULL;
1119 }
1120 
1121 void SfxObjectShell::SetInitialized_Impl( const bool i_fromInitNew )
1122 {
1123     pImp->bInitialized = sal_True;
1124     if ( i_fromInitNew )
1125     {
1126         SetActivateEvent_Impl( SFX_EVENT_CREATEDOC );
1127         SFX_APP()->NotifyEvent( SfxEventHint( SFX_EVENT_DOCCREATED, GlobalEventConfig::GetEventName(STR_EVENT_DOCCREATED), this ) );
1128     }
1129     else
1130     {
1131         SFX_APP()->NotifyEvent( SfxEventHint( SFX_EVENT_LOADFINISHED, GlobalEventConfig::GetEventName(STR_EVENT_LOADFINISHED), this ) );
1132     }
1133 }
1134 
1135 
1136 bool SfxObjectShell::IsChangeRecording() const
1137 {
1138     // currently this function needs to be overwritten by Writer and Calc only
1139     DBG_ASSERT( 0, "function not implemented" );
1140     return false;
1141 }
1142 
1143 
1144 bool SfxObjectShell::HasChangeRecordProtection() const
1145 {
1146     // currently this function needs to be overwritten by Writer and Calc only
1147     DBG_ASSERT( 0, "function not implemented" );
1148     return false;
1149 }
1150 
1151 
1152 void SfxObjectShell::SetChangeRecording( bool /*bActivate*/ )
1153 {
1154     // currently this function needs to be overwritten by Writer and Calc only
1155     DBG_ASSERT( 0, "function not implemented" );
1156 }
1157 
1158 
1159 bool SfxObjectShell::SetProtectionPassword( const String & /*rPassword*/ )
1160 {
1161     // currently this function needs to be overwritten by Writer and Calc only
1162     DBG_ASSERT( 0, "function not implemented" );
1163     return false;
1164 }
1165 
1166 
1167 bool SfxObjectShell::GetProtectionHash( /*out*/ ::com::sun::star::uno::Sequence< sal_Int8 > & /*rPasswordHash*/ )
1168 {
1169     // currently this function needs to be overwritten by Writer and Calc only
1170     DBG_ASSERT( 0, "function not implemented" );
1171     return false;
1172 }
1173 
1174