/**************************************************************
 *
 * 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 <vcl/msgbox.hxx>
#include <tools/fsys.hxx>

#include "errobject.hxx"
#include "runtime.hxx"
#include "sbintern.hxx"
#include "iosys.hxx"
#include <sb.hrc>
#include <basrid.hxx>
#include "sbunoobj.hxx"
#include "image.hxx"
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/util/SearchOptions.hdl>
#include <vcl/svapp.hxx>
#include <unotools/textsearch.hxx>

Reference< XInterface > createComListener( const Any& aControlAny, const ::rtl::OUString& aVBAType,
										   const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj );

#include <algorithm>
#include <hash_map>

SbxVariable* getDefaultProp( SbxVariable* pRef );

void SbiRuntime::StepNOP()
{}

void SbiRuntime::StepArith( SbxOperator eOp )
{
	SbxVariableRef p1 = PopVar();
	TOSMakeTemp();
	SbxVariable* p2 = GetTOS();


	// This could & should be moved to the MakeTempTOS() method in runtime.cxx
	// In the code which this is cut'npaste from there is a check for a ref
	// count != 1 based on which the copy of the SbxVariable is done.
	// see orig code in MakeTempTOS ( and I'm not sure what the significance,
	// of that is )
	// here we alway seem to have a refcount of 1. Also it seems that
	// MakeTempTOS is called for other operation, so I hold off for now
	// until I have a better idea
	if ( bVBAEnabled
		&& ( p2->GetType() == SbxOBJECT || p2->GetType() == SbxVARIANT )
	)
	{
		SbxVariable* pDflt = getDefaultProp( p2 );
		if ( pDflt )
		{
			pDflt->Broadcast( SBX_HINT_DATAWANTED );
			// replacing new p2 on stack causes object pointed by
			// pDft->pParent to be deleted, when p2->Compute() is
			// called below pParent is accessed ( but its deleted )
			// so set it to NULL now
			pDflt->SetParent( NULL );
			p2 = new SbxVariable( *pDflt );
			p2->SetFlag( SBX_READWRITE );
			refExprStk->Put( p2, nExprLvl - 1 );
		}
	}

	p2->ResetFlag( SBX_FIXED );
	p2->Compute( eOp, *p1 );

    checkArithmeticOverflow( p2 );
}

void SbiRuntime::StepUnary( SbxOperator eOp )
{
	TOSMakeTemp();
	SbxVariable* p = GetTOS();
	p->Compute( eOp, *p );
}

void SbiRuntime::StepCompare( SbxOperator eOp )
{
	SbxVariableRef p1 = PopVar();
	SbxVariableRef p2 = PopVar();

	// Make sure objects with default params have
	// values ( and type ) set as appropriate
	SbxDataType p1Type = p1->GetType();
	SbxDataType p2Type = p2->GetType();
	if ( p1Type == p2Type )
	{
		if ( p1Type == SbxEMPTY )
		{
			p1->Broadcast( SBX_HINT_DATAWANTED );
			p2->Broadcast( SBX_HINT_DATAWANTED );
		}
		// if both sides are an object and have default props
		// then we need to use the default props
		// we don't need to worry if only one side ( lhs, rhs ) is an
		// object ( object side will get coerced to correct type in
		// Compare )
		else if ( p1Type ==  SbxOBJECT )
		{
			SbxVariable* pDflt = getDefaultProp( p1 );
			if ( pDflt )
			{
				p1 = pDflt;
				p1->Broadcast( SBX_HINT_DATAWANTED );
			}
			pDflt = getDefaultProp( p2 );
			if ( pDflt )
			{
				p2 = pDflt;
				p2->Broadcast( SBX_HINT_DATAWANTED );
			}
		}

	}
	static SbxVariable* pTRUE = NULL;
	static SbxVariable* pFALSE = NULL;

	if( p2->Compare( eOp, *p1 ) )
	{
		if( !pTRUE )
		{
			pTRUE = new SbxVariable;
			pTRUE->PutBool( sal_True );
			pTRUE->AddRef();
		}
		PushVar( pTRUE );
	}
	else
	{
		if( !pFALSE )
		{
			pFALSE = new SbxVariable;
			pFALSE->PutBool( sal_False );
			pFALSE->AddRef();
		}
		PushVar( pFALSE );
	}
}

void SbiRuntime::StepEXP()		{ StepArith( SbxEXP );		}
void SbiRuntime::StepMUL()		{ StepArith( SbxMUL );		}
void SbiRuntime::StepDIV()		{ StepArith( SbxDIV );		}
void SbiRuntime::StepIDIV()		{ StepArith( SbxIDIV );		}
void SbiRuntime::StepMOD()		{ StepArith( SbxMOD );		}
void SbiRuntime::StepPLUS()		{ StepArith( SbxPLUS );		}
void SbiRuntime::StepMINUS()		{ StepArith( SbxMINUS );	}
void SbiRuntime::StepCAT()		{ StepArith( SbxCAT );		}
void SbiRuntime::StepAND()		{ StepArith( SbxAND );		}
void SbiRuntime::StepOR()		{ StepArith( SbxOR );		}
void SbiRuntime::StepXOR()		{ StepArith( SbxXOR );		}
void SbiRuntime::StepEQV()		{ StepArith( SbxEQV );		}
void SbiRuntime::StepIMP()		{ StepArith( SbxIMP );		}

void SbiRuntime::StepNEG()		{ StepUnary( SbxNEG );		}
void SbiRuntime::StepNOT()		{ StepUnary( SbxNOT );		}

void SbiRuntime::StepEQ()		{ StepCompare( SbxEQ );		}
void SbiRuntime::StepNE()		{ StepCompare( SbxNE );		}
void SbiRuntime::StepLT()		{ StepCompare( SbxLT );		}
void SbiRuntime::StepGT()		{ StepCompare( SbxGT );		}
void SbiRuntime::StepLE()		{ StepCompare( SbxLE );		}
void SbiRuntime::StepGE()		{ StepCompare( SbxGE );		}

namespace
{
	bool NeedEsc(sal_Unicode cCode)
	{
		String sEsc(RTL_CONSTASCII_USTRINGPARAM(".^$+\\|{}()"));
		return (STRING_NOTFOUND != sEsc.Search(cCode));
	}

	String VBALikeToRegexp(const String &rIn)
	{
		String sResult;
		const sal_Unicode *start = rIn.GetBuffer();
		const sal_Unicode *end = start + rIn.Len();

		int seenright = 0;

		sResult.Append('^');

		while (start < end)
		{
			switch (*start)
			{
				case '?':
					sResult.Append('.');
					start++;
					break;
				case '*':
					sResult.Append(String(RTL_CONSTASCII_USTRINGPARAM(".*")));
					start++;
					break;
				case '#':
					sResult.Append(String(RTL_CONSTASCII_USTRINGPARAM("[0-9]")));
					start++;
					break;
				case ']':
					sResult.Append('\\');
					sResult.Append(*start++);
					break;
				case '[':
					sResult.Append(*start++);
					seenright = 0;
					while (start < end && !seenright)
					{
						switch (*start)
						{
							case '[':
							case '?':
							case '*':
							sResult.Append('\\');
							sResult.Append(*start);
								break;
							case ']':
							sResult.Append(*start);
								seenright = 1;
								break;
							case '!':
								sResult.Append('^');
								break;
							default:
							if (NeedEsc(*start))
									sResult.Append('\\');
							sResult.Append(*start);
								break;
						}
						start++;
					}
					break;
				default:
					if (NeedEsc(*start))
						sResult.Append('\\');
					sResult.Append(*start++);
			}
		}

		sResult.Append('$');

		return sResult;
	}
}

void SbiRuntime::StepLIKE()
{
    SbxVariableRef refVar1 = PopVar();
    SbxVariableRef refVar2 = PopVar();

    String pattern = VBALikeToRegexp(refVar1->GetString());
    String value = refVar2->GetString();

    com::sun::star::util::SearchOptions aSearchOpt;

    aSearchOpt.algorithmType = com::sun::star::util::SearchAlgorithms_REGEXP;

    aSearchOpt.Locale = Application::GetSettings().GetLocale();
    aSearchOpt.searchString = pattern;

    int bTextMode(1);
    bool bCompatibility = ( pINST && pINST->IsCompatibility() );
    if( bCompatibility )
        bTextMode = GetImageFlag( SBIMG_COMPARETEXT );

    if( bTextMode )
        aSearchOpt.transliterateFlags |= com::sun::star::i18n::TransliterationModules_IGNORE_CASE;

    SbxVariable* pRes = new SbxVariable;
    utl::TextSearch aSearch(aSearchOpt);
    xub_StrLen nStart=0, nEnd=value.Len();
    int bRes = aSearch.SearchFrwrd(value, &nStart, &nEnd);
    pRes->PutBool( bRes != 0 );

    PushVar( pRes );
}

// TOS und TOS-1 sind beides Objektvariable und enthalten den selben Pointer

void SbiRuntime::StepIS()
{
	SbxVariableRef refVar1 = PopVar();
	SbxVariableRef refVar2 = PopVar();

	SbxDataType eType1 = refVar1->GetType();
	SbxDataType eType2 = refVar2->GetType();
	if ( eType1 == SbxEMPTY )
	{
		refVar1->Broadcast( SBX_HINT_DATAWANTED );
		eType1 = refVar1->GetType();
	}
	if ( eType2 == SbxEMPTY )
	{
		refVar2->Broadcast( SBX_HINT_DATAWANTED );
		eType2 = refVar2->GetType();
	}

	sal_Bool bRes = sal_Bool( eType1 == SbxOBJECT && eType2 == SbxOBJECT );
	if ( bVBAEnabled  && !bRes )
		Error( SbERR_INVALID_USAGE_OBJECT );
	bRes = ( bRes && refVar1->GetObject() == refVar2->GetObject() );
	SbxVariable* pRes = new SbxVariable;
	pRes->PutBool( bRes );
	PushVar( pRes );
}

// Aktualisieren des Wertes von TOS

void SbiRuntime::StepGET()
{
	SbxVariable* p = GetTOS();
	p->Broadcast( SBX_HINT_DATAWANTED );
}

// #67607 Uno-Structs kopieren
inline void checkUnoStructCopy( SbxVariableRef& refVal, SbxVariableRef& refVar )
{
	SbxDataType eVarType = refVar->GetType();
	if( eVarType != SbxOBJECT )
        return;

	SbxObjectRef xValObj = (SbxObject*)refVal->GetObject();
	if( !xValObj.Is() || xValObj->ISA(SbUnoAnyObject) )
        return;

	// #115826: Exclude ProcedureProperties to avoid call to Property Get procedure
	if( refVar->ISA(SbProcedureProperty) )
		return;

	SbxObjectRef xVarObj = (SbxObject*)refVar->GetObject();
	SbxDataType eValType = refVal->GetType();
	if( eValType == SbxOBJECT && xVarObj == xValObj )
	{
		SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)xVarObj);
		if( pUnoObj )
		{
			Any aAny = pUnoObj->getUnoAny();
			if( aAny.getValueType().getTypeClass() == TypeClass_STRUCT )
			{
				SbUnoObject* pNewUnoObj = new SbUnoObject( pUnoObj->GetName(), aAny );
				// #70324: ClassName uebernehmen
				pNewUnoObj->SetClassName( pUnoObj->GetClassName() );
				refVar->PutObject( pNewUnoObj );
			}
		}
	}
}


// Ablage von TOS in TOS-1

void SbiRuntime::StepPUT()
{
	SbxVariableRef refVal = PopVar();
	SbxVariableRef refVar = PopVar();
	// Store auf die eigene Methode (innerhalb einer Function)?
	sal_Bool bFlagsChanged = sal_False;
	sal_uInt16 n = 0;
	if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
	{
		bFlagsChanged = sal_True;
		n = refVar->GetFlags();
		refVar->SetFlag( SBX_WRITE );
	}

	// if left side arg is an object or variant and right handside isn't
	// either an object or a variant then try and see if a default
	// property exists.
	// to use e.g. Range{"A1") = 34
	// could equate to Range("A1").Value = 34
	if ( bVBAEnabled )
	{
		if ( refVar->GetType() == SbxOBJECT  )
		{
			SbxVariable* pDflt = getDefaultProp( refVar );
			if ( pDflt )
				refVar = pDflt;
		}
		if (  refVal->GetType() == SbxOBJECT  )
		{
			SbxVariable* pDflt = getDefaultProp( refVal );
			if ( pDflt )
				refVal = pDflt;
		}
	}

	*refVar = *refVal;
	// lhs is a property who's value is currently null
	if ( !bVBAEnabled || ( bVBAEnabled && refVar->GetType() != SbxEMPTY ) )
	// #67607 Uno-Structs kopieren
		checkUnoStructCopy( refVal, refVar );
	if( bFlagsChanged )
		refVar->SetFlags( n );
}


// VBA Dim As New behavior handling, save init object information
struct DimAsNewRecoverItem
{
	String			m_aObjClass;
	String			m_aObjName;
	SbxObject*		m_pObjParent;
	SbModule*		m_pClassModule;

	DimAsNewRecoverItem( void )
		: m_pObjParent( NULL )
		, m_pClassModule( NULL )
	{}

	DimAsNewRecoverItem( const String& rObjClass, const String& rObjName,
		SbxObject* pObjParent, SbModule* pClassModule )
			: m_aObjClass( rObjClass )
			, m_aObjName( rObjName )
			, m_pObjParent( pObjParent )
			, m_pClassModule( pClassModule )
	{}

};


struct SbxVariablePtrHash
{
    size_t operator()( SbxVariable* pVar ) const
        { return (size_t)pVar; }
};

typedef std::hash_map< SbxVariable*, DimAsNewRecoverItem, SbxVariablePtrHash >	DimAsNewRecoverHash;

static DimAsNewRecoverHash		GaDimAsNewRecoverHash;

void removeDimAsNewRecoverItem( SbxVariable* pVar )
{
	DimAsNewRecoverHash::iterator it = GaDimAsNewRecoverHash.find( pVar );
	if( it != GaDimAsNewRecoverHash.end() )
		GaDimAsNewRecoverHash.erase( it );
}


// Speichern Objektvariable
// Nicht-Objekt-Variable fuehren zu Fehlern

static const char pCollectionStr[] = "Collection";

void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, bool bHandleDefaultProp )
{
	// #67733 Typen mit Array-Flag sind auch ok

	// Check var, !object is no error for sure if, only if type is fixed
	SbxDataType eVarType = refVar->GetType();
	if( !bHandleDefaultProp && eVarType != SbxOBJECT && !(eVarType & SbxARRAY) && refVar->IsFixed() )
	{
		Error( SbERR_INVALID_USAGE_OBJECT );
		return;
	}

	// Check value, !object is no error for sure if, only if type is fixed
	SbxDataType eValType = refVal->GetType();
//	bool bGetValObject = false;
	if( !bHandleDefaultProp && eValType != SbxOBJECT && !(eValType & SbxARRAY) && refVal->IsFixed() )
	{
		Error( SbERR_INVALID_USAGE_OBJECT );
		return;
	}

	// Getting in here causes problems with objects with default properties
	// if they are SbxEMPTY I guess
	if ( !bHandleDefaultProp || ( bHandleDefaultProp && eValType == SbxOBJECT ) )
	{
	// Auf refVal GetObject fuer Collections ausloesen
		SbxBase* pObjVarObj = refVal->GetObject();
		if( pObjVarObj )
		{
			SbxVariableRef refObjVal = PTR_CAST(SbxObject,pObjVarObj);

			// #67733 Typen mit Array-Flag sind auch ok
			if( refObjVal )
				refVal = refObjVal;
			else if( !(eValType & SbxARRAY) )
				refVal = NULL;
		}
	}

	// #52896 Wenn Uno-Sequences bzw. allgemein Arrays einer als
	// Object deklarierten Variable zugewiesen werden, kann hier
	// refVal ungueltig sein!
	if( !refVal )
	{
		Error( SbERR_INVALID_USAGE_OBJECT );
	}
	else
	{
		// Store auf die eigene Methode (innerhalb einer Function)?
		sal_Bool bFlagsChanged = sal_False;
		sal_uInt16 n = 0;
		if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
		{
			bFlagsChanged = sal_True;
			n = refVar->GetFlags();
			refVar->SetFlag( SBX_WRITE );
		}
		SbProcedureProperty* pProcProperty = PTR_CAST(SbProcedureProperty,(SbxVariable*)refVar);
		if( pProcProperty )
			pProcProperty->setSet( true );

		if ( bHandleDefaultProp )
		{
			// get default properties for lhs & rhs where necessary
			// SbxVariable* defaultProp = NULL; unused variable
			bool bLHSHasDefaultProp = false;
			// LHS try determine if a default prop exists
			if ( refVar->GetType() == SbxOBJECT )
			{
				SbxVariable* pDflt = getDefaultProp( refVar );
				if ( pDflt )
				{
					refVar = pDflt;
					bLHSHasDefaultProp = true;
				}
			}
			// RHS only get a default prop is the rhs has one
			if (  refVal->GetType() == SbxOBJECT )
			{
				// check if lhs is a null object
				// if it is then use the object not the default property
				SbxObject* pObj = NULL;


				pObj = PTR_CAST(SbxObject,(SbxVariable*)refVar);

				// calling GetObject on a SbxEMPTY variable raises
				// object not set errors, make sure its an Object
				if ( !pObj && refVar->GetType() == SbxOBJECT )
				{
					SbxBase* pObjVarObj = refVar->GetObject();
					pObj = PTR_CAST(SbxObject,pObjVarObj);
				}
				SbxVariable* pDflt = NULL;
				if ( pObj || bLHSHasDefaultProp )
					// lhs is either a valid object || or has a defaultProp
					pDflt = getDefaultProp( refVal );
				if ( pDflt )
					refVal = pDflt;
			}
		}

		// Handle Dim As New
		sal_Bool bDimAsNew = bVBAEnabled && refVar->IsSet( SBX_DIM_AS_NEW );
		SbxBaseRef xPrevVarObj;
		if( bDimAsNew )
			xPrevVarObj = refVar->GetObject();

		// Handle withevents
		sal_Bool bWithEvents = refVar->IsSet( SBX_WITH_EVENTS );
        if ( bWithEvents )
        {
            Reference< XInterface > xComListener;

            SbxBase* pObj = refVal->GetObject();
            SbUnoObject* pUnoObj = (pObj != NULL) ? PTR_CAST(SbUnoObject,pObj) : NULL;
            if( pUnoObj != NULL )
            {
                Any aControlAny = pUnoObj->getUnoAny();
                String aDeclareClassName = refVar->GetDeclareClassName();
                ::rtl::OUString aVBAType = aDeclareClassName;
                ::rtl::OUString aPrefix = refVar->GetName();
                SbxObjectRef xScopeObj = refVar->GetParent();
                xComListener = createComListener( aControlAny, aVBAType, aPrefix, xScopeObj );

                refVal->SetDeclareClassName( aDeclareClassName );
                refVal->SetComListener( xComListener, &rBasic );		// Hold reference
            }

            *refVar = *refVal;
        }
        else
        {
            *refVar = *refVal;
        }

        if ( bDimAsNew )
        {
			if( !refVar->ISA(SbxObject) )
			{
	            SbxBase* pValObjBase = refVal->GetObject();
				if( pValObjBase == NULL )
				{
					if( xPrevVarObj.Is() )
					{
						// Object is overwritten with NULL, instantiate init object
						DimAsNewRecoverHash::iterator it = GaDimAsNewRecoverHash.find( refVar );
						if( it != GaDimAsNewRecoverHash.end() )
						{
							const DimAsNewRecoverItem& rItem = it->second;
							if( rItem.m_pClassModule != NULL )
							{
								SbClassModuleObject* pNewObj = new SbClassModuleObject( rItem.m_pClassModule );
								pNewObj->SetName( rItem.m_aObjName );
								pNewObj->SetParent( rItem.m_pObjParent );
								refVar->PutObject( pNewObj );
							}
							else if( rItem.m_aObjClass.EqualsIgnoreCaseAscii( pCollectionStr ) )
							{
								BasicCollection* pNewCollection = new BasicCollection( String( RTL_CONSTASCII_USTRINGPARAM(pCollectionStr) ) );
								pNewCollection->SetName( rItem.m_aObjName );
								pNewCollection->SetParent( rItem.m_pObjParent );
								refVar->PutObject( pNewCollection );
							}
						}
					}
				}
				else
				{
					// Does old value exist?
					bool bFirstInit = !xPrevVarObj.Is();
					if( bFirstInit )
					{
						// Store information to instantiate object later
						SbxObject* pValObj = PTR_CAST(SbxObject,pValObjBase);
						if( pValObj != NULL )
						{
							String aObjClass = pValObj->GetClassName();

							SbClassModuleObject* pClassModuleObj = PTR_CAST(SbClassModuleObject,pValObjBase);
							if( pClassModuleObj != NULL )
							{
								SbModule* pClassModule = pClassModuleObj->getClassModule();
								GaDimAsNewRecoverHash[refVar] =
									DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), pClassModule );
							}
							else if( aObjClass.EqualsIgnoreCaseAscii( "Collection" ) )
							{
								GaDimAsNewRecoverHash[refVar] =
									DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), NULL );
							}
						}
					}
				}
			}
		}


		// lhs is a property who's value is currently (Empty e.g. no broadcast yet)
		// in this case if there is a default prop involved the value of the
		// default property may infact be void so the type will also be SbxEMPTY
		// in this case we do not want to call checkUnoStructCopy 'cause that will
		// cause an error also
		if ( !bHandleDefaultProp || ( bHandleDefaultProp && ( refVar->GetType() != SbxEMPTY ) ) )
		// #67607 Uno-Structs kopieren
			checkUnoStructCopy( refVal, refVar );
		if( bFlagsChanged )
			refVar->SetFlags( n );
	}
}

void SbiRuntime::StepSET()
{
	SbxVariableRef refVal = PopVar();
	SbxVariableRef refVar = PopVar();
	StepSET_Impl( refVal, refVar, bVBAEnabled ); // this is really assigment
}

void SbiRuntime::StepVBASET()
{
	SbxVariableRef refVal = PopVar();
	SbxVariableRef refVar = PopVar();
	// don't handle default property
	StepSET_Impl( refVal, refVar, false ); // set obj = something
}


// JSM 07.10.95
void SbiRuntime::StepLSET()
{
	SbxVariableRef refVal = PopVar();
	SbxVariableRef refVar = PopVar();
	if( refVar->GetType() != SbxSTRING
	 || refVal->GetType() != SbxSTRING )
		Error( SbERR_INVALID_USAGE_OBJECT );
	else
	{
		// Store auf die eigene Methode (innerhalb einer Function)?
		sal_uInt16 n = refVar->GetFlags();
		if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
			refVar->SetFlag( SBX_WRITE );
		String aRefVarString = refVar->GetString();
		String aRefValString = refVal->GetString();

        sal_uInt16 nVarStrLen = aRefVarString.Len();
        sal_uInt16 nValStrLen = aRefValString.Len();
        String aNewStr;
		if( nVarStrLen > nValStrLen )
        {
			aRefVarString.Fill(nVarStrLen,' ');
		    aNewStr  = aRefValString.Copy( 0, nValStrLen );
		    aNewStr += aRefVarString.Copy( nValStrLen, nVarStrLen - nValStrLen );
        }
        else
        {
		    aNewStr = aRefValString.Copy( 0, nVarStrLen );
        }

	    refVar->PutString( aNewStr );
		refVar->SetFlags( n );
	}
}

// JSM 07.10.95
void SbiRuntime::StepRSET()
{
	SbxVariableRef refVal = PopVar();
	SbxVariableRef refVar = PopVar();
	if( refVar->GetType() != SbxSTRING
	 || refVal->GetType() != SbxSTRING )
		Error( SbERR_INVALID_USAGE_OBJECT );
	else
	{
		// Store auf die eigene Methode (innerhalb einer Function)?
		sal_uInt16 n = refVar->GetFlags();
		if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
			refVar->SetFlag( SBX_WRITE );
		String aRefVarString = refVar->GetString();
		String aRefValString = refVal->GetString();

		sal_uInt16 nPos = 0;
        sal_uInt16 nVarStrLen = aRefVarString.Len();
		if( nVarStrLen > aRefValString.Len() )
		{
			aRefVarString.Fill(nVarStrLen,' ');
			nPos = nVarStrLen - aRefValString.Len();
		}
		aRefVarString  = aRefVarString.Copy( 0, nPos );
		aRefVarString += aRefValString.Copy( 0, nVarStrLen - nPos );
		refVar->PutString(aRefVarString);

		refVar->SetFlags( n );
	}
}

// Ablage von TOS in TOS-1, dann ReadOnly-Bit setzen

void SbiRuntime::StepPUTC()
{
	SbxVariableRef refVal = PopVar();
	SbxVariableRef refVar = PopVar();
	refVar->SetFlag( SBX_WRITE );
	*refVar = *refVal;
	refVar->ResetFlag( SBX_WRITE );
	refVar->SetFlag( SBX_CONST );
}

// DIM
// TOS = Variable fuer das Array mit Dimensionsangaben als Parameter

void SbiRuntime::StepDIM()
{
	SbxVariableRef refVar = PopVar();
	DimImpl( refVar );
}

// #56204 DIM-Funktionalitaet in Hilfsmethode auslagern (step0.cxx)
void SbiRuntime::DimImpl( SbxVariableRef refVar )
{
	SbxArray* pDims = refVar->GetParameters();
	// Muss eine gerade Anzahl Argumente haben
	// Man denke daran, dass Arg[0] nicht zaehlt!
	if( pDims && !( pDims->Count() & 1 ) )
		StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
	else
	{
		SbxDataType eType = refVar->IsFixed() ? refVar->GetType() : SbxVARIANT;
		SbxDimArray* pArray = new SbxDimArray( eType );
		// AB 2.4.1996, auch Arrays ohne Dimensionsangaben zulassen (VB-komp.)
		if( pDims )
		{
			refVar->ResetFlag( SBX_VAR_TO_DIM );

			for( sal_uInt16 i = 1; i < pDims->Count(); )
			{
				sal_Int32 lb = pDims->Get( i++ )->GetLong();
				sal_Int32 ub = pDims->Get( i++ )->GetLong();
				if( ub < lb )
					Error( SbERR_OUT_OF_RANGE ), ub = lb;
				pArray->AddDim32( lb, ub );
				if ( lb != ub )
					pArray->setHasFixedSize( true );
			}
		}
		else
		{
			// #62867 Beim Anlegen eines Arrays der Laenge 0 wie bei
			// Uno-Sequences der Laenge 0 eine Dimension anlegen
			pArray->unoAddDim( 0, -1 );
		}
		sal_uInt16 nSavFlags = refVar->GetFlags();
		refVar->ResetFlag( SBX_FIXED );
		refVar->PutObject( pArray );
		refVar->SetFlags( nSavFlags );
		refVar->SetParameters( NULL );
	}
}

// REDIM
// TOS  = Variable fuer das Array
// argv = Dimensionsangaben

void SbiRuntime::StepREDIM()
{
	// Im Moment ist es nichts anderes als Dim, da doppeltes Dim
	// bereits vom Compiler erkannt wird.
	StepDIM();
}


// Helper function for StepREDIMP
void implCopyDimArray( SbxDimArray* pNewArray, SbxDimArray* pOldArray, short nMaxDimIndex,
	short nActualDim, sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds )
{
	sal_Int32& ri = pActualIndices[nActualDim];
	for( ri = pLowerBounds[nActualDim] ; ri <= pUpperBounds[nActualDim] ; ri++ )
	{
		if( nActualDim < nMaxDimIndex )
		{
			implCopyDimArray( pNewArray, pOldArray, nMaxDimIndex, nActualDim + 1,
				pActualIndices, pLowerBounds, pUpperBounds );
		}
		else
		{
			SbxVariable* pSource = pOldArray->Get32( pActualIndices );
			SbxVariable* pDest   = pNewArray->Get32( pActualIndices );
			if( pSource && pDest )
				*pDest = *pSource;
		}
	}
}

// REDIM PRESERVE
// TOS  = Variable fuer das Array
// argv = Dimensionsangaben

void SbiRuntime::StepREDIMP()
{
	SbxVariableRef refVar = PopVar();
	DimImpl( refVar );

	// Now check, if we can copy from the old array
	if( refRedimpArray.Is() )
	{
		SbxBase* pElemObj = refVar->GetObject();
		SbxDimArray* pNewArray = PTR_CAST(SbxDimArray,pElemObj);
		SbxDimArray* pOldArray = (SbxDimArray*)(SbxArray*)refRedimpArray;
		if( pNewArray )
		{
			short nDimsNew = pNewArray->GetDims();
			short nDimsOld = pOldArray->GetDims();
			short nDims = nDimsNew;
			sal_Bool bRangeError = sal_False;

			// Store dims to use them for copying later
			sal_Int32* pLowerBounds = new sal_Int32[nDims];
			sal_Int32* pUpperBounds = new sal_Int32[nDims];
			sal_Int32* pActualIndices = new sal_Int32[nDims];

			if( nDimsOld != nDimsNew )
			{
				bRangeError = sal_True;
			}
			else
			{
				// Compare bounds
				for( short i = 1 ; i <= nDims ; i++ )
				{
					sal_Int32 lBoundNew, uBoundNew;
					sal_Int32 lBoundOld, uBoundOld;
					pNewArray->GetDim32( i, lBoundNew, uBoundNew );
					pOldArray->GetDim32( i, lBoundOld, uBoundOld );

                    /* #69094 Allow all dimensions to be changed
                       although Visual Basic is not able to do so.
					// All bounds but the last have to be the same
					if( i < nDims && ( lBoundNew != lBoundOld || uBoundNew != uBoundOld ) )
					{
						bRangeError = sal_True;
						break;
					}
					else
                    */
					{
						// #69094: if( i == nDims )
						{
							lBoundNew = std::max( lBoundNew, lBoundOld );
							uBoundNew = std::min( uBoundNew, uBoundOld );
						}
						short j = i - 1;
						pActualIndices[j] = pLowerBounds[j] = lBoundNew;
						pUpperBounds[j] = uBoundNew;
					}
				}
			}

			if( bRangeError )
			{
				StarBASIC::Error( SbERR_OUT_OF_RANGE );
			}
			else
			{
				// Copy data from old array by going recursively through all dimensions
				// (It would be faster to work on the flat internal data array of an
				// SbyArray but this solution is clearer and easier)
				implCopyDimArray( pNewArray, pOldArray, nDims - 1,
					0, pActualIndices, pLowerBounds, pUpperBounds );
			}

			delete[] pUpperBounds;
			delete[] pLowerBounds;
			delete[] pActualIndices;
			refRedimpArray = NULL;
		}
	}

	//StarBASIC::FatalError( SbERR_NOT_IMPLEMENTED );
}

