/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_basic.hxx"

#include <stdio.h>

#include "sb.hxx"
#include <tools/rcid.h>
#include <tools/config.hxx>
#include <tools/stream.hxx>
#ifndef __RSC //autogen
#include <tools/errinf.hxx>
#endif
#include <basic/sbx.hxx>
#include <tools/list.hxx>
#include <tools/shl.hxx>
#include <tools/rc.hxx>
#include <vcl/svapp.hxx>
#include <comphelper/processfactory.hxx>
#include "sbunoobj.hxx"
#include "sbjsmeth.hxx"
#include "sbjsmod.hxx"
#include "sbintern.hxx"
#include "disas.hxx"
#include "runtime.hxx"
#include <basic/sbuno.hxx>
#include <basic/sbobjmod.hxx>
#include "stdobj.hxx"
#include "filefmt.hxx"
#include "sb.hrc"
#include <basrid.hxx>
#include <vos/mutex.hxx>
#include <cppuhelper/implbase1.hxx>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/util/XCloseBroadcaster.hpp>
#include <com/sun/star/util/XCloseListener.hpp>
#include "errobject.hxx"
#include <map>
#include <hash_map>

#include <com/sun/star/script/ModuleType.hpp>
#include <com/sun/star/script/ModuleInfo.hpp>
using namespace ::com::sun::star::script;

// #pragma SW_SEGMENT_CLASS( SBASIC, SBASIC_CODE )

SV_IMPL_VARARR(SbTextPortions,SbTextPortion)

#define RTLNAME "@SBRTL"
//  i#i68894#
using namespace ::com::sun::star;
using com::sun::star::uno::Reference;
using com::sun::star::uno::Any;
using com::sun::star::uno::UNO_QUERY;
using com::sun::star::lang::XMultiServiceFactory;

const static String aThisComponent( RTL_CONSTASCII_USTRINGPARAM("ThisComponent") );
const static String aVBAHook( RTL_CONSTASCII_USTRINGPARAM( "VBAGlobals" ) );

// ============================================================================

class DocBasicItem : public ::cppu::WeakImplHelper1< util::XCloseListener >
{
public:
    explicit DocBasicItem( StarBASIC& rDocBasic );
    virtual ~DocBasicItem();

    inline const SbxObjectRef& getClassModules() const { return mxClassModules; }
    inline bool isDocClosed() const { return mbDocClosed; }

	void clearDependingVarsOnDelete( StarBASIC& rDeletedBasic );

    void startListening();
    void stopListening();

    virtual void SAL_CALL queryClosing( const lang::EventObject& rSource, sal_Bool bGetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException);
    virtual void SAL_CALL notifyClosing( const lang::EventObject& rSource ) throw (uno::RuntimeException);
    virtual void SAL_CALL disposing( const lang::EventObject& rSource ) throw (uno::RuntimeException);

private:
    StarBASIC&      mrDocBasic;
    SbxObjectRef    mxClassModules;
    bool            mbDocClosed;
    bool            mbDisposed;
};

// ----------------------------------------------------------------------------

DocBasicItem::DocBasicItem( StarBASIC& rDocBasic ) :
    mrDocBasic( rDocBasic ),
    mxClassModules( new SbxObject( String() ) ),
    mbDocClosed( false ),
    mbDisposed( false )
{
}

DocBasicItem::~DocBasicItem()
{
    stopListening();
}

void DocBasicItem::clearDependingVarsOnDelete( StarBASIC& rDeletedBasic )
{
    mrDocBasic.implClearDependingVarsOnDelete( &rDeletedBasic );
}

void DocBasicItem::startListening()
{
    Any aThisComp;
    mrDocBasic.GetUNOConstant( "ThisComponent", aThisComp );
    Reference< util::XCloseBroadcaster > xCloseBC( aThisComp, UNO_QUERY );
    mbDisposed = !xCloseBC.is();
    if( xCloseBC.is() )
        try { xCloseBC->addCloseListener( this ); } catch( uno::Exception& ) {}
}

void DocBasicItem::stopListening()
{
    if( mbDisposed ) return;
    mbDisposed = true;
    Any aThisComp;
    mrDocBasic.GetUNOConstant( "ThisComponent", aThisComp );
    Reference< util::XCloseBroadcaster > xCloseBC( aThisComp, UNO_QUERY );
    if( xCloseBC.is() )
        try { xCloseBC->removeCloseListener( this ); } catch( uno::Exception& ) {}
}

void SAL_CALL DocBasicItem::queryClosing( const lang::EventObject& /*rSource*/, sal_Bool /*bGetsOwnership*/ ) throw (util::CloseVetoException, uno::RuntimeException)
{
}

void SAL_CALL DocBasicItem::notifyClosing( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException)
{
    stopListening();
    mbDocClosed = true;
}

void SAL_CALL DocBasicItem::disposing( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException)
{
    stopListening();
}

// ----------------------------------------------------------------------------

namespace {

typedef ::rtl::Reference< DocBasicItem > DocBasicItemRef;
typedef std::map< const StarBASIC*, DocBasicItemRef > DocBasicItemMap;
static DocBasicItemMap GaDocBasicItems;

const DocBasicItem* lclFindDocBasicItem( const StarBASIC* pDocBasic )
{
    DocBasicItemMap::iterator it = GaDocBasicItems.find( pDocBasic );
    return (it != GaDocBasicItems.end()) ? it->second.get() : 0;
}

void lclInsertDocBasicItem( StarBASIC& rDocBasic )
{
    DocBasicItemRef& rxDocBasicItem = GaDocBasicItems[ &rDocBasic ];
    rxDocBasicItem.set( new DocBasicItem( rDocBasic ) );
    rxDocBasicItem->startListening();
}

void lclRemoveDocBasicItem( StarBASIC& rDocBasic )
{
    DocBasicItemMap::iterator it = GaDocBasicItems.find( &rDocBasic );
    if( it != GaDocBasicItems.end() )
    {
        it->second->stopListening();
        GaDocBasicItems.erase( it );
    }
    DocBasicItemMap::iterator it_end = GaDocBasicItems.end();
    for( it = GaDocBasicItems.begin(); it != it_end; ++it )
        it->second->clearDependingVarsOnDelete( rDocBasic );
}

StarBASIC* lclGetDocBasicForModule( SbModule* pModule )
{
    StarBASIC* pRetBasic = NULL;
    SbxObject* pCurParent = pModule;
    while( pCurParent->GetParent() != NULL )
    {
        pCurParent = pCurParent->GetParent();
        StarBASIC* pDocBasic = dynamic_cast< StarBASIC* >( pCurParent );
        if( pDocBasic != NULL && pDocBasic->IsDocBasic() )
        {
            pRetBasic = pDocBasic;
            break;
        }
    }
    return pRetBasic;
}

} // namespace

// ============================================================================

SbxObject* StarBASIC::getVBAGlobals( )
{
	if ( !pVBAGlobals )
	{	
		Any aThisDoc;
		if ( GetUNOConstant("ThisComponent", aThisDoc) )
		{
			Reference< XMultiServiceFactory > xDocFac( aThisDoc, UNO_QUERY );
                        if ( xDocFac.is() )
			{
				try
				{
					xDocFac->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAGlobals" ) ) );
				}
				catch( Exception& )
				{
					// Ignore
				}
			}
		}
		pVBAGlobals = (SbUnoObject*)Find( aVBAHook , SbxCLASS_DONTCARE );
	}
	return pVBAGlobals;
}

//  i#i68894#
SbxVariable* StarBASIC::VBAFind( const String& rName, SbxClassType t )
{
	if( rName == aThisComponent )
		return NULL;
	// rename to init globals
	if ( getVBAGlobals( ) )
		return pVBAGlobals->Find( rName, t );
	return NULL;

}
// Create array for conversion SFX <-> VB error code
struct SFX_VB_ErrorItem
{
	sal_uInt16  nErrorVB;
	SbError nErrorSFX;
};

