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