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