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