1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_basic.hxx" 30 31 #include <stdio.h> 32 33 #include "sb.hxx" 34 #include <tools/rcid.h> 35 #include <tools/config.hxx> 36 #include <tools/stream.hxx> 37 #ifndef __RSC //autogen 38 #include <tools/errinf.hxx> 39 #endif 40 #include <basic/sbx.hxx> 41 #include <tools/list.hxx> 42 #include <tools/shl.hxx> 43 #include <tools/rc.hxx> 44 #include <vcl/svapp.hxx> 45 #include <comphelper/processfactory.hxx> 46 #include "sbunoobj.hxx" 47 #include "sbjsmeth.hxx" 48 #include "sbjsmod.hxx" 49 #include "sbintern.hxx" 50 #include "disas.hxx" 51 #include "runtime.hxx" 52 #include <basic/sbuno.hxx> 53 #include <basic/sbobjmod.hxx> 54 #include "stdobj.hxx" 55 #include "filefmt.hxx" 56 #include "sb.hrc" 57 #include <basrid.hxx> 58 #include <vos/mutex.hxx> 59 #include <cppuhelper/implbase1.hxx> 60 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 61 #include <com/sun/star/util/XCloseBroadcaster.hpp> 62 #include <com/sun/star/util/XCloseListener.hpp> 63 #include "errobject.hxx" 64 #include <map> 65 #include <hash_map> 66 67 #include <com/sun/star/script/ModuleType.hpp> 68 #include <com/sun/star/script/ModuleInfo.hpp> 69 using namespace ::com::sun::star::script; 70 71 // #pragma SW_SEGMENT_CLASS( SBASIC, SBASIC_CODE ) 72 73 SV_IMPL_VARARR(SbTextPortions,SbTextPortion) 74 75 TYPEINIT1(StarBASIC,SbxObject) 76 77 #define RTLNAME "@SBRTL" 78 // i#i68894# 79 using namespace ::com::sun::star; 80 using com::sun::star::uno::Reference; 81 using com::sun::star::uno::Any; 82 using com::sun::star::uno::UNO_QUERY; 83 using com::sun::star::lang::XMultiServiceFactory; 84 85 const static String aThisComponent( RTL_CONSTASCII_USTRINGPARAM("ThisComponent") ); 86 const static String aVBAHook( RTL_CONSTASCII_USTRINGPARAM( "VBAGlobals" ) ); 87 88 // ============================================================================ 89 90 class DocBasicItem : public ::cppu::WeakImplHelper1< util::XCloseListener > 91 { 92 public: 93 explicit DocBasicItem( StarBASIC& rDocBasic ); 94 virtual ~DocBasicItem(); 95 96 inline const SbxObjectRef& getClassModules() const { return mxClassModules; } 97 inline bool isDocClosed() const { return mbDocClosed; } 98 99 void clearDependingVarsOnDelete( StarBASIC& rDeletedBasic ); 100 101 void startListening(); 102 void stopListening(); 103 104 virtual void SAL_CALL queryClosing( const lang::EventObject& rSource, sal_Bool bGetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException); 105 virtual void SAL_CALL notifyClosing( const lang::EventObject& rSource ) throw (uno::RuntimeException); 106 virtual void SAL_CALL disposing( const lang::EventObject& rSource ) throw (uno::RuntimeException); 107 108 private: 109 StarBASIC& mrDocBasic; 110 SbxObjectRef mxClassModules; 111 bool mbDocClosed; 112 bool mbDisposed; 113 }; 114 115 // ---------------------------------------------------------------------------- 116 117 DocBasicItem::DocBasicItem( StarBASIC& rDocBasic ) : 118 mrDocBasic( rDocBasic ), 119 mxClassModules( new SbxObject( String() ) ), 120 mbDocClosed( false ), 121 mbDisposed( false ) 122 { 123 } 124 125 DocBasicItem::~DocBasicItem() 126 { 127 stopListening(); 128 } 129 130 void DocBasicItem::clearDependingVarsOnDelete( StarBASIC& rDeletedBasic ) 131 { 132 mrDocBasic.implClearDependingVarsOnDelete( &rDeletedBasic ); 133 } 134 135 void DocBasicItem::startListening() 136 { 137 Any aThisComp; 138 mrDocBasic.GetUNOConstant( "ThisComponent", aThisComp ); 139 Reference< util::XCloseBroadcaster > xCloseBC( aThisComp, UNO_QUERY ); 140 mbDisposed = !xCloseBC.is(); 141 if( xCloseBC.is() ) 142 try { xCloseBC->addCloseListener( this ); } catch( uno::Exception& ) {} 143 } 144 145 void DocBasicItem::stopListening() 146 { 147 if( mbDisposed ) return; 148 mbDisposed = true; 149 Any aThisComp; 150 mrDocBasic.GetUNOConstant( "ThisComponent", aThisComp ); 151 Reference< util::XCloseBroadcaster > xCloseBC( aThisComp, UNO_QUERY ); 152 if( xCloseBC.is() ) 153 try { xCloseBC->removeCloseListener( this ); } catch( uno::Exception& ) {} 154 } 155 156 void SAL_CALL DocBasicItem::queryClosing( const lang::EventObject& /*rSource*/, sal_Bool /*bGetsOwnership*/ ) throw (util::CloseVetoException, uno::RuntimeException) 157 { 158 } 159 160 void SAL_CALL DocBasicItem::notifyClosing( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) 161 { 162 stopListening(); 163 mbDocClosed = true; 164 } 165 166 void SAL_CALL DocBasicItem::disposing( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) 167 { 168 stopListening(); 169 } 170 171 // ---------------------------------------------------------------------------- 172 173 namespace { 174 175 typedef ::rtl::Reference< DocBasicItem > DocBasicItemRef; 176 typedef std::map< const StarBASIC*, DocBasicItemRef > DocBasicItemMap; 177 static DocBasicItemMap GaDocBasicItems; 178 179 const DocBasicItem* lclFindDocBasicItem( const StarBASIC* pDocBasic ) 180 { 181 DocBasicItemMap::iterator it = GaDocBasicItems.find( pDocBasic ); 182 return (it != GaDocBasicItems.end()) ? it->second.get() : 0; 183 } 184 185 void lclInsertDocBasicItem( StarBASIC& rDocBasic ) 186 { 187 DocBasicItemRef& rxDocBasicItem = GaDocBasicItems[ &rDocBasic ]; 188 rxDocBasicItem.set( new DocBasicItem( rDocBasic ) ); 189 rxDocBasicItem->startListening(); 190 } 191 192 void lclRemoveDocBasicItem( StarBASIC& rDocBasic ) 193 { 194 DocBasicItemMap::iterator it = GaDocBasicItems.find( &rDocBasic ); 195 if( it != GaDocBasicItems.end() ) 196 { 197 it->second->stopListening(); 198 GaDocBasicItems.erase( it ); 199 } 200 DocBasicItemMap::iterator it_end = GaDocBasicItems.end(); 201 for( it = GaDocBasicItems.begin(); it != it_end; ++it ) 202 it->second->clearDependingVarsOnDelete( rDocBasic ); 203 } 204 205 StarBASIC* lclGetDocBasicForModule( SbModule* pModule ) 206 { 207 StarBASIC* pRetBasic = NULL; 208 SbxObject* pCurParent = pModule; 209 while( pCurParent->GetParent() != NULL ) 210 { 211 pCurParent = pCurParent->GetParent(); 212 StarBASIC* pDocBasic = PTR_CAST( StarBASIC, pCurParent ); 213 if( pDocBasic != NULL && pDocBasic->IsDocBasic() ) 214 { 215 pRetBasic = pDocBasic; 216 break; 217 } 218 } 219 return pRetBasic; 220 } 221 222 } // namespace 223 224 // ============================================================================ 225 226 SbxObject* StarBASIC::getVBAGlobals( ) 227 { 228 if ( !pVBAGlobals ) 229 { 230 Any aThisDoc; 231 if ( GetUNOConstant("ThisComponent", aThisDoc) ) 232 { 233 Reference< XMultiServiceFactory > xDocFac( aThisDoc, UNO_QUERY ); 234 if ( xDocFac.is() ) 235 { 236 try 237 { 238 xDocFac->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAGlobals" ) ) ); 239 } 240 catch( Exception& ) 241 { 242 // Ignore 243 } 244 } 245 } 246 pVBAGlobals = (SbUnoObject*)Find( aVBAHook , SbxCLASS_DONTCARE ); 247 } 248 return pVBAGlobals; 249 } 250 251 // i#i68894# 252 SbxVariable* StarBASIC::VBAFind( const String& rName, SbxClassType t ) 253 { 254 if( rName == aThisComponent ) 255 return NULL; 256 // rename to init globals 257 if ( getVBAGlobals( ) ) 258 return pVBAGlobals->Find( rName, t ); 259 return NULL; 260 261 } 262 // Create array for conversion SFX <-> VB error code 263 struct SFX_VB_ErrorItem 264 { 265 sal_uInt16 nErrorVB; 266 SbError nErrorSFX; 267 }; 268 269 const SFX_VB_ErrorItem __FAR_DATA SFX_VB_ErrorTab[] = 270 { 271 { 1, SbERR_BASIC_EXCEPTION }, // #87844 Map exception to error code 1 272 { 2, SbERR_SYNTAX }, 273 { 3, SbERR_NO_GOSUB }, 274 { 4, SbERR_REDO_FROM_START }, 275 { 5, SbERR_BAD_ARGUMENT }, 276 { 6, SbERR_MATH_OVERFLOW }, 277 { 7, SbERR_NO_MEMORY }, 278 { 8, SbERR_ALREADY_DIM }, 279 { 9, SbERR_OUT_OF_RANGE }, 280 { 10, SbERR_DUPLICATE_DEF }, 281 { 11, SbERR_ZERODIV }, 282 { 12, SbERR_VAR_UNDEFINED }, 283 { 13, SbERR_CONVERSION }, 284 { 14, SbERR_BAD_PARAMETER }, 285 { 18, SbERR_USER_ABORT }, 286 { 20, SbERR_BAD_RESUME }, 287 { 28, SbERR_STACK_OVERFLOW }, 288 { 35, SbERR_PROC_UNDEFINED }, 289 { 48, SbERR_BAD_DLL_LOAD }, 290 { 49, SbERR_BAD_DLL_CALL }, 291 { 51, SbERR_INTERNAL_ERROR }, 292 { 52, SbERR_BAD_CHANNEL }, 293 { 53, SbERR_FILE_NOT_FOUND }, 294 { 54, SbERR_BAD_FILE_MODE }, 295 { 55, SbERR_FILE_ALREADY_OPEN }, 296 { 57, SbERR_IO_ERROR }, 297 { 58, SbERR_FILE_EXISTS }, 298 { 59, SbERR_BAD_RECORD_LENGTH }, 299 { 61, SbERR_DISK_FULL }, 300 { 62, SbERR_READ_PAST_EOF }, 301 { 63, SbERR_BAD_RECORD_NUMBER }, 302 { 67, SbERR_TOO_MANY_FILES }, 303 { 68, SbERR_NO_DEVICE }, 304 { 70, SbERR_ACCESS_DENIED }, 305 { 71, SbERR_NOT_READY }, 306 { 73, SbERR_NOT_IMPLEMENTED }, 307 { 74, SbERR_DIFFERENT_DRIVE }, 308 { 75, SbERR_ACCESS_ERROR }, 309 { 76, SbERR_PATH_NOT_FOUND }, 310 { 91, SbERR_NO_OBJECT }, 311 { 93, SbERR_BAD_PATTERN }, 312 { 94, SBERR_IS_NULL }, 313 { 250, SbERR_DDE_ERROR }, 314 { 280, SbERR_DDE_WAITINGACK }, 315 { 281, SbERR_DDE_OUTOFCHANNELS }, 316 { 282, SbERR_DDE_NO_RESPONSE }, 317 { 283, SbERR_DDE_MULT_RESPONSES }, 318 { 284, SbERR_DDE_CHANNEL_LOCKED }, 319 { 285, SbERR_DDE_NOTPROCESSED }, 320 { 286, SbERR_DDE_TIMEOUT }, 321 { 287, SbERR_DDE_USER_INTERRUPT }, 322 { 288, SbERR_DDE_BUSY }, 323 { 289, SbERR_DDE_NO_DATA }, 324 { 290, SbERR_DDE_WRONG_DATA_FORMAT }, 325 { 291, SbERR_DDE_PARTNER_QUIT }, 326 { 292, SbERR_DDE_CONV_CLOSED }, 327 { 293, SbERR_DDE_NO_CHANNEL }, 328 { 294, SbERR_DDE_INVALID_LINK }, 329 { 295, SbERR_DDE_QUEUE_OVERFLOW }, 330 { 296, SbERR_DDE_LINK_ALREADY_EST }, 331 { 297, SbERR_DDE_LINK_INV_TOPIC }, 332 { 298, SbERR_DDE_DLL_NOT_FOUND }, 333 { 323, SbERR_CANNOT_LOAD }, 334 { 341, SbERR_BAD_INDEX }, 335 { 366, SbERR_NO_ACTIVE_OBJECT }, 336 { 380, SbERR_BAD_PROP_VALUE }, 337 { 382, SbERR_PROP_READONLY }, 338 { 394, SbERR_PROP_WRITEONLY }, 339 { 420, SbERR_INVALID_OBJECT }, 340 { 423, SbERR_NO_METHOD }, 341 { 424, SbERR_NEEDS_OBJECT }, 342 { 425, SbERR_INVALID_USAGE_OBJECT }, 343 { 430, SbERR_NO_OLE }, 344 { 438, SbERR_BAD_METHOD }, 345 { 440, SbERR_OLE_ERROR }, 346 { 445, SbERR_BAD_ACTION }, 347 { 446, SbERR_NO_NAMED_ARGS }, 348 { 447, SbERR_BAD_LOCALE }, 349 { 448, SbERR_NAMED_NOT_FOUND }, 350 { 449, SbERR_NOT_OPTIONAL }, 351 { 450, SbERR_WRONG_ARGS }, 352 { 451, SbERR_NOT_A_COLL }, 353 { 452, SbERR_BAD_ORDINAL }, 354 { 453, SbERR_DLLPROC_NOT_FOUND }, 355 { 460, SbERR_BAD_CLIPBD_FORMAT }, 356 { 951, SbERR_UNEXPECTED }, 357 { 952, SbERR_EXPECTED }, 358 { 953, SbERR_SYMBOL_EXPECTED }, 359 { 954, SbERR_VAR_EXPECTED }, 360 { 955, SbERR_LABEL_EXPECTED }, 361 { 956, SbERR_LVALUE_EXPECTED }, 362 { 957, SbERR_VAR_DEFINED }, 363 { 958, SbERR_PROC_DEFINED }, 364 { 959, SbERR_LABEL_DEFINED }, 365 { 960, SbERR_UNDEF_VAR }, 366 { 961, SbERR_UNDEF_ARRAY }, 367 { 962, SbERR_UNDEF_PROC }, 368 { 963, SbERR_UNDEF_LABEL }, 369 { 964, SbERR_UNDEF_TYPE }, 370 { 965, SbERR_BAD_EXIT }, 371 { 966, SbERR_BAD_BLOCK }, 372 { 967, SbERR_BAD_BRACKETS }, 373 { 968, SbERR_BAD_DECLARATION }, 374 { 969, SbERR_BAD_PARAMETERS }, 375 { 970, SbERR_BAD_CHAR_IN_NUMBER }, 376 { 971, SbERR_MUST_HAVE_DIMS }, 377 { 972, SbERR_NO_IF }, 378 { 973, SbERR_NOT_IN_SUBR }, 379 { 974, SbERR_NOT_IN_MAIN }, 380 { 975, SbERR_WRONG_DIMS }, 381 { 976, SbERR_BAD_OPTION }, 382 { 977, SbERR_CONSTANT_REDECLARED }, 383 { 978, SbERR_PROG_TOO_LARGE }, 384 { 979, SbERR_NO_STRINGS_ARRAYS }, 385 { 1000, SbERR_PROPERTY_NOT_FOUND }, 386 { 1001, SbERR_METHOD_NOT_FOUND }, 387 { 1002, SbERR_ARG_MISSING }, 388 { 1003, SbERR_BAD_NUMBER_OF_ARGS }, 389 { 1004, SbERR_METHOD_FAILED }, 390 { 1005, SbERR_SETPROP_FAILED }, 391 { 1006, SbERR_GETPROP_FAILED }, 392 { 1007, SbERR_BASIC_COMPAT }, 393 { 0xFFFF, 0xFFFFFFFFL } // End mark 394 }; 395 396 // The StarBASIC factory is a hack. When a SbModule is created, its pointer 397 // is saved and given to the following SbProperties/SbMethods. This restores 398 // the Modul-relationshop. But it works only when a modul is loaded. 399 // Can cause troubles with separately loaded properties! 400 401 SbxBase* SbiFactory::Create( sal_uInt16 nSbxId, sal_uInt32 nCreator ) 402 { 403 if( nCreator == SBXCR_SBX ) 404 { 405 String aEmpty; 406 switch( nSbxId ) 407 { 408 case SBXID_BASIC: 409 return new StarBASIC( NULL ); 410 case SBXID_BASICMOD: 411 return new SbModule( aEmpty ); 412 case SBXID_BASICPROP: 413 return new SbProperty( aEmpty, SbxVARIANT, NULL ); 414 case SBXID_BASICMETHOD: 415 return new SbMethod( aEmpty, SbxVARIANT, NULL ); 416 case SBXID_JSCRIPTMOD: 417 return new SbJScriptModule( aEmpty ); 418 case SBXID_JSCRIPTMETH: 419 return new SbJScriptMethod( aEmpty, SbxVARIANT, NULL ); 420 } 421 } 422 return NULL; 423 } 424 425 SbxObject* SbiFactory::CreateObject( const String& rClass ) 426 { 427 if( rClass.EqualsIgnoreCaseAscii( "StarBASIC" ) ) 428 return new StarBASIC( NULL ); 429 else 430 if( rClass.EqualsIgnoreCaseAscii( "StarBASICModule" ) ) 431 { 432 String aEmpty; 433 return new SbModule( aEmpty ); 434 } 435 else 436 if( rClass.EqualsIgnoreCaseAscii( "Collection" ) ) 437 { 438 String aCollectionName( RTL_CONSTASCII_USTRINGPARAM("Collection") ); 439 return new BasicCollection( aCollectionName ); 440 } 441 else 442 if( rClass.EqualsIgnoreCaseAscii( "FileSystemObject" ) ) 443 { 444 try 445 { 446 Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory(), UNO_SET_THROW ); 447 ::rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.FileSystemObject" ) ); 448 Reference< XInterface > xInterface( xFactory->createInstance( aServiceName ), UNO_SET_THROW ); 449 return new SbUnoObject( aServiceName, uno::makeAny( xInterface ) ); 450 } 451 catch( Exception& ) 452 {} 453 } 454 455 return NULL; 456 } 457 458 459 // Factory class to create OLE objects 460 class SbOLEFactory : public SbxFactory 461 { 462 public: 463 virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 = SBXCR_SBX ); 464 virtual SbxObject* CreateObject( const String& ); 465 }; 466 467 SbxBase* SbOLEFactory::Create( sal_uInt16, sal_uInt32 ) 468 { 469 // Not supported 470 return NULL; 471 } 472 473 SbUnoObject* createOLEObject_Impl( const String& aType ); // sbunoobj.cxx 474 475 SbxObject* SbOLEFactory::CreateObject( const String& rClassName ) 476 { 477 SbxObject* pRet = createOLEObject_Impl( rClassName ); 478 return pRet; 479 } 480 481 482 //======================================================================== 483 // SbFormFactory, show user forms by: dim as new <user form name> 484 485 class SbFormFactory : public SbxFactory 486 { 487 public: 488 virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 = SBXCR_SBX ); 489 virtual SbxObject* CreateObject( const String& ); 490 }; 491 492 SbxBase* SbFormFactory::Create( sal_uInt16, sal_uInt32 ) 493 { 494 // Not supported 495 return NULL; 496 } 497 498 SbxObject* SbFormFactory::CreateObject( const String& rClassName ) 499 { 500 if( SbModule* pMod = pMOD ) 501 { 502 if( SbxVariable* pVar = pMod->Find( rClassName, SbxCLASS_OBJECT ) ) 503 { 504 if( SbUserFormModule* pFormModule = PTR_CAST( SbUserFormModule, pVar->GetObject() ) ) 505 { 506 bool bInitState = pFormModule->getInitState(); 507 if( bInitState ) 508 { 509 // Not the first instantiate, reset 510 bool bTriggerTerminateEvent = false; 511 pFormModule->ResetApiObj( bTriggerTerminateEvent ); 512 pFormModule->setInitState( false ); 513 } 514 else 515 { 516 pFormModule->Load(); 517 } 518 return pFormModule->CreateInstance(); 519 } 520 } 521 } 522 return 0; 523 } 524 525 526 //======================================================================== 527 // SbTypeFactory 528 529 SbxObject* cloneTypeObjectImpl( const SbxObject& rTypeObj ) 530 { 531 SbxObject* pRet = new SbxObject( rTypeObj ); 532 pRet->PutObject( pRet ); 533 534 // Copy the properties, not only the reference to them 535 SbxArray* pProps = pRet->GetProperties(); 536 sal_uInt32 nCount = pProps->Count32(); 537 for( sal_uInt32 i = 0 ; i < nCount ; i++ ) 538 { 539 SbxVariable* pVar = pProps->Get32( i ); 540 SbxProperty* pProp = PTR_CAST( SbxProperty, pVar ); 541 if( pProp ) 542 { 543 SbxProperty* pNewProp = new SbxProperty( *pProp ); 544 SbxDataType eVarType = pVar->GetType(); 545 if( eVarType & SbxARRAY ) 546 { 547 SbxBase* pParObj = pVar->GetObject(); 548 SbxDimArray* pSource = PTR_CAST(SbxDimArray,pParObj); 549 SbxDimArray* pDest = new SbxDimArray( pVar->GetType() ); 550 sal_Int32 lb = 0; 551 sal_Int32 ub = 0; 552 553 pDest->setHasFixedSize( pSource->hasFixedSize() ); 554 if ( pSource->GetDims() && pSource->hasFixedSize() ) 555 { 556 for ( sal_Int32 j = 1 ; j <= pSource->GetDims(); ++j ) 557 { 558 pSource->GetDim32( (sal_Int32)j, lb, ub ); 559 pDest->AddDim32( lb, ub ); 560 } 561 } 562 else 563 pDest->unoAddDim( 0, -1 ); // variant array 564 565 sal_uInt16 nSavFlags = pVar->GetFlags(); 566 pNewProp->ResetFlag( SBX_FIXED ); 567 // need to reset the FIXED flag 568 // when calling PutObject ( because the type will not match Object ) 569 pNewProp->PutObject( pDest ); 570 pNewProp->SetFlags( nSavFlags ); 571 } 572 if( eVarType == SbxOBJECT ) 573 { 574 SbxBase* pObjBase = pVar->GetObject(); 575 SbxObject* pSrcObj = PTR_CAST(SbxObject,pObjBase); 576 SbxObject* pDestObj = NULL; 577 if( pSrcObj != NULL ) 578 pDestObj = cloneTypeObjectImpl( *pSrcObj ); 579 pNewProp->PutObject( pDestObj ); 580 } 581 pProps->PutDirect( pNewProp, i ); 582 } 583 } 584 return pRet; 585 } 586 587 // Factory class to create user defined objects (type command) 588 class SbTypeFactory : public SbxFactory 589 { 590 public: 591 virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 = SBXCR_SBX ); 592 virtual SbxObject* CreateObject( const String& ); 593 }; 594 595 SbxBase* SbTypeFactory::Create( sal_uInt16, sal_uInt32 ) 596 { 597 // Not supported 598 return NULL; 599 } 600 601 SbxObject* SbTypeFactory::CreateObject( const String& rClassName ) 602 { 603 SbxObject* pRet = NULL; 604 SbModule* pMod = pMOD; 605 if( pMod ) 606 { 607 const SbxObject* pObj = pMod->FindType( rClassName ); 608 if( pObj ) 609 pRet = cloneTypeObjectImpl( *pObj ); 610 } 611 return pRet; 612 } 613 614 SbxObject* createUserTypeImpl( const String& rClassName ) 615 { 616 SbxObject* pRetObj = pTYPEFAC->CreateObject( rClassName ); 617 return pRetObj; 618 } 619 620 621 TYPEINIT1(SbClassModuleObject,SbModule) 622 623 SbClassModuleObject::SbClassModuleObject( SbModule* pClassModule ) 624 : SbModule( pClassModule->GetName() ) 625 , mpClassModule( pClassModule ) 626 , mbInitializeEventDone( false ) 627 { 628 aOUSource = pClassModule->aOUSource; 629 aComment = pClassModule->aComment; 630 pImage = pClassModule->pImage; 631 pBreaks = pClassModule->pBreaks; 632 633 SetClassName( pClassModule->GetName() ); 634 635 // Allow search only internally 636 ResetFlag( SBX_GBLSEARCH ); 637 638 // Copy the methods from original class module 639 SbxArray* pClassMethods = pClassModule->GetMethods(); 640 sal_uInt32 nMethodCount = pClassMethods->Count32(); 641 sal_uInt32 i; 642 for( i = 0 ; i < nMethodCount ; i++ ) 643 { 644 SbxVariable* pVar = pClassMethods->Get32( i ); 645 646 // Exclude SbIfaceMapperMethod to copy them in a second step 647 SbIfaceMapperMethod* pIfaceMethod = PTR_CAST( SbIfaceMapperMethod, pVar ); 648 if( !pIfaceMethod ) 649 { 650 SbMethod* pMethod = PTR_CAST(SbMethod, pVar ); 651 if( pMethod ) 652 { 653 sal_uInt16 nFlags_ = pMethod->GetFlags(); 654 pMethod->SetFlag( SBX_NO_BROADCAST ); 655 SbMethod* pNewMethod = new SbMethod( *pMethod ); 656 pNewMethod->ResetFlag( SBX_NO_BROADCAST ); 657 pMethod->SetFlags( nFlags_ ); 658 pNewMethod->pMod = this; 659 pNewMethod->SetParent( this ); 660 pMethods->PutDirect( pNewMethod, i ); 661 StartListening( pNewMethod->GetBroadcaster(), sal_True ); 662 } 663 } 664 } 665 666 // Copy SbIfaceMapperMethod in a second step to ensure that 667 // the corresponding base methods have already been copied 668 for( i = 0 ; i < nMethodCount ; i++ ) 669 { 670 SbxVariable* pVar = pClassMethods->Get32( i ); 671 672 SbIfaceMapperMethod* pIfaceMethod = PTR_CAST( SbIfaceMapperMethod, pVar ); 673 if( pIfaceMethod ) 674 { 675 SbMethod* pImplMethod = pIfaceMethod->getImplMethod(); 676 if( !pImplMethod ) 677 { 678 DBG_ERROR( "No ImplMethod" ); 679 continue; 680 } 681 682 // Search for own copy of ImplMethod 683 String aImplMethodName = pImplMethod->GetName(); 684 SbxVariable* p = pMethods->Find( aImplMethodName, SbxCLASS_METHOD ); 685 SbMethod* pImplMethodCopy = p ? PTR_CAST(SbMethod,p) : NULL; 686 if( !pImplMethodCopy ) 687 { 688 DBG_ERROR( "Found no ImplMethod copy" ); 689 continue; 690 } 691 SbIfaceMapperMethod* pNewIfaceMethod = 692 new SbIfaceMapperMethod( pIfaceMethod->GetName(), pImplMethodCopy ); 693 pMethods->PutDirect( pNewIfaceMethod, i ); 694 } 695 } 696 697 // Copy the properties from original class module 698 SbxArray* pClassProps = pClassModule->GetProperties(); 699 sal_uInt32 nPropertyCount = pClassProps->Count32(); 700 for( i = 0 ; i < nPropertyCount ; i++ ) 701 { 702 SbxVariable* pVar = pClassProps->Get32( i ); 703 SbProcedureProperty* pProcedureProp = PTR_CAST( SbProcedureProperty, pVar ); 704 if( pProcedureProp ) 705 { 706 sal_uInt16 nFlags_ = pProcedureProp->GetFlags(); 707 pProcedureProp->SetFlag( SBX_NO_BROADCAST ); 708 SbProcedureProperty* pNewProp = new SbProcedureProperty 709 ( pProcedureProp->GetName(), pProcedureProp->GetType() ); 710 // ( pProcedureProp->GetName(), pProcedureProp->GetType(), this ); 711 pNewProp->SetFlags( nFlags_ ); // Copy flags 712 pNewProp->ResetFlag( SBX_NO_BROADCAST ); // except the Broadcast if it was set 713 pProcedureProp->SetFlags( nFlags_ ); 714 pProps->PutDirect( pNewProp, i ); 715 StartListening( pNewProp->GetBroadcaster(), sal_True ); 716 } 717 else 718 { 719 SbxProperty* pProp = PTR_CAST( SbxProperty, pVar ); 720 if( pProp ) 721 { 722 sal_uInt16 nFlags_ = pProp->GetFlags(); 723 pProp->SetFlag( SBX_NO_BROADCAST ); 724 SbxProperty* pNewProp = new SbxProperty( *pProp ); 725 726 // Special handling for modules instances and collections, they need 727 // to be instantiated, otherwise all refer to the same base object 728 SbxDataType eVarType = pProp->GetType(); 729 if( eVarType == SbxOBJECT ) 730 { 731 SbxBase* pObjBase = pProp->GetObject(); 732 SbxObject* pObj = PTR_CAST(SbxObject,pObjBase); 733 if( pObj != NULL ) 734 { 735 String aObjClass = pObj->GetClassName(); 736 737 SbClassModuleObject* pClassModuleObj = PTR_CAST(SbClassModuleObject,pObjBase); 738 if( pClassModuleObj != NULL ) 739 { 740 SbModule* pLclClassModule = pClassModuleObj->getClassModule(); 741 SbClassModuleObject* pNewObj = new SbClassModuleObject( pLclClassModule ); 742 pNewObj->SetName( pProp->GetName() ); 743 pNewObj->SetParent( pLclClassModule->pParent ); 744 pNewProp->PutObject( pNewObj ); 745 } 746 else if( aObjClass.EqualsIgnoreCaseAscii( "Collection" ) ) 747 { 748 String aCollectionName( RTL_CONSTASCII_USTRINGPARAM("Collection") ); 749 BasicCollection* pNewCollection = new BasicCollection( aCollectionName ); 750 pNewCollection->SetName( pProp->GetName() ); 751 pNewCollection->SetParent( pClassModule->pParent ); 752 pNewProp->PutObject( pNewCollection ); 753 } 754 } 755 } 756 757 pNewProp->ResetFlag( SBX_NO_BROADCAST ); 758 pNewProp->SetParent( this ); 759 pProps->PutDirect( pNewProp, i ); 760 pProp->SetFlags( nFlags_ ); 761 } 762 } 763 } 764 SetModuleType( ModuleType::CLASS ); 765 mbVBACompat = pClassModule->mbVBACompat; 766 } 767 768 SbClassModuleObject::~SbClassModuleObject() 769 { 770 // do not trigger termination event when document is already closed 771 if( StarBASIC::IsRunning() ) 772 if( StarBASIC* pDocBasic = lclGetDocBasicForModule( this ) ) 773 if( const DocBasicItem* pDocBasicItem = lclFindDocBasicItem( pDocBasic ) ) 774 if( !pDocBasicItem->isDocClosed() ) 775 triggerTerminateEvent(); 776 777 // Must be deleted by base class dtor because this data 778 // is not owned by the SbClassModuleObject object 779 pImage = NULL; 780 pBreaks = NULL; 781 } 782 783 void SbClassModuleObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType, 784 const SfxHint& rHint, const TypeId& rHintType ) 785 { 786 handleProcedureProperties( rBC, rHint ); 787 } 788 789 SbxVariable* SbClassModuleObject::Find( const XubString& rName, SbxClassType t ) 790 { 791 SbxVariable* pRes = SbxObject::Find( rName, t ); 792 if( pRes ) 793 { 794 triggerInitializeEvent(); 795 796 SbIfaceMapperMethod* pIfaceMapperMethod = PTR_CAST(SbIfaceMapperMethod,pRes); 797 if( pIfaceMapperMethod ) 798 { 799 pRes = pIfaceMapperMethod->getImplMethod(); 800 pRes->SetFlag( SBX_EXTFOUND ); 801 } 802 } 803 return pRes; 804 } 805 806 void SbClassModuleObject::triggerInitializeEvent( void ) 807 { 808 static String aInitMethodName( RTL_CONSTASCII_USTRINGPARAM("Class_Initialize") ); 809 810 if( mbInitializeEventDone ) 811 return; 812 813 mbInitializeEventDone = true; 814 815 // Search method 816 SbxVariable* pMeth = SbxObject::Find( aInitMethodName, SbxCLASS_METHOD ); 817 if( pMeth ) 818 { 819 SbxValues aVals; 820 pMeth->Get( aVals ); 821 } 822 } 823 824 void SbClassModuleObject::triggerTerminateEvent( void ) 825 { 826 static String aTermMethodName( RTL_CONSTASCII_USTRINGPARAM("Class_Terminate") ); 827 828 if( !mbInitializeEventDone || GetSbData()->bRunInit ) 829 return; 830 831 // Search method 832 SbxVariable* pMeth = SbxObject::Find( aTermMethodName, SbxCLASS_METHOD ); 833 if( pMeth ) 834 { 835 SbxValues aVals; 836 pMeth->Get( aVals ); 837 } 838 } 839 840 841 SbClassData::SbClassData( void ) 842 { 843 mxIfaces = new SbxArray(); 844 } 845 846 void SbClassData::clear( void ) 847 { 848 mxIfaces->Clear(); 849 maRequiredTypes.clear(); 850 } 851 852 SbClassFactory::SbClassFactory( void ) 853 { 854 String aDummyName; 855 xClassModules = new SbxObject( aDummyName ); 856 } 857 858 SbClassFactory::~SbClassFactory() 859 {} 860 861 void SbClassFactory::AddClassModule( SbModule* pClassModule ) 862 { 863 SbxObjectRef xToUseClassModules = xClassModules; 864 865 if( StarBASIC* pDocBasic = lclGetDocBasicForModule( pClassModule ) ) 866 if( const DocBasicItem* pDocBasicItem = lclFindDocBasicItem( pDocBasic ) ) 867 xToUseClassModules = pDocBasicItem->getClassModules(); 868 869 SbxObject* pParent = pClassModule->GetParent(); 870 xToUseClassModules->Insert( pClassModule ); 871 pClassModule->SetParent( pParent ); 872 } 873 874 void SbClassFactory::RemoveClassModule( SbModule* pClassModule ) 875 { 876 xClassModules->Remove( pClassModule ); 877 } 878 879 SbxBase* SbClassFactory::Create( sal_uInt16, sal_uInt32 ) 880 { 881 // Not supported 882 return NULL; 883 } 884 885 SbxObject* SbClassFactory::CreateObject( const String& rClassName ) 886 { 887 SbxObjectRef xToUseClassModules = xClassModules; 888 889 if( SbModule* pMod = pMOD ) 890 if( StarBASIC* pDocBasic = lclGetDocBasicForModule( pMod ) ) 891 if( const DocBasicItem* pDocBasicItem = lclFindDocBasicItem( pDocBasic ) ) 892 xToUseClassModules = pDocBasicItem->getClassModules(); 893 894 SbxVariable* pVar = xToUseClassModules->Find( rClassName, SbxCLASS_OBJECT ); 895 SbxObject* pRet = NULL; 896 if( pVar ) 897 { 898 SbModule* pVarMod = (SbModule*)pVar; 899 pRet = new SbClassModuleObject( pVarMod ); 900 } 901 return pRet; 902 } 903 904 SbModule* SbClassFactory::FindClass( const String& rClassName ) 905 { 906 SbxVariable* pVar = xClassModules->Find( rClassName, SbxCLASS_DONTCARE ); 907 SbModule* pMod = pVar ? (SbModule*)pVar : NULL; 908 return pMod; 909 } 910 911 StarBASIC::StarBASIC( StarBASIC* p, sal_Bool bIsDocBasic ) 912 : SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("StarBASIC") ) ), bDocBasic( bIsDocBasic ) 913 { 914 SetParent( p ); 915 pLibInfo = NULL; 916 bNoRtl = bBreak = sal_False; 917 bVBAEnabled = sal_False; 918 pModules = new SbxArray; 919 920 if( !GetSbData()->nInst++ ) 921 { 922 pSBFAC = new SbiFactory; 923 AddFactory( pSBFAC ); 924 pTYPEFAC = new SbTypeFactory; 925 AddFactory( pTYPEFAC ); 926 pCLASSFAC = new SbClassFactory; 927 AddFactory( pCLASSFAC ); 928 pOLEFAC = new SbOLEFactory; 929 AddFactory( pOLEFAC ); 930 pFORMFAC = new SbFormFactory; 931 AddFactory( pFORMFAC ); 932 pUNOFAC = new SbUnoFactory; 933 AddFactory( pUNOFAC ); 934 } 935 pRtl = new SbiStdObject( String( RTL_CONSTASCII_USTRINGPARAM(RTLNAME) ), this ); 936 // Search via StarBasic is always global 937 SetFlag( SBX_GBLSEARCH ); 938 pVBAGlobals = NULL; 939 bQuit = sal_False; 940 941 if( bDocBasic ) 942 lclInsertDocBasicItem( *this ); 943 } 944 945 // #51727 Override SetModified so that the modified state 946 // is not given to the parent 947 void StarBASIC::SetModified( sal_Bool b ) 948 { 949 SbxBase::SetModified( b ); 950 } 951 952 extern void lcl_closeTraceFile(); 953 954 StarBASIC::~StarBASIC() 955 { 956 #ifdef DBG_TRACE_BASIC 957 lcl_closeTraceFile(); 958 #endif 959 960 // Needs to be first action as it can trigger events 961 disposeComVariablesForBasic( this ); 962 963 if( !--GetSbData()->nInst ) 964 { 965 RemoveFactory( pSBFAC ); 966 delete pSBFAC; pSBFAC = NULL; 967 RemoveFactory( pUNOFAC ); 968 delete pUNOFAC; pUNOFAC = NULL; 969 RemoveFactory( pTYPEFAC ); 970 delete pTYPEFAC; pTYPEFAC = NULL; 971 RemoveFactory( pCLASSFAC ); 972 delete pCLASSFAC; pCLASSFAC = NULL; 973 RemoveFactory( pOLEFAC ); 974 delete pOLEFAC; pOLEFAC = NULL; 975 RemoveFactory( pFORMFAC ); 976 delete pFORMFAC; pFORMFAC = NULL; 977 978 #ifdef DBG_UTIL 979 // There is no need to clean SbiData at program end, 980 // but we dislike MLK's at Purify 981 // TODO: Where else??? 982 SbiGlobals** pp = (SbiGlobals**) ::GetAppData( SHL_SBC ); 983 SbiGlobals* p = *pp; 984 if( p ) 985 { 986 delete p; 987 *pp = 0; 988 } 989 #endif 990 } 991 else if( bDocBasic ) 992 { 993 SbxError eOld = SbxBase::GetError(); 994 995 lclRemoveDocBasicItem( *this ); 996 997 SbxBase::ResetError(); 998 if( eOld != SbxERR_OK ) 999 SbxBase::SetError( eOld ); 1000 } 1001 1002 // #100326 Set Parent NULL in registered listeners 1003 if( xUnoListeners.Is() ) 1004 { 1005 sal_uInt16 uCount = xUnoListeners->Count(); 1006 for( sal_uInt16 i = 0 ; i < uCount ; i++ ) 1007 { 1008 SbxVariable* pListenerObj = xUnoListeners->Get( i ); 1009 pListenerObj->SetParent( NULL ); 1010 } 1011 xUnoListeners = NULL; 1012 } 1013 1014 clearUnoMethodsForBasic( this ); 1015 } 1016 1017 // Override new() operator, so that everyone can create a new instance 1018 void* StarBASIC::operator new( size_t n ) 1019 { 1020 if( n < sizeof( StarBASIC ) ) 1021 { 1022 // DBG_ASSERT( sal_False, "Warnung: inkompatibler BASIC-Stand!" ); 1023 n = sizeof( StarBASIC ); 1024 } 1025 return ::operator new( n ); 1026 } 1027 1028 void StarBASIC::operator delete( void* p ) 1029 { 1030 ::operator delete( p ); 1031 } 1032 1033 void StarBASIC::implClearDependingVarsOnDelete( StarBASIC* pDeletedBasic ) 1034 { 1035 if( this != pDeletedBasic ) 1036 { 1037 for( sal_uInt16 i = 0; i < pModules->Count(); i++ ) 1038 { 1039 SbModule* p = (SbModule*)pModules->Get( i ); 1040 p->ClearVarsDependingOnDeletedBasic( pDeletedBasic ); 1041 } 1042 } 1043 1044 for( sal_uInt16 nObj = 0; nObj < pObjs->Count(); nObj++ ) 1045 { 1046 SbxVariable* pVar = pObjs->Get( nObj ); 1047 StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar); 1048 if( pBasic && pBasic != pDeletedBasic ) 1049 pBasic->implClearDependingVarsOnDelete( pDeletedBasic ); 1050 } 1051 } 1052 1053 1054 /************************************************************************** 1055 * 1056 * Creation/Managment of modules 1057 * 1058 **************************************************************************/ 1059 1060 SbModule* StarBASIC::MakeModule( const String& rName, const String& rSrc ) 1061 { 1062 return MakeModule32( rName, rSrc ); 1063 } 1064 1065 SbModule* StarBASIC::MakeModule32( const String& rName, const ::rtl::OUString& rSrc ) 1066 { 1067 ModuleInfo mInfo; 1068 mInfo.ModuleType = ModuleType::NORMAL; 1069 return MakeModule32( rName, mInfo, rSrc ); 1070 } 1071 SbModule* StarBASIC::MakeModule32( const String& rName, const ModuleInfo& mInfo, const rtl::OUString& rSrc ) 1072 { 1073 1074 OSL_TRACE("create module %s type mInfo %d", rtl::OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr(), mInfo.ModuleType ); 1075 SbModule* p = NULL; 1076 switch ( mInfo.ModuleType ) 1077 { 1078 case ModuleType::DOCUMENT: 1079 // In theory we should be able to create Object modules 1080 // in ordinary basic ( in vba mode thought these are create 1081 // by the application/basic and not by the user ) 1082 p = new SbObjModule( rName, mInfo, isVBAEnabled() ); 1083 break; 1084 case ModuleType::CLASS: 1085 p = new SbModule( rName, isVBAEnabled() ); 1086 p->SetModuleType( ModuleType::CLASS ); 1087 break; 1088 case ModuleType::FORM: 1089 p = new SbUserFormModule( rName, mInfo, isVBAEnabled() ); 1090 break; 1091 default: 1092 p = new SbModule( rName, isVBAEnabled() ); 1093 1094 } 1095 p->SetSource32( rSrc ); 1096 p->SetParent( this ); 1097 pModules->Insert( p, pModules->Count() ); 1098 SetModified( sal_True ); 1099 return p; 1100 } 1101 1102 void StarBASIC::Insert( SbxVariable* pVar ) 1103 { 1104 if( pVar->IsA( TYPE(SbModule) ) ) 1105 { 1106 pModules->Insert( pVar, pModules->Count() ); 1107 pVar->SetParent( this ); 1108 StartListening( pVar->GetBroadcaster(), sal_True ); 1109 } 1110 else 1111 { 1112 sal_Bool bWasModified = IsModified(); 1113 SbxObject::Insert( pVar ); 1114 if( !bWasModified && pVar->IsSet( SBX_DONTSTORE ) ) 1115 SetModified( sal_False ); 1116 } 1117 } 1118 1119 void StarBASIC::Remove( SbxVariable* pVar ) 1120 { 1121 if( pVar->IsA( TYPE(SbModule) ) ) 1122 { 1123 // #87540 Can be last reference! 1124 SbxVariableRef xVar = pVar; 1125 pModules->Remove( pVar ); 1126 pVar->SetParent( 0 ); 1127 EndListening( pVar->GetBroadcaster() ); 1128 } 1129 else 1130 SbxObject::Remove( pVar ); 1131 } 1132 1133 sal_Bool StarBASIC::Compile( SbModule* pMod ) 1134 { 1135 return pMod ? pMod->Compile() : sal_False; 1136 } 1137 1138 sal_Bool StarBASIC::Disassemble( SbModule* pMod, String& rText ) 1139 { 1140 rText.Erase(); 1141 if( pMod ) 1142 pMod->Disassemble( rText ); 1143 return sal_Bool( rText.Len() != 0 ); 1144 } 1145 1146 void StarBASIC::Clear() 1147 { 1148 while( pModules->Count() ) 1149 pModules->Remove( pModules->Count() - 1 ); 1150 } 1151 1152 SbModule* StarBASIC::FindModule( const String& rName ) 1153 { 1154 for( sal_uInt16 i = 0; i < pModules->Count(); i++ ) 1155 { 1156 SbModule* p = (SbModule*) pModules->Get( i ); 1157 if( p->GetName().EqualsIgnoreCaseAscii( rName ) ) 1158 return p; 1159 } 1160 return NULL; 1161 } 1162 1163 1164 struct ClassModuleRunInitItem 1165 { 1166 SbModule* m_pModule; 1167 bool m_bProcessing; 1168 bool m_bRunInitDone; 1169 //ModuleVector m_vModulesDependingOnThisModule; 1170 1171 ClassModuleRunInitItem( void ) 1172 : m_pModule( NULL ) 1173 , m_bProcessing( false ) 1174 , m_bRunInitDone( false ) 1175 {} 1176 ClassModuleRunInitItem( SbModule* pModule ) 1177 : m_pModule( pModule ) 1178 , m_bProcessing( false ) 1179 , m_bRunInitDone( false ) 1180 {} 1181 }; 1182 1183 // Derive from has_map type instead of typedef 1184 // to allow forward declaration in sbmod.hxx 1185 class ModuleInitDependencyMap : public 1186 std::hash_map< ::rtl::OUString, ClassModuleRunInitItem, 1187 ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > 1188 {}; 1189 1190 void SbModule::implProcessModuleRunInit( ModuleInitDependencyMap& rMap, ClassModuleRunInitItem& rItem ) 1191 { 1192 rItem.m_bProcessing = true; 1193 1194 //bool bAnyDependencies = true; 1195 SbModule* pModule = rItem.m_pModule; 1196 if( pModule->pClassData != NULL ) 1197 { 1198 StringVector& rReqTypes = pModule->pClassData->maRequiredTypes; 1199 if( rReqTypes.size() > 0 ) 1200 { 1201 for( StringVector::iterator it = rReqTypes.begin() ; it != rReqTypes.end() ; ++it ) 1202 { 1203 String& rStr = *it; 1204 1205 // Is required type a class module? 1206 ModuleInitDependencyMap::iterator itFind = rMap.find( rStr ); 1207 if( itFind != rMap.end() ) 1208 { 1209 ClassModuleRunInitItem& rParentItem = itFind->second; 1210 if( rParentItem.m_bProcessing ) 1211 { 1212 // TODO: raise error? 1213 DBG_ERROR( "Cyclic module dependency detected" ); 1214 continue; 1215 } 1216 1217 if( !rParentItem.m_bRunInitDone ) 1218 implProcessModuleRunInit( rMap, rParentItem ); 1219 } 1220 } 1221 } 1222 } 1223 1224 pModule->RunInit(); 1225 rItem.m_bRunInitDone = true; 1226 rItem.m_bProcessing = false; 1227 } 1228 1229 // Run Init-Code of all modules (including inserted libraries) 1230 void StarBASIC::InitAllModules( StarBASIC* pBasicNotToInit ) 1231 { 1232 ::vos::OGuard guard( Application::GetSolarMutex() ); 1233 1234 // Init own modules 1235 for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ ) 1236 { 1237 SbModule* pModule = (SbModule*)pModules->Get( nMod ); 1238 if( !pModule->IsCompiled() ) 1239 pModule->Compile(); 1240 } 1241 // compile modules first then RunInit ( otherwise there is 1242 // can be order dependency, e.g. classmodule A has a member 1243 // of of type classmodule B and classmodule B hasn't been compiled yet ) 1244 1245 // Consider required types to init in right order. Class modules 1246 // that are required by other modules have to be initialized first. 1247 ModuleInitDependencyMap aMIDMap; 1248 for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ ) 1249 { 1250 SbModule* pModule = (SbModule*)pModules->Get( nMod ); 1251 String aModuleName = pModule->GetName(); 1252 if( pModule->isProxyModule() ) 1253 aMIDMap[aModuleName] = ClassModuleRunInitItem( pModule ); 1254 } 1255 1256 ModuleInitDependencyMap::iterator it; 1257 for( it = aMIDMap.begin() ; it != aMIDMap.end(); ++it ) 1258 { 1259 ClassModuleRunInitItem& rItem = it->second; 1260 SbModule::implProcessModuleRunInit( aMIDMap, rItem ); 1261 } 1262 1263 // Call RunInit on standard modules 1264 for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ ) 1265 { 1266 SbModule* pModule = (SbModule*)pModules->Get( nMod ); 1267 if( !pModule->isProxyModule() ) 1268 pModule->RunInit(); 1269 } 1270 1271 // Check all objects if they are BASIC, 1272 // if yes initialize 1273 for ( sal_uInt16 nObj = 0; nObj < pObjs->Count(); nObj++ ) 1274 { 1275 SbxVariable* pVar = pObjs->Get( nObj ); 1276 StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar); 1277 if( pBasic && pBasic != pBasicNotToInit ) 1278 pBasic->InitAllModules(); 1279 } 1280 } 1281 1282 // #88329 Put modules back to not initialised state to 1283 // force reinitialisation at next start 1284 void StarBASIC::DeInitAllModules( void ) 1285 { 1286 // Deinit own modules 1287 for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ ) 1288 { 1289 SbModule* pModule = (SbModule*)pModules->Get( nMod ); 1290 if( pModule->pImage && !pModule->isProxyModule() && !pModule->ISA(SbObjModule) ) 1291 pModule->pImage->bInit = false; 1292 } 1293 1294 for ( sal_uInt16 nObj = 0; nObj < pObjs->Count(); nObj++ ) 1295 { 1296 SbxVariable* pVar = pObjs->Get( nObj ); 1297 StarBASIC* pBasic = PTR_CAST(StarBASIC,pVar); 1298 if( pBasic ) 1299 pBasic->DeInitAllModules(); 1300 } 1301 } 1302 1303 // #43011 For TestTool, to delete global vars 1304 void StarBASIC::ClearGlobalVars( void ) 1305 { 1306 SbxArrayRef xProps( GetProperties() ); 1307 sal_uInt16 nPropCount = xProps->Count(); 1308 for ( sal_uInt16 nProp = 0 ; nProp < nPropCount ; ++nProp ) 1309 { 1310 SbxBase* pVar = xProps->Get( nProp ); 1311 pVar->Clear(); 1312 } 1313 SetModified( sal_True ); 1314 } 1315 1316 // This implementation at first searches within the runtime library, 1317 // then it looks for an element within one module. This moudle can be 1318 // a public var or an entrypoint. If it is not found and we look for a 1319 // method and a module with the given name is found the search continues 1320 // for entrypoint "Main". 1321 // If this fails again a conventional search over objects is performend. 1322 SbxVariable* StarBASIC::Find( const String& rName, SbxClassType t ) 1323 { 1324 static String aMainStr( RTL_CONSTASCII_USTRINGPARAM("Main") ); 1325 1326 SbxVariable* pRes = NULL; 1327 SbModule* pNamed = NULL; 1328 // "Extended" search in Runtime Lib 1329 // but only if SbiRuntime has not set the flag 1330 if( !bNoRtl ) 1331 { 1332 if( t == SbxCLASS_DONTCARE || t == SbxCLASS_OBJECT ) 1333 { 1334 if( rName.EqualsIgnoreCaseAscii( RTLNAME ) ) 1335 pRes = pRtl; 1336 } 1337 if( !pRes ) 1338 pRes = ((SbiStdObject*) (SbxObject*) pRtl)->Find( rName, t ); 1339 if( pRes ) 1340 pRes->SetFlag( SBX_EXTFOUND ); 1341 } 1342 // Search module 1343 if( !pRes ) 1344 for( sal_uInt16 i = 0; i < pModules->Count(); i++ ) 1345 { 1346 SbModule* p = (SbModule*) pModules->Get( i ); 1347 if( p->IsVisible() ) 1348 { 1349 // Remember modul fpr Main() call 1350 // or is the name equal?!? 1351 if( p->GetName().EqualsIgnoreCaseAscii( rName ) ) 1352 { 1353 if( t == SbxCLASS_OBJECT || t == SbxCLASS_DONTCARE ) 1354 { 1355 pRes = p; break; 1356 } 1357 pNamed = p; 1358 } 1359 // Only variables qualified by the Module Name e.g. Sheet1.foo 1360 // should work for Documant && Class type Modules 1361 sal_Int32 nType = p->GetModuleType(); 1362 if ( nType == ModuleType::DOCUMENT || nType == ModuleType::FORM ) 1363 continue; 1364 1365 // otherwise check if the element is available 1366 // unset GBLSEARCH-Flag (due to Rekursion) 1367 sal_uInt16 nGblFlag = p->GetFlags() & SBX_GBLSEARCH; 1368 p->ResetFlag( SBX_GBLSEARCH ); 1369 pRes = p->Find( rName, t ); 1370 p->SetFlag( nGblFlag ); 1371 if( pRes ) 1372 break; 1373 } 1374 } 1375 if( !pRes && pNamed && ( t == SbxCLASS_METHOD || t == SbxCLASS_DONTCARE ) && 1376 !pNamed->GetName().EqualsIgnoreCaseAscii( aMainStr ) ) 1377 pRes = pNamed->Find( aMainStr, SbxCLASS_METHOD ); 1378 if( !pRes ) 1379 pRes = SbxObject::Find( rName, t ); 1380 return pRes; 1381 } 1382 1383 sal_Bool StarBASIC::Call( const String& rName, SbxArray* pParam ) 1384 { 1385 sal_Bool bRes = SbxObject::Call( rName, pParam ); 1386 if( !bRes ) 1387 { 1388 SbxError eErr = SbxBase::GetError(); 1389 SbxBase::ResetError(); 1390 if( eErr != SbxERR_OK ) 1391 RTError( (SbError)eErr, 0, 0, 0 ); 1392 } 1393 return bRes; 1394 } 1395 1396 // Find method via name (e.g. query via BASIC IDE) 1397 SbxBase* StarBASIC::FindSBXInCurrentScope( const String& rName ) 1398 { 1399 if( !pINST ) 1400 return NULL; 1401 if( !pINST->pRun ) 1402 return NULL; 1403 return pINST->pRun->FindElementExtern( rName ); 1404 } 1405 1406 // Preserve old interface 1407 SbxVariable* StarBASIC::FindVarInCurrentScopy 1408 ( const String& rName, sal_uInt16& rStatus ) 1409 { 1410 rStatus = 1; // Presumption: nothing found 1411 SbxVariable* pVar = NULL; 1412 SbxBase* pSbx = FindSBXInCurrentScope( rName ); 1413 if( pSbx ) 1414 { 1415 if( !pSbx->ISA(SbxMethod) && !pSbx->ISA(SbxObject) ) 1416 pVar = PTR_CAST(SbxVariable,pSbx); 1417 } 1418 if( pVar ) 1419 rStatus = 0; // We found something 1420 return pVar; 1421 } 1422 1423 void StarBASIC::QuitAndExitApplication() 1424 { 1425 Stop(); 1426 bQuit = sal_True; 1427 } 1428 1429 void StarBASIC::Stop() 1430 { 1431 SbiInstance* p = pINST; 1432 while( p ) 1433 { 1434 p->Stop(); 1435 p = p->pNext; 1436 } 1437 } 1438 1439 sal_Bool StarBASIC::IsRunning() 1440 { 1441 return sal_Bool( pINST != NULL ); 1442 } 1443 1444 /************************************************************************** 1445 * 1446 * Object factories and others 1447 * 1448 **************************************************************************/ 1449 1450 // Activation of an object. There is no need to access active objects 1451 // with name via BASIC. If NULL is given, everything is activated. 1452 void StarBASIC::ActivateObject( const String* pName, sal_Bool bActivate ) 1453 { 1454 if( pName ) 1455 { 1456 SbxObject* p = (SbxObject*) SbxObject::Find( *pName, SbxCLASS_OBJECT ); 1457 if( p ) 1458 { 1459 if( bActivate ) 1460 p->SetFlag( SBX_EXTSEARCH ); 1461 else 1462 p->ResetFlag( SBX_EXTSEARCH ); 1463 } 1464 } 1465 else 1466 { 1467 for( sal_uInt16 i = 0; i < GetObjects()->Count(); i++ ) 1468 { 1469 SbxObject* p = (SbxObject*) GetObjects()->Get( i ); 1470 if( bActivate ) 1471 p->SetFlag( SBX_EXTSEARCH ); 1472 else 1473 p->ResetFlag( SBX_EXTSEARCH ); 1474 } 1475 } 1476 } 1477 1478 /************************************************************************** 1479 * 1480 * Debugging and error handling 1481 * 1482 **************************************************************************/ 1483 1484 SbMethod* StarBASIC::GetActiveMethod( sal_uInt16 nLevel ) 1485 { 1486 if( pINST ) 1487 return pINST->GetCaller( nLevel ); 1488 else 1489 return NULL; 1490 } 1491 1492 SbModule* StarBASIC::GetActiveModule() 1493 { 1494 if( pINST && !IsCompilerError() ) 1495 return pINST->GetActiveModule(); 1496 else 1497 return pCMOD; 1498 } 1499 1500 sal_uInt16 StarBASIC::BreakPoint( sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 ) 1501 { 1502 SetErrorData( 0, l, c1, c2 ); 1503 bBreak = sal_True; 1504 if( GetSbData()->aBreakHdl.IsSet() ) 1505 return (sal_uInt16) GetSbData()->aBreakHdl.Call( this ); 1506 else 1507 return BreakHdl(); 1508 } 1509 1510 sal_uInt16 StarBASIC::StepPoint( sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 ) 1511 { 1512 SetErrorData( 0, l, c1, c2 ); 1513 bBreak = sal_False; 1514 if( GetSbData()->aBreakHdl.IsSet() ) 1515 return (sal_uInt16) GetSbData()->aBreakHdl.Call( this ); 1516 else 1517 return BreakHdl(); 1518 } 1519 1520 sal_uInt16 __EXPORT StarBASIC::BreakHdl() 1521 { 1522 return (sal_uInt16) ( aBreakHdl.IsSet() 1523 ? aBreakHdl.Call( this ) : SbDEBUG_CONTINUE ); 1524 } 1525 1526 // Calls for error handler and break handler 1527 sal_uInt16 StarBASIC::GetLine() { return GetSbData()->nLine; } 1528 sal_uInt16 StarBASIC::GetCol1() { return GetSbData()->nCol1; } 1529 sal_uInt16 StarBASIC::GetCol2() { return GetSbData()->nCol2; } 1530 1531 // Specific to error handler 1532 SbError StarBASIC::GetErrorCode() { return GetSbData()->nCode; } 1533 const String& StarBASIC::GetErrorText() { return GetSbData()->aErrMsg; } 1534 sal_Bool StarBASIC::IsCompilerError() { return GetSbData()->bCompiler; } 1535 void StarBASIC::SetGlobalLanguageMode( SbLanguageMode eLanguageMode ) 1536 { 1537 GetSbData()->eLanguageMode = eLanguageMode; 1538 } 1539 SbLanguageMode StarBASIC::GetGlobalLanguageMode() 1540 { 1541 return GetSbData()->eLanguageMode; 1542 } 1543 // Local settings 1544 SbLanguageMode StarBASIC::GetLanguageMode() 1545 { 1546 // Use global settings? 1547 if( eLanguageMode == SB_LANG_GLOBAL ) 1548 return GetSbData()->eLanguageMode; 1549 else 1550 return eLanguageMode; 1551 } 1552 1553 // AB: 29.3.96 1554 // Das Mapping zwischen alten und neuen Fehlercodes erfolgt, indem die Tabelle 1555 // SFX_VB_ErrorTab[] durchsucht wird. Dies ist zwar nicht besonders performant, 1556 // verbraucht aber viel weniger Speicher als entsprechende switch-Bloecke. 1557 // Die Umrechnung von Fehlercodes muss nicht schnell sein, daher auch keine 1558 // binaere Suche bei VB-Error -> SFX-Error. 1559 1560 // Neue Fehler-Codes auf alte, Sbx-Kompatible zurueckmappen 1561 sal_uInt16 StarBASIC::GetVBErrorCode( SbError nError ) 1562 { 1563 sal_uInt16 nRet = 0; 1564 1565 if( SbiRuntime::isVBAEnabled() ) 1566 { 1567 switch( nError ) 1568 { 1569 case SbERR_BASIC_ARRAY_FIX: 1570 return 10; 1571 case SbERR_BASIC_STRING_OVERFLOW: 1572 return 14; 1573 case SbERR_BASIC_EXPR_TOO_COMPLEX: 1574 return 16; 1575 case SbERR_BASIC_OPER_NOT_PERFORM: 1576 return 17; 1577 case SbERR_BASIC_TOO_MANY_DLL: 1578 return 47; 1579 case SbERR_BASIC_LOOP_NOT_INIT: 1580 return 92; 1581 default: 1582 nRet = 0; 1583 } 1584 } 1585 1586 // Suchschleife 1587 const SFX_VB_ErrorItem* pErrItem; 1588 sal_uInt16 nIndex = 0; 1589 do 1590 { 1591 pErrItem = SFX_VB_ErrorTab + nIndex; 1592 if( pErrItem->nErrorSFX == nError ) 1593 { 1594 nRet = pErrItem->nErrorVB; 1595 break; 1596 } 1597 nIndex++; 1598 } 1599 while( pErrItem->nErrorVB != 0xFFFF ); // bis End-Marke 1600 return nRet; 1601 } 1602 1603 SbError StarBASIC::GetSfxFromVBError( sal_uInt16 nError ) 1604 { 1605 SbError nRet = 0L; 1606 1607 if( SbiRuntime::isVBAEnabled() ) 1608 { 1609 switch( nError ) 1610 { 1611 case 1: 1612 case 2: 1613 case 4: 1614 case 8: 1615 case 12: 1616 case 73: 1617 return 0L; 1618 case 10: 1619 return SbERR_BASIC_ARRAY_FIX; 1620 case 14: 1621 return SbERR_BASIC_STRING_OVERFLOW; 1622 case 16: 1623 return SbERR_BASIC_EXPR_TOO_COMPLEX; 1624 case 17: 1625 return SbERR_BASIC_OPER_NOT_PERFORM; 1626 case 47: 1627 return SbERR_BASIC_TOO_MANY_DLL; 1628 case 92: 1629 return SbERR_BASIC_LOOP_NOT_INIT; 1630 default: 1631 nRet = 0L; 1632 } 1633 } 1634 const SFX_VB_ErrorItem* pErrItem; 1635 sal_uInt16 nIndex = 0; 1636 do 1637 { 1638 pErrItem = SFX_VB_ErrorTab + nIndex; 1639 if( pErrItem->nErrorVB == nError ) 1640 { 1641 nRet = pErrItem->nErrorSFX; 1642 break; 1643 } 1644 else if( pErrItem->nErrorVB > nError ) 1645 break; // kann nicht mehr gefunden werden 1646 1647 nIndex++; 1648 } 1649 while( pErrItem->nErrorVB != 0xFFFF ); // bis End-Marke 1650 return nRet; 1651 } 1652 1653 // Error- / Break-Daten setzen 1654 void StarBASIC::SetErrorData 1655 ( SbError nCode, sal_uInt16 nLine, sal_uInt16 nCol1, sal_uInt16 nCol2 ) 1656 { 1657 SbiGlobals& aGlobals = *GetSbData(); 1658 aGlobals.nCode = nCode; 1659 aGlobals.nLine = nLine; 1660 aGlobals.nCol1 = nCol1; 1661 aGlobals.nCol2 = nCol2; 1662 } 1663 1664 //---------------------------------------------------------------- 1665 // Hilfsklasse zum Zugriff auf String SubResourcen einer Resource. 1666 // Quelle: sfx2\source\doc\docfile.cxx (TLX) 1667 struct BasicStringList_Impl : private Resource 1668 { 1669 ResId aResId; 1670 1671 BasicStringList_Impl( ResId& rErrIdP, sal_uInt16 nId) 1672 : Resource( rErrIdP ),aResId(nId, *rErrIdP.GetResMgr() ){} 1673 ~BasicStringList_Impl() { FreeResource(); } 1674 1675 String GetString(){ return String( aResId ); } 1676 sal_Bool IsErrorTextAvailable( void ) 1677 { return IsAvailableRes(aResId.SetRT(RSC_STRING)); } 1678 }; 1679 //---------------------------------------------------------------- 1680 1681 // #60175 Flag, das bei Basic-Fehlern das Anziehen der SFX-Resourcen verhindert 1682 static sal_Bool bStaticSuppressSfxResource = sal_False; 1683 1684 void StarBASIC::StaticSuppressSfxResource( sal_Bool bSuppress ) 1685 { 1686 bStaticSuppressSfxResource = bSuppress; 1687 } 1688 1689 // Hack for #83750, use bStaticSuppressSfxResource as setup flag 1690 sal_Bool runsInSetup( void ) 1691 { 1692 return bStaticSuppressSfxResource; 1693 } 1694 1695 1696 void StarBASIC::MakeErrorText( SbError nId, const String& aMsg ) 1697 { 1698 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 1699 1700 if( bStaticSuppressSfxResource ) 1701 { 1702 GetSbData()->aErrMsg = String( RTL_CONSTASCII_USTRINGPARAM("No resource: Error message not available") ); 1703 return; 1704 } 1705 1706 sal_uInt16 nOldID = GetVBErrorCode( nId ); 1707 1708 // Hilfsklasse instanzieren 1709 BasResId aId( RID_BASIC_START ); 1710 BasicStringList_Impl aMyStringList( aId, sal_uInt16(nId & ERRCODE_RES_MASK) ); 1711 1712 if( aMyStringList.IsErrorTextAvailable() ) 1713 { 1714 // Merge Message mit Zusatztext 1715 String aMsg1 = aMyStringList.GetString(); 1716 // Argument-Platzhalter durch %s ersetzen 1717 String aSrgStr( RTL_CONSTASCII_USTRINGPARAM("$(ARG1)") ); 1718 sal_uInt16 nResult = aMsg1.Search( aSrgStr ); 1719 1720 if( nResult != STRING_NOTFOUND ) 1721 { 1722 aMsg1.Erase( nResult, aSrgStr.Len() ); 1723 aMsg1.Insert( aMsg, nResult ); 1724 } 1725 GetSbData()->aErrMsg = aMsg1; 1726 } 1727 else if( nOldID != 0 ) 1728 { 1729 String aStdMsg( RTL_CONSTASCII_USTRINGPARAM("Fehler ") ); 1730 aStdMsg += String::CreateFromInt32( nOldID); 1731 aStdMsg += String( RTL_CONSTASCII_USTRINGPARAM(": Kein Fehlertext verfuegbar!") ); 1732 GetSbData()->aErrMsg = aStdMsg; 1733 } 1734 else 1735 GetSbData()->aErrMsg = String::EmptyString(); 1736 1737 } 1738 1739 sal_Bool StarBASIC::CError 1740 ( SbError code, const String& rMsg, sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 ) 1741 { 1742 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 1743 1744 // Compiler-Fehler waehrend der Laufzeit -> Programm anhalten 1745 if( IsRunning() ) 1746 { 1747 // #109018 Check if running Basic is affected 1748 StarBASIC* pStartedBasic = pINST->GetBasic(); 1749 if( pStartedBasic != this ) 1750 return sal_False; 1751 1752 Stop(); 1753 } 1754 1755 // Flag setzen, damit GlobalRunInit den Fehler mitbekommt 1756 GetSbData()->bGlobalInitErr = sal_True; 1757 1758 // Fehlertext basteln 1759 MakeErrorText( code, rMsg ); 1760 1761 // Umsetzung des Codes fuer String-Transport in SFX-Error 1762 if( rMsg.Len() ) 1763 code = (sal_uIntPtr)*new StringErrorInfo( code, String(rMsg) ); 1764 1765 SetErrorData( code, l, c1, c2 ); 1766 GetSbData()->bCompiler = sal_True; 1767 sal_Bool bRet; 1768 if( GetSbData()->aErrHdl.IsSet() ) 1769 bRet = (sal_Bool) GetSbData()->aErrHdl.Call( this ); 1770 else 1771 bRet = ErrorHdl(); 1772 GetSbData()->bCompiler = sal_False; // nur sal_True fuer Error-Handler 1773 return bRet; 1774 } 1775 1776 sal_Bool StarBASIC::RTError 1777 ( SbError code, sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 ) 1778 { 1779 return RTError( code, String(), l, c1, c2 ); 1780 } 1781 1782 sal_Bool StarBASIC::RTError( SbError code, const String& rMsg, sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 ) 1783 { 1784 vos::OGuard aSolarGuard( Application::GetSolarMutex() ); 1785 1786 SbError c = code; 1787 if( (c & ERRCODE_CLASS_MASK) == ERRCODE_CLASS_COMPILER ) 1788 c = 0; 1789 MakeErrorText( c, rMsg ); 1790 1791 // Umsetzung des Codes fuer String-Transport in SFX-Error 1792 if( rMsg.Len() ) 1793 { 1794 // very confusing, even though MakeErrorText sets up the error text 1795 // seems that this is not used ( if rMsg already has content ) 1796 // In the case of VBA MakeErrorText also formats the error to be alittle more 1797 // like vba ( adds an error number etc ) 1798 if ( SbiRuntime::isVBAEnabled() && ( code == SbERR_BASIC_COMPAT ) ) 1799 { 1800 String aTmp = '\''; 1801 aTmp += String::CreateFromInt32( SbxErrObject::getUnoErrObject()->getNumber() ); 1802 aTmp += String( RTL_CONSTASCII_USTRINGPARAM("\'\n") ); 1803 aTmp += GetSbData()->aErrMsg.Len() ? GetSbData()->aErrMsg : rMsg; 1804 code = (sal_uIntPtr)*new StringErrorInfo( code, aTmp ); 1805 } 1806 else 1807 code = (sal_uIntPtr)*new StringErrorInfo( code, String(rMsg) ); 1808 } 1809 1810 SetErrorData( code, l, c1, c2 ); 1811 if( GetSbData()->aErrHdl.IsSet() ) 1812 return (sal_Bool) GetSbData()->aErrHdl.Call( this ); 1813 else 1814 return ErrorHdl(); 1815 } 1816 1817 void StarBASIC::Error( SbError n ) 1818 { 1819 Error( n, String() ); 1820 } 1821 1822 void StarBASIC::Error( SbError n, const String& rMsg ) 1823 { 1824 if( pINST ) 1825 pINST->Error( n, rMsg ); 1826 } 1827 1828 void StarBASIC::FatalError( SbError n ) 1829 { 1830 if( pINST ) 1831 pINST->FatalError( n ); 1832 } 1833 1834 void StarBASIC::FatalError( SbError _errCode, const String& _details ) 1835 { 1836 if( pINST ) 1837 pINST->FatalError( _errCode, _details ); 1838 } 1839 1840 SbError StarBASIC::GetErrBasic() 1841 { 1842 if( pINST ) 1843 return pINST->GetErr(); 1844 else 1845 return 0; 1846 } 1847 1848 // #66536 Zusatz-Message fuer RTL-Funktion Error zugreifbar machen 1849 String StarBASIC::GetErrorMsg() 1850 { 1851 if( pINST ) 1852 return pINST->GetErrorMsg(); 1853 else 1854 return String(); 1855 } 1856 1857 sal_uInt16 StarBASIC::GetErl() 1858 { 1859 if( pINST ) 1860 return pINST->GetErl(); 1861 else 1862 return 0; 1863 } 1864 1865 sal_Bool __EXPORT StarBASIC::ErrorHdl() 1866 { 1867 return (sal_Bool) ( aErrorHdl.IsSet() 1868 ? aErrorHdl.Call( this ) : sal_False ); 1869 } 1870 1871 Link StarBASIC::GetGlobalErrorHdl() 1872 { 1873 return GetSbData()->aErrHdl; 1874 } 1875 1876 void StarBASIC::SetGlobalErrorHdl( const Link& rLink ) 1877 { 1878 GetSbData()->aErrHdl = rLink; 1879 } 1880 1881 1882 Link StarBASIC::GetGlobalBreakHdl() 1883 { 1884 return GetSbData()->aBreakHdl; 1885 } 1886 1887 void StarBASIC::SetGlobalBreakHdl( const Link& rLink ) 1888 { 1889 GetSbData()->aBreakHdl = rLink; 1890 } 1891 1892 SbxArrayRef StarBASIC::getUnoListeners( void ) 1893 { 1894 if( !xUnoListeners.Is() ) 1895 xUnoListeners = new SbxArray(); 1896 return xUnoListeners; 1897 } 1898 1899 1900 /************************************************************************** 1901 * 1902 * Laden und Speichern 1903 * 1904 **************************************************************************/ 1905 1906 sal_Bool StarBASIC::LoadData( SvStream& r, sal_uInt16 nVer ) 1907 { 1908 if( !SbxObject::LoadData( r, nVer ) ) 1909 return sal_False; 1910 1911 // #95459 Delete dialogs, otherwise endless recursion 1912 // in SbxVarable::GetType() if dialogs are accessed 1913 sal_uInt16 nObjCount = pObjs->Count(); 1914 SbxVariable** ppDeleteTab = new SbxVariable*[ nObjCount ]; 1915 sal_uInt16 nObj; 1916 1917 for( nObj = 0 ; nObj < nObjCount ; nObj++ ) 1918 { 1919 SbxVariable* pVar = pObjs->Get( nObj ); 1920 StarBASIC* pBasic = PTR_CAST( StarBASIC, pVar ); 1921 ppDeleteTab[nObj] = pBasic ? NULL : pVar; 1922 } 1923 for( nObj = 0 ; nObj < nObjCount ; nObj++ ) 1924 { 1925 SbxVariable* pVar = ppDeleteTab[nObj]; 1926 if( pVar ) 1927 pObjs->Remove( pVar ); 1928 } 1929 delete[] ppDeleteTab; 1930 1931 sal_uInt16 nMod; 1932 pModules->Clear(); 1933 r >> nMod; 1934 for( sal_uInt16 i = 0; i < nMod; i++ ) 1935 { 1936 SbModule* pMod = (SbModule*) SbxBase::Load( r ); 1937 if( !pMod ) 1938 return sal_False; 1939 else if( pMod->ISA(SbJScriptModule) ) 1940 { 1941 // Ref zuweisen, damit pMod deleted wird 1942 SbModuleRef xRef = pMod; 1943 } 1944 else 1945 { 1946 pMod->SetParent( this ); 1947 pModules->Put( pMod, i ); 1948 } 1949 } 1950 // HACK fuer SFX-Mist! 1951 SbxVariable* p = Find( String( RTL_CONSTASCII_USTRINGPARAM("FALSE") ), SbxCLASS_PROPERTY ); 1952 if( p ) 1953 Remove( p ); 1954 p = Find( String( RTL_CONSTASCII_USTRINGPARAM("TRUE") ), SbxCLASS_PROPERTY ); 1955 if( p ) 1956 Remove( p ); 1957 // Ende des Hacks! 1958 // Suche ueber StarBASIC ist immer global 1959 DBG_ASSERT( IsSet( SBX_GBLSEARCH ), "Basic ohne GBLSEARCH geladen" ); 1960 SetFlag( SBX_GBLSEARCH ); 1961 return sal_True; 1962 } 1963 1964 sal_Bool StarBASIC::StoreData( SvStream& r ) const 1965 { 1966 if( !SbxObject::StoreData( r ) ) 1967 return sal_False; 1968 r << (sal_uInt16) pModules->Count(); 1969 for( sal_uInt16 i = 0; i < pModules->Count(); i++ ) 1970 { 1971 SbModule* p = (SbModule*) pModules->Get( i ); 1972 if( !p->Store( r ) ) 1973 return sal_False; 1974 } 1975 return sal_True; 1976 } 1977 1978 sal_Bool StarBASIC::LoadOldModules( SvStream& ) 1979 { 1980 return sal_False; 1981 } 1982 1983 bool StarBASIC::GetUNOConstant( const sal_Char* _pAsciiName, ::com::sun::star::uno::Any& aOut ) 1984 { 1985 bool bRes = false; 1986 ::rtl::OUString sVarName( ::rtl::OUString::createFromAscii( _pAsciiName ) ); 1987 SbUnoObject* pGlobs = dynamic_cast<SbUnoObject*>( Find( sVarName, SbxCLASS_DONTCARE ) ); 1988 if ( pGlobs ) 1989 { 1990 aOut = pGlobs->getUnoAny(); 1991 bRes = true; 1992 } 1993 return bRes; 1994 } 1995 1996 Reference< frame::XModel > StarBASIC::GetModelFromBasic( SbxObject* pBasic ) 1997 { 1998 OSL_PRECOND( pBasic != NULL, "getModelFromBasic: illegal call!" ); 1999 if ( !pBasic ) 2000 return NULL; 2001 2002 // look for the ThisComponent variable, first in the parent (which 2003 // might be the document's Basic), then in the parent's parent (which might be 2004 // the application Basic) 2005 const ::rtl::OUString sThisComponent( RTL_CONSTASCII_USTRINGPARAM( "ThisComponent" ) ); 2006 SbxVariable* pThisComponent = NULL; 2007 2008 SbxObject* pLookup = pBasic->GetParent(); 2009 while ( pLookup && !pThisComponent ) 2010 { 2011 pThisComponent = pLookup->Find( sThisComponent, SbxCLASS_OBJECT ); 2012 pLookup = pLookup->GetParent(); 2013 } 2014 if ( !pThisComponent ) 2015 { 2016 OSL_TRACE("Failed to get ThisComponent"); 2017 // the application Basic, at the latest, should have this variable 2018 return NULL; 2019 } 2020 2021 Any aThisComponentAny( sbxToUnoValue( pThisComponent ) ); 2022 Reference< frame::XModel > xModel( aThisComponentAny, UNO_QUERY ); 2023 if ( !xModel.is() ) 2024 { 2025 // it's no XModel. Okay, ThisComponent nowadays is allowed to be a controller. 2026 Reference< frame::XController > xController( aThisComponentAny, UNO_QUERY ); 2027 if ( xController.is() ) 2028 xModel = xController->getModel(); 2029 } 2030 2031 if ( !xModel.is() ) 2032 return NULL; 2033 2034 #if OSL_DEBUG_LEVEL > 0 2035 OSL_TRACE("Have model ThisComponent points to url %s", 2036 ::rtl::OUStringToOString( xModel->getURL(), 2037 RTL_TEXTENCODING_ASCII_US ).pData->buffer ); 2038 #endif 2039 2040 return xModel; 2041 } 2042 2043 2044 //======================================================================== 2045 // #118116 Implementation Collection object 2046 2047 TYPEINIT1(BasicCollection,SbxObject) 2048 2049 static const char pCountStr[] = "Count"; 2050 static const char pAddStr[] = "Add"; 2051 static const char pItemStr[] = "Item"; 2052 static const char pRemoveStr[] = "Remove"; 2053 static sal_uInt16 nCountHash = 0, nAddHash, nItemHash, nRemoveHash; 2054 2055 SbxInfoRef BasicCollection::xAddInfo = NULL; 2056 SbxInfoRef BasicCollection::xItemInfo = NULL; 2057 2058 BasicCollection::BasicCollection( const XubString& rClass ) 2059 : SbxObject( rClass ) 2060 { 2061 if( !nCountHash ) 2062 { 2063 nCountHash = MakeHashCode( String::CreateFromAscii( pCountStr ) ); 2064 nAddHash = MakeHashCode( String::CreateFromAscii( pAddStr ) ); 2065 nItemHash = MakeHashCode( String::CreateFromAscii( pItemStr ) ); 2066 nRemoveHash = MakeHashCode( String::CreateFromAscii( pRemoveStr ) ); 2067 } 2068 Initialize(); 2069 2070 } 2071 2072 BasicCollection::~BasicCollection() 2073 {} 2074 2075 void BasicCollection::Clear() 2076 { 2077 SbxObject::Clear(); 2078 Initialize(); 2079 } 2080 2081 void BasicCollection::Initialize() 2082 { 2083 xItemArray = new SbxArray(); 2084 SetType( SbxOBJECT ); 2085 SetFlag( SBX_FIXED ); 2086 ResetFlag( SBX_WRITE ); 2087 SbxVariable* p; 2088 p = Make( String::CreateFromAscii( pCountStr ), SbxCLASS_PROPERTY, SbxINTEGER ); 2089 p->ResetFlag( SBX_WRITE ); 2090 p->SetFlag( SBX_DONTSTORE ); 2091 p = Make( String::CreateFromAscii( pAddStr ), SbxCLASS_METHOD, SbxEMPTY ); 2092 p->SetFlag( SBX_DONTSTORE ); 2093 p = Make( String::CreateFromAscii( pItemStr ), SbxCLASS_METHOD, SbxVARIANT ); 2094 p->SetFlag( SBX_DONTSTORE ); 2095 p = Make( String::CreateFromAscii( pRemoveStr ), SbxCLASS_METHOD, SbxEMPTY ); 2096 p->SetFlag( SBX_DONTSTORE ); 2097 if ( !xAddInfo.Is() ) 2098 { 2099 xAddInfo = new SbxInfo; 2100 xAddInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("Item") ), SbxVARIANT, SBX_READ ); 2101 xAddInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("Key") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL ); 2102 xAddInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("Before") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL ); 2103 xAddInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("After") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL ); 2104 } 2105 if ( !xItemInfo.Is() ) 2106 { 2107 xItemInfo = new SbxInfo; 2108 xItemInfo->AddParam( String( RTL_CONSTASCII_USTRINGPARAM("Index") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL); 2109 } 2110 } 2111 2112 SbxVariable* BasicCollection::Find( const XubString& rName, SbxClassType t ) 2113 { 2114 SbxVariable* pFind = SbxObject::Find( rName, t ); 2115 return pFind; 2116 } 2117 2118 void BasicCollection::SFX_NOTIFY( SfxBroadcaster& rCst, const TypeId& rId1, 2119 const SfxHint& rHint, const TypeId& rId2 ) 2120 { 2121 const SbxHint* p = PTR_CAST(SbxHint,&rHint); 2122 if( p ) 2123 { 2124 sal_uIntPtr nId = p->GetId(); 2125 sal_Bool bRead = sal_Bool( nId == SBX_HINT_DATAWANTED ); 2126 sal_Bool bWrite = sal_Bool( nId == SBX_HINT_DATACHANGED ); 2127 sal_Bool bRequestInfo = sal_Bool( nId == SBX_HINT_INFOWANTED ); 2128 SbxVariable* pVar = p->GetVar(); 2129 SbxArray* pArg = pVar->GetParameters(); 2130 XubString aVarName( pVar->GetName() ); 2131 if( bRead || bWrite ) 2132 { 2133 if( pVar->GetHashCode() == nCountHash 2134 && aVarName.EqualsIgnoreCaseAscii( pCountStr ) ) 2135 pVar->PutLong( xItemArray->Count32() ); 2136 else if( pVar->GetHashCode() == nAddHash 2137 && aVarName.EqualsIgnoreCaseAscii( pAddStr ) ) 2138 CollAdd( pArg ); 2139 else if( pVar->GetHashCode() == nItemHash 2140 && aVarName.EqualsIgnoreCaseAscii( pItemStr ) ) 2141 CollItem( pArg ); 2142 else if( pVar->GetHashCode() == nRemoveHash 2143 && aVarName.EqualsIgnoreCaseAscii( pRemoveStr ) ) 2144 CollRemove( pArg ); 2145 else 2146 SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 ); 2147 return; 2148 } 2149 else if ( bRequestInfo ) 2150 { 2151 if( pVar->GetHashCode() == nAddHash 2152 && aVarName.EqualsIgnoreCaseAscii( pAddStr ) ) 2153 pVar->SetInfo( xAddInfo ); 2154 else if( pVar->GetHashCode() == nItemHash 2155 && aVarName.EqualsIgnoreCaseAscii( pItemStr ) ) 2156 pVar->SetInfo( xItemInfo ); 2157 } 2158 } 2159 SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 ); 2160 } 2161 2162 sal_Int32 BasicCollection::implGetIndex( SbxVariable* pIndexVar ) 2163 { 2164 sal_Int32 nIndex = -1; 2165 if( pIndexVar->GetType() == SbxSTRING ) 2166 nIndex = implGetIndexForName( pIndexVar->GetString() ); 2167 else 2168 nIndex = pIndexVar->GetLong() - 1; 2169 return nIndex; 2170 } 2171 2172 sal_Int32 BasicCollection::implGetIndexForName( const String& rName ) 2173 { 2174 sal_Int32 nIndex = -1; 2175 sal_Int32 nCount = xItemArray->Count32(); 2176 sal_Int32 nNameHash = MakeHashCode( rName ); 2177 for( sal_Int32 i = 0 ; i < nCount ; i++ ) 2178 { 2179 SbxVariable* pVar = xItemArray->Get32( i ); 2180 if( pVar->GetHashCode() == nNameHash && 2181 pVar->GetName().EqualsIgnoreCaseAscii( rName ) ) 2182 { 2183 nIndex = i; 2184 break; 2185 } 2186 } 2187 return nIndex; 2188 } 2189 2190 void BasicCollection::CollAdd( SbxArray* pPar_ ) 2191 { 2192 sal_uInt16 nCount = pPar_->Count(); 2193 if( nCount < 2 || nCount > 5 ) 2194 { 2195 SetError( SbxERR_WRONG_ARGS ); 2196 return; 2197 } 2198 2199 SbxVariable* pItem = pPar_->Get(1); 2200 if( pItem ) 2201 { 2202 int nNextIndex; 2203 if( nCount < 4 ) 2204 { 2205 nNextIndex = xItemArray->Count(); 2206 } 2207 else 2208 { 2209 SbxVariable* pBefore = pPar_->Get(3); 2210 if( nCount == 5 ) 2211 { 2212 if( !( pBefore->IsErr() || ( pBefore->GetType() == SbxEMPTY ) ) ) 2213 { 2214 SetError( SbERR_BAD_ARGUMENT ); 2215 return; 2216 } 2217 SbxVariable* pAfter = pPar_->Get(4); 2218 sal_Int32 nAfterIndex = implGetIndex( pAfter ); 2219 if( nAfterIndex == -1 ) 2220 { 2221 SetError( SbERR_BAD_ARGUMENT ); 2222 return; 2223 } 2224 nNextIndex = nAfterIndex + 1; 2225 } 2226 else // if( nCount == 4 ) 2227 { 2228 sal_Int32 nBeforeIndex = implGetIndex( pBefore ); 2229 if( nBeforeIndex == -1 ) 2230 { 2231 SetError( SbERR_BAD_ARGUMENT ); 2232 return; 2233 } 2234 nNextIndex = nBeforeIndex; 2235 } 2236 } 2237 2238 SbxVariableRef pNewItem = new SbxVariable( *pItem ); 2239 if( nCount >= 3 ) 2240 { 2241 SbxVariable* pKey = pPar_->Get(2); 2242 if( !( pKey->IsErr() || ( pKey->GetType() == SbxEMPTY ) ) ) 2243 { 2244 if( pKey->GetType() != SbxSTRING ) 2245 { 2246 SetError( SbERR_BAD_ARGUMENT ); 2247 return; 2248 } 2249 String aKey = pKey->GetString(); 2250 if( implGetIndexForName( aKey ) != -1 ) 2251 { 2252 SetError( SbERR_BAD_ARGUMENT ); 2253 return; 2254 } 2255 pNewItem->SetName( aKey ); 2256 } 2257 } 2258 pNewItem->SetFlag( SBX_READWRITE ); 2259 xItemArray->Insert32( pNewItem, nNextIndex ); 2260 } 2261 else 2262 { 2263 SetError( SbERR_BAD_ARGUMENT ); 2264 return; 2265 } 2266 } 2267 2268 void BasicCollection::CollItem( SbxArray* pPar_ ) 2269 { 2270 if( pPar_->Count() != 2 ) 2271 { 2272 SetError( SbxERR_WRONG_ARGS ); 2273 return; 2274 } 2275 SbxVariable* pRes = NULL; 2276 SbxVariable* p = pPar_->Get( 1 ); 2277 sal_Int32 nIndex = implGetIndex( p ); 2278 if( nIndex >= 0 && nIndex < (sal_Int32)xItemArray->Count32() ) 2279 pRes = xItemArray->Get32( nIndex ); 2280 if( !pRes ) 2281 SetError( SbERR_BAD_ARGUMENT ); 2282 else 2283 *(pPar_->Get(0)) = *pRes; 2284 } 2285 2286 void BasicCollection::CollRemove( SbxArray* pPar_ ) 2287 { 2288 if( pPar_ == NULL || pPar_->Count() != 2 ) 2289 { 2290 SetError( SbxERR_WRONG_ARGS ); 2291 return; 2292 } 2293 2294 SbxVariable* p = pPar_->Get( 1 ); 2295 sal_Int32 nIndex = implGetIndex( p ); 2296 if( nIndex >= 0 && nIndex < (sal_Int32)xItemArray->Count32() ) 2297 { 2298 xItemArray->Remove32( nIndex ); 2299 2300 // Correct for stack if necessary 2301 SbiInstance* pInst = pINST; 2302 SbiRuntime* pRT = pInst ? pInst->pRun : NULL; 2303 if( pRT ) 2304 { 2305 SbiForStack* pStack = pRT->FindForStackItemForCollection( this ); 2306 if( pStack != NULL ) 2307 { 2308 if( pStack->nCurCollectionIndex >= nIndex ) 2309 --pStack->nCurCollectionIndex; 2310 } 2311 } 2312 } 2313 else 2314 SetError( SbERR_BAD_ARGUMENT ); 2315 } 2316 2317