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