// REDIM_COPY
// TOS  = Array-Variable, Reference to array is copied
//		  Variable is cleared as in ERASE

void SbiRuntime::StepREDIMP_ERASE()
{
	SbxVariableRef refVar = PopVar();
	SbxDataType eType = refVar->GetType();
	if( eType & SbxARRAY )
	{
		SbxBase* pElemObj = refVar->GetObject();
		SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
		if( pDimArray )
		{
			refRedimpArray = pDimArray;
		}

		// As in ERASE
		sal_uInt16 nSavFlags = refVar->GetFlags();
		refVar->ResetFlag( SBX_FIXED );
		refVar->SetType( SbxDataType(eType & 0x0FFF) );
		refVar->SetFlags( nSavFlags );
		refVar->Clear();
	}
	else
	if( refVar->IsFixed() )
		refVar->Clear();
	else
		refVar->SetType( SbxEMPTY );
}

void lcl_clearImpl( SbxVariableRef& refVar, SbxDataType& eType )
{
	sal_uInt16 nSavFlags = refVar->GetFlags();
	refVar->ResetFlag( SBX_FIXED );
	refVar->SetType( SbxDataType(eType & 0x0FFF) );
	refVar->SetFlags( nSavFlags );
	refVar->Clear();
}

void lcl_eraseImpl( SbxVariableRef& refVar, bool bVBAEnabled )
{
	SbxDataType eType = refVar->GetType();
	if( eType & SbxARRAY )
	{
		if ( bVBAEnabled )
		{
			SbxBase* pElemObj = refVar->GetObject();
			SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
			bool bClearValues = true;
			if( pDimArray )
			{
				if ( pDimArray->hasFixedSize() )
				{
					// Clear all Value(s)
					pDimArray->SbxArray::Clear();
					bClearValues = false;
				}
				else
					pDimArray->Clear(); // clear Dims
			}
			if ( bClearValues )
			{
				SbxArray* pArray = PTR_CAST(SbxArray,pElemObj);
				if ( pArray )
					pArray->Clear();
			}
		}
		else
		// AB 2.4.1996
		// Arrays haben bei Erase nach VB ein recht komplexes Verhalten. Hier
		// werden zunaechst nur die Typ-Probleme bei REDIM (#26295) beseitigt:
		// Typ hart auf den Array-Typ setzen, da eine Variable mit Array
		// SbxOBJECT ist. Bei REDIM entsteht dann ein SbxOBJECT-Array und
		// der ursruengliche Typ geht verloren -> Laufzeitfehler
			lcl_clearImpl( refVar, eType );
	}
	else
	if( refVar->IsFixed() )
		refVar->Clear();
	else
		refVar->SetType( SbxEMPTY );
}

