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