xref: /aoo41x/main/basic/source/classes/sbxmod.cxx (revision cdf0e10c)
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