const SFX_VB_ErrorItem __FAR_DATA SFX_VB_ErrorTab[] =
{
	{ 1, SbERR_BASIC_EXCEPTION },  // #87844 Map exception to error code 1
	{ 2, SbERR_SYNTAX },
	{ 3, SbERR_NO_GOSUB },
	{ 4, SbERR_REDO_FROM_START },
	{ 5, SbERR_BAD_ARGUMENT },
	{ 6, SbERR_MATH_OVERFLOW },
	{ 7, SbERR_NO_MEMORY },
	{ 8, SbERR_ALREADY_DIM },
	{ 9, SbERR_OUT_OF_RANGE },
	{ 10, SbERR_DUPLICATE_DEF },
	{ 11, SbERR_ZERODIV },
	{ 12, SbERR_VAR_UNDEFINED },
	{ 13, SbERR_CONVERSION },
	{ 14, SbERR_BAD_PARAMETER },
	{ 18, SbERR_USER_ABORT },
	{ 20, SbERR_BAD_RESUME },
	{ 28, SbERR_STACK_OVERFLOW },
	{ 35, SbERR_PROC_UNDEFINED },
	{ 48, SbERR_BAD_DLL_LOAD },
	{ 49, SbERR_BAD_DLL_CALL },
	{ 51, SbERR_INTERNAL_ERROR },
	{ 52, SbERR_BAD_CHANNEL },
	{ 53, SbERR_FILE_NOT_FOUND },
	{ 54, SbERR_BAD_FILE_MODE },
	{ 55, SbERR_FILE_ALREADY_OPEN },
	{ 57, SbERR_IO_ERROR },
	{ 58, SbERR_FILE_EXISTS },
	{ 59, SbERR_BAD_RECORD_LENGTH },
	{ 61, SbERR_DISK_FULL },
	{ 62, SbERR_READ_PAST_EOF },
	{ 63, SbERR_BAD_RECORD_NUMBER },
	{ 67, SbERR_TOO_MANY_FILES },
	{ 68, SbERR_NO_DEVICE },
	{ 70, SbERR_ACCESS_DENIED },
	{ 71, SbERR_NOT_READY },
	{ 73, SbERR_NOT_IMPLEMENTED },
	{ 74, SbERR_DIFFERENT_DRIVE },
	{ 75, SbERR_ACCESS_ERROR },
	{ 76, SbERR_PATH_NOT_FOUND },
	{ 91, SbERR_NO_OBJECT },
	{ 93, SbERR_BAD_PATTERN },
	{ 94, SBERR_IS_NULL },
	{ 250, SbERR_DDE_ERROR },
	{ 280, SbERR_DDE_WAITINGACK },
	{ 281, SbERR_DDE_OUTOFCHANNELS },
	{ 282, SbERR_DDE_NO_RESPONSE },
	{ 283, SbERR_DDE_MULT_RESPONSES },
	{ 284, SbERR_DDE_CHANNEL_LOCKED },
	{ 285, SbERR_DDE_NOTPROCESSED },
	{ 286, SbERR_DDE_TIMEOUT },
	{ 287, SbERR_DDE_USER_INTERRUPT },
	{ 288, SbERR_DDE_BUSY },
	{ 289, SbERR_DDE_NO_DATA },
	{ 290, SbERR_DDE_WRONG_DATA_FORMAT },
	{ 291, SbERR_DDE_PARTNER_QUIT },
	{ 292, SbERR_DDE_CONV_CLOSED },
	{ 293, SbERR_DDE_NO_CHANNEL },
	{ 294, SbERR_DDE_INVALID_LINK },
	{ 295, SbERR_DDE_QUEUE_OVERFLOW },
	{ 296, SbERR_DDE_LINK_ALREADY_EST },
	{ 297, SbERR_DDE_LINK_INV_TOPIC },
	{ 298, SbERR_DDE_DLL_NOT_FOUND },
	{ 323, SbERR_CANNOT_LOAD },
	{ 341, SbERR_BAD_INDEX },
	{ 366, SbERR_NO_ACTIVE_OBJECT },
	{ 380, SbERR_BAD_PROP_VALUE },
	{ 382, SbERR_PROP_READONLY },
	{ 394, SbERR_PROP_WRITEONLY },
	{ 420, SbERR_INVALID_OBJECT },
	{ 423, SbERR_NO_METHOD },
	{ 424, SbERR_NEEDS_OBJECT },
	{ 425, SbERR_INVALID_USAGE_OBJECT },
	{ 430, SbERR_NO_OLE },
	{ 438, SbERR_BAD_METHOD },
	{ 440, SbERR_OLE_ERROR },
	{ 445, SbERR_BAD_ACTION },
	{ 446, SbERR_NO_NAMED_ARGS },
	{ 447, SbERR_BAD_LOCALE },
	{ 448, SbERR_NAMED_NOT_FOUND },
	{ 449, SbERR_NOT_OPTIONAL },
	{ 450, SbERR_WRONG_ARGS },
	{ 451, SbERR_NOT_A_COLL },
	{ 452, SbERR_BAD_ORDINAL },
	{ 453, SbERR_DLLPROC_NOT_FOUND },
	{ 460, SbERR_BAD_CLIPBD_FORMAT },
	{ 951, SbERR_UNEXPECTED },
	{ 952, SbERR_EXPECTED },
	{ 953, SbERR_SYMBOL_EXPECTED },
	{ 954, SbERR_VAR_EXPECTED },
	{ 955, SbERR_LABEL_EXPECTED },
	{ 956, SbERR_LVALUE_EXPECTED },
	{ 957, SbERR_VAR_DEFINED },
	{ 958, SbERR_PROC_DEFINED },
	{ 959, SbERR_LABEL_DEFINED },
	{ 960, SbERR_UNDEF_VAR },
	{ 961, SbERR_UNDEF_ARRAY },
	{ 962, SbERR_UNDEF_PROC },
	{ 963, SbERR_UNDEF_LABEL },
	{ 964, SbERR_UNDEF_TYPE },
	{ 965, SbERR_BAD_EXIT },
	{ 966, SbERR_BAD_BLOCK },
	{ 967, SbERR_BAD_BRACKETS },
	{ 968, SbERR_BAD_DECLARATION },
	{ 969, SbERR_BAD_PARAMETERS },
	{ 970, SbERR_BAD_CHAR_IN_NUMBER },
	{ 971, SbERR_MUST_HAVE_DIMS },
	{ 972, SbERR_NO_IF },
	{ 973, SbERR_NOT_IN_SUBR },
	{ 974, SbERR_NOT_IN_MAIN },
	{ 975, SbERR_WRONG_DIMS },
	{ 976, SbERR_BAD_OPTION },
	{ 977, SbERR_CONSTANT_REDECLARED },
	{ 978, SbERR_PROG_TOO_LARGE },
	{ 979, SbERR_NO_STRINGS_ARRAYS },
	{ 1000, SbERR_PROPERTY_NOT_FOUND },
	{ 1001, SbERR_METHOD_NOT_FOUND },
	{ 1002, SbERR_ARG_MISSING },
	{ 1003, SbERR_BAD_NUMBER_OF_ARGS },
	{ 1004, SbERR_METHOD_FAILED },
	{ 1005, SbERR_SETPROP_FAILED },
	{ 1006, SbERR_GETPROP_FAILED },
	{ 1007, SbERR_BASIC_COMPAT },
	{ 0xFFFF, 0xFFFFFFFFL }		// End mark
};

// The StarBASIC factory is a hack. When a SbModule is created, its pointer
// is saved and given to the following SbProperties/SbMethods. This restores
// the Modul-relationshop. But it works only when a modul is loaded.
// Can cause troubles with separately loaded properties!

SbxBase* SbiFactory::Create( sal_uInt16 nSbxId, sal_uInt32 nCreator )
{
	if( nCreator ==  SBXCR_SBX )
	{
		String aEmpty;
		switch( nSbxId )
		{
			case SBXID_BASIC:
				return new StarBASIC( NULL );
			case SBXID_BASICMOD:
				return new SbModule( aEmpty );
			case SBXID_BASICPROP:
				return new SbProperty( aEmpty, SbxVARIANT, NULL );
			case SBXID_BASICMETHOD:
				return new SbMethod( aEmpty, SbxVARIANT, NULL );
			case SBXID_JSCRIPTMOD:
				return new SbJScriptModule( aEmpty );
			case SBXID_JSCRIPTMETH:
				return new SbJScriptMethod( aEmpty, SbxVARIANT, NULL );
		}
	}
	return NULL;
}

SbxObject* SbiFactory::CreateObject( const String& rClass )
{
	if( rClass.EqualsIgnoreCaseAscii( "StarBASIC" ) )
		return new StarBASIC( NULL );
	else
	if( rClass.EqualsIgnoreCaseAscii( "StarBASICModule" ) )
	{
		String aEmpty;
		return new SbModule( aEmpty );
	}
	else
	if( rClass.EqualsIgnoreCaseAscii( "Collection" ) )
	{
		String aCollectionName( RTL_CONSTASCII_USTRINGPARAM("Collection") );
		return new BasicCollection( aCollectionName );
	}
	else
    if( rClass.EqualsIgnoreCaseAscii( "FileSystemObject" ) )
    {
        try
        {
            Reference< XMultiServiceFactory > xFactory( comphelper::getProcessServiceFactory(), UNO_SET_THROW );
            ::rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.FileSystemObject" ) );
            Reference< XInterface > xInterface( xFactory->createInstance( aServiceName ), UNO_SET_THROW );
            return new SbUnoObject( aServiceName, uno::makeAny( xInterface ) );
        }
        catch( Exception& )
        {}
    }

    return NULL;
}


// Factory class to create OLE objects
class SbOLEFactory : public SbxFactory
{
public:
	virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 = SBXCR_SBX );
	virtual SbxObject* CreateObject( const String& );
};

SbxBase* SbOLEFactory::Create( sal_uInt16, sal_uInt32 )
{
	// Not supported
	return NULL;
}

SbUnoObject* createOLEObject_Impl( const String& aType );	// sbunoobj.cxx

SbxObject* SbOLEFactory::CreateObject( const String& rClassName )
{
	SbxObject* pRet = createOLEObject_Impl( rClassName );
	return pRet;
}


//========================================================================
// SbFormFactory, show user forms by: dim as new <user form name>

class SbFormFactory : public SbxFactory
{
public:
	virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 = SBXCR_SBX );
	virtual SbxObject* CreateObject( const String& );
};

SbxBase* SbFormFactory::Create( sal_uInt16, sal_uInt32 )
{
	// Not supported
	return NULL;
}

SbxObject* SbFormFactory::CreateObject( const String& rClassName )
{
	if( SbModule* pMod = pMOD )
	{
		if( SbxVariable* pVar = pMod->Find( rClassName, SbxCLASS_OBJECT ) )
		{
			if( SbUserFormModule* pFormModule = dynamic_cast< SbUserFormModule* >( pVar->GetObject() ) )
			{
			    bool bInitState = pFormModule->getInitState();
				if( bInitState )
				{
					// Not the first instantiate, reset
					bool bTriggerTerminateEvent = false;
					pFormModule->ResetApiObj( bTriggerTerminateEvent );
					pFormModule->setInitState( false );
				}
				else
				{
					pFormModule->Load();
				}
				return pFormModule->CreateInstance();
			}
		}
	}
	return 0;
}


//========================================================================
// SbTypeFactory

