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