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