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