// Variable loeschen
// TOS = Variable

void SbiRuntime::StepERASE()
{
	SbxVariableRef refVar = PopVar();
	lcl_eraseImpl( refVar, bVBAEnabled );
}

void SbiRuntime::StepERASE_CLEAR()
{
	SbxVariableRef refVar = PopVar();
	lcl_eraseImpl( refVar, bVBAEnabled );
	SbxDataType eType = refVar->GetType();
	lcl_clearImpl( refVar, eType );
}

void SbiRuntime::StepARRAYACCESS()
{
	if( !refArgv )
		StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
    SbxVariableRef refVar = PopVar();
	refVar->SetParameters( refArgv );
	PopArgv();
	PushVar( CheckArray( refVar ) );
}

void SbiRuntime::StepBYVAL()
{
	// Copy variable on stack to break call by reference
	SbxVariableRef pVar = PopVar();
	SbxDataType t = pVar->GetType();

	SbxVariable* pCopyVar = new SbxVariable( t );
	pCopyVar->SetFlag( SBX_READWRITE );
	*pCopyVar = *pVar;

	PushVar( pCopyVar );
}

// Einrichten eines Argvs
// nOp1 bleibt so -> 1. Element ist Returnwert

void SbiRuntime::StepARGC()
{
	PushArgv();
	refArgv = new SbxArray;
	nArgc = 1;
}

