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