SbxObject* cloneTypeObjectImpl( const SbxObject& rTypeObj )
{
	SbxObject* pRet = new SbxObject( rTypeObj );
	pRet->PutObject( pRet );

	// Copy the properties, not only the reference to them
	SbxArray* pProps = pRet->GetProperties();
	sal_uInt32 nCount = pProps->Count32();
	for( sal_uInt32 i = 0 ; i < nCount ; i++ )
	{
		SbxVariable* pVar = pProps->Get32( i );
		SbxProperty* pProp = dynamic_cast< SbxProperty* >( pVar );
		if( pProp )
		{
			SbxProperty* pNewProp = new SbxProperty( *pProp );
			SbxDataType eVarType = pVar->GetType();
			if( eVarType & SbxARRAY )
			{
				SbxBase* pParObj = pVar->GetObject();
				SbxDimArray* pSource = dynamic_cast< SbxDimArray* >( pParObj);
				SbxDimArray* pDest = new SbxDimArray( pVar->GetType() );
				sal_Int32 lb = 0;
				sal_Int32 ub = 0;

				pDest->setHasFixedSize( pSource->hasFixedSize() );
				if ( pSource->GetDims() && pSource->hasFixedSize() )
				{
					for ( sal_Int32 j = 1 ; j <= pSource->GetDims(); ++j )
					{
						pSource->GetDim32( (sal_Int32)j, lb, ub );
						pDest->AddDim32( lb, ub );
					}
				}
				else 
					pDest->unoAddDim( 0, -1 ); // variant array

				sal_uInt16 nSavFlags = pVar->GetFlags();
				pNewProp->ResetFlag( SBX_FIXED );
				// need to reset the FIXED flag 
				// when calling PutObject ( because the type will not match Object ) 	
				pNewProp->PutObject( pDest );
				pNewProp->SetFlags( nSavFlags );
			}
			if( eVarType == SbxOBJECT )
			{
				SbxBase* pObjBase = pVar->GetObject();
				SbxObject* pSrcObj = dynamic_cast< SbxObject* >( pObjBase);
				SbxObject* pDestObj = NULL;
				if( pSrcObj != NULL )
					pDestObj = cloneTypeObjectImpl( *pSrcObj );
				pNewProp->PutObject( pDestObj );
			}
			pProps->PutDirect( pNewProp, i );
		}
	}
	return pRet;
}

// Factory class to create user defined objects (type command)
class SbTypeFactory : public SbxFactory
{
public:
	virtual SbxBase* Create( sal_uInt16 nSbxId, sal_uInt32 = SBXCR_SBX );
	virtual SbxObject* CreateObject( const String& );
};

SbxBase* SbTypeFactory::Create( sal_uInt16, sal_uInt32 )
{
	// Not supported
	return NULL;
}

SbxObject* SbTypeFactory::CreateObject( const String& rClassName )
{
	SbxObject* pRet = NULL;
	SbModule* pMod = pMOD;
	if( pMod )
	{
		const SbxObject* pObj = pMod->FindType( rClassName );
		if( pObj )
			pRet = cloneTypeObjectImpl( *pObj );
	}
	return pRet;
}

SbxObject* createUserTypeImpl( const String& rClassName )
{
	SbxObject* pRetObj = pTYPEFAC->CreateObject( rClassName );
	return pRetObj;
}

SbClassModuleObject::SbClassModuleObject( SbModule* pClassModule )
	: SbModule( pClassModule->GetName() )
	, mpClassModule( pClassModule )
	, mbInitializeEventDone( false )
{
	aOUSource = pClassModule->aOUSource;
	aComment = pClassModule->aComment;
	pImage = pClassModule->pImage;
	pBreaks = pClassModule->pBreaks;

	SetClassName( pClassModule->GetName() );

	// Allow search only internally
	ResetFlag( SBX_GBLSEARCH );

	// Copy the methods from original class module
	SbxArray* pClassMethods = pClassModule->GetMethods();
	sal_uInt32 nMethodCount = pClassMethods->Count32();
	sal_uInt32 i;
	for( i = 0 ; i < nMethodCount ; i++ )
	{
		SbxVariable* pVar = pClassMethods->Get32( i );

		// Exclude SbIfaceMapperMethod to copy them in a second step
		SbIfaceMapperMethod* pIfaceMethod = dynamic_cast< SbIfaceMapperMethod* >( pVar );
		if( !pIfaceMethod )
		{
			SbMethod* pMethod = dynamic_cast< SbMethod* >( pVar );
			if( pMethod )
			{
				sal_uInt16 nFlags_ = pMethod->GetFlags();
				pMethod->SetFlag( SBX_NO_BROADCAST );
				SbMethod* pNewMethod = new SbMethod( *pMethod );
				pNewMethod->ResetFlag( SBX_NO_BROADCAST );
				pMethod->SetFlags( nFlags_ );
				pNewMethod->pMod = this;
				pNewMethod->SetParent( this );
				pMethods->PutDirect( pNewMethod, i );
				StartListening( pNewMethod->GetBroadcaster(), sal_True );
			}
		}
	}

	// Copy SbIfaceMapperMethod in a second step to ensure that
	// the corresponding base methods have already been copied
	for( i = 0 ; i < nMethodCount ; i++ )
	{
		SbxVariable* pVar = pClassMethods->Get32( i );

		SbIfaceMapperMethod* pIfaceMethod = dynamic_cast< SbIfaceMapperMethod* >( pVar );
		if( pIfaceMethod )
		{
			SbMethod* pImplMethod = pIfaceMethod->getImplMethod();
			if( !pImplMethod )
			{
				DBG_ERROR( "No ImplMethod" );
				continue;
			}

			// Search for own copy of ImplMethod
			String aImplMethodName = pImplMethod->GetName();
			SbxVariable* p = pMethods->Find( aImplMethodName, SbxCLASS_METHOD );
			SbMethod* pImplMethodCopy = p ? dynamic_cast< SbMethod* >( p) : NULL;
			if( !pImplMethodCopy )
			{
				DBG_ERROR( "Found no ImplMethod copy" );
				continue;
			}
			SbIfaceMapperMethod* pNewIfaceMethod =
				new SbIfaceMapperMethod( pIfaceMethod->GetName(), pImplMethodCopy );
			pMethods->PutDirect( pNewIfaceMethod, i );
		}
	}

	// Copy the properties from original class module
	SbxArray* pClassProps = pClassModule->GetProperties();
	sal_uInt32 nPropertyCount = pClassProps->Count32();
	for( i = 0 ; i < nPropertyCount ; i++ )
	{
		SbxVariable* pVar = pClassProps->Get32( i );
		SbProcedureProperty* pProcedureProp = dynamic_cast< SbProcedureProperty* >( pVar );
		if( pProcedureProp )
		{
			sal_uInt16 nFlags_ = pProcedureProp->GetFlags();
			pProcedureProp->SetFlag( SBX_NO_BROADCAST );
			SbProcedureProperty* pNewProp = new SbProcedureProperty
				( pProcedureProp->GetName(), pProcedureProp->GetType() );
				// ( pProcedureProp->GetName(), pProcedureProp->GetType(), this );
			pNewProp->SetFlags( nFlags_ ); // Copy flags
			pNewProp->ResetFlag( SBX_NO_BROADCAST ); // except the Broadcast if it was set
			pProcedureProp->SetFlags( nFlags_ );
			pProps->PutDirect( pNewProp, i );
			StartListening( pNewProp->GetBroadcaster(), sal_True );
		}
		else
		{
			SbxProperty* pProp = dynamic_cast< SbxProperty* >( pVar );
			if( pProp )
			{
				sal_uInt16 nFlags_ = pProp->GetFlags();
				pProp->SetFlag( SBX_NO_BROADCAST );
				SbxProperty* pNewProp = new SbxProperty( *pProp );

				// Special handling for modules instances and collections, they need
				// to be instantiated, otherwise all refer to the same base object
				SbxDataType eVarType = pProp->GetType();
				if( eVarType == SbxOBJECT )
				{
					SbxBase* pObjBase = pProp->GetObject();
					SbxObject* pObj = dynamic_cast< SbxObject* >( pObjBase);
					if( pObj != NULL )
					{
						String aObjClass = pObj->GetClassName();

						SbClassModuleObject* pClassModuleObj = dynamic_cast< SbClassModuleObject* >( pObjBase);
						if( pClassModuleObj != NULL )
						{
							SbModule* pLclClassModule = pClassModuleObj->getClassModule();
							SbClassModuleObject* pNewObj = new SbClassModuleObject( pLclClassModule );
							pNewObj->SetName( pProp->GetName() );
							pNewObj->SetParent( pLclClassModule->pParent );
							pNewProp->PutObject( pNewObj );
						}
						else if( aObjClass.EqualsIgnoreCaseAscii( "Collection" ) )
						{
							String aCollectionName( RTL_CONSTASCII_USTRINGPARAM("Collection") );
							BasicCollection* pNewCollection = new BasicCollection( aCollectionName );
							pNewCollection->SetName( pProp->GetName() );
							pNewCollection->SetParent( pClassModule->pParent );
							pNewProp->PutObject( pNewCollection );
						}
					}
				}

				pNewProp->ResetFlag( SBX_NO_BROADCAST );
				pNewProp->SetParent( this );
				pProps->PutDirect( pNewProp, i );
				pProp->SetFlags( nFlags_ );
			}
		}
	}
	SetModuleType( ModuleType::CLASS );
	mbVBACompat = pClassModule->mbVBACompat;
}

SbClassModuleObject::~SbClassModuleObject()
{
    // do not trigger termination event when document is already closed
	if( StarBASIC::IsRunning() )
        if( StarBASIC* pDocBasic = lclGetDocBasicForModule( this ) )
            if( const DocBasicItem* pDocBasicItem = lclFindDocBasicItem( pDocBasic ) )
                if( !pDocBasicItem->isDocClosed() )
                    triggerTerminateEvent();

	// Must be deleted by base class dtor because this data
	// is not owned by the SbClassModuleObject object
	pImage = NULL;
	pBreaks = NULL;
}

void SbClassModuleObject::SFX_NOTIFY( SfxBroadcaster& rBC, const TypeId& rBCType,
						   const SfxHint& rHint, const TypeId& rHintType )
{
	handleProcedureProperties( rBC, rHint );
}

SbxVariable* SbClassModuleObject::Find( const XubString& rName, SbxClassType t )
{
	SbxVariable* pRes = SbxObject::Find( rName, t );
	if( pRes )
	{
		triggerInitializeEvent();

		SbIfaceMapperMethod* pIfaceMapperMethod = dynamic_cast< SbIfaceMapperMethod* >( pRes);
		if( pIfaceMapperMethod )
		{
			pRes = pIfaceMapperMethod->getImplMethod();
			pRes->SetFlag( SBX_EXTFOUND );
		}
	}
	return pRes;
}

void SbClassModuleObject::triggerInitializeEvent( void )
{
	static String aInitMethodName( RTL_CONSTASCII_USTRINGPARAM("Class_Initialize") );

	if( mbInitializeEventDone )
		return;

	mbInitializeEventDone = true;

	// Search method
	SbxVariable* pMeth = SbxObject::Find( aInitMethodName, SbxCLASS_METHOD );
	if( pMeth )
	{
		SbxValues aVals;
		pMeth->Get( aVals );
	}
}

void SbClassModuleObject::triggerTerminateEvent( void )
{
	static String aTermMethodName( RTL_CONSTASCII_USTRINGPARAM("Class_Terminate") );

	if( !mbInitializeEventDone || GetSbData()->bRunInit )
		return;

	// Search method
	SbxVariable* pMeth = SbxObject::Find( aTermMethodName, SbxCLASS_METHOD );
	if( pMeth )
	{
		SbxValues aVals;
		pMeth->Get( aVals );
	}
}


SbClassData::SbClassData( void )
{
	mxIfaces = new SbxArray();
}

void SbClassData::clear( void )
{
	mxIfaces->Clear(); 
	maRequiredTypes.clear();
}

SbClassFactory::SbClassFactory( void )
{
	String aDummyName;
	xClassModules = new SbxObject( aDummyName );
}

SbClassFactory::~SbClassFactory()
{}

void SbClassFactory::AddClassModule( SbModule* pClassModule )
{
	SbxObjectRef xToUseClassModules = xClassModules;

    if( StarBASIC* pDocBasic = lclGetDocBasicForModule( pClassModule ) )
        if( const DocBasicItem* pDocBasicItem = lclFindDocBasicItem( pDocBasic ) )
            xToUseClassModules = pDocBasicItem->getClassModules();

	SbxObject* pParent = pClassModule->GetParent();
	xToUseClassModules->Insert( pClassModule );
	pClassModule->SetParent( pParent );
}

void SbClassFactory::RemoveClassModule( SbModule* pClassModule )
{
	xClassModules->Remove( pClassModule );
}

SbxBase* SbClassFactory::Create( sal_uInt16, sal_uInt32 )
{
	// Not supported
	return NULL;
}

SbxObject* SbClassFactory::CreateObject( const String& rClassName )
{
	SbxObjectRef xToUseClassModules = xClassModules;

    if( SbModule* pMod = pMOD )
        if( StarBASIC* pDocBasic = lclGetDocBasicForModule( pMod ) )
            if( const DocBasicItem* pDocBasicItem = lclFindDocBasicItem( pDocBasic ) )
                xToUseClassModules = pDocBasicItem->getClassModules();

	SbxVariable* pVar = xToUseClassModules->Find( rClassName, SbxCLASS_OBJECT );
	SbxObject* pRet = NULL;
	if( pVar )
	{
		SbModule* pVarMod = (SbModule*)pVar;
		pRet = new SbClassModuleObject( pVarMod );
	}
	return pRet;
}

SbModule* SbClassFactory::FindClass( const String& rClassName )
{
	SbxVariable* pVar = xClassModules->Find( rClassName, SbxCLASS_DONTCARE );
	SbModule* pMod = pVar ? (SbModule*)pVar : NULL;
	return pMod;
}

StarBASIC::StarBASIC( StarBASIC* p, sal_Bool bIsDocBasic  )
	: SbxObject( String( RTL_CONSTASCII_USTRINGPARAM("StarBASIC") ) ), bDocBasic( bIsDocBasic )
{
	SetParent( p );
	pLibInfo = NULL;
	bNoRtl = bBreak = sal_False;
	bVBAEnabled = sal_False;
	pModules = new SbxArray;

	if( !GetSbData()->nInst++ )
	{
		pSBFAC = new SbiFactory;
		AddFactory( pSBFAC );
		pTYPEFAC = new SbTypeFactory;
		AddFactory( pTYPEFAC );
		pCLASSFAC = new SbClassFactory;
		AddFactory( pCLASSFAC );
		pOLEFAC = new SbOLEFactory;
		AddFactory( pOLEFAC );
		pFORMFAC = new SbFormFactory;
		AddFactory( pFORMFAC );
		pUNOFAC = new SbUnoFactory;
		AddFactory( pUNOFAC );
	}
	pRtl = new SbiStdObject( String( RTL_CONSTASCII_USTRINGPARAM(RTLNAME) ), this );
    // Search via StarBasic is always global
	SetFlag( SBX_GBLSEARCH );
	pVBAGlobals = NULL;
	bQuit = sal_False;

	if( bDocBasic )
        lclInsertDocBasicItem( *this );
}

// #51727 Override SetModified so that the modified state
// is not given to the parent
void StarBASIC::SetModified( sal_Bool b )
{
    SbxBase::SetModified( b );
}

extern void lcl_closeTraceFile();

StarBASIC::~StarBASIC()
{
#ifdef DBG_TRACE_BASIC
    lcl_closeTraceFile();
#endif

	// Needs to be first action as it can trigger events
	disposeComVariablesForBasic( this );

	if( !--GetSbData()->nInst )
	{
		RemoveFactory( pSBFAC );
		delete pSBFAC; pSBFAC = NULL;
		RemoveFactory( pUNOFAC );
		delete pUNOFAC; pUNOFAC = NULL;
		RemoveFactory( pTYPEFAC );
		delete pTYPEFAC; pTYPEFAC = NULL;
		RemoveFactory( pCLASSFAC );
		delete pCLASSFAC; pCLASSFAC = NULL;
		RemoveFactory( pOLEFAC );
		delete pOLEFAC; pOLEFAC = NULL;
		RemoveFactory( pFORMFAC );
		delete pFORMFAC; pFORMFAC = NULL;

#ifdef DBG_UTIL
	// There is no need to clean SbiData at program end,
	// but we dislike MLK's at Purify
	// TODO: Where else???
	SbiGlobals** pp = (SbiGlobals**) ::GetAppData( SHL_SBC );
	SbiGlobals* p = *pp;
	if( p )
	{
		delete p;
		*pp = 0;
	}
#endif
	}
	else if( bDocBasic )
	{
	    SbxError eOld = SbxBase::GetError();

        lclRemoveDocBasicItem( *this );

		SbxBase::ResetError();
		if( eOld != SbxERR_OK )
			SbxBase::SetError( eOld );
	}

    // #100326 Set Parent NULL in registered listeners
    if( xUnoListeners.Is() )
    {
        sal_uInt16 uCount = xUnoListeners->Count();
	    for( sal_uInt16 i = 0 ; i < uCount ; i++ )
	    {
		    SbxVariable* pListenerObj = xUnoListeners->Get( i );
            pListenerObj->SetParent( NULL );
        }
        xUnoListeners = NULL;
    }

    clearUnoMethodsForBasic( this );
}

// Override new() operator, so that everyone can create a new instance
void* StarBASIC::operator new( size_t n )
{
	if( n < sizeof( StarBASIC ) )
	{
//		DBG_ASSERT( sal_False, "Warnung: inkompatibler BASIC-Stand!" );
		n = sizeof( StarBASIC );
	}
	return ::operator new( n );
}

void StarBASIC::operator delete( void* p )
{
	::operator delete( p );
}

void StarBASIC::implClearDependingVarsOnDelete( StarBASIC* pDeletedBasic )
{
	if( this != pDeletedBasic )
	{
		for( sal_uInt16 i = 0; i < pModules->Count(); i++ )
		{
			SbModule* p = (SbModule*)pModules->Get( i );
			p->ClearVarsDependingOnDeletedBasic( pDeletedBasic );
		}
	}

	for( sal_uInt16 nObj = 0; nObj < pObjs->Count(); nObj++ )
	{
		SbxVariable* pVar = pObjs->Get( nObj );
		StarBASIC* pBasic = dynamic_cast< StarBASIC* >(pVar);
		if( pBasic && pBasic != pDeletedBasic )
			pBasic->implClearDependingVarsOnDelete( pDeletedBasic );
	}
}


/**************************************************************************
*
*    Creation/Management of modules
*
**************************************************************************/

SbModule* StarBASIC::MakeModule( const String& rName, const String& rSrc )
{
	return MakeModule32( rName, rSrc );
}

SbModule* StarBASIC::MakeModule32( const String& rName, const ::rtl::OUString& rSrc )
{
    ModuleInfo mInfo;
    mInfo.ModuleType = ModuleType::NORMAL;
    return MakeModule32(  rName, mInfo, rSrc );
}
SbModule* StarBASIC::MakeModule32( const String& rName, const ModuleInfo& mInfo, const rtl::OUString& rSrc )
{
    
    OSL_TRACE("create module %s type mInfo %d", rtl::OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr(), mInfo.ModuleType );
    SbModule* p = NULL;
    switch ( mInfo.ModuleType )
    {
        case ModuleType::DOCUMENT:
            // In theory we should be able to create Object modules
            // in ordinary basic ( in vba mode thought these are create
            // by the application/basic and not by the user )
            p = new SbObjModule( rName, mInfo, isVBAEnabled() );
            break;
        case ModuleType::CLASS:
            p = new SbModule( rName, isVBAEnabled() );
			p->SetModuleType( ModuleType::CLASS );
	    break;
        case ModuleType::FORM:
            p = new SbUserFormModule( rName, mInfo, isVBAEnabled() );
	    break;
        default:
            p = new SbModule( rName, isVBAEnabled() );
            
    }
	p->SetSource32( rSrc );
	p->SetParent( this );
	pModules->Insert( p, pModules->Count() );
	SetModified( sal_True );
	return p;
}

void StarBASIC::Insert( SbxVariable* pVar )
{
	if( dynamic_cast< SbModule* >(pVar) )
	{
		pModules->Insert( pVar, pModules->Count() );
		pVar->SetParent( this );
		StartListening( pVar->GetBroadcaster(), sal_True );
	}
	else
	{
		sal_Bool bWasModified = IsModified();
		SbxObject::Insert( pVar );
		if( !bWasModified && pVar->IsSet( SBX_DONTSTORE ) )
			SetModified( sal_False );
	}
}