// Speichern eines Arguments in Argv

void SbiRuntime::StepARGV()
{
	if( !refArgv )
		StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
	else
	{
		SbxVariableRef pVal = PopVar();

		// Before fix of #94916:
		// if( pVal->ISA(SbxMethod) || pVal->ISA(SbxProperty) )
		if( pVal->ISA(SbxMethod) || pVal->ISA(SbUnoProperty) || pVal->ISA(SbProcedureProperty) )
		{
			// Methoden und Properties evaluieren!
			SbxVariable* pRes = new SbxVariable( *pVal );
			pVal = pRes;
		}
		refArgv->Put( pVal, nArgc++ );
	}
}

// Input to Variable. Die Variable ist auf TOS und wird
// anschliessend entfernt.

void SbiRuntime::StepINPUT()
{
	String s;
	char ch = 0;
	SbError err;
	// Skip whitespace
	while( ( err = pIosys->GetError() ) == 0 )
	{
		ch = pIosys->Read();
		if( ch != ' ' && ch != '\t' && ch != '\n' )
			break;
	}
	if( !err )
	{
		// Scan until comma or whitespace
		char sep = ( ch == '"' ) ? ch : 0;
		if( sep ) ch = pIosys->Read();
		while( ( err = pIosys->GetError() ) == 0 )
		{
			if( ch == sep )
			{
				ch = pIosys->Read();
				if( ch != sep )
					break;
			}
			else if( !sep && (ch == ',' || ch == '\n') )
				break;
			s += ch;
			ch = pIosys->Read();
		}
		// skip whitespace
		if( ch == ' ' || ch == '\t' )
		  while( ( err = pIosys->GetError() ) == 0 )
		{
			if( ch != ' ' && ch != '\t' && ch != '\n' )
				break;
			ch = pIosys->Read();
		}
	}
	if( !err )
	{
		SbxVariableRef pVar = GetTOS();
		// Zuerst versuchen, die Variable mit einem numerischen Wert
		// zu fuellen, dann mit einem Stringwert
		if( !pVar->IsFixed() || pVar->IsNumeric() )
		{
			sal_uInt16 nLen = 0;
			if( !pVar->Scan( s, &nLen ) )
			{
				err = SbxBase::GetError();
				SbxBase::ResetError();
			}
			// Der Wert muss komplett eingescant werden
			else if( nLen != s.Len() && !pVar->PutString( s ) )
			{
				err = SbxBase::GetError();
				SbxBase::ResetError();
			}
			else if( nLen != s.Len() && pVar->IsNumeric() )
			{
				err = SbxBase::GetError();
				SbxBase::ResetError();
				if( !err )
					err = SbERR_CONVERSION;
			}
		}
		else
		{
			pVar->PutString( s );
			err = SbxBase::GetError();
			SbxBase::ResetError();
		}
	}
	if( err == SbERR_USER_ABORT )
		Error( err );
	else if( err )
	{
		if( pRestart && !pIosys->GetChannel() )
		{
			BasResId aId( IDS_SBERR_START + 4 );
			String aMsg( aId );

            //****** DON'T CHECK IN, TEST ONLY *******
            //****** DON'T CHECK IN, TEST ONLY *******
			// ErrorBox( NULL, WB_OK, aMsg ).Execute();
            //****** DON'T CHECK IN, TEST ONLY *******
            //****** DON'T CHECK IN, TEST ONLY *******

			pCode = pRestart;
		}
		else
			Error( err );
	}
	else
	{
		// pIosys->ResetChannel();
		PopVar();
	}
}

