1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <tools/rcid.h>
22 #include <tools/stream.hxx>
23 #include <tools/errinf.hxx>
24 #include <tools/solarmutex.hxx>
25 #include <basic/sbx.hxx>
26 #include <tools/rc.hxx>
27 #include <vcl/svapp.hxx>
28 #include <comphelper/processfactory.hxx>
30 #include "sbunoobj.hxx"
31 #include "sbjsmeth.hxx"
32 #include "sbjsmod.hxx"
33 #include "sbintern.hxx"
34 #include "runtime.hxx"
35 #include <basic/sbuno.hxx>
36 #include "sbobjmod.hxx"
38 #include "filefmt.hxx"
41 #include <osl/mutex.hxx>
42 #include <cppuhelper/implbase1.hxx>
43 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
44 #include <com/sun/star/util/XCloseBroadcaster.hpp>
45 #include <com/sun/star/util/XCloseListener.hpp>
46 #include "errobject.hxx"
47 #include <boost/scoped_array.hpp>
48 #include <unordered_map>
50 #include <com/sun/star/script/ModuleType.hpp>
51 #include <com/sun/star/script/ModuleInfo.hpp>
52 #include <svtools/miscopt.hxx>
53 using namespace ::com::sun::star::script
;
55 TYPEINIT1(StarBASIC
,SbxObject
)
57 #define RTLNAME "@SBRTL"
59 using namespace ::com::sun::star
;
60 using namespace ::com::sun::star::uno
;
61 using com::sun::star::uno::Reference
;
62 using com::sun::star::uno::Any
;
63 using com::sun::star::uno::UNO_QUERY
;
64 using com::sun::star::lang::XMultiServiceFactory
;
68 class DocBasicItem
: public ::cppu::WeakImplHelper1
< util::XCloseListener
>
71 explicit DocBasicItem( StarBASIC
& rDocBasic
);
72 virtual ~DocBasicItem();
74 inline const SbxObjectRef
& getClassModules() const { return mxClassModules
; }
75 inline bool isDocClosed() const { return mbDocClosed
; }
77 void clearDependingVarsOnDelete( StarBASIC
& rDeletedBasic
);
79 void startListening();
82 void setDisposed( bool bDisposed
)
84 mbDisposed
= bDisposed
;
87 virtual void SAL_CALL
queryClosing( const lang::EventObject
& rSource
, sal_Bool bGetsOwnership
) throw (util::CloseVetoException
, uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
88 virtual void SAL_CALL
notifyClosing( const lang::EventObject
& rSource
) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
89 virtual void SAL_CALL
disposing( const lang::EventObject
& rSource
) throw (uno::RuntimeException
, std::exception
) SAL_OVERRIDE
;
92 StarBASIC
& mrDocBasic
;
93 SbxObjectRef mxClassModules
;
100 DocBasicItem::DocBasicItem( StarBASIC
& rDocBasic
) :
101 mrDocBasic( rDocBasic
),
102 mxClassModules( new SbxObject( OUString() ) ),
103 mbDocClosed( false ),
108 DocBasicItem::~DocBasicItem()
110 // tdf#90969 HACK: don't use SolarMutexGuard - there is a horrible global
111 // map GaDocBasicItems holding instances, and these get deleted from exit
112 // handlers, when the SolarMutex is already dead
113 tools::SolarMutex::Acquire();
118 mxClassModules
.Clear(); // release with SolarMutex locked
125 tools::SolarMutex::Release();
128 void DocBasicItem::clearDependingVarsOnDelete( StarBASIC
& rDeletedBasic
)
130 mrDocBasic
.implClearDependingVarsOnDelete( &rDeletedBasic
);
133 void DocBasicItem::startListening()
136 mrDocBasic
.GetUNOConstant( "ThisComponent", aThisComp
);
137 Reference
< util::XCloseBroadcaster
> xCloseBC( aThisComp
, UNO_QUERY
);
138 mbDisposed
= !xCloseBC
.is();
141 try { xCloseBC
->addCloseListener( this ); } catch(const uno::Exception
& ) {}
145 void DocBasicItem::stopListening()
147 if( mbDisposed
) return;
150 if (!mrDocBasic
.GetUNOConstant("ThisComponent", aThisComp
))
153 Reference
< util::XCloseBroadcaster
> xCloseBC( aThisComp
, UNO_QUERY
);
156 try { xCloseBC
->removeCloseListener( this ); } catch(const uno::Exception
& ) {}
160 void SAL_CALL
DocBasicItem::queryClosing( const lang::EventObject
& /*rSource*/, sal_Bool
/*bGetsOwnership*/ ) throw (util::CloseVetoException
, uno::RuntimeException
, std::exception
)
164 void SAL_CALL
DocBasicItem::notifyClosing( const lang::EventObject
& /*rEvent*/ ) throw (uno::RuntimeException
, std::exception
)
170 void SAL_CALL
DocBasicItem::disposing( const lang::EventObject
& /*rEvent*/ ) throw (uno::RuntimeException
, std::exception
)
179 typedef ::rtl::Reference
< DocBasicItem
> DocBasicItemRef
;
180 typedef std::unordered_map
< const StarBASIC
*, DocBasicItemRef
> DocBasicItemMap
;
182 class GaDocBasicItems
: public rtl::Static
<DocBasicItemMap
,GaDocBasicItems
> {};
184 const DocBasicItem
* lclFindDocBasicItem( const StarBASIC
* pDocBasic
)
186 DocBasicItemMap::iterator it
= GaDocBasicItems::get().find( pDocBasic
);
187 DocBasicItemMap::iterator end
= GaDocBasicItems::get().end();
188 return (it
!= end
) ? it
->second
.get() : 0;
191 void lclInsertDocBasicItem( StarBASIC
& rDocBasic
)
193 DocBasicItemRef
& rxDocBasicItem
= GaDocBasicItems::get()[ &rDocBasic
];
194 rxDocBasicItem
.set( new DocBasicItem( rDocBasic
) );
195 rxDocBasicItem
->startListening();
198 void lclRemoveDocBasicItem( StarBASIC
& rDocBasic
)
200 DocBasicItemMap::iterator it
= GaDocBasicItems::get().find( &rDocBasic
);
201 if( it
!= GaDocBasicItems::get().end() )
203 it
->second
->stopListening();
204 GaDocBasicItems::get().erase( it
);
206 DocBasicItemMap::iterator it_end
= GaDocBasicItems::get().end();
207 for( it
= GaDocBasicItems::get().begin(); it
!= it_end
; ++it
)
209 it
->second
->clearDependingVarsOnDelete( rDocBasic
);
213 StarBASIC
* lclGetDocBasicForModule( SbModule
* pModule
)
215 StarBASIC
* pRetBasic
= NULL
;
216 SbxObject
* pCurParent
= pModule
;
217 while( pCurParent
->GetParent() != NULL
)
219 pCurParent
= pCurParent
->GetParent();
220 StarBASIC
* pDocBasic
= PTR_CAST( StarBASIC
, pCurParent
);
221 if( pDocBasic
!= NULL
&& pDocBasic
->IsDocBasic() )
223 pRetBasic
= pDocBasic
;
234 SbxObject
* StarBASIC::getVBAGlobals( )
239 if ( GetUNOConstant("ThisComponent", aThisDoc
) )
241 Reference
< XMultiServiceFactory
> xDocFac( aThisDoc
, UNO_QUERY
);
246 xDocFac
->createInstance("ooo.vba.VBAGlobals");
248 catch(const Exception
& )
254 const OUString
aVBAHook("VBAGlobals");
255 pVBAGlobals
= static_cast<SbUnoObject
*>(Find( aVBAHook
, SbxCLASS_DONTCARE
));
261 SbxVariable
* StarBASIC::VBAFind( const OUString
& rName
, SbxClassType t
)
263 if( rName
== "ThisComponent" )
267 // rename to init globals
268 if ( getVBAGlobals( ) )
270 return pVBAGlobals
->Find( rName
, t
);
275 // Create array for conversion SFX <-> VB error code
276 struct SFX_VB_ErrorItem
282 const SFX_VB_ErrorItem SFX_VB_ErrorTab
[] =
284 { 1, SbERR_BASIC_EXCEPTION
}, // #87844 Map exception to error code 1
286 { 3, SbERR_NO_GOSUB
},
287 { 4, SbERR_REDO_FROM_START
},
288 { 5, SbERR_BAD_ARGUMENT
},
289 { 6, SbERR_MATH_OVERFLOW
},
290 { 7, SbERR_NO_MEMORY
},
291 { 8, SbERR_ALREADY_DIM
},
292 { 9, SbERR_OUT_OF_RANGE
},
293 { 10, SbERR_DUPLICATE_DEF
},
294 { 11, SbERR_ZERODIV
},
295 { 12, SbERR_VAR_UNDEFINED
},
296 { 13, SbERR_CONVERSION
},
297 { 14, SbERR_BAD_PARAMETER
},
298 { 18, SbERR_USER_ABORT
},
299 { 20, SbERR_BAD_RESUME
},
300 { 28, SbERR_STACK_OVERFLOW
},
301 { 35, SbERR_PROC_UNDEFINED
},
302 { 48, SbERR_BAD_DLL_LOAD
},
303 { 49, SbERR_BAD_DLL_CALL
},
304 { 51, SbERR_INTERNAL_ERROR
},
305 { 52, SbERR_BAD_CHANNEL
},
306 { 53, SbERR_FILE_NOT_FOUND
},
307 { 54, SbERR_BAD_FILE_MODE
},
308 { 55, SbERR_FILE_ALREADY_OPEN
},
309 { 57, SbERR_IO_ERROR
},
310 { 58, SbERR_FILE_EXISTS
},
311 { 59, SbERR_BAD_RECORD_LENGTH
},
312 { 61, SbERR_DISK_FULL
},
313 { 62, SbERR_READ_PAST_EOF
},
314 { 63, SbERR_BAD_RECORD_NUMBER
},
315 { 67, SbERR_TOO_MANY_FILES
},
316 { 68, SbERR_NO_DEVICE
},
317 { 70, SbERR_ACCESS_DENIED
},
318 { 71, SbERR_NOT_READY
},
319 { 73, SbERR_NOT_IMPLEMENTED
},
320 { 74, SbERR_DIFFERENT_DRIVE
},
321 { 75, SbERR_ACCESS_ERROR
},
322 { 76, SbERR_PATH_NOT_FOUND
},
323 { 91, SbERR_NO_OBJECT
},
324 { 93, SbERR_BAD_PATTERN
},
325 { 94, SBERR_IS_NULL
},
326 { 250, SbERR_DDE_ERROR
},
327 { 280, SbERR_DDE_WAITINGACK
},
328 { 281, SbERR_DDE_OUTOFCHANNELS
},
329 { 282, SbERR_DDE_NO_RESPONSE
},
330 { 283, SbERR_DDE_MULT_RESPONSES
},
331 { 284, SbERR_DDE_CHANNEL_LOCKED
},
332 { 285, SbERR_DDE_NOTPROCESSED
},
333 { 286, SbERR_DDE_TIMEOUT
},
334 { 287, SbERR_DDE_USER_INTERRUPT
},
335 { 288, SbERR_DDE_BUSY
},
336 { 289, SbERR_DDE_NO_DATA
},
337 { 290, SbERR_DDE_WRONG_DATA_FORMAT
},
338 { 291, SbERR_DDE_PARTNER_QUIT
},
339 { 292, SbERR_DDE_CONV_CLOSED
},
340 { 293, SbERR_DDE_NO_CHANNEL
},
341 { 294, SbERR_DDE_INVALID_LINK
},
342 { 295, SbERR_DDE_QUEUE_OVERFLOW
},
343 { 296, SbERR_DDE_LINK_ALREADY_EST
},
344 { 297, SbERR_DDE_LINK_INV_TOPIC
},
345 { 298, SbERR_DDE_DLL_NOT_FOUND
},
346 { 323, SbERR_CANNOT_LOAD
},
347 { 341, SbERR_BAD_INDEX
},
348 { 366, SbERR_NO_ACTIVE_OBJECT
},
349 { 380, SbERR_BAD_PROP_VALUE
},
350 { 382, SbERR_PROP_READONLY
},
351 { 394, SbERR_PROP_WRITEONLY
},
352 { 420, SbERR_INVALID_OBJECT
},
353 { 423, SbERR_NO_METHOD
},
354 { 424, SbERR_NEEDS_OBJECT
},
355 { 425, SbERR_INVALID_USAGE_OBJECT
},
356 { 430, SbERR_NO_OLE
},
357 { 438, SbERR_BAD_METHOD
},
358 { 440, SbERR_OLE_ERROR
},
359 { 445, SbERR_BAD_ACTION
},
360 { 446, SbERR_NO_NAMED_ARGS
},
361 { 447, SbERR_BAD_LOCALE
},
362 { 448, SbERR_NAMED_NOT_FOUND
},
363 { 449, SbERR_NOT_OPTIONAL
},
364 { 450, SbERR_WRONG_ARGS
},
365 { 451, SbERR_NOT_A_COLL
},
366 { 452, SbERR_BAD_ORDINAL
},
367 { 453, SbERR_DLLPROC_NOT_FOUND
},
368 { 460, SbERR_BAD_CLIPBD_FORMAT
},
369 { 951, SbERR_UNEXPECTED
},
370 { 952, SbERR_EXPECTED
},
371 { 953, SbERR_SYMBOL_EXPECTED
},
372 { 954, SbERR_VAR_EXPECTED
},
373 { 955, SbERR_LABEL_EXPECTED
},
374 { 956, SbERR_LVALUE_EXPECTED
},
375 { 957, SbERR_VAR_DEFINED
},
376 { 958, SbERR_PROC_DEFINED
},
377 { 959, SbERR_LABEL_DEFINED
},
378 { 960, SbERR_UNDEF_VAR
},
379 { 961, SbERR_UNDEF_ARRAY
},
380 { 962, SbERR_UNDEF_PROC
},
381 { 963, SbERR_UNDEF_LABEL
},
382 { 964, SbERR_UNDEF_TYPE
},
383 { 965, SbERR_BAD_EXIT
},
384 { 966, SbERR_BAD_BLOCK
},
385 { 967, SbERR_BAD_BRACKETS
},
386 { 968, SbERR_BAD_DECLARATION
},
387 { 969, SbERR_BAD_PARAMETERS
},
388 { 970, SbERR_BAD_CHAR_IN_NUMBER
},
389 { 971, SbERR_MUST_HAVE_DIMS
},
390 { 972, SbERR_NO_IF
},
391 { 973, SbERR_NOT_IN_SUBR
},
392 { 974, SbERR_NOT_IN_MAIN
},
393 { 975, SbERR_WRONG_DIMS
},
394 { 976, SbERR_BAD_OPTION
},
395 { 977, SbERR_CONSTANT_REDECLARED
},
396 { 978, SbERR_PROG_TOO_LARGE
},
397 { 979, SbERR_NO_STRINGS_ARRAYS
},
398 { 1000, SbERR_PROPERTY_NOT_FOUND
},
399 { 1001, SbERR_METHOD_NOT_FOUND
},
400 { 1002, SbERR_ARG_MISSING
},
401 { 1003, SbERR_BAD_NUMBER_OF_ARGS
},
402 { 1004, SbERR_METHOD_FAILED
},
403 { 1005, SbERR_SETPROP_FAILED
},
404 { 1006, SbERR_GETPROP_FAILED
},
405 { 1007, SbERR_BASIC_COMPAT
},
406 { 0xFFFF, 0xFFFFFFFFL
} // End mark
409 // The StarBASIC factory is a hack. When a SbModule is created, its pointer
410 // is saved and given to the following SbProperties/SbMethods. This restores
411 // the Modul-relationshop. But it works only when a modul is loaded.
412 // Can cause troubles with separately loaded properties!
414 SbxBase
* SbiFactory::Create( sal_uInt16 nSbxId
, sal_uInt32 nCreator
)
416 if( nCreator
== SBXCR_SBX
)
422 return new StarBASIC( NULL
);
424 return new SbModule( aEmpty
);
425 case SBXID_BASICPROP
:
426 return new SbProperty( aEmpty
, SbxVARIANT
, NULL
);
427 case SBXID_BASICMETHOD
:
428 return new SbMethod( aEmpty
, SbxVARIANT
, NULL
);
429 case SBXID_JSCRIPTMOD
:
430 return new SbJScriptModule( aEmpty
);
431 case SBXID_JSCRIPTMETH
:
432 return new SbJScriptMethod( aEmpty
, SbxVARIANT
, NULL
);
438 SbxObject
* SbiFactory::CreateObject( const OUString
& rClass
)
440 if( rClass
.equalsIgnoreAsciiCase( "StarBASIC" ) )
442 return new StarBASIC( NULL
);
444 else if( rClass
.equalsIgnoreAsciiCase( "StarBASICModule" ) )
446 return new SbModule( OUString() );
448 else if( rClass
.equalsIgnoreAsciiCase( "Collection" ) )
450 return new BasicCollection( OUString("Collection"));
452 else if( rClass
.equalsIgnoreAsciiCase( "FileSystemObject" ) )
456 Reference
< XMultiServiceFactory
> xFactory( comphelper::getProcessServiceFactory(), UNO_SET_THROW
);
457 OUString
aServiceName("ooo.vba.FileSystemObject");
458 Reference
< XInterface
> xInterface( xFactory
->createInstance( aServiceName
), UNO_SET_THROW
);
459 return new SbUnoObject( aServiceName
, uno::makeAny( xInterface
) );
461 catch(const Exception
& )
469 // Factory class to create OLE objects
470 class SbOLEFactory
: public SbxFactory
473 virtual SbxBase
* Create( sal_uInt16 nSbxId
, sal_uInt32
= SBXCR_SBX
) SAL_OVERRIDE
;
474 virtual SbxObject
* CreateObject( const OUString
& ) SAL_OVERRIDE
;
477 SbxBase
* SbOLEFactory::Create( sal_uInt16
, sal_uInt32
)
483 SbxObject
* SbOLEFactory::CreateObject( const OUString
& rClassName
)
485 SbxObject
* pRet
= createOLEObject_Impl( rClassName
);
491 // SbFormFactory, show user forms by: dim as new <user form name>
493 class SbFormFactory
: public SbxFactory
496 virtual SbxBase
* Create( sal_uInt16 nSbxId
, sal_uInt32
= SBXCR_SBX
) SAL_OVERRIDE
;
497 virtual SbxObject
* CreateObject( const OUString
& ) SAL_OVERRIDE
;
500 SbxBase
* SbFormFactory::Create( sal_uInt16
, sal_uInt32
)
506 SbxObject
* SbFormFactory::CreateObject( const OUString
& rClassName
)
508 if( SbModule
* pMod
= GetSbData()->pMod
)
510 if( SbxVariable
* pVar
= pMod
->Find( rClassName
, SbxCLASS_OBJECT
) )
512 if( SbUserFormModule
* pFormModule
= PTR_CAST( SbUserFormModule
, pVar
->GetObject() ) )
514 bool bInitState
= pFormModule
->getInitState();
517 // Not the first instantiate, reset
518 bool bTriggerTerminateEvent
= false;
519 pFormModule
->ResetApiObj( bTriggerTerminateEvent
);
520 pFormModule
->setInitState( false );
526 return pFormModule
->CreateInstance();
537 SbxObject
* cloneTypeObjectImpl( const SbxObject
& rTypeObj
)
539 SbxObject
* pRet
= new SbxObject( rTypeObj
);
540 pRet
->PutObject( pRet
);
542 // Copy the properties, not only the reference to them
543 SbxArray
* pProps
= pRet
->GetProperties();
544 sal_uInt32 nCount
= pProps
->Count32();
545 for( sal_uInt32 i
= 0 ; i
< nCount
; i
++ )
547 SbxVariable
* pVar
= pProps
->Get32( i
);
548 SbxProperty
* pProp
= PTR_CAST( SbxProperty
, pVar
);
551 SbxProperty
* pNewProp
= new SbxProperty( *pProp
);
552 SbxDataType eVarType
= pVar
->GetType();
553 if( eVarType
& SbxARRAY
)
555 SbxBase
* pParObj
= pVar
->GetObject();
556 SbxDimArray
* pSource
= PTR_CAST(SbxDimArray
,pParObj
);
557 SbxDimArray
* pDest
= new SbxDimArray( pVar
->GetType() );
559 pDest
->setHasFixedSize( pSource
&& pSource
->hasFixedSize() );
560 if ( pSource
&& pSource
->GetDims() && pSource
->hasFixedSize() )
564 for ( sal_Int32 j
= 1 ; j
<= pSource
->GetDims(); ++j
)
566 pSource
->GetDim32( (sal_Int32
)j
, lb
, ub
);
567 pDest
->AddDim32( lb
, ub
);
572 pDest
->unoAddDim( 0, -1 ); // variant array
574 SbxFlagBits nSavFlags
= pVar
->GetFlags();
575 pNewProp
->ResetFlag( SBX_FIXED
);
576 // need to reset the FIXED flag
577 // when calling PutObject ( because the type will not match Object )
578 pNewProp
->PutObject( pDest
);
579 pNewProp
->SetFlags( nSavFlags
);
581 if( eVarType
== SbxOBJECT
)
583 SbxBase
* pObjBase
= pVar
->GetObject();
584 SbxObject
* pSrcObj
= PTR_CAST(SbxObject
,pObjBase
);
585 SbxObject
* pDestObj
= NULL
;
586 if( pSrcObj
!= NULL
)
587 pDestObj
= cloneTypeObjectImpl( *pSrcObj
);
588 pNewProp
->PutObject( pDestObj
);
590 pProps
->PutDirect( pNewProp
, i
);
596 // Factory class to create user defined objects (type command)
597 class SbTypeFactory
: public SbxFactory
600 virtual SbxBase
* Create( sal_uInt16 nSbxId
, sal_uInt32
= SBXCR_SBX
) SAL_OVERRIDE
;
601 virtual SbxObject
* CreateObject( const OUString
& ) SAL_OVERRIDE
;
604 SbxBase
* SbTypeFactory::Create( sal_uInt16
, sal_uInt32
)
610 SbxObject
* SbTypeFactory::CreateObject( const OUString
& rClassName
)
612 SbxObject
* pRet
= NULL
;
613 SbModule
* pMod
= GetSbData()->pMod
;
616 const SbxObject
* pObj
= pMod
->FindType( rClassName
);
619 pRet
= cloneTypeObjectImpl( *pObj
);
625 SbxObject
* createUserTypeImpl( const OUString
& rClassName
)
627 SbxObject
* pRetObj
= GetSbData()->pTypeFac
->CreateObject( rClassName
);
632 TYPEINIT1(SbClassModuleObject
,SbModule
)
634 SbClassModuleObject::SbClassModuleObject( SbModule
* pClassModule
)
635 : SbModule( pClassModule
->GetName() )
636 , mpClassModule( pClassModule
)
637 , mbInitializeEventDone( false )
639 aOUSource
= pClassModule
->aOUSource
;
640 aComment
= pClassModule
->aComment
;
641 pImage
= pClassModule
->pImage
;
642 pBreaks
= pClassModule
->pBreaks
;
644 SetClassName( pClassModule
->GetName() );
646 // Allow search only internally
647 ResetFlag( SBX_GBLSEARCH
);
649 // Copy the methods from original class module
650 SbxArray
* pClassMethods
= pClassModule
->GetMethods();
651 sal_uInt32 nMethodCount
= pClassMethods
->Count32();
653 for( i
= 0 ; i
< nMethodCount
; i
++ )
655 SbxVariable
* pVar
= pClassMethods
->Get32( i
);
657 // Exclude SbIfaceMapperMethod to copy them in a second step
658 SbIfaceMapperMethod
* pIfaceMethod
= PTR_CAST( SbIfaceMapperMethod
, pVar
);
661 SbMethod
* pMethod
= PTR_CAST(SbMethod
, pVar
);
664 SbxFlagBits 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(), true );
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
++ )
681 SbxVariable
* pVar
= pClassMethods
->Get32( i
);
683 SbIfaceMapperMethod
* pIfaceMethod
= PTR_CAST( SbIfaceMapperMethod
, pVar
);
686 SbMethod
* pImplMethod
= pIfaceMethod
->getImplMethod();
689 OSL_FAIL( "No ImplMethod" );
693 // Search for own copy of ImplMethod
694 SbxVariable
* p
= pMethods
->Find( pImplMethod
->GetName(), SbxCLASS_METHOD
);
695 SbMethod
* pImplMethodCopy
= p
? PTR_CAST(SbMethod
,p
) : NULL
;
696 if( !pImplMethodCopy
)
698 OSL_FAIL( "Found no ImplMethod copy" );
701 SbIfaceMapperMethod
* pNewIfaceMethod
=
702 new SbIfaceMapperMethod( pIfaceMethod
->GetName(), pImplMethodCopy
);
703 pMethods
->PutDirect( pNewIfaceMethod
, i
);
707 // Copy the properties from original class module
708 SbxArray
* pClassProps
= pClassModule
->GetProperties();
709 sal_uInt32 nPropertyCount
= pClassProps
->Count32();
710 for( i
= 0 ; i
< nPropertyCount
; i
++ )
712 SbxVariable
* pVar
= pClassProps
->Get32( i
);
713 SbProcedureProperty
* pProcedureProp
= PTR_CAST( SbProcedureProperty
, pVar
);
716 SbxFlagBits nFlags_
= pProcedureProp
->GetFlags();
717 pProcedureProp
->SetFlag( SBX_NO_BROADCAST
);
718 SbProcedureProperty
* pNewProp
= new SbProcedureProperty
719 ( pProcedureProp
->GetName(), pProcedureProp
->GetType() );
720 pNewProp
->SetFlags( nFlags_
); // Copy flags
721 pNewProp
->ResetFlag( SBX_NO_BROADCAST
); // except the Broadcast if it was set
722 pProcedureProp
->SetFlags( nFlags_
);
723 pProps
->PutDirect( pNewProp
, i
);
724 StartListening( pNewProp
->GetBroadcaster(), true );
728 SbxProperty
* pProp
= PTR_CAST( SbxProperty
, pVar
);
731 SbxFlagBits nFlags_
= pProp
->GetFlags();
732 pProp
->SetFlag( SBX_NO_BROADCAST
);
733 SbxProperty
* pNewProp
= new SbxProperty( *pProp
);
735 // Special handling for modules instances and collections, they need
736 // to be instantiated, otherwise all refer to the same base object
737 SbxDataType eVarType
= pProp
->GetType();
738 if( eVarType
== SbxOBJECT
)
740 SbxBase
* pObjBase
= pProp
->GetObject();
741 SbxObject
* pObj
= PTR_CAST(SbxObject
,pObjBase
);
744 OUString aObjClass
= pObj
->GetClassName();
746 SbClassModuleObject
* pClassModuleObj
= PTR_CAST(SbClassModuleObject
,pObjBase
);
747 if( pClassModuleObj
!= NULL
)
749 SbModule
* pLclClassModule
= pClassModuleObj
->getClassModule();
750 SbClassModuleObject
* pNewObj
= new SbClassModuleObject( pLclClassModule
);
751 pNewObj
->SetName( pProp
->GetName() );
752 pNewObj
->SetParent( pLclClassModule
->pParent
);
753 pNewProp
->PutObject( pNewObj
);
755 else if( aObjClass
.equalsIgnoreAsciiCase( "Collection" ) )
757 OUString
aCollectionName("Collection");
758 BasicCollection
* pNewCollection
= new BasicCollection( aCollectionName
);
759 pNewCollection
->SetName( pProp
->GetName() );
760 pNewCollection
->SetParent( pClassModule
->pParent
);
761 pNewProp
->PutObject( pNewCollection
);
766 pNewProp
->ResetFlag( SBX_NO_BROADCAST
);
767 pNewProp
->SetParent( this );
768 pProps
->PutDirect( pNewProp
, i
);
769 pProp
->SetFlags( nFlags_
);
773 SetModuleType( ModuleType::CLASS
);
774 mbVBACompat
= pClassModule
->mbVBACompat
;
777 SbClassModuleObject::~SbClassModuleObject()
779 // do not trigger termination event when document is already closed
780 if( StarBASIC::IsRunning() )
781 if( StarBASIC
* pDocBasic
= lclGetDocBasicForModule( this ) )
782 if( const DocBasicItem
* pDocBasicItem
= lclFindDocBasicItem( pDocBasic
) )
783 if( !pDocBasicItem
->isDocClosed() )
784 triggerTerminateEvent();
786 // Must be deleted by base class dtor because this data
787 // is not owned by the SbClassModuleObject object
792 void SbClassModuleObject::SFX_NOTIFY( SfxBroadcaster
& rBC
, const TypeId
& rBCType
,
793 const SfxHint
& rHint
, const TypeId
& rHintType
)
795 handleProcedureProperties( rBC
, rHint
);
798 SbxVariable
* SbClassModuleObject::Find( const OUString
& rName
, SbxClassType t
)
800 SbxVariable
* pRes
= SbxObject::Find( rName
, t
);
803 triggerInitializeEvent();
805 SbIfaceMapperMethod
* pIfaceMapperMethod
= PTR_CAST(SbIfaceMapperMethod
,pRes
);
806 if( pIfaceMapperMethod
)
808 pRes
= pIfaceMapperMethod
->getImplMethod();
809 pRes
->SetFlag( SBX_EXTFOUND
);
815 void SbClassModuleObject::triggerInitializeEvent()
817 if( mbInitializeEventDone
)
822 mbInitializeEventDone
= true;
825 SbxVariable
* pMeth
= SbxObject::Find(OUString("Class_Initialize"), SbxCLASS_METHOD
);
833 void SbClassModuleObject::triggerTerminateEvent()
835 if( !mbInitializeEventDone
|| GetSbData()->bRunInit
)
840 SbxVariable
* pMeth
= SbxObject::Find(OUString("Class_Terminate"), SbxCLASS_METHOD
);
849 SbClassData::SbClassData()
851 mxIfaces
= new SbxArray();
854 void SbClassData::clear()
857 maRequiredTypes
.clear();
860 SbClassFactory::SbClassFactory()
863 xClassModules
= new SbxObject( aDummyName
);
866 SbClassFactory::~SbClassFactory()
869 void SbClassFactory::AddClassModule( SbModule
* pClassModule
)
871 SbxObjectRef xToUseClassModules
= xClassModules
;
873 if( StarBASIC
* pDocBasic
= lclGetDocBasicForModule( pClassModule
) )
874 if( const DocBasicItem
* pDocBasicItem
= lclFindDocBasicItem( pDocBasic
) )
875 xToUseClassModules
= pDocBasicItem
->getClassModules();
877 SbxObject
* pParent
= pClassModule
->GetParent();
878 xToUseClassModules
->Insert( pClassModule
);
879 pClassModule
->SetParent( pParent
);
882 void SbClassFactory::RemoveClassModule( SbModule
* pClassModule
)
884 xClassModules
->Remove( pClassModule
);
887 SbxBase
* SbClassFactory::Create( sal_uInt16
, sal_uInt32
)
893 SbxObject
* SbClassFactory::CreateObject( const OUString
& rClassName
)
895 SbxObjectRef xToUseClassModules
= xClassModules
;
897 if( SbModule
* pMod
= GetSbData()->pMod
)
899 if( StarBASIC
* pDocBasic
= lclGetDocBasicForModule( pMod
) )
901 if( const DocBasicItem
* pDocBasicItem
= lclFindDocBasicItem( pDocBasic
) )
903 xToUseClassModules
= pDocBasicItem
->getClassModules();
907 SbxVariable
* pVar
= xToUseClassModules
->Find( rClassName
, SbxCLASS_OBJECT
);
908 SbxObject
* pRet
= NULL
;
911 SbModule
* pVarMod
= static_cast<SbModule
*>(pVar
);
912 pRet
= new SbClassModuleObject( pVarMod
);
917 SbModule
* SbClassFactory::FindClass( const OUString
& rClassName
)
919 SbxVariable
* pVar
= xClassModules
->Find( rClassName
, SbxCLASS_DONTCARE
);
920 SbModule
* pMod
= pVar
? static_cast<SbModule
*>(pVar
) : NULL
;
924 StarBASIC::StarBASIC( StarBASIC
* p
, bool bIsDocBasic
)
925 : SbxObject( OUString("StarBASIC") ), bDocBasic( bIsDocBasic
)
929 bNoRtl
= bBreak
= false;
931 pModules
= new SbxArray
;
933 if( !GetSbData()->nInst
++ )
935 GetSbData()->pSbFac
= new SbiFactory
;
936 AddFactory( GetSbData()->pSbFac
);
937 GetSbData()->pTypeFac
= new SbTypeFactory
;
938 AddFactory( GetSbData()->pTypeFac
);
939 GetSbData()->pClassFac
= new SbClassFactory
;
940 AddFactory( GetSbData()->pClassFac
);
941 GetSbData()->pOLEFac
= new SbOLEFactory
;
942 AddFactory( GetSbData()->pOLEFac
);
943 GetSbData()->pFormFac
= new SbFormFactory
;
944 AddFactory( GetSbData()->pFormFac
);
945 GetSbData()->pUnoFac
= new SbUnoFactory
;
946 AddFactory( GetSbData()->pUnoFac
);
948 pRtl
= new SbiStdObject(OUString(RTLNAME
), this );
949 // Search via StarBasic is always global
950 SetFlag( SBX_GBLSEARCH
);
956 lclInsertDocBasicItem( *this );
960 // #51727 Override SetModified so that the modified state
961 // is not given to the parent
962 void StarBASIC::SetModified( bool b
)
964 SbxBase::SetModified( b
);
967 StarBASIC::~StarBASIC()
969 // Needs to be first action as it can trigger events
970 disposeComVariablesForBasic( this );
972 if( !--GetSbData()->nInst
)
974 RemoveFactory( GetSbData()->pSbFac
);
975 delete GetSbData()->pSbFac
; GetSbData()->pSbFac
= NULL
;
976 RemoveFactory( GetSbData()->pUnoFac
);
977 delete GetSbData()->pUnoFac
; GetSbData()->pUnoFac
= NULL
;
978 RemoveFactory( GetSbData()->pTypeFac
);
979 delete GetSbData()->pTypeFac
; GetSbData()->pTypeFac
= NULL
;
980 RemoveFactory( GetSbData()->pClassFac
);
981 delete GetSbData()->pClassFac
; GetSbData()->pClassFac
= NULL
;
982 RemoveFactory( GetSbData()->pOLEFac
);
983 delete GetSbData()->pOLEFac
; GetSbData()->pOLEFac
= NULL
;
984 RemoveFactory( GetSbData()->pFormFac
);
985 delete GetSbData()->pFormFac
; GetSbData()->pFormFac
= NULL
;
987 if( SbiGlobals::pGlobals
)
989 delete SbiGlobals::pGlobals
;
990 SbiGlobals::pGlobals
= 0;
995 SbxError eOld
= SbxBase::GetError();
997 lclRemoveDocBasicItem( *this );
999 SbxBase::ResetError();
1000 if( eOld
!= SbxERR_OK
)
1002 SbxBase::SetError( eOld
);
1006 // #100326 Set Parent NULL in registered listeners
1007 if( xUnoListeners
.Is() )
1009 sal_uInt16 uCount
= xUnoListeners
->Count();
1010 for( sal_uInt16 i
= 0 ; i
< uCount
; i
++ )
1012 SbxVariable
* pListenerObj
= xUnoListeners
->Get( i
);
1013 pListenerObj
->SetParent( NULL
);
1015 xUnoListeners
= NULL
;
1018 clearUnoMethodsForBasic( this );
1021 // Override new() operator, so that everyone can create a new instance
1022 void* StarBASIC::operator new( size_t n
)
1024 if( n
< sizeof( StarBASIC
) )
1026 n
= sizeof( StarBASIC
);
1028 return ::operator new( n
);
1031 void StarBASIC::operator delete( void* p
)
1033 ::operator delete( p
);
1036 void StarBASIC::implClearDependingVarsOnDelete( StarBASIC
* pDeletedBasic
)
1038 if( this != pDeletedBasic
)
1040 for( sal_uInt16 i
= 0; i
< pModules
->Count(); i
++ )
1042 SbModule
* p
= static_cast<SbModule
*>(pModules
->Get( i
));
1043 p
->ClearVarsDependingOnDeletedBasic( pDeletedBasic
);
1047 for( sal_uInt16 nObj
= 0; nObj
< pObjs
->Count(); nObj
++ )
1049 SbxVariable
* pVar
= pObjs
->Get( nObj
);
1050 StarBASIC
* pBasic
= PTR_CAST(StarBASIC
,pVar
);
1051 if( pBasic
&& pBasic
!= pDeletedBasic
)
1053 pBasic
->implClearDependingVarsOnDelete( pDeletedBasic
);
1059 /**************************************************************************
1061 * Creation/Management of modules
1063 **************************************************************************/
1065 SbModule
* StarBASIC::MakeModule( const OUString
& rName
, const OUString
& rSrc
)
1067 return MakeModule32( rName
, rSrc
);
1070 SbModule
* StarBASIC::MakeModule32( const OUString
& rName
, const OUString
& rSrc
)
1073 mInfo
.ModuleType
= ModuleType::NORMAL
;
1074 return MakeModule32( rName
, mInfo
, rSrc
);
1076 SbModule
* StarBASIC::MakeModule32( const OUString
& rName
, const ModuleInfo
& mInfo
, const OUString
& rSrc
)
1081 "create module " << rName
<< " type mInfo " << mInfo
.ModuleType
);
1083 switch ( mInfo
.ModuleType
)
1085 case ModuleType::DOCUMENT
:
1086 // In theory we should be able to create Object modules
1087 // in ordinary basic ( in vba mode thought these are create
1088 // by the application/basic and not by the user )
1089 p
= new SbObjModule( rName
, mInfo
, isVBAEnabled() );
1091 case ModuleType::CLASS
:
1092 p
= new SbModule( rName
, isVBAEnabled() );
1093 p
->SetModuleType( ModuleType::CLASS
);
1095 case ModuleType::FORM
:
1096 p
= new SbUserFormModule( rName
, mInfo
, isVBAEnabled() );
1099 p
= new SbModule( rName
, isVBAEnabled() );
1102 p
->SetSource32( rSrc
);
1103 p
->SetParent( this );
1104 pModules
->Insert( p
, pModules
->Count() );
1105 SetModified( true );
1109 void StarBASIC::Insert( SbxVariable
* pVar
)
1111 if( pVar
->IsA( TYPE(SbModule
) ) )
1113 pModules
->Insert( pVar
, pModules
->Count() );
1114 pVar
->SetParent( this );
1115 StartListening( pVar
->GetBroadcaster(), true );
1119 bool bWasModified
= IsModified();
1120 SbxObject::Insert( pVar
);
1121 if( !bWasModified
&& pVar
->IsSet( SBX_DONTSTORE
) )
1123 SetModified( false );
1128 void StarBASIC::Remove( SbxVariable
* pVar
)
1130 if( pVar
->IsA( TYPE(SbModule
) ) )
1132 // #87540 Can be last reference!
1133 SbxVariableRef xVar
= pVar
;
1134 pModules
->Remove( pVar
);
1135 pVar
->SetParent( 0 );
1136 EndListening( pVar
->GetBroadcaster() );
1140 SbxObject::Remove( pVar
);
1144 bool StarBASIC::Compile( SbModule
* pMod
)
1146 return pMod
&& pMod
->Compile();
1149 void StarBASIC::Clear()
1151 while( pModules
->Count() )
1153 pModules
->Remove( pModules
->Count() - 1 );
1157 SbModule
* StarBASIC::FindModule( const OUString
& rName
)
1159 for( sal_uInt16 i
= 0; i
< pModules
->Count(); i
++ )
1161 SbModule
* p
= static_cast<SbModule
*>( pModules
->Get( i
) );
1162 if( p
->GetName().equalsIgnoreAsciiCase( rName
) )
1171 struct ClassModuleRunInitItem
1173 SbModule
* m_pModule
;
1175 bool m_bRunInitDone
;
1177 ClassModuleRunInitItem()
1179 , m_bProcessing( false )
1180 , m_bRunInitDone( false )
1182 ClassModuleRunInitItem( SbModule
* pModule
)
1183 : m_pModule( pModule
)
1184 , m_bProcessing( false )
1185 , m_bRunInitDone( false )
1189 // Derive from unordered_map type instead of typedef
1190 // to allow forward declaration in sbmod.hxx
1191 class ModuleInitDependencyMap
: public
1192 std::unordered_map
< OUString
, ClassModuleRunInitItem
,
1193 OUStringHash
, ::std::equal_to
< OUString
> >
1196 void SbModule::implProcessModuleRunInit( ModuleInitDependencyMap
& rMap
, ClassModuleRunInitItem
& rItem
)
1198 rItem
.m_bProcessing
= true;
1200 SbModule
* pModule
= rItem
.m_pModule
;
1201 if( pModule
->pClassData
!= NULL
)
1203 StringVector
& rReqTypes
= pModule
->pClassData
->maRequiredTypes
;
1204 if( rReqTypes
.size() > 0 )
1206 for( StringVector::iterator it
= rReqTypes
.begin() ; it
!= rReqTypes
.end() ; ++it
)
1208 OUString
& rStr
= *it
;
1210 // Is required type a class module?
1211 ModuleInitDependencyMap::iterator itFind
= rMap
.find( rStr
);
1212 if( itFind
!= rMap
.end() )
1214 ClassModuleRunInitItem
& rParentItem
= itFind
->second
;
1215 if( rParentItem
.m_bProcessing
)
1217 // TODO: raise error?
1218 OSL_FAIL( "Cyclic module dependency detected" );
1222 if( !rParentItem
.m_bRunInitDone
)
1224 implProcessModuleRunInit( rMap
, rParentItem
);
1232 rItem
.m_bRunInitDone
= true;
1233 rItem
.m_bProcessing
= false;
1236 // Run Init-Code of all modules (including inserted libraries)
1237 void StarBASIC::InitAllModules( StarBASIC
* pBasicNotToInit
)
1239 SolarMutexGuard guard
;
1242 for ( sal_uInt16 nMod
= 0; nMod
< pModules
->Count(); nMod
++ )
1244 SbModule
* pModule
= static_cast<SbModule
*>( pModules
->Get( nMod
) );
1245 if( !pModule
->IsCompiled() )
1250 // compile modules first then RunInit ( otherwise there is
1251 // can be order dependency, e.g. classmodule A has a member
1252 // of type classmodule B and classmodule B hasn't been compiled yet )
1254 // Consider required types to init in right order. Class modules
1255 // that are required by other modules have to be initialized first.
1256 ModuleInitDependencyMap aMIDMap
;
1257 for ( sal_uInt16 nMod
= 0; nMod
< pModules
->Count(); nMod
++ )
1259 SbModule
* pModule
= static_cast<SbModule
*>(pModules
->Get( nMod
));
1260 OUString aModuleName
= pModule
->GetName();
1261 if( pModule
->isProxyModule() )
1263 aMIDMap
[aModuleName
] = ClassModuleRunInitItem( pModule
);
1267 ModuleInitDependencyMap::iterator it
;
1268 for( it
= aMIDMap
.begin() ; it
!= aMIDMap
.end(); ++it
)
1270 ClassModuleRunInitItem
& rItem
= it
->second
;
1271 SbModule::implProcessModuleRunInit( aMIDMap
, rItem
);
1274 // Call RunInit on standard modules
1275 for ( sal_uInt16 nMod
= 0; nMod
< pModules
->Count(); nMod
++ )
1277 SbModule
* pModule
= static_cast<SbModule
*>(pModules
->Get( nMod
));
1278 if( !pModule
->isProxyModule() )
1284 // Check all objects if they are BASIC,
1285 // if yes initialize
1286 for ( sal_uInt16 nObj
= 0; nObj
< pObjs
->Count(); nObj
++ )
1288 SbxVariable
* pVar
= pObjs
->Get( nObj
);
1289 StarBASIC
* pBasic
= PTR_CAST(StarBASIC
,pVar
);
1290 if( pBasic
&& pBasic
!= pBasicNotToInit
)
1292 pBasic
->InitAllModules();
1297 // #88329 Put modules back to not initialised state to
1298 // force reinitialisation at next start
1299 void StarBASIC::DeInitAllModules()
1301 // Deinit own modules
1302 for ( sal_uInt16 nMod
= 0; nMod
< pModules
->Count(); nMod
++ )
1304 SbModule
* pModule
= static_cast<SbModule
*>(pModules
->Get( nMod
));
1305 if( pModule
->pImage
&& !pModule
->isProxyModule() && !pModule
->ISA(SbObjModule
) )
1307 pModule
->pImage
->bInit
= false;
1311 for ( sal_uInt16 nObj
= 0; nObj
< pObjs
->Count(); nObj
++ )
1313 SbxVariable
* pVar
= pObjs
->Get( nObj
);
1314 StarBASIC
* pBasic
= PTR_CAST(StarBASIC
,pVar
);
1317 pBasic
->DeInitAllModules();
1322 // This implementation at first searches within the runtime library,
1323 // then it looks for an element within one module. This moudle can be
1324 // a public var or an entrypoint. If it is not found and we look for a
1325 // method and a module with the given name is found the search continues
1326 // for entrypoint "Main".
1327 // If this fails again a conventional search over objects is performend.
1328 SbxVariable
* StarBASIC::Find( const OUString
& rName
, SbxClassType t
)
1330 SbxVariable
* pRes
= NULL
;
1331 SbModule
* pNamed
= NULL
;
1332 // "Extended" search in Runtime Lib
1333 // but only if SbiRuntime has not set the flag
1336 if( t
== SbxCLASS_DONTCARE
|| t
== SbxCLASS_OBJECT
)
1338 if( rName
.equalsIgnoreAsciiCase( RTLNAME
) )
1345 pRes
= static_cast<SbiStdObject
*>((SbxObject
*) pRtl
)->Find( rName
, t
);
1349 pRes
->SetFlag( SBX_EXTFOUND
);
1355 for( sal_uInt16 i
= 0; i
< pModules
->Count(); i
++ )
1357 SbModule
* p
= static_cast<SbModule
*>( pModules
->Get( i
) );
1358 if( p
->IsVisible() )
1360 // Remember modul fpr Main() call
1361 // or is the name equal?!?
1362 if( p
->GetName().equalsIgnoreAsciiCase( rName
) )
1364 if( t
== SbxCLASS_OBJECT
|| t
== SbxCLASS_DONTCARE
)
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
)
1377 // otherwise check if the element is available
1378 // unset GBLSEARCH-Flag (due to Rekursion)
1379 SbxFlagBits nGblFlag
= p
->GetFlags() & SBX_GBLSEARCH
;
1380 p
->ResetFlag( SBX_GBLSEARCH
);
1381 pRes
= p
->Find( rName
, t
);
1382 p
->SetFlag( nGblFlag
);
1390 OUString
aMainStr("Main");
1391 if( !pRes
&& pNamed
&& ( t
== SbxCLASS_METHOD
|| t
== SbxCLASS_DONTCARE
) &&
1392 !pNamed
->GetName().equalsIgnoreAsciiCase( aMainStr
) )
1394 pRes
= pNamed
->Find( aMainStr
, SbxCLASS_METHOD
);
1398 pRes
= SbxObject::Find( rName
, t
);
1403 bool StarBASIC::Call( const OUString
& rName
, SbxArray
* pParam
)
1405 bool bRes
= SbxObject::Call( rName
, pParam
);
1408 SbxError eErr
= SbxBase::GetError();
1409 SbxBase::ResetError();
1410 if( eErr
!= SbxERR_OK
)
1412 RTError( (SbError
)eErr
, 0, 0, 0 );
1418 // Find method via name (e.g. query via BASIC IDE)
1419 SbxBase
* StarBASIC::FindSBXInCurrentScope( const OUString
& rName
)
1421 if( !GetSbData()->pInst
)
1425 if( !GetSbData()->pInst
->pRun
)
1429 return GetSbData()->pInst
->pRun
->FindElementExtern( rName
);
1432 void StarBASIC::QuitAndExitApplication()
1438 void StarBASIC::Stop()
1440 SbiInstance
* p
= GetSbData()->pInst
;
1448 bool StarBASIC::IsRunning()
1450 return GetSbData()->pInst
!= NULL
;
1453 /**************************************************************************
1455 * Debugging and error handling
1457 **************************************************************************/
1459 SbMethod
* StarBASIC::GetActiveMethod( sal_uInt16 nLevel
)
1461 if( GetSbData()->pInst
)
1463 return GetSbData()->pInst
->GetCaller( nLevel
);
1471 SbModule
* StarBASIC::GetActiveModule()
1473 if( GetSbData()->pInst
&& !IsCompilerError() )
1475 return GetSbData()->pInst
->GetActiveModule();
1479 return GetSbData()->pCompMod
;
1483 sal_uInt16
StarBASIC::BreakPoint( sal_Int32 l
, sal_Int32 c1
, sal_Int32 c2
)
1485 SetErrorData( 0, l
, c1
, c2
);
1487 if( GetSbData()->aBreakHdl
.IsSet() )
1489 return GetSbData()->aBreakHdl
.Call( this );
1497 sal_uInt16
StarBASIC::StepPoint( sal_Int32 l
, sal_Int32 c1
, sal_Int32 c2
)
1499 SetErrorData( 0, l
, c1
, c2
);
1501 if( GetSbData()->aBreakHdl
.IsSet() )
1503 return GetSbData()->aBreakHdl
.Call( this );
1511 sal_uInt16
StarBASIC::BreakHdl()
1513 return aBreakHdl
.IsSet() ? aBreakHdl
.Call( this ) : SbDEBUG_CONTINUE
;
1516 // Calls for error handler and break handler
1517 sal_uInt16
StarBASIC::GetLine() { return GetSbData()->nLine
; }
1518 sal_uInt16
StarBASIC::GetCol1() { return GetSbData()->nCol1
; }
1519 sal_uInt16
StarBASIC::GetCol2() { return GetSbData()->nCol2
; }
1521 // Specific to error handler
1522 SbError
StarBASIC::GetErrorCode() { return GetSbData()->nCode
; }
1523 const OUString
& StarBASIC::GetErrorText() { return GetSbData()->aErrMsg
; }
1524 bool StarBASIC::IsCompilerError() { return GetSbData()->bCompiler
; }
1527 // The mapping between the old and the new error codes take place by searching
1528 // through the table SFX_VB_ErrorTab[]. This is indeed not with good performance,
1529 // but it consumes much less memory than corresponding switch blocs.
1530 // Because the conversion of error codes has not to be fast. there is no
1531 // binary search by VB Error -> Error SFX.
1533 // Map back new error codes to old, Sbx-compatible
1534 sal_uInt16
StarBASIC::GetVBErrorCode( SbError nError
)
1536 sal_uInt16 nRet
= 0;
1538 if( SbiRuntime::isVBAEnabled() )
1542 case SbERR_BASIC_ARRAY_FIX
:
1544 case SbERR_BASIC_STRING_OVERFLOW
:
1546 case SbERR_BASIC_EXPR_TOO_COMPLEX
:
1548 case SbERR_BASIC_OPER_NOT_PERFORM
:
1550 case SbERR_BASIC_TOO_MANY_DLL
:
1552 case SbERR_BASIC_LOOP_NOT_INIT
:
1560 const SFX_VB_ErrorItem
* pErrItem
;
1561 sal_uInt16 nIndex
= 0;
1564 pErrItem
= SFX_VB_ErrorTab
+ nIndex
;
1565 if( pErrItem
->nErrorSFX
== nError
)
1567 nRet
= pErrItem
->nErrorVB
;
1572 while( pErrItem
->nErrorVB
!= 0xFFFF ); // up to end mark
1576 SbError
StarBASIC::GetSfxFromVBError( sal_uInt16 nError
)
1580 if( SbiRuntime::isVBAEnabled() )
1592 return SbERR_BASIC_ARRAY_FIX
;
1594 return SbERR_BASIC_STRING_OVERFLOW
;
1596 return SbERR_BASIC_EXPR_TOO_COMPLEX
;
1598 return SbERR_BASIC_OPER_NOT_PERFORM
;
1600 return SbERR_BASIC_TOO_MANY_DLL
;
1602 return SbERR_BASIC_LOOP_NOT_INIT
;
1607 const SFX_VB_ErrorItem
* pErrItem
;
1608 sal_uInt16 nIndex
= 0;
1611 pErrItem
= SFX_VB_ErrorTab
+ nIndex
;
1612 if( pErrItem
->nErrorVB
== nError
)
1614 nRet
= pErrItem
->nErrorSFX
;
1617 else if( pErrItem
->nErrorVB
> nError
)
1619 break; // couldn't found anymore
1623 while( pErrItem
->nErrorVB
!= 0xFFFF ); // up to end mark
1627 // set Error- / Break-data
1628 void StarBASIC::SetErrorData( SbError nCode
, sal_uInt16 nLine
,
1629 sal_uInt16 nCol1
, sal_uInt16 nCol2
)
1631 SbiGlobals
& aGlobals
= *GetSbData();
1632 aGlobals
.nCode
= nCode
;
1633 aGlobals
.nLine
= nLine
;
1634 aGlobals
.nCol1
= nCol1
;
1635 aGlobals
.nCol2
= nCol2
;
1639 // help class for access to string SubResource of a Resource.
1640 // Source: sfx2\source\doc\docfile.cxx (TLX)
1641 struct BasicStringList_Impl
: private Resource
1645 BasicStringList_Impl( ResId
& rErrIdP
, sal_uInt16 nId
)
1646 : Resource( rErrIdP
),aResId(nId
, *rErrIdP
.GetResMgr() ){}
1647 ~BasicStringList_Impl() { FreeResource(); }
1649 OUString
GetString(){ return aResId
.toString(); }
1650 bool IsErrorTextAvailable()
1651 { return IsAvailableRes(aResId
.SetRT(RSC_STRING
)); }
1655 void StarBASIC::MakeErrorText( SbError nId
, const OUString
& aMsg
)
1657 SolarMutexGuard aSolarGuard
;
1658 sal_uInt16 nOldID
= GetVBErrorCode( nId
);
1660 // intantiate the help class
1661 BasResId
aId( RID_BASIC_START
);
1662 BasicStringList_Impl
aMyStringList( aId
, sal_uInt16(nId
& ERRCODE_RES_MASK
) );
1664 if( aMyStringList
.IsErrorTextAvailable() )
1666 // merge message with additional text
1667 OUStringBuffer
aMsg1(aMyStringList
.GetString());
1668 // replace argument placeholder with %s
1669 OUString
aSrgStr( "$(ARG1)" );
1670 sal_Int32 nResult
= aMyStringList
.GetString().indexOf( aSrgStr
);
1674 aMsg1
.remove(nResult
, aSrgStr
.getLength());
1675 aMsg1
.insert(nResult
, aMsg
);
1677 GetSbData()->aErrMsg
= aMsg1
.makeStringAndClear();
1679 else if( nOldID
!= 0 )
1681 OUString aStdMsg
= "Fehler " + OUString::number(nOldID
) +
1682 ": Kein Fehlertext verfuegbar!";
1683 GetSbData()->aErrMsg
= aStdMsg
;
1687 GetSbData()->aErrMsg
.clear();
1691 bool StarBASIC::CError( SbError code
, const OUString
& rMsg
,
1692 sal_Int32 l
, sal_Int32 c1
, sal_Int32 c2
)
1694 SolarMutexGuard aSolarGuard
;
1696 // compiler error during runtime -> stop programm
1699 // #109018 Check if running Basic is affected
1700 StarBASIC
* pStartedBasic
= GetSbData()->pInst
->GetBasic();
1701 if( pStartedBasic
!= this )
1708 // set flag, so that GlobalRunInit notice the error
1709 GetSbData()->bGlobalInitErr
= true;
1711 // tinker the error message
1712 MakeErrorText( code
, rMsg
);
1714 // Implementation of the code for the string transport to SFX-Error
1715 if( !rMsg
.isEmpty() )
1717 code
= (sal_uIntPtr
)*new StringErrorInfo( code
, rMsg
);
1719 SetErrorData( code
, l
, c1
, c2
);
1720 GetSbData()->bCompiler
= true;
1722 if( GetSbData()->aErrHdl
.IsSet() )
1724 bRet
= GetSbData()->aErrHdl
.Call( this );
1730 GetSbData()->bCompiler
= false; // only true for error handler
1734 bool StarBASIC::RTError( SbError code
, sal_Int32 l
, sal_Int32 c1
, sal_Int32 c2
)
1736 return RTError( code
, OUString(), l
, c1
, c2
);
1739 bool StarBASIC::RTError( SbError code
, const OUString
& rMsg
, sal_Int32 l
, sal_Int32 c1
, sal_Int32 c2
)
1741 SolarMutexGuard aSolarGuard
;
1744 if( (c
& ERRCODE_CLASS_MASK
) == ERRCODE_CLASS_COMPILER
)
1748 MakeErrorText( c
, rMsg
);
1750 // Implementation of the code for the string transport to SFX-Error
1751 if( !rMsg
.isEmpty() )
1753 // very confusing, even though MakeErrorText sets up the error text
1754 // seems that this is not used ( if rMsg already has content )
1755 // In the case of VBA MakeErrorText also formats the error to be alittle more
1756 // like vba ( adds an error number etc )
1757 if ( SbiRuntime::isVBAEnabled() && ( code
== SbERR_BASIC_COMPAT
) )
1759 OUString aTmp
= "\'" + OUString::number(SbxErrObject::getUnoErrObject()->getNumber()) +
1760 "\'\n" + OUString(!GetSbData()->aErrMsg
.isEmpty() ? GetSbData()->aErrMsg
: rMsg
);
1761 code
= (sal_uIntPtr
)*new StringErrorInfo( code
, aTmp
);
1765 code
= (sal_uIntPtr
)*new StringErrorInfo( code
, rMsg
);
1769 SetErrorData( code
, l
, c1
, c2
);
1770 if( GetSbData()->aErrHdl
.IsSet() )
1772 return GetSbData()->aErrHdl
.Call( this );
1780 void StarBASIC::Error( SbError n
)
1782 Error( n
, OUString() );
1785 void StarBASIC::Error( SbError n
, const OUString
& rMsg
)
1787 if( GetSbData()->pInst
)
1789 GetSbData()->pInst
->Error( n
, rMsg
);
1793 void StarBASIC::FatalError( SbError n
)
1795 if( GetSbData()->pInst
)
1797 GetSbData()->pInst
->FatalError( n
);
1801 void StarBASIC::FatalError( SbError _errCode
, const OUString
& _details
)
1803 if( GetSbData()->pInst
)
1805 GetSbData()->pInst
->FatalError( _errCode
, _details
);
1809 SbError
StarBASIC::GetErrBasic()
1811 if( GetSbData()->pInst
)
1813 return GetSbData()->pInst
->GetErr();
1821 // make the additional message for the RTL function error accessible
1822 OUString
StarBASIC::GetErrorMsg()
1824 if( GetSbData()->pInst
)
1826 return GetSbData()->pInst
->GetErrorMsg();
1834 sal_Int32
StarBASIC::GetErl()
1836 if( GetSbData()->pInst
)
1838 return GetSbData()->pInst
->GetErl();
1846 bool StarBASIC::ErrorHdl()
1848 return aErrorHdl
.IsSet() && aErrorHdl
.Call( this );
1851 Link
<StarBASIC
*,bool> StarBASIC::GetGlobalErrorHdl()
1853 return GetSbData()->aErrHdl
;
1856 void StarBASIC::SetGlobalErrorHdl( const Link
<StarBASIC
*,bool>& rLink
)
1858 GetSbData()->aErrHdl
= rLink
;
1861 void StarBASIC::SetGlobalBreakHdl( const Link
<StarBASIC
*,sal_uInt16
>& rLink
)
1863 GetSbData()->aBreakHdl
= rLink
;
1866 SbxArrayRef
StarBASIC::getUnoListeners()
1868 if( !xUnoListeners
.Is() )
1870 xUnoListeners
= new SbxArray();
1872 return xUnoListeners
;
1876 /**************************************************************************
1880 **************************************************************************/
1882 bool StarBASIC::LoadData( SvStream
& r
, sal_uInt16 nVer
)
1884 if( !SbxObject::LoadData( r
, nVer
) )
1888 // #95459 Delete dialogs, otherwise endless recursion
1889 // in SbxVarable::GetType() if dialogs are accessed
1890 sal_uInt16 nObjCount
= pObjs
->Count();
1891 boost::scoped_array
<SbxVariable
*> ppDeleteTab(new SbxVariable
*[ nObjCount
]);
1894 for( nObj
= 0 ; nObj
< nObjCount
; nObj
++ )
1896 SbxVariable
* pVar
= pObjs
->Get( nObj
);
1897 StarBASIC
* pBasic
= PTR_CAST( StarBASIC
, pVar
);
1898 ppDeleteTab
[nObj
] = pBasic
? NULL
: pVar
;
1900 for( nObj
= 0 ; nObj
< nObjCount
; nObj
++ )
1902 SbxVariable
* pVar
= ppDeleteTab
[nObj
];
1905 pObjs
->Remove( pVar
);
1908 ppDeleteTab
.reset();
1912 r
.ReadUInt16( nMod
);
1913 const size_t nMinSbxSize(14);
1914 const size_t nMaxPossibleEntries
= r
.remainingSize() / nMinSbxSize
;
1915 if (nMod
> nMaxPossibleEntries
)
1917 nMod
= nMaxPossibleEntries
;
1918 SAL_WARN("basic", "Parsing error: " << nMaxPossibleEntries
<<
1919 " max possible entries, but " << nMod
<< " claimed, truncating");
1921 for (sal_uInt16 i
= 0; i
< nMod
; ++i
)
1923 SbxBase
* pBase
= SbxBase::Load( r
);
1924 SbModule
* pMod
= dynamic_cast<SbModule
*>(pBase
);
1929 else if( pMod
->ISA(SbJScriptModule
) )
1931 // assign Ref, so that pMod will be deleted
1932 SbModuleRef xRef
= pMod
;
1936 pMod
->SetParent( this );
1937 pModules
->Put( pMod
, i
);
1940 // HACK for SFX-Bullshit!
1941 SbxVariable
* p
= Find( OUString("FALSE"), SbxCLASS_PROPERTY
);
1946 p
= Find( OUString("TRUE"), SbxCLASS_PROPERTY
);
1951 // End of the hacks!
1952 // Search via StarBASIC is at all times global
1953 DBG_ASSERT( IsSet( SBX_GBLSEARCH
), "Basic loaded without GBLSEARCH" );
1954 SetFlag( SBX_GBLSEARCH
);
1958 bool StarBASIC::StoreData( SvStream
& r
) const
1960 if( !SbxObject::StoreData( r
) )
1964 r
.WriteUInt16( pModules
->Count() );
1965 for( sal_uInt16 i
= 0; i
< pModules
->Count(); i
++ )
1967 SbModule
* p
= static_cast<SbModule
*>( pModules
->Get( i
) );
1968 if( !p
->Store( r
) )
1976 bool StarBASIC::GetUNOConstant( const sal_Char
* _pAsciiName
, ::com::sun::star::uno::Any
& aOut
)
1979 OUString
sVarName( OUString::createFromAscii( _pAsciiName
) );
1980 SbUnoObject
* pGlobs
= dynamic_cast<SbUnoObject
*>( Find( sVarName
, SbxCLASS_DONTCARE
) );
1983 aOut
= pGlobs
->getUnoAny();
1989 Reference
< frame::XModel
> StarBASIC::GetModelFromBasic( SbxObject
* pBasic
)
1991 OSL_PRECOND( pBasic
!= NULL
, "getModelFromBasic: illegal call!" );
1996 // look for the ThisComponent variable, first in the parent (which
1997 // might be the document's Basic), then in the parent's parent (which might be
1998 // the application Basic)
1999 const OUString
sThisComponent( "ThisComponent");
2000 SbxVariable
* pThisComponent
= NULL
;
2002 SbxObject
* pLookup
= pBasic
->GetParent();
2003 while ( pLookup
&& !pThisComponent
)
2005 pThisComponent
= pLookup
->Find( sThisComponent
, SbxCLASS_OBJECT
);
2006 pLookup
= pLookup
->GetParent();
2008 if ( !pThisComponent
)
2010 OSL_TRACE("Failed to get ThisComponent");
2011 // the application Basic, at the latest, should have this variable
2015 Any
aThisComponentAny( sbxToUnoValue( pThisComponent
) );
2016 Reference
< frame::XModel
> xModel( aThisComponentAny
, UNO_QUERY
);
2019 // it's no XModel. Okay, ThisComponent nowadays is allowed to be a controller.
2020 Reference
< frame::XController
> xController( aThisComponentAny
, UNO_QUERY
);
2021 if ( xController
.is() )
2023 xModel
= xController
->getModel();
2030 #if OSL_DEBUG_LEVEL > 0
2031 OSL_TRACE("Have model ThisComponent points to url %s",
2032 OUStringToOString( xModel
->getURL(),
2033 RTL_TEXTENCODING_ASCII_US
).pData
->buffer
);
2039 void StarBASIC::DetachAllDocBasicItems()
2041 DocBasicItemMap
& rItems
= GaDocBasicItems::get();
2042 DocBasicItemMap::iterator it
= rItems
.begin(), itEnd
= rItems
.end();
2043 for (; it
!= itEnd
; ++it
)
2045 DocBasicItemRef xItem
= it
->second
;
2046 xItem
->setDisposed(true);
2050 // #118116 Implementation Collection object
2052 TYPEINIT1(BasicCollection
,SbxObject
)
2054 static const char pCountStr
[] = "Count";
2055 static const char pAddStr
[] = "Add";
2056 static const char pItemStr
[] = "Item";
2057 static const char pRemoveStr
[] = "Remove";
2058 static sal_uInt16 nCountHash
= 0, nAddHash
, nItemHash
, nRemoveHash
;
2060 SbxInfoRef
BasicCollection::xAddInfo
= NULL
;
2061 SbxInfoRef
BasicCollection::xItemInfo
= NULL
;
2063 BasicCollection::BasicCollection( const OUString
& rClass
)
2064 : SbxObject( rClass
)
2068 nCountHash
= MakeHashCode( pCountStr
);
2069 nAddHash
= MakeHashCode( pAddStr
);
2070 nItemHash
= MakeHashCode( pItemStr
);
2071 nRemoveHash
= MakeHashCode( pRemoveStr
);
2077 BasicCollection::~BasicCollection()
2080 void BasicCollection::Clear()
2086 void BasicCollection::Initialize()
2088 xItemArray
= new SbxArray();
2089 SetType( SbxOBJECT
);
2090 SetFlag( SBX_FIXED
);
2091 ResetFlag( SBX_WRITE
);
2093 p
= Make( pCountStr
, SbxCLASS_PROPERTY
, SbxINTEGER
);
2094 p
->ResetFlag( SBX_WRITE
);
2095 p
->SetFlag( SBX_DONTSTORE
);
2096 p
= Make( pAddStr
, SbxCLASS_METHOD
, SbxEMPTY
);
2097 p
->SetFlag( SBX_DONTSTORE
);
2098 p
= Make( pItemStr
, SbxCLASS_METHOD
, SbxVARIANT
);
2099 p
->SetFlag( SBX_DONTSTORE
);
2100 p
= Make( pRemoveStr
, SbxCLASS_METHOD
, SbxEMPTY
);
2101 p
->SetFlag( SBX_DONTSTORE
);
2102 if ( !xAddInfo
.Is() )
2104 xAddInfo
= new SbxInfo
;
2105 xAddInfo
->AddParam( OUString( "Item" ), SbxVARIANT
, SBX_READ
);
2106 xAddInfo
->AddParam( OUString( "Key" ), SbxVARIANT
, SBX_READ
| SBX_OPTIONAL
);
2107 xAddInfo
->AddParam( OUString( "Before" ), SbxVARIANT
, SBX_READ
| SBX_OPTIONAL
);
2108 xAddInfo
->AddParam( OUString( "After" ), SbxVARIANT
, SBX_READ
| SBX_OPTIONAL
);
2110 if ( !xItemInfo
.Is() )
2112 xItemInfo
= new SbxInfo
;
2113 xItemInfo
->AddParam( OUString( "Index" ), SbxVARIANT
, SBX_READ
| SBX_OPTIONAL
);
2117 SbxVariable
* BasicCollection::Find( const OUString
& rName
, SbxClassType t
)
2119 SbxVariable
* pFind
= SbxObject::Find( rName
, t
);
2123 void BasicCollection::SFX_NOTIFY( SfxBroadcaster
& rCst
, const TypeId
& rId1
,
2124 const SfxHint
& rHint
, const TypeId
& rId2
)
2126 const SbxHint
* p
= dynamic_cast<const SbxHint
*>(&rHint
);
2129 sal_uIntPtr nId
= p
->GetId();
2130 bool bRead
= nId
== SBX_HINT_DATAWANTED
;
2131 bool bWrite
= nId
== SBX_HINT_DATACHANGED
;
2132 bool bRequestInfo
= nId
== SBX_HINT_INFOWANTED
;
2133 SbxVariable
* pVar
= p
->GetVar();
2134 SbxArray
* pArg
= pVar
->GetParameters();
2135 OUString
aVarName( pVar
->GetName() );
2136 if( bRead
|| bWrite
)
2138 if( pVar
->GetHashCode() == nCountHash
2139 && aVarName
.equalsIgnoreAsciiCase( pCountStr
) )
2141 pVar
->PutLong( xItemArray
->Count32() );
2143 else if( pVar
->GetHashCode() == nAddHash
2144 && aVarName
.equalsIgnoreAsciiCase( pAddStr
) )
2148 else if( pVar
->GetHashCode() == nItemHash
2149 && aVarName
.equalsIgnoreAsciiCase( pItemStr
) )
2153 else if( pVar
->GetHashCode() == nRemoveHash
2154 && aVarName
.equalsIgnoreAsciiCase( pRemoveStr
) )
2160 SbxObject::SFX_NOTIFY( rCst
, rId1
, rHint
, rId2
);
2164 else if ( bRequestInfo
)
2166 if( pVar
->GetHashCode() == nAddHash
2167 && aVarName
.equalsIgnoreAsciiCase( pAddStr
) )
2169 pVar
->SetInfo( xAddInfo
);
2171 else if( pVar
->GetHashCode() == nItemHash
2172 && aVarName
.equalsIgnoreAsciiCase( pItemStr
) )
2174 pVar
->SetInfo( xItemInfo
);
2178 SbxObject::SFX_NOTIFY( rCst
, rId1
, rHint
, rId2
);
2181 sal_Int32
BasicCollection::implGetIndex( SbxVariable
* pIndexVar
)
2183 sal_Int32 nIndex
= -1;
2184 if( pIndexVar
->GetType() == SbxSTRING
)
2186 nIndex
= implGetIndexForName( pIndexVar
->GetOUString() );
2190 nIndex
= pIndexVar
->GetLong() - 1;
2195 sal_Int32
BasicCollection::implGetIndexForName( const OUString
& rName
)
2197 sal_Int32 nIndex
= -1;
2198 sal_Int32 nCount
= xItemArray
->Count32();
2199 sal_Int32 nNameHash
= MakeHashCode( rName
);
2200 for( sal_Int32 i
= 0 ; i
< nCount
; i
++ )
2202 SbxVariable
* pVar
= xItemArray
->Get32( i
);
2203 if( pVar
->GetHashCode() == nNameHash
&&
2204 pVar
->GetName().equalsIgnoreAsciiCase( rName
) )
2213 void BasicCollection::CollAdd( SbxArray
* pPar_
)
2215 sal_uInt16 nCount
= pPar_
->Count();
2216 if( nCount
< 2 || nCount
> 5 )
2218 SetError( SbxERR_WRONG_ARGS
);
2222 SbxVariable
* pItem
= pPar_
->Get(1);
2228 nNextIndex
= xItemArray
->Count();
2232 SbxVariable
* pBefore
= pPar_
->Get(3);
2235 if( !( pBefore
->IsErr() || ( pBefore
->GetType() == SbxEMPTY
) ) )
2237 SetError( SbERR_BAD_ARGUMENT
);
2240 SbxVariable
* pAfter
= pPar_
->Get(4);
2241 sal_Int32 nAfterIndex
= implGetIndex( pAfter
);
2242 if( nAfterIndex
== -1 )
2244 SetError( SbERR_BAD_ARGUMENT
);
2247 nNextIndex
= nAfterIndex
+ 1;
2249 else // if( nCount == 4 )
2251 sal_Int32 nBeforeIndex
= implGetIndex( pBefore
);
2252 if( nBeforeIndex
== -1 )
2254 SetError( SbERR_BAD_ARGUMENT
);
2257 nNextIndex
= nBeforeIndex
;
2261 SbxVariableRef pNewItem
= new SbxVariable( *pItem
);
2264 SbxVariable
* pKey
= pPar_
->Get(2);
2265 if( !( pKey
->IsErr() || ( pKey
->GetType() == SbxEMPTY
) ) )
2267 if( pKey
->GetType() != SbxSTRING
)
2269 SetError( SbERR_BAD_ARGUMENT
);
2272 OUString aKey
= pKey
->GetOUString();
2273 if( implGetIndexForName( aKey
) != -1 )
2275 SetError( SbERR_BAD_ARGUMENT
);
2278 pNewItem
->SetName( aKey
);
2281 pNewItem
->SetFlag( SBX_READWRITE
);
2282 xItemArray
->Insert32( pNewItem
, nNextIndex
);
2286 SetError( SbERR_BAD_ARGUMENT
);
2291 void BasicCollection::CollItem( SbxArray
* pPar_
)
2293 if( pPar_
->Count() != 2 )
2295 SetError( SbxERR_WRONG_ARGS
);
2298 SbxVariable
* pRes
= NULL
;
2299 SbxVariable
* p
= pPar_
->Get( 1 );
2300 sal_Int32 nIndex
= implGetIndex( p
);
2301 if( nIndex
>= 0 && nIndex
< (sal_Int32
)xItemArray
->Count32() )
2303 pRes
= xItemArray
->Get32( nIndex
);
2307 SetError( SbERR_BAD_ARGUMENT
);
2311 *(pPar_
->Get(0)) = *pRes
;
2315 void BasicCollection::CollRemove( SbxArray
* pPar_
)
2317 if( pPar_
== NULL
|| pPar_
->Count() != 2 )
2319 SetError( SbxERR_WRONG_ARGS
);
2323 SbxVariable
* p
= pPar_
->Get( 1 );
2324 sal_Int32 nIndex
= implGetIndex( p
);
2325 if( nIndex
>= 0 && nIndex
< (sal_Int32
)xItemArray
->Count32() )
2327 xItemArray
->Remove32( nIndex
);
2329 // Correct for stack if necessary
2330 SbiInstance
* pInst
= GetSbData()->pInst
;
2331 SbiRuntime
* pRT
= pInst
? pInst
->pRun
: NULL
;
2334 SbiForStack
* pStack
= pRT
->FindForStackItemForCollection( this );
2335 if( pStack
!= NULL
)
2337 if( pStack
->nCurCollectionIndex
>= nIndex
)
2339 --pStack
->nCurCollectionIndex
;
2346 SetError( SbERR_BAD_ARGUMENT
);
2350 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */