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