// Line Input to Variable. Die Variable ist auf TOS und wird
// anschliessend entfernt.

void SbiRuntime::StepLINPUT()
{
	ByteString aInput;
	pIosys->Read( aInput );
	Error( pIosys->GetError() );
	SbxVariableRef p = PopVar();
	p->PutString( String( aInput, gsl_getSystemTextEncoding() ) );
	// pIosys->ResetChannel();
}

// Programmende

void SbiRuntime::StepSTOP()
{
	pInst->Stop();
}

// FOR-Variable initialisieren

void SbiRuntime::StepINITFOR()
{
	PushFor();
}

void SbiRuntime::StepINITFOREACH()
{
	PushForEach();
}

// FOR-Variable inkrementieren

void SbiRuntime::StepNEXT()
{
	if( !pForStk )
	{
		StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
		return;
	}
	if( pForStk->eForType == FOR_TO )
		pForStk->refVar->Compute( SbxPLUS, *pForStk->refInc );
}

// Anfang CASE: TOS in CASE-Stack

void SbiRuntime::StepCASE()
{
	if( !refCaseStk.Is() )
		refCaseStk = new SbxArray;
	SbxVariableRef xVar = PopVar();
	refCaseStk->Put( xVar, refCaseStk->Count() );
}

// Ende CASE: Variable freigeben