void StarBASIC::Remove( SbxVariable* pVar )
{
	if( dynamic_cast< SbModule* >(pVar) )
	{
        // #87540 Can be last reference!
        SbxVariableRef xVar = pVar;
		pModules->Remove( pVar );
		pVar->SetParent( 0 );
		EndListening( pVar->GetBroadcaster() );
	}
	else
		SbxObject::Remove( pVar );
}

sal_Bool StarBASIC::Compile( SbModule* pMod )
{
	return pMod ? pMod->Compile() : sal_False;
}

sal_Bool StarBASIC::Disassemble( SbModule* pMod, String& rText )
{
	rText.Erase();
	if( pMod )
		pMod->Disassemble( rText );
	return sal_Bool( rText.Len() != 0 );
}

void StarBASIC::Clear()
{
	while( pModules->Count() )
		pModules->Remove( pModules->Count() - 1 );
}

SbModule* StarBASIC::FindModule( const String& rName )
{
	for( sal_uInt16 i = 0; i < pModules->Count(); i++ )
	{
		SbModule* p = (SbModule*) pModules->Get( i );
		if( p->GetName().EqualsIgnoreCaseAscii( rName ) )
			return p;
	}
	return NULL;
}


struct ClassModuleRunInitItem
{
	SbModule*		m_pModule;
	bool			m_bProcessing;
	bool			m_bRunInitDone;
	//ModuleVector	m_vModulesDependingOnThisModule;

	ClassModuleRunInitItem( void )
		: m_pModule( NULL )
		, m_bProcessing( false )
		, m_bRunInitDone( false )
	{}
	ClassModuleRunInitItem( SbModule* pModule )
		: m_pModule( pModule )
		, m_bProcessing( false )
		, m_bRunInitDone( false )
	{}
};

// Derive from has_map type instead of typedef
// to allow forward declaration in sbmod.hxx
class ModuleInitDependencyMap : public
	std::hash_map< ::rtl::OUString, ClassModuleRunInitItem,
		::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > >
{};

void SbModule::implProcessModuleRunInit( ModuleInitDependencyMap& rMap, ClassModuleRunInitItem& rItem )
{
	rItem.m_bProcessing = true;

	//bool bAnyDependencies = true;
	SbModule* pModule = rItem.m_pModule;
	if( pModule->pClassData != NULL )
	{
		StringVector& rReqTypes = pModule->pClassData->maRequiredTypes;
		if( rReqTypes.size() > 0 )
		{
			for( StringVector::iterator it = rReqTypes.begin() ; it != rReqTypes.end() ; ++it )
			{
				String& rStr = *it;

				// Is required type a class module?
				ModuleInitDependencyMap::iterator itFind = rMap.find( rStr );
				if( itFind != rMap.end() )
				{
					ClassModuleRunInitItem& rParentItem = itFind->second;
					if( rParentItem.m_bProcessing )
					{
						// TODO: raise error?
						DBG_ERROR( "Cyclic module dependency detected" );
						continue;
					}

					if( !rParentItem.m_bRunInitDone )
						implProcessModuleRunInit( rMap, rParentItem );
				}
			}
		}
	}

	pModule->RunInit();
	rItem.m_bRunInitDone = true;
	rItem.m_bProcessing = false;
}

// Run Init-Code of all modules (including inserted libraries)
void StarBASIC::InitAllModules( StarBASIC* pBasicNotToInit )
{
	::vos::OGuard guard( Application::GetSolarMutex() );

    // Init own modules
	for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ )
	{
		SbModule* pModule = (SbModule*)pModules->Get( nMod );
		if(	!pModule->IsCompiled() )
			pModule->Compile();
	}
	// compile modules first then RunInit ( otherwise there is 
	// can be order dependency, e.g. classmodule A has a member
	// of of type classmodule B and classmodule B hasn't been compiled yet )

	// Consider required types to init in right order. Class modules
	// that are required by other modules have to be initialized first.
	ModuleInitDependencyMap aMIDMap;
	for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ )
	{
		SbModule* pModule = (SbModule*)pModules->Get( nMod );
		String aModuleName = pModule->GetName();
		if( pModule->isProxyModule() )
			aMIDMap[aModuleName] = ClassModuleRunInitItem( pModule );
	}

	ModuleInitDependencyMap::iterator it;
	for( it = aMIDMap.begin() ; it != aMIDMap.end(); ++it )
	{
		ClassModuleRunInitItem& rItem = it->second;
		SbModule::implProcessModuleRunInit( aMIDMap, rItem );
	}

	// Call RunInit on standard modules
	for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ )
	{
		SbModule* pModule = (SbModule*)pModules->Get( nMod );
		if( !pModule->isProxyModule() )
			pModule->RunInit();
	}

    // Check all objects if they are BASIC,
    // if yes initialize
	for ( sal_uInt16 nObj = 0; nObj < pObjs->Count(); nObj++ )
	{
		SbxVariable* pVar = pObjs->Get( nObj );
		StarBASIC* pBasic = dynamic_cast< StarBASIC* >( pVar);
		if( pBasic && pBasic != pBasicNotToInit )
			pBasic->InitAllModules();
	}
}

// #88329 Put modules back to not initialised state to
// force reinitialisation at next start
void StarBASIC::DeInitAllModules( void )
{
    // Deinit own modules
	for ( sal_uInt16 nMod = 0; nMod < pModules->Count(); nMod++ )
	{
		SbModule* pModule = (SbModule*)pModules->Get( nMod );
        if( pModule->pImage && !pModule->isProxyModule() && !dynamic_cast< SbObjModule* >(pModule) )
		    pModule->pImage->bInit = false;
	}

	for ( sal_uInt16 nObj = 0; nObj < pObjs->Count(); nObj++ )
	{
		SbxVariable* pVar = pObjs->Get( nObj );
		StarBASIC* pBasic = dynamic_cast< StarBASIC* >( pVar);
		if( pBasic )
			pBasic->DeInitAllModules();
	}
}

// #43011 For TestTool, to delete global vars
void StarBASIC::ClearGlobalVars( void )
{
	SbxArrayRef xProps( GetProperties() );
	sal_uInt16 nPropCount = xProps->Count();
	for ( sal_uInt16 nProp = 0 ; nProp < nPropCount ; ++nProp )
	{
		SbxBase* pVar = xProps->Get( nProp );
		pVar->Clear();
	}
	SetModified( sal_True );
}

// This implementation at first searches within the runtime library,
// then it looks for an element within one module. This moudle can be
// a public var or an entrypoint. If it is not found and we look for a
// method and a module with the given name is found the search continues
// for entrypoint "Main".
// If this fails again a conventional search over objects is performend.
SbxVariable* StarBASIC::Find( const String& rName, SbxClassType t )
{
	static String aMainStr( RTL_CONSTASCII_USTRINGPARAM("Main") );

	SbxVariable* pRes = NULL;
	SbModule* pNamed = NULL;
	// "Extended" search in Runtime Lib
	// but only if SbiRuntime has not set the flag
	if( !bNoRtl )
	{
		if( t == SbxCLASS_DONTCARE || t == SbxCLASS_OBJECT )
		{
			if( rName.EqualsIgnoreCaseAscii( RTLNAME ) )
				pRes = pRtl;
		}
		if( !pRes )
			pRes = ((SbiStdObject*) (SbxObject*) pRtl)->Find( rName, t );
		if( pRes )
			pRes->SetFlag( SBX_EXTFOUND );
	}
	// Search module
	if( !pRes )
	  for( sal_uInt16 i = 0; i < pModules->Count(); i++ )
	{
		SbModule* p = (SbModule*) pModules->Get( i );
		if( p->IsVisible() )
		{
			// Remember modul fpr Main() call
			// or is the name equal?!?
			if( p->GetName().EqualsIgnoreCaseAscii( rName ) )
			{
				if( t == SbxCLASS_OBJECT || t == SbxCLASS_DONTCARE )
				{
					pRes = p; break;
				}
				pNamed = p;
			}
			// Only variables qualified by the Module Name e.g. Sheet1.foo
			// should work for Documant && Class type Modules
			sal_Int32 nType = p->GetModuleType();
			if ( nType == ModuleType::DOCUMENT || nType == ModuleType::FORM )
				continue;

			// otherwise check if the element is available
			// unset GBLSEARCH-Flag (due to Rekursion)
			sal_uInt16 nGblFlag = p->GetFlags() & SBX_GBLSEARCH;
			p->ResetFlag( SBX_GBLSEARCH );
			pRes = p->Find( rName, t );
			p->SetFlag( nGblFlag );
			if( pRes )
				break;
		}
	}
	if( !pRes && pNamed && ( t == SbxCLASS_METHOD || t == SbxCLASS_DONTCARE ) &&
		!pNamed->GetName().EqualsIgnoreCaseAscii( aMainStr ) )
			pRes = pNamed->Find( aMainStr, SbxCLASS_METHOD );
	if( !pRes )
		pRes = SbxObject::Find( rName, t );
	return pRes;
}

sal_Bool StarBASIC::Call( const String& rName, SbxArray* pParam )
{
	sal_Bool bRes = SbxObject::Call( rName, pParam );
	if( !bRes )
	{
		SbxError eErr = SbxBase::GetError();
		SbxBase::ResetError();
		if( eErr != SbxERR_OK )
			RTError( (SbError)eErr, 0, 0, 0 );
	}
	return bRes;
}

// Find method via name (e.g. query via BASIC IDE)
SbxBase* StarBASIC::FindSBXInCurrentScope( const String& rName )
{
	if( !pINST )
		return NULL;
	if( !pINST->pRun )
		return NULL;
	return pINST->pRun->FindElementExtern( rName );
}

// Preserve old interface
SbxVariable* StarBASIC::FindVarInCurrentScopy
( const String& rName, sal_uInt16& rStatus )
{
	rStatus = 1;              // Presumption: nothing found
	SbxVariable* pVar = NULL;
	SbxBase* pSbx = FindSBXInCurrentScope( rName );
	if( pSbx )
	{
		if( !dynamic_cast< SbxMethod* >(pSbx) && !dynamic_cast< SbxObject* >(pSbx) )
			pVar = dynamic_cast< SbxVariable* >( pSbx);
	}
	if( pVar )
		rStatus = 0;      // We found something
	return pVar;
}

