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