void SbiRuntime::StepENDCASE()
{
	if( !refCaseStk || !refCaseStk->Count() )
		StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
	else
		refCaseStk->Remove( refCaseStk->Count() - 1 );
}

// Standard-Fehlerbehandlung

void SbiRuntime::StepSTDERROR()
{
	pError = NULL; bError = sal_True;
	pInst->aErrorMsg = String();
	pInst->nErr = 0L;
	pInst->nErl = 0;
	nError = 0L;
	SbxErrObject::getUnoErrObject()->Clear();
}

void SbiRuntime::StepNOERROR()
{
	pInst->aErrorMsg = String();
	pInst->nErr = 0L;
	pInst->nErl = 0;
	nError = 0L;
	SbxErrObject::getUnoErrObject()->Clear();
	bError = sal_False;
}

// UP verlassen

void SbiRuntime::StepLEAVE()
{
	bRun = sal_False;
        // If VBA and we are leaving an ErrorHandler then clear the error ( it's been processed )
	if ( bInError && pError )
	    SbxErrObject::getUnoErrObject()->Clear();
}

void SbiRuntime::StepCHANNEL()	  	// TOS = Kanalnummer
{
	SbxVariableRef pChan = PopVar();
	short nChan = pChan->GetInteger();
	pIosys->SetChannel( nChan );
	Error( pIosys->GetError() );
}