void StarBASIC::QuitAndExitApplication()
{
    Stop();
    bQuit = sal_True;
}

void StarBASIC::Stop()
{
	SbiInstance* p = pINST;
	while( p )
	{
		p->Stop();
		p = p->pNext;
	}
}

sal_Bool StarBASIC::IsRunning()
{
	return sal_Bool( pINST != NULL );
}

/**************************************************************************
*
*    Object factories and others
*
**************************************************************************/

// Activation of an object. There is no need to access active objects
// with name via BASIC. If NULL is given, everything is activated.
void StarBASIC::ActivateObject( const String* pName, sal_Bool bActivate )
{
	if( pName )
	{
		SbxObject* p = (SbxObject*) SbxObject::Find( *pName, SbxCLASS_OBJECT );
		if( p )
		{
			if( bActivate )
				p->SetFlag( SBX_EXTSEARCH );
			else
				p->ResetFlag( SBX_EXTSEARCH );
		}
	}
	else
	{
		for( sal_uInt16 i = 0; i < GetObjects()->Count(); i++ )
		{
			SbxObject* p = (SbxObject*) GetObjects()->Get( i );
			if( bActivate )
				p->SetFlag( SBX_EXTSEARCH );
			else
				p->ResetFlag( SBX_EXTSEARCH );
		}
	}
}

/**************************************************************************
*
*    Debugging and error handling
*
**************************************************************************/

SbMethod* StarBASIC::GetActiveMethod( sal_uInt16 nLevel )
{
	if( pINST )
		return pINST->GetCaller( nLevel );
	else
		return NULL;
}

SbModule* StarBASIC::GetActiveModule()
{
	if( pINST && !IsCompilerError() )
		return pINST->GetActiveModule();
	else
		return pCMOD;
}

sal_uInt16 StarBASIC::BreakPoint( sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 )
{
	SetErrorData( 0, l, c1, c2 );
	bBreak = sal_True;
	if( GetSbData()->aBreakHdl.IsSet() )
		return (sal_uInt16) GetSbData()->aBreakHdl.Call( this );
	else
		return BreakHdl();
}

sal_uInt16 StarBASIC::StepPoint( sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 )
{
	SetErrorData( 0, l, c1, c2 );
	bBreak = sal_False;
	if( GetSbData()->aBreakHdl.IsSet() )
		return (sal_uInt16) GetSbData()->aBreakHdl.Call( this );
	else
		return BreakHdl();
}

sal_uInt16 __EXPORT StarBASIC::BreakHdl()
{
	return (sal_uInt16) ( aBreakHdl.IsSet()
		? aBreakHdl.Call( this ) : SbDEBUG_CONTINUE );
}

// Calls for error handler and break handler
sal_uInt16 StarBASIC::GetLine()		{ return GetSbData()->nLine; }
sal_uInt16 StarBASIC::GetCol1()		{ return GetSbData()->nCol1; }
sal_uInt16 StarBASIC::GetCol2()		{ return GetSbData()->nCol2; }

// Specific to error handler
SbError StarBASIC::GetErrorCode()		{ return GetSbData()->nCode; }
const String& StarBASIC::GetErrorText()	{ return GetSbData()->aErrMsg; }
sal_Bool StarBASIC::IsCompilerError()		{ return GetSbData()->bCompiler; }
void StarBASIC::SetGlobalLanguageMode( SbLanguageMode eLanguageMode )
{
	GetSbData()->eLanguageMode = eLanguageMode;
}
SbLanguageMode StarBASIC::GetGlobalLanguageMode()
{
	return GetSbData()->eLanguageMode;
}
// Local settings
SbLanguageMode StarBASIC::GetLanguageMode()
{
	// Use global settings?
	if( eLanguageMode == SB_LANG_GLOBAL )
		return GetSbData()->eLanguageMode;
	else
		return eLanguageMode;
}

// AB: 29.3.96
// Das Mapping zwischen alten und neuen Fehlercodes erfolgt, indem die Tabelle
// SFX_VB_ErrorTab[] durchsucht wird. Dies ist zwar nicht besonders performant,
// verbraucht aber viel weniger Speicher als entsprechende switch-Bloecke.
// Die Umrechnung von Fehlercodes muss nicht schnell sein, daher auch keine
// binaere Suche bei VB-Error -> SFX-Error.

// Neue Fehler-Codes auf alte, Sbx-Kompatible zurueckmappen
sal_uInt16 StarBASIC::GetVBErrorCode( SbError nError )
{
	sal_uInt16 nRet = 0;

	if( SbiRuntime::isVBAEnabled() )
	{
		switch( nError )
		{
			case SbERR_BASIC_ARRAY_FIX:
				return 10;
			case SbERR_BASIC_STRING_OVERFLOW:
				return 14;
			case SbERR_BASIC_EXPR_TOO_COMPLEX:
				return 16;
			case SbERR_BASIC_OPER_NOT_PERFORM:
				return 17;
			case SbERR_BASIC_TOO_MANY_DLL:
				return 47;
			case SbERR_BASIC_LOOP_NOT_INIT:
				return 92;
			default:
				nRet = 0;
		}
	}
	
	// Suchschleife
	const SFX_VB_ErrorItem* pErrItem;
	sal_uInt16 nIndex = 0;
	do
	{
		pErrItem = SFX_VB_ErrorTab + nIndex;
		if( pErrItem->nErrorSFX == nError )
		{
			nRet = pErrItem->nErrorVB;
			break;
		}
		nIndex++;
	}
	while( pErrItem->nErrorVB != 0xFFFF );		// bis End-Marke
	return nRet;
}

SbError	StarBASIC::GetSfxFromVBError( sal_uInt16 nError )
{
	SbError nRet = 0L;

	if( SbiRuntime::isVBAEnabled() )
	{
		switch( nError )
		{
			case 1:
			case 2:
			case 4:
			case 8:
			case 12:
			case 73:
				return 0L;
			case 10:
				return SbERR_BASIC_ARRAY_FIX;
			case 14:
				return SbERR_BASIC_STRING_OVERFLOW;
			case 16:
				return SbERR_BASIC_EXPR_TOO_COMPLEX;
			case 17:
				return SbERR_BASIC_OPER_NOT_PERFORM;
			case 47:
				return SbERR_BASIC_TOO_MANY_DLL;
			case 92:
				return SbERR_BASIC_LOOP_NOT_INIT;
			default:
				nRet = 0L;
		}
	}
	const SFX_VB_ErrorItem* pErrItem;
	sal_uInt16 nIndex = 0;
	do
	{
		pErrItem = SFX_VB_ErrorTab + nIndex;
		if( pErrItem->nErrorVB == nError )
		{
			nRet = pErrItem->nErrorSFX;
			break;
		}
		else if( pErrItem->nErrorVB > nError )
			break;				// kann nicht mehr gefunden werden

		nIndex++;
	}
	while( pErrItem->nErrorVB != 0xFFFF );		// bis End-Marke
	return nRet;
}

// Error- / Break-Daten setzen
void StarBASIC::SetErrorData
( SbError nCode, sal_uInt16 nLine, sal_uInt16 nCol1, sal_uInt16 nCol2 )
{
	SbiGlobals& aGlobals = *GetSbData();
	aGlobals.nCode = nCode;
	aGlobals.nLine = nLine;
	aGlobals.nCol1 = nCol1;
	aGlobals.nCol2 = nCol2;
}

//----------------------------------------------------------------
// Hilfsklasse zum Zugriff auf String SubResourcen einer Resource.
// Quelle: sfx2\source\doc\docfile.cxx (TLX)
struct BasicStringList_Impl : private Resource
{
	ResId aResId;

	BasicStringList_Impl( ResId& rErrIdP,  sal_uInt16 nId)
		: Resource( rErrIdP ),aResId(nId, *rErrIdP.GetResMgr() ){}
	~BasicStringList_Impl() { FreeResource(); }

	String GetString(){ return String( aResId ); }
	sal_Bool IsErrorTextAvailable( void )
		{ return IsAvailableRes(aResId.SetRT(RSC_STRING)); }
};
//----------------------------------------------------------------

// #60175 Flag, das bei Basic-Fehlern das Anziehen der SFX-Resourcen verhindert
static sal_Bool bStaticSuppressSfxResource = sal_False;

void StarBASIC::StaticSuppressSfxResource( sal_Bool bSuppress )
{
	bStaticSuppressSfxResource = bSuppress;
}

// Hack for #83750, use bStaticSuppressSfxResource as setup flag
sal_Bool runsInSetup( void )
{
	return bStaticSuppressSfxResource;
}


void StarBASIC::MakeErrorText( SbError nId, const String& aMsg )
{
	vos::OGuard aSolarGuard( Application::GetSolarMutex() );

	if( bStaticSuppressSfxResource )
	{
		GetSbData()->aErrMsg = String( RTL_CONSTASCII_USTRINGPARAM("No resource: Error message not available") );
		return;
	}

	sal_uInt16 nOldID = GetVBErrorCode( nId );

	// Hilfsklasse instanzieren
	BasResId aId( RID_BASIC_START );
	BasicStringList_Impl aMyStringList( aId, sal_uInt16(nId & ERRCODE_RES_MASK) );

	if( aMyStringList.IsErrorTextAvailable() )
	{
		// Merge Message mit Zusatztext
		String aMsg1 = aMyStringList.GetString();
		// Argument-Platzhalter durch %s ersetzen
		String aSrgStr( RTL_CONSTASCII_USTRINGPARAM("$(ARG1)") );
		sal_uInt16 nResult = aMsg1.Search( aSrgStr );

		if( nResult != STRING_NOTFOUND )
		{
			aMsg1.Erase( nResult, aSrgStr.Len() );
			aMsg1.Insert( aMsg, nResult );
		}
		GetSbData()->aErrMsg = aMsg1;
	}
	else if( nOldID != 0 )
	{
		String aStdMsg( RTL_CONSTASCII_USTRINGPARAM("Fehler ") );
		aStdMsg += String::CreateFromInt32( nOldID);
		aStdMsg += String( RTL_CONSTASCII_USTRINGPARAM(": Kein Fehlertext verfuegbar!") );
		GetSbData()->aErrMsg = aStdMsg;
	}
	else
		GetSbData()->aErrMsg = String::EmptyString();

}

