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
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( "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
Create(sal_uInt16,sal_uInt32)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
CreateObject(const String & rClassName)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
Create(sal_uInt16,sal_uInt32)490 SbxBase* SbFormFactory::Create( sal_uInt16, sal_uInt32 )
491 {
492 // Not supported
493 return NULL;
494 }
495
CreateObject(const String & rClassName)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
cloneTypeObjectImpl(const SbxObject & rTypeObj)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
Create(sal_uInt16,sal_uInt32)593 SbxBase* SbTypeFactory::Create( sal_uInt16, sal_uInt32 )
594 {
595 // Not supported
596 return NULL;
597 }
598
CreateObject(const String & rClassName)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
createUserTypeImpl(const String & rClassName)612 SbxObject* createUserTypeImpl( const String& rClassName )
613 {
614 SbxObject* pRetObj = pTYPEFAC->CreateObject( rClassName );
615 return pRetObj;
616 }
617
618
TYPEINIT1(SbClassModuleObject,SbModule)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
~SbClassModuleObject()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
SFX_NOTIFY(SfxBroadcaster & rBC,const TypeId & rBCType,const SfxHint & rHint,const TypeId & rHintType)781 void SbClassModuleObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
782 const SfxHint& rHint, const TypeId& rHintType )
783 {
784 handleProcedureProperties( rBC, rHint );
785 }
786
Find(const XubString & rName,SbxClassType t)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
triggerInitializeEvent(void)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
triggerTerminateEvent(void)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
SbClassData(void)839 SbClassData::SbClassData( void )
840 {
841 mxIfaces = new SbxArray();
842 }
843
clear(void)844 void SbClassData::clear( void )
845 {
846 mxIfaces->Clear();
847 maRequiredTypes.clear();
848 }
849
SbClassFactory(void)850 SbClassFactory::SbClassFactory( void )
851 {
852 String aDummyName;
853 xClassModules = new SbxObject( aDummyName );
854 }
855
~SbClassFactory()856 SbClassFactory::~SbClassFactory()
857 {}
858
AddClassModule(SbModule * pClassModule)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
RemoveClassModule(SbModule * pClassModule)872 void SbClassFactory::RemoveClassModule( SbModule* pClassModule )
873 {
874 xClassModules->Remove( pClassModule );
875 }
876
Create(sal_uInt16,sal_uInt32)877 SbxBase* SbClassFactory::Create( sal_uInt16, sal_uInt32 )
878 {
879 // Not supported
880 return NULL;
881 }
882
CreateObject(const String & rClassName)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
FindClass(const String & rClassName)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
StarBASIC(StarBASIC * p,sal_Bool bIsDocBasic)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
SetModified(sal_Bool b)945 void StarBASIC::SetModified( sal_Bool b )
946 {
947 SbxBase::SetModified( b );
948 }
949
950 extern void lcl_closeTraceFile();
951
~StarBASIC()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
operator new(size_t n)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
operator delete(void * p)1026 void StarBASIC::operator delete( void* p )
1027 {
1028 ::operator delete( p );
1029 }
1030
implClearDependingVarsOnDelete(StarBASIC * pDeletedBasic)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
MakeModule(const String & rName,const String & rSrc)1058 SbModule* StarBASIC::MakeModule( const String& rName, const String& rSrc )
1059 {
1060 return MakeModule32( rName, rSrc );
1061 }
1062
MakeModule32(const String & rName,const::rtl::OUString & rSrc)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 }
MakeModule32(const String & rName,const ModuleInfo & mInfo,const rtl::OUString & rSrc)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
Insert(SbxVariable * pVar)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
Remove(SbxVariable * pVar)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
Compile(SbModule * pMod)1131 sal_Bool StarBASIC::Compile( SbModule* pMod )
1132 {
1133 return pMod ? pMod->Compile() : sal_False;
1134 }
1135
Disassemble(SbModule * pMod,String & rText)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
Clear()1144 void StarBASIC::Clear()
1145 {
1146 while( pModules->Count() )
1147 pModules->Remove( pModules->Count() - 1 );
1148 }
1149
FindModule(const String & rName)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
ClassModuleRunInitItemClassModuleRunInitItem1169 ClassModuleRunInitItem( void )
1170 : m_pModule( NULL )
1171 , m_bProcessing( false )
1172 , m_bRunInitDone( false )
1173 {}
ClassModuleRunInitItemClassModuleRunInitItem1174 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
implProcessModuleRunInit(ModuleInitDependencyMap & rMap,ClassModuleRunInitItem & rItem)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)
InitAllModules(StarBASIC * pBasicNotToInit)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
DeInitAllModules(void)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
ClearGlobalVars(void)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.
Find(const String & rName,SbxClassType t)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
Call(const String & rName,SbxArray * pParam)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)
FindSBXInCurrentScope(const String & rName)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
FindVarInCurrentScopy(const String & rName,sal_uInt16 & rStatus)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
QuitAndExitApplication()1421 void StarBASIC::QuitAndExitApplication()
1422 {
1423 Stop();
1424 bQuit = sal_True;
1425 }
1426
Stop()1427 void StarBASIC::Stop()
1428 {
1429 SbiInstance* p = pINST;
1430 while( p )
1431 {
1432 p->Stop();
1433 p = p->pNext;
1434 }
1435 }
1436
IsRunning()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.
ActivateObject(const String * pName,sal_Bool bActivate)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
GetActiveMethod(sal_uInt16 nLevel)1482 SbMethod* StarBASIC::GetActiveMethod( sal_uInt16 nLevel )
1483 {
1484 if( pINST )
1485 return pINST->GetCaller( nLevel );
1486 else
1487 return NULL;
1488 }
1489
GetActiveModule()1490 SbModule* StarBASIC::GetActiveModule()
1491 {
1492 if( pINST && !IsCompilerError() )
1493 return pINST->GetActiveModule();
1494 else
1495 return pCMOD;
1496 }
1497
BreakPoint(sal_uInt16 l,sal_uInt16 c1,sal_uInt16 c2)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
StepPoint(sal_uInt16 l,sal_uInt16 c1,sal_uInt16 c2)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
BreakHdl()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
GetLine()1525 sal_uInt16 StarBASIC::GetLine() { return GetSbData()->nLine; }
GetCol1()1526 sal_uInt16 StarBASIC::GetCol1() { return GetSbData()->nCol1; }
GetCol2()1527 sal_uInt16 StarBASIC::GetCol2() { return GetSbData()->nCol2; }
1528
1529 // Specific to error handler
GetErrorCode()1530 SbError StarBASIC::GetErrorCode() { return GetSbData()->nCode; }
GetErrorText()1531 const String& StarBASIC::GetErrorText() { return GetSbData()->aErrMsg; }
IsCompilerError()1532 sal_Bool StarBASIC::IsCompilerError() { return GetSbData()->bCompiler; }
SetGlobalLanguageMode(SbLanguageMode eLanguageMode)1533 void StarBASIC::SetGlobalLanguageMode( SbLanguageMode eLanguageMode )
1534 {
1535 GetSbData()->eLanguageMode = eLanguageMode;
1536 }
GetGlobalLanguageMode()1537 SbLanguageMode StarBASIC::GetGlobalLanguageMode()
1538 {
1539 return GetSbData()->eLanguageMode;
1540 }
1541 // Local settings
GetLanguageMode()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
GetVBErrorCode(SbError nError)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
GetSfxFromVBError(sal_uInt16 nError)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
SetErrorData(SbError nCode,sal_uInt16 nLine,sal_uInt16 nCol1,sal_uInt16 nCol2)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
BasicStringList_ImplBasicStringList_Impl1669 BasicStringList_Impl( ResId& rErrIdP, sal_uInt16 nId)
1670 : Resource( rErrIdP ),aResId(nId, *rErrIdP.GetResMgr() ){}
~BasicStringList_ImplBasicStringList_Impl1671 ~BasicStringList_Impl() { FreeResource(); }
1672
GetStringBasicStringList_Impl1673 String GetString(){ return String( aResId ); }
IsErrorTextAvailableBasicStringList_Impl1674 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
StaticSuppressSfxResource(sal_Bool bSuppress)1682 void StarBASIC::StaticSuppressSfxResource( sal_Bool bSuppress )
1683 {
1684 bStaticSuppressSfxResource = bSuppress;
1685 }
1686
1687 // Hack for #83750, use bStaticSuppressSfxResource as setup flag
runsInSetup(void)1688 sal_Bool runsInSetup( void )
1689 {
1690 return bStaticSuppressSfxResource;
1691 }
1692
1693
MakeErrorText(SbError nId,const String & aMsg)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
CError(SbError code,const String & rMsg,sal_uInt16 l,sal_uInt16 c1,sal_uInt16 c2)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
RTError(SbError code,sal_uInt16 l,sal_uInt16 c1,sal_uInt16 c2)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
RTError(SbError code,const String & rMsg,sal_uInt16 l,sal_uInt16 c1,sal_uInt16 c2)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
Error(SbError n)1815 void StarBASIC::Error( SbError n )
1816 {
1817 Error( n, String() );
1818 }
1819
Error(SbError n,const String & rMsg)1820 void StarBASIC::Error( SbError n, const String& rMsg )
1821 {
1822 if( pINST )
1823 pINST->Error( n, rMsg );
1824 }
1825
FatalError(SbError n)1826 void StarBASIC::FatalError( SbError n )
1827 {
1828 if( pINST )
1829 pINST->FatalError( n );
1830 }
1831
FatalError(SbError _errCode,const String & _details)1832 void StarBASIC::FatalError( SbError _errCode, const String& _details )
1833 {
1834 if( pINST )
1835 pINST->FatalError( _errCode, _details );
1836 }
1837
GetErrBasic()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
GetErrorMsg()1847 String StarBASIC::GetErrorMsg()
1848 {
1849 if( pINST )
1850 return pINST->GetErrorMsg();
1851 else
1852 return String();
1853 }
1854
GetErl()1855 sal_uInt16 StarBASIC::GetErl()
1856 {
1857 if( pINST )
1858 return pINST->GetErl();
1859 else
1860 return 0;
1861 }
1862
ErrorHdl()1863 sal_Bool __EXPORT StarBASIC::ErrorHdl()
1864 {
1865 return (sal_Bool) ( aErrorHdl.IsSet()
1866 ? aErrorHdl.Call( this ) : sal_False );
1867 }
1868
GetGlobalErrorHdl()1869 Link StarBASIC::GetGlobalErrorHdl()
1870 {
1871 return GetSbData()->aErrHdl;
1872 }
1873
SetGlobalErrorHdl(const Link & rLink)1874 void StarBASIC::SetGlobalErrorHdl( const Link& rLink )
1875 {
1876 GetSbData()->aErrHdl = rLink;
1877 }
1878
1879
GetGlobalBreakHdl()1880 Link StarBASIC::GetGlobalBreakHdl()
1881 {
1882 return GetSbData()->aBreakHdl;
1883 }
1884
SetGlobalBreakHdl(const Link & rLink)1885 void StarBASIC::SetGlobalBreakHdl( const Link& rLink )
1886 {
1887 GetSbData()->aBreakHdl = rLink;
1888 }
1889
getUnoListeners(void)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
LoadData(SvStream & r,sal_uInt16 nVer)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
StoreData(SvStream & r) const1962 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
LoadOldModules(SvStream &)1976 sal_Bool StarBASIC::LoadOldModules( SvStream& )
1977 {
1978 return sal_False;
1979 }
1980
GetUNOConstant(const sal_Char * _pAsciiName,::com::sun::star::uno::Any & aOut)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
GetModelFromBasic(SbxObject * pBasic)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
lcl_foldCollectionName(const String & rName)2064 static ::rtl::OUString lcl_foldCollectionName( const String& rName )
2065 {
2066 return ::rtl::OUString( rName ).toAsciiUpperCase();
2067 }
2068
BasicCollection(const XubString & rClass)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
~BasicCollection()2083 BasicCollection::~BasicCollection()
2084 {
2085 delete mpNameMap;
2086 }
2087
Clear()2088 void BasicCollection::Clear()
2089 {
2090 SbxObject::Clear();
2091 Initialize();
2092 }
2093
Initialize()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
Find(const XubString & rName,SbxClassType t)2126 SbxVariable* BasicCollection::Find( const XubString& rName, SbxClassType t )
2127 {
2128 SbxVariable* pFind = SbxObject::Find( rName, t );
2129 return pFind;
2130 }
2131
SFX_NOTIFY(SfxBroadcaster & rCst,const TypeId & rId1,const SfxHint & rHint,const TypeId & rId2)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
implGetIndex(SbxVariable * pIndexVar)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
implRegisterName(SbxVariable * pVar)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
implUnregisterName(SbxVariable * pVar)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
implFindByName(const String & rName)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
implGetIndexForName(const String & rName)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
CollAdd(SbxArray * pPar_)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
CollItem(SbxArray * pPar_)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
CollRemove(SbxArray * pPar_)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