void SbiRuntime::StepCHANNEL0()
{
	pIosys->ResetChannel();
}

void SbiRuntime::StepPRINT()	  	// print TOS
{
	SbxVariableRef p = PopVar();
	String s1 = p->GetString();
	String s;
	if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
		s = ' ';	// ein Blank davor
	s += s1;
	ByteString aByteStr( s, gsl_getSystemTextEncoding() );
	pIosys->Write( aByteStr );
	Error( pIosys->GetError() );
}

void SbiRuntime::StepPRINTF()	  	// print TOS in field
{
	SbxVariableRef p = PopVar();
	String s1 = p->GetString();
	String s;
	if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
		s = ' ';	// ein Blank davor
	s += s1;
	s.Expand( 14, ' ' );
	ByteString aByteStr( s, gsl_getSystemTextEncoding() );
	pIosys->Write( aByteStr );
	Error( pIosys->GetError() );
}

void SbiRuntime::StepWRITE()	  	// write TOS
{
	SbxVariableRef p = PopVar();
	// Muss der String gekapselt werden?
	char ch = 0;
	switch (p->GetType() )
	{
		case SbxSTRING: ch = '"'; break;
		case SbxCURRENCY:
		case SbxBOOL:
		case SbxDATE: ch = '#'; break;
		default: break;
	}
	String s;
	if( ch )
		s += ch;
	s += p->GetString();
	if( ch )
		s += ch;
	ByteString aByteStr( s, gsl_getSystemTextEncoding() );
	pIosys->Write( aByteStr );
	Error( pIosys->GetError() );
}