sal_Bool StarBASIC::CError
	( SbError code, const String& rMsg, sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 )
{
	vos::OGuard aSolarGuard( Application::GetSolarMutex() );

	// Compiler-Fehler waehrend der Laufzeit -> Programm anhalten
	if( IsRunning() )
	{
		// #109018 Check if running Basic is affected
		StarBASIC* pStartedBasic = pINST->GetBasic();
		if( pStartedBasic != this )
			return sal_False;

		Stop();
	}

	// Flag setzen, damit GlobalRunInit den Fehler mitbekommt
	GetSbData()->bGlobalInitErr = sal_True;

	// Fehlertext basteln
	MakeErrorText( code, rMsg );

	// Umsetzung des Codes fuer String-Transport in SFX-Error
	if( rMsg.Len() )
		code = (sal_uIntPtr)*new StringErrorInfo( code, String(rMsg) );

	SetErrorData( code, l, c1, c2 );
	GetSbData()->bCompiler = sal_True;
	sal_Bool bRet;
	if( GetSbData()->aErrHdl.IsSet() )
		bRet = (sal_Bool) GetSbData()->aErrHdl.Call( this );
	else
		bRet = ErrorHdl();
	GetSbData()->bCompiler = sal_False;		// nur sal_True fuer Error-Handler
	return bRet;
}

sal_Bool StarBASIC::RTError
	( SbError code, sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 )
{
	return RTError( code, String(), l, c1, c2 );
}

sal_Bool StarBASIC::RTError( SbError code, const String& rMsg, sal_uInt16 l, sal_uInt16 c1, sal_uInt16 c2 )
{
	vos::OGuard aSolarGuard( Application::GetSolarMutex() );

	SbError c = code;
	if( (c & ERRCODE_CLASS_MASK) == ERRCODE_CLASS_COMPILER )
		c = 0;
	MakeErrorText( c, rMsg );

	// Umsetzung des Codes fuer String-Transport in SFX-Error
	if( rMsg.Len() )
	{
		// very confusing, even though MakeErrorText sets up the error text
		// seems that this is not used ( if rMsg already has content )
		// In the case of VBA MakeErrorText also formats the error to be alittle more 
		// like vba ( adds an error number etc )
		if ( SbiRuntime::isVBAEnabled() && ( code == SbERR_BASIC_COMPAT ) )
		{
			String aTmp = '\'';
			aTmp += String::CreateFromInt32( SbxErrObject::getUnoErrObject()->getNumber() );
			aTmp += String( RTL_CONSTASCII_USTRINGPARAM("\'\n") );
			aTmp +=  GetSbData()->aErrMsg.Len() ? GetSbData()->aErrMsg : rMsg;
			code = (sal_uIntPtr)*new StringErrorInfo( code, aTmp );
		}
		else
			code = (sal_uIntPtr)*new StringErrorInfo( code, String(rMsg) );
	}

	SetErrorData( code, l, c1, c2 );
	if( GetSbData()->aErrHdl.IsSet() )
		return (sal_Bool) GetSbData()->aErrHdl.Call( this );
	else
		return ErrorHdl();
}

void StarBASIC::Error( SbError n )
{
	Error( n, String() );
}

void StarBASIC::Error( SbError n, const String& rMsg )
{
	if( pINST )
		pINST->Error( n, rMsg );
}

void StarBASIC::FatalError( SbError n )
{
	if( pINST )
		pINST->FatalError( n );
}

void StarBASIC::FatalError( SbError _errCode, const String& _details )
{
	if( pINST )
		pINST->FatalError( _errCode, _details );
}

SbError StarBASIC::GetErrBasic()
{
	if( pINST )
		return pINST->GetErr();
	else
		return 0;
}

// #66536 Zusatz-Message fuer RTL-Funktion Error zugreifbar machen
String StarBASIC::GetErrorMsg()
{
	if( pINST )
		return pINST->GetErrorMsg();
	else
		return String();
}

sal_uInt16 StarBASIC::GetErl()
{
	if( pINST )
		return pINST->GetErl();
	else
		return 0;
}

sal_Bool __EXPORT StarBASIC::ErrorHdl()
{
	return (sal_Bool) ( aErrorHdl.IsSet()
		? aErrorHdl.Call( this ) : sal_False );
}

Link StarBASIC::GetGlobalErrorHdl()
{
	return GetSbData()->aErrHdl;
}

void StarBASIC::SetGlobalErrorHdl( const Link& rLink )
{
	GetSbData()->aErrHdl = rLink;
}


Link StarBASIC::GetGlobalBreakHdl()
{
	return GetSbData()->aBreakHdl;
}

void StarBASIC::SetGlobalBreakHdl( const Link& rLink )
{
	GetSbData()->aBreakHdl = rLink;
}

SbxArrayRef StarBASIC::getUnoListeners( void )
{
    if( !xUnoListeners.Is() )
        xUnoListeners = new SbxArray();
    return xUnoListeners;
}


/**************************************************************************
*
*	Laden und Speichern
*
**************************************************************************/

sal_Bool StarBASIC::LoadData( SvStream& r, sal_uInt16 nVer )
{
	if( !SbxObject::LoadData( r, nVer ) )
		return sal_False;

    // #95459 Delete dialogs, otherwise endless recursion
    // in SbxVarable::GetType() if dialogs are accessed
    sal_uInt16 nObjCount = pObjs->Count();
    SbxVariable** ppDeleteTab = new SbxVariable*[ nObjCount ];
	sal_uInt16 nObj;

	for( nObj = 0 ; nObj < nObjCount ; nObj++ )
	{
		SbxVariable* pVar = pObjs->Get( nObj );
		StarBASIC* pBasic = dynamic_cast< StarBASIC* >( pVar );
        ppDeleteTab[nObj] = pBasic ? NULL : pVar;
	}
	for( nObj = 0 ; nObj < nObjCount ; nObj++ )
	{
        SbxVariable* pVar = ppDeleteTab[nObj];
        if( pVar )
            pObjs->Remove( pVar );
    }
    delete[] ppDeleteTab;

	sal_uInt16 nMod;
	pModules->Clear();
	r >> nMod;
	for( sal_uInt16 i = 0; i < nMod; i++ )
	{
		SbModule* pMod = (SbModule*) SbxBase::Load( r );
		if( !pMod )
			return sal_False;
		else if( dynamic_cast< SbJScriptModule* >(pMod) )
		{
			// Ref zuweisen, damit pMod deleted wird
			SbModuleRef xRef = pMod;
		}
		else
		{
			pMod->SetParent( this );
			pModules->Put( pMod, i );
		}
	}
	// HACK fuer SFX-Mist!
	SbxVariable* p = Find( String( RTL_CONSTASCII_USTRINGPARAM("FALSE") ), SbxCLASS_PROPERTY );
	if( p )
		Remove( p );
	p = Find( String( RTL_CONSTASCII_USTRINGPARAM("TRUE") ), SbxCLASS_PROPERTY );
	if( p )
		Remove( p );
	// Ende des Hacks!
	// Suche ueber StarBASIC ist immer global
	DBG_ASSERT( IsSet( SBX_GBLSEARCH ), "Basic ohne GBLSEARCH geladen" );
	SetFlag( SBX_GBLSEARCH );
	return sal_True;
}

sal_Bool StarBASIC::StoreData( SvStream& r ) const
{
	if( !SbxObject::StoreData( r ) )
		return sal_False;
	r << (sal_uInt16) pModules->Count();
	for( sal_uInt16 i = 0; i < pModules->Count(); i++ )
	{
		SbModule* p = (SbModule*) pModules->Get( i );
		if( !p->Store( r ) )
			return sal_False;
	}
	return sal_True;
}

sal_Bool StarBASIC::LoadOldModules( SvStream& )
{
	return sal_False;
}

bool StarBASIC::GetUNOConstant( const sal_Char* _pAsciiName, ::com::sun::star::uno::Any& aOut )
{
    bool bRes = false;
    ::rtl::OUString sVarName( ::rtl::OUString::createFromAscii( _pAsciiName ) );
    SbUnoObject* pGlobs = dynamic_cast<SbUnoObject*>( Find( sVarName, SbxCLASS_DONTCARE ) );
    if ( pGlobs )
    {
        aOut = pGlobs->getUnoAny();
        bRes = true;
    }
    return bRes;
}

Reference< frame::XModel > StarBASIC::GetModelFromBasic( SbxObject* pBasic )
{
    OSL_PRECOND( pBasic != NULL, "getModelFromBasic: illegal call!" );
    if ( !pBasic )
        return NULL;

    // look for the ThisComponent variable, first in the parent (which
    // might be the document's Basic), then in the parent's parent (which might be
    // the application Basic)
    const ::rtl::OUString sThisComponent( RTL_CONSTASCII_USTRINGPARAM( "ThisComponent" ) );
    SbxVariable* pThisComponent = NULL;

    SbxObject* pLookup = pBasic->GetParent();
    while ( pLookup && !pThisComponent )
    {
        pThisComponent = pLookup->Find( sThisComponent, SbxCLASS_OBJECT );
        pLookup = pLookup->GetParent();
    }
    if ( !pThisComponent )
    {
        OSL_TRACE("Failed to get ThisComponent");
            // the application Basic, at the latest, should have this variable
        return NULL;
    }

    Any aThisComponentAny( sbxToUnoValue( pThisComponent ) );
    Reference< frame::XModel > xModel( aThisComponentAny, UNO_QUERY );
    if ( !xModel.is() )
    {
        // it's no XModel. Okay, ThisComponent nowadays is allowed to be a controller.
        Reference< frame::XController > xController( aThisComponentAny, UNO_QUERY );
        if ( xController.is() )
            xModel = xController->getModel();
    }

    if ( !xModel.is() )
        return NULL;

#if OSL_DEBUG_LEVEL > 0
    OSL_TRACE("Have model ThisComponent points to url %s",
        ::rtl::OUStringToOString( xModel->getURL(),
            RTL_TEXTENCODING_ASCII_US ).pData->buffer );
#endif

    return xModel;
}


