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