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 <memory>
21 #include <scriptdocument.hxx>
22 #include <basobj.hxx>
23 #include <strings.hrc>
24 #include <iderid.hxx>
25 #include <dlgeddef.hxx>
26 #include <doceventnotifier.hxx>
27 #include "documentenumeration.hxx"
28 
29 #include <com/sun/star/ucb/ContentCreationException.hpp>
30 #include <com/sun/star/uri/UriReferenceFactory.hpp>
31 #include <com/sun/star/util/theMacroExpander.hpp>
32 #include <com/sun/star/document/MacroExecMode.hpp>
33 #include <com/sun/star/frame/XStorable.hpp>
34 #include <com/sun/star/frame/FrameSearchFlag.hpp>
35 #include <com/sun/star/awt/XWindow2.hpp>
36 #include <com/sun/star/document/XEmbeddedScripts.hpp>
37 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
38 #include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
39 #include <com/sun/star/script/ModuleInfo.hpp>
40 #include <com/sun/star/script/ModuleType.hpp>
41 
42 #include <sfx2/objsh.hxx>
43 #include <sfx2/bindings.hxx>
44 #include <sfx2/docfile.hxx>
45 
46 
47 #include <basic/basicmanagerrepository.hxx>
48 
49 #include <xmlscript/xmldlg_imexp.hxx>
50 
51 #include <unotools/syslocale.hxx>
52 
53 #include <unotools/collatorwrapper.hxx>
54 
55 #include <tools/diagnose_ex.h>
56 
57 #include <comphelper/documentinfo.hxx>
58 #include <comphelper/processfactory.hxx>
59 #include <comphelper/propertysequence.hxx>
60 
61 #include <sal/log.hxx>
62 #include <osl/file.hxx>
63 #include <rtl/uri.hxx>
64 #include <set>
65 
66 
67 namespace basctl
68 {
69     using ::com::sun::star::uno::Sequence;
70     using ::com::sun::star::uno::Reference;
71     using ::com::sun::star::frame::XModel;
72     using ::com::sun::star::beans::XPropertySet;
73     using ::com::sun::star::script::XLibraryContainer;
74     using ::com::sun::star::uno::UNO_QUERY_THROW;
75     using ::com::sun::star::uno::UNO_SET_THROW;
76     using ::com::sun::star::uno::Exception;
77     using ::com::sun::star::container::XNameContainer;
78     using ::com::sun::star::container::NoSuchElementException;
79     using ::com::sun::star::uno::UNO_QUERY;
80     using ::com::sun::star::task::XStatusIndicator;
81     using ::com::sun::star::uno::Any;
82     using ::com::sun::star::script::XLibraryContainer2;
83     using ::com::sun::star::uri::UriReferenceFactory;
84     using ::com::sun::star::uri::XUriReferenceFactory;
85     using ::com::sun::star::uri::XUriReference;
86     using ::com::sun::star::uno::XComponentContext;
87     using ::com::sun::star::util::XMacroExpander;
88     using ::com::sun::star::util::theMacroExpander;
89     using ::com::sun::star::io::XInputStreamProvider;
90     using ::com::sun::star::uno::Any;
91     using ::com::sun::star::io::XInputStream;
92     using ::com::sun::star::frame::XStorable;
93     using ::com::sun::star::util::XModifiable;
94     using ::com::sun::star::frame::XController;
95     using ::com::sun::star::frame::XFrame;
96     using ::com::sun::star::util::URL;
97     using ::com::sun::star::frame::XDispatchProvider;
98     using ::com::sun::star::frame::XDispatch;
99     using ::com::sun::star::beans::PropertyValue;
100     using ::com::sun::star::awt::XWindow2;
101     using ::com::sun::star::document::XEmbeddedScripts;
102     using ::com::sun::star::script::ModuleInfo;
103     using ::com::sun::star::script::vba::XVBACompatibility;
104     using ::com::sun::star::script::vba::XVBAModuleInfo;
105 
106     namespace FrameSearchFlag = ::com::sun::star::frame::FrameSearchFlag;
107 
108 
109     namespace
110     {
111         bool StringCompareLessThan( const OUString& lhs, const OUString& rhs )
112         {
113             return lhs.compareToIgnoreAsciiCase( rhs ) < 0;
114         }
115 
116         class FilterDocuments : public docs::IDocumentDescriptorFilter
117         {
118         public:
119             explicit FilterDocuments(bool _bFilterInvisible)
120                 : m_bFilterInvisible(_bFilterInvisible)
121             {
122             }
123 
124             virtual ~FilterDocuments() {}
125 
126             virtual bool    includeDocument( const docs::DocumentDescriptor& _rDocument ) const override;
127 
128         private:
129             static bool    impl_isDocumentVisible_nothrow( const docs::DocumentDescriptor& _rDocument );
130 
131         private:
132             bool    m_bFilterInvisible;
133         };
134 
135         bool FilterDocuments::impl_isDocumentVisible_nothrow( const docs::DocumentDescriptor& _rDocument )
136         {
137             try
138             {
139                 for (auto const& controller : _rDocument.aControllers)
140                 {
141                     Reference< XFrame > xFrame( controller->getFrame(), UNO_SET_THROW );
142                     Reference< XWindow2 > xContainer( xFrame->getContainerWindow(), UNO_QUERY_THROW );
143                     if ( xContainer->isVisible() )
144                         return true;
145                 }
146             }
147             catch( const Exception& )
148             {
149                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
150             }
151             return false;
152         }
153 
154         bool FilterDocuments::includeDocument( const docs::DocumentDescriptor& _rDocument ) const
155         {
156             Reference< XEmbeddedScripts > xScripts( _rDocument.xModel, UNO_QUERY );
157             if ( !xScripts.is() )
158                 return false;
159             return !m_bFilterInvisible || impl_isDocumentVisible_nothrow( _rDocument );
160         }
161 
162         void lcl_getAllModels_throw( docs::Documents& _out_rModels, bool _bVisibleOnly )
163         {
164             _out_rModels.clear();
165 
166             FilterDocuments aFilter( _bVisibleOnly );
167             docs::DocumentEnumeration aEnum(
168                 comphelper::getProcessComponentContext(), &aFilter );
169 
170             aEnum.getDocuments( _out_rModels );
171         }
172     }
173 
174     class ScriptDocument::Impl : public DocumentEventListener
175     {
176     private:
177         bool                            m_bIsApplication;
178         bool                            m_bValid;
179         bool                            m_bDocumentClosed;
180         Reference< XModel >             m_xDocument;
181         Reference< XModifiable >        m_xDocModify;
182         Reference< XEmbeddedScripts >   m_xScriptAccess;
183         std::unique_ptr< DocumentEventNotifier > m_pDocListener;
184 
185     public:
186         Impl ();
187         explicit Impl(Reference<XModel> const& rxDocument);
188         virtual ~Impl() override;
189 
190         /** determines whether the instance refers to a valid "document" with script and
191             dialog libraries
192         */
193         bool    isValid()       const   { return m_bValid; }
194         /** determines whether the instance refers to a non-closed document
195         */
196         bool    isAlive()       const   { return m_bValid && ( m_bIsApplication || !m_bDocumentClosed ); }
197         /// determines whether the "document" refers to the application in real
198         bool    isApplication() const   { return m_bValid && m_bIsApplication; }
199         /// determines whether the document refers to a real document (instead of the application)
200         bool    isDocument()    const   { return m_bValid && !m_bIsApplication; }
201 
202         /** invalidates the instance
203         */
204         void    invalidate();
205 
206         const Reference< XModel >&
207                         getDocumentRef() const { return m_xDocument; }
208 
209         /// returns a library container belonging to the document
210         Reference< XLibraryContainer >
211                     getLibraryContainer( LibraryContainerType _eType ) const;
212 
213         /// determines whether a given library is part of the shared installation
214         bool        isLibraryShared( const OUString& _rLibName, LibraryContainerType _eType );
215 
216         /** returns the current frame of the document
217 
218             To be called for documents only, not for the application.
219 
220             If <FALSE/> is returned, an assertion will be raised in non-product builds.
221         */
222         bool        getCurrentFrame( Reference< XFrame >& _out_rxFrame ) const;
223 
224         // versions with the same signature/semantics as in ScriptDocument itself
225         bool        isReadOnly() const;
226         bool        isInVBAMode() const;
227         BasicManager*
228                     getBasicManager() const;
229         Reference< XModel >
230                     getDocument() const;
231         void        setDocumentModified() const;
232         bool        isDocumentModified() const;
233         void        saveDocument( const Reference< XStatusIndicator >& _rxStatusIndicator ) const;
234 
235         OUString    getTitle() const;
236         OUString    getURL() const;
237 
238         bool        allowMacros() const;
239 
240         Reference< XNameContainer >
241                     getLibrary( LibraryContainerType _eType, const OUString& _rLibName, bool _bLoadLibrary ) const;
242         bool        hasLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const;
243         Reference< XNameContainer >
244                     getOrCreateLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const;
245 
246         void        loadLibraryIfExists( LibraryContainerType _eType, const OUString& _rLibrary );
247 
248         bool        removeModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rModuleName );
249         bool        hasModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rModName ) const;
250         bool        getModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rObjectName, Any& _out_rModuleOrDialog );
251         bool        renameModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rOldName, const OUString& _rNewName, const Reference< XNameContainer >& _rxExistingDialogModel );
252         bool        createModule( const OUString& _rLibName, const OUString& _rModName, bool _bCreateMain, OUString& _out_rNewModuleCode ) const;
253         bool        insertModuleOrDialog( LibraryContainerType _eType, const OUString& _rObjectName, const OUString& _rModName, const Any& _rElement ) const;
254         bool        updateModule( const OUString& _rLibName, const OUString& _rModName, const OUString& _rModuleCode ) const;
255         bool        createDialog( const OUString& _rLibName, const OUString& _rDialogName, Reference< XInputStreamProvider >& _out_rDialogProvider ) const;
256 
257     protected:
258         // DocumentEventListener
259         virtual void onDocumentCreated( const ScriptDocument& _rDocument ) override;
260         virtual void onDocumentOpened( const ScriptDocument& _rDocument ) override;
261         virtual void onDocumentSave( const ScriptDocument& _rDocument ) override;
262         virtual void onDocumentSaveDone( const ScriptDocument& _rDocument ) override;
263         virtual void onDocumentSaveAs( const ScriptDocument& _rDocument ) override;
264         virtual void onDocumentSaveAsDone( const ScriptDocument& _rDocument ) override;
265         virtual void onDocumentClosed( const ScriptDocument& _rDocument ) override;
266         virtual void onDocumentTitleChanged( const ScriptDocument& _rDocument ) override;
267         virtual void onDocumentModeChanged( const ScriptDocument& _rDocument ) override;
268 
269     private:
270         bool        impl_initDocument_nothrow( const Reference< XModel >& _rxModel );
271     };
272 
273 
274     ScriptDocument::Impl::Impl()
275         :m_bIsApplication( true )
276         ,m_bValid( true )
277         ,m_bDocumentClosed( false )
278     {
279     }
280 
281     ScriptDocument::Impl::Impl( const Reference< XModel >& _rxDocument )
282         :m_bIsApplication( false )
283         ,m_bValid( false )
284         ,m_bDocumentClosed( false )
285     {
286         if ( _rxDocument.is() )
287             impl_initDocument_nothrow( _rxDocument );
288     }
289 
290     ScriptDocument::Impl::~Impl()
291     {
292         invalidate();
293     }
294 
295     void ScriptDocument::Impl::invalidate()
296     {
297         m_bIsApplication = false;
298         m_bValid = false;
299         m_bDocumentClosed = false;
300 
301         m_xDocument.clear();
302         m_xDocModify.clear();
303         m_xScriptAccess.clear();
304 
305         if (m_pDocListener)
306             m_pDocListener->dispose();
307     }
308 
309     bool ScriptDocument::Impl::impl_initDocument_nothrow( const Reference< XModel >& _rxModel )
310     {
311         try
312         {
313             m_xDocument.set     ( _rxModel, UNO_SET_THROW );
314             m_xDocModify.set    ( _rxModel, UNO_QUERY_THROW );
315             m_xScriptAccess.set ( _rxModel, UNO_QUERY );
316 
317             m_bValid = m_xScriptAccess.is();
318 
319             if ( m_bValid )
320                 m_pDocListener.reset( new DocumentEventNotifier( *this, _rxModel ) );
321         }
322         catch( const Exception& )
323         {
324             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
325             m_bValid = false;
326         }
327 
328         if ( !m_bValid )
329         {
330             invalidate();
331         }
332 
333         return m_bValid;
334     }
335 
336     Reference< XLibraryContainer > ScriptDocument::Impl::getLibraryContainer( LibraryContainerType _eType ) const
337     {
338         OSL_ENSURE( isValid(), "ScriptDocument::Impl::getLibraryContainer: invalid!" );
339 
340         Reference< XLibraryContainer > xContainer;
341         if ( !isValid() )
342             return xContainer;
343 
344         try
345         {
346             if ( isApplication() )
347                 xContainer.set( _eType == E_SCRIPTS ? SfxGetpApp()->GetBasicContainer() : SfxGetpApp()->GetDialogContainer(), UNO_QUERY_THROW );
348             else
349             {
350                 xContainer.set(
351                     _eType == E_SCRIPTS ? m_xScriptAccess->getBasicLibraries() : m_xScriptAccess->getDialogLibraries(),
352                     UNO_QUERY_THROW );
353             }
354         }
355         catch( const Exception& )
356         {
357             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
358         }
359         return xContainer;
360     }
361 
362     bool ScriptDocument::Impl::isReadOnly() const
363     {
364         OSL_ENSURE( isValid(), "ScriptDocument::Impl::isReadOnly: invalid state!" );
365         OSL_ENSURE( !isApplication(), "ScriptDocument::Impl::isReadOnly: not allowed to be called for the application!" );
366 
367         bool bIsReadOnly = true;
368         if ( isValid() && !isApplication() )
369         {
370             try
371             {
372                 // note that XStorable is required by the OfficeDocument service
373                 Reference< XStorable > xDocStorable( m_xDocument, UNO_QUERY_THROW );
374                 bIsReadOnly = xDocStorable->isReadonly();
375             }
376             catch( const Exception& )
377             {
378                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
379             }
380         }
381         return bIsReadOnly;
382     }
383 
384     bool ScriptDocument::Impl::isInVBAMode() const
385     {
386         bool bResult = false;
387         if ( !isApplication() )
388         {
389             Reference< XVBACompatibility > xVBACompat( getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
390             if ( xVBACompat.is() )
391                 bResult = xVBACompat->getVBACompatibilityMode();
392         }
393         return bResult;
394     }
395 
396     BasicManager* ScriptDocument::Impl::getBasicManager() const
397     {
398         try
399         {
400             OSL_ENSURE( isValid(), "ScriptDocument::Impl::getBasicManager: invalid state!" );
401             if ( !isValid() )
402                 return nullptr;
403 
404             if ( isApplication() )
405                 return SfxApplication::GetBasicManager();
406 
407             return ::basic::BasicManagerRepository::getDocumentBasicManager( m_xDocument );
408         }
409         catch (const css::ucb::ContentCreationException& e)
410         {
411             SAL_WARN( "basctl.basicide", "ScriptDocument::getBasicManager: Caught exception: " << e );
412         }
413         return nullptr;
414     }
415 
416     Reference< XModel > ScriptDocument::Impl::getDocument() const
417     {
418         OSL_ENSURE( isValid(), "ScriptDocument::Impl::getDocument: invalid state!" );
419         OSL_ENSURE( isDocument(), "ScriptDocument::Impl::getDocument: for documents only!" );
420         if ( !isValid() || !isDocument() )
421             return nullptr;
422 
423         return m_xDocument;
424     }
425 
426 
427     Reference< XNameContainer > ScriptDocument::Impl::getLibrary( LibraryContainerType _eType, const OUString& _rLibName, bool _bLoadLibrary ) const
428     {
429         OSL_ENSURE( isValid(), "ScriptDocument::Impl::getLibrary: invalid state!" );
430 
431         Reference< XNameContainer > xContainer;
432         try
433         {
434             Reference< XLibraryContainer > xLibContainer = getLibraryContainer( _eType );
435             if ( isValid() && xLibContainer.is() )
436                 xContainer.set( xLibContainer->getByName( _rLibName ), UNO_QUERY_THROW );
437 
438             if ( !xContainer.is() )
439                 throw NoSuchElementException();
440 
441             // load library
442             if ( _bLoadLibrary && !xLibContainer->isLibraryLoaded( _rLibName ) )
443                 xLibContainer->loadLibrary( _rLibName );
444         }
445         catch( const NoSuchElementException& )
446         {
447             throw;  // allowed to leave
448         }
449         catch( const Exception& )
450         {
451             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
452         }
453 
454         return xContainer;
455     }
456 
457 
458     bool ScriptDocument::Impl::hasLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const
459     {
460         bool bHas = false;
461         try
462         {
463             Reference< XLibraryContainer > xLibContainer = getLibraryContainer( _eType );
464             bHas = xLibContainer.is() && xLibContainer->hasByName( _rLibName );
465         }
466         catch( const Exception& )
467         {
468             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
469         }
470         return bHas;
471     }
472 
473 
474     Reference< XNameContainer > ScriptDocument::Impl::getOrCreateLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const
475     {
476         Reference< XNameContainer > xLibrary;
477         try
478         {
479             Reference< XLibraryContainer > xLibContainer( getLibraryContainer( _eType ), UNO_QUERY_THROW );
480             if ( xLibContainer->hasByName( _rLibName ) )
481                 xLibrary.set( xLibContainer->getByName( _rLibName ), UNO_QUERY_THROW );
482             else
483                 xLibrary.set( xLibContainer->createLibrary( _rLibName ), UNO_QUERY_THROW );
484 
485             if ( !xLibContainer->isLibraryLoaded( _rLibName ) )
486                 xLibContainer->loadLibrary( _rLibName );
487         }
488         catch( const Exception& )
489         {
490             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
491         }
492         return xLibrary;
493     }
494 
495 
496     void ScriptDocument::Impl::loadLibraryIfExists( LibraryContainerType _eType, const OUString& _rLibrary )
497     {
498         try
499         {
500             Reference< XLibraryContainer > xLibContainer( getLibraryContainer( _eType ) );
501             if ( xLibContainer.is() && xLibContainer->hasByName( _rLibrary ) && !xLibContainer->isLibraryLoaded( _rLibrary ) )
502                 xLibContainer->loadLibrary( _rLibrary );
503         }
504         catch( const Exception& )
505         {
506             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
507         }
508     }
509 
510 
511     bool ScriptDocument::Impl::removeModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rModuleName )
512     {
513         OSL_ENSURE( isValid(), "ScriptDocument::Impl::removeModuleOrDialog: invalid!" );
514         if ( isValid() )
515         {
516             try
517             {
518                 Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, true ) );
519                 if ( xLib.is() )
520                 {
521                     xLib->removeByName( _rModuleName );
522                     Reference< XVBAModuleInfo > xVBAModuleInfo(xLib, UNO_QUERY);
523                     if(xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo(_rModuleName))
524                         xVBAModuleInfo->removeModuleInfo(_rModuleName);
525                     return true;
526                 }
527             }
528             catch( const Exception& )
529             {
530                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
531             }
532         }
533         return false;
534     }
535 
536 
537     bool ScriptDocument::Impl::hasModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rModName ) const
538     {
539         OSL_ENSURE( isValid(), "ScriptDocument::Impl::hasModuleOrDialog: invalid!" );
540         if ( !isValid() )
541             return false;
542 
543         try
544         {
545             Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, true ) );
546             if ( xLib.is() )
547                 return xLib->hasByName( _rModName );
548         }
549         catch( const Exception& )
550         {
551             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
552         }
553         return false;
554     }
555 
556 
557     bool ScriptDocument::Impl::getModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rObjectName, Any& _out_rModuleOrDialog )
558     {
559         OSL_ENSURE( isValid(), "ScriptDocument::Impl::getModuleOrDialog: invalid!" );
560         if ( !isValid() )
561             return false;
562 
563         _out_rModuleOrDialog.clear();
564         try
565         {
566             Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, true ), UNO_QUERY_THROW );
567             if ( xLib->hasByName( _rObjectName ) )
568             {
569                 _out_rModuleOrDialog = xLib->getByName( _rObjectName );
570                 return true;
571             }
572         }
573         catch( const Exception& )
574         {
575             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
576         }
577         return false;
578     }
579 
580 
581     bool ScriptDocument::Impl::renameModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName,
582         const OUString& _rOldName, const OUString& _rNewName, const Reference< XNameContainer >& _rxExistingDialogModel )
583     {
584         OSL_ENSURE( isValid(), "ScriptDocument::Impl::renameModuleOrDialog: invalid!" );
585         if ( !isValid() )
586             return false;
587 
588         try
589         {
590             Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, true ), UNO_QUERY_THROW );
591 
592             // get element
593             Any aElement( xLib->getByName( _rOldName ) );
594 
595             // remove element from container
596             xLib->removeByName( _rOldName );
597 
598             // if it's a dialog, import and export, to reflect the new name
599             if ( _eType == E_DIALOGS )
600             {
601                 // create dialog model
602                 Reference< XComponentContext > aContext(
603                     comphelper::getProcessComponentContext() );
604                 Reference< XNameContainer > xDialogModel;
605                 if ( _rxExistingDialogModel.is() )
606                     xDialogModel = _rxExistingDialogModel;
607                 else
608                     xDialogModel.set(
609                         ( aContext->getServiceManager()->
610                           createInstanceWithContext(
611                               "com.sun.star.awt.UnoControlDialogModel",
612                               aContext ) ),
613                         UNO_QUERY_THROW );
614 
615                 // import dialog model
616                 Reference< XInputStreamProvider > xISP( aElement, UNO_QUERY_THROW );
617                 if ( !_rxExistingDialogModel.is() )
618                 {
619                     Reference< XInputStream > xInput( xISP->createInputStream(), UNO_QUERY_THROW );
620                     ::xmlscript::importDialogModel( xInput, xDialogModel, aContext, isDocument() ? getDocument() : Reference< XModel >() );
621                 }
622 
623                 // set new name as property
624                 Reference< XPropertySet > xDlgPSet( xDialogModel, UNO_QUERY_THROW );
625                 xDlgPSet->setPropertyValue( DLGED_PROP_NAME, Any( _rNewName ) );
626 
627                 // export dialog model
628                 xISP = ::xmlscript::exportDialogModel( xDialogModel, aContext, isDocument() ? getDocument() : Reference< XModel >() );
629                 aElement <<= xISP;
630             }
631 
632             // insert element by new name in container
633             if ( _eType == E_SCRIPTS )
634             {
635                 Reference< XVBAModuleInfo > xVBAModuleInfo( xLib, UNO_QUERY );
636                 if ( xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo( _rOldName ) )
637                 {
638                     ModuleInfo sModuleInfo = xVBAModuleInfo->getModuleInfo( _rOldName );
639                     xVBAModuleInfo->removeModuleInfo( _rOldName );
640                     xVBAModuleInfo->insertModuleInfo( _rNewName, sModuleInfo );
641                 }
642             }
643             xLib->insertByName( _rNewName, aElement );
644             return true;
645         }
646         catch( const Exception& )
647         {
648             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
649         }
650         return false;
651     }
652 
653 
654     bool ScriptDocument::Impl::createModule( const OUString& _rLibName, const OUString& _rModName, bool _bCreateMain, OUString& _out_rNewModuleCode ) const
655     {
656         _out_rNewModuleCode.clear();
657         try
658         {
659             Reference< XNameContainer > xLib( getLibrary( E_SCRIPTS, _rLibName, true ) );
660             if ( !xLib.is() || xLib->hasByName( _rModName ) )
661                 return false;
662 
663             // create new module
664             _out_rNewModuleCode = "REM  *****  BASIC  *****\n\n" ;
665             if ( _bCreateMain )
666                 _out_rNewModuleCode += "Sub Main\n\nEnd Sub\n" ;
667 
668             Reference< XVBAModuleInfo > xVBAModuleInfo(xLib, UNO_QUERY);
669             if (xVBAModuleInfo.is())
670             {
671                 css::script::ModuleInfo aModuleInfo;
672                 aModuleInfo.ModuleType = css::script::ModuleType::NORMAL;
673                 xVBAModuleInfo->insertModuleInfo(_rModName, aModuleInfo);
674             }
675 
676             // insert module into library
677             xLib->insertByName( _rModName, Any( _out_rNewModuleCode ) );
678         }
679         catch( const Exception& )
680         {
681             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
682             return false;
683         }
684 
685         return true;
686     }
687 
688 
689     bool ScriptDocument::Impl::insertModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rObjectName, const Any& _rElement ) const
690     {
691         try
692         {
693             Reference< XNameContainer > xLib( getOrCreateLibrary( _eType, _rLibName ), UNO_QUERY_THROW );
694             if ( xLib->hasByName( _rObjectName ) )
695                 return false;
696 
697             xLib->insertByName( _rObjectName, _rElement );
698             return true;
699         }
700         catch( const Exception& )
701         {
702             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
703         }
704         return false;
705     }
706 
707 
708     bool ScriptDocument::Impl::updateModule( const OUString& _rLibName, const OUString& _rModName, const OUString& _rModuleCode ) const
709     {
710         try
711         {
712             Reference< XNameContainer > xLib( getOrCreateLibrary( E_SCRIPTS, _rLibName ), UNO_QUERY_THROW );
713             if ( !xLib->hasByName( _rModName ) )
714                 return false;
715             xLib->replaceByName( _rModName, Any( _rModuleCode ) );
716             return true;
717         }
718         catch( const Exception& )
719         {
720             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
721         }
722         return false;
723     }
724 
725 
726     bool ScriptDocument::Impl::createDialog( const OUString& _rLibName, const OUString& _rDialogName, Reference< XInputStreamProvider >& _out_rDialogProvider ) const
727     {
728         try
729         {
730             Reference< XNameContainer > xLib( getLibrary( E_DIALOGS, _rLibName, true ), UNO_QUERY_THROW );
731 
732             // create dialog
733             _out_rDialogProvider.clear();
734             if ( xLib->hasByName( _rDialogName ) )
735                 return false;
736 
737             // create new dialog model
738             Reference< XComponentContext > aContext(
739                 comphelper::getProcessComponentContext() );
740             Reference< XNameContainer > xDialogModel(
741                 aContext->getServiceManager()->createInstanceWithContext(
742                     "com.sun.star.awt.UnoControlDialogModel", aContext ),
743                 UNO_QUERY_THROW );
744 
745             // set name property
746             Reference< XPropertySet > xDlgPSet( xDialogModel, UNO_QUERY_THROW );
747             xDlgPSet->setPropertyValue( DLGED_PROP_NAME, Any( _rDialogName ) );
748 
749             // export dialog model
750             _out_rDialogProvider = ::xmlscript::exportDialogModel( xDialogModel, aContext, isDocument() ? getDocument() : Reference< XModel >() );
751 
752             // insert dialog into library
753             xLib->insertByName( _rDialogName, Any( _out_rDialogProvider ) );
754         }
755         catch( const Exception& )
756         {
757             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
758         }
759 
760         return _out_rDialogProvider.is();
761     }
762 
763 
764     void ScriptDocument::Impl::setDocumentModified() const
765     {
766         OSL_ENSURE( isValid() && isDocument(), "ScriptDocument::Impl::setDocumentModified: only to be called for real documents!" );
767         if ( isValid() && isDocument() )
768         {
769             try
770             {
771                 m_xDocModify->setModified( true );
772             }
773             catch( const Exception& )
774             {
775                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
776             }
777         }
778     }
779 
780 
781     bool ScriptDocument::Impl::isDocumentModified() const
782     {
783         OSL_ENSURE( isValid() && isDocument(), "ScriptDocument::Impl::isDocumentModified: only to be called for real documents!" );
784         bool bIsModified = false;
785         if ( isValid() && isDocument() )
786         {
787             try
788             {
789                 bIsModified = m_xDocModify->isModified();
790             }
791             catch( const Exception& )
792             {
793                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
794             }
795         }
796         return bIsModified;
797     }
798 
799 
800     void ScriptDocument::Impl::saveDocument( const Reference< XStatusIndicator >& _rxStatusIndicator ) const
801     {
802         Reference< XFrame > xFrame;
803         if ( !getCurrentFrame( xFrame ) )
804             return;
805 
806         Sequence< PropertyValue > aArgs;
807         if ( _rxStatusIndicator.is() )
808         {
809             aArgs = ::comphelper::InitPropertySequence({
810                 { "StatusIndicator", Any(_rxStatusIndicator) }
811             });
812         }
813 
814         try
815         {
816             URL aURL;
817             aURL.Complete = ".uno:Save" ;
818             aURL.Main = aURL.Complete;
819             aURL.Protocol = ".uno:" ;
820             aURL.Path = "Save" ;
821 
822             Reference< XDispatchProvider > xDispProv( xFrame, UNO_QUERY_THROW );
823             Reference< XDispatch > xDispatch(
824                 xDispProv->queryDispatch( aURL, "_self", FrameSearchFlag::AUTO ),
825                 UNO_SET_THROW );
826 
827             xDispatch->dispatch( aURL, aArgs );
828         }
829         catch( const Exception& )
830         {
831             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
832         }
833     }
834 
835 
836     OUString ScriptDocument::Impl::getTitle() const
837     {
838         OSL_PRECOND( isValid() && isDocument(), "ScriptDocument::Impl::getTitle: for documents only!" );
839 
840         OUString sTitle;
841         if ( isValid() && isDocument() )
842         {
843             sTitle = ::comphelper::DocumentInfo::getDocumentTitle( m_xDocument );
844         }
845         return sTitle;
846     }
847 
848 
849     OUString ScriptDocument::Impl::getURL() const
850     {
851         OSL_PRECOND( isValid() && isDocument(), "ScriptDocument::Impl::getURL: for documents only!" );
852 
853         OUString sURL;
854         if ( isValid() && isDocument() )
855         {
856             try
857             {
858                 sURL = m_xDocument->getURL();
859             }
860             catch( const Exception& )
861             {
862                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
863             }
864         }
865         return sURL;
866     }
867 
868 
869     bool ScriptDocument::Impl::allowMacros() const
870     {
871         OSL_ENSURE( isValid() && isDocument(), "ScriptDocument::Impl::allowMacros: for documents only!" );
872         bool bAllow = false;
873         if ( isValid() && isDocument() )
874         {
875             try
876             {
877                 bAllow = m_xScriptAccess->getAllowMacroExecution();
878             }
879             catch( const Exception& )
880             {
881                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
882             }
883         }
884         return bAllow;
885     }
886 
887 
888     bool ScriptDocument::Impl::getCurrentFrame( Reference< XFrame >& _out_rxFrame ) const
889     {
890         _out_rxFrame.clear();
891         OSL_PRECOND( isValid() && isDocument(), "ScriptDocument::Impl::getCurrentFrame: documents only!" );
892         if ( !isValid() || !isDocument() )
893             return false;
894 
895         try
896         {
897             Reference< XModel > xDocument( m_xDocument, UNO_SET_THROW );
898             Reference< XController > xController( xDocument->getCurrentController(), UNO_SET_THROW );
899             _out_rxFrame.set( xController->getFrame(), UNO_SET_THROW );
900         }
901         catch( const Exception& )
902         {
903             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
904         }
905 
906         return _out_rxFrame.is();
907     }
908 
909 
910     bool ScriptDocument::Impl::isLibraryShared( const OUString& _rLibName, LibraryContainerType _eType )
911     {
912         bool bIsShared = false;
913         try
914         {
915             Reference< XLibraryContainer2 > xLibContainer( getLibraryContainer( _eType ), UNO_QUERY_THROW );
916 
917             if ( !xLibContainer->hasByName( _rLibName ) || !xLibContainer->isLibraryLink( _rLibName ) )
918                 return false;
919             OUString aFileURL;
920             Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
921             Reference< XUriReferenceFactory > xUriFac = UriReferenceFactory::create(xContext);
922 
923             OUString aLinkURL( xLibContainer->getLibraryLinkURL( _rLibName ) );
924             Reference< XUriReference > xUriRef( xUriFac->parse( aLinkURL ), UNO_QUERY_THROW );
925 
926             OUString aScheme = xUriRef->getScheme();
927             if ( aScheme.equalsIgnoreAsciiCase("file") )
928             {
929                 aFileURL = aLinkURL;
930             }
931             else if ( aScheme.equalsIgnoreAsciiCase("vnd.sun.star.pkg") )
932             {
933                 OUString aAuthority = xUriRef->getAuthority();
934                 if ( aAuthority.matchIgnoreAsciiCase("vnd.sun.star.expand:") )
935                 {
936                     OUString aDecodedURL( aAuthority.copy( sizeof ( "vnd.sun.star.expand:" ) - 1 ) );
937                     aDecodedURL = ::rtl::Uri::decode( aDecodedURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
938                     Reference< XMacroExpander > xMacroExpander = theMacroExpander::get(xContext);
939                     aFileURL = xMacroExpander->expandMacros( aDecodedURL );
940                 }
941             }
942 
943             if ( !aFileURL.isEmpty() )
944             {
945                 ::osl::DirectoryItem aFileItem;
946                 ::osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL );
947                 OSL_VERIFY( ::osl::DirectoryItem::get( aFileURL, aFileItem ) == ::osl::FileBase::E_None );
948                 OSL_VERIFY( aFileItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None );
949                 OUString aCanonicalFileURL( aFileStatus.getFileURL() );
950 
951                 if( aCanonicalFileURL.indexOf( "share/basic" ) >= 0 ||
952                     aCanonicalFileURL.indexOf( "share/uno_packages" ) >= 0 ||
953                     aCanonicalFileURL.indexOf( "share/extensions" ) >= 0 )
954                         bIsShared = true;
955             }
956         }
957         catch( const Exception& )
958         {
959             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
960         }
961 
962         return bIsShared;
963     }
964 
965 
966     void ScriptDocument::Impl::onDocumentCreated( const ScriptDocument& /*_rDocument*/ )
967     {
968         // not interested in
969     }
970 
971     void ScriptDocument::Impl::onDocumentOpened( const ScriptDocument& /*_rDocument*/ )
972     {
973         // not interested in
974     }
975 
976     void ScriptDocument::Impl::onDocumentSave( const ScriptDocument& /*_rDocument*/ )
977     {
978         // not interested in
979     }
980 
981     void ScriptDocument::Impl::onDocumentSaveDone( const ScriptDocument& /*_rDocument*/ )
982     {
983         // not interested in
984     }
985 
986     void ScriptDocument::Impl::onDocumentSaveAs( const ScriptDocument& /*_rDocument*/ )
987     {
988         // not interested in
989     }
990 
991     void ScriptDocument::Impl::onDocumentSaveAsDone( const ScriptDocument& /*_rDocument*/ )
992     {
993         // not interested in
994     }
995 
996     void ScriptDocument::Impl::onDocumentClosed( const ScriptDocument& _rDocument )
997     {
998         DBG_TESTSOLARMUTEX();
999         OSL_PRECOND( isValid(), "ScriptDocument::Impl::onDocumentClosed: should not be listening if I'm not valid!" );
1000 
1001         bool bMyDocument = m_xDocument == _rDocument.getDocument();
1002         OSL_PRECOND( bMyDocument, "ScriptDocument::Impl::onDocumentClosed: didn't want to know *this*!" );
1003         if ( bMyDocument )
1004         {
1005             m_bDocumentClosed = true;
1006         }
1007     }
1008 
1009 
1010     void ScriptDocument::Impl::onDocumentTitleChanged( const ScriptDocument& /*_rDocument*/ )
1011     {
1012         // not interested in
1013     }
1014 
1015     void ScriptDocument::Impl::onDocumentModeChanged( const ScriptDocument& /*_rDocument*/ )
1016     {
1017         // not interested in
1018     }
1019 
1020 
1021     ScriptDocument::ScriptDocument()
1022         :m_pImpl(new Impl)
1023     { }
1024 
1025 
1026     ScriptDocument::ScriptDocument( ScriptDocument::SpecialDocument _eType )
1027         :m_pImpl( new Impl( Reference< XModel >() ) )
1028     {
1029         OSL_ENSURE( _eType == NoDocument, "ScriptDocument::ScriptDocument: unknown SpecialDocument type!" );
1030     }
1031 
1032 
1033     ScriptDocument::ScriptDocument( const Reference< XModel >& _rxDocument )
1034         :m_pImpl( new Impl( _rxDocument ) )
1035     {
1036         OSL_ENSURE( _rxDocument.is(), "ScriptDocument::ScriptDocument: document must not be NULL!" );
1037             // a NULL document results in an uninitialized instance, and for this
1038             // purpose, there is a dedicated constructor
1039     }
1040 
1041 
1042     const ScriptDocument& ScriptDocument::getApplicationScriptDocument()
1043     {
1044         static ScriptDocument s_aApplicationScripts;
1045         return s_aApplicationScripts;
1046     }
1047 
1048 
1049     ScriptDocument ScriptDocument::getDocumentForBasicManager( const BasicManager* _pManager )
1050     {
1051         if ( _pManager == SfxApplication::GetBasicManager() )
1052             return getApplicationScriptDocument();
1053 
1054         docs::Documents aDocuments;
1055         lcl_getAllModels_throw( aDocuments, false );
1056 
1057         for (auto const& doc : aDocuments)
1058         {
1059             const BasicManager* pDocBasicManager = ::basic::BasicManagerRepository::getDocumentBasicManager( doc.xModel );
1060             if  (   ( pDocBasicManager != SfxApplication::GetBasicManager() )
1061                 &&  ( pDocBasicManager == _pManager )
1062                 )
1063             {
1064                 return ScriptDocument( doc.xModel );
1065             }
1066         }
1067 
1068         OSL_FAIL( "ScriptDocument::getDocumentForBasicManager: did not find a document for this manager!" );
1069         return ScriptDocument( NoDocument );
1070     }
1071 
1072 
1073     ScriptDocument ScriptDocument::getDocumentWithURLOrCaption( const OUString& _rUrlOrCaption )
1074     {
1075         ScriptDocument aDocument( getApplicationScriptDocument() );
1076         if ( _rUrlOrCaption.isEmpty() )
1077             return aDocument;
1078 
1079         docs::Documents aDocuments;
1080         lcl_getAllModels_throw( aDocuments, false );
1081 
1082         for (auto const& doc : aDocuments)
1083         {
1084             const ScriptDocument aCheck = ScriptDocument( doc.xModel );
1085             if  (   _rUrlOrCaption == aCheck.getTitle()
1086                 ||  _rUrlOrCaption == aCheck.m_pImpl->getURL()
1087                 )
1088             {
1089                 aDocument = aCheck;
1090                 break;
1091             }
1092         }
1093 
1094         return aDocument;
1095     }
1096 
1097 
1098     namespace
1099     {
1100         struct DocumentTitleLess
1101         {
1102             explicit DocumentTitleLess( const CollatorWrapper& _rCollator )
1103                 :m_aCollator( _rCollator )
1104             {
1105             }
1106 
1107             bool operator()( const ScriptDocument& _lhs, const ScriptDocument& _rhs ) const
1108             {
1109                 return m_aCollator.compareString( _lhs.getTitle(), _rhs.getTitle() ) < 0;
1110             }
1111         private:
1112             const CollatorWrapper   m_aCollator;
1113         };
1114     }
1115 
1116 
1117     ScriptDocuments ScriptDocument::getAllScriptDocuments( ScriptDocument::ScriptDocumentList _eListType )
1118     {
1119         ScriptDocuments aScriptDocs;
1120 
1121         // include application?
1122         if ( _eListType == AllWithApplication )
1123             aScriptDocs.push_back( getApplicationScriptDocument() );
1124 
1125         // obtain documents
1126         try
1127         {
1128             docs::Documents aDocuments;
1129             lcl_getAllModels_throw( aDocuments, true /* exclude invisible */ );
1130 
1131             for (auto const& doc : aDocuments)
1132             {
1133                 // exclude documents without script/library containers
1134                 ScriptDocument aDoc( doc.xModel );
1135                 if ( !aDoc.isValid() )
1136                     continue;
1137 
1138                 aScriptDocs.push_back( aDoc );
1139             }
1140         }
1141         catch( const Exception& )
1142         {
1143             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
1144         }
1145 
1146         // sort document list by doc title?
1147         if ( _eListType == DocumentsSorted )
1148         {
1149             CollatorWrapper aCollator( ::comphelper::getProcessComponentContext() );
1150             aCollator.loadDefaultCollator( SvtSysLocale().GetLanguageTag().getLocale(), 0 );
1151             std::sort( aScriptDocs.begin(), aScriptDocs.end(), DocumentTitleLess( aCollator ) );
1152         }
1153 
1154         return aScriptDocs;
1155     }
1156 
1157 
1158     bool ScriptDocument::operator==( const ScriptDocument& _rhs ) const
1159     {
1160         return m_pImpl->getDocumentRef() == _rhs.m_pImpl->getDocumentRef();
1161     }
1162 
1163 
1164     sal_Int32 ScriptDocument::hashCode() const
1165     {
1166         return sal::static_int_cast<sal_Int32>(reinterpret_cast< sal_IntPtr >( m_pImpl->getDocumentRef().get() ));
1167     }
1168 
1169 
1170     bool ScriptDocument::isValid() const
1171     {
1172         return m_pImpl->isValid();
1173     }
1174 
1175 
1176     bool ScriptDocument::isAlive() const
1177     {
1178         return m_pImpl->isAlive();
1179     }
1180 
1181 
1182     Reference< XLibraryContainer > ScriptDocument::getLibraryContainer( LibraryContainerType _eType ) const
1183     {
1184         return m_pImpl->getLibraryContainer( _eType );
1185     }
1186 
1187 
1188     Reference< XNameContainer > ScriptDocument::getLibrary( LibraryContainerType _eType, const OUString& _rLibName, bool _bLoadLibrary ) const
1189     {
1190         return m_pImpl->getLibrary( _eType, _rLibName, _bLoadLibrary );
1191     }
1192 
1193 
1194     bool ScriptDocument::hasLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const
1195     {
1196         return m_pImpl->hasLibrary( _eType, _rLibName );
1197     }
1198 
1199 
1200     Reference< XNameContainer > ScriptDocument::getOrCreateLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const
1201     {
1202         return m_pImpl->getOrCreateLibrary( _eType, _rLibName );
1203     }
1204 
1205 
1206     void ScriptDocument::loadLibraryIfExists( LibraryContainerType _eType, const OUString& _rLibrary )
1207     {
1208         m_pImpl->loadLibraryIfExists( _eType, _rLibrary );
1209     }
1210 
1211 
1212     Sequence< OUString > ScriptDocument::getObjectNames( LibraryContainerType _eType, const OUString& _rLibName ) const
1213     {
1214         Sequence< OUString > aModuleNames;
1215 
1216         try
1217         {
1218             if ( hasLibrary( _eType, _rLibName ) )
1219             {
1220                 Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, false ) );
1221                 if ( xLib.is() )
1222                     aModuleNames = xLib->getElementNames();
1223             }
1224         }
1225         catch( const Exception& )
1226         {
1227             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
1228         }
1229 
1230         // sort
1231         std::sort( aModuleNames.begin(), aModuleNames.end(), StringCompareLessThan );
1232 
1233         return aModuleNames;
1234     }
1235 
1236 
1237     OUString ScriptDocument::createObjectName( LibraryContainerType _eType, const OUString& _rLibName ) const
1238     {
1239         OUString aObjectName;
1240 
1241         OUString aBaseName = _eType == E_SCRIPTS ? OUString("Module") : OUString("Dialog");
1242 
1243         Sequence< OUString > aUsedNames( getObjectNames( _eType, _rLibName ) );
1244         std::set< OUString > aUsedNamesCheck;
1245         std::copy( aUsedNames.begin(), aUsedNames.end(),
1246             std::insert_iterator< std::set< OUString > >( aUsedNamesCheck, aUsedNamesCheck.begin() ) );
1247 
1248         bool bValid = false;
1249         sal_Int32 i = 1;
1250         while ( !bValid )
1251         {
1252             aObjectName = aBaseName
1253                         + OUString::number( i );
1254 
1255             if ( aUsedNamesCheck.find( aObjectName ) == aUsedNamesCheck.end() )
1256                 bValid = true;
1257 
1258             ++i;
1259         }
1260 
1261         return aObjectName;
1262     }
1263 
1264 
1265     Sequence< OUString > ScriptDocument::getLibraryNames() const
1266     {
1267         return GetMergedLibraryNames( getLibraryContainer( E_SCRIPTS ), getLibraryContainer( E_DIALOGS ) );
1268     }
1269 
1270 
1271     bool ScriptDocument::isReadOnly() const
1272     {
1273         return m_pImpl->isReadOnly();
1274     }
1275 
1276 
1277     bool ScriptDocument::isApplication() const
1278     {
1279         return m_pImpl->isApplication();
1280     }
1281 
1282     bool ScriptDocument::isInVBAMode() const
1283     {
1284         return m_pImpl->isInVBAMode();
1285     }
1286 
1287 
1288     BasicManager* ScriptDocument::getBasicManager() const
1289     {
1290         return m_pImpl->getBasicManager();
1291     }
1292 
1293 
1294     Reference< XModel > ScriptDocument::getDocument() const
1295     {
1296         return m_pImpl->getDocument();
1297     }
1298 
1299 
1300     Reference< XModel > ScriptDocument::getDocumentOrNull() const
1301     {
1302         if ( isDocument() )
1303             return m_pImpl->getDocument();
1304         return nullptr;
1305     }
1306 
1307 
1308     bool ScriptDocument::removeModule( const OUString& _rLibName, const OUString& _rModuleName ) const
1309     {
1310         return m_pImpl->removeModuleOrDialog( E_SCRIPTS, _rLibName, _rModuleName );
1311     }
1312 
1313 
1314     bool ScriptDocument::hasModule( const OUString& _rLibName, const OUString& _rModuleName ) const
1315     {
1316         return m_pImpl->hasModuleOrDialog( E_SCRIPTS, _rLibName, _rModuleName );
1317     }
1318 
1319 
1320     bool ScriptDocument::getModule( const OUString& _rLibName, const OUString& _rModName, OUString& _out_rModuleSource ) const
1321     {
1322         Any aCode;
1323         if ( !m_pImpl->getModuleOrDialog( E_SCRIPTS, _rLibName, _rModName, aCode ) )
1324             return false;
1325         OSL_VERIFY( aCode >>= _out_rModuleSource );
1326         return true;
1327     }
1328 
1329 
1330     bool ScriptDocument::renameModule( const OUString& _rLibName, const OUString& _rOldName, const OUString& _rNewName ) const
1331     {
1332         return m_pImpl->renameModuleOrDialog( E_SCRIPTS, _rLibName, _rOldName, _rNewName, nullptr );
1333     }
1334 
1335 
1336     bool ScriptDocument::createModule( const OUString& _rLibName, const OUString& _rModName, bool _bCreateMain, OUString& _out_rNewModuleCode ) const
1337     {
1338         if ( !m_pImpl->createModule( _rLibName, _rModName, _bCreateMain, _out_rNewModuleCode ) )
1339             return false;
1340 
1341         // doc shell modified
1342         MarkDocumentModified( *const_cast< ScriptDocument* >( this ) );    // here?
1343         return true;
1344     }
1345 
1346 
1347     bool ScriptDocument::insertModule( const OUString& _rLibName, const OUString& _rModName, const OUString& _rModuleCode ) const
1348     {
1349         return m_pImpl->insertModuleOrDialog( E_SCRIPTS, _rLibName, _rModName, Any( _rModuleCode ) );
1350     }
1351 
1352 
1353     bool ScriptDocument::updateModule( const OUString& _rLibName, const OUString& _rModName, const OUString& _rModuleCode ) const
1354     {
1355         return m_pImpl->updateModule( _rLibName, _rModName, _rModuleCode );
1356     }
1357 
1358 
1359     bool ScriptDocument::removeDialog( const OUString& _rLibName, const OUString& _rDialogName ) const
1360     {
1361         return m_pImpl->removeModuleOrDialog( E_DIALOGS, _rLibName, _rDialogName );
1362     }
1363 
1364 
1365     bool ScriptDocument::hasDialog( const OUString& _rLibName, const OUString& _rDialogName ) const
1366     {
1367         return m_pImpl->hasModuleOrDialog( E_DIALOGS, _rLibName, _rDialogName );
1368     }
1369 
1370 
1371     bool ScriptDocument::getDialog( const OUString& _rLibName, const OUString& _rDialogName, Reference< XInputStreamProvider >& _out_rDialogProvider ) const
1372     {
1373         Any aCode;
1374         if ( !m_pImpl->getModuleOrDialog( E_DIALOGS, _rLibName, _rDialogName, aCode ) )
1375             return false;
1376         OSL_VERIFY( aCode >>= _out_rDialogProvider );
1377         return _out_rDialogProvider.is();
1378     }
1379 
1380 
1381     bool ScriptDocument::renameDialog( const OUString& _rLibName, const OUString& _rOldName, const OUString& _rNewName, const Reference< XNameContainer >& _rxExistingDialogModel ) const
1382     {
1383         return m_pImpl->renameModuleOrDialog( E_DIALOGS, _rLibName, _rOldName, _rNewName, _rxExistingDialogModel );
1384     }
1385 
1386 
1387     bool ScriptDocument::createDialog( const OUString& _rLibName, const OUString& _rDialogName, Reference< XInputStreamProvider >& _out_rDialogProvider ) const
1388     {
1389         if ( !m_pImpl->createDialog( _rLibName, _rDialogName, _out_rDialogProvider ) )
1390             return false;
1391 
1392         MarkDocumentModified( *const_cast< ScriptDocument* >( this ) );    // here?
1393         return true;
1394     }
1395 
1396 
1397     bool ScriptDocument::insertDialog( const OUString& _rLibName, const OUString& _rDialogName, const Reference< XInputStreamProvider >& _rxDialogProvider ) const
1398     {
1399         return m_pImpl->insertModuleOrDialog( E_DIALOGS, _rLibName, _rDialogName, Any( _rxDialogProvider ) );
1400     }
1401 
1402 
1403     void ScriptDocument::setDocumentModified() const
1404     {
1405         m_pImpl->setDocumentModified();
1406     }
1407 
1408 
1409     bool ScriptDocument::isDocumentModified() const
1410     {
1411         return m_pImpl->isDocumentModified();
1412     }
1413 
1414 
1415     void ScriptDocument::saveDocument( const Reference< XStatusIndicator >& _rxStatusIndicator ) const
1416     {
1417         m_pImpl->saveDocument( _rxStatusIndicator );
1418     }
1419 
1420 
1421     LibraryLocation ScriptDocument::getLibraryLocation( const OUString& _rLibName ) const
1422     {
1423         LibraryLocation eLocation = LIBRARY_LOCATION_UNKNOWN;
1424         if ( !_rLibName.isEmpty() )
1425         {
1426             if ( isDocument() )
1427             {
1428                 eLocation = LIBRARY_LOCATION_DOCUMENT;
1429             }
1430             else
1431             {
1432                 if  (  ( hasLibrary( E_SCRIPTS, _rLibName ) && !m_pImpl->isLibraryShared( _rLibName, E_SCRIPTS ) )
1433                     || ( hasLibrary( E_DIALOGS, _rLibName ) && !m_pImpl->isLibraryShared( _rLibName, E_DIALOGS ) )
1434                     )
1435                 {
1436                     eLocation = LIBRARY_LOCATION_USER;
1437                 }
1438                 else
1439                 {
1440                     eLocation = LIBRARY_LOCATION_SHARE;
1441                 }
1442             }
1443         }
1444 
1445         return eLocation;
1446     }
1447 
1448 
1449     OUString ScriptDocument::getTitle( LibraryLocation _eLocation, LibraryType _eType ) const
1450     {
1451         OUString aTitle;
1452 
1453         switch ( _eLocation )
1454         {
1455             case LIBRARY_LOCATION_USER:
1456             {
1457                 switch ( _eType )
1458                 {
1459                 case LibraryType::Module:   aTitle = IDEResId(RID_STR_USERMACROS); break;
1460                 case LibraryType::Dialog:   aTitle = IDEResId(RID_STR_USERDIALOGS); break;
1461                 case LibraryType::All:      aTitle = IDEResId(RID_STR_USERMACROSDIALOGS); break;
1462                 default:
1463                     break;
1464                 }
1465             }
1466             break;
1467             case LIBRARY_LOCATION_SHARE:
1468             {
1469                 switch ( _eType )
1470                 {
1471                 case LibraryType::Module:   aTitle = IDEResId(RID_STR_SHAREMACROS); break;
1472                 case LibraryType::Dialog:   aTitle = IDEResId(RID_STR_SHAREDIALOGS); break;
1473                 case LibraryType::All:      aTitle = IDEResId(RID_STR_SHAREMACROSDIALOGS); break;
1474                 default:
1475                     break;
1476                 }
1477             }
1478             break;
1479             case LIBRARY_LOCATION_DOCUMENT:
1480                 aTitle = getTitle();
1481                 break;
1482             default:
1483                 break;
1484         }
1485 
1486         return aTitle;
1487     }
1488 
1489 
1490     OUString ScriptDocument::getTitle() const
1491     {
1492         return m_pImpl->getTitle();
1493     }
1494 
1495 
1496     bool ScriptDocument::isActive() const
1497     {
1498         bool bIsActive( false );
1499         try
1500         {
1501             Reference< XFrame > xFrame;
1502             if ( m_pImpl->getCurrentFrame( xFrame ) )
1503                 bIsActive = xFrame->isActive();
1504         }
1505         catch( const Exception& )
1506         {
1507             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
1508         }
1509         return bIsActive;
1510     }
1511 
1512 
1513     bool ScriptDocument::allowMacros() const
1514     {
1515         return m_pImpl->allowMacros();
1516     }
1517 
1518 } // namespace basctl
1519 
1520 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1521