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 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 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 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 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 224 DocObjectWrapper::~DocObjectWrapper() 225 { 226 } 227 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 250 DocObjectWrapper::getIntrospection( ) throw (RuntimeException) 251 { 252 return NULL; 253 } 254 255 Any SAL_CALL 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 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 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 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 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 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 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 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 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 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 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 { 484 AsyncQuitHandler() {} 485 AsyncQuitHandler( const AsyncQuitHandler&); 486 public: 487 static AsyncQuitHandler& instance() 488 { 489 static AsyncQuitHandler dInst; 490 return dInst; 491 } 492 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 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 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 > 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 553 sal_Bool SbModule::IsCompiled() const 554 { 555 return sal_Bool( pImage != 0 ); 556 } 557 558 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 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 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 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 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 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 674 SbIfaceMapperMethod::~SbIfaceMapperMethod() 675 { 676 } 677 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 704 void SbModule::Clear() 705 { 706 delete pImage; pImage = NULL; 707 if( pClassData ) 708 pClassData->clear(); 709 SbxObject::Clear(); 710 } 711 712 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 750 const ::rtl::OUString& SbModule::GetSource32() const 751 { 752 return aOUSource; 753 } 754 755 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 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 771 void SbModule::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, 772 const SfxHint& rHint, const TypeId& rHintType ) 773 { 774 const SbxHint* pHint = PTR_CAST(SbxHint,&rHint); 775 if( pHint ) 776 { 777 SbxVariable* pVar = pHint->GetVar(); 778 SbProperty* pProp = PTR_CAST(SbProperty,pVar); 779 SbMethod* pMeth = PTR_CAST(SbMethod,pVar); 780 if( pProp ) 781 { 782 if( pProp->GetModule() != this ) 783 SetError( SbxERR_BAD_ACTION ); 784 } 785 else if( pMeth ) 786 { 787 if( pHint->GetId() == SBX_HINT_DATAWANTED ) 788 { 789 if( pMeth->bInvalid && !Compile() ) 790 // Auto-Compile hat nicht geklappt! 791 StarBASIC::Error( SbERR_BAD_PROP_VALUE ); 792 else 793 { 794 // Aufruf eines Unterprogramms 795 SbModule* pOld = pMOD; 796 pMOD = this; 797 Run( (SbMethod*) pVar ); 798 pMOD = pOld; 799 } 800 } 801 } 802 else 803 { 804 // #i92642: Special handling for name property to avoid 805 // side effects when using name as variable implicitely 806 bool bForwardToSbxObject = true; 807 808 sal_uIntPtr nId = pHint->GetId(); 809 if( (nId == SBX_HINT_DATAWANTED || nId == SBX_HINT_DATACHANGED) && 810 pVar->GetName().EqualsIgnoreCaseAscii( "name" ) ) 811 bForwardToSbxObject = false; 812 813 if( bForwardToSbxObject ) 814 SbxObject::SFX_NOTIFY( rBC, rBCType, rHint, rHintType ); 815 } 816 } 817 } 818 819 // Das Setzen der Source macht das Image ungueltig 820 // und scant die Methoden-Definitionen neu ein 821 822 void SbModule::SetSource( const String& r ) 823 { 824 SetSource32( r ); 825 } 826 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 910 void SbModule::SetComment( const String& r ) 911 { 912 aComment = r; 913 SetModified( sal_True ); 914 } 915 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 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 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. 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 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 } 1009 sal_Bool SbModule::IsVBACompat() const 1010 { 1011 return mbVBACompat; 1012 } 1013 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 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 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 1308 void SbModule::AddVarName( const String& aName ) 1309 { 1310 // see if the name is added allready 1311 std::vector< String >::iterator it_end = mModuleVariableNames.end(); 1312 for ( std::vector< String >::iterator it = mModuleVariableNames.begin(); it != it_end; ++it ) 1313 { 1314 if ( aName == *it ) 1315 return; 1316 } 1317 mModuleVariableNames.push_back( aName ); 1318 } 1319 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 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 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 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) 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 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 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 1514 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 1519 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 1559 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 1571 size_t SbModule::GetBPCount() const 1572 { 1573 return pBreaks ? pBreaks->size() : 0; 1574 } 1575 1576 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 1584 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 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 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 1647 void SbModule::ClearAllBP() 1648 { 1649 delete pBreaks; 1650 pBreaks = NULL; 1651 } 1652 1653 void 1654 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 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 1721 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 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 1768 sal_Bool SbModule::StoreBinaryData( SvStream& rStrm ) 1769 { 1770 return StoreBinaryData( rStrm, 0 ); 1771 } 1772 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 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 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 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) 1930 SbJScriptModule::SbJScriptModule( const String& rName ) 1931 :SbModule( rName ) 1932 { 1933 } 1934 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 1951 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 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 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 1992 SbMethod::~SbMethod() 1993 { 1994 } 1995 1996 SbxArray* SbMethod::GetLocals() 1997 { 1998 if( pINST ) 1999 return pINST->GetLocals( this ); 2000 else 2001 return NULL; 2002 } 2003 2004 void SbMethod::ClearStatics() 2005 { 2006 refStatics = new SbxArray; 2007 2008 } 2009 SbxArray* SbMethod::GetStatics() 2010 { 2011 return refStatics; 2012 } 2013 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 2030 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 2042 void SbMethod::GetLineRange( sal_uInt16& l1, sal_uInt16& l2 ) 2043 { 2044 l1 = nLine1; l2 = nLine2; 2045 } 2046 2047 // Kann spaeter mal weg 2048 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. 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 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 2137 SbJScriptMethod::SbJScriptMethod( const String& r, SbxDataType t, SbModule* p ) 2138 : SbMethod( r, t, p ) 2139 { 2140 } 2141 2142 SbJScriptMethod::~SbJScriptMethod() 2143 {} 2144 2145 2146 ///////////////////////////////////////////////////////////////////////// 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 2159 SbObjModule::~SbObjModule() 2160 { 2161 } 2162 2163 void 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* 2183 SbObjModule::GetObject() 2184 { 2185 return pDocObject; 2186 } 2187 SbxVariable* 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 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: 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 2254 virtual ~FormObjEventListenerImpl() 2255 { 2256 removeListener(); 2257 } 2258 2259 sal_Bool isShowing() const { return mbShowing; } 2260 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 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 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 2339 virtual void SAL_CALL windowClosed( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) 2340 { 2341 mbOpened = sal_False; 2342 mbShowing = sal_False; 2343 } 2344 2345 virtual void SAL_CALL windowMinimized( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) 2346 { 2347 } 2348 2349 virtual void SAL_CALL windowNormalized( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) 2350 { 2351 } 2352 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 2366 virtual void SAL_CALL windowDeactivated( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) 2367 { 2368 if ( mpUserForm ) 2369 mpUserForm->triggerDeactivateEvent(); 2370 } 2371 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 2381 virtual void SAL_CALL windowMoved( const awt::WindowEvent& /*e*/ ) throw (uno::RuntimeException) 2382 { 2383 if ( mpUserForm ) 2384 mpUserForm->triggerLayoutEvent(); 2385 } 2386 2387 virtual void SAL_CALL windowShown( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) 2388 { 2389 } 2390 2391 virtual void SAL_CALL windowHidden( const lang::EventObject& /*e*/ ) throw (uno::RuntimeException) 2392 { 2393 } 2394 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 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 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 2425 SbUserFormModule::~SbUserFormModule() 2426 { 2427 } 2428 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 2439 void SbUserFormModule::triggerMethod( const String& aMethodToRun ) 2440 { 2441 Sequence< Any > aArguments; 2442 triggerMethod( aMethodToRun, aArguments ); 2443 } 2444 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 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 2493 void SbUserFormModule::triggerDeactivateEvent( void ) 2494 { 2495 OSL_TRACE("**** SbUserFormModule::triggerDeactivate"); 2496 triggerMethod( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Userform_Deactivate") ) ); 2497 } 2498 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 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 2517 void SbUserFormModule::triggerLayoutEvent( void ) 2518 { 2519 static String aMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Layout") ); 2520 triggerMethod( aMethodName ); 2521 } 2522 2523 void SbUserFormModule::triggerResizeEvent( void ) 2524 { 2525 static String aMethodName( RTL_CONSTASCII_USTRINGPARAM("Userform_Resize") ); 2526 triggerMethod( aMethodName ); 2527 } 2528 2529 SbUserFormModuleInstance* SbUserFormModule::CreateInstance() 2530 { 2531 SbUserFormModuleInstance* pInstance = new SbUserFormModuleInstance( this, GetName(), m_mInfo, IsVBACompat() ); 2532 return pInstance; 2533 } 2534 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 2542 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 2549 SbxVariable* SbUserFormModuleInstance::Find( const XubString& rName, SbxClassType t ) 2550 { 2551 SbxVariable* pVar = m_pParentModule->Find( rName, t ); 2552 return pVar; 2553 } 2554 2555 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 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 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* 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 2687 SbProperty::SbProperty( const String& r, SbxDataType t, SbModule* p ) 2688 : SbxProperty( r, t ), pMod( p ) 2689 { 2690 bInvalid = sal_False; 2691 } 2692 2693 SbProperty::~SbProperty() 2694 {} 2695 2696 ///////////////////////////////////////////////////////////////////////// 2697 2698 SbProcedureProperty::~SbProcedureProperty() 2699 {} 2700 2701