void SbiRuntime::StepRENAME()	  	// Rename Tos+1 to Tos
{
	SbxVariableRef pTos1 = PopVar();
	SbxVariableRef pTos  = PopVar();
	String aDest = pTos1->GetString();
	String aSource = pTos->GetString();

	// <-- UCB
	if( hasUno() )
	{
		implStepRenameUCB( aSource, aDest );
	}
	else
	// --> UCB
	{
#ifdef _OLD_FILE_IMPL
		DirEntry aSourceDirEntry( aSource );
		if( aSourceDirEntry.Exists() )
		{
			if( aSourceDirEntry.MoveTo( DirEntry(aDest) ) != FSYS_ERR_OK )
				StarBASIC::Error( SbERR_PATH_NOT_FOUND );
		}
		else
				StarBASIC::Error( SbERR_PATH_NOT_FOUND );
#else
		implStepRenameOSL( aSource, aDest );
#endif
	}
}

// TOS = Prompt

void SbiRuntime::StepPROMPT()
{
	SbxVariableRef p = PopVar();
	ByteString aStr( p->GetString(), gsl_getSystemTextEncoding() );
	pIosys->SetPrompt( aStr );
}

// Set Restart point

void SbiRuntime::StepRESTART()
{
	pRestart = pCode;
}

// Leerer Ausdruck auf Stack fuer fehlenden Parameter

void SbiRuntime::StepEMPTY()
{
	// #57915 Die Semantik von StepEMPTY() ist die Repraesentation eines fehlenden
	// Arguments. Dies wird in VB durch ein durch den Wert 448 (SbERR_NAMED_NOT_FOUND)
	// vom Typ Error repraesentiert. StepEmpty jetzt muesste besser StepMISSING()
	// heissen, aber der Name wird der Einfachkeit halber beibehalten.
	SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
	xVar->PutErr( 448 );
	PushVar( xVar );
	// ALT: PushVar( new SbxVariable( SbxEMPTY ) );
}

// TOS = Fehlercode

void SbiRuntime::StepERROR()
{
	SbxVariableRef refCode = PopVar();
	sal_uInt16 n = refCode->GetUShort();
	SbError error = StarBASIC::GetSfxFromVBError( n );
	if ( bVBAEnabled )
		pInst->Error( error );
	else
		Error( error );
}