//========================================================================
// #118116 Implementation Collection object

static const char pCountStr[]	= "Count";
static const char pAddStr[]		= "Add";
static const char pItemStr[]	= "Item";
static const char pRemoveStr[]	= "Remove";
static sal_uInt16 nCountHash = 0, nAddHash, nItemHash, nRemoveHash;

SbxInfoRef BasicCollection::xAddInfo = NULL;
SbxInfoRef BasicCollection::xItemInfo = NULL;

BasicCollection::BasicCollection( const XubString& rClass )
			 : SbxObject( rClass )
{
	if( !nCountHash )
	{
		nCountHash  = MakeHashCode( String::CreateFromAscii( pCountStr ) );
		nAddHash    = MakeHashCode( String::CreateFromAscii( pAddStr ) );
		nItemHash   = MakeHashCode( String::CreateFromAscii( pItemStr ) );
		nRemoveHash = MakeHashCode( String::CreateFromAscii( pRemoveStr ) );
	}
	Initialize();
	
}

BasicCollection::~BasicCollection()
{}

void BasicCollection::Clear()
{
	SbxObject::Clear();
	Initialize();
}

void BasicCollection::Initialize()
{
	xItemArray = new SbxArray();
	SetType( SbxOBJECT );
	SetFlag( SBX_FIXED );
	ResetFlag( SBX_WRITE );
	SbxVariable* p;
	p = Make( String::CreateFromAscii( pCountStr ), SbxCLASS_PROPERTY, SbxINTEGER );
	p->ResetFlag( SBX_WRITE );
	p->SetFlag( SBX_DONTSTORE );
	p = Make( String::CreateFromAscii( pAddStr ), SbxCLASS_METHOD, SbxEMPTY );
	p->SetFlag( SBX_DONTSTORE );
	p = Make( String::CreateFromAscii( pItemStr ), SbxCLASS_METHOD, SbxVARIANT );
	p->SetFlag( SBX_DONTSTORE );
	p = Make( String::CreateFromAscii( pRemoveStr ), SbxCLASS_METHOD, SbxEMPTY );
	p->SetFlag( SBX_DONTSTORE );
	if ( !xAddInfo.Is() ) 
	{
		xAddInfo = new SbxInfo;
		xAddInfo->AddParam(  String( RTL_CONSTASCII_USTRINGPARAM("Item") ), SbxVARIANT, SBX_READ );	
		xAddInfo->AddParam(  String( RTL_CONSTASCII_USTRINGPARAM("Key") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL );	
		xAddInfo->AddParam(  String( RTL_CONSTASCII_USTRINGPARAM("Before") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL );	
		xAddInfo->AddParam(  String( RTL_CONSTASCII_USTRINGPARAM("After") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL );	
	}
	if ( !xItemInfo.Is() ) 
	{
		xItemInfo = new SbxInfo;
		xItemInfo->AddParam(  String( RTL_CONSTASCII_USTRINGPARAM("Index") ), SbxVARIANT, SBX_READ | SBX_OPTIONAL);	
	}
}

SbxVariable* BasicCollection::Find( const XubString& rName, SbxClassType t )
{
	SbxVariable* pFind = SbxObject::Find( rName, t );
	return pFind;
}

void BasicCollection::SFX_NOTIFY( SfxBroadcaster& rCst, const TypeId& rId1,
								const SfxHint& rHint, const TypeId& rId2 )
{
	const SbxHint* p = dynamic_cast< const SbxHint* >( &rHint);
	if( p )
	{
		sal_uIntPtr nId = p->GetId();
		sal_Bool bRead  = sal_Bool( nId == SBX_HINT_DATAWANTED );
		sal_Bool bWrite = sal_Bool( nId == SBX_HINT_DATACHANGED );
		sal_Bool bRequestInfo = sal_Bool( nId == SBX_HINT_INFOWANTED );
		SbxVariable* pVar = p->GetVar();
		SbxArray* pArg = pVar->GetParameters();
		XubString aVarName( pVar->GetName() );
		if( bRead || bWrite )
		{
			if( pVar->GetHashCode() == nCountHash
				  && aVarName.EqualsIgnoreCaseAscii( pCountStr ) )
				pVar->PutLong( xItemArray->Count32() );
			else if( pVar->GetHashCode() == nAddHash
				  && aVarName.EqualsIgnoreCaseAscii( pAddStr ) )
				CollAdd( pArg );
			else if( pVar->GetHashCode() == nItemHash
				  && aVarName.EqualsIgnoreCaseAscii( pItemStr ) )
				CollItem( pArg );
			else if( pVar->GetHashCode() == nRemoveHash
				  && aVarName.EqualsIgnoreCaseAscii( pRemoveStr ) )
				CollRemove( pArg );
			else
				SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 );
			return;
		}
		else if ( bRequestInfo )
		{
			if( pVar->GetHashCode() == nAddHash
				  && aVarName.EqualsIgnoreCaseAscii( pAddStr ) )
				pVar->SetInfo( xAddInfo );
			else if( pVar->GetHashCode() == nItemHash
				  && aVarName.EqualsIgnoreCaseAscii( pItemStr ) )
				pVar->SetInfo( xItemInfo );
		}
	}
	SbxObject::SFX_NOTIFY( rCst, rId1, rHint, rId2 );
}

sal_Int32 BasicCollection::implGetIndex( SbxVariable* pIndexVar )
{
	sal_Int32 nIndex = -1;
	if( pIndexVar->GetType() == SbxSTRING )
		nIndex = implGetIndexForName( pIndexVar->GetString() );
	else
		nIndex = pIndexVar->GetLong() - 1;
	return nIndex;
}

sal_Int32 BasicCollection::implGetIndexForName( const String& rName )
{
	sal_Int32 nIndex = -1;
	sal_Int32 nCount = xItemArray->Count32();
	sal_Int32 nNameHash = MakeHashCode( rName );
	for( sal_Int32 i = 0 ; i < nCount ; i++ )
	{
		SbxVariable* pVar = xItemArray->Get32( i );
		if( pVar->GetHashCode() == nNameHash &&
			pVar->GetName().EqualsIgnoreCaseAscii( rName ) )
		{
			nIndex = i;
			break;
		}
	}
	return nIndex;
}

void BasicCollection::CollAdd( SbxArray* pPar_ )
{
	sal_uInt16 nCount = pPar_->Count();
	if( nCount < 2 || nCount > 5 )
	{
		SetError( SbxERR_WRONG_ARGS );
		return;
	}

	SbxVariable* pItem = pPar_->Get(1);
	if( pItem )
	{
		int nNextIndex;
		if( nCount < 4 )
		{
			nNextIndex = xItemArray->Count();
		}
		else
		{
			SbxVariable* pBefore = pPar_->Get(3);
			if( nCount == 5 )
			{
				if( !( pBefore->IsErr() || ( pBefore->GetType() == SbxEMPTY ) ) )
				{
					SetError( SbERR_BAD_ARGUMENT );
					return;
				}
				SbxVariable* pAfter = pPar_->Get(4);
				sal_Int32 nAfterIndex = implGetIndex( pAfter );
				if( nAfterIndex == -1 )
				{
					SetError( SbERR_BAD_ARGUMENT );
					return;
				}
				nNextIndex = nAfterIndex + 1;
			}
			else // if( nCount == 4 )
			{
				sal_Int32 nBeforeIndex = implGetIndex( pBefore );
				if( nBeforeIndex == -1 )
				{
					SetError( SbERR_BAD_ARGUMENT );
					return;
				}
				nNextIndex = nBeforeIndex;
			}
		}

		SbxVariableRef pNewItem = new SbxVariable( *pItem );
		if( nCount >= 3 )
		{
			SbxVariable* pKey = pPar_->Get(2);
			if( !( pKey->IsErr() || ( pKey->GetType() == SbxEMPTY ) ) )
			{
				if( pKey->GetType() != SbxSTRING )
				{
					SetError( SbERR_BAD_ARGUMENT );
					return;
				}
				String aKey = pKey->GetString();
				if( implGetIndexForName( aKey ) != -1 )
				{
					SetError( SbERR_BAD_ARGUMENT );
					return;
				}
				pNewItem->SetName( aKey );
			}
		}
		pNewItem->SetFlag( SBX_READWRITE );
		xItemArray->Insert32( pNewItem, nNextIndex );
	}
	else
	{
		SetError( SbERR_BAD_ARGUMENT );
		return;
	}
}

void BasicCollection::CollItem( SbxArray* pPar_ )
{
	if( pPar_->Count() != 2 )
	{
		SetError( SbxERR_WRONG_ARGS );
		return;
	}
	SbxVariable* pRes = NULL;
	SbxVariable* p = pPar_->Get( 1 );
	sal_Int32 nIndex = implGetIndex( p );
	if( nIndex >= 0 && nIndex < (sal_Int32)xItemArray->Count32() )
		pRes = xItemArray->Get32( nIndex );
	if( !pRes )
		SetError( SbERR_BAD_ARGUMENT );
	else
		*(pPar_->Get(0)) = *pRes;
}

void BasicCollection::CollRemove( SbxArray* pPar_ )
{
	if( pPar_ == NULL || pPar_->Count() != 2 )
	{
		SetError( SbxERR_WRONG_ARGS );
		return;
	}

	SbxVariable* p = pPar_->Get( 1 );
	sal_Int32 nIndex = implGetIndex( p );
	if( nIndex >= 0 && nIndex < (sal_Int32)xItemArray->Count32() )
	{
		xItemArray->Remove32( nIndex );

		// Correct for stack if necessary
		SbiInstance* pInst = pINST;
		SbiRuntime* pRT = pInst ? pInst->pRun : NULL;
		if( pRT )
		{
			SbiForStack* pStack = pRT->FindForStackItemForCollection( this );
			if( pStack != NULL )
			{
				if( pStack->nCurCollectionIndex >= nIndex )
					--pStack->nCurCollectionIndex;
			}
		}
	}
	else
		SetError( SbERR_BAD_ARGUMENT );
}

