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