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