xref: /trunk/main/basic/source/classes/sbxmod.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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_basic.hxx"
30 
31 #include <list>
32 
33 #include <vos/macros.hxx>
34 #include <vcl/svapp.hxx>
35 #include <tools/stream.hxx>
36 #include <svl/brdcst.hxx>
37 #include <tools/shl.hxx>
38 #include <basic/sbx.hxx>
39 #include "sbdiagnose.hxx"
40 #include "sb.hxx"
41 #include <sbjsmeth.hxx>
42 #include "sbjsmod.hxx"
43 #include "sbintern.hxx"
44 #include "image.hxx"
45 #include "opcodes.hxx"
46 #include "runtime.hxx"
47 #include "token.hxx"
48 #include "sbunoobj.hxx"
49 #include "sbtrace.hxx"
50 
51 
52 //#include <basic/hilight.hxx>
53 #include <svtools/syntaxhighlight.hxx>
54 
55 #include <basic/basrdll.hxx>
56 #include <vos/mutex.hxx>
57 #include <basic/sbobjmod.hxx>
58 #include <basic/vbahelper.hxx>
59 #include <cppuhelper/implbase3.hxx>
60 #include <unotools/eventcfg.hxx>
61 #include <com/sun/star/lang/XServiceInfo.hpp>
62 #include <com/sun/star/script/ModuleType.hpp>
63 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
64 #include <com/sun/star/script/vba/VBAScriptEventId.hpp>
65 #include <com/sun/star/beans/XPropertySet.hpp>
66 #include <com/sun/star/document/XEventBroadcaster.hpp>
67 #include <com/sun/star/document/XEventListener.hpp>
68 
69 using namespace com::sun::star;
70 
71 // for the bsearch
72 #ifdef WNT
73 #define CDECL _cdecl
74 #endif
75 #if defined(UNX) || defined(OS2)
76 #define CDECL
77 #endif
78 #ifdef UNX
79 #include <sys/resource.h>
80 #endif
81 
82 #include <stdio.h>
83 #include <com/sun/star/frame/XDesktop.hpp>
84 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
85 #include <comphelper/processfactory.hxx>
86 #include <vcl/svapp.hxx>
87 #include <map>
88 #include <com/sun/star/reflection/XProxyFactory.hpp>
89 #include <cppuhelper/implbase1.hxx>
90 #include <basic/sbobjmod.hxx>
91 #include <com/sun/star/uno/XAggregation.hpp>
92 #include <com/sun/star/script/XInvocation.hpp>
93 
94 using namespace com::sun::star::lang;
95 using namespace com::sun::star::reflection;
96 using namespace com::sun::star::beans;
97 using namespace com::sun::star::script;
98 
99 
100 #include <com/sun/star/script/XLibraryContainer.hpp>
101 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
102 #include <com/sun/star/awt/XDialogProvider.hpp>
103 #include <com/sun/star/awt/XTopWindow.hpp>
104 #include <com/sun/star/awt/XWindow.hpp>
105 #include <com/sun/star/awt/XControl.hpp>
106 #include <cppuhelper/implbase1.hxx>
107 #include <comphelper/anytostring.hxx>
108 #include <com/sun/star/beans/XPropertySet.hpp>
109 #include <ooo/vba/VbQueryClose.hpp>
110 
111 typedef ::cppu::WeakImplHelper1< XInvocation > DocObjectWrapper_BASE;
112 typedef ::std::map< sal_Int16, Any, ::std::less< sal_Int16 > > OutParamMap;
113 ::com::sun::star::uno::Any sbxToUnoValue( SbxVariable* pVar );
114 void unoToSbxValue( SbxVariable* pVar, const ::com::sun::star::uno::Any& aValue );
115 
116 class DocObjectWrapper : public DocObjectWrapper_BASE
117 {
118     Reference< XAggregation >  m_xAggProxy;
119     Reference< XInvocation >  m_xAggInv;
120     Reference< XTypeProvider > m_xAggregateTypeProv;
121     Sequence< Type >           m_Types;
122     SbModule*                m_pMod;
123     SbMethodRef getMethod( const rtl::OUString& aName ) throw (RuntimeException);
124     SbPropertyRef getProperty( const rtl::OUString& aName ) throw (RuntimeException);
125     String mName; // for debugging
126 
127 public:
128     DocObjectWrapper( SbModule* pMod );
129     virtual ~DocObjectWrapper();
130 
131     virtual void SAL_CALL acquire() throw();
132     virtual void SAL_CALL release() throw();
133 
134     virtual Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (RuntimeException)
135     {
136         if( !m_xAggregateTypeProv.is() )
137             throw RuntimeException();
138         return m_xAggregateTypeProv->getImplementationId();
139     }
140 
141     virtual Reference< XIntrospectionAccess > SAL_CALL getIntrospection(  ) throw (RuntimeException);
142 
143     virtual Any SAL_CALL invoke( const ::rtl::OUString& aFunctionName, const Sequence< Any >& aParams, Sequence< ::sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) throw (IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException);
144     virtual void SAL_CALL setValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException);
145     virtual Any SAL_CALL getValue( const ::rtl::OUString& aPropertyName ) throw (UnknownPropertyException, RuntimeException);
146     virtual ::sal_Bool SAL_CALL hasMethod( const ::rtl::OUString& aName ) throw (RuntimeException);
147     virtual ::sal_Bool SAL_CALL hasProperty( const ::rtl::OUString& aName ) throw (RuntimeException);
148     virtual  Any SAL_CALL queryInterface( const Type& aType ) throw ( RuntimeException );
149 
150     virtual Sequence< Type > SAL_CALL getTypes() throw ( RuntimeException );
151 };
152 
153 DocObjectWrapper::DocObjectWrapper( SbModule* pVar ) : m_pMod( pVar ), mName( pVar->GetName() )
154 {
155     SbObjModule* pMod = PTR_CAST(SbObjModule,pVar);
156     if ( pMod )
157     {
158         if ( pMod->GetModuleType() == ModuleType::DOCUMENT )
159         {
160             Reference< XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
161             // Use proxy factory service to create aggregatable proxy.
162             SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pMod->GetObject() );
163             Reference< XInterface > xIf;
164             if ( pUnoObj )
165             {
166                    Any aObj = pUnoObj->getUnoAny();
167                    aObj >>= xIf;
168                    if ( xIf.is() )
169                    {
170                        m_xAggregateTypeProv.set( xIf, UNO_QUERY );
171                        m_xAggInv.set( xIf, UNO_QUERY );
172                    }
173             }
174             if ( xIf.is() )
175             {
176                 try
177                 {
178                     Reference< XMultiComponentFactory > xMFac( xFactory, UNO_QUERY_THROW );
179                     Reference< XPropertySet> xPSMPropertySet( xMFac, UNO_QUERY_THROW );
180                     Reference< XComponentContext >  xCtx;
181                     xPSMPropertySet->getPropertyValue(
182                     String( RTL_CONSTASCII_USTRINGPARAM("DefaultContext") ) ) >>= xCtx;
183                     Reference< XProxyFactory > xProxyFac( xMFac->createInstanceWithContext( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.reflection.ProxyFactory" ) ), xCtx  ), UNO_QUERY_THROW );
184                     m_xAggProxy = xProxyFac->createProxy( xIf );
185                 }
186                 catch(  Exception& )
187                 {
188                     OSL_ENSURE( false, "DocObjectWrapper::DocObjectWrapper: Caught exception!" );
189                 }
190             }
191 
192             if ( m_xAggProxy.is() )
193             {
194                 osl_incrementInterlockedCount( &m_refCount );
195 
196                 /* i35609 - Fix crash on Solaris. The setDelegator call needs
197                     to be in its own block to ensure that all temporary Reference
198                     instances that are acquired during the call are released
199                     before m_refCount is decremented again */
200                 {
201                     m_xAggProxy->setDelegator( static_cast< cppu::OWeakObject * >( this ) );
202                 }
203 
204                  osl_decrementInterlockedCount( &m_refCount );
205             }
206         }
207     }
208 }
209 
210 void SAL_CALL
211 DocObjectWrapper::acquire() throw ()
212 {
213     osl_incrementInterlockedCount( &m_refCount );
214     OSL_TRACE("DocObjectWrapper::acquire(%s) 0x%x refcount is now %d", rtl::OUStringToOString( mName, RTL_TEXTENCODING_UTF8 ).getStr(), this, m_refCount );
215 }
216 void SAL_CALL
217 DocObjectWrapper::release() throw ()
218 {
219     if ( osl_decrementInterlockedCount( &m_refCount ) == 0 )
220     {
221         OSL_TRACE("DocObjectWrapper::release(%s) 0x%x refcount is now %d", rtl::OUStringToOString( mName, RTL_TEXTENCODING_UTF8 ).getStr(), this, m_refCount );
222         delete this;
223     }
224     else
225         OSL_TRACE("DocObjectWrapper::release(%s) 0x%x refcount is now %d", rtl::OUStringToOString( mName, RTL_TEXTENCODING_UTF8 ).getStr(), this, m_refCount );
226 }
227 
228 DocObjectWrapper::~DocObjectWrapper()
229 {
230 }
231 
232 Sequence< Type > SAL_CALL DocObjectWrapper::getTypes()
233     throw ( RuntimeException )
234 {
235     if ( m_Types.getLength() == 0 )
236     {
237         Sequence< Type > sTypes;
238         if ( m_xAggregateTypeProv.is() )
239             sTypes = m_xAggregateTypeProv->getTypes();
240         m_Types.realloc( sTypes.getLength() + 1 );
241         Type* pPtr = m_Types.getArray();
242         for ( int i=0; i<m_Types.getLength(); ++i, ++pPtr )
243         {
244             if ( i == 0 )
245                 *pPtr = XInvocation::static_type( NULL );
246             else
247                 *pPtr = sTypes[ i - 1 ];
248         }
249     }
250     return m_Types;
251 }
252 
253 Reference< XIntrospectionAccess > SAL_CALL
254 DocObjectWrapper::getIntrospection(  ) throw (RuntimeException)
255 {
256     return NULL;
257 }
258 
259 Any SAL_CALL
260 DocObjectWrapper::invoke( const ::rtl::OUString& aFunctionName, const Sequence< Any >& aParams, Sequence< ::sal_Int16 >& aOutParamIndex, Sequence< Any >& aOutParam ) throw (IllegalArgumentException, CannotConvertException, InvocationTargetException, RuntimeException)
261 {
262     if ( m_xAggInv.is() &&  m_xAggInv->hasMethod( aFunctionName ) )
263             return m_xAggInv->invoke( aFunctionName, aParams, aOutParamIndex, aOutParam );
264     SbMethodRef pMethod = getMethod( aFunctionName );
265     if ( !pMethod )
266         throw RuntimeException();
267     // check number of parameters
268     sal_Int32 nParamsCount = aParams.getLength();
269     SbxInfo* pInfo = pMethod->GetInfo();
270     if ( pInfo )
271     {
272         sal_Int32 nSbxOptional = 0;
273         sal_uInt16 n = 1;
274         for ( const SbxParamInfo* pParamInfo = pInfo->GetParam( n ); pParamInfo; pParamInfo = pInfo->GetParam( ++n ) )
275         {
276             if ( ( pParamInfo->nFlags & SBX_OPTIONAL ) != 0 )
277                 ++nSbxOptional;
278             else
279                 nSbxOptional = 0;
280         }
281         sal_Int32 nSbxCount = n - 1;
282         if ( nParamsCount < nSbxCount - nSbxOptional )
283         {
284             throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "wrong number of parameters!" ) ), Reference< XInterface >() );
285         }
286     }
287     // set parameters
288     SbxArrayRef xSbxParams;
289     if ( nParamsCount > 0 )
290     {
291         xSbxParams = new SbxArray;
292         const Any* pParams = aParams.getConstArray();
293         for ( sal_Int32 i = 0; i < nParamsCount; ++i )
294         {
295             SbxVariableRef xSbxVar = new SbxVariable( SbxVARIANT );
296             unoToSbxValue( static_cast< SbxVariable* >( xSbxVar ), pParams[i] );
297             xSbxParams->Put( xSbxVar, static_cast< sal_uInt16 >( i ) + 1 );
298 
299             // Enable passing by ref
300             if ( xSbxVar->GetType() != SbxVARIANT )
301                 xSbxVar->SetFlag( SBX_FIXED );
302         }
303     }
304     if ( xSbxParams.Is() )
305         pMethod->SetParameters( xSbxParams );
306 
307     // call method
308     SbxVariableRef xReturn = new SbxVariable;
309     ErrCode nErr = SbxERR_OK;
310 
311     nErr = pMethod->Call( xReturn );
312     Any aReturn;
313     // get output parameters
314     if ( xSbxParams.Is() )
315     {
316         SbxInfo* pInfo_ = pMethod->GetInfo();
317         if ( pInfo_ )
318         {
319             OutParamMap aOutParamMap;
320             for ( sal_uInt16 n = 1, nCount = xSbxParams->Count(); n < nCount; ++n )
321             {
322                 const SbxParamInfo* pParamInfo = pInfo_->GetParam( n );
323                 if ( pParamInfo && ( pParamInfo->eType & SbxBYREF ) != 0 )
324                 {
325                     SbxVariable* pVar = xSbxParams->Get( n );
326                     if ( pVar )
327                     {
328                         SbxVariableRef xVar = pVar;
329                         aOutParamMap.insert( OutParamMap::value_type( n - 1, sbxToUnoValue( xVar ) ) );
330                     }
331                 }
332             }
333             sal_Int32 nOutParamCount = aOutParamMap.size();
334             aOutParamIndex.realloc( nOutParamCount );
335             aOutParam.realloc( nOutParamCount );
336             sal_Int16* pOutParamIndex = aOutParamIndex.getArray();
337             Any* pOutParam = aOutParam.getArray();
338             for ( OutParamMap::iterator aIt = aOutParamMap.begin(); aIt != aOutParamMap.end(); ++aIt, ++pOutParamIndex, ++pOutParam )
339             {
340                 *pOutParamIndex = aIt->first;
341                 *pOutParam = aIt->second;
342             }
343         }
344     }
345 
346     // get return value
347     aReturn = sbxToUnoValue( xReturn );
348 
349     pMethod->SetParameters( NULL );
350 
351     return aReturn;
352 }
353 
354 void SAL_CALL
355 DocObjectWrapper::setValue( const ::rtl::OUString& aPropertyName, const Any& aValue ) throw (UnknownPropertyException, CannotConvertException, InvocationTargetException, RuntimeException)
356 {
357     if ( m_xAggInv.is() &&  m_xAggInv->hasProperty( aPropertyName ) )
358             return m_xAggInv->setValue( aPropertyName, aValue );
359 
360     SbPropertyRef pProperty = getProperty( aPropertyName );
361     if ( !pProperty.Is() )
362        throw UnknownPropertyException();
363     unoToSbxValue( (SbxVariable*) pProperty, aValue );
364 }
365 
366 Any SAL_CALL
367 DocObjectWrapper::getValue( const ::rtl::OUString& aPropertyName ) throw (UnknownPropertyException, RuntimeException)
368 {
369     if ( m_xAggInv.is() &&  m_xAggInv->hasProperty( aPropertyName ) )
370             return m_xAggInv->getValue( aPropertyName );
371 
372     SbPropertyRef pProperty = getProperty( aPropertyName );
373     if ( !pProperty.Is() )
374        throw UnknownPropertyException();
375 
376     SbxVariable* pProp = ( SbxVariable* ) pProperty;
377     if ( pProp->GetType() == SbxEMPTY )
378         pProperty->Broadcast( SBX_HINT_DATAWANTED );
379 
380     Any aRet = sbxToUnoValue( pProp );
381     return aRet;
382 }
383 
384 ::sal_Bool SAL_CALL
385 DocObjectWrapper::hasMethod( const ::rtl::OUString& aName ) throw (RuntimeException)
386 {
387     if ( m_xAggInv.is() && m_xAggInv->hasMethod( aName ) )
388         return sal_True;
389     return getMethod( aName ).Is();
390 }
391 
392 ::sal_Bool SAL_CALL
393 DocObjectWrapper::hasProperty( const ::rtl::OUString& aName ) throw (RuntimeException)
394 {
395     sal_Bool bRes = sal_False;
396     if ( m_xAggInv.is() && m_xAggInv->hasProperty( aName ) )
397         bRes = sal_True;
398     else bRes = getProperty( aName ).Is();
399     return bRes;
400 }
401 
402 Any SAL_CALL DocObjectWrapper::queryInterface( const Type& aType )
403     throw ( RuntimeException )
404 {
405     Any aRet = DocObjectWrapper_BASE::queryInterface( aType );
406     if ( aRet.hasValue() )
407         return aRet;
408     else if ( m_xAggProxy.is() )
409         aRet = m_xAggProxy->queryAggregation( aType );
410     return aRet;
411 }
412 
413 SbMethodRef DocObjectWrapper::getMethod( const rtl::OUString& aName ) throw (RuntimeException)
414 {
415     SbMethodRef pMethod = NULL;
416     if ( m_pMod )
417     {
418         sal_uInt16 nSaveFlgs = m_pMod->GetFlags();
419         // Limit search to this module
420         m_pMod->ResetFlag( SBX_GBLSEARCH );
421         pMethod = (SbMethod*) m_pMod->SbModule::Find( aName,  SbxCLASS_METHOD );
422         m_pMod->SetFlags( nSaveFlgs );
423     }
424 
425     return pMethod;
426 }
427 
428 SbPropertyRef DocObjectWrapper::getProperty( const rtl::OUString& aName ) throw (RuntimeException)
429 {
430     SbPropertyRef pProperty = NULL;
431     if ( m_pMod )
432     {
433         sal_uInt16 nSaveFlgs = m_pMod->GetFlags();
434         // Limit search to this module.
435         m_pMod->ResetFlag( SBX_GBLSEARCH );
436         pProperty = (SbProperty*)m_pMod->SbModule::Find( aName,  SbxCLASS_PROPERTY );
437         m_pMod->SetFlag( nSaveFlgs );
438     }
439 
440     return pProperty;
441 }
442 
443 TYPEINIT1(SbModule,SbxObject)
444 TYPEINIT1(SbMethod,SbxMethod)
445 TYPEINIT1(SbProperty,SbxProperty)
446 TYPEINIT1(SbProcedureProperty,SbxProperty)
447 TYPEINIT1(SbJScriptModule,SbModule)
448 TYPEINIT1(SbJScriptMethod,SbMethod)
449 TYPEINIT1(SbObjModule,SbModule)
450 TYPEINIT1(SbUserFormModule,SbObjModule)
451 
452 typedef std::vector<HighlightPortion> HighlightPortions;
453 
454 uno::Reference< frame::XModel > getDocumentModel( StarBASIC* pb )
455 {
456     uno::Reference< frame::XModel > xModel;
457     if( pb && pb->IsDocBasic() )
458     {
459         uno::Any aDoc;
460         if( pb->GetUNOConstant( "ThisComponent", aDoc ) )
461             xModel.set( aDoc, uno::UNO_QUERY );
462     }
463     return xModel;
464 }
465 
466 uno::Reference< vba::XVBACompatibility > getVBACompatibility( const uno::Reference< frame::XModel >& rxModel )
467 {
468     uno::Reference< vba::XVBACompatibility > xVBACompat;
469     try
470     {
471         uno::Reference< beans::XPropertySet > xModelProps( rxModel, uno::UNO_QUERY_THROW );
472         xVBACompat.set( xModelProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicLibraries" ) ) ), uno::UNO_QUERY );
473     }
474     catch( uno::Exception& )
475     {
476     }
477     return xVBACompat;
478 }
479 
480 bool getDefaultVBAMode( StarBASIC* pb )
481 {
482     uno::Reference< vba::XVBACompatibility > xVBACompat = getVBACompatibility( getDocumentModel( pb ) );
483     return xVBACompat.is() && xVBACompat->getVBACompatibilityMode();
484 }
485 
486 class AsyncQuitHandler
487 {
488     AsyncQuitHandler() {}
489     AsyncQuitHandler( const AsyncQuitHandler&);
490 public:
491     static AsyncQuitHandler& instance()
492     {
493         static AsyncQuitHandler dInst;
494         return dInst;
495     }
496 
497     void QuitApplication()
498     {
499         uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
500         if ( xFactory.is() )
501     {
502             uno::Reference< frame::XDesktop > xDeskTop( xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.frame.Desktop") ) ), uno::UNO_QUERY );
503            if ( xDeskTop.is() )
504                xDeskTop->terminate();
505         }
506     }
507     DECL_LINK( OnAsyncQuit, void* );
508 };
509 
510 IMPL_LINK( AsyncQuitHandler, OnAsyncQuit, void*, /*pNull*/ )
511 {
512     QuitApplication();
513     return 0L;
514 }
515 
516 /////////////////////////////////////////////////////////////////////////////
517 
518 // Ein BASIC-Modul hat EXTSEARCH gesetzt, damit die im Modul enthaltenen
519 // Elemente von anderen Modulen aus gefunden werden koennen.
520 
521 SbModule::SbModule( const String& rName,  sal_Bool bVBACompat )
522          : SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("StarBASICModule") ) ),
523            pImage( NULL ), pBreaks( NULL ), pClassData( NULL ), mbVBACompat( bVBACompat ),  pDocObject( NULL ), bIsProxyModule( false )
524 {
525     SetName( rName );
526     SetFlag( SBX_EXTSEARCH | SBX_GBLSEARCH );
527     SetModuleType( script::ModuleType::NORMAL );
528 
529     // #i92642: Set name property to intitial name
530     SbxVariable* pNameProp = pProps->Find( String( RTL_CONSTASCII_USTRINGPARAM("Name") ), SbxCLASS_PROPERTY );
531     if( pNameProp != NULL )
532         pNameProp->PutString( GetName() );
533 }
534 
535 SbModule::~SbModule()
536 {
537     OSL_TRACE("Module named %s is destructing", rtl::OUStringToOString( GetName(), RTL_TEXTENCODING_UTF8 ).getStr() );
538     if( pImage )
539         delete pImage;
540     if( pBreaks )
541         delete pBreaks;
542     if( pClassData )
543         delete pClassData;
544         mxWrapper = NULL;
545 }
546 
547 uno::Reference< script::XInvocation >
548 SbModule::GetUnoModule()
549 {
550     if ( !mxWrapper.is() )
551         mxWrapper = new DocObjectWrapper( this );
552 
553     OSL_TRACE("Module named %s returning wrapper mxWrapper (0x%x)", rtl::OUStringToOString( GetName(), RTL_TEXTENCODING_UTF8 ).getStr(), mxWrapper.get() );
554     return mxWrapper;
555 }
556 
557 sal_Bool SbModule::IsCompiled() const
558 {
559     return sal_Bool( pImage != 0 );
560 }
561 
562 const SbxObject* SbModule::FindType( String aTypeName ) const
563 {
564     return pImage ? pImage->FindType( aTypeName ) : NULL;
565 }
566 
567 
568 // Aus dem Codegenerator: Loeschen des Images und Invalidieren der Entries
569 
570 void SbModule::StartDefinitions()
571 {
572     delete pImage; pImage = NULL;
573     if( pClassData )
574         pClassData->clear();
575 
576     // Methoden und Properties bleiben erhalten, sind jedoch ungueltig
577     // schliesslich sind ja u.U. die Infos belegt
578     sal_uInt16 i;
579     for( i = 0; i < pMethods->Count(); i++ )
580     {
581         SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) );
582         if( p )
583             p->bInvalid = sal_True;
584     }
585     for( i = 0; i < pProps->Count(); )
586     {
587         SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) );
588         if( p )
589             pProps->Remove( i );
590         else
591             i++;
592     }
593 }
594 
595 // Methode anfordern/anlegen
596 
597 SbMethod* SbModule::GetMethod( const String& rName, SbxDataType t )
598 {
599     SbxVariable* p = pMethods->Find( rName, SbxCLASS_METHOD );
600     SbMethod* pMeth = p ? PTR_CAST(SbMethod,p) : NULL;
601     if( p && !pMeth )
602         pMethods->Remove( p );
603     if( !pMeth )
604     {
605         pMeth = new SbMethod( rName, t, this );
606         pMeth->SetParent( this );
607         pMeth->SetFlags( SBX_READ );
608         pMethods->Put( pMeth, pMethods->Count() );
609         StartListening( pMeth->GetBroadcaster(), sal_True );
610     }
611     // Per Default ist die Methode GUELTIG, da sie auch vom Compiler
612     // (Codegenerator) erzeugt werden kann
613     pMeth->bInvalid = sal_False;
614     pMeth->ResetFlag( SBX_FIXED );
615     pMeth->SetFlag( SBX_WRITE );
616     pMeth->SetType( t );
617     pMeth->ResetFlag( SBX_WRITE );
618     if( t != SbxVARIANT )
619         pMeth->SetFlag( SBX_FIXED );
620     return pMeth;
621 }
622 
623 // Property anfordern/anlegen
624 
625 SbProperty* SbModule::GetProperty( const String& rName, SbxDataType t )
626 {
627     SbxVariable* p = pProps->Find( rName, SbxCLASS_PROPERTY );
628     SbProperty* pProp = p ? PTR_CAST(SbProperty,p) : NULL;
629     if( p && !pProp )
630         pProps->Remove( p );
631     if( !pProp )
632     {
633         pProp = new SbProperty( rName, t, this );
634         pProp->SetFlag( SBX_READWRITE );
635         pProp->SetParent( this );
636         pProps->Put( pProp, pProps->Count() );
637         StartListening( pProp->GetBroadcaster(), sal_True );
638     }
639     return pProp;
640 }
641 
642 SbProcedureProperty* SbModule::GetProcedureProperty
643     ( const String& rName, SbxDataType t )
644 {
645     SbxVariable* p = pProps->Find( rName, SbxCLASS_PROPERTY );
646     SbProcedureProperty* pProp = p ? PTR_CAST(SbProcedureProperty,p) : NULL;
647     if( p && !pProp )
648         pProps->Remove( p );
649     if( !pProp )
650     {
651         pProp = new SbProcedureProperty( rName, t );
652         pProp->SetFlag( SBX_READWRITE );
653         pProp->SetParent( this );
654         pProps->Put( pProp, pProps->Count() );
655         StartListening( pProp->GetBroadcaster(), sal_True );
656     }
657     return pProp;
658 }
659 
660 SbIfaceMapperMethod* SbModule::GetIfaceMapperMethod
661     ( const String& rName, SbMethod* pImplMeth )
662 {
663     SbxVariable* p = pMethods->Find( rName, SbxCLASS_METHOD );
664     SbIfaceMapperMethod* pMapperMethod = p ? PTR_CAST(SbIfaceMapperMethod,p) : NULL;
665     if( p && !pMapperMethod )
666         pMethods->Remove( p );
667     if( !pMapperMethod )
668     {
669         pMapperMethod = new SbIfaceMapperMethod( rName, pImplMeth );
670         pMapperMethod->SetParent( this );
671         pMapperMethod->SetFlags( SBX_READ );
672         pMethods->Put( pMapperMethod, pMethods->Count() );
673     }
674     pMapperMethod->bInvalid = sal_False;
675     return pMapperMethod;
676 }
677 
678 SbIfaceMapperMethod::~SbIfaceMapperMethod()
679 {
680 }
681 
682 TYPEINIT1(SbIfaceMapperMethod,SbMethod)
683 
684 
685 // Aus dem Codegenerator: Ungueltige Eintraege entfernen
686 
687 void SbModule::EndDefinitions( sal_Bool bNewState )
688 {
689     for( sal_uInt16 i = 0; i < pMethods->Count(); )
690     {
691         SbMethod* p = PTR_CAST(SbMethod,pMethods->Get( i ) );
692         if( p )
693         {
694             if( p->bInvalid )
695                 pMethods->Remove( p );
696             else
697             {
698                 p->bInvalid = bNewState;
699                 i++;
700             }
701         }
702         else
703             i++;
704     }
705     SetModified( sal_True );
706 }
707 
708 void SbModule::Clear()
709 {
710     delete pImage; pImage = NULL;
711     if( pClassData )
712         pClassData->clear();
713     SbxObject::Clear();
714 }
715 
716 
717 SbxVariable* SbModule::Find( const XubString& rName, SbxClassType t )
718 {
719     // make sure a search in an uninstatiated class module will fail
720     SbxVariable* pRes = SbxObject::Find( rName, t );
721     if ( bIsProxyModule && !GetSbData()->bRunInit )
722         return NULL;
723     if( !pRes && pImage )
724     {
725         SbiInstance* pInst = pINST;
726         if( pInst && pInst->IsCompatibility() )
727         {
728             // Put enum types as objects into module,
729             // allows MyEnum.First notation
730             SbxArrayRef xArray = pImage->GetEnums();
731             if( xArray.Is() )
732             {
733                 SbxVariable* pEnumVar = xArray->Find( rName, SbxCLASS_DONTCARE );
734                 SbxObject* pEnumObject = PTR_CAST( SbxObject, pEnumVar );
735                 if( pEnumObject )
736                 {
737                     bool bPrivate = pEnumObject->IsSet( SBX_PRIVATE );
738                     String aEnumName = pEnumObject->GetName();
739 
740                     pRes = new SbxVariable( SbxOBJECT );
741                     pRes->SetName( aEnumName );
742                     pRes->SetParent( this );
743                     pRes->SetFlag( SBX_READ );
744                     if( bPrivate )
745                         pRes->SetFlag( SBX_PRIVATE );
746                     pRes->PutObject( pEnumObject );
747                 }
748             }
749         }
750     }
751     return pRes;
752 }
753 
754 const ::rtl::OUString& SbModule::GetSource32() const
755 {
756     return aOUSource;
757 }
758 
759 const String& SbModule::GetSource() const
760 {
761     static String aRetStr;
762     aRetStr = aOUSource;
763     return aRetStr;
764 }
765 
766 // Parent und BASIC sind eins!
767 
768 void SbModule::SetParent( SbxObject* p )
769 {
770     // #118083: Assertion is not valid any more
771     // DBG_ASSERT( !p || p->IsA( TYPE(StarBASIC) ), "SbModules nur in BASIC eintragen" );
772     pParent = p;
773 }
774 
775 void SbModule::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
776                            const SfxHint& rHint, const TypeId& rHintType )
777 {
778     const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
779     if( pHint )
780     {
781         SbxVariable* pVar = pHint->GetVar();
782         SbProperty* pProp = PTR_CAST(SbProperty,pVar);
783         SbMethod* pMeth = PTR_CAST(SbMethod,pVar);
784         if( pProp )
785         {
786             if( pProp->GetModule() != this )
787                 SetError( SbxERR_BAD_ACTION );
788         }
789         else if( pMeth )
790         {
791             if( pHint->GetId() == SBX_HINT_DATAWANTED )
792             {
793                 if( pMeth->bInvalid && !Compile() )
794                     // Auto-Compile hat nicht geklappt!
795                     StarBASIC::Error( SbERR_BAD_PROP_VALUE );
796                 else
797                 {
798                     // Aufruf eines Unterprogramms
799                     SbModule* pOld = pMOD;
800                     pMOD = this;
801                     Run( (SbMethod*) pVar );
802                     pMOD = pOld;
803                 }
804             }
805         }
806         else
807         {
808             // #i92642: Special handling for name property to avoid
809             // side effects when using name as variable implicitely
810             bool bForwardToSbxObject = true;
811 
812             sal_uIntPtr nId = pHint->GetId();
813             if( (nId == SBX_HINT_DATAWANTED || nId == SBX_HINT_DATACHANGED) &&
814                 pVar->GetName().EqualsIgnoreCaseAscii( "name" ) )
815                     bForwardToSbxObject = false;
816 
817             if( bForwardToSbxObject )
818                 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType );
819         }
820     }
821 }
822 
823 // Das Setzen der Source macht das Image ungueltig
824 // und scant die Methoden-Definitionen neu ein
825 
826 void SbModule::SetSource( const String& r )
827 {
828     SetSource32( r );
829 }
830 
831 void SbModule::SetSource32( const ::rtl::OUString& r )
832 {
833     // Default basic mode to library container mode, but.. allow Option VBASupport 0/1 override
834     SetVBACompat( getDefaultVBAMode( static_cast< StarBASIC*>( GetParent() ) ) );
835     aOUSource = r;
836     StartDefinitions();
837     SbiTokenizer aTok( r );
838     while( !aTok.IsEof() )
839     {
840         SbiToken eEndTok = NIL;
841 
842         // Suchen nach SUB oder FUNCTION
843         SbiToken eLastTok = NIL;
844         while( !aTok.IsEof() )
845         {
846             // #32385: Nicht bei declare
847             SbiToken eCurTok = aTok.Next();
848             if( eLastTok != DECLARE )
849             {
850                 if( eCurTok == SUB )
851                 {
852                     eEndTok = ENDSUB; break;
853                 }
854                 if( eCurTok == FUNCTION )
855                 {
856                     eEndTok = ENDFUNC; break;
857                 }
858                 if( eCurTok == PROPERTY )
859                 {
860                     eEndTok = ENDPROPERTY; break;
861                 }
862                 if( eCurTok == OPTION )
863                 {
864                     eCurTok = aTok.Next();
865                     if( eCurTok == COMPATIBLE )
866                         aTok.SetCompatible( true );
867                     else if ( ( eCurTok == VBASUPPORT ) && ( aTok.Next() == NUMBER ) )
868                     {
869                             sal_Bool bIsVBA = ( aTok.GetDbl()== 1 );
870                             SetVBACompat( bIsVBA );
871                         aTok.SetCompatible( bIsVBA );
872                     }
873                 }
874             }
875             eLastTok = eCurTok;
876         }
877         // Definition der Methode
878         SbMethod* pMeth = NULL;
879         if( eEndTok != NIL )
880         {
881             sal_uInt16 nLine1 = aTok.GetLine();
882             if( aTok.Next() == SYMBOL )
883             {
884                 String aName_( aTok.GetSym() );
885                 SbxDataType t = aTok.GetType();
886                 if( t == SbxVARIANT && eEndTok == ENDSUB )
887                     t = SbxVOID;
888                 pMeth = GetMethod( aName_, t );
889                 pMeth->nLine1 = pMeth->nLine2 = nLine1;
890                 // Die Methode ist erst mal GUELTIG
891                 pMeth->bInvalid = sal_False;
892             }
893             else
894                 eEndTok = NIL;
895         }
896         // Skip bis END SUB/END FUNCTION
897         if( eEndTok != NIL )
898         {
899             while( !aTok.IsEof() )
900             {
901                 if( aTok.Next() == eEndTok )
902                 {
903                     pMeth->nLine2 = aTok.GetLine();
904                     break;
905                 }
906             }
907             if( aTok.IsEof() )
908                 pMeth->nLine2 = aTok.GetLine();
909         }
910     }
911     EndDefinitions( sal_True );
912 }
913 
914 void SbModule::SetComment( const String& r )
915 {
916     aComment = r;
917     SetModified( sal_True );
918 }
919 
920 SbMethod* SbModule::GetFunctionForLine( sal_uInt16 nLine )
921 {
922     for( sal_uInt16 i = 0; i < pMethods->Count(); i++ )
923     {
924         SbMethod* p = (SbMethod*) pMethods->Get( i );
925         if( p->GetSbxId() == SBXID_BASICMETHOD )
926         {
927             if( nLine >= p->nLine1 && nLine <= p->nLine2 )
928                 return p;
929         }
930     }
931     return NULL;
932 }
933 
934 // Ausstrahlen eines Hints an alle Basics
935 
936 static void _SendHint( SbxObject* pObj, sal_uIntPtr nId, SbMethod* p )
937 {
938     // Selbst ein BASIC?
939     if( pObj->IsA( TYPE(StarBASIC) ) && pObj->IsBroadcaster() )
940         pObj->GetBroadcaster().Broadcast( SbxHint( nId, p ) );
941     // Dann die Unterobjekte fragen
942     SbxArray* pObjs = pObj->GetObjects();
943     for( sal_uInt16 i = 0; i < pObjs->Count(); i++ )
944     {
945         SbxVariable* pVar = pObjs->Get( i );
946         if( pVar->IsA( TYPE(SbxObject) ) )
947             _SendHint( PTR_CAST(SbxObject,pVar), nId, p );
948     }
949 }
950 
951 static void SendHint( SbxObject* pObj, sal_uIntPtr nId, SbMethod* p )
952 {
953     while( pObj->GetParent() )
954         pObj = pObj->GetParent();
955     _SendHint( pObj, nId, p );
956 }
957 
958 // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden,
959 // beim Programm-Ende freigeben, damit nichts gehalten wird.
960 void ClearUnoObjectsInRTL_Impl_Rek( StarBASIC* pBasic )
961 {
962     // return-Wert von CreateUnoService loeschen
963     static String aName( RTL_CONSTASCII_USTRINGPARAM("CreateUnoService") );
964     SbxVariable* pVar = pBasic->GetRtl()->Find( aName, SbxCLASS_METHOD );
965     if( pVar )
966         pVar->SbxValue::Clear();
967 
968     // return-Wert von CreateUnoDialog loeschen
969     static String aName2( RTL_CONSTASCII_USTRINGPARAM("CreateUnoDialog") );
970     pVar = pBasic->GetRtl()->Find( aName2, SbxCLASS_METHOD );
971     if( pVar )
972         pVar->SbxValue::Clear();
973 
974     // return-Wert von CDec loeschen
975     static String aName3( RTL_CONSTASCII_USTRINGPARAM("CDec") );
976     pVar = pBasic->GetRtl()->Find( aName3, SbxCLASS_METHOD );
977     if( pVar )
978         pVar->SbxValue::Clear();
979 
980     // return-Wert von CreateObject loeschen
981     static String aName4( RTL_CONSTASCII_USTRINGPARAM("CreateObject") );
982     pVar = pBasic->GetRtl()->Find( aName4, SbxCLASS_METHOD );
983     if( pVar )
984         pVar->SbxValue::Clear();
985 
986     // Ueber alle Sub-Basics gehen
987     SbxArray* pObjs = pBasic->GetObjects();
988     sal_uInt16 nCount = pObjs->Count();
989     for( sal_uInt16 i = 0 ; i < nCount ; i++ )
990     {
991         SbxVariable* pObjVar = pObjs->Get( i );
992         StarBASIC* pSubBasic = PTR_CAST( StarBASIC, pObjVar );
993         if( pSubBasic )
994             ClearUnoObjectsInRTL_Impl_Rek( pSubBasic );
995     }
996 }
997 
998 void ClearUnoObjectsInRTL_Impl( StarBASIC* pBasic )
999 {
1000     // #67781 Rueckgabewerte der Uno-Methoden loeschen
1001     clearUnoMethods();
1002     clearUnoServiceCtors();
1003 
1004     ClearUnoObjectsInRTL_Impl_Rek( pBasic );
1005 
1006     // Oberstes Basic suchen
1007     SbxObject* p = pBasic;
1008     while( p->GetParent() )
1009         p = p->GetParent();
1010     if( ((StarBASIC*)p) != pBasic )
1011         ClearUnoObjectsInRTL_Impl_Rek( (StarBASIC*)p );
1012 }
1013 sal_Bool SbModule::IsVBACompat() const
1014 {
1015     return mbVBACompat;
1016 }
1017 
1018 void SbModule::SetVBACompat( sal_Bool bCompat )
1019 {
1020     if( mbVBACompat != bCompat )
1021     {
1022         mbVBACompat = bCompat;
1023         // initialize VBA document API
1024         if( mbVBACompat ) try
1025         {
1026             StarBASIC* pBasic = static_cast< StarBASIC* >( GetParent() );
1027             uno::Reference< lang::XMultiServiceFactory > xFactory( getDocumentModel( pBasic ), uno::UNO_QUERY_THROW );
1028             xFactory->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAGlobals" ) ) );
1029         }
1030         catch( Exception& )
1031         {
1032         }
1033     }
1034 }
1035 
1036 // Ausfuehren eines BASIC-Unterprogramms
1037 sal_uInt16 SbModule::Run( SbMethod* pMeth )
1038 {
1039     static sal_uInt16 nMaxCallLevel = 0;
1040     static String aMSOMacroRuntimeLibName = String::CreateFromAscii( "Launcher" );
1041     static String aMSOMacroRuntimeAppSymbol = String::CreateFromAscii( "Application" );
1042 
1043     sal_uInt16 nRes = 0;
1044     sal_Bool bDelInst = sal_Bool( pINST == NULL );
1045     StarBASICRef xBasic;
1046     uno::Reference< frame::XModel > xModel;
1047     uno::Reference< script::vba::XVBACompatibility > xVBACompat;
1048     if( bDelInst )
1049     {
1050 #ifdef DBG_TRACE_BASIC
1051         dbg_InitTrace();
1052 #endif
1053         // #32779: Basic waehrend der Ausfuehrung festhalten
1054         xBasic = (StarBASIC*) GetParent();
1055 
1056         pINST = new SbiInstance( (StarBASIC*) GetParent() );
1057 
1058         /*  If a VBA script in a document is started, get the VBA compatibility
1059             interface from the document Basic library container, and notify all
1060             VBA script listeners about the started script. */
1061         if( mbVBACompat )
1062         {
1063             StarBASIC* pBasic = static_cast< StarBASIC* >( GetParent() );
1064             if( pBasic && pBasic->IsDocBasic() ) try
1065             {
1066                 xModel.set( getDocumentModel( pBasic ), uno::UNO_SET_THROW );
1067                 xVBACompat.set( getVBACompatibility( xModel ), uno::UNO_SET_THROW );
1068                 xVBACompat->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::SCRIPT_STARTED, GetName() );
1069             }
1070             catch( uno::Exception& )
1071             {
1072             }
1073         }
1074 
1075         // Launcher problem
1076         // i80726 The Find below will genarate an error in Testtool so we reset it unless there was one before already
1077         sal_Bool bWasError = SbxBase::GetError() != 0;
1078         SbxVariable* pMSOMacroRuntimeLibVar = Find( aMSOMacroRuntimeLibName, SbxCLASS_OBJECT );
1079         if ( !bWasError && (SbxBase::GetError() == SbxERR_PROC_UNDEFINED) )
1080             SbxBase::ResetError();
1081         if( pMSOMacroRuntimeLibVar )
1082         {
1083             StarBASIC* pMSOMacroRuntimeLib = PTR_CAST(StarBASIC,pMSOMacroRuntimeLibVar);
1084             if( pMSOMacroRuntimeLib )
1085             {
1086                 sal_uInt16 nGblFlag = pMSOMacroRuntimeLib->GetFlags() & SBX_GBLSEARCH;
1087                 pMSOMacroRuntimeLib->ResetFlag( SBX_GBLSEARCH );
1088                 SbxVariable* pAppSymbol = pMSOMacroRuntimeLib->Find( aMSOMacroRuntimeAppSymbol, SbxCLASS_METHOD );
1089                 pMSOMacroRuntimeLib->SetFlag( nGblFlag );
1090                 if( pAppSymbol )
1091                 {
1092                     pMSOMacroRuntimeLib->SetFlag( SBX_EXTSEARCH );      // Could have been disabled before
1093                     GetSbData()->pMSOMacroRuntimLib = pMSOMacroRuntimeLib;
1094                 }
1095             }
1096         }
1097 
1098         // Error-Stack loeschen
1099         SbErrorStack*& rErrStack = GetSbData()->pErrStack;
1100         delete rErrStack;
1101         rErrStack = NULL;
1102 
1103         if( nMaxCallLevel == 0 )
1104         {
1105 #ifdef UNX
1106           struct rlimit rl;
1107           getrlimit ( RLIMIT_STACK, &rl );
1108           // printf( "RLIMIT_STACK = %ld\n", rl.rlim_cur );
1109 #endif
1110 #if defined LINUX
1111           // Empiric value, 900 = needed bytes/Basic call level
1112           // for Linux including 10% safety margin
1113           nMaxCallLevel = rl.rlim_cur / 900;
1114 #elif defined SOLARIS
1115           // Empiric value, 1650 = needed bytes/Basic call level
1116           // for Solaris including 10% safety margin
1117           nMaxCallLevel = rl.rlim_cur / 1650;
1118 #elif defined WIN32
1119           nMaxCallLevel = 5800;
1120 #else
1121           nMaxCallLevel = MAXRECURSION;
1122 #endif
1123         }
1124     }
1125 
1126     // Rekursion zu tief?
1127     if( ++pINST->nCallLvl <= nMaxCallLevel )
1128     {
1129         // Globale Variable in allen Mods definieren
1130         GlobalRunInit( /* bBasicStart = */ bDelInst );
1131 
1132         // Trat ein Compiler-Fehler auf? Dann starten wir nicht
1133         if( GetSbData()->bGlobalInitErr == sal_False )
1134         {
1135             if( bDelInst )
1136             {
1137                 SendHint( GetParent(), SBX_HINT_BASICSTART, pMeth );
1138 
1139                 // 16.10.96: #31460 Neues Konzept fuer StepInto/Over/Out
1140                 // Erklaerung siehe runtime.cxx bei SbiInstance::CalcBreakCallLevel()
1141                 // BreakCallLevel ermitteln
1142                 pINST->CalcBreakCallLevel( pMeth->GetDebugFlags() );
1143             }
1144 
1145             SbModule* pOldMod = pMOD;
1146             pMOD = this;
1147             SbiRuntime* pRt = new SbiRuntime( this, pMeth, pMeth->nStart );
1148 
1149 #ifdef DBG_TRACE_BASIC
1150             dbg_traceNotifyCall( this, pMeth, pINST->nCallLvl );
1151 #endif
1152 
1153             pRt->pNext = pINST->pRun;
1154             if( pRt->pNext )
1155                 pRt->pNext->block();
1156             pINST->pRun = pRt;
1157             if ( mbVBACompat )
1158             {
1159                 pINST->EnableCompatibility( sal_True );
1160             }
1161             while( pRt->Step() ) {}
1162             if( pRt->pNext )
1163                 pRt->pNext->unblock();
1164 
1165 #ifdef DBG_TRACE_BASIC
1166             bool bLeave = true;
1167             dbg_traceNotifyCall( this, pMeth, pINST->nCallLvl, bLeave );
1168 #endif
1169 
1170             // #63710 Durch ein anderes Thread-Handling bei Events kann es passieren,
1171             // dass show-Aufruf an einem Dialog zurueckkehrt (durch schliessen des
1172             // Dialogs per UI), BEVOR ein per Event ausgeloester weitergehender Call,
1173             // der in Basic weiter oben im Stack steht und auf einen Basic-Breakpoint
1174             // gelaufen ist, zurueckkehrt. Dann wird unten die Instanz zerstoert und
1175             // wenn das noch im Call stehende Basic weiterlaeuft, gibt es einen GPF.
1176             // Daher muss hier gewartet werden, bis andere Call zurueckkehrt.
1177             if( bDelInst )
1178             {
1179                 // Hier mit 1 statt 0 vergleichen, da vor nCallLvl--
1180                 while( pINST->nCallLvl != 1 )
1181                     GetpApp()->Yield();
1182             }
1183 
1184             nRes = sal_True;
1185             pINST->pRun = pRt->pNext;
1186             pINST->nCallLvl--;          // Call-Level wieder runter
1187 
1188             // Gibt es eine uebergeordnete Runtime-Instanz?
1189             // Dann SbDEBUG_BREAK uebernehmen, wenn gesetzt
1190             SbiRuntime* pRtNext = pRt->pNext;
1191             if( pRtNext && (pRt->GetDebugFlags() & SbDEBUG_BREAK) )
1192                 pRtNext->SetDebugFlags( SbDEBUG_BREAK );
1193 
1194             delete pRt;
1195             pMOD = pOldMod;
1196             if( bDelInst )
1197             {
1198                 // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden,
1199                 // beim Programm-Ende freigeben, damit nichts gehalten wird.
1200                 ClearUnoObjectsInRTL_Impl( xBasic );
1201 
1202                 clearNativeObjectWrapperVector();
1203 
1204                 DBG_ASSERT(pINST->nCallLvl==0,"BASIC-Call-Level > 0");
1205                 delete pINST, pINST = NULL, bDelInst = sal_False;
1206 
1207                 // #i30690
1208                 vos::OGuard aSolarGuard( Application::GetSolarMutex() );
1209                 SendHint( GetParent(), SBX_HINT_BASICSTOP, pMeth );
1210 
1211                 GlobalRunDeInit();
1212 
1213 #ifdef DBG_UTIL
1214                 ResetCapturedAssertions();
1215 #endif
1216 
1217                 if( xVBACompat.is() )
1218                 {
1219                     // notify all VBA script listeners about the stopped script
1220                     try
1221                     {
1222                         xVBACompat->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::SCRIPT_STOPPED, GetName() );
1223                     }
1224                     catch( uno::Exception& )
1225                     {
1226                     }
1227                     // VBA always ensures screenupdating is enabled after completing
1228                     ::basic::vba::lockControllersOfAllDocuments( xModel, sal_False );
1229                     ::basic::vba::enableContainerWindowsOfAllDocuments( xModel, sal_True );
1230                 }
1231 
1232 #ifdef DBG_TRACE_BASIC
1233                 dbg_DeInitTrace();
1234 #endif
1235             }
1236         }
1237         else
1238             pINST->nCallLvl--;          // Call-Level wieder runter
1239     }
1240     else
1241     {
1242         pINST->nCallLvl--;          // Call-Level wieder runter
1243         StarBASIC::FatalError( SbERR_STACK_OVERFLOW );
1244     }
1245 
1246     StarBASIC* pBasic = PTR_CAST(StarBASIC,GetParent());
1247     if( bDelInst )
1248     {
1249         // #57841 Uno-Objekte, die in RTL-Funktionen gehalten werden,
1250         // beim Programm-Ende freigeben, damit nichts gehalten wird.
1251         ClearUnoObjectsInRTL_Impl( xBasic );
1252 
1253         delete pINST;
1254         pINST = NULL;
1255     }
1256     if ( pBasic && pBasic->IsDocBasic() && pBasic->IsQuitApplication() && !pINST )
1257     {
1258         Application::PostUserEvent( LINK( &AsyncQuitHandler::instance(), AsyncQuitHandler, OnAsyncQuit ), NULL );
1259     }
1260 
1261     return nRes;
1262 }
1263 
1264 // Ausfuehren der Init-Methode eines Moduls nach dem Laden
1265 // oder der Compilation
1266 
1267 void SbModule::RunInit()
1268 {
1269     if( pImage
1270      && !pImage->bInit
1271      && pImage->GetFlag( SBIMG_INITCODE ) )
1272     {
1273         // Flag setzen, dass RunInit aktiv ist (Testtool)
1274         GetSbData()->bRunInit = sal_True;
1275 
1276         // sal_Bool bDelInst = sal_Bool( pINST == NULL );
1277         // if( bDelInst )
1278             // pINST = new SbiInstance( (StarBASIC*) GetParent() );
1279         SbModule* pOldMod = pMOD;
1280         pMOD = this;
1281         // Der Init-Code beginnt immer hier
1282         SbiRuntime* pRt = new SbiRuntime( this, NULL, 0 );
1283 
1284 #ifdef DBG_TRACE_BASIC
1285         dbg_traceNotifyCall( this, NULL, 0 );
1286 #endif
1287 
1288         pRt->pNext = pINST->pRun;
1289         pINST->pRun = pRt;
1290         while( pRt->Step() ) {}
1291 
1292 #ifdef DBG_TRACE_BASIC
1293         bool bLeave = true;
1294         dbg_traceNotifyCall( this, NULL, 0, bLeave );
1295 #endif
1296 
1297         pINST->pRun = pRt->pNext;
1298         delete pRt;
1299         pMOD = pOldMod;
1300         // if( bDelInst )
1301             // delete pINST, pINST = NULL;
1302         pImage->bInit = sal_True;
1303         pImage->bFirstInit = sal_False;
1304 
1305         // RunInit ist nicht mehr aktiv
1306         GetSbData()->bRunInit = sal_False;
1307     }
1308 }
1309 
1310 // Mit private/dim deklarierte Variablen loeschen
1311 
1312 void SbModule::AddVarName( const String& aName )
1313 {
1314     // see if the name is added allready
1315     std::vector< String >::iterator it_end = mModuleVariableNames.end();
1316     for ( std::vector< String >::iterator it = mModuleVariableNames.begin(); it != it_end; ++it )
1317     {
1318         if ( aName == *it )
1319             return;
1320     }
1321     mModuleVariableNames.push_back( aName );
1322 }
1323 
1324 void SbModule::RemoveVars()
1325 {
1326     std::vector< String >::iterator it_end = mModuleVariableNames.end();
1327     for ( std::vector< String >::iterator it = mModuleVariableNames.begin(); it != it_end; ++it )
1328     {
1329     // We don't want a Find being called in a derived class ( e.g.
1330     // SbUserform because it could trigger say an initialise event
1331     // which would cause basic to be re-run in the middle of the init ( and remember RemoveVars is called from compile and we don't want code to run as part of the compile )
1332     SbxVariableRef p = SbModule::Find( *it, SbxCLASS_PROPERTY );
1333     if( p.Is() )
1334         Remove (p);
1335     }
1336 }
1337 
1338 void SbModule::ClearPrivateVars()
1339 {
1340     for( sal_uInt16 i = 0 ; i < pProps->Count() ; i++ )
1341     {
1342         SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) );
1343         if( p )
1344         {
1345             // Arrays nicht loeschen, sondern nur deren Inhalt
1346             if( p->GetType() & SbxARRAY )
1347             {
1348                 SbxArray* pArray = PTR_CAST(SbxArray,p->GetObject());
1349                 if( pArray )
1350                 {
1351                     for( sal_uInt16 j = 0 ; j < pArray->Count() ; j++ )
1352                     {
1353                         SbxVariable* pj = PTR_CAST(SbxVariable,pArray->Get( j ));
1354                         pj->SbxValue::Clear();
1355                         /*
1356                         sal_uInt16 nFlags = pj->GetFlags();
1357                         pj->SetFlags( (nFlags | SBX_WRITE) & (~SBX_FIXED) );
1358                         pj->PutEmpty();
1359                         pj->SetFlags( nFlags );
1360                         */
1361                     }
1362                 }
1363             }
1364             else
1365             {
1366                 p->SbxValue::Clear();
1367                 /*
1368                 sal_uInt16 nFlags = p->GetFlags();
1369                 p->SetFlags( (nFlags | SBX_WRITE) & (~SBX_FIXED) );
1370                 p->PutEmpty();
1371                 p->SetFlags( nFlags );
1372                 */
1373             }
1374         }
1375     }
1376 }
1377 
1378 void SbModule::implClearIfVarDependsOnDeletedBasic( SbxVariable* pVar, StarBASIC* pDeletedBasic )
1379 {
1380     if( pVar->SbxValue::GetType() != SbxOBJECT || pVar->ISA( SbProcedureProperty ) )
1381         return;
1382 
1383     SbxObject* pObj = PTR_CAST(SbxObject,pVar->GetObject());
1384     if( pObj != NULL )
1385     {
1386         SbxObject* p = pObj;
1387 
1388         SbModule* pMod = PTR_CAST( SbModule, p );
1389         if( pMod != NULL )
1390             pMod->ClearVarsDependingOnDeletedBasic( pDeletedBasic );
1391 
1392         while( (p = p->GetParent()) != NULL )
1393         {
1394             StarBASIC* pBasic = PTR_CAST( StarBASIC, p );
1395             if( pBasic != NULL && pBasic == pDeletedBasic )
1396             {
1397                 pVar->SbxValue::Clear();
1398                 break;
1399             }
1400         }
1401     }
1402 }
1403 
1404 void SbModule::ClearVarsDependingOnDeletedBasic( StarBASIC* pDeletedBasic )
1405 {
1406     (void)pDeletedBasic;
1407 
1408     for( sal_uInt16 i = 0 ; i < pProps->Count() ; i++ )
1409     {
1410         SbProperty* p = PTR_CAST(SbProperty,pProps->Get( i ) );
1411         if( p )
1412         {
1413             if( p->GetType() & SbxARRAY )
1414             {
1415                 SbxArray* pArray = PTR_CAST(SbxArray,p->GetObject());
1416                 if( pArray )
1417                 {
1418                     for( sal_uInt16 j = 0 ; j < pArray->Count() ; j++ )
1419                     {
1420                         SbxVariable* pVar = PTR_CAST(SbxVariable,pArray->Get( j ));
1421                         implClearIfVarDependsOnDeletedBasic( pVar, pDeletedBasic );
1422                     }
1423                 }
1424             }
1425             else
1426             {
1427                 implClearIfVarDependsOnDeletedBasic( p, pDeletedBasic );
1428             }
1429         }
1430     }
1431 }
1432 
1433 // Zunaechst in dieses Modul, um 358-faehig zu bleiben
1434 // (Branch in sb.cxx vermeiden)
1435 void StarBASIC::ClearAllModuleVars( void )
1436 {
1437     // Eigene Module initialisieren
1438     for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ )
1439     {
1440         SbModule* pModule = (SbModule*)pModules->Get( nMod );
1441         // Nur initialisieren, wenn der Startcode schon ausgefuehrt wurde
1442         if( pModule->pImage && pModule->pImage->bInit && !pModule->isProxyModule() && !pModule->ISA(SbObjModule) )
1443             pModule->ClearPrivateVars();
1444     }
1445 
1446     /* #88042 This code can delete already used public vars during runtime!
1447     // Alle Objekte ueberpruefen, ob es sich um ein Basic handelt
1448     // Wenn ja, auch dort initialisieren
1449     for ( sal_uInt16 nObj = 0; nObj < pObjs->Count(); nObj++ )
1450     {
1451         SbxVariable* pVar = pObjs->Get( nObj );
1452         StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar);
1453         if( pBasic )
1454             pBasic->ClearAllModuleVars();
1455     }
1456     */
1457 }
1458 
1459 // Ausfuehren des Init-Codes aller Module
1460 void SbModule::GlobalRunInit( sal_Bool bBasicStart )
1461 {
1462     // Wenn kein Basic-Start, nur initialisieren, wenn Modul uninitialisiert
1463     if( !bBasicStart )
1464         if( !(pImage && !pImage->bInit) )
1465             return;
1466 
1467     // GlobalInitErr-Flag fuer Compiler-Error initialisieren
1468     // Anhand dieses Flags kann in SbModule::Run() nach dem Aufruf
1469     // von GlobalRunInit festgestellt werden, ob beim initialisieren
1470     // der Module ein Fehler auftrat. Dann wird nicht gestartet.
1471     GetSbData()->bGlobalInitErr = sal_False;
1472 
1473     // Parent vom Modul ist ein Basic
1474     StarBASIC *pBasic = PTR_CAST(StarBASIC,GetParent());
1475     if( pBasic )
1476     {
1477         pBasic->InitAllModules();
1478 
1479         SbxObject* pParent_ = pBasic->GetParent();
1480         if( pParent_ )
1481         {
1482             StarBASIC * pParentBasic = PTR_CAST(StarBASIC,pParent_);
1483             if( pParentBasic )
1484             {
1485                 pParentBasic->InitAllModules( pBasic );
1486 
1487                 // #109018 Parent can also have a parent (library in doc)
1488                 SbxObject* pParentParent = pParentBasic->GetParent();
1489                 if( pParentParent )
1490                 {
1491                     StarBASIC * pParentParentBasic = PTR_CAST(StarBASIC,pParentParent);
1492                     if( pParentParentBasic )
1493                         pParentParentBasic->InitAllModules( pParentBasic );
1494                 }
1495             }
1496         }
1497     }
1498 }
1499 
1500 void SbModule::GlobalRunDeInit( void )
1501 {
1502     StarBASIC *pBasic = PTR_CAST(StarBASIC,GetParent());
1503     if( pBasic )
1504     {
1505         pBasic->DeInitAllModules();
1506 
1507         SbxObject* pParent_ = pBasic->GetParent();
1508         if( pParent_ )
1509             pBasic = PTR_CAST(StarBASIC,pParent_);
1510         if( pBasic )
1511             pBasic->DeInitAllModules();
1512     }
1513 }
1514 
1515 // Suche nach dem naechsten STMNT-Befehl im Code. Wird vom STMNT-
1516 // Opcode verwendet, um die Endspalte zu setzen.
1517 
1518 const sal_uInt8* SbModule::FindNextStmnt( const sal_uInt8* p, sal_uInt16& nLine, sal_uInt16& nCol ) const
1519 {
1520     return FindNextStmnt( p, nLine, nCol, sal_False );
1521 }
1522 
1523 const sal_uInt8* SbModule::FindNextStmnt( const sal_uInt8* p, sal_uInt16& nLine, sal_uInt16& nCol,
1524     sal_Bool bFollowJumps, const SbiImage* pImg ) const
1525 {
1526     sal_uInt32 nPC = (sal_uInt32) ( p - (const sal_uInt8*) pImage->GetCode() );
1527     while( nPC < pImage->GetCodeSize() )
1528     {
1529         SbiOpcode eOp = (SbiOpcode ) ( *p++ );
1530         nPC++;
1531         if( bFollowJumps && eOp == _JUMP && pImg )
1532         {
1533             DBG_ASSERT( pImg, "FindNextStmnt: pImg==NULL with FollowJumps option" );
1534             sal_uInt32 nOp1 = *p++; nOp1 |= *p++ << 8;
1535             nOp1 |= *p++ << 16; nOp1 |= *p++ << 24;
1536             p = (const sal_uInt8*) pImg->GetCode() + nOp1;
1537         }
1538         else if( eOp >= SbOP1_START && eOp <= SbOP1_END )
1539             p += 4, nPC += 4;
1540         else if( eOp == _STMNT )
1541         {
1542             sal_uInt32 nl, nc;
1543             nl = *p++; nl |= *p++ << 8;
1544             nl |= *p++ << 16 ; nl |= *p++ << 24;
1545             nc = *p++; nc |= *p++ << 8;
1546             nc |= *p++ << 16 ; nc |= *p++ << 24;
1547             nLine = (sal_uInt16)nl; nCol = (sal_uInt16)nc;
1548             return p;
1549         }
1550         else if( eOp >= SbOP2_START && eOp <= SbOP2_END )
1551             p += 8, nPC += 8;
1552         else if( !( eOp >= SbOP0_START && eOp <= SbOP0_END ) )
1553         {
1554             StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
1555             break;
1556         }
1557     }
1558     return NULL;
1559 }
1560 
1561 // Testen, ob eine Zeile STMNT-Opcodes enthaelt
1562 
1563 sal_Bool SbModule::IsBreakable( sal_uInt16 nLine ) const
1564 {
1565     if( !pImage )
1566         return sal_False;
1567     const sal_uInt8* p = (const sal_uInt8* ) pImage->GetCode();
1568     sal_uInt16 nl, nc;
1569     while( ( p = FindNextStmnt( p, nl, nc ) ) != NULL )
1570         if( nl == nLine )
1571             return sal_True;
1572     return sal_False;
1573 }
1574 
1575 size_t SbModule::GetBPCount() const
1576 {
1577     return pBreaks ? pBreaks->size() : 0;
1578 }
1579 
1580 sal_uInt16 SbModule::GetBP( size_t n ) const
1581 {
1582     if( pBreaks && n < pBreaks->size() )
1583         return pBreaks->operator[]( n );
1584     else
1585         return 0;
1586 }
1587 
1588 sal_Bool SbModule::IsBP( sal_uInt16 nLine ) const
1589 {
1590     if( pBreaks )
1591     {
1592         for( size_t i = 0; i < pBreaks->size(); i++ )
1593         {
1594             sal_uInt16 b = pBreaks->operator[]( i );
1595             if( b == nLine )
1596                 return sal_True;
1597             if( b < nLine )
1598                 break;
1599         }
1600     }
1601     return sal_False;
1602 }
1603 
1604 sal_Bool SbModule::SetBP( sal_uInt16 nLine )
1605 {
1606     if( !IsBreakable( nLine ) )
1607         return sal_False;
1608     if( !pBreaks )
1609         pBreaks = new SbiBreakpoints;
1610     size_t i;
1611     for( i = 0; i < pBreaks->size(); i++ )
1612     {
1613         sal_uInt16 b = pBreaks->operator[]( i );
1614         if( b == nLine )
1615             return sal_True;
1616         if( b < nLine )
1617             break;
1618     }
1619     pBreaks->insert( pBreaks->begin() + i, nLine );
1620 
1621     // #38568: Zur Laufzeit auch hier SbDEBUG_BREAK setzen
1622     if( pINST && pINST->pRun )
1623         pINST->pRun->SetDebugFlags( SbDEBUG_BREAK );
1624 
1625     return IsBreakable( nLine );
1626 }
1627 
1628 sal_Bool SbModule::ClearBP( sal_uInt16 nLine )
1629 {
1630     sal_Bool bRes = sal_False;
1631     if( pBreaks )
1632     {
1633         for( size_t i = 0; i < pBreaks->size(); i++ )
1634         {
1635             sal_uInt16 b = pBreaks->operator[]( i );
1636             if( b == nLine )
1637             {
1638                 pBreaks->erase( pBreaks->begin() + i );
1639                 bRes = sal_True;
1640                 break;
1641             }
1642             if( b < nLine )
1643                 break;
1644         }
1645         if( pBreaks->empty() )
1646             delete pBreaks, pBreaks = NULL;
1647     }
1648     return bRes;
1649 }
1650 
1651 void SbModule::ClearAllBP()
1652 {
1653     delete pBreaks;
1654     pBreaks = NULL;
1655 }
1656 
1657 void
1658 SbModule::fixUpMethodStart( bool bCvtToLegacy, SbiImage* pImg ) const
1659 {
1660         if ( !pImg )
1661             pImg = pImage;
1662         for( sal_uInt32 i = 0; i < pMethods->Count(); i++ )
1663         {
1664             SbMethod* pMeth = PTR_CAST(SbMethod,pMethods->Get( (sal_uInt16)i ) );
1665             if( pMeth )
1666             {
1667                 //fixup method start positions
1668                 if ( bCvtToLegacy )
1669                     pMeth->nStart = pImg->CalcLegacyOffset( pMeth->nStart );
1670                 else
1671                     pMeth->nStart = pImg->CalcNewOffset( (sal_uInt16)pMeth->nStart );
1672             }
1673         }
1674 
1675 }
1676 
1677 sal_Bool SbModule::LoadData( SvStream& rStrm, sal_uInt16 nVer )
1678 {
1679     Clear();
1680     if( !SbxObject::LoadData( rStrm, 1 ) )
1681         return sal_False;
1682     // Precaution...
1683     SetFlag( SBX_EXTSEARCH | SBX_GBLSEARCH );
1684     sal_uInt8 bImage;
1685     rStrm >> bImage;
1686     if( bImage )
1687     {
1688         SbiImage* p = new SbiImage;
1689         sal_uInt32 nImgVer = 0;
1690 
1691         if( !p->Load( rStrm, nImgVer ) )
1692         {
1693             delete p;
1694             return sal_False;
1695         }
1696         // If the image is in old format, we fix up the method start offsets
1697         if ( nImgVer < B_EXT_IMG_VERSION )
1698         {
1699             fixUpMethodStart( false, p );
1700             p->ReleaseLegacyBuffer();
1701         }
1702         aComment = p->aComment;
1703         SetName( p->aName );
1704         if( p->GetCodeSize() )
1705         {
1706             aOUSource = p->aOUSource;
1707             // Alte Version: Image weg
1708             if( nVer == 1 )
1709             {
1710                 SetSource32( p->aOUSource );
1711                 delete p;
1712             }
1713             else
1714                 pImage = p;
1715         }
1716         else
1717         {
1718             SetSource32( p->aOUSource );
1719             delete p;
1720         }
1721     }
1722     return sal_True;
1723 }
1724 
1725 sal_Bool SbModule::StoreData( SvStream& rStrm ) const
1726 {
1727     sal_Bool bFixup = ( pImage && !pImage->ExceedsLegacyLimits() );
1728     if ( bFixup )
1729         fixUpMethodStart( true );
1730     sal_Bool bRet = SbxObject::StoreData( rStrm );
1731     if ( !bRet )
1732         return sal_False;
1733 
1734     if( pImage )
1735     {
1736         pImage->aOUSource = aOUSource;
1737         pImage->aComment = aComment;
1738         pImage->aName = GetName();
1739         rStrm << (sal_uInt8) 1;
1740         // # PCode is saved only for legacy formats only
1741         // It should be noted that it probably isn't necessary
1742         // It would be better not to store the image ( more flexible with
1743         // formats )
1744         bool bRes = pImage->Save( rStrm, B_LEGACYVERSION );
1745         if ( bFixup )
1746             fixUpMethodStart( false ); // restore method starts
1747         return bRes;
1748 
1749     }
1750     else
1751     {
1752         SbiImage aImg;
1753         aImg.aOUSource = aOUSource;
1754         aImg.aComment = aComment;
1755         aImg.aName = GetName();
1756         rStrm << (sal_uInt8) 1;
1757         return aImg.Save( rStrm );
1758     }
1759 }
1760 
1761 sal_Bool SbModule::ExceedsLegacyModuleSize()
1762 {
1763     if ( !IsCompiled() )
1764         Compile();
1765     if ( pImage && pImage->ExceedsLegacyLimits() )
1766         return true;
1767     return false;
1768 }
1769 
1770 
1771 // Store only image, no source
1772 sal_Bool SbModule::StoreBinaryData( SvStream& rStrm )
1773 {
1774     return StoreBinaryData( rStrm, 0 );
1775 }
1776 
1777 sal_Bool SbModule::StoreBinaryData( SvStream& rStrm, sal_uInt16 nVer )
1778 {
1779     sal_Bool bRet = Compile();
1780     if( bRet )
1781     {
1782         sal_Bool bFixup = ( !nVer && !pImage->ExceedsLegacyLimits() );// save in old image format, fix up method starts
1783 
1784         if ( bFixup ) // save in old image format, fix up method starts
1785             fixUpMethodStart( true );
1786         bRet = SbxObject::StoreData( rStrm );
1787         if( bRet )
1788         {
1789             pImage->aOUSource = ::rtl::OUString();
1790             pImage->aComment = aComment;
1791             pImage->aName = GetName();
1792 
1793             rStrm << (sal_uInt8) 1;
1794                     if ( nVer )
1795                         bRet = pImage->Save( rStrm, B_EXT_IMG_VERSION );
1796                     else
1797                         bRet = pImage->Save( rStrm, B_LEGACYVERSION );
1798                     if ( bFixup )
1799                         fixUpMethodStart( false ); // restore method starts
1800 
1801             pImage->aOUSource = aOUSource;
1802         }
1803     }
1804     return bRet;
1805 }
1806 
1807 // Called for >= OO 1.0 passwd protected libraries only
1808 //
1809 
1810 sal_Bool SbModule::LoadBinaryData( SvStream& rStrm )
1811 {
1812     ::rtl::OUString aKeepSource = aOUSource;
1813     bool bRet = LoadData( rStrm, 2 );
1814     LoadCompleted();
1815     aOUSource = aKeepSource;
1816     return bRet;
1817 }
1818 
1819 
1820 sal_Bool SbModule::LoadCompleted()
1821 {
1822     SbxArray* p = GetMethods();
1823     sal_uInt16 i;
1824     for( i = 0; i < p->Count(); i++ )
1825     {
1826         SbMethod* q = PTR_CAST(SbMethod,p->Get( i ) );
1827         if( q )
1828             q->pMod = this;
1829     }
1830     p = GetProperties();
1831     for( i = 0; i < p->Count(); i++ )
1832     {
1833         SbProperty* q = PTR_CAST(SbProperty,p->Get( i ) );
1834         if( q )
1835             q->pMod = this;
1836     }
1837     return sal_True;
1838 }
1839 
1840 void SbModule::handleProcedureProperties( SfxBroadcaster& rBC, const SfxHint& rHint )
1841 {
1842     bool bDone = false;
1843 
1844     const SbxHint* pHint = PTR_CAST(SbxHint,&rHint);
1845     if( pHint )
1846     {
1847         SbxVariable* pVar = pHint->GetVar();
1848         SbProcedureProperty* pProcProperty = PTR_CAST( SbProcedureProperty, pVar );
1849         if( pProcProperty )
1850         {
1851             bDone = true;
1852 
1853             if( pHint->GetId() == SBX_HINT_DATAWANTED )
1854             {
1855                 String aProcName;
1856                 aProcName.AppendAscii( "Property Get " );
1857                 aProcName += pProcProperty->GetName();
1858 
1859                 SbxVariable* pMeth = Find( aProcName, SbxCLASS_METHOD );
1860                 if( pMeth )
1861                 {
1862                     SbxValues aVals;
1863                     aVals.eType = SbxVARIANT;
1864 
1865                     SbxArray* pArg = pVar->GetParameters();
1866                     sal_uInt16 nVarParCount = (pArg != NULL) ? pArg->Count() : 0;
1867                     if( nVarParCount > 1 )
1868                     {
1869                         SbxArrayRef xMethParameters = new SbxArray;
1870                         xMethParameters->Put( pMeth, 0 );   // Method as parameter 0
1871                         for( sal_uInt16 i = 1 ; i < nVarParCount ; ++i )
1872                         {
1873                             SbxVariable* pPar = pArg->Get( i );
1874                             xMethParameters->Put( pPar, i );
1875                         }
1876 
1877                         pMeth->SetParameters( xMethParameters );
1878                         pMeth->Get( aVals );
1879                         pMeth->SetParameters( NULL );
1880                     }
1881                     else
1882                     {
1883                         pMeth->Get( aVals );
1884                     }
1885 
1886                     pVar->Put( aVals );
1887                 }
1888             }
1889             else if( pHint->GetId() == SBX_HINT_DATACHANGED )
1890             {
1891                 SbxVariable* pMeth = NULL;
1892 
1893                 bool bSet = pProcProperty->isSet();
1894                 if( bSet )
1895                 {
1896                     pProcProperty->setSet( false );
1897 
1898                     String aProcName;
1899                     aProcName.AppendAscii( "Property Set " );
1900                     aProcName += pProcProperty->GetName();
1901                     pMeth = Find( aProcName, SbxCLASS_METHOD );
1902                 }
1903                 if( !pMeth )    // Let
1904                 {
1905                     String aProcName;
1906                     aProcName.AppendAscii( "Property Let " );
1907                     aProcName += pProcProperty->GetName();
1908                     pMeth = Find( aProcName, SbxCLASS_METHOD );
1909                 }
1910 
1911                 if( pMeth )
1912                 {
1913                     // Setup parameters
1914                     SbxArrayRef xArray = new SbxArray;
1915                     xArray->Put( pMeth, 0 );    // Method as parameter 0
1916                     xArray->Put( pVar, 1 );
1917                     pMeth->SetParameters( xArray );
1918 
1919                     SbxValues aVals;
1920                     pMeth->Get( aVals );
1921                     pMeth->SetParameters( NULL );
1922                 }
1923             }
1924         }
1925     }
1926 
1927     if( !bDone )
1928         SbModule::Notify( rBC, rHint );
1929 }
1930 
1931 
1932 /////////////////////////////////////////////////////////////////////////
1933 // Implementation SbJScriptModule (Basic-Modul fuer JavaScript-Sourcen)
1934 SbJScriptModule::SbJScriptModule( const String& rName )
1935     :SbModule( rName )
1936 {
1937 }
1938 
1939 sal_Bool SbJScriptModule::LoadData( SvStream& rStrm, sal_uInt16 nVer )
1940 {
1941     (void)nVer;
1942 
1943     Clear();
1944     if( !SbxObject::LoadData( rStrm, 1 ) )
1945         return sal_False;
1946 
1947     // Source-String holen
1948     String aTmp;
1949     rStrm.ReadByteString( aTmp, gsl_getSystemTextEncoding() );
1950     aOUSource = aTmp;
1951     //rStrm >> aSource;
1952     return sal_True;
1953 }
1954 
1955 sal_Bool SbJScriptModule::StoreData( SvStream& rStrm ) const
1956 {
1957     if( !SbxObject::StoreData( rStrm ) )
1958         return sal_False;
1959 
1960     // Source-String schreiben
1961     String aTmp = aOUSource;
1962     rStrm.WriteByteString( aTmp, gsl_getSystemTextEncoding() );
1963     //rStrm << aSource;
1964     return sal_True;
1965 }
1966 
1967 
1968 /////////////////////////////////////////////////////////////////////////
1969 
1970 SbMethod::SbMethod( const String& r, SbxDataType t, SbModule* p )
1971         : SbxMethod( r, t ), pMod( p )
1972 {
1973     bInvalid     = sal_True;
1974     nStart       =
1975     nDebugFlags  =
1976     nLine1       =
1977     nLine2       = 0;
1978     refStatics = new SbxArray;
1979     // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden'
1980     SetFlag( SBX_NO_MODIFY );
1981 }
1982 
1983 SbMethod::SbMethod( const SbMethod& r )
1984     : SvRefBase( r ), SbxMethod( r )
1985 {
1986     pMod         = r.pMod;
1987     bInvalid     = r.bInvalid;
1988     nStart       = r.nStart;
1989     nDebugFlags  = r.nDebugFlags;
1990     nLine1       = r.nLine1;
1991     nLine2       = r.nLine2;
1992         refStatics = r.refStatics;
1993     SetFlag( SBX_NO_MODIFY );
1994 }
1995 
1996 SbMethod::~SbMethod()
1997 {
1998 }
1999 
2000 SbxArray* SbMethod::GetLocals()
2001 {
2002     if( pINST )
2003         return pINST->GetLocals( this );
2004     else
2005         return NULL;
2006 }
2007 
2008 void SbMethod::ClearStatics()
2009 {
2010     refStatics = new SbxArray;
2011 
2012 }
2013 SbxArray* SbMethod::GetStatics()
2014 {
2015     return refStatics;
2016 }
2017 
2018 sal_Bool SbMethod::LoadData( SvStream& rStrm, sal_uInt16 nVer )
2019 {
2020     if( !SbxMethod::LoadData( rStrm, 1 ) )
2021         return sal_False;
2022     sal_Int16 n;
2023     rStrm >> n;
2024     sal_Int16 nTempStart = (sal_Int16)nStart;
2025     // nDebugFlags = n;     // AB 16.1.96: Nicht mehr uebernehmen
2026     if( nVer == 2 )
2027         rStrm >> nLine1 >> nLine2 >> nTempStart >> bInvalid;
2028     // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden'
2029     SetFlag( SBX_NO_MODIFY );
2030     nStart = nTempStart;
2031     return sal_True;
2032 }
2033 
2034 sal_Bool SbMethod::StoreData( SvStream& rStrm ) const
2035 {
2036     if( !SbxMethod::StoreData( rStrm ) )
2037         return sal_False;
2038     rStrm << (sal_Int16) nDebugFlags
2039           << (sal_Int16) nLine1
2040           << (sal_Int16) nLine2
2041           << (sal_Int16) nStart
2042           << (sal_uInt8)  bInvalid;
2043     return sal_True;
2044 }
2045 
2046 void SbMethod::GetLineRange( sal_uInt16& l1, sal_uInt16& l2 )
2047 {
2048     l1 = nLine1; l2 = nLine2;
2049 }
2050 
2051 // Kann spaeter mal weg
2052 
2053 SbxInfo* SbMethod::GetInfo()
2054 {
2055     return pInfo;
2056 }
2057 
2058 // Schnittstelle zum Ausfuehren einer Methode aus den Applikationen
2059 // #34191# Mit speziellem RefCounting, damit das Basic nicht durch CloseDocument()
2060 // abgeschossen werden kann. Rueckgabewert wird als String geliefert.
2061 ErrCode SbMethod::Call( SbxValue* pRet )
2062 {
2063     // RefCount vom Modul hochzaehlen
2064     SbModule* pMod_ = (SbModule*)GetParent();
2065     pMod_->AddRef();
2066 
2067     // RefCount vom Basic hochzaehlen
2068     StarBASIC* pBasic = (StarBASIC*)pMod_->GetParent();
2069     pBasic->AddRef();
2070 
2071     // Values anlegen, um Return-Wert zu erhalten
2072     SbxValues aVals;
2073     aVals.eType = SbxVARIANT;
2074 
2075     // #104083: Compile BEFORE get
2076     if( bInvalid && !pMod_->Compile() )
2077         StarBASIC::Error( SbERR_BAD_PROP_VALUE );
2078 
2079     Get( aVals );
2080     if ( pRet )
2081         pRet->Put( aVals );
2082 
2083     // Gab es einen Error
2084     ErrCode nErr = SbxBase::GetError();
2085     SbxBase::ResetError();
2086 
2087     // Objekte freigeben
2088     pMod_->ReleaseRef();
2089     pBasic->ReleaseRef();
2090 
2091     return nErr;
2092 }
2093 
2094 
2095 // #100883 Own Broadcast for SbMethod
2096 void SbMethod::Broadcast( sal_uIntPtr nHintId )
2097 {
2098     if( pCst && !IsSet( SBX_NO_BROADCAST ) && StaticIsEnabledBroadcasting() )
2099     {
2100         // Da die Methode von aussen aufrufbar ist, hier noch einmal
2101         // die Berechtigung testen
2102         if( nHintId & SBX_HINT_DATAWANTED )
2103             if( !CanRead() )
2104                 return;
2105         if( nHintId & SBX_HINT_DATACHANGED )
2106             if( !CanWrite() )
2107                 return;
2108 
2109         if( pMod && !pMod->IsCompiled() )
2110             pMod->Compile();
2111 
2112         // Block broadcasts while creating new method
2113         SfxBroadcaster* pSave = pCst;
2114         pCst = NULL;
2115         SbMethod* pThisCopy = new SbMethod( *this );
2116         SbMethodRef xHolder = pThisCopy;
2117         if( mpPar.Is() )
2118         {
2119             // this, als Element 0 eintragen, aber den Parent nicht umsetzen!
2120             if( GetType() != SbxVOID )
2121                 mpPar->PutDirect( pThisCopy, 0 );
2122             SetParameters( NULL );
2123         }
2124 
2125         pCst = pSave;
2126         pSave->Broadcast( SbxHint( nHintId, pThisCopy ) );
2127 
2128         sal_uInt16 nSaveFlags = GetFlags();
2129         SetFlag( SBX_READWRITE );
2130         pCst = NULL;
2131         Put( pThisCopy->GetValues_Impl() );
2132         pCst = pSave;
2133         SetFlags( nSaveFlags );
2134     }
2135 }
2136 
2137 /////////////////////////////////////////////////////////////////////////
2138 
2139 // Implementation SbJScriptMethod (Method-Klasse als Wrapper fuer JavaScript-Funktionen)
2140 
2141 SbJScriptMethod::SbJScriptMethod( const String& r, SbxDataType t, SbModule* p )
2142         : SbMethod( r, t, p )
2143 {
2144 }
2145 
2146 SbJScriptMethod::~SbJScriptMethod()
2147 {}
2148 
2149 
2150 /////////////////////////////////////////////////////////////////////////
2151 SbObjModule::SbObjModule( const String& rName, const com::sun::star::script::ModuleInfo& mInfo, bool bIsVbaCompatible )
2152     : SbModule( rName, bIsVbaCompatible )
2153 {
2154     SetModuleType( mInfo.ModuleType );
2155     if ( mInfo.ModuleType == script::ModuleType::FORM )
2156     {
2157         SetClassName( rtl::OUString::createFromAscii( "Form" ) );
2158     }
2159     else if ( mInfo.ModuleObject.is() )
2160         SetUnoObject( uno::makeAny( mInfo.ModuleObject ) );
2161 }
2162 
2163 SbObjModule::~SbObjModule()
2164 {
2165 }
2166 
2167 void
2168 SbObjModule::SetUnoObject( const uno::Any& aObj ) throw ( uno::RuntimeException )
2169 {
2170     SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxVariable*)pDocObject);
2171     if ( pUnoObj && pUnoObj->getUnoAny() == aObj ) // object is equal, nothing to do
2172         return;
2173     pDocObject = new SbUnoObject( GetName(), uno::makeAny( aObj ) );
2174 
2175     com::sun::star::uno::Reference< com::sun::star::lang::XServiceInfo > xServiceInfo( aObj, com::sun::star::uno::UNO_QUERY_THROW );
2176     if( xServiceInfo->supportsService( rtl::OUString::createFromAscii( "ooo.vba.excel.Worksheet" ) ) )
2177     {
2178         SetClassName( rtl::OUString::createFromAscii( "Worksheet" ) );
2179     }
2180     else if( xServiceInfo->supportsService( rtl::OUString::createFromAscii( "ooo.vba.excel.Workbook" ) ) )
2181     {
2182         SetClassName( rtl::OUString::createFromAscii( "Workbook" ) );
2183     }
2184 }
2185 
2186 SbxVariable*
2187 SbObjModule::GetObject()
2188 {
2189     return pDocObject;
2190 }
2191 SbxVariable*
2192 SbObjModule::Find( const XubString& rName, SbxClassType t )
2193 {
2194     //OSL_TRACE("SbObjectModule find for %s", rtl::OUStringToOString(  rName, RTL_TEXTENCODING_UTF8 ).getStr() );
2195     SbxVariable* pVar = NULL;
2196     if ( pDocObject)
2197         pVar = pDocObject->Find( rName, t );
2198     if ( !pVar )
2199         pVar = SbModule::Find( rName, t );
2200     return pVar;
2201 }
2202 
2203 void SbObjModule::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
2204                          const SfxHint& rHint, const TypeId& rHintType )
2205 {
2206     SbModule::handleProcedureProperties( rBC, rHint );
2207 }
2208 
2209 
2210 typedef ::cppu::WeakImplHelper3<
2211     awt::XTopWindowListener,
2212     awt::XWindowListener,
2213     document::XEventListener > FormObjEventListener_BASE;
2214 
2215 class FormObjEventListenerImpl : public FormObjEventListener_BASE
2216 {
2217     SbUserFormModule* mpUserForm;
2218     uno::Reference< lang::XComponent > mxComponent;
2219     uno::Reference< frame::XModel > mxModel;
2220     bool mbDisposed;
2221     sal_Bool mbOpened;
2222     sal_Bool mbActivated;
2223     sal_Bool mbShowing;
2224 
2225     FormObjEventListenerImpl(const FormObjEventListenerImpl&); // not defined
2226     FormObjEventListenerImpl& operator=(const FormObjEventListenerImpl&); // not defined
2227 
2228 public:
2229     FormObjEventListenerImpl( SbUserFormModule* pUserForm, const uno::Reference< lang::XComponent >& xComponent, const uno::Reference< frame::XModel >& xModel ) :
2230         mpUserForm( pUserForm ), mxComponent( xComponent), mxModel( xModel ),
2231         mbDisposed( false ), mbOpened( sal_False ), mbActivated( sal_False ), mbShowing( sal_False )
2232     {
2233         if ( mxComponent.is() )
2234         {
2235             OSL_TRACE("*********** Registering the listeners");
2236             try
2237             {
2238                 uno::Reference< awt::XTopWindow >( mxComponent, uno::UNO_QUERY_THROW )->addTopWindowListener( this );
2239             }
2240             catch( uno::Exception& ) {}
2241             try
2242             {
2243                 uno::Reference< awt::XWindow >( mxComponent, uno::UNO_QUERY_THROW )->addWindowListener( this );
2244             }
2245             catch( uno::Exception& ) {}
2246         }
2247 
2248         if ( mxModel.is() )
2249         {
2250             try
2251             {
2252                 uno::Reference< document::XEventBroadcaster >( mxModel, uno::UNO_QUERY_THROW )->addEventListener( this );
2253             }
2254             catch( uno::Exception& ) {}
2255         }
2256     }
2257 
2258     virtual ~FormObjEventListenerImpl()
2259     {
2260         removeListener();
2261     }
2262 
2263     sal_Bool isShowing() const { return mbShowing; }
2264 
2265     void removeListener()
2266     {
2267         if ( mxComponent.is() && !mbDisposed )
2268         {
2269             OSL_TRACE("*********** Removing the listeners");
2270             try
2271             {
2272                 uno::Reference< awt::XTopWindow >( mxComponent, uno::UNO_QUERY_THROW )->removeTopWindowListener( this );
2273             }
2274             catch( uno::Exception& ) {}
2275             try
2276             {
2277                 uno::Reference< awt::XWindow >( mxComponent, uno::UNO_QUERY_THROW )->removeWindowListener( this );
2278             }
2279             catch( uno::Exception& ) {}
2280         }
2281         mxComponent.clear();
2282 
2283         if ( mxModel.is() && !mbDisposed )
2284         {
2285             try
2286             {
2287                 uno::Reference< document::XEventBroadcaster >( mxModel, uno::UNO_QUERY_THROW )->removeEventListener( this );
2288             }
2289             catch( uno::Exception& ) {}
2290         }
2291         mxModel.clear();
2292     }
2293 
2294     virtual void SAL_CALL windowOpened( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
2295     {
2296         if ( mpUserForm )
2297         {
2298             mbOpened = sal_True;
2299             mbShowing = sal_True;
2300             if ( mbActivated )
2301             {
2302                 mbOpened = mbActivated = sal_False;
2303                 mpUserForm->triggerActivateEvent();
2304             }
2305         }
2306     }
2307 
2308     //liuchen 2009-7-21, support Excel VBA Form_QueryClose event
2309     virtual void SAL_CALL windowClosing( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
2310     {
2311 #if IN_THE_FUTURE
2312         uno::Reference< awt::XDialog > xDialog( e.Source, uno::UNO_QUERY );
2313         if ( xDialog.is() )
2314         {
2315             uno::Reference< awt::XControl > xControl( xDialog, uno::UNO_QUERY );
2316             if ( xControl->getPeer().is() )
2317             {
2318                 uno::Reference< document::XVbaMethodParameter > xVbaMethodParameter( xControl->getPeer(), uno::UNO_QUERY );
2319                 if ( xVbaMethodParameter.is() )
2320                 {
2321 #endif
2322                     sal_Int8 nCancel = 0;
2323                     sal_Int8 nCloseMode = ::ooo::vba::VbQueryClose::vbFormControlMenu;
2324 
2325                     Sequence< Any > aParams;
2326                     aParams.realloc(2);
2327                     aParams[0] <<= nCancel;
2328                     aParams[1] <<= nCloseMode;
2329 
2330                     mpUserForm->triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ),
2331                                                 aParams);
2332 #if IN_THE_FUTURE
2333                     xVbaMethodParameter->setVbaMethodParameter( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Cancel")), aParams[0]);
2334                     return;
2335 
2336                 }
2337             }
2338         }
2339 #endif
2340     }
2341     //liuchen 2009-7-21
2342 
2343     virtual void SAL_CALL windowClosed( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
2344     {
2345         mbOpened = sal_False;
2346         mbShowing = sal_False;
2347     }
2348 
2349     virtual void SAL_CALL windowMinimized( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
2350     {
2351     }
2352 
2353     virtual void SAL_CALL windowNormalized( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
2354     {
2355     }
2356 
2357     virtual void SAL_CALL windowActivated( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
2358     {
2359         if ( mpUserForm )
2360         {
2361             mbActivated = sal_True;
2362             if ( mbOpened )
2363             {
2364                 mbOpened = mbActivated = sal_False;
2365                 mpUserForm->triggerActivateEvent();
2366             }
2367         }
2368     }
2369 
2370     virtual void SAL_CALL windowDeactivated( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
2371     {
2372         if ( mpUserForm )
2373             mpUserForm->triggerDeactivateEvent();
2374     }
2375 
2376     virtual void SAL_CALL windowResized( const awt::WindowEvent& /*e*/ ) throw (uno::RuntimeException)
2377     {
2378         if ( mpUserForm )
2379         {
2380             mpUserForm->triggerResizeEvent();
2381             mpUserForm->triggerLayoutEvent();
2382         }
2383     }
2384 
2385     virtual void SAL_CALL windowMoved( const awt::WindowEvent& /*e*/ ) throw (uno::RuntimeException)
2386     {
2387         if ( mpUserForm )
2388             mpUserForm->triggerLayoutEvent();
2389     }
2390 
2391     virtual void SAL_CALL windowShown( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
2392     {
2393     }
2394 
2395     virtual void SAL_CALL windowHidden( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException)
2396     {
2397     }
2398 
2399     virtual void SAL_CALL notifyEvent( const document::EventObject& rEvent ) throw (uno::RuntimeException)
2400     {
2401         // early dosposing on document event "OnUnload", to be sure Basic still exists when calling VBA "UserForm_Terminate"
2402         if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_CLOSEDOC ) )
2403         {
2404             removeListener();
2405             mbDisposed = true;
2406             if ( mpUserForm )
2407                 mpUserForm->ResetApiObj();   // will trigger "UserForm_Terminate"
2408         }
2409     }
2410 
2411     virtual void SAL_CALL disposing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException)
2412     {
2413         OSL_TRACE("** Userform/Dialog disposing");
2414         removeListener();
2415         mbDisposed = true;
2416         if ( mpUserForm )
2417             mpUserForm->ResetApiObj( false );   // pass false (too late to trigger VBA events here)
2418     }
2419 };
2420 
2421 SbUserFormModule::SbUserFormModule( const String& rName, const com::sun::star::script::ModuleInfo& mInfo, bool bIsCompat )
2422     : SbObjModule( rName, mInfo, bIsCompat )
2423     , m_mInfo( mInfo )
2424     , mbInit( false )
2425 {
2426     m_xModel.set( mInfo.ModuleObject, uno::UNO_QUERY_THROW );
2427 }
2428 
2429 SbUserFormModule::~SbUserFormModule()
2430 {
2431 }
2432 
2433 void SbUserFormModule::ResetApiObj(  bool bTriggerTerminateEvent )
2434 {
2435     if ( bTriggerTerminateEvent && m_xDialog.is() ) // probably someone close the dialog window
2436     {
2437         triggerTerminateEvent();
2438     }
2439     pDocObject = NULL;
2440     m_xDialog = NULL;
2441 }
2442 
2443 void SbUserFormModule::triggerMethod( const String& aMethodToRun )
2444 {
2445     Sequence< Any > aArguments;
2446     triggerMethod( aMethodToRun, aArguments );
2447 }
2448 
2449 void SbUserFormModule::triggerMethod( const String& aMethodToRun, Sequence< Any >& aArguments )
2450 {
2451     OSL_TRACE("*** trigger %s ***", rtl::OUStringToOString( aMethodToRun, RTL_TEXTENCODING_UTF8 ).getStr() );
2452     // Search method
2453     SbxVariable* pMeth = SbObjModule::Find( aMethodToRun, SbxCLASS_METHOD );
2454     if( pMeth )
2455     {
2456         if ( aArguments.getLength() > 0 )   // Setup parameters
2457         {
2458             SbxArrayRef xArray = new SbxArray;
2459             xArray->Put( pMeth, 0 );    // Method as parameter 0
2460 
2461             for ( sal_Int32 i = 0; i < aArguments.getLength(); ++i )
2462             {
2463                 SbxVariableRef xSbxVar = new SbxVariable( SbxVARIANT );
2464                 unoToSbxValue( static_cast< SbxVariable* >( xSbxVar ), aArguments[i] );
2465                 xArray->Put( xSbxVar, static_cast< sal_uInt16 >( i ) + 1 );
2466 
2467                 // Enable passing by ref
2468                 if ( xSbxVar->GetType() != SbxVARIANT )
2469                     xSbxVar->SetFlag( SBX_FIXED );
2470             }
2471             pMeth->SetParameters( xArray );
2472 
2473             SbxValues aVals;
2474             pMeth->Get( aVals );
2475 
2476             for ( sal_Int32 i = 0; i < aArguments.getLength(); ++i )
2477             {
2478                 aArguments[i] = sbxToUnoValue( xArray->Get( static_cast< sal_uInt16 >(i) + 1) );
2479             }
2480             pMeth->SetParameters( NULL );
2481         }
2482         else
2483         {
2484             SbxValues aVals;
2485             pMeth->Get( aVals );
2486         }
2487     }
2488 }
2489 
2490 void SbUserFormModule::triggerActivateEvent( void )
2491 {
2492     OSL_TRACE("**** entering SbUserFormModule::triggerActivate");
2493     triggerMethod( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("UserForm_Activate") ) );
2494     OSL_TRACE("**** leaving SbUserFormModule::triggerActivate");
2495 }
2496 
2497 void SbUserFormModule::triggerDeactivateEvent( void )
2498 {
2499     OSL_TRACE("**** SbUserFormModule::triggerDeactivate");
2500     triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_Deactivate") ) );
2501 }
2502 
2503 void SbUserFormModule::triggerInitializeEvent( void )
2504 {
2505     if ( mbInit )
2506         return;
2507     OSL_TRACE("**** SbUserFormModule::triggerInitializeEvent");
2508     static String aInitMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Initialize") );
2509     triggerMethod( aInitMethodName );
2510     mbInit = true;
2511 }
2512 
2513 void SbUserFormModule::triggerTerminateEvent( void )
2514 {
2515     OSL_TRACE("**** SbUserFormModule::triggerTerminateEvent");
2516     static String aTermMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Terminate") );
2517     triggerMethod( aTermMethodName );
2518     mbInit=false;
2519 }
2520 
2521 void SbUserFormModule::triggerLayoutEvent( void )
2522 {
2523     static String aMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Layout") );
2524     triggerMethod( aMethodName );
2525 }
2526 
2527 void SbUserFormModule::triggerResizeEvent( void )
2528 {
2529     static String aMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Resize") );
2530     triggerMethod( aMethodName );
2531 }
2532 
2533 SbUserFormModuleInstance* SbUserFormModule::CreateInstance()
2534 {
2535     SbUserFormModuleInstance* pInstance = new SbUserFormModuleInstance( this, GetName(), m_mInfo, IsVBACompat() );
2536     return pInstance;
2537 }
2538 
2539 SbUserFormModuleInstance::SbUserFormModuleInstance( SbUserFormModule* pParentModule,
2540     const String& rName, const com::sun::star::script::ModuleInfo& mInfo, bool bIsVBACompat )
2541         : SbUserFormModule( rName, mInfo, bIsVBACompat )
2542         , m_pParentModule( pParentModule )
2543 {
2544 }
2545 
2546 sal_Bool SbUserFormModuleInstance::IsClass( const XubString& rName ) const
2547 {
2548     sal_Bool bParentNameMatches = m_pParentModule->GetName().EqualsIgnoreCaseAscii( rName );
2549     sal_Bool bRet = bParentNameMatches || SbxObject::IsClass( rName );
2550     return bRet;
2551 }
2552 
2553 SbxVariable* SbUserFormModuleInstance::Find( const XubString& rName, SbxClassType t )
2554 {
2555     SbxVariable* pVar = m_pParentModule->Find( rName, t );
2556     return pVar;
2557 }
2558 
2559 
2560 void SbUserFormModule::Load()
2561 {
2562     OSL_TRACE("** load() ");
2563     // forces a load
2564     if ( !pDocObject )
2565         InitObject();
2566 }
2567 
2568 //liuchen 2009-7-21 change to accmordate VBA's beheavior
2569 void SbUserFormModule::Unload()
2570 {
2571     OSL_TRACE("** Unload() ");
2572 
2573     sal_Int8 nCancel = 0;
2574     sal_Int8 nCloseMode = ::ooo::vba::VbQueryClose::vbFormCode;
2575 
2576     Sequence< Any > aParams;
2577     aParams.realloc(2);
2578     aParams[0] <<= nCancel;
2579     aParams[1] <<= nCloseMode;
2580 
2581     triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_QueryClose") ), aParams);
2582 
2583     aParams[0] >>= nCancel;
2584     if (nCancel != 0)  // Basic returns -1 for "True"
2585     {
2586         return;
2587     }
2588 
2589     if ( m_xDialog.is() )
2590     {
2591         triggerTerminateEvent();
2592     }
2593     // Search method
2594     SbxVariable* pMeth = SbObjModule::Find( String( RTL_CONSTASCII_USTRINGPARAM( "UnloadObject" ) ), SbxCLASS_METHOD );
2595     if( pMeth )
2596     {
2597         OSL_TRACE("Attempting too run the UnloadObjectMethod");
2598         m_xDialog.clear(); //release ref to the uno object
2599         SbxValues aVals;
2600         bool bWaitForDispose = true; // assume dialog is showing
2601         if ( m_DialogListener.get() )
2602         {
2603             bWaitForDispose = m_DialogListener->isShowing();
2604             OSL_TRACE("Showing %d", bWaitForDispose );
2605         }
2606         pMeth->Get( aVals);
2607         if ( !bWaitForDispose )
2608         {
2609             // we've either already got a dispose or we'er never going to get one
2610             ResetApiObj();
2611         } // else wait for dispose
2612         OSL_TRACE("UnloadObject completed ( we hope )");
2613     }
2614 }
2615 //liuchen
2616 
2617 void registerComponentToBeDisposedForBasic( Reference< XComponent > xComponent, StarBASIC* pBasic );
2618 
2619 void SbUserFormModule::InitObject()
2620 {
2621     try
2622     {
2623         String aHook( RTL_CONSTASCII_USTRINGPARAM( "VBAGlobals" ) );
2624         SbUnoObject* pGlobs = (SbUnoObject*)GetParent()->Find( aHook, SbxCLASS_DONTCARE );
2625         if ( m_xModel.is() && pGlobs )
2626         {
2627             // broadcast INITIALIZE_USERFORM script event before the dialog is created
2628             Reference< script::vba::XVBACompatibility > xVBACompat( getVBACompatibility( m_xModel ), uno::UNO_SET_THROW );
2629             xVBACompat->broadcastVBAScriptEvent( script::vba::VBAScriptEventId::INITIALIZE_USERFORM, GetName() );
2630 
2631             uno::Reference< lang::XMultiServiceFactory > xVBAFactory( pGlobs->getUnoAny(), uno::UNO_QUERY_THROW );
2632             uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
2633             uno::Sequence< uno::Any > aArgs(1);
2634             aArgs[ 0 ] <<= m_xModel;
2635             rtl::OUString sDialogUrl( RTL_CONSTASCII_USTRINGPARAM("vnd.sun.star.script:" ) );
2636             rtl::OUString sProjectName( RTL_CONSTASCII_USTRINGPARAM("Standard") );
2637             if ( this->GetParent()->GetName().Len() )
2638                 sProjectName = this->GetParent()->GetName();
2639             sDialogUrl = sDialogUrl.concat( sProjectName ).concat( rtl::OUString( '.') ).concat( GetName() ).concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("?location=document") ) );
2640 
2641             uno::Reference< awt::XDialogProvider > xProvider( xFactory->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.awt.DialogProvider")), aArgs  ), uno::UNO_QUERY_THROW );
2642             m_xDialog = xProvider->createDialog( sDialogUrl );
2643 
2644             // create vba api object
2645             aArgs.realloc( 4 );
2646             aArgs[ 0 ] = uno::Any();
2647             aArgs[ 1 ] <<= m_xDialog;
2648             aArgs[ 2 ] <<= m_xModel;
2649             aArgs[ 3 ] <<= rtl::OUString( GetParent()->GetName() );
2650             pDocObject = new SbUnoObject( GetName(), uno::makeAny( xVBAFactory->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ooo.vba.msforms.UserForm")), aArgs  ) ) );
2651 
2652             uno::Reference< lang::XComponent > xComponent( m_xDialog, uno::UNO_QUERY_THROW );
2653 
2654             // the dialog must be disposed at the end!
2655             StarBASIC* pParentBasic = NULL;
2656             SbxObject* pCurObject = this;
2657             do
2658             {
2659                 SbxObject* pObjParent = pCurObject->GetParent();
2660                 pParentBasic = PTR_CAST( StarBASIC, pObjParent );
2661                 pCurObject = pObjParent;
2662             }
2663             while( pParentBasic == NULL && pCurObject != NULL );
2664 
2665             OSL_ASSERT( pParentBasic != NULL );
2666             registerComponentToBeDisposedForBasic( xComponent, pParentBasic );
2667 
2668             // if old listener object exists, remove it from dialog and document model
2669             if( m_DialogListener.is() )
2670                 m_DialogListener->removeListener();
2671             m_DialogListener.set( new FormObjEventListenerImpl( this, xComponent, m_xModel ) );
2672 
2673             triggerInitializeEvent();
2674         }
2675     }
2676     catch( uno::Exception& )
2677     {
2678     }
2679 
2680 }
2681 
2682 SbxVariable*
2683 SbUserFormModule::Find( const XubString& rName, SbxClassType t )
2684 {
2685     if ( !pDocObject && !GetSbData()->bRunInit && pINST )
2686         InitObject();
2687     return SbObjModule::Find( rName, t );
2688 }
2689 /////////////////////////////////////////////////////////////////////////
2690 
2691 SbProperty::SbProperty( const String& r, SbxDataType t, SbModule* p )
2692         : SbxProperty( r, t ), pMod( p )
2693 {
2694     bInvalid = sal_False;
2695 }
2696 
2697 SbProperty::~SbProperty()
2698 {}
2699 
2700 /////////////////////////////////////////////////////////////////////////
2701 
2702 SbProcedureProperty::~SbProcedureProperty()
2703 {}
2704 
2705