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() )
436             {
437                 if ( xLibContainer.is() )
438                     xContainer.set( xLibContainer->getByName( _rLibName ), UNO_QUERY_THROW );
439             }
440 
441             if ( !xContainer.is() )
442                 throw NoSuchElementException();
443 
444             // load library
445             if ( _bLoadLibrary && !xLibContainer->isLibraryLoaded( _rLibName ) )
446                 xLibContainer->loadLibrary( _rLibName );
447         }
448         catch( const NoSuchElementException& )
449         {
450             throw;  // allowed to leave
451         }
452         catch( const Exception& )
453         {
454             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
455         }
456 
457         return xContainer;
458     }
459 
460 
461     bool ScriptDocument::Impl::hasLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const
462     {
463         bool bHas = false;
464         try
465         {
466             Reference< XLibraryContainer > xLibContainer = getLibraryContainer( _eType );
467             bHas = xLibContainer.is() && xLibContainer->hasByName( _rLibName );
468         }
469         catch( const Exception& )
470         {
471             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
472         }
473         return bHas;
474     }
475 
476 
477     Reference< XNameContainer > ScriptDocument::Impl::getOrCreateLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const
478     {
479         Reference< XNameContainer > xLibrary;
480         try
481         {
482             Reference< XLibraryContainer > xLibContainer( getLibraryContainer( _eType ), UNO_QUERY_THROW );
483             if ( xLibContainer->hasByName( _rLibName ) )
484                 xLibrary.set( xLibContainer->getByName( _rLibName ), UNO_QUERY_THROW );
485             else
486                 xLibrary.set( xLibContainer->createLibrary( _rLibName ), UNO_QUERY_THROW );
487 
488             if ( !xLibContainer->isLibraryLoaded( _rLibName ) )
489                 xLibContainer->loadLibrary( _rLibName );
490         }
491         catch( const Exception& )
492         {
493             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
494         }
495         return xLibrary;
496     }
497 
498 
499     void ScriptDocument::Impl::loadLibraryIfExists( LibraryContainerType _eType, const OUString& _rLibrary )
500     {
501         try
502         {
503             Reference< XLibraryContainer > xLibContainer( getLibraryContainer( _eType ) );
504             if ( xLibContainer.is() && xLibContainer->hasByName( _rLibrary ) && !xLibContainer->isLibraryLoaded( _rLibrary ) )
505                 xLibContainer->loadLibrary( _rLibrary );
506         }
507         catch( const Exception& )
508         {
509             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
510         }
511     }
512 
513 
514     bool ScriptDocument::Impl::removeModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rModuleName )
515     {
516         OSL_ENSURE( isValid(), "ScriptDocument::Impl::removeModuleOrDialog: invalid!" );
517         if ( isValid() )
518         {
519             try
520             {
521                 Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, true ) );
522                 if ( xLib.is() )
523                 {
524                     xLib->removeByName( _rModuleName );
525                     Reference< XVBAModuleInfo > xVBAModuleInfo(xLib, UNO_QUERY);
526                     if(xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo(_rModuleName))
527                         xVBAModuleInfo->removeModuleInfo(_rModuleName);
528                     return true;
529                 }
530             }
531             catch( const Exception& )
532             {
533                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
534             }
535         }
536         return false;
537     }
538 
539 
540     bool ScriptDocument::Impl::hasModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rModName ) const
541     {
542         OSL_ENSURE( isValid(), "ScriptDocument::Impl::hasModuleOrDialog: invalid!" );
543         if ( !isValid() )
544             return false;
545 
546         try
547         {
548             Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, true ) );
549             if ( xLib.is() )
550                 return xLib->hasByName( _rModName );
551         }
552         catch( const Exception& )
553         {
554             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
555         }
556         return false;
557     }
558 
559 
560     bool ScriptDocument::Impl::getModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rObjectName, Any& _out_rModuleOrDialog )
561     {
562         OSL_ENSURE( isValid(), "ScriptDocument::Impl::getModuleOrDialog: invalid!" );
563         if ( !isValid() )
564             return false;
565 
566         _out_rModuleOrDialog.clear();
567         try
568         {
569             Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, true ), UNO_QUERY_THROW );
570             if ( xLib->hasByName( _rObjectName ) )
571             {
572                 _out_rModuleOrDialog = xLib->getByName( _rObjectName );
573                 return true;
574             }
575         }
576         catch( const Exception& )
577         {
578             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
579         }
580         return false;
581     }
582 
583 
584     bool ScriptDocument::Impl::renameModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName,
585         const OUString& _rOldName, const OUString& _rNewName, const Reference< XNameContainer >& _rxExistingDialogModel )
586     {
587         OSL_ENSURE( isValid(), "ScriptDocument::Impl::renameModuleOrDialog: invalid!" );
588         if ( !isValid() )
589             return false;
590 
591         try
592         {
593             Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, true ), UNO_QUERY_THROW );
594 
595             // get element
596             Any aElement( xLib->getByName( _rOldName ) );
597 
598             // remove element from container
599             xLib->removeByName( _rOldName );
600 
601             // if it's a dialog, import and export, to reflect the new name
602             if ( _eType == E_DIALOGS )
603             {
604                 // create dialog model
605                 Reference< XComponentContext > aContext(
606                     comphelper::getProcessComponentContext() );
607                 Reference< XNameContainer > xDialogModel;
608                 if ( _rxExistingDialogModel.is() )
609                     xDialogModel = _rxExistingDialogModel;
610                 else
611                     xDialogModel.set(
612                         ( aContext->getServiceManager()->
613                           createInstanceWithContext(
614                               "com.sun.star.awt.UnoControlDialogModel",
615                               aContext ) ),
616                         UNO_QUERY_THROW );
617 
618                 // import dialog model
619                 Reference< XInputStreamProvider > xISP( aElement, UNO_QUERY_THROW );
620                 if ( !_rxExistingDialogModel.is() )
621                 {
622                     Reference< XInputStream > xInput( xISP->createInputStream(), UNO_QUERY_THROW );
623                     ::xmlscript::importDialogModel( xInput, xDialogModel, aContext, isDocument() ? getDocument() : Reference< XModel >() );
624                 }
625 
626                 // set new name as property
627                 Reference< XPropertySet > xDlgPSet( xDialogModel, UNO_QUERY_THROW );
628                 xDlgPSet->setPropertyValue( DLGED_PROP_NAME, Any( _rNewName ) );
629 
630                 // export dialog model
631                 xISP = ::xmlscript::exportDialogModel( xDialogModel, aContext, isDocument() ? getDocument() : Reference< XModel >() );
632                 aElement <<= xISP;
633             }
634 
635             // insert element by new name in container
636             if ( _eType == E_SCRIPTS )
637             {
638                 Reference< XVBAModuleInfo > xVBAModuleInfo( xLib, UNO_QUERY );
639                 if ( xVBAModuleInfo.is() && xVBAModuleInfo->hasModuleInfo( _rOldName ) )
640                 {
641                     ModuleInfo sModuleInfo = xVBAModuleInfo->getModuleInfo( _rOldName );
642                     xVBAModuleInfo->removeModuleInfo( _rOldName );
643                     xVBAModuleInfo->insertModuleInfo( _rNewName, sModuleInfo );
644                 }
645             }
646             xLib->insertByName( _rNewName, aElement );
647             return true;
648         }
649         catch( const Exception& )
650         {
651             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
652         }
653         return false;
654     }
655 
656 
657     bool ScriptDocument::Impl::createModule( const OUString& _rLibName, const OUString& _rModName, bool _bCreateMain, OUString& _out_rNewModuleCode ) const
658     {
659         _out_rNewModuleCode.clear();
660         try
661         {
662             Reference< XNameContainer > xLib( getLibrary( E_SCRIPTS, _rLibName, true ) );
663             if ( !xLib.is() || xLib->hasByName( _rModName ) )
664                 return false;
665 
666             // create new module
667             _out_rNewModuleCode = "REM  *****  BASIC  *****\n\n" ;
668             if ( _bCreateMain )
669                 _out_rNewModuleCode += "Sub Main\n\nEnd Sub\n" ;
670 
671             Reference< XVBAModuleInfo > xVBAModuleInfo(xLib, UNO_QUERY);
672             if (xVBAModuleInfo.is())
673             {
674                 css::script::ModuleInfo aModuleInfo;
675                 aModuleInfo.ModuleType = css::script::ModuleType::NORMAL;
676                 xVBAModuleInfo->insertModuleInfo(_rModName, aModuleInfo);
677             }
678 
679             // insert module into library
680             xLib->insertByName( _rModName, Any( _out_rNewModuleCode ) );
681         }
682         catch( const Exception& )
683         {
684             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
685             return false;
686         }
687 
688         return true;
689     }
690 
691 
692     bool ScriptDocument::Impl::insertModuleOrDialog( LibraryContainerType _eType, const OUString& _rLibName, const OUString& _rObjectName, const Any& _rElement ) const
693     {
694         try
695         {
696             Reference< XNameContainer > xLib( getOrCreateLibrary( _eType, _rLibName ), UNO_QUERY_THROW );
697             if ( xLib->hasByName( _rObjectName ) )
698                 return false;
699 
700             xLib->insertByName( _rObjectName, _rElement );
701             return true;
702         }
703         catch( const Exception& )
704         {
705             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
706         }
707         return false;
708     }
709 
710 
711     bool ScriptDocument::Impl::updateModule( const OUString& _rLibName, const OUString& _rModName, const OUString& _rModuleCode ) const
712     {
713         try
714         {
715             Reference< XNameContainer > xLib( getOrCreateLibrary( E_SCRIPTS, _rLibName ), UNO_QUERY_THROW );
716             if ( !xLib->hasByName( _rModName ) )
717                 return false;
718             xLib->replaceByName( _rModName, Any( _rModuleCode ) );
719             return true;
720         }
721         catch( const Exception& )
722         {
723             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
724         }
725         return false;
726     }
727 
728 
729     bool ScriptDocument::Impl::createDialog( const OUString& _rLibName, const OUString& _rDialogName, Reference< XInputStreamProvider >& _out_rDialogProvider ) const
730     {
731         try
732         {
733             Reference< XNameContainer > xLib( getLibrary( E_DIALOGS, _rLibName, true ), UNO_QUERY_THROW );
734 
735             // create dialog
736             _out_rDialogProvider.clear();
737             if ( xLib->hasByName( _rDialogName ) )
738                 return false;
739 
740             // create new dialog model
741             Reference< XComponentContext > aContext(
742                 comphelper::getProcessComponentContext() );
743             Reference< XNameContainer > xDialogModel(
744                 aContext->getServiceManager()->createInstanceWithContext(
745                     "com.sun.star.awt.UnoControlDialogModel", aContext ),
746                 UNO_QUERY_THROW );
747 
748             // set name property
749             Reference< XPropertySet > xDlgPSet( xDialogModel, UNO_QUERY_THROW );
750             xDlgPSet->setPropertyValue( DLGED_PROP_NAME, Any( _rDialogName ) );
751 
752             // export dialog model
753             _out_rDialogProvider = ::xmlscript::exportDialogModel( xDialogModel, aContext, isDocument() ? getDocument() : Reference< XModel >() );
754 
755             // insert dialog into library
756             xLib->insertByName( _rDialogName, Any( _out_rDialogProvider ) );
757         }
758         catch( const Exception& )
759         {
760             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
761         }
762 
763         return _out_rDialogProvider.is();
764     }
765 
766 
767     void ScriptDocument::Impl::setDocumentModified() const
768     {
769         OSL_ENSURE( isValid() && isDocument(), "ScriptDocument::Impl::setDocumentModified: only to be called for real documents!" );
770         if ( isValid() && isDocument() )
771         {
772             try
773             {
774                 m_xDocModify->setModified( true );
775             }
776             catch( const Exception& )
777             {
778                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
779             }
780         }
781     }
782 
783 
784     bool ScriptDocument::Impl::isDocumentModified() const
785     {
786         OSL_ENSURE( isValid() && isDocument(), "ScriptDocument::Impl::isDocumentModified: only to be called for real documents!" );
787         bool bIsModified = false;
788         if ( isValid() && isDocument() )
789         {
790             try
791             {
792                 bIsModified = m_xDocModify->isModified();
793             }
794             catch( const Exception& )
795             {
796                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
797             }
798         }
799         return bIsModified;
800     }
801 
802 
803     void ScriptDocument::Impl::saveDocument( const Reference< XStatusIndicator >& _rxStatusIndicator ) const
804     {
805         Reference< XFrame > xFrame;
806         if ( !getCurrentFrame( xFrame ) )
807             return;
808 
809         Sequence< PropertyValue > aArgs;
810         if ( _rxStatusIndicator.is() )
811         {
812             aArgs = ::comphelper::InitPropertySequence({
813                 { "StatusIndicator", Any(_rxStatusIndicator) }
814             });
815         }
816 
817         try
818         {
819             URL aURL;
820             aURL.Complete = ".uno:Save" ;
821             aURL.Main = aURL.Complete;
822             aURL.Protocol = ".uno:" ;
823             aURL.Path = "Save" ;
824 
825             Reference< XDispatchProvider > xDispProv( xFrame, UNO_QUERY_THROW );
826             Reference< XDispatch > xDispatch(
827                 xDispProv->queryDispatch( aURL, "_self", FrameSearchFlag::AUTO ),
828                 UNO_SET_THROW );
829 
830             xDispatch->dispatch( aURL, aArgs );
831         }
832         catch( const Exception& )
833         {
834             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
835         }
836     }
837 
838 
839     OUString ScriptDocument::Impl::getTitle() const
840     {
841         OSL_PRECOND( isValid() && isDocument(), "ScriptDocument::Impl::getTitle: for documents only!" );
842 
843         OUString sTitle;
844         if ( isValid() && isDocument() )
845         {
846             sTitle = ::comphelper::DocumentInfo::getDocumentTitle( m_xDocument );
847         }
848         return sTitle;
849     }
850 
851 
852     OUString ScriptDocument::Impl::getURL() const
853     {
854         OSL_PRECOND( isValid() && isDocument(), "ScriptDocument::Impl::getURL: for documents only!" );
855 
856         OUString sURL;
857         if ( isValid() && isDocument() )
858         {
859             try
860             {
861                 sURL = m_xDocument->getURL();
862             }
863             catch( const Exception& )
864             {
865                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
866             }
867         }
868         return sURL;
869     }
870 
871 
872     bool ScriptDocument::Impl::allowMacros() const
873     {
874         OSL_ENSURE( isValid() && isDocument(), "ScriptDocument::Impl::allowMacros: for documents only!" );
875         bool bAllow = false;
876         if ( isValid() && isDocument() )
877         {
878             try
879             {
880                 bAllow = m_xScriptAccess->getAllowMacroExecution();
881             }
882             catch( const Exception& )
883             {
884                 DBG_UNHANDLED_EXCEPTION("basctl.basicide");
885             }
886         }
887         return bAllow;
888     }
889 
890 
891     bool ScriptDocument::Impl::getCurrentFrame( Reference< XFrame >& _out_rxFrame ) const
892     {
893         _out_rxFrame.clear();
894         OSL_PRECOND( isValid() && isDocument(), "ScriptDocument::Impl::getCurrentFrame: documents only!" );
895         if ( !isValid() || !isDocument() )
896             return false;
897 
898         try
899         {
900             Reference< XModel > xDocument( m_xDocument, UNO_SET_THROW );
901             Reference< XController > xController( xDocument->getCurrentController(), UNO_SET_THROW );
902             _out_rxFrame.set( xController->getFrame(), UNO_SET_THROW );
903         }
904         catch( const Exception& )
905         {
906             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
907         }
908 
909         return _out_rxFrame.is();
910     }
911 
912 
913     bool ScriptDocument::Impl::isLibraryShared( const OUString& _rLibName, LibraryContainerType _eType )
914     {
915         bool bIsShared = false;
916         try
917         {
918             Reference< XLibraryContainer2 > xLibContainer( getLibraryContainer( _eType ), UNO_QUERY_THROW );
919 
920             if ( !xLibContainer->hasByName( _rLibName ) || !xLibContainer->isLibraryLink( _rLibName ) )
921                 return false;
922             OUString aFileURL;
923             Reference< XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
924             Reference< XUriReferenceFactory > xUriFac = UriReferenceFactory::create(xContext);
925 
926             OUString aLinkURL( xLibContainer->getLibraryLinkURL( _rLibName ) );
927             Reference< XUriReference > xUriRef( xUriFac->parse( aLinkURL ), UNO_QUERY_THROW );
928 
929             OUString aScheme = xUriRef->getScheme();
930             if ( aScheme.equalsIgnoreAsciiCase("file") )
931             {
932                 aFileURL = aLinkURL;
933             }
934             else if ( aScheme.equalsIgnoreAsciiCase("vnd.sun.star.pkg") )
935             {
936                 OUString aAuthority = xUriRef->getAuthority();
937                 if ( aAuthority.matchIgnoreAsciiCase("vnd.sun.star.expand:") )
938                 {
939                     OUString aDecodedURL( aAuthority.copy( sizeof ( "vnd.sun.star.expand:" ) - 1 ) );
940                     aDecodedURL = ::rtl::Uri::decode( aDecodedURL, rtl_UriDecodeWithCharset, RTL_TEXTENCODING_UTF8 );
941                     Reference< XMacroExpander > xMacroExpander = theMacroExpander::get(xContext);
942                     aFileURL = xMacroExpander->expandMacros( aDecodedURL );
943                 }
944             }
945 
946             if ( !aFileURL.isEmpty() )
947             {
948                 ::osl::DirectoryItem aFileItem;
949                 ::osl::FileStatus aFileStatus( osl_FileStatus_Mask_FileURL );
950                 OSL_VERIFY( ::osl::DirectoryItem::get( aFileURL, aFileItem ) == ::osl::FileBase::E_None );
951                 OSL_VERIFY( aFileItem.getFileStatus( aFileStatus ) == ::osl::FileBase::E_None );
952                 OUString aCanonicalFileURL( aFileStatus.getFileURL() );
953 
954                 if( aCanonicalFileURL.indexOf( "share/basic" ) >= 0 ||
955                     aCanonicalFileURL.indexOf( "share/uno_packages" ) >= 0 ||
956                     aCanonicalFileURL.indexOf( "share/extensions" ) >= 0 )
957                         bIsShared = true;
958             }
959         }
960         catch( const Exception& )
961         {
962             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
963         }
964 
965         return bIsShared;
966     }
967 
968 
969     void ScriptDocument::Impl::onDocumentCreated( const ScriptDocument& /*_rDocument*/ )
970     {
971         // not interested in
972     }
973 
974     void ScriptDocument::Impl::onDocumentOpened( const ScriptDocument& /*_rDocument*/ )
975     {
976         // not interested in
977     }
978 
979     void ScriptDocument::Impl::onDocumentSave( const ScriptDocument& /*_rDocument*/ )
980     {
981         // not interested in
982     }
983 
984     void ScriptDocument::Impl::onDocumentSaveDone( const ScriptDocument& /*_rDocument*/ )
985     {
986         // not interested in
987     }
988 
989     void ScriptDocument::Impl::onDocumentSaveAs( const ScriptDocument& /*_rDocument*/ )
990     {
991         // not interested in
992     }
993 
994     void ScriptDocument::Impl::onDocumentSaveAsDone( const ScriptDocument& /*_rDocument*/ )
995     {
996         // not interested in
997     }
998 
999     void ScriptDocument::Impl::onDocumentClosed( const ScriptDocument& _rDocument )
1000     {
1001         DBG_TESTSOLARMUTEX();
1002         OSL_PRECOND( isValid(), "ScriptDocument::Impl::onDocumentClosed: should not be listening if I'm not valid!" );
1003 
1004         bool bMyDocument = m_xDocument == _rDocument.getDocument();
1005         OSL_PRECOND( bMyDocument, "ScriptDocument::Impl::onDocumentClosed: didn't want to know *this*!" );
1006         if ( bMyDocument )
1007         {
1008             m_bDocumentClosed = true;
1009         }
1010     }
1011 
1012 
1013     void ScriptDocument::Impl::onDocumentTitleChanged( const ScriptDocument& /*_rDocument*/ )
1014     {
1015         // not interested in
1016     }
1017 
1018     void ScriptDocument::Impl::onDocumentModeChanged( const ScriptDocument& /*_rDocument*/ )
1019     {
1020         // not interested in
1021     }
1022 
1023 
1024     ScriptDocument::ScriptDocument()
1025         :m_pImpl(new Impl)
1026     { }
1027 
1028 
1029     ScriptDocument::ScriptDocument( ScriptDocument::SpecialDocument _eType )
1030         :m_pImpl( new Impl( Reference< XModel >() ) )
1031     {
1032         OSL_ENSURE( _eType == NoDocument, "ScriptDocument::ScriptDocument: unknown SpecialDocument type!" );
1033     }
1034 
1035 
1036     ScriptDocument::ScriptDocument( const Reference< XModel >& _rxDocument )
1037         :m_pImpl( new Impl( _rxDocument ) )
1038     {
1039         OSL_ENSURE( _rxDocument.is(), "ScriptDocument::ScriptDocument: document must not be NULL!" );
1040             // a NULL document results in an uninitialized instance, and for this
1041             // purpose, there is a dedicated constructor
1042     }
1043 
1044 
1045     const ScriptDocument& ScriptDocument::getApplicationScriptDocument()
1046     {
1047         static ScriptDocument s_aApplicationScripts;
1048         return s_aApplicationScripts;
1049     }
1050 
1051 
1052     ScriptDocument ScriptDocument::getDocumentForBasicManager( const BasicManager* _pManager )
1053     {
1054         if ( _pManager == SfxApplication::GetBasicManager() )
1055             return getApplicationScriptDocument();
1056 
1057         docs::Documents aDocuments;
1058         lcl_getAllModels_throw( aDocuments, false );
1059 
1060         for (auto const& doc : aDocuments)
1061         {
1062             const BasicManager* pDocBasicManager = ::basic::BasicManagerRepository::getDocumentBasicManager( doc.xModel );
1063             if  (   ( pDocBasicManager != SfxApplication::GetBasicManager() )
1064                 &&  ( pDocBasicManager == _pManager )
1065                 )
1066             {
1067                 return ScriptDocument( doc.xModel );
1068             }
1069         }
1070 
1071         OSL_FAIL( "ScriptDocument::getDocumentForBasicManager: did not find a document for this manager!" );
1072         return ScriptDocument( NoDocument );
1073     }
1074 
1075 
1076     ScriptDocument ScriptDocument::getDocumentWithURLOrCaption( const OUString& _rUrlOrCaption )
1077     {
1078         ScriptDocument aDocument( getApplicationScriptDocument() );
1079         if ( _rUrlOrCaption.isEmpty() )
1080             return aDocument;
1081 
1082         docs::Documents aDocuments;
1083         lcl_getAllModels_throw( aDocuments, false );
1084 
1085         for (auto const& doc : aDocuments)
1086         {
1087             const ScriptDocument aCheck = ScriptDocument( doc.xModel );
1088             if  (   _rUrlOrCaption == aCheck.getTitle()
1089                 ||  _rUrlOrCaption == aCheck.m_pImpl->getURL()
1090                 )
1091             {
1092                 aDocument = aCheck;
1093                 break;
1094             }
1095         }
1096 
1097         return aDocument;
1098     }
1099 
1100 
1101     namespace
1102     {
1103         struct DocumentTitleLess
1104         {
1105             explicit DocumentTitleLess( const CollatorWrapper& _rCollator )
1106                 :m_aCollator( _rCollator )
1107             {
1108             }
1109 
1110             bool operator()( const ScriptDocument& _lhs, const ScriptDocument& _rhs ) const
1111             {
1112                 return m_aCollator.compareString( _lhs.getTitle(), _rhs.getTitle() ) < 0;
1113             }
1114         private:
1115             const CollatorWrapper   m_aCollator;
1116         };
1117     }
1118 
1119 
1120     ScriptDocuments ScriptDocument::getAllScriptDocuments( ScriptDocument::ScriptDocumentList _eListType )
1121     {
1122         ScriptDocuments aScriptDocs;
1123 
1124         // include application?
1125         if ( _eListType == AllWithApplication )
1126             aScriptDocs.push_back( getApplicationScriptDocument() );
1127 
1128         // obtain documents
1129         try
1130         {
1131             docs::Documents aDocuments;
1132             lcl_getAllModels_throw( aDocuments, true /* exclude invisible */ );
1133 
1134             for (auto const& doc : aDocuments)
1135             {
1136                 // exclude documents without script/library containers
1137                 ScriptDocument aDoc( doc.xModel );
1138                 if ( !aDoc.isValid() )
1139                     continue;
1140 
1141                 aScriptDocs.push_back( aDoc );
1142             }
1143         }
1144         catch( const Exception& )
1145         {
1146             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
1147         }
1148 
1149         // sort document list by doc title?
1150         if ( _eListType == DocumentsSorted )
1151         {
1152             CollatorWrapper aCollator( ::comphelper::getProcessComponentContext() );
1153             aCollator.loadDefaultCollator( SvtSysLocale().GetLanguageTag().getLocale(), 0 );
1154             std::sort( aScriptDocs.begin(), aScriptDocs.end(), DocumentTitleLess( aCollator ) );
1155         }
1156 
1157         return aScriptDocs;
1158     }
1159 
1160 
1161     bool ScriptDocument::operator==( const ScriptDocument& _rhs ) const
1162     {
1163         return m_pImpl->getDocumentRef() == _rhs.m_pImpl->getDocumentRef();
1164     }
1165 
1166 
1167     sal_Int32 ScriptDocument::hashCode() const
1168     {
1169         return sal::static_int_cast<sal_Int32>(reinterpret_cast< sal_IntPtr >( m_pImpl->getDocumentRef().get() ));
1170     }
1171 
1172 
1173     bool ScriptDocument::isValid() const
1174     {
1175         return m_pImpl->isValid();
1176     }
1177 
1178 
1179     bool ScriptDocument::isAlive() const
1180     {
1181         return m_pImpl->isAlive();
1182     }
1183 
1184 
1185     Reference< XLibraryContainer > ScriptDocument::getLibraryContainer( LibraryContainerType _eType ) const
1186     {
1187         return m_pImpl->getLibraryContainer( _eType );
1188     }
1189 
1190 
1191     Reference< XNameContainer > ScriptDocument::getLibrary( LibraryContainerType _eType, const OUString& _rLibName, bool _bLoadLibrary ) const
1192     {
1193         return m_pImpl->getLibrary( _eType, _rLibName, _bLoadLibrary );
1194     }
1195 
1196 
1197     bool ScriptDocument::hasLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const
1198     {
1199         return m_pImpl->hasLibrary( _eType, _rLibName );
1200     }
1201 
1202 
1203     Reference< XNameContainer > ScriptDocument::getOrCreateLibrary( LibraryContainerType _eType, const OUString& _rLibName ) const
1204     {
1205         return m_pImpl->getOrCreateLibrary( _eType, _rLibName );
1206     }
1207 
1208 
1209     void ScriptDocument::loadLibraryIfExists( LibraryContainerType _eType, const OUString& _rLibrary )
1210     {
1211         m_pImpl->loadLibraryIfExists( _eType, _rLibrary );
1212     }
1213 
1214 
1215     Sequence< OUString > ScriptDocument::getObjectNames( LibraryContainerType _eType, const OUString& _rLibName ) const
1216     {
1217         Sequence< OUString > aModuleNames;
1218 
1219         try
1220         {
1221             if ( hasLibrary( _eType, _rLibName ) )
1222             {
1223                 Reference< XNameContainer > xLib( getLibrary( _eType, _rLibName, false ) );
1224                 if ( xLib.is() )
1225                     aModuleNames = xLib->getElementNames();
1226             }
1227         }
1228         catch( const Exception& )
1229         {
1230             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
1231         }
1232 
1233         // sort
1234         std::sort( aModuleNames.begin(), aModuleNames.end(), StringCompareLessThan );
1235 
1236         return aModuleNames;
1237     }
1238 
1239 
1240     OUString ScriptDocument::createObjectName( LibraryContainerType _eType, const OUString& _rLibName ) const
1241     {
1242         OUString aObjectName;
1243 
1244         OUString aBaseName = _eType == E_SCRIPTS ? OUString("Module") : OUString("Dialog");
1245 
1246         Sequence< OUString > aUsedNames( getObjectNames( _eType, _rLibName ) );
1247         std::set< OUString > aUsedNamesCheck;
1248         std::copy( aUsedNames.begin(), aUsedNames.end(),
1249             std::insert_iterator< std::set< OUString > >( aUsedNamesCheck, aUsedNamesCheck.begin() ) );
1250 
1251         bool bValid = false;
1252         sal_Int32 i = 1;
1253         while ( !bValid )
1254         {
1255             aObjectName = aBaseName
1256                         + OUString::number( i );
1257 
1258             if ( aUsedNamesCheck.find( aObjectName ) == aUsedNamesCheck.end() )
1259                 bValid = true;
1260 
1261             ++i;
1262         }
1263 
1264         return aObjectName;
1265     }
1266 
1267 
1268     Sequence< OUString > ScriptDocument::getLibraryNames() const
1269     {
1270         return GetMergedLibraryNames( getLibraryContainer( E_SCRIPTS ), getLibraryContainer( E_DIALOGS ) );
1271     }
1272 
1273 
1274     bool ScriptDocument::isReadOnly() const
1275     {
1276         return m_pImpl->isReadOnly();
1277     }
1278 
1279 
1280     bool ScriptDocument::isApplication() const
1281     {
1282         return m_pImpl->isApplication();
1283     }
1284 
1285     bool ScriptDocument::isInVBAMode() const
1286     {
1287         return m_pImpl->isInVBAMode();
1288     }
1289 
1290 
1291     BasicManager* ScriptDocument::getBasicManager() const
1292     {
1293         return m_pImpl->getBasicManager();
1294     }
1295 
1296 
1297     Reference< XModel > ScriptDocument::getDocument() const
1298     {
1299         return m_pImpl->getDocument();
1300     }
1301 
1302 
1303     Reference< XModel > ScriptDocument::getDocumentOrNull() const
1304     {
1305         if ( isDocument() )
1306             return m_pImpl->getDocument();
1307         return nullptr;
1308     }
1309 
1310 
1311     bool ScriptDocument::removeModule( const OUString& _rLibName, const OUString& _rModuleName ) const
1312     {
1313         return m_pImpl->removeModuleOrDialog( E_SCRIPTS, _rLibName, _rModuleName );
1314     }
1315 
1316 
1317     bool ScriptDocument::hasModule( const OUString& _rLibName, const OUString& _rModuleName ) const
1318     {
1319         return m_pImpl->hasModuleOrDialog( E_SCRIPTS, _rLibName, _rModuleName );
1320     }
1321 
1322 
1323     bool ScriptDocument::getModule( const OUString& _rLibName, const OUString& _rModName, OUString& _out_rModuleSource ) const
1324     {
1325         Any aCode;
1326         if ( !m_pImpl->getModuleOrDialog( E_SCRIPTS, _rLibName, _rModName, aCode ) )
1327             return false;
1328         OSL_VERIFY( aCode >>= _out_rModuleSource );
1329         return true;
1330     }
1331 
1332 
1333     bool ScriptDocument::renameModule( const OUString& _rLibName, const OUString& _rOldName, const OUString& _rNewName ) const
1334     {
1335         return m_pImpl->renameModuleOrDialog( E_SCRIPTS, _rLibName, _rOldName, _rNewName, nullptr );
1336     }
1337 
1338 
1339     bool ScriptDocument::createModule( const OUString& _rLibName, const OUString& _rModName, bool _bCreateMain, OUString& _out_rNewModuleCode ) const
1340     {
1341         if ( !m_pImpl->createModule( _rLibName, _rModName, _bCreateMain, _out_rNewModuleCode ) )
1342             return false;
1343 
1344         // doc shell modified
1345         MarkDocumentModified( *const_cast< ScriptDocument* >( this ) );    // here?
1346         return true;
1347     }
1348 
1349 
1350     bool ScriptDocument::insertModule( const OUString& _rLibName, const OUString& _rModName, const OUString& _rModuleCode ) const
1351     {
1352         return m_pImpl->insertModuleOrDialog( E_SCRIPTS, _rLibName, _rModName, Any( _rModuleCode ) );
1353     }
1354 
1355 
1356     bool ScriptDocument::updateModule( const OUString& _rLibName, const OUString& _rModName, const OUString& _rModuleCode ) const
1357     {
1358         return m_pImpl->updateModule( _rLibName, _rModName, _rModuleCode );
1359     }
1360 
1361 
1362     bool ScriptDocument::removeDialog( const OUString& _rLibName, const OUString& _rDialogName ) const
1363     {
1364         return m_pImpl->removeModuleOrDialog( E_DIALOGS, _rLibName, _rDialogName );
1365     }
1366 
1367 
1368     bool ScriptDocument::hasDialog( const OUString& _rLibName, const OUString& _rDialogName ) const
1369     {
1370         return m_pImpl->hasModuleOrDialog( E_DIALOGS, _rLibName, _rDialogName );
1371     }
1372 
1373 
1374     bool ScriptDocument::getDialog( const OUString& _rLibName, const OUString& _rDialogName, Reference< XInputStreamProvider >& _out_rDialogProvider ) const
1375     {
1376         Any aCode;
1377         if ( !m_pImpl->getModuleOrDialog( E_DIALOGS, _rLibName, _rDialogName, aCode ) )
1378             return false;
1379         OSL_VERIFY( aCode >>= _out_rDialogProvider );
1380         return _out_rDialogProvider.is();
1381     }
1382 
1383 
1384     bool ScriptDocument::renameDialog( const OUString& _rLibName, const OUString& _rOldName, const OUString& _rNewName, const Reference< XNameContainer >& _rxExistingDialogModel ) const
1385     {
1386         return m_pImpl->renameModuleOrDialog( E_DIALOGS, _rLibName, _rOldName, _rNewName, _rxExistingDialogModel );
1387     }
1388 
1389 
1390     bool ScriptDocument::createDialog( const OUString& _rLibName, const OUString& _rDialogName, Reference< XInputStreamProvider >& _out_rDialogProvider ) const
1391     {
1392         if ( !m_pImpl->createDialog( _rLibName, _rDialogName, _out_rDialogProvider ) )
1393             return false;
1394 
1395         MarkDocumentModified( *const_cast< ScriptDocument* >( this ) );    // here?
1396         return true;
1397     }
1398 
1399 
1400     bool ScriptDocument::insertDialog( const OUString& _rLibName, const OUString& _rDialogName, const Reference< XInputStreamProvider >& _rxDialogProvider ) const
1401     {
1402         return m_pImpl->insertModuleOrDialog( E_DIALOGS, _rLibName, _rDialogName, Any( _rxDialogProvider ) );
1403     }
1404 
1405 
1406     void ScriptDocument::setDocumentModified() const
1407     {
1408         m_pImpl->setDocumentModified();
1409     }
1410 
1411 
1412     bool ScriptDocument::isDocumentModified() const
1413     {
1414         return m_pImpl->isDocumentModified();
1415     }
1416 
1417 
1418     void ScriptDocument::saveDocument( const Reference< XStatusIndicator >& _rxStatusIndicator ) const
1419     {
1420         m_pImpl->saveDocument( _rxStatusIndicator );
1421     }
1422 
1423 
1424     LibraryLocation ScriptDocument::getLibraryLocation( const OUString& _rLibName ) const
1425     {
1426         LibraryLocation eLocation = LIBRARY_LOCATION_UNKNOWN;
1427         if ( !_rLibName.isEmpty() )
1428         {
1429             if ( isDocument() )
1430             {
1431                 eLocation = LIBRARY_LOCATION_DOCUMENT;
1432             }
1433             else
1434             {
1435                 if  (  ( hasLibrary( E_SCRIPTS, _rLibName ) && !m_pImpl->isLibraryShared( _rLibName, E_SCRIPTS ) )
1436                     || ( hasLibrary( E_DIALOGS, _rLibName ) && !m_pImpl->isLibraryShared( _rLibName, E_DIALOGS ) )
1437                     )
1438                 {
1439                     eLocation = LIBRARY_LOCATION_USER;
1440                 }
1441                 else
1442                 {
1443                     eLocation = LIBRARY_LOCATION_SHARE;
1444                 }
1445             }
1446         }
1447 
1448         return eLocation;
1449     }
1450 
1451 
1452     OUString ScriptDocument::getTitle( LibraryLocation _eLocation, LibraryType _eType ) const
1453     {
1454         OUString aTitle;
1455 
1456         switch ( _eLocation )
1457         {
1458             case LIBRARY_LOCATION_USER:
1459             {
1460                 switch ( _eType )
1461                 {
1462                 case LibraryType::Module:   aTitle = IDEResId(RID_STR_USERMACROS); break;
1463                 case LibraryType::Dialog:   aTitle = IDEResId(RID_STR_USERDIALOGS); break;
1464                 case LibraryType::All:      aTitle = IDEResId(RID_STR_USERMACROSDIALOGS); break;
1465                 default:
1466                     break;
1467                 }
1468             }
1469             break;
1470             case LIBRARY_LOCATION_SHARE:
1471             {
1472                 switch ( _eType )
1473                 {
1474                 case LibraryType::Module:   aTitle = IDEResId(RID_STR_SHAREMACROS); break;
1475                 case LibraryType::Dialog:   aTitle = IDEResId(RID_STR_SHAREDIALOGS); break;
1476                 case LibraryType::All:      aTitle = IDEResId(RID_STR_SHAREMACROSDIALOGS); break;
1477                 default:
1478                     break;
1479                 }
1480             }
1481             break;
1482             case LIBRARY_LOCATION_DOCUMENT:
1483                 aTitle = getTitle();
1484                 break;
1485             default:
1486                 break;
1487         }
1488 
1489         return aTitle;
1490     }
1491 
1492 
1493     OUString ScriptDocument::getTitle() const
1494     {
1495         return m_pImpl->getTitle();
1496     }
1497 
1498 
1499     bool ScriptDocument::isActive() const
1500     {
1501         bool bIsActive( false );
1502         try
1503         {
1504             Reference< XFrame > xFrame;
1505             if ( m_pImpl->getCurrentFrame( xFrame ) )
1506                 bIsActive = xFrame->isActive();
1507         }
1508         catch( const Exception& )
1509         {
1510             DBG_UNHANDLED_EXCEPTION("basctl.basicide");
1511         }
1512         return bIsActive;
1513     }
1514 
1515 
1516     bool ScriptDocument::allowMacros() const
1517     {
1518         return m_pImpl->allowMacros();
1519     }
1520 
1521 } // namespace basctl
1522 
1523 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1524