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