summaryrefslogtreecommitdiff
path: root/basic
diff options
context:
space:
mode:
Diffstat (limited to 'basic')
-rw-r--r--basic/Library_sb.mk3
-rw-r--r--basic/source/inc/sbunoobj.hxx10
-rw-r--r--basic/source/runtime/runtime.cxx3446
-rw-r--r--basic/source/runtime/step0.cxx1540
-rw-r--r--basic/source/runtime/step1.cxx582
-rw-r--r--basic/source/runtime/step2.cxx1400
6 files changed, 3443 insertions, 3538 deletions
diff --git a/basic/Library_sb.mk b/basic/Library_sb.mk
index 98eea5c81dac..c89214389b8b 100644
--- a/basic/Library_sb.mk
+++ b/basic/Library_sb.mk
@@ -98,9 +98,6 @@ $(eval $(call gb_Library_add_exception_objects,sb,\
basic/source/runtime/sbdiagnose \
basic/source/runtime/stdobj \
basic/source/runtime/stdobj1 \
- basic/source/runtime/step0 \
- basic/source/runtime/step1 \
- basic/source/runtime/step2 \
))
endif
diff --git a/basic/source/inc/sbunoobj.hxx b/basic/source/inc/sbunoobj.hxx
index 9bf887654645..12b62e5907a5 100644
--- a/basic/source/inc/sbunoobj.hxx
+++ b/basic/source/inc/sbunoobj.hxx
@@ -411,7 +411,15 @@ public:
bool isVBAConstantType( const OUString& rName );
};
-#endif
+SbxVariable* getDefaultProp( SbxVariable* pRef );
+
+::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > createComListener( const ::com::sun::star::uno::Any& aControlAny,
+ const OUString& aVBAType,
+ const OUString& aPrefix,
+ SbxObjectRef xScopeObj );
+bool checkUnoObjectType( SbUnoObject* refVal, const OUString& aClass );
+
+#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/runtime/runtime.cxx b/basic/source/runtime/runtime.cxx
index d1f026d5cf95..4c2ffa97e661 100644
--- a/basic/source/runtime/runtime.cxx
+++ b/basic/source/runtime/runtime.cxx
@@ -17,30 +17,67 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#include <vcl/svapp.hxx>
+#include <stdlib.h>
+
+#include <algorithm>
+
+#include <boost/unordered_map.hpp>
+
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XEnumerationAccess.hpp>
+#include <com/sun/star/container/XIndexAccess.hpp>
+#include <com/sun/star/script/XDefaultMethod.hpp>
+#include <com/sun/star/uno/Any.hxx>
+#include <com/sun/star/util/SearchOptions.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <comphelper/string.hxx>
+
+#include <sal/log.hxx>
+
#include <tools/wldcrd.hxx>
+
+#include <vcl/msgbox.hxx>
+#include <vcl/svapp.hxx>
+
+#include <rtl/instance.hxx>
+#include <rtl/math.hxx>
+#include <rtl/ustrbuf.hxx>
+
#include <svl/zforlist.hxx>
+
#include <unotools/syslocale.hxx>
-#include "runtime.hxx"
-#include "sbintern.hxx"
-#include "opcodes.hxx"
+#include <unotools/textsearch.hxx>
+
+#include <basic/sbuno.hxx>
+
+#include "basrid.hxx"
#include "codegen.hxx"
-#include "iosys.hxx"
-#include "image.hxx"
+#include "comenumwrapper.hxx"
#include "ddectrl.hxx"
#include "dllmgr.hxx"
-#include <comphelper/processfactory.hxx>
-#include <com/sun/star/container/XEnumerationAccess.hpp>
-#include "sbunoobj.hxx"
#include "errobject.hxx"
-#include "sal/log.hxx"
+#include "image.hxx"
+#include "iosys.hxx"
+#include "opcodes.hxx"
+#include "runtime.hxx"
+#include "sb.hrc"
+#include "sbintern.hxx"
+#include "sbunoobj.hxx"
-#include "comenumwrapper.hxx"
+using com::sun::star::uno::Reference;
-SbxVariable* getDefaultProp( SbxVariable* pRef );
+using namespace com::sun::star::uno;
+using namespace com::sun::star::container;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::script;
using namespace ::com::sun::star;
+static void lcl_clearImpl( SbxVariableRef& refVar, SbxDataType& eType );
+static void lcl_eraseImpl( SbxVariableRef& refVar, bool bVBAEnabled );
+
bool SbiRuntime::isVBAEnabled()
{
bool result = false;
@@ -1290,4 +1327,3389 @@ sal_uInt16 SbiRuntime::GetBase()
return pImg->GetBase();
}
+void SbiRuntime::StepNOP()
+{}
+
+void SbiRuntime::StepArith( SbxOperator eOp )
+{
+ SbxVariableRef p1 = PopVar();
+ TOSMakeTemp();
+ SbxVariable* p2 = GetTOS();
+
+ 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 == SbxEMPTY )
+ {
+ p1->Broadcast( SBX_HINT_DATAWANTED );
+ p1Type = p1->GetType();
+ }
+ if ( p2Type == SbxEMPTY )
+ {
+ p2->Broadcast( SBX_HINT_DATAWANTED );
+ p2Type = p2->GetType();
+ }
+ if ( p1Type == p2Type )
+ {
+ // 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 )
+ 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;
+ static SbxVariable* pNULL = NULL;
+ // why do this on non-windows ?
+ // why do this at all ?
+ // I dumbly follow the pattern :-/
+ if ( bVBAEnabled && ( p1->IsNull() || p2->IsNull() ) )
+ {
+ if( !pNULL )
+ {
+ pNULL = new SbxVariable;
+ pNULL->PutNull();
+ pNULL->AddRef();
+ }
+ PushVar( pNULL );
+ }
+ else 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)
+ {
+ if((cCode & 0xFF80))
+ {
+ return false;
+ }
+ switch((sal_uInt8)(cCode & 0x07F))
+ {
+ case '.':
+ case '^':
+ case '$':
+ case '+':
+ case '\\':
+ case '|':
+ case '{':
+ case '}':
+ case '(':
+ case ')':
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ OUString VBALikeToRegexp(const OUString &rIn)
+ {
+ OUStringBuffer sResult;
+ const sal_Unicode *start = rIn.getStr();
+ const sal_Unicode *end = start + rIn.getLength();
+
+ int seenright = 0;
+
+ sResult.append('^');
+
+ while (start < end)
+ {
+ switch (*start)
+ {
+ case '?':
+ sResult.append('.');
+ start++;
+ break;
+ case '*':
+ sResult.append(".*");
+ start++;
+ break;
+ case '#':
+ sResult.append("[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.makeStringAndClear();
+ }
+}
+
+void SbiRuntime::StepLIKE()
+{
+ SbxVariableRef refVar1 = PopVar();
+ SbxVariableRef refVar2 = PopVar();
+
+ OUString pattern = VBALikeToRegexp(refVar1->GetOUString());
+ OUString value = refVar2->GetOUString();
+
+ com::sun::star::util::SearchOptions aSearchOpt;
+
+ aSearchOpt.algorithmType = com::sun::star::util::SearchAlgorithms_REGEXP;
+
+ aSearchOpt.Locale = Application::GetSettings().GetLanguageTag().getLocale();
+ aSearchOpt.searchString = pattern;
+
+ int bTextMode(1);
+ bool bCompatibility = ( GetSbData()->pInst && GetSbData()->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);
+ sal_uInt16 nStart=0, nEnd=value.getLength();
+ int bRes = aSearch.SearchFrwrd(value, &nStart, &nEnd);
+ pRes->PutBool( bRes != 0 );
+
+ PushVar( pRes );
+}
+
+// TOS and TOS-1 are both object variables and contain the same 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 );
+}
+
+// update the value of TOS
+
+void SbiRuntime::StepGET()
+{
+ SbxVariable* p = GetTOS();
+ p->Broadcast( SBX_HINT_DATAWANTED );
+}
+
+// #67607 copy Uno-Structs
+inline bool checkUnoStructCopy( bool bVBA, SbxVariableRef& refVal, SbxVariableRef& refVar )
+{
+ SbxDataType eVarType = refVar->GetType();
+ SbxDataType eValType = refVal->GetType();
+
+ if ( !( !bVBA|| ( bVBA && refVar->GetType() != SbxEMPTY ) ) || !refVar->CanWrite() )
+ return false;
+
+ if ( eValType != SbxOBJECT )
+ return false;
+ // we seem to be duplicating parts of SbxValue=operator, maybe we should just move this to
+ // there :-/ not sure if for every '=' we would want struct handling
+ if( eVarType != SbxOBJECT )
+ {
+ if ( refVar->IsFixed() )
+ return false;
+ }
+ // #115826: Exclude ProcedureProperties to avoid call to Property Get procedure
+ else if( refVar->ISA(SbProcedureProperty) )
+ return false;
+
+ SbxObjectRef xValObj = (SbxObject*)refVal->GetObject();
+ if( !xValObj.Is() || xValObj->ISA(SbUnoAnyObject) )
+ return false;
+
+ SbUnoObject* pUnoVal = PTR_CAST(SbUnoObject,(SbxObject*)xValObj);
+ SbUnoStructRefObject* pUnoStructVal = PTR_CAST(SbUnoStructRefObject,(SbxObject*)xValObj);
+ Any aAny;
+ // make doubly sure value is either an Uno object or
+ // an uno struct
+ if ( pUnoVal || pUnoStructVal )
+ aAny = pUnoVal ? pUnoVal->getUnoAny() : pUnoStructVal->getUnoAny();
+ else
+ return false;
+ if ( aAny.getValueType().getTypeClass() == TypeClass_STRUCT )
+ {
+ refVar->SetType( SbxOBJECT );
+ SbxError eOldErr = refVar->GetError();
+ // There are some circumstances when calling GetObject
+ // will trigger an error, we need to squash those here.
+ // Alternatively it is possible that the same scenario
+ // could overwrite and existing error. Lets prevent that
+ SbxObjectRef xVarObj = (SbxObject*)refVar->GetObject();
+ if ( eOldErr != SbxERR_OK )
+ refVar->SetError( eOldErr );
+ else
+ refVar->ResetError();
+
+ SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,(SbxObject*)xVarObj);
+
+ OUString sClassName = pUnoVal ? pUnoVal->GetClassName() : pUnoStructVal->GetClassName();
+ OUString sName = pUnoVal ? pUnoVal->GetName() : pUnoStructVal->GetName();
+
+ if ( pUnoStructObj )
+ {
+ StructRefInfo aInfo = pUnoStructObj->getStructInfo();
+ aInfo.setValue( aAny );
+ }
+ else
+ {
+ SbUnoObject* pNewUnoObj = new SbUnoObject( sName, aAny );
+ // #70324: adopt ClassName
+ pNewUnoObj->SetClassName( sClassName );
+ refVar->PutObject( pNewUnoObj );
+ }
+ return true;
+ }
+ return false;
+}
+
+
+// laying down TOS in TOS-1
+
+void SbiRuntime::StepPUT()
+{
+ SbxVariableRef refVal = PopVar();
+ SbxVariableRef refVar = PopVar();
+ // store on its own method (inside a function)?
+ bool bFlagsChanged = false;
+ sal_uInt16 n = 0;
+ if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
+ {
+ bFlagsChanged = 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 )
+ {
+ // yet more hacking at this, I feel we don't quite have the correct
+ // heuristics for dealing with obj1 = obj2 ( where obj2 ( and maybe
+ // obj1 ) has default member/property ) ) It seems that default props
+ // aren't dealt with if the object is a member of some parent object
+ bool bObjAssign = false;
+ if ( refVar->GetType() == SbxEMPTY )
+ refVar->Broadcast( SBX_HINT_DATAWANTED );
+ if ( refVar->GetType() == SbxOBJECT )
+ {
+ if ( refVar->IsA( TYPE(SbxMethod) ) || ! refVar->GetParent() )
+ {
+ SbxVariable* pDflt = getDefaultProp( refVar );
+
+ if ( pDflt )
+ refVar = pDflt;
+ }
+ else
+ bObjAssign = true;
+ }
+ if ( refVal->GetType() == SbxOBJECT && !bObjAssign && ( refVal->IsA( TYPE(SbxMethod) ) || ! refVal->GetParent() ) )
+ {
+ SbxVariable* pDflt = getDefaultProp( refVal );
+ if ( pDflt )
+ refVal = pDflt;
+ }
+ }
+
+ if ( !checkUnoStructCopy( bVBAEnabled, refVal, refVar ) )
+ *refVar = *refVal;
+
+ if( bFlagsChanged )
+ refVar->SetFlags( n );
+}
+
+
+// VBA Dim As New behavior handling, save init object information
+struct DimAsNewRecoverItem
+{
+ OUString m_aObjClass;
+ OUString m_aObjName;
+ SbxObject* m_pObjParent;
+ SbModule* m_pClassModule;
+
+ DimAsNewRecoverItem( void )
+ : m_pObjParent( NULL )
+ , m_pClassModule( NULL )
+ {}
+
+ DimAsNewRecoverItem( const OUString& rObjClass, const OUString& 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 boost::unordered_map< SbxVariable*, DimAsNewRecoverItem,
+ SbxVariablePtrHash > DimAsNewRecoverHash;
+
+class GaDimAsNewRecoverHash : public rtl::Static<DimAsNewRecoverHash, GaDimAsNewRecoverHash> {};
+
+void removeDimAsNewRecoverItem( SbxVariable* pVar )
+{
+ DimAsNewRecoverHash &rDimAsNewRecoverHash = GaDimAsNewRecoverHash::get();
+ DimAsNewRecoverHash::iterator it = rDimAsNewRecoverHash.find( pVar );
+ if( it != rDimAsNewRecoverHash.end() )
+ {
+ rDimAsNewRecoverHash.erase( it );
+ }
+}
+
+
+// saving object variable
+// not-object variables will cause errors
+
+static const char pCollectionStr[] = "Collection";
+
+void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, bool bHandleDefaultProp )
+{
+ // #67733 types with array-flag are OK too
+
+ // 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();
+ 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 ) )
+ {
+ // activate GetOject for collections on refVal
+ SbxBase* pObjVarObj = refVal->GetObject();
+ if( pObjVarObj )
+ {
+ SbxVariableRef refObjVal = PTR_CAST(SbxObject,pObjVarObj);
+
+ if( refObjVal )
+ {
+ refVal = refObjVal;
+ }
+ else if( !(eValType & SbxARRAY) )
+ {
+ refVal = NULL;
+ }
+ }
+ }
+
+ // #52896 refVal can be invalid here, if uno-sequences - or more
+ // general arrays - are assigned to variables that are declared
+ // as an object!
+ if( !refVal )
+ {
+ Error( SbERR_INVALID_USAGE_OBJECT );
+ }
+ else
+ {
+ bool bFlagsChanged = false;
+ sal_uInt16 n = 0;
+ if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
+ {
+ bFlagsChanged = 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
+ // LHS try determine if a default prop exists
+ // again like in StepPUT (see there too ) we are tweaking the
+ // heursitics again for when to assign an object reference or
+ // use default memebers if they exists
+ // #FIXME we really need to get to the bottom of this mess
+ bool bObjAssign = false;
+ if ( refVar->GetType() == SbxOBJECT )
+ {
+ if ( refVar->IsA( TYPE(SbxMethod) ) || ! refVar->GetParent() )
+ {
+ SbxVariable* pDflt = getDefaultProp( refVar );
+ if ( pDflt )
+ {
+ refVar = pDflt;
+ }
+ }
+ else
+ bObjAssign = 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 && !bObjAssign )
+ {
+ // lhs is either a valid object || or has a defaultProp
+ pDflt = getDefaultProp( refVal );
+ }
+ if ( pDflt )
+ {
+ refVal = pDflt;
+ }
+ }
+ }
+
+ // Handle Dim As New
+ 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();
+ OUString aDeclareClassName = refVar->GetDeclareClassName();
+ OUString aVBAType = aDeclareClassName;
+ OUString aPrefix = refVar->GetName();
+ SbxObjectRef xScopeObj = refVar->GetParent();
+ xComListener = createComListener( aControlAny, aVBAType, aPrefix, xScopeObj );
+
+ refVal->SetDeclareClassName( aDeclareClassName );
+ refVal->SetComListener( xComListener, &rBasic ); // Hold reference
+ }
+
+ }
+
+ // 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 ( !checkUnoStructCopy( bHandleDefaultProp, refVal, refVar ) )
+ {
+ *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 &rDimAsNewRecoverHash = GaDimAsNewRecoverHash::get();
+ DimAsNewRecoverHash::iterator it = rDimAsNewRecoverHash.find( refVar );
+ if( it != rDimAsNewRecoverHash.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.equalsIgnoreAsciiCaseAscii( pCollectionStr ) )
+ {
+ BasicCollection* pNewCollection = new BasicCollection( OUString(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 )
+ {
+ OUString aObjClass = pValObj->GetClassName();
+
+ SbClassModuleObject* pClassModuleObj = PTR_CAST(SbClassModuleObject,pValObjBase);
+ DimAsNewRecoverHash &rDimAsNewRecoverHash = GaDimAsNewRecoverHash::get();
+ if( pClassModuleObj != NULL )
+ {
+ SbModule* pClassModule = pClassModuleObj->getClassModule();
+ rDimAsNewRecoverHash[refVar] =
+ DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), pClassModule );
+ }
+ else if( aObjClass.equalsIgnoreAsciiCase( "Collection" ) )
+ {
+ rDimAsNewRecoverHash[refVar] =
+ DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), NULL );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ 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
+}
+
+
+void SbiRuntime::StepLSET()
+{
+ SbxVariableRef refVal = PopVar();
+ SbxVariableRef refVar = PopVar();
+ if( refVar->GetType() != SbxSTRING ||
+ refVal->GetType() != SbxSTRING )
+ {
+ Error( SbERR_INVALID_USAGE_OBJECT );
+ }
+ else
+ {
+ sal_uInt16 n = refVar->GetFlags();
+ if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
+ {
+ refVar->SetFlag( SBX_WRITE );
+ }
+ OUString aRefVarString = refVar->GetOUString();
+ OUString aRefValString = refVal->GetOUString();
+
+ sal_Int32 nVarStrLen = aRefVarString.getLength();
+ sal_Int32 nValStrLen = aRefValString.getLength();
+ OUStringBuffer aNewStr;
+ if( nVarStrLen > nValStrLen )
+ {
+ aNewStr.append(aRefValString);
+ comphelper::string::padToLength(aNewStr, nVarStrLen, ' ');
+ }
+ else
+ {
+ aNewStr = aRefValString.copy( 0, nVarStrLen );
+ }
+
+ refVar->PutString(aNewStr.makeStringAndClear());
+ refVar->SetFlags( n );
+ }
+}
+
+void SbiRuntime::StepRSET()
+{
+ SbxVariableRef refVal = PopVar();
+ SbxVariableRef refVar = PopVar();
+ if( refVar->GetType() != SbxSTRING || refVal->GetType() != SbxSTRING )
+ {
+ Error( SbERR_INVALID_USAGE_OBJECT );
+ }
+ else
+ {
+ sal_uInt16 n = refVar->GetFlags();
+ if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
+ {
+ refVar->SetFlag( SBX_WRITE );
+ }
+ OUString aRefVarString = refVar->GetOUString();
+ OUString aRefValString = refVal->GetOUString();
+ sal_Int32 nVarStrLen = aRefVarString.getLength();
+ sal_Int32 nValStrLen = aRefValString.getLength();
+
+ OUStringBuffer aNewStr(nVarStrLen);
+ if (nVarStrLen > nValStrLen)
+ {
+ comphelper::string::padToLength(aNewStr, nVarStrLen - nValStrLen, ' ');
+ aNewStr.append(aRefValString);
+ }
+ else
+ {
+ aNewStr.append(aRefValString.copy(0, nVarStrLen));
+ }
+ refVar->PutString(aNewStr.makeStringAndClear());
+
+ refVar->SetFlags( n );
+ }
+}
+
+// laying down TOS in TOS-1, then set ReadOnly-Bit
+
+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 for the array with dimension information as parameter
+
+void SbiRuntime::StepDIM()
+{
+ SbxVariableRef refVar = PopVar();
+ DimImpl( refVar );
+}
+
+// #56204 swap out DIM-functionality into a help method (step0.cxx)
+void SbiRuntime::DimImpl( SbxVariableRef refVar )
+{
+ // If refDim then this DIM statement is terminating a ReDIM and
+ // previous StepERASE_CLEAR for an array, the following actions have
+ // been delayed from ( StepERASE_CLEAR ) 'till here
+ if ( refRedim )
+ {
+ if ( !refRedimpArray ) // only erase the array not ReDim Preserve
+ {
+ lcl_eraseImpl( refVar, bVBAEnabled );
+ }
+ SbxDataType eType = refVar->GetType();
+ lcl_clearImpl( refVar, eType );
+ refRedim = NULL;
+ }
+ SbxArray* pDims = refVar->GetParameters();
+ // must have an even number of arguments
+ // have in mind that Arg[0] does not count!
+ if( pDims && !( pDims->Count() & 1 ) )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ }
+ else
+ {
+ SbxDataType eType = refVar->IsFixed() ? refVar->GetType() : SbxVARIANT;
+ SbxDimArray* pArray = new SbxDimArray( eType );
+ // allow arrays without dimension information, too (VB-compatible)
+ 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 On creating an array of the length 0, create
+ // a dimension (like for Uno-Sequences of the length 0)
+ 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 for the array
+// argv = dimension information
+
+void SbiRuntime::StepREDIM()
+{
+ // Nothing different than dim at the moment because
+ // a double dim is already recognized by the compiler.
+ 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 for the array
+// argv = dimension information
+
+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;
+
+ if( nDimsOld != nDimsNew )
+ {
+ StarBASIC::Error( SbERR_OUT_OF_RANGE );
+ }
+ else
+ {
+ // 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];
+
+ // 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 );
+ lBoundNew = std::max( lBoundNew, lBoundOld );
+ uBoundNew = std::min( uBoundNew, uBoundOld );
+ short j = i - 1;
+ pActualIndices[j] = pLowerBounds[j] = lBoundNew;
+ pUpperBounds[j] = uBoundNew;
+ }
+ // 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;
+ }
+ }
+
+}
+
+// REDIM_COPY
+// TOS = Array-Variable, Reference to array is copied
+// Variable is cleared as in ERASE
+
+void SbiRuntime::StepREDIMP_ERASE()
+{
+ SbxVariableRef refVar = PopVar();
+ refRedim = refVar;
+ SbxDataType eType = refVar->GetType();
+ if( eType & SbxARRAY )
+ {
+ SbxBase* pElemObj = refVar->GetObject();
+ SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
+ if( pDimArray )
+ {
+ refRedimpArray = pDimArray;
+ }
+
+ }
+ else if( refVar->IsFixed() )
+ {
+ refVar->Clear();
+ }
+ else
+ {
+ refVar->SetType( SbxEMPTY );
+ }
+}
+
+static 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();
+}
+
+static 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
+ {
+ // Arrays have on an erase to VB quite a complex behaviour. Here are
+ // only the type problems at REDIM (#26295) removed at first:
+ // Set type hard onto the array-type, because a variable with array is
+ // SbxOBJECT. At REDIM there's an SbxOBJECT-array generated then and
+ // the original type is lost -> runtime error
+ lcl_clearImpl( refVar, eType );
+ }
+ }
+ else if( refVar->IsFixed() )
+ {
+ refVar->Clear();
+ }
+ else
+ {
+ refVar->SetType( SbxEMPTY );
+ }
+}
+
+// delete variable
+// TOS = variable
+
+void SbiRuntime::StepERASE()
+{
+ SbxVariableRef refVar = PopVar();
+ lcl_eraseImpl( refVar, bVBAEnabled );
+}
+
+void SbiRuntime::StepERASE_CLEAR()
+{
+ refRedim = PopVar();
+}
+
+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 );
+}
+
+// establishing an argv
+// nOp1 stays as it is -> 1st element is the return value
+
+void SbiRuntime::StepARGC()
+{
+ PushArgv();
+ refArgv = new SbxArray;
+ nArgc = 1;
+}
+
+// storing an argument 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(SbUnoProperty) || pVal->ISA(SbProcedureProperty) )
+ {
+ // evaluate methods and properties!
+ SbxVariable* pRes = new SbxVariable( *pVal );
+ pVal = pRes;
+ }
+ refArgv->Put( pVal, nArgc++ );
+ }
+}
+
+// Input to Variable. The variable is on TOS and is
+// is removed afterwards.
+void SbiRuntime::StepINPUT()
+{
+ OUStringBuffer sin;
+ OUString 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;
+ }
+ sin.append( 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 )
+ {
+ s = sin.makeStringAndClear();
+ SbxVariableRef pVar = GetTOS();
+ // try to fill the variable with a numeric value first,
+ // then with a string value
+ if( !pVar->IsFixed() || pVar->IsNumeric() )
+ {
+ sal_uInt16 nLen = 0;
+ if( !pVar->Scan( s, &nLen ) )
+ {
+ err = SbxBase::GetError();
+ SbxBase::ResetError();
+ }
+ // the value has to be scanned in completely
+ else if( nLen != s.getLength() && !pVar->PutString( s ) )
+ {
+ err = SbxBase::GetError();
+ SbxBase::ResetError();
+ }
+ else if( nLen != s.getLength() && 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() )
+ {
+ pCode = pRestart;
+ }
+ else
+ {
+ Error( err );
+ }
+ }
+ else
+ {
+ PopVar();
+ }
+}
+
+// Line Input to Variable. The variable is on TOS and is
+// deleted afterwards.
+
+void SbiRuntime::StepLINPUT()
+{
+ OString aInput;
+ pIosys->Read( aInput );
+ Error( pIosys->GetError() );
+ SbxVariableRef p = PopVar();
+ p->PutString(OStringToOUString(aInput, osl_getThreadTextEncoding()));
+}
+
+// end of program
+
+void SbiRuntime::StepSTOP()
+{
+ pInst->Stop();
+}
+
+
+void SbiRuntime::StepINITFOR()
+{
+ PushFor();
+}
+
+void SbiRuntime::StepINITFOREACH()
+{
+ PushForEach();
+}
+
+// increment FOR-variable
+
+void SbiRuntime::StepNEXT()
+{
+ if( !pForStk )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ return;
+ }
+ if( pForStk->eForType == FOR_TO )
+ {
+ pForStk->refVar->Compute( SbxPLUS, *pForStk->refInc );
+ }
+}
+
+// beginning CASE: TOS in CASE-stack
+
+void SbiRuntime::StepCASE()
+{
+ if( !refCaseStk.Is() )
+ {
+ refCaseStk = new SbxArray;
+ }
+ SbxVariableRef xVar = PopVar();
+ refCaseStk->Put( xVar, refCaseStk->Count() );
+}
+
+// end CASE: free variable
+
+void SbiRuntime::StepENDCASE()
+{
+ if( !refCaseStk || !refCaseStk->Count() )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ }
+ else
+ {
+ refCaseStk->Remove( refCaseStk->Count() - 1 );
+ }
+}
+
+
+void SbiRuntime::StepSTDERROR()
+{
+ pError = NULL; bError = true;
+ pInst->aErrorMsg = OUString();
+ pInst->nErr = 0L;
+ pInst->nErl = 0;
+ nError = 0L;
+ SbxErrObject::getUnoErrObject()->Clear();
+}
+
+void SbiRuntime::StepNOERROR()
+{
+ pInst->aErrorMsg = OUString();
+ pInst->nErr = 0L;
+ pInst->nErl = 0;
+ nError = 0L;
+ SbxErrObject::getUnoErrObject()->Clear();
+ bError = false;
+}
+
+// leave UP
+
+void SbiRuntime::StepLEAVE()
+{
+ bRun = 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 = channel number
+{
+ 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();
+ OUString s1 = p->GetOUString();
+ OUString s;
+ if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
+ {
+ s = " "; // one blank before
+ }
+ s += s1;
+ OString aByteStr(OUStringToOString(s, osl_getThreadTextEncoding()));
+ pIosys->Write( aByteStr );
+ Error( pIosys->GetError() );
+}
+
+void SbiRuntime::StepPRINTF() // print TOS in field
+{
+ SbxVariableRef p = PopVar();
+ OUString s1 = p->GetOUString();
+ OUStringBuffer s;
+ if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
+ {
+ s.append(' ');
+ }
+ s.append(s1);
+ comphelper::string::padToLength(s, 14, ' ');
+ OString aByteStr(OUStringToOString(s.makeStringAndClear(), osl_getThreadTextEncoding()));
+ pIosys->Write( aByteStr );
+ Error( pIosys->GetError() );
+}
+
+void SbiRuntime::StepWRITE() // write TOS
+{
+ SbxVariableRef p = PopVar();
+ // Does the string have to be encapsulated?
+ char ch = 0;
+ switch (p->GetType() )
+ {
+ case SbxSTRING: ch = '"'; break;
+ case SbxCURRENCY:
+ case SbxBOOL:
+ case SbxDATE: ch = '#'; break;
+ default: break;
+ }
+ OUString s;
+ if( ch )
+ {
+ s += OUString(ch);
+ }
+ s += p->GetOUString();
+ if( ch )
+ {
+ s += OUString(ch);
+ }
+ OString aByteStr(OUStringToOString(s, osl_getThreadTextEncoding()));
+ pIosys->Write( aByteStr );
+ Error( pIosys->GetError() );
+}
+
+void SbiRuntime::StepRENAME() // Rename Tos+1 to Tos
+{
+ SbxVariableRef pTos1 = PopVar();
+ SbxVariableRef pTos = PopVar();
+ OUString aDest = pTos1->GetOUString();
+ OUString aSource = pTos->GetOUString();
+
+ if( hasUno() )
+ {
+ implStepRenameUCB( aSource, aDest );
+ }
+ else
+ {
+ implStepRenameOSL( aSource, aDest );
+ }
+}
+
+// TOS = Prompt
+
+void SbiRuntime::StepPROMPT()
+{
+ SbxVariableRef p = PopVar();
+ OString aStr(OUStringToOString(p->GetOUString(), osl_getThreadTextEncoding()));
+ pIosys->SetPrompt( aStr );
+}
+
+// Set Restart point
+
+void SbiRuntime::StepRESTART()
+{
+ pRestart = pCode;
+}
+
+// empty expression on stack for missing parameter
+
+void SbiRuntime::StepEMPTY()
+{
+ // #57915 The semantics of StepEMPTY() is the representation of a missing argument.
+ // This is represented by the value 448 (SbERR_NAMED_NOT_FOUND) of the type error
+ // in VB. StepEmpty should now rather be named StepMISSING() but the name is kept
+ // to simplify matters.
+ SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
+ xVar->PutErr( 448 );
+ PushVar( xVar );
+}
+
+// TOS = error code
+
+void SbiRuntime::StepERROR()
+{
+ SbxVariableRef refCode = PopVar();
+ sal_uInt16 n = refCode->GetUShort();
+ SbError error = StarBASIC::GetSfxFromVBError( n );
+ if ( bVBAEnabled )
+ {
+ pInst->Error( error );
+ }
+ else
+ {
+ Error( error );
+ }
+}
+
+// loading a numeric constant (+ID)
+
+void SbiRuntime::StepLOADNC( sal_uInt32 nOp1 )
+{
+ SbxVariable* p = new SbxVariable( SbxDOUBLE );
+
+ // #57844 use localized function
+ OUString aStr = pImg->GetString( static_cast<short>( nOp1 ) );
+ // also allow , !!!
+ sal_Int32 iComma = aStr.indexOf((sal_Unicode)',');
+ if( iComma >= 0 )
+ {
+ aStr = aStr.replaceAt(iComma, 1, OUString("."));
+ }
+ double n = ::rtl::math::stringToDouble( aStr, '.', ',', NULL, NULL );
+
+ p->PutDouble( n );
+ PushVar( p );
+}
+
+// loading a string constant (+ID)
+
+void SbiRuntime::StepLOADSC( sal_uInt32 nOp1 )
+{
+ SbxVariable* p = new SbxVariable;
+ p->PutString( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ PushVar( p );
+}
+
+// Immediate Load (+Wert)
+
+void SbiRuntime::StepLOADI( sal_uInt32 nOp1 )
+{
+ SbxVariable* p = new SbxVariable;
+ p->PutInteger( static_cast<sal_Int16>( nOp1 ) );
+ PushVar( p );
+}
+
+// stora a named argument in Argv (+Arg-no. from 1!)
+
+void SbiRuntime::StepARGN( sal_uInt32 nOp1 )
+{
+ if( !refArgv )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ else
+ {
+ OUString aAlias( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ SbxVariableRef pVal = PopVar();
+ if( bVBAEnabled && ( pVal->ISA(SbxMethod) || pVal->ISA(SbUnoProperty) || pVal->ISA(SbProcedureProperty) ) )
+ {
+ // named variables ( that are Any especially properties ) can be empty at this point and need a broadcast
+ if ( pVal->GetType() == SbxEMPTY )
+ pVal->Broadcast( SBX_HINT_DATAWANTED );
+ // evaluate methods and properties!
+ SbxVariable* pRes = new SbxVariable( *pVal );
+ pVal = pRes;
+ }
+ refArgv->Put( pVal, nArgc );
+ refArgv->PutAlias( aAlias, nArgc++ );
+ }
+}
+
+// converting the type of an argument in Argv for DECLARE-Fkt. (+type)
+
+void SbiRuntime::StepARGTYP( sal_uInt32 nOp1 )
+{
+ if( !refArgv )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ else
+ {
+ bool bByVal = (nOp1 & 0x8000) != 0; // Ist BYVAL requested?
+ SbxDataType t = (SbxDataType) (nOp1 & 0x7FFF);
+ SbxVariable* pVar = refArgv->Get( refArgv->Count() - 1 ); // last Arg
+
+ // check BYVAL
+ if( pVar->GetRefCount() > 2 ) // 2 is normal for BYVAL
+ {
+ // parameter is a reference
+ if( bByVal )
+ {
+ // Call by Value is requested -> create a copy
+ pVar = new SbxVariable( *pVar );
+ pVar->SetFlag( SBX_READWRITE );
+ refExprStk->Put( pVar, refArgv->Count() - 1 );
+ }
+ else
+ pVar->SetFlag( SBX_REFERENCE ); // Ref-Flag for DllMgr
+ }
+ else
+ {
+ // parameter is NO reference
+ if( bByVal )
+ pVar->ResetFlag( SBX_REFERENCE ); // no reference -> OK
+ else
+ Error( SbERR_BAD_PARAMETERS ); // reference needed
+ }
+
+ if( pVar->GetType() != t )
+ {
+ // variant for correct conversion
+ // besides error, if SbxBYREF
+ pVar->Convert( SbxVARIANT );
+ pVar->Convert( t );
+ }
+ }
+}
+
+// bring string to a definite length (+length)
+
+void SbiRuntime::StepPAD( sal_uInt32 nOp1 )
+{
+ SbxVariable* p = GetTOS();
+ OUString s = p->GetOUString();
+ sal_Int32 nLen(nOp1);
+ if( s.getLength() != nLen )
+ {
+ OUStringBuffer aBuf(s);
+ if (aBuf.getLength() > nLen)
+ {
+ comphelper::string::truncateToLength(aBuf, nLen);
+ }
+ else
+ {
+ comphelper::string::padToLength(aBuf, nLen, ' ');
+ }
+ s = aBuf.makeStringAndClear();
+ }
+}
+
+// jump (+target)
+
+void SbiRuntime::StepJUMP( sal_uInt32 nOp1 )
+{
+#ifdef DBG_UTIL
+ // #QUESTION shouln't this be
+ // if( (sal_uInt8*)( nOp1+pImagGetCode() ) >= pImg->GetCodeSize() )
+ if( nOp1 >= pImg->GetCodeSize() )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+#endif
+ pCode = (const sal_uInt8*) pImg->GetCode() + nOp1;
+}
+
+// evaluate TOS, conditional jump (+target)
+
+void SbiRuntime::StepJUMPT( sal_uInt32 nOp1 )
+{
+ SbxVariableRef p = PopVar();
+ if( p->GetBool() )
+ StepJUMP( nOp1 );
+}
+
+// evaluate TOS, conditional jump (+target)
+
+void SbiRuntime::StepJUMPF( sal_uInt32 nOp1 )
+{
+ SbxVariableRef p = PopVar();
+ // In a test e.g. If Null then
+ // will evaluate Null will act as if False
+ if( ( bVBAEnabled && p->IsNull() ) || !p->GetBool() )
+ StepJUMP( nOp1 );
+}
+
+// evaluate TOS, jump into JUMP-table (+MaxVal)
+// looks like this:
+// ONJUMP 2
+// JUMP target1
+// JUMP target2
+// ...
+// if 0x8000 is set in the operand, push the return address (ON..GOSUB)
+
+void SbiRuntime::StepONJUMP( sal_uInt32 nOp1 )
+{
+ SbxVariableRef p = PopVar();
+ sal_Int16 n = p->GetInteger();
+ if( nOp1 & 0x8000 )
+ {
+ nOp1 &= 0x7FFF;
+ PushGosub( pCode + 5 * nOp1 );
+ }
+ if( n < 1 || static_cast<sal_uInt32>(n) > nOp1 )
+ n = static_cast<sal_Int16>( nOp1 + 1 );
+ nOp1 = (sal_uInt32) ( (const char*) pCode - pImg->GetCode() ) + 5 * --n;
+ StepJUMP( nOp1 );
+}
+
+// UP-call (+target)
+
+void SbiRuntime::StepGOSUB( sal_uInt32 nOp1 )
+{
+ PushGosub( pCode );
+ if( nOp1 >= pImg->GetCodeSize() )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ pCode = (const sal_uInt8*) pImg->GetCode() + nOp1;
+}
+
+// UP-return (+0 or target)
+
+void SbiRuntime::StepRETURN( sal_uInt32 nOp1 )
+{
+ PopGosub();
+ if( nOp1 )
+ StepJUMP( nOp1 );
+}
+
+// check FOR-variable (+Endlabel)
+
+void SbiRuntime::StepTESTFOR( sal_uInt32 nOp1 )
+{
+ if( !pForStk )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ return;
+ }
+
+ bool bEndLoop = false;
+ switch( pForStk->eForType )
+ {
+ case FOR_TO:
+ {
+ SbxOperator eOp = ( pForStk->refInc->GetDouble() < 0 ) ? SbxLT : SbxGT;
+ if( pForStk->refVar->Compare( eOp, *pForStk->refEnd ) )
+ bEndLoop = true;
+ break;
+ }
+ case FOR_EACH_ARRAY:
+ {
+ SbiForStack* p = pForStk;
+ if( p->pArrayCurIndices == NULL )
+ {
+ bEndLoop = true;
+ }
+ else
+ {
+ SbxDimArray* pArray = (SbxDimArray*)(SbxVariable*)p->refEnd;
+ short nDims = pArray->GetDims();
+
+ // Empty array?
+ if( nDims == 1 && p->pArrayLowerBounds[0] > p->pArrayUpperBounds[0] )
+ {
+ bEndLoop = true;
+ break;
+ }
+ SbxVariable* pVal = pArray->Get32( p->pArrayCurIndices );
+ *(p->refVar) = *pVal;
+
+ bool bFoundNext = false;
+ for( short i = 0 ; i < nDims ; i++ )
+ {
+ if( p->pArrayCurIndices[i] < p->pArrayUpperBounds[i] )
+ {
+ bFoundNext = true;
+ p->pArrayCurIndices[i]++;
+ for( short j = i - 1 ; j >= 0 ; j-- )
+ p->pArrayCurIndices[j] = p->pArrayLowerBounds[j];
+ break;
+ }
+ }
+ if( !bFoundNext )
+ {
+ delete[] p->pArrayCurIndices;
+ p->pArrayCurIndices = NULL;
+ }
+ }
+ break;
+ }
+ case FOR_EACH_COLLECTION:
+ {
+ BasicCollection* pCollection = (BasicCollection*)(SbxVariable*)pForStk->refEnd;
+ SbxArrayRef xItemArray = pCollection->xItemArray;
+ sal_Int32 nCount = xItemArray->Count32();
+ if( pForStk->nCurCollectionIndex < nCount )
+ {
+ SbxVariable* pRes = xItemArray->Get32( pForStk->nCurCollectionIndex );
+ pForStk->nCurCollectionIndex++;
+ (*pForStk->refVar) = *pRes;
+ }
+ else
+ {
+ bEndLoop = true;
+ }
+ break;
+ }
+ case FOR_EACH_XENUMERATION:
+ {
+ SbiForStack* p = pForStk;
+ if( p->xEnumeration->hasMoreElements() )
+ {
+ Any aElem = p->xEnumeration->nextElement();
+ SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
+ unoToSbxValue( (SbxVariable*)xVar, aElem );
+ (*pForStk->refVar) = *xVar;
+ }
+ else
+ {
+ bEndLoop = true;
+ }
+ break;
+ }
+ }
+ if( bEndLoop )
+ {
+ PopFor();
+ StepJUMP( nOp1 );
+ }
+}
+
+// Tos+1 <= Tos+2 <= Tos, 2xremove (+Target)
+
+void SbiRuntime::StepCASETO( sal_uInt32 nOp1 )
+{
+ if( !refCaseStk || !refCaseStk->Count() )
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ else
+ {
+ SbxVariableRef xTo = PopVar();
+ SbxVariableRef xFrom = PopVar();
+ SbxVariableRef xCase = refCaseStk->Get( refCaseStk->Count() - 1 );
+ if( *xCase >= *xFrom && *xCase <= *xTo )
+ StepJUMP( nOp1 );
+ }
+}
+
+
+void SbiRuntime::StepERRHDL( sal_uInt32 nOp1 )
+{
+ const sal_uInt8* p = pCode;
+ StepJUMP( nOp1 );
+ pError = pCode;
+ pCode = p;
+ pInst->aErrorMsg = OUString();
+ pInst->nErr = 0;
+ pInst->nErl = 0;
+ nError = 0;
+ SbxErrObject::getUnoErrObject()->Clear();
+}
+
+// Resume after errors (+0=statement, 1=next or Label)
+
+void SbiRuntime::StepRESUME( sal_uInt32 nOp1 )
+{
+ // #32714 Resume without error? -> error
+ if( !bInError )
+ {
+ Error( SbERR_BAD_RESUME );
+ return;
+ }
+ if( nOp1 )
+ {
+ // set Code-pointer to the next statement
+ sal_uInt16 n1, n2;
+ pCode = pMod->FindNextStmnt( pErrCode, n1, n2, sal_True, pImg );
+ }
+ else
+ pCode = pErrStmnt;
+ if ( pError ) // current in error handler ( and got a Resume Next statement )
+ SbxErrObject::getUnoErrObject()->Clear();
+
+ if( nOp1 > 1 )
+ StepJUMP( nOp1 );
+ pInst->aErrorMsg = OUString();
+ pInst->nErr = 0;
+ pInst->nErl = 0;
+ nError = 0;
+ bInError = false;
+}
+
+// close channel (+channel, 0=all)
+void SbiRuntime::StepCLOSE( sal_uInt32 nOp1 )
+{
+ SbError err;
+ if( !nOp1 )
+ pIosys->Shutdown();
+ else
+ {
+ err = pIosys->GetError();
+ if( !err )
+ {
+ pIosys->Close();
+ }
+ }
+ err = pIosys->GetError();
+ Error( err );
+}
+
+// output character (+char)
+
+void SbiRuntime::StepPRCHAR( sal_uInt32 nOp1 )
+{
+ OString s(static_cast<sal_Char>(nOp1));
+ pIosys->Write( s );
+ Error( pIosys->GetError() );
+}
+
+// check whether TOS is a certain object class (+StringID)
+
+bool SbiRuntime::implIsClass( SbxObject* pObj, const OUString& aClass )
+{
+ bool bRet = true;
+
+ if( !aClass.isEmpty() )
+ {
+ bRet = pObj->IsClass( aClass );
+ if( !bRet )
+ bRet = aClass.equalsIgnoreAsciiCase( "object" );
+ if( !bRet )
+ {
+ OUString aObjClass = pObj->GetClassName();
+ SbModule* pClassMod = GetSbData()->pClassFac->FindClass( aObjClass );
+ SbClassData* pClassData;
+ if( pClassMod && (pClassData=pClassMod->pClassData) != NULL )
+ {
+ SbxVariable* pClassVar = pClassData->mxIfaces->Find( aClass, SbxCLASS_DONTCARE );
+ bRet = (pClassVar != NULL);
+ }
+ }
+ }
+ return bRet;
+}
+
+bool SbiRuntime::checkClass_Impl( const SbxVariableRef& refVal,
+ const OUString& aClass, bool bRaiseErrors, bool bDefault )
+{
+ bool bOk = bDefault;
+
+ SbxDataType t = refVal->GetType();
+ SbxVariable* pVal = (SbxVariable*)refVal;
+ // we don't know the type of uno properties that are (maybevoid)
+ if ( t == SbxEMPTY && refVal->ISA(SbUnoProperty) )
+ {
+ SbUnoProperty* pProp = (SbUnoProperty*)pVal;
+ t = pProp->getRealType();
+ }
+ if( t == SbxOBJECT )
+ {
+ SbxObject* pObj;
+ if( pVal->IsA( TYPE(SbxObject) ) )
+ pObj = (SbxObject*) pVal;
+ else
+ {
+ pObj = (SbxObject*) refVal->GetObject();
+ if( pObj && !pObj->IsA( TYPE(SbxObject) ) )
+ pObj = NULL;
+ }
+ if( pObj )
+ {
+ if( !implIsClass( pObj, aClass ) )
+ {
+ if ( bVBAEnabled && pObj->IsA( TYPE(SbUnoObject) ) )
+ {
+ SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
+ bOk = checkUnoObjectType( pUnoObj, aClass );
+ }
+ else
+ bOk = false;
+ if ( !bOk )
+ {
+ if( bRaiseErrors )
+ Error( SbERR_INVALID_USAGE_OBJECT );
+ }
+ }
+ else
+ {
+ bOk = true;
+
+ SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pObj);
+ if( pClassModuleObject != NULL )
+ pClassModuleObject->triggerInitializeEvent();
+ }
+ }
+ }
+ else
+ {
+ if ( !bVBAEnabled )
+ {
+ if( bRaiseErrors )
+ Error( SbERR_NEEDS_OBJECT );
+ bOk = false;
+ }
+ }
+ return bOk;
+}
+
+void SbiRuntime::StepSETCLASS_impl( sal_uInt32 nOp1, bool bHandleDflt )
+{
+ SbxVariableRef refVal = PopVar();
+ SbxVariableRef refVar = PopVar();
+ OUString aClass( pImg->GetString( static_cast<short>( nOp1 ) ) );
+
+ bool bOk = checkClass_Impl( refVal, aClass, true );
+ if( bOk )
+ {
+ StepSET_Impl( refVal, refVar, bHandleDflt ); // don't do handle dflt prop for a "proper" set
+ }
+}
+
+void SbiRuntime::StepVBASETCLASS( sal_uInt32 nOp1 )
+{
+ StepSETCLASS_impl( nOp1, false );
+}
+
+void SbiRuntime::StepSETCLASS( sal_uInt32 nOp1 )
+{
+ StepSETCLASS_impl( nOp1, true );
+}
+
+void SbiRuntime::StepTESTCLASS( sal_uInt32 nOp1 )
+{
+ SbxVariableRef xObjVal = PopVar();
+ OUString aClass( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ bool bDefault = !bVBAEnabled;
+ bool bOk = checkClass_Impl( xObjVal, aClass, false, bDefault );
+
+ SbxVariable* pRet = new SbxVariable;
+ pRet->PutBool( bOk );
+ PushVar( pRet );
+}
+
+// define library for following declare-call
+
+void SbiRuntime::StepLIB( sal_uInt32 nOp1 )
+{
+ aLibName = pImg->GetString( static_cast<short>( nOp1 ) );
+}
+
+// TOS is incremented by BASE, BASE is pushed before (+BASE)
+// This opcode is pushed before DIM/REDIM-commands,
+// if there's been only one index named.
+
+void SbiRuntime::StepBASED( sal_uInt32 nOp1 )
+{
+ SbxVariable* p1 = new SbxVariable;
+ SbxVariableRef x2 = PopVar();
+
+ // #109275 Check compatiblity mode
+ bool bCompatible = ((nOp1 & 0x8000) != 0);
+ sal_uInt16 uBase = static_cast<sal_uInt16>(nOp1 & 1); // Can only be 0 or 1
+ p1->PutInteger( uBase );
+ if( !bCompatible )
+ x2->Compute( SbxPLUS, *p1 );
+ PushVar( x2 ); // first the Expr
+ PushVar( p1 ); // then the Base
+}
+
+// the bits in the String-ID:
+// 0x8000 - Argv is reserved
+
+SbxVariable* SbiRuntime::FindElement( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt32 nOp2,
+ SbError nNotFound, bool bLocal, bool bStatic )
+{
+ bool bIsVBAInterOp = SbiRuntime::isVBAEnabled();
+ if( bIsVBAInterOp )
+ {
+ StarBASIC* pMSOMacroRuntimeLib = GetSbData()->pMSOMacroRuntimLib;
+ if( pMSOMacroRuntimeLib != NULL )
+ {
+ pMSOMacroRuntimeLib->ResetFlag( SBX_EXTSEARCH );
+ }
+ }
+
+ SbxVariable* pElem = NULL;
+ if( !pObj )
+ {
+ Error( SbERR_NO_OBJECT );
+ pElem = new SbxVariable;
+ }
+ else
+ {
+ bool bFatalError = false;
+ SbxDataType t = (SbxDataType) nOp2;
+ OUString aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) );
+ // Hacky capture of Evaluate [] syntax
+ // this should be tackled I feel at the pcode level
+ if ( bIsVBAInterOp && aName.indexOf((sal_Unicode)'[') == 0 )
+ {
+ // emulate pcode here
+ StepARGC();
+ // psuedo StepLOADSC
+ OUString sArg = aName.copy( 1, aName.getLength() - 2 );
+ SbxVariable* p = new SbxVariable;
+ p->PutString( sArg );
+ PushVar( p );
+ StepARGV();
+ nOp1 = nOp1 | 0x8000; // indicate params are present
+ aName = OUString("Evaluate");
+ }
+ if( bLocal )
+ {
+ if ( bStatic )
+ {
+ if ( pMeth )
+ {
+ pElem = pMeth->GetStatics()->Find( aName, SbxCLASS_DONTCARE );
+ }
+ }
+
+ if ( !pElem )
+ {
+ pElem = refLocals->Find( aName, SbxCLASS_DONTCARE );
+ }
+ }
+ if( !pElem )
+ {
+ bool bSave = rBasic.bNoRtl;
+ rBasic.bNoRtl = true;
+ pElem = pObj->Find( aName, SbxCLASS_DONTCARE );
+
+ // #110004, #112015: Make private really private
+ if( bLocal && pElem ) // Local as flag for global search
+ {
+ if( pElem->IsSet( SBX_PRIVATE ) )
+ {
+ SbiInstance* pInst_ = GetSbData()->pInst;
+ if( pInst_ && pInst_->IsCompatibility() && pObj != pElem->GetParent() )
+ {
+ pElem = NULL; // Found but in wrong module!
+ }
+ // Interfaces: Use SBX_EXTFOUND
+ }
+ }
+ rBasic.bNoRtl = bSave;
+
+ // is it a global uno-identifier?
+ if( bLocal && !pElem )
+ {
+ bool bSetName = true; // preserve normal behaviour
+
+ // i#i68894# if VBAInterOp favour searching vba globals
+ // over searching for uno classess
+ if ( bVBAEnabled )
+ {
+ // Try Find in VBA symbols space
+ pElem = rBasic.VBAFind( aName, SbxCLASS_DONTCARE );
+ if ( pElem )
+ {
+ bSetName = false; // don't overwrite uno name
+ }
+ else
+ {
+ pElem = VBAConstantHelper::instance().getVBAConstant( aName );
+ }
+ }
+
+ if( !pElem )
+ {
+ // #72382 ATTENTION! ALWAYS returns a result now
+ // because of unknown modules!
+ SbUnoClass* pUnoClass = findUnoClass( aName );
+ if( pUnoClass )
+ {
+ pElem = new SbxVariable( t );
+ SbxValues aRes( SbxOBJECT );
+ aRes.pObj = pUnoClass;
+ pElem->SbxVariable::Put( aRes );
+ }
+ }
+
+ // #62939 If an uno-class has been found, the wrapper
+ // object has to be held, because the uno-class, e. g.
+ // "stardiv", has to be read out of the registry
+ // every time again otherwise
+ if( pElem )
+ {
+ // #63774 May not be saved too!!!
+ pElem->SetFlag( SBX_DONTSTORE );
+ pElem->SetFlag( SBX_NO_MODIFY);
+
+ // #72382 save locally, all variables that have been declared
+ // implicit would become global automatically otherwise!
+ if ( bSetName )
+ {
+ pElem->SetName( aName );
+ }
+ refLocals->Put( pElem, refLocals->Count() );
+ }
+ }
+
+ if( !pElem )
+ {
+ // not there and not in the object?
+ // don't establish if that thing has parameters!
+ if( nOp1 & 0x8000 )
+ {
+ bFatalError = true;
+ }
+
+ // else, if there are parameters, use different error code
+ if( !bLocal || pImg->GetFlag( SBIMG_EXPLICIT ) )
+ {
+ // #39108 if explicit and as ELEM always a fatal error
+ bFatalError = true;
+
+
+ if( !( nOp1 & 0x8000 ) && nNotFound == SbERR_PROC_UNDEFINED )
+ {
+ nNotFound = SbERR_VAR_UNDEFINED;
+ }
+ }
+ if( bFatalError )
+ {
+ // #39108 use dummy variable instead of fatal error
+ if( !xDummyVar.Is() )
+ {
+ xDummyVar = new SbxVariable( SbxVARIANT );
+ }
+ pElem = xDummyVar;
+
+ ClearArgvStack();
+
+ Error( nNotFound, aName );
+ }
+ else
+ {
+ if ( bStatic )
+ {
+ pElem = StepSTATIC_Impl( aName, t );
+ }
+ if ( !pElem )
+ {
+ pElem = new SbxVariable( t );
+ if( t != SbxVARIANT )
+ {
+ pElem->SetFlag( SBX_FIXED );
+ }
+ pElem->SetName( aName );
+ refLocals->Put( pElem, refLocals->Count() );
+ }
+ }
+ }
+ }
+ // #39108 Args can already be deleted!
+ if( !bFatalError )
+ {
+ SetupArgs( pElem, nOp1 );
+ }
+ // because a particular call-type is requested
+ if( pElem->IsA( TYPE(SbxMethod) ) )
+ {
+ // shall the type be converted?
+ SbxDataType t2 = pElem->GetType();
+ bool bSet = false;
+ if( !( pElem->GetFlags() & SBX_FIXED ) )
+ {
+ if( t != SbxVARIANT && t != t2 &&
+ t >= SbxINTEGER && t <= SbxSTRING )
+ {
+ pElem->SetType( t ), bSet = true;
+ }
+ }
+ // assign pElem to a Ref, to delete a temp-var if applicable
+ SbxVariableRef refTemp = pElem;
+
+ // remove potential rests of the last call of the SbxMethod
+ // free Write before, so that there's no error
+ sal_uInt16 nSavFlags = pElem->GetFlags();
+ pElem->SetFlag( SBX_READWRITE | SBX_NO_BROADCAST );
+ pElem->SbxValue::Clear();
+ pElem->SetFlags( nSavFlags );
+
+ // don't touch before setting, as e. g. LEFT()
+ // has to know the difference between Left$() and Left()
+
+ // because the methods' parameters are cut away in PopVar()
+ SbxVariable* pNew = new SbxMethod( *((SbxMethod*)pElem) );
+ //OLD: SbxVariable* pNew = new SbxVariable( *pElem );
+
+ pElem->SetParameters(0);
+ pNew->SetFlag( SBX_READWRITE );
+
+ if( bSet )
+ {
+ pElem->SetType( t2 );
+ }
+ pElem = pNew;
+ }
+ // consider index-access for UnoObjects
+ // definitely we want this for VBA where properties are often
+ // collections ( which need index access ), but lets only do
+ // this if we actually have params following
+ else if( bVBAEnabled && pElem->ISA(SbUnoProperty) && pElem->GetParameters() )
+ {
+ SbxVariableRef refTemp = pElem;
+
+ // dissolve the notify while copying variable
+ SbxVariable* pNew = new SbxVariable( *((SbxVariable*)pElem) );
+ pElem->SetParameters( NULL );
+ pElem = pNew;
+ }
+ }
+ return CheckArray( pElem );
+}
+
+// for current scope (e. g. query from BASIC-IDE)
+SbxBase* SbiRuntime::FindElementExtern( const OUString& rName )
+{
+ // don't expect pMeth to be != 0, as there are none set
+ // in the RunInit yet
+
+ SbxVariable* pElem = NULL;
+ if( !pMod || rName.isEmpty() )
+ {
+ return NULL;
+ }
+ if( refLocals )
+ {
+ pElem = refLocals->Find( rName, SbxCLASS_DONTCARE );
+ }
+ if ( !pElem && pMeth )
+ {
+ // for statics, set the method's name in front
+ OUString aMethName = pMeth->GetName();
+ aMethName += ":";
+ aMethName += rName;
+ pElem = pMod->Find(aMethName, SbxCLASS_DONTCARE);
+ }
+
+ // search in parameter list
+ if( !pElem && pMeth )
+ {
+ SbxInfo* pInfo = pMeth->GetInfo();
+ if( pInfo && refParams )
+ {
+ sal_uInt16 nParamCount = refParams->Count();
+ sal_uInt16 j = 1;
+ const SbxParamInfo* pParam = pInfo->GetParam( j );
+ while( pParam )
+ {
+ if( pParam->aName.equalsIgnoreAsciiCase( rName ) )
+ {
+ if( j >= nParamCount )
+ {
+ // Parameter is missing
+ pElem = new SbxVariable( SbxSTRING );
+ pElem->PutString( OUString("<missing parameter>"));
+ }
+ else
+ {
+ pElem = refParams->Get( j );
+ }
+ break;
+ }
+ pParam = pInfo->GetParam( ++j );
+ }
+ }
+ }
+
+ // search in module
+ if( !pElem )
+ {
+ bool bSave = rBasic.bNoRtl;
+ rBasic.bNoRtl = true;
+ pElem = pMod->Find( rName, SbxCLASS_DONTCARE );
+ rBasic.bNoRtl = bSave;
+ }
+ return pElem;
+}
+
+
+
+void SbiRuntime::SetupArgs( SbxVariable* p, sal_uInt32 nOp1 )
+{
+ if( nOp1 & 0x8000 )
+ {
+ if( !refArgv )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ }
+ bool bHasNamed = false;
+ sal_uInt16 i;
+ sal_uInt16 nArgCount = refArgv->Count();
+ for( i = 1 ; i < nArgCount ; i++ )
+ {
+ if( !refArgv->GetAlias(i).isEmpty() )
+ {
+ bHasNamed = true; break;
+ }
+ }
+ if( bHasNamed )
+ {
+ SbxInfo* pInfo = p->GetInfo();
+ if( !pInfo )
+ {
+ bool bError_ = true;
+
+ SbUnoMethod* pUnoMethod = PTR_CAST(SbUnoMethod,p);
+ SbUnoProperty* pUnoProperty = PTR_CAST(SbUnoProperty,p);
+ if( pUnoMethod || pUnoProperty )
+ {
+ SbUnoObject* pParentUnoObj = PTR_CAST( SbUnoObject,p->GetParent() );
+ if( pParentUnoObj )
+ {
+ Any aUnoAny = pParentUnoObj->getUnoAny();
+ Reference< XInvocation > xInvocation;
+ aUnoAny >>= xInvocation;
+ if( xInvocation.is() ) // TODO: if( xOLEAutomation.is() )
+ {
+ bError_ = false;
+
+ sal_uInt16 nCurPar = 1;
+ AutomationNamedArgsSbxArray* pArg =
+ new AutomationNamedArgsSbxArray( nArgCount );
+ OUString* pNames = pArg->getNames().getArray();
+ for( i = 1 ; i < nArgCount ; i++ )
+ {
+ SbxVariable* pVar = refArgv->Get( i );
+ const OUString& rName = refArgv->GetAlias( i );
+ if( !rName.isEmpty() )
+ {
+ pNames[i] = rName;
+ }
+ pArg->Put( pVar, nCurPar++ );
+ }
+ refArgv = pArg;
+ }
+ }
+ }
+ else if( bVBAEnabled && p->GetType() == SbxOBJECT && (!p->ISA(SbxMethod) || !p->IsBroadcaster()) )
+ {
+ // Check for default method with named parameters
+ SbxBaseRef pObj = (SbxBase*)p->GetObject();
+ if( pObj && pObj->ISA(SbUnoObject) )
+ {
+ SbUnoObject* pUnoObj = (SbUnoObject*)(SbxBase*)pObj;
+ Any aAny = pUnoObj->getUnoAny();
+
+ if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
+ {
+ Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue();
+ Reference< XDefaultMethod > xDfltMethod( x, UNO_QUERY );
+
+ OUString sDefaultMethod;
+ if ( xDfltMethod.is() )
+ {
+ sDefaultMethod = xDfltMethod->getDefaultMethodName();
+ }
+ if ( !sDefaultMethod.isEmpty() )
+ {
+ SbxVariable* meth = pUnoObj->Find( sDefaultMethod, SbxCLASS_METHOD );
+ if( meth != NULL )
+ {
+ pInfo = meth->GetInfo();
+ }
+ if( pInfo )
+ {
+ bError_ = false;
+ }
+ }
+ }
+ }
+ }
+ if( bError_ )
+ {
+ Error( SbERR_NO_NAMED_ARGS );
+ }
+ }
+ else
+ {
+ sal_uInt16 nCurPar = 1;
+ SbxArray* pArg = new SbxArray;
+ for( i = 1 ; i < nArgCount ; i++ )
+ {
+ SbxVariable* pVar = refArgv->Get( i );
+ const OUString& rName = refArgv->GetAlias( i );
+ if( !rName.isEmpty() )
+ {
+ // nCurPar is set to the found parameter
+ sal_uInt16 j = 1;
+ const SbxParamInfo* pParam = pInfo->GetParam( j );
+ while( pParam )
+ {
+ if( pParam->aName.equalsIgnoreAsciiCase( rName ) )
+ {
+ nCurPar = j;
+ break;
+ }
+ pParam = pInfo->GetParam( ++j );
+ }
+ if( !pParam )
+ {
+ Error( SbERR_NAMED_NOT_FOUND ); break;
+ }
+ }
+ pArg->Put( pVar, nCurPar++ );
+ }
+ refArgv = pArg;
+ }
+ }
+ // own var as parameter 0
+ refArgv->Put( p, 0 );
+ p->SetParameters( refArgv );
+ PopArgv();
+ }
+ else
+ {
+ p->SetParameters( NULL );
+ }
+}
+
+// getting an array element
+
+SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem )
+{
+ SbxArray* pPar;
+ if( ( pElem->GetType() & SbxARRAY ) && (SbxVariable*)refRedim != pElem )
+ {
+ SbxBase* pElemObj = pElem->GetObject();
+ SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
+ pPar = pElem->GetParameters();
+ if( pDimArray )
+ {
+ // parameters may be missing, if an array is
+ // passed as an argument
+ if( pPar )
+ pElem = pDimArray->Get( pPar );
+ }
+ else
+ {
+ SbxArray* pArray = PTR_CAST(SbxArray,pElemObj);
+ if( pArray )
+ {
+ if( !pPar )
+ {
+ Error( SbERR_OUT_OF_RANGE );
+ pElem = new SbxVariable;
+ }
+ else
+ {
+ pElem = pArray->Get( pPar->Get( 1 )->GetInteger() );
+ }
+ }
+ }
+
+ // #42940, set parameter 0 to NULL so that var doesn't contain itself
+ if( pPar )
+ {
+ pPar->Put( NULL, 0 );
+ }
+ }
+ // consider index-access for UnoObjects
+ else if( pElem->GetType() == SbxOBJECT && !pElem->ISA(SbxMethod) && ( !bVBAEnabled || ( bVBAEnabled && !pElem->ISA(SbxProperty) ) ) )
+ {
+ pPar = pElem->GetParameters();
+ if ( pPar )
+ {
+ // is it an uno-object?
+ SbxBaseRef pObj = (SbxBase*)pElem->GetObject();
+ if( pObj )
+ {
+ if( pObj->ISA(SbUnoObject) )
+ {
+ SbUnoObject* pUnoObj = (SbUnoObject*)(SbxBase*)pObj;
+ Any aAny = pUnoObj->getUnoAny();
+
+ if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
+ {
+ Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue();
+ Reference< XIndexAccess > xIndexAccess( x, UNO_QUERY );
+ if ( !bVBAEnabled )
+ {
+ if( xIndexAccess.is() )
+ {
+ sal_uInt32 nParamCount = (sal_uInt32)pPar->Count() - 1;
+ if( nParamCount != 1 )
+ {
+ StarBASIC::Error( SbERR_BAD_ARGUMENT );
+ return pElem;
+ }
+
+ // get index
+ sal_Int32 nIndex = pPar->Get( 1 )->GetLong();
+ Reference< XInterface > xRet;
+ try
+ {
+ Any aAny2 = xIndexAccess->getByIndex( nIndex );
+ TypeClass eType = aAny2.getValueType().getTypeClass();
+ if( eType == TypeClass_INTERFACE )
+ {
+ xRet = *(Reference< XInterface >*)aAny2.getValue();
+ }
+ }
+ catch (const IndexOutOfBoundsException&)
+ {
+ // usually expect converting problem
+ StarBASIC::Error( SbERR_OUT_OF_RANGE );
+ }
+
+ // #57847 always create a new variable, else error
+ // due to PutObject(NULL) at ReadOnly-properties
+ pElem = new SbxVariable( SbxVARIANT );
+ if( xRet.is() )
+ {
+ aAny <<= xRet;
+
+ // #67173 don't specify a name so that the real class name is entered
+ OUString aName;
+ SbxObjectRef xWrapper = (SbxObject*)new SbUnoObject( aName, aAny );
+ pElem->PutObject( xWrapper );
+ }
+ else
+ {
+ pElem->PutObject( NULL );
+ }
+ }
+ }
+ else
+ {
+ // check if there isn't a default member between the current variable
+ // and the params, e.g.
+ // Dim rst1 As New ADODB.Recordset
+ // "
+ // val = rst1("FirstName")
+ // has the default 'Fields' member between rst1 and '("FirstName")'
+ SbxVariable* pDflt = getDefaultProp( pElem );
+ if ( pDflt )
+ {
+ pDflt->Broadcast( SBX_HINT_DATAWANTED );
+ SbxBaseRef pDfltObj = (SbxBase*)pDflt->GetObject();
+ if( pDfltObj )
+ {
+ if( pDfltObj->ISA(SbUnoObject) )
+ {
+ pUnoObj = (SbUnoObject*)(SbxBase*)pDfltObj;
+ Any aUnoAny = pUnoObj->getUnoAny();
+
+ if( aUnoAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
+ x = *(Reference< XInterface >*)aUnoAny.getValue();
+ pElem = pDflt;
+ }
+ }
+ }
+ OUString sDefaultMethod;
+
+ Reference< XDefaultMethod > xDfltMethod( x, UNO_QUERY );
+
+ if ( xDfltMethod.is() )
+ {
+ sDefaultMethod = xDfltMethod->getDefaultMethodName();
+ }
+ else if( xIndexAccess.is() )
+ {
+ sDefaultMethod = OUString( "getByIndex" );
+ }
+ if ( !sDefaultMethod.isEmpty() )
+ {
+ SbxVariable* meth = pUnoObj->Find( sDefaultMethod, SbxCLASS_METHOD );
+ SbxVariableRef refTemp = meth;
+ if ( refTemp )
+ {
+ meth->SetParameters( pPar );
+ SbxVariable* pNew = new SbxMethod( *(SbxMethod*)meth );
+ pElem = pNew;
+ }
+ }
+ }
+ }
+
+ // #42940, set parameter 0 to NULL so that var doesn't contain itself
+ pPar->Put( NULL, 0 );
+ }
+ else if( pObj->ISA(BasicCollection) )
+ {
+ BasicCollection* pCol = (BasicCollection*)(SbxBase*)pObj;
+ pElem = new SbxVariable( SbxVARIANT );
+ pPar->Put( pElem, 0 );
+ pCol->CollItem( pPar );
+ }
+ }
+ else if( bVBAEnabled ) // !pObj
+ {
+ SbxArray* pParam = pElem->GetParameters();
+ if( pParam != NULL && !pElem->IsSet( SBX_VAR_TO_DIM ) )
+ {
+ Error( SbERR_NO_OBJECT );
+ }
+ }
+ }
+ }
+
+ return pElem;
+}
+
+// loading an element from the runtime-library (+StringID+type)
+
+void SbiRuntime::StepRTL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ PushVar( FindElement( rBasic.pRtl, nOp1, nOp2, SbERR_PROC_UNDEFINED, false ) );
+}
+
+void SbiRuntime::StepFIND_Impl( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt32 nOp2,
+ SbError nNotFound, bool bLocal, bool bStatic )
+{
+ if( !refLocals )
+ {
+ refLocals = new SbxArray;
+ }
+ PushVar( FindElement( pObj, nOp1, nOp2, nNotFound, bLocal, bStatic ) );
+}
+// loading a local/global variable (+StringID+type)
+
+void SbiRuntime::StepFIND( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, true );
+}
+
+// Search inside a class module (CM) to enable global search in time
+void SbiRuntime::StepFIND_CM( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+
+ SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pMod);
+ if( pClassModuleObject )
+ {
+ pMod->SetFlag( SBX_GBLSEARCH );
+ }
+ StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, true );
+
+ if( pClassModuleObject )
+ {
+ pMod->ResetFlag( SBX_GBLSEARCH );
+ }
+}
+
+void SbiRuntime::StepFIND_STATIC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, true, true );
+}
+
+// loading an object-element (+StringID+type)
+// the object lies on TOS
+
+void SbiRuntime::StepELEM( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ SbxVariableRef pObjVar = PopVar();
+
+ SbxObject* pObj = PTR_CAST(SbxObject,(SbxVariable*) pObjVar);
+ if( !pObj )
+ {
+ SbxBase* pObjVarObj = pObjVar->GetObject();
+ pObj = PTR_CAST(SbxObject,pObjVarObj);
+ }
+
+ // #56368 save reference at StepElem, otherwise objects could
+ // lose their reference too early in qualification chains like
+ // ActiveComponent.Selection(0).Text
+ // #74254 now per list
+ if( pObj )
+ {
+ SaveRef( (SbxVariable*)pObj );
+ }
+ PushVar( FindElement( pObj, nOp1, nOp2, SbERR_NO_METHOD, false ) );
+}
+
+// loading a parameter (+offset+type)
+// If the data type is wrong, create a copy.
+// The data type SbxEMPTY shows that no parameters are given.
+// Get( 0 ) may be EMPTY
+
+void SbiRuntime::StepPARAM( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ sal_uInt16 i = static_cast<sal_uInt16>( nOp1 & 0x7FFF );
+ SbxDataType t = (SbxDataType) nOp2;
+ SbxVariable* p;
+
+ // #57915 solve missing in a cleaner way
+ sal_uInt16 nParamCount = refParams->Count();
+ if( i >= nParamCount )
+ {
+ sal_Int16 iLoop = i;
+ while( iLoop >= nParamCount )
+ {
+ p = new SbxVariable();
+
+ if( SbiRuntime::isVBAEnabled() &&
+ (t == SbxOBJECT || t == SbxSTRING) )
+ {
+ if( t == SbxOBJECT )
+ {
+ p->PutObject( NULL );
+ }
+ else
+ {
+ p->PutString( OUString() );
+ }
+ }
+ else
+ {
+ p->PutErr( 448 ); // like in VB: Error-Code 448 (SbERR_NAMED_NOT_FOUND)
+ }
+ refParams->Put( p, iLoop );
+ iLoop--;
+ }
+ }
+ p = refParams->Get( i );
+
+ if( p->GetType() == SbxERROR && ( i ) )
+ {
+ // if there's a parameter missing, it can be OPTIONAL
+ bool bOpt = false;
+ if( pMeth )
+ {
+ SbxInfo* pInfo = pMeth->GetInfo();
+ if ( pInfo )
+ {
+ const SbxParamInfo* pParam = pInfo->GetParam( i );
+ if( pParam && ( (pParam->nFlags & SBX_OPTIONAL) != 0 ) )
+ {
+ // Default value?
+ sal_uInt16 nDefaultId = (sal_uInt16)(pParam->nUserData & 0x0ffff);
+ if( nDefaultId > 0 )
+ {
+ OUString aDefaultStr = pImg->GetString( nDefaultId );
+ p = new SbxVariable();
+ p->PutString( aDefaultStr );
+ refParams->Put( p, i );
+ }
+ bOpt = true;
+ }
+ }
+ }
+ if( !bOpt )
+ {
+ Error( SbERR_NOT_OPTIONAL );
+ }
+ }
+ else if( t != SbxVARIANT && (SbxDataType)(p->GetType() & 0x0FFF ) != t )
+ {
+ SbxVariable* q = new SbxVariable( t );
+ SaveRef( q );
+ *q = *p;
+ p = q;
+ if ( i )
+ {
+ refParams->Put( p, i );
+ }
+ }
+ SetupArgs( p, nOp1 );
+ PushVar( CheckArray( p ) );
+}
+
+// Case-Test (+True-Target+Test-Opcode)
+
+void SbiRuntime::StepCASEIS( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ if( !refCaseStk || !refCaseStk->Count() )
+ {
+ StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
+ }
+ else
+ {
+ SbxVariableRef xComp = PopVar();
+ SbxVariableRef xCase = refCaseStk->Get( refCaseStk->Count() - 1 );
+ if( xCase->Compare( (SbxOperator) nOp2, *xComp ) )
+ {
+ StepJUMP( nOp1 );
+ }
+ }
+}
+
+// call of a DLL-procedure (+StringID+type)
+// the StringID's MSB shows that Argv is occupied
+
+void SbiRuntime::StepCALL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ OUString aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) );
+ SbxArray* pArgs = NULL;
+ if( nOp1 & 0x8000 )
+ {
+ pArgs = refArgv;
+ }
+ DllCall( aName, aLibName, pArgs, (SbxDataType) nOp2, false );
+ aLibName = OUString();
+ if( nOp1 & 0x8000 )
+ {
+ PopArgv();
+ }
+}
+
+// call of a DLL-procedure after CDecl (+StringID+type)
+
+void SbiRuntime::StepCALLC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ OUString aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) );
+ SbxArray* pArgs = NULL;
+ if( nOp1 & 0x8000 )
+ {
+ pArgs = refArgv;
+ }
+ DllCall( aName, aLibName, pArgs, (SbxDataType) nOp2, true );
+ aLibName = OUString();
+ if( nOp1 & 0x8000 )
+ {
+ PopArgv();
+ }
+}
+
+
+// beginning of a statement (+Line+Col)
+
+void SbiRuntime::StepSTMNT( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ // If the Expr-Stack at the beginning of a statement constains a variable,
+ // some fool has called X as a function, although it's a variable!
+ bool bFatalExpr = false;
+ OUString sUnknownMethodName;
+ if( nExprLvl > 1 )
+ {
+ bFatalExpr = true;
+ }
+ else if( nExprLvl )
+ {
+ SbxVariable* p = refExprStk->Get( 0 );
+ if( p->GetRefCount() > 1 &&
+ refLocals.Is() && refLocals->Find( p->GetName(), p->GetClass() ) )
+ {
+ sUnknownMethodName = p->GetName();
+ bFatalExpr = true;
+ }
+ }
+
+ ClearExprStack();
+
+ ClearRefs();
+
+ // We have to cancel hard here because line and column
+ // would be wrong later otherwise!
+ if( bFatalExpr)
+ {
+ StarBASIC::FatalError( SbERR_NO_METHOD, sUnknownMethodName );
+ return;
+ }
+ pStmnt = pCode - 9;
+ sal_uInt16 nOld = nLine;
+ nLine = static_cast<short>( nOp1 );
+
+ // #29955 & 0xFF, to filter out for-loop-level
+ nCol1 = static_cast<short>( nOp2 & 0xFF );
+
+ // find the next STMNT-command to set the final column
+ // of this statement
+
+ nCol2 = 0xffff;
+ sal_uInt16 n1, n2;
+ const sal_uInt8* p = pMod->FindNextStmnt( pCode, n1, n2 );
+ if( p )
+ {
+ if( n1 == nOp1 )
+ {
+ // #29955 & 0xFF, to filter out for-loop-level
+ nCol2 = (n2 & 0xFF) - 1;
+ }
+ }
+
+ // #29955 correct for-loop-level, #67452 NOT in the error-handler
+ if( !bInError )
+ {
+ // (there's a difference here in case of a jump out of a loop)
+ sal_uInt16 nExspectedForLevel = static_cast<sal_uInt16>( nOp2 / 0x100 );
+ if( pGosubStk )
+ {
+ nExspectedForLevel = nExspectedForLevel + pGosubStk->nStartForLvl;
+ }
+
+ // if the actual for-level is too small it'd jump out
+ // of a loop -> corrected
+ while( nForLvl > nExspectedForLevel )
+ {
+ PopFor();
+ }
+ }
+
+ // 16.10.96: #31460 new concept for StepInto/Over/Out
+ // see explanation at _ImplGetBreakCallLevel
+ if( pInst->nCallLvl <= pInst->nBreakCallLvl )
+ {
+ StarBASIC* pStepBasic = GetCurrentBasic( &rBasic );
+ sal_uInt16 nNewFlags = pStepBasic->StepPoint( nLine, nCol1, nCol2 );
+
+ pInst->CalcBreakCallLevel( nNewFlags );
+ }
+
+ // break points only at STMNT-commands in a new line!
+ else if( ( nOp1 != nOld )
+ && ( nFlags & SbDEBUG_BREAK )
+ && pMod->IsBP( static_cast<sal_uInt16>( nOp1 ) ) )
+ {
+ StarBASIC* pBreakBasic = GetCurrentBasic( &rBasic );
+ sal_uInt16 nNewFlags = pBreakBasic->BreakPoint( nLine, nCol1, nCol2 );
+
+ pInst->CalcBreakCallLevel( nNewFlags );
+ }
+}
+
+// (+SvStreamFlags+Flags)
+// Stack: block length
+// channel number
+// file name
+
+void SbiRuntime::StepOPEN( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ SbxVariableRef pName = PopVar();
+ SbxVariableRef pChan = PopVar();
+ SbxVariableRef pLen = PopVar();
+ short nBlkLen = pLen->GetInteger();
+ short nChan = pChan->GetInteger();
+ OString aName(OUStringToOString(pName->GetOUString(), osl_getThreadTextEncoding()));
+ pIosys->Open( nChan, aName, static_cast<short>( nOp1 ),
+ static_cast<short>( nOp2 ), nBlkLen );
+ Error( pIosys->GetError() );
+}
+
+// create object (+StringID+StringID)
+
+void SbiRuntime::StepCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) );
+ SbxObject *pObj = SbxBase::CreateObject( aClass );
+ if( !pObj )
+ {
+ Error( SbERR_INVALID_OBJECT );
+ }
+ else
+ {
+ OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ pObj->SetName( aName );
+ // the object must be able to call the BASIC
+ pObj->SetParent( &rBasic );
+ SbxVariable* pNew = new SbxVariable;
+ pNew->PutObject( pObj );
+ PushVar( pNew );
+ }
+}
+
+void SbiRuntime::StepDCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ StepDCREATE_IMPL( nOp1, nOp2 );
+}
+
+void SbiRuntime::StepDCREATE_REDIMP( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ StepDCREATE_IMPL( nOp1, nOp2 );
+}
+
+
+// Helper function for StepDCREATE_IMPL / bRedimp = true
+void implCopyDimArray_DCREATE( 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_DCREATE( pNewArray, pOldArray, nMaxDimIndex, nActualDim + 1,
+ pActualIndices, pLowerBounds, pUpperBounds );
+ }
+ else
+ {
+ SbxVariable* pSource = pOldArray->Get32( pActualIndices );
+ pNewArray->Put32( pSource, pActualIndices );
+ }
+ }
+}
+
+// #56204 create object array (+StringID+StringID), DCREATE == Dim-Create
+void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ SbxVariableRef refVar = PopVar();
+
+ DimImpl( refVar );
+
+ // fill the array with instances of the requested class
+ SbxBaseRef xObj = (SbxBase*)refVar->GetObject();
+ if( !xObj )
+ {
+ StarBASIC::Error( SbERR_INVALID_OBJECT );
+ return;
+ }
+
+ SbxDimArray* pArray = 0;
+ if( xObj->ISA(SbxDimArray) )
+ {
+ SbxBase* pObj = (SbxBase*)xObj;
+ pArray = (SbxDimArray*)pObj;
+
+ short nDims = pArray->GetDims();
+ sal_Int32 nTotalSize = 0;
+
+ // must be a one-dimensional array
+ sal_Int32 nLower, nUpper, nSize;
+ sal_Int32 i;
+ for( i = 0 ; i < nDims ; i++ )
+ {
+ pArray->GetDim32( i+1, nLower, nUpper );
+ nSize = nUpper - nLower + 1;
+ if( i == 0 )
+ {
+ nTotalSize = nSize;
+ }
+ else
+ {
+ nTotalSize *= nSize;
+ }
+ }
+
+ // create objects and insert them into the array
+ OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) );
+ for( i = 0 ; i < nTotalSize ; i++ )
+ {
+ SbxObject *pClassObj = SbxBase::CreateObject( aClass );
+ if( !pClassObj )
+ {
+ Error( SbERR_INVALID_OBJECT );
+ break;
+ }
+ else
+ {
+ OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ pClassObj->SetName( aName );
+ // the object must be able to call the basic
+ pClassObj->SetParent( &rBasic );
+ pArray->SbxArray::Put32( pClassObj, i );
+ }
+ }
+ }
+
+ SbxDimArray* pOldArray = (SbxDimArray*)(SbxArray*)refRedimpArray;
+ if( pArray && pOldArray )
+ {
+ short nDimsNew = pArray->GetDims();
+ short nDimsOld = pOldArray->GetDims();
+ short nDims = nDimsNew;
+ bool bRangeError = 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 = true;
+ }
+ else
+ {
+ // Compare bounds
+ for( short i = 1 ; i <= nDims ; i++ )
+ {
+ sal_Int32 lBoundNew, uBoundNew;
+ sal_Int32 lBoundOld, uBoundOld;
+ pArray->GetDim32( i, lBoundNew, uBoundNew );
+ pOldArray->GetDim32( i, lBoundOld, uBoundOld );
+
+ 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_DCREATE( pArray, pOldArray, nDims - 1,
+ 0, pActualIndices, pLowerBounds, pUpperBounds );
+ }
+ delete [] pUpperBounds;
+ delete [] pLowerBounds;
+ delete [] pActualIndices;
+ refRedimpArray = NULL;
+ }
+}
+
+// create object from user-type (+StringID+StringID)
+
+SbxObject* createUserTypeImpl( const OUString& rClassName ); // sb.cxx
+
+void SbiRuntime::StepTCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) );
+
+ SbxObject* pCopyObj = createUserTypeImpl( aClass );
+ if( pCopyObj )
+ {
+ pCopyObj->SetName( aName );
+ }
+ SbxVariable* pNew = new SbxVariable;
+ pNew->PutObject( pCopyObj );
+ pNew->SetDeclareClassName( aClass );
+ PushVar( pNew );
+}
+
+void SbiRuntime::implHandleSbxFlags( SbxVariable* pVar, SbxDataType t, sal_uInt32 nOp2 )
+{
+ bool bWithEvents = ((t & 0xff) == SbxOBJECT && (nOp2 & SBX_TYPE_WITH_EVENTS_FLAG) != 0);
+ if( bWithEvents )
+ {
+ pVar->SetFlag( SBX_WITH_EVENTS );
+ }
+ bool bDimAsNew = ((nOp2 & SBX_TYPE_DIM_AS_NEW_FLAG) != 0);
+ if( bDimAsNew )
+ {
+ pVar->SetFlag( SBX_DIM_AS_NEW );
+ }
+ bool bFixedString = ((t & 0xff) == SbxSTRING && (nOp2 & SBX_FIXED_LEN_STRING_FLAG) != 0);
+ if( bFixedString )
+ {
+ sal_uInt16 nCount = static_cast<sal_uInt16>( nOp2 >> 17 ); // len = all bits above 0x10000
+ OUStringBuffer aBuf;
+ comphelper::string::padToLength(aBuf, nCount, 0);
+ pVar->PutString(aBuf.makeStringAndClear());
+ }
+
+ bool bVarToDim = ((nOp2 & SBX_TYPE_VAR_TO_DIM_FLAG) != 0);
+ if( bVarToDim )
+ {
+ pVar->SetFlag( SBX_VAR_TO_DIM );
+ }
+}
+
+// establishing a local variable (+StringID+type)
+
+void SbiRuntime::StepLOCAL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ if( !refLocals.Is() )
+ {
+ refLocals = new SbxArray;
+ }
+ OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ if( refLocals->Find( aName, SbxCLASS_DONTCARE ) == NULL )
+ {
+ SbxDataType t = (SbxDataType)(nOp2 & 0xffff);
+ SbxVariable* p = new SbxVariable( t );
+ p->SetName( aName );
+ implHandleSbxFlags( p, t, nOp2 );
+ refLocals->Put( p, refLocals->Count() );
+ }
+}
+
+// establishing a module-global variable (+StringID+type)
+
+void SbiRuntime::StepPUBLIC_Impl( sal_uInt32 nOp1, sal_uInt32 nOp2, bool bUsedForClassModule )
+{
+ OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ SbxDataType t = (SbxDataType)(SbxDataType)(nOp2 & 0xffff);;
+ sal_Bool bFlag = pMod->IsSet( SBX_NO_MODIFY );
+ pMod->SetFlag( SBX_NO_MODIFY );
+ SbxVariableRef p = pMod->Find( aName, SbxCLASS_PROPERTY );
+ if( p.Is() )
+ {
+ pMod->Remove (p);
+ }
+ SbProperty* pProp = pMod->GetProperty( aName, t );
+ if( !bUsedForClassModule )
+ {
+ pProp->SetFlag( SBX_PRIVATE );
+ }
+ if( !bFlag )
+ {
+ pMod->ResetFlag( SBX_NO_MODIFY );
+ }
+ if( pProp )
+ {
+ pProp->SetFlag( SBX_DONTSTORE );
+ // from 2.7.1996: HACK because of 'reference can't be saved'
+ pProp->SetFlag( SBX_NO_MODIFY);
+
+ implHandleSbxFlags( pProp, t, nOp2 );
+ }
+}
+
+void SbiRuntime::StepPUBLIC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ StepPUBLIC_Impl( nOp1, nOp2, false );
+}
+
+void SbiRuntime::StepPUBLIC_P( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ // Creates module variable that isn't reinitialised when
+ // between invocations ( for VBASupport & document basic only )
+ if( pMod->pImage->bFirstInit )
+ {
+ bool bUsedForClassModule = pImg->GetFlag( SBIMG_CLASSMODULE );
+ StepPUBLIC_Impl( nOp1, nOp2, bUsedForClassModule );
+ }
+}
+
+// establishing a global variable (+StringID+type)
+
+void SbiRuntime::StepGLOBAL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ if( pImg->GetFlag( SBIMG_CLASSMODULE ) )
+ {
+ StepPUBLIC_Impl( nOp1, nOp2, true );
+ }
+ OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ SbxDataType t = (SbxDataType)(nOp2 & 0xffff);
+
+ // Store module scope variables at module scope
+ // in non vba mode these are stored at the library level :/
+ // not sure if this really should not be enabled for ALL basic
+ SbxObject* pStorage = &rBasic;
+ if ( SbiRuntime::isVBAEnabled() )
+ {
+ pStorage = pMod;
+ pMod->AddVarName( aName );
+ }
+
+ sal_Bool bFlag = pStorage->IsSet( SBX_NO_MODIFY );
+ rBasic.SetFlag( SBX_NO_MODIFY );
+ SbxVariableRef p = pStorage->Find( aName, SbxCLASS_PROPERTY );
+ if( p.Is() )
+ {
+ pStorage->Remove (p);
+ }
+ p = pStorage->Make( aName, SbxCLASS_PROPERTY, t );
+ if( !bFlag )
+ {
+ pStorage->ResetFlag( SBX_NO_MODIFY );
+ }
+ if( p )
+ {
+ p->SetFlag( SBX_DONTSTORE );
+ // from 2.7.1996: HACK because of 'reference can't be saved'
+ p->SetFlag( SBX_NO_MODIFY);
+ }
+}
+
+
+// Creates global variable that isn't reinitialised when
+// basic is restarted, P=PERSIST (+StringID+Typ)
+
+void SbiRuntime::StepGLOBAL_P( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ if( pMod->pImage->bFirstInit )
+ {
+ StepGLOBAL( nOp1, nOp2 );
+ }
+}
+
+
+// Searches for global variable, behavior depends on the fact
+// if the variable is initialised for the first time
+
+void SbiRuntime::StepFIND_G( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ if( pMod->pImage->bFirstInit )
+ {
+ // Behave like always during first init
+ StepFIND( nOp1, nOp2 );
+ }
+ else
+ {
+ // Return dummy variable
+ SbxDataType t = (SbxDataType) nOp2;
+ OUString aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) );
+
+ SbxVariable* pDummyVar = new SbxVariable( t );
+ pDummyVar->SetName( aName );
+ PushVar( pDummyVar );
+ }
+}
+
+
+SbxVariable* SbiRuntime::StepSTATIC_Impl( OUString& aName, SbxDataType& t )
+{
+ SbxVariable* p = NULL;
+ if ( pMeth )
+ {
+ SbxArray* pStatics = pMeth->GetStatics();
+ if( pStatics && ( pStatics->Find( aName, SbxCLASS_DONTCARE ) == NULL ) )
+ {
+ p = new SbxVariable( t );
+ if( t != SbxVARIANT )
+ {
+ p->SetFlag( SBX_FIXED );
+ }
+ p->SetName( aName );
+ pStatics->Put( p, pStatics->Count() );
+ }
+ }
+ return p;
+}
+// establishing a static variable (+StringID+type)
+void SbiRuntime::StepSTATIC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
+{
+ OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
+ SbxDataType t = (SbxDataType) nOp2;
+ StepSTATIC_Impl( aName, t );
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/runtime/step0.cxx b/basic/source/runtime/step0.cxx
deleted file mode 100644
index 37e21162c353..000000000000
--- a/basic/source/runtime/step0.cxx
+++ /dev/null
@@ -1,1540 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * 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 .
- */
-
-#include <comphelper/string.hxx>
-#include <vcl/msgbox.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.hpp>
-#include <rtl/instance.hxx>
-#include <vcl/svapp.hxx>
-#include <unotools/textsearch.hxx>
-
-Reference< XInterface > createComListener( const Any& aControlAny, const OUString& aVBAType,
- const OUString& aPrefix, SbxObjectRef xScopeObj );
-
-#include <algorithm>
-#include <boost/unordered_map.hpp>
-
-// for a patch forward declaring these methods below makes sense
-// but, #FIXME lets really just move the methods to the top
-static void lcl_clearImpl( SbxVariableRef& refVar, SbxDataType& eType );
-static void lcl_eraseImpl( SbxVariableRef& refVar, bool bVBAEnabled );
-
-SbxVariable* getDefaultProp( SbxVariable* pRef );
-
-void SbiRuntime::StepNOP()
-{}
-
-void SbiRuntime::StepArith( SbxOperator eOp )
-{
- SbxVariableRef p1 = PopVar();
- TOSMakeTemp();
- SbxVariable* p2 = GetTOS();
-
- 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 == SbxEMPTY )
- {
- p1->Broadcast( SBX_HINT_DATAWANTED );
- p1Type = p1->GetType();
- }
- if ( p2Type == SbxEMPTY )
- {
- p2->Broadcast( SBX_HINT_DATAWANTED );
- p2Type = p2->GetType();
- }
- if ( p1Type == p2Type )
- {
- // 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 )
- 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;
- static SbxVariable* pNULL = NULL;
- // why do this on non-windows ?
- // why do this at all ?
- // I dumbly follow the pattern :-/
- if ( bVBAEnabled && ( p1->IsNull() || p2->IsNull() ) )
- {
- if( !pNULL )
- {
- pNULL = new SbxVariable;
- pNULL->PutNull();
- pNULL->AddRef();
- }
- PushVar( pNULL );
- }
- else 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)
- {
- if((cCode & 0xFF80))
- {
- return false;
- }
- switch((sal_uInt8)(cCode & 0x07F))
- {
- case '.':
- case '^':
- case '$':
- case '+':
- case '\\':
- case '|':
- case '{':
- case '}':
- case '(':
- case ')':
- return true;
- default:
- return false;
- }
- }
-
- OUString VBALikeToRegexp(const OUString &rIn)
- {
- OUStringBuffer sResult;
- const sal_Unicode *start = rIn.getStr();
- const sal_Unicode *end = start + rIn.getLength();
-
- int seenright = 0;
-
- sResult.append('^');
-
- while (start < end)
- {
- switch (*start)
- {
- case '?':
- sResult.append('.');
- start++;
- break;
- case '*':
- sResult.append(".*");
- start++;
- break;
- case '#':
- sResult.append("[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.makeStringAndClear();
- }
-}
-
-void SbiRuntime::StepLIKE()
-{
- SbxVariableRef refVar1 = PopVar();
- SbxVariableRef refVar2 = PopVar();
-
- OUString pattern = VBALikeToRegexp(refVar1->GetOUString());
- OUString value = refVar2->GetOUString();
-
- com::sun::star::util::SearchOptions aSearchOpt;
-
- aSearchOpt.algorithmType = com::sun::star::util::SearchAlgorithms_REGEXP;
-
- aSearchOpt.Locale = Application::GetSettings().GetLanguageTag().getLocale();
- aSearchOpt.searchString = pattern;
-
- int bTextMode(1);
- bool bCompatibility = ( GetSbData()->pInst && GetSbData()->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);
- sal_uInt16 nStart=0, nEnd=value.getLength();
- int bRes = aSearch.SearchFrwrd(value, &nStart, &nEnd);
- pRes->PutBool( bRes != 0 );
-
- PushVar( pRes );
-}
-
-// TOS and TOS-1 are both object variables and contain the same 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 );
-}
-
-// update the value of TOS
-
-void SbiRuntime::StepGET()
-{
- SbxVariable* p = GetTOS();
- p->Broadcast( SBX_HINT_DATAWANTED );
-}
-
-// #67607 copy Uno-Structs
-inline bool checkUnoStructCopy( bool bVBA, SbxVariableRef& refVal, SbxVariableRef& refVar )
-{
- SbxDataType eVarType = refVar->GetType();
- SbxDataType eValType = refVal->GetType();
-
- if ( !( !bVBA|| ( bVBA && refVar->GetType() != SbxEMPTY ) ) || !refVar->CanWrite() )
- return false;
-
- if ( eValType != SbxOBJECT )
- return false;
- // we seem to be duplicating parts of SbxValue=operator, maybe we should just move this to
- // there :-/ not sure if for every '=' we would want struct handling
- if( eVarType != SbxOBJECT )
- {
- if ( refVar->IsFixed() )
- return false;
- }
- // #115826: Exclude ProcedureProperties to avoid call to Property Get procedure
- else if( refVar->ISA(SbProcedureProperty) )
- return false;
-
- SbxObjectRef xValObj = (SbxObject*)refVal->GetObject();
- if( !xValObj.Is() || xValObj->ISA(SbUnoAnyObject) )
- return false;
-
- SbUnoObject* pUnoVal = PTR_CAST(SbUnoObject,(SbxObject*)xValObj);
- SbUnoStructRefObject* pUnoStructVal = PTR_CAST(SbUnoStructRefObject,(SbxObject*)xValObj);
- Any aAny;
- // make doubly sure value is either an Uno object or
- // an uno struct
- if ( pUnoVal || pUnoStructVal )
- aAny = pUnoVal ? pUnoVal->getUnoAny() : pUnoStructVal->getUnoAny();
- else
- return false;
- if ( aAny.getValueType().getTypeClass() == TypeClass_STRUCT )
- {
- refVar->SetType( SbxOBJECT );
- SbxError eOldErr = refVar->GetError();
- // There are some circumstances when calling GetObject
- // will trigger an error, we need to squash those here.
- // Alternatively it is possible that the same scenario
- // could overwrite and existing error. Lets prevent that
- SbxObjectRef xVarObj = (SbxObject*)refVar->GetObject();
- if ( eOldErr != SbxERR_OK )
- refVar->SetError( eOldErr );
- else
- refVar->ResetError();
-
- SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,(SbxObject*)xVarObj);
-
- OUString sClassName = pUnoVal ? pUnoVal->GetClassName() : pUnoStructVal->GetClassName();
- OUString sName = pUnoVal ? pUnoVal->GetName() : pUnoStructVal->GetName();
-
- if ( pUnoStructObj )
- {
- StructRefInfo aInfo = pUnoStructObj->getStructInfo();
- aInfo.setValue( aAny );
- }
- else
- {
- SbUnoObject* pNewUnoObj = new SbUnoObject( sName, aAny );
- // #70324: adopt ClassName
- pNewUnoObj->SetClassName( sClassName );
- refVar->PutObject( pNewUnoObj );
- }
- return true;
- }
- return false;
-}
-
-
-// laying down TOS in TOS-1
-
-void SbiRuntime::StepPUT()
-{
- SbxVariableRef refVal = PopVar();
- SbxVariableRef refVar = PopVar();
- // store on its own method (inside a function)?
- bool bFlagsChanged = false;
- sal_uInt16 n = 0;
- if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
- {
- bFlagsChanged = 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 )
- {
- // yet more hacking at this, I feel we don't quite have the correct
- // heuristics for dealing with obj1 = obj2 ( where obj2 ( and maybe
- // obj1 ) has default member/property ) ) It seems that default props
- // aren't dealt with if the object is a member of some parent object
- bool bObjAssign = false;
- if ( refVar->GetType() == SbxEMPTY )
- refVar->Broadcast( SBX_HINT_DATAWANTED );
- if ( refVar->GetType() == SbxOBJECT )
- {
- if ( refVar->IsA( TYPE(SbxMethod) ) || ! refVar->GetParent() )
- {
- SbxVariable* pDflt = getDefaultProp( refVar );
-
- if ( pDflt )
- refVar = pDflt;
- }
- else
- bObjAssign = true;
- }
- if ( refVal->GetType() == SbxOBJECT && !bObjAssign && ( refVal->IsA( TYPE(SbxMethod) ) || ! refVal->GetParent() ) )
- {
- SbxVariable* pDflt = getDefaultProp( refVal );
- if ( pDflt )
- refVal = pDflt;
- }
- }
-
- if ( !checkUnoStructCopy( bVBAEnabled, refVal, refVar ) )
- *refVar = *refVal;
-
- if( bFlagsChanged )
- refVar->SetFlags( n );
-}
-
-
-// VBA Dim As New behavior handling, save init object information
-struct DimAsNewRecoverItem
-{
- OUString m_aObjClass;
- OUString m_aObjName;
- SbxObject* m_pObjParent;
- SbModule* m_pClassModule;
-
- DimAsNewRecoverItem( void )
- : m_pObjParent( NULL )
- , m_pClassModule( NULL )
- {}
-
- DimAsNewRecoverItem( const OUString& rObjClass, const OUString& 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 boost::unordered_map< SbxVariable*, DimAsNewRecoverItem,
- SbxVariablePtrHash > DimAsNewRecoverHash;
-
-class GaDimAsNewRecoverHash : public rtl::Static<DimAsNewRecoverHash, GaDimAsNewRecoverHash> {};
-
-void removeDimAsNewRecoverItem( SbxVariable* pVar )
-{
- DimAsNewRecoverHash &rDimAsNewRecoverHash = GaDimAsNewRecoverHash::get();
- DimAsNewRecoverHash::iterator it = rDimAsNewRecoverHash.find( pVar );
- if( it != rDimAsNewRecoverHash.end() )
- {
- rDimAsNewRecoverHash.erase( it );
- }
-}
-
-
-// saving object variable
-// not-object variables will cause errors
-
-static const char pCollectionStr[] = "Collection";
-
-void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, bool bHandleDefaultProp )
-{
- // #67733 types with array-flag are OK too
-
- // 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();
- 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 ) )
- {
- // activate GetOject for collections on refVal
- SbxBase* pObjVarObj = refVal->GetObject();
- if( pObjVarObj )
- {
- SbxVariableRef refObjVal = PTR_CAST(SbxObject,pObjVarObj);
-
- if( refObjVal )
- {
- refVal = refObjVal;
- }
- else if( !(eValType & SbxARRAY) )
- {
- refVal = NULL;
- }
- }
- }
-
- // #52896 refVal can be invalid here, if uno-sequences - or more
- // general arrays - are assigned to variables that are declared
- // as an object!
- if( !refVal )
- {
- Error( SbERR_INVALID_USAGE_OBJECT );
- }
- else
- {
- bool bFlagsChanged = false;
- sal_uInt16 n = 0;
- if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
- {
- bFlagsChanged = 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
- // LHS try determine if a default prop exists
- // again like in StepPUT (see there too ) we are tweaking the
- // heursitics again for when to assign an object reference or
- // use default memebers if they exists
- // #FIXME we really need to get to the bottom of this mess
- bool bObjAssign = false;
- if ( refVar->GetType() == SbxOBJECT )
- {
- if ( refVar->IsA( TYPE(SbxMethod) ) || ! refVar->GetParent() )
- {
- SbxVariable* pDflt = getDefaultProp( refVar );
- if ( pDflt )
- {
- refVar = pDflt;
- }
- }
- else
- bObjAssign = 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 && !bObjAssign )
- {
- // lhs is either a valid object || or has a defaultProp
- pDflt = getDefaultProp( refVal );
- }
- if ( pDflt )
- {
- refVal = pDflt;
- }
- }
- }
-
- // Handle Dim As New
- 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();
- OUString aDeclareClassName = refVar->GetDeclareClassName();
- OUString aVBAType = aDeclareClassName;
- OUString aPrefix = refVar->GetName();
- SbxObjectRef xScopeObj = refVar->GetParent();
- xComListener = createComListener( aControlAny, aVBAType, aPrefix, xScopeObj );
-
- refVal->SetDeclareClassName( aDeclareClassName );
- refVal->SetComListener( xComListener, &rBasic ); // Hold reference
- }
-
- }
-
- // 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 ( !checkUnoStructCopy( bHandleDefaultProp, refVal, refVar ) )
- {
- *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 &rDimAsNewRecoverHash = GaDimAsNewRecoverHash::get();
- DimAsNewRecoverHash::iterator it = rDimAsNewRecoverHash.find( refVar );
- if( it != rDimAsNewRecoverHash.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.equalsIgnoreAsciiCaseAscii( pCollectionStr ) )
- {
- BasicCollection* pNewCollection = new BasicCollection( OUString(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 )
- {
- OUString aObjClass = pValObj->GetClassName();
-
- SbClassModuleObject* pClassModuleObj = PTR_CAST(SbClassModuleObject,pValObjBase);
- DimAsNewRecoverHash &rDimAsNewRecoverHash = GaDimAsNewRecoverHash::get();
- if( pClassModuleObj != NULL )
- {
- SbModule* pClassModule = pClassModuleObj->getClassModule();
- rDimAsNewRecoverHash[refVar] =
- DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), pClassModule );
- }
- else if( aObjClass.equalsIgnoreAsciiCase( "Collection" ) )
- {
- rDimAsNewRecoverHash[refVar] =
- DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), NULL );
- }
- }
- }
- }
- }
- }
-
- 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
-}
-
-
-void SbiRuntime::StepLSET()
-{
- SbxVariableRef refVal = PopVar();
- SbxVariableRef refVar = PopVar();
- if( refVar->GetType() != SbxSTRING ||
- refVal->GetType() != SbxSTRING )
- {
- Error( SbERR_INVALID_USAGE_OBJECT );
- }
- else
- {
- sal_uInt16 n = refVar->GetFlags();
- if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
- {
- refVar->SetFlag( SBX_WRITE );
- }
- OUString aRefVarString = refVar->GetOUString();
- OUString aRefValString = refVal->GetOUString();
-
- sal_Int32 nVarStrLen = aRefVarString.getLength();
- sal_Int32 nValStrLen = aRefValString.getLength();
- OUStringBuffer aNewStr;
- if( nVarStrLen > nValStrLen )
- {
- aNewStr.append(aRefValString);
- comphelper::string::padToLength(aNewStr, nVarStrLen, ' ');
- }
- else
- {
- aNewStr = aRefValString.copy( 0, nVarStrLen );
- }
-
- refVar->PutString(aNewStr.makeStringAndClear());
- refVar->SetFlags( n );
- }
-}
-
-void SbiRuntime::StepRSET()
-{
- SbxVariableRef refVal = PopVar();
- SbxVariableRef refVar = PopVar();
- if( refVar->GetType() != SbxSTRING || refVal->GetType() != SbxSTRING )
- {
- Error( SbERR_INVALID_USAGE_OBJECT );
- }
- else
- {
- sal_uInt16 n = refVar->GetFlags();
- if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
- {
- refVar->SetFlag( SBX_WRITE );
- }
- OUString aRefVarString = refVar->GetOUString();
- OUString aRefValString = refVal->GetOUString();
- sal_Int32 nVarStrLen = aRefVarString.getLength();
- sal_Int32 nValStrLen = aRefValString.getLength();
-
- OUStringBuffer aNewStr(nVarStrLen);
- if (nVarStrLen > nValStrLen)
- {
- comphelper::string::padToLength(aNewStr, nVarStrLen - nValStrLen, ' ');
- aNewStr.append(aRefValString);
- }
- else
- {
- aNewStr.append(aRefValString.copy(0, nVarStrLen));
- }
- refVar->PutString(aNewStr.makeStringAndClear());
-
- refVar->SetFlags( n );
- }
-}
-
-// laying down TOS in TOS-1, then set ReadOnly-Bit
-
-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 for the array with dimension information as parameter
-
-void SbiRuntime::StepDIM()
-{
- SbxVariableRef refVar = PopVar();
- DimImpl( refVar );
-}
-
-// #56204 swap out DIM-functionality into a help method (step0.cxx)
-void SbiRuntime::DimImpl( SbxVariableRef refVar )
-{
- // If refDim then this DIM statement is terminating a ReDIM and
- // previous StepERASE_CLEAR for an array, the following actions have
- // been delayed from ( StepERASE_CLEAR ) 'till here
- if ( refRedim )
- {
- if ( !refRedimpArray ) // only erase the array not ReDim Preserve
- {
- lcl_eraseImpl( refVar, bVBAEnabled );
- }
- SbxDataType eType = refVar->GetType();
- lcl_clearImpl( refVar, eType );
- refRedim = NULL;
- }
- SbxArray* pDims = refVar->GetParameters();
- // must have an even number of arguments
- // have in mind that Arg[0] does not count!
- if( pDims && !( pDims->Count() & 1 ) )
- {
- StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
- }
- else
- {
- SbxDataType eType = refVar->IsFixed() ? refVar->GetType() : SbxVARIANT;
- SbxDimArray* pArray = new SbxDimArray( eType );
- // allow arrays without dimension information, too (VB-compatible)
- 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 On creating an array of the length 0, create
- // a dimension (like for Uno-Sequences of the length 0)
- 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 for the array
-// argv = dimension information
-
-void SbiRuntime::StepREDIM()
-{
- // Nothing different than dim at the moment because
- // a double dim is already recognized by the compiler.
- 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 for the array
-// argv = dimension information
-
-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;
-
- if( nDimsOld != nDimsNew )
- {
- StarBASIC::Error( SbERR_OUT_OF_RANGE );
- }
- else
- {
- // 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];
-
- // 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 );
- lBoundNew = std::max( lBoundNew, lBoundOld );
- uBoundNew = std::min( uBoundNew, uBoundOld );
- short j = i - 1;
- pActualIndices[j] = pLowerBounds[j] = lBoundNew;
- pUpperBounds[j] = uBoundNew;
- }
- // 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;
- }
- }
-
-}
-
-// REDIM_COPY
-// TOS = Array-Variable, Reference to array is copied
-// Variable is cleared as in ERASE
-
-void SbiRuntime::StepREDIMP_ERASE()
-{
- SbxVariableRef refVar = PopVar();
- refRedim = refVar;
- SbxDataType eType = refVar->GetType();
- if( eType & SbxARRAY )
- {
- SbxBase* pElemObj = refVar->GetObject();
- SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
- if( pDimArray )
- {
- refRedimpArray = pDimArray;
- }
-
- }
- else if( refVar->IsFixed() )
- {
- refVar->Clear();
- }
- else
- {
- refVar->SetType( SbxEMPTY );
- }
-}
-
-static 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();
-}
-
-static 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
- {
- // Arrays have on an erase to VB quite a complex behaviour. Here are
- // only the type problems at REDIM (#26295) removed at first:
- // Set type hard onto the array-type, because a variable with array is
- // SbxOBJECT. At REDIM there's an SbxOBJECT-array generated then and
- // the original type is lost -> runtime error
- lcl_clearImpl( refVar, eType );
- }
- }
- else if( refVar->IsFixed() )
- {
- refVar->Clear();
- }
- else
- {
- refVar->SetType( SbxEMPTY );
- }
-}
-
-// delete variable
-// TOS = variable
-
-void SbiRuntime::StepERASE()
-{
- SbxVariableRef refVar = PopVar();
- lcl_eraseImpl( refVar, bVBAEnabled );
-}
-
-void SbiRuntime::StepERASE_CLEAR()
-{
- refRedim = PopVar();
-}
-
-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 );
-}
-
-// establishing an argv
-// nOp1 stays as it is -> 1st element is the return value
-
-void SbiRuntime::StepARGC()
-{
- PushArgv();
- refArgv = new SbxArray;
- nArgc = 1;
-}
-
-// storing an argument 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(SbUnoProperty) || pVal->ISA(SbProcedureProperty) )
- {
- // evaluate methods and properties!
- SbxVariable* pRes = new SbxVariable( *pVal );
- pVal = pRes;
- }
- refArgv->Put( pVal, nArgc++ );
- }
-}
-
-// Input to Variable. The variable is on TOS and is
-// is removed afterwards.
-void SbiRuntime::StepINPUT()
-{
- OUStringBuffer sin;
- OUString 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;
- }
- sin.append( 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 )
- {
- s = sin.makeStringAndClear();
- SbxVariableRef pVar = GetTOS();
- // try to fill the variable with a numeric value first,
- // then with a string value
- if( !pVar->IsFixed() || pVar->IsNumeric() )
- {
- sal_uInt16 nLen = 0;
- if( !pVar->Scan( s, &nLen ) )
- {
- err = SbxBase::GetError();
- SbxBase::ResetError();
- }
- // the value has to be scanned in completely
- else if( nLen != s.getLength() && !pVar->PutString( s ) )
- {
- err = SbxBase::GetError();
- SbxBase::ResetError();
- }
- else if( nLen != s.getLength() && 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() )
- {
- pCode = pRestart;
- }
- else
- {
- Error( err );
- }
- }
- else
- {
- PopVar();
- }
-}
-
-// Line Input to Variable. The variable is on TOS and is
-// deleted afterwards.
-
-void SbiRuntime::StepLINPUT()
-{
- OString aInput;
- pIosys->Read( aInput );
- Error( pIosys->GetError() );
- SbxVariableRef p = PopVar();
- p->PutString(OStringToOUString(aInput, osl_getThreadTextEncoding()));
-}
-
-// end of program
-
-void SbiRuntime::StepSTOP()
-{
- pInst->Stop();
-}
-
-
-void SbiRuntime::StepINITFOR()
-{
- PushFor();
-}
-
-void SbiRuntime::StepINITFOREACH()
-{
- PushForEach();
-}
-
-// increment FOR-variable
-
-void SbiRuntime::StepNEXT()
-{
- if( !pForStk )
- {
- StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
- return;
- }
- if( pForStk->eForType == FOR_TO )
- {
- pForStk->refVar->Compute( SbxPLUS, *pForStk->refInc );
- }
-}
-
-// beginning CASE: TOS in CASE-stack
-
-void SbiRuntime::StepCASE()
-{
- if( !refCaseStk.Is() )
- {
- refCaseStk = new SbxArray;
- }
- SbxVariableRef xVar = PopVar();
- refCaseStk->Put( xVar, refCaseStk->Count() );
-}
-
-// end CASE: free variable
-
-void SbiRuntime::StepENDCASE()
-{
- if( !refCaseStk || !refCaseStk->Count() )
- {
- StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
- }
- else
- {
- refCaseStk->Remove( refCaseStk->Count() - 1 );
- }
-}
-
-
-void SbiRuntime::StepSTDERROR()
-{
- pError = NULL; bError = true;
- pInst->aErrorMsg = OUString();
- pInst->nErr = 0L;
- pInst->nErl = 0;
- nError = 0L;
- SbxErrObject::getUnoErrObject()->Clear();
-}
-
-void SbiRuntime::StepNOERROR()
-{
- pInst->aErrorMsg = OUString();
- pInst->nErr = 0L;
- pInst->nErl = 0;
- nError = 0L;
- SbxErrObject::getUnoErrObject()->Clear();
- bError = false;
-}
-
-// leave UP
-
-void SbiRuntime::StepLEAVE()
-{
- bRun = 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 = channel number
-{
- 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();
- OUString s1 = p->GetOUString();
- OUString s;
- if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
- {
- s = " "; // one blank before
- }
- s += s1;
- OString aByteStr(OUStringToOString(s, osl_getThreadTextEncoding()));
- pIosys->Write( aByteStr );
- Error( pIosys->GetError() );
-}
-
-void SbiRuntime::StepPRINTF() // print TOS in field
-{
- SbxVariableRef p = PopVar();
- OUString s1 = p->GetOUString();
- OUStringBuffer s;
- if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
- {
- s.append(' ');
- }
- s.append(s1);
- comphelper::string::padToLength(s, 14, ' ');
- OString aByteStr(OUStringToOString(s.makeStringAndClear(), osl_getThreadTextEncoding()));
- pIosys->Write( aByteStr );
- Error( pIosys->GetError() );
-}
-
-void SbiRuntime::StepWRITE() // write TOS
-{
- SbxVariableRef p = PopVar();
- // Does the string have to be encapsulated?
- char ch = 0;
- switch (p->GetType() )
- {
- case SbxSTRING: ch = '"'; break;
- case SbxCURRENCY:
- case SbxBOOL:
- case SbxDATE: ch = '#'; break;
- default: break;
- }
- OUString s;
- if( ch )
- {
- s += OUString(ch);
- }
- s += p->GetOUString();
- if( ch )
- {
- s += OUString(ch);
- }
- OString aByteStr(OUStringToOString(s, osl_getThreadTextEncoding()));
- pIosys->Write( aByteStr );
- Error( pIosys->GetError() );
-}
-
-void SbiRuntime::StepRENAME() // Rename Tos+1 to Tos
-{
- SbxVariableRef pTos1 = PopVar();
- SbxVariableRef pTos = PopVar();
- OUString aDest = pTos1->GetOUString();
- OUString aSource = pTos->GetOUString();
-
- if( hasUno() )
- {
- implStepRenameUCB( aSource, aDest );
- }
- else
- {
- implStepRenameOSL( aSource, aDest );
- }
-}
-
-// TOS = Prompt
-
-void SbiRuntime::StepPROMPT()
-{
- SbxVariableRef p = PopVar();
- OString aStr(OUStringToOString(p->GetOUString(), osl_getThreadTextEncoding()));
- pIosys->SetPrompt( aStr );
-}
-
-// Set Restart point
-
-void SbiRuntime::StepRESTART()
-{
- pRestart = pCode;
-}
-
-// empty expression on stack for missing parameter
-
-void SbiRuntime::StepEMPTY()
-{
- // #57915 The semantics of StepEMPTY() is the representation of a missing argument.
- // This is represented by the value 448 (SbERR_NAMED_NOT_FOUND) of the type error
- // in VB. StepEmpty should now rather be named StepMISSING() but the name is kept
- // to simplify matters.
- SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
- xVar->PutErr( 448 );
- PushVar( xVar );
-}
-
-// TOS = error code
-
-void SbiRuntime::StepERROR()
-{
- SbxVariableRef refCode = PopVar();
- sal_uInt16 n = refCode->GetUShort();
- SbError error = StarBASIC::GetSfxFromVBError( n );
- if ( bVBAEnabled )
- {
- pInst->Error( error );
- }
- else
- {
- Error( error );
- }
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/runtime/step1.cxx b/basic/source/runtime/step1.cxx
deleted file mode 100644
index 7b721294df5b..000000000000
--- a/basic/source/runtime/step1.cxx
+++ /dev/null
@@ -1,582 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * 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 .
- */
-
-
-#include <stdlib.h>
-#include <comphelper/string.hxx>
-#include <rtl/math.hxx>
-#include <rtl/ustrbuf.hxx>
-#include <basic/sbuno.hxx>
-#include "runtime.hxx"
-#include "sbintern.hxx"
-#include "iosys.hxx"
-#include "image.hxx"
-#include "sbunoobj.hxx"
-#include "errobject.hxx"
-
-bool checkUnoObjectType( SbUnoObject* refVal, const OUString& aClass );
-
-// loading a numeric constant (+ID)
-
-void SbiRuntime::StepLOADNC( sal_uInt32 nOp1 )
-{
- SbxVariable* p = new SbxVariable( SbxDOUBLE );
-
- // #57844 use localized function
- OUString aStr = pImg->GetString( static_cast<short>( nOp1 ) );
- // also allow , !!!
- sal_Int32 iComma = aStr.indexOf((sal_Unicode)',');
- if( iComma >= 0 )
- {
- aStr = aStr.replaceAt(iComma, 1, OUString("."));
- }
- double n = ::rtl::math::stringToDouble( aStr, '.', ',', NULL, NULL );
-
- p->PutDouble( n );
- PushVar( p );
-}
-
-// loading a string constant (+ID)
-
-void SbiRuntime::StepLOADSC( sal_uInt32 nOp1 )
-{
- SbxVariable* p = new SbxVariable;
- p->PutString( pImg->GetString( static_cast<short>( nOp1 ) ) );
- PushVar( p );
-}
-
-// Immediate Load (+Wert)
-
-void SbiRuntime::StepLOADI( sal_uInt32 nOp1 )
-{
- SbxVariable* p = new SbxVariable;
- p->PutInteger( static_cast<sal_Int16>( nOp1 ) );
- PushVar( p );
-}
-
-// stora a named argument in Argv (+Arg-no. from 1!)
-
-void SbiRuntime::StepARGN( sal_uInt32 nOp1 )
-{
- if( !refArgv )
- StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
- else
- {
- OUString aAlias( pImg->GetString( static_cast<short>( nOp1 ) ) );
- SbxVariableRef pVal = PopVar();
- if( bVBAEnabled && ( pVal->ISA(SbxMethod) || pVal->ISA(SbUnoProperty) || pVal->ISA(SbProcedureProperty) ) )
- {
- // named variables ( that are Any especially properties ) can be empty at this point and need a broadcast
- if ( pVal->GetType() == SbxEMPTY )
- pVal->Broadcast( SBX_HINT_DATAWANTED );
- // evaluate methods and properties!
- SbxVariable* pRes = new SbxVariable( *pVal );
- pVal = pRes;
- }
- refArgv->Put( pVal, nArgc );
- refArgv->PutAlias( aAlias, nArgc++ );
- }
-}
-
-// converting the type of an argument in Argv for DECLARE-Fkt. (+type)
-
-void SbiRuntime::StepARGTYP( sal_uInt32 nOp1 )
-{
- if( !refArgv )
- StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
- else
- {
- bool bByVal = (nOp1 & 0x8000) != 0; // Ist BYVAL requested?
- SbxDataType t = (SbxDataType) (nOp1 & 0x7FFF);
- SbxVariable* pVar = refArgv->Get( refArgv->Count() - 1 ); // last Arg
-
- // check BYVAL
- if( pVar->GetRefCount() > 2 ) // 2 is normal for BYVAL
- {
- // parameter is a reference
- if( bByVal )
- {
- // Call by Value is requested -> create a copy
- pVar = new SbxVariable( *pVar );
- pVar->SetFlag( SBX_READWRITE );
- refExprStk->Put( pVar, refArgv->Count() - 1 );
- }
- else
- pVar->SetFlag( SBX_REFERENCE ); // Ref-Flag for DllMgr
- }
- else
- {
- // parameter is NO reference
- if( bByVal )
- pVar->ResetFlag( SBX_REFERENCE ); // no reference -> OK
- else
- Error( SbERR_BAD_PARAMETERS ); // reference needed
- }
-
- if( pVar->GetType() != t )
- {
- // variant for correct conversion
- // besides error, if SbxBYREF
- pVar->Convert( SbxVARIANT );
- pVar->Convert( t );
- }
- }
-}
-
-// bring string to a definite length (+length)
-
-void SbiRuntime::StepPAD( sal_uInt32 nOp1 )
-{
- SbxVariable* p = GetTOS();
- OUString s = p->GetOUString();
- sal_Int32 nLen(nOp1);
- if( s.getLength() != nLen )
- {
- OUStringBuffer aBuf(s);
- if (aBuf.getLength() > nLen)
- {
- comphelper::string::truncateToLength(aBuf, nLen);
- }
- else
- {
- comphelper::string::padToLength(aBuf, nLen, ' ');
- }
- s = aBuf.makeStringAndClear();
- }
-}
-
-// jump (+target)
-
-void SbiRuntime::StepJUMP( sal_uInt32 nOp1 )
-{
-#ifdef DBG_UTIL
- // #QUESTION shouln't this be
- // if( (sal_uInt8*)( nOp1+pImagGetCode() ) >= pImg->GetCodeSize() )
- if( nOp1 >= pImg->GetCodeSize() )
- StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
-#endif
- pCode = (const sal_uInt8*) pImg->GetCode() + nOp1;
-}
-
-// evaluate TOS, conditional jump (+target)
-
-void SbiRuntime::StepJUMPT( sal_uInt32 nOp1 )
-{
- SbxVariableRef p = PopVar();
- if( p->GetBool() )
- StepJUMP( nOp1 );
-}
-
-// evaluate TOS, conditional jump (+target)
-
-void SbiRuntime::StepJUMPF( sal_uInt32 nOp1 )
-{
- SbxVariableRef p = PopVar();
- // In a test e.g. If Null then
- // will evaluate Null will act as if False
- if( ( bVBAEnabled && p->IsNull() ) || !p->GetBool() )
- StepJUMP( nOp1 );
-}
-
-// evaluate TOS, jump into JUMP-table (+MaxVal)
-// looks like this:
-// ONJUMP 2
-// JUMP target1
-// JUMP target2
-// ...
-// if 0x8000 is set in the operand, push the return address (ON..GOSUB)
-
-void SbiRuntime::StepONJUMP( sal_uInt32 nOp1 )
-{
- SbxVariableRef p = PopVar();
- sal_Int16 n = p->GetInteger();
- if( nOp1 & 0x8000 )
- {
- nOp1 &= 0x7FFF;
- PushGosub( pCode + 5 * nOp1 );
- }
- if( n < 1 || static_cast<sal_uInt32>(n) > nOp1 )
- n = static_cast<sal_Int16>( nOp1 + 1 );
- nOp1 = (sal_uInt32) ( (const char*) pCode - pImg->GetCode() ) + 5 * --n;
- StepJUMP( nOp1 );
-}
-
-// UP-call (+target)
-
-void SbiRuntime::StepGOSUB( sal_uInt32 nOp1 )
-{
- PushGosub( pCode );
- if( nOp1 >= pImg->GetCodeSize() )
- StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
- pCode = (const sal_uInt8*) pImg->GetCode() + nOp1;
-}
-
-// UP-return (+0 or target)
-
-void SbiRuntime::StepRETURN( sal_uInt32 nOp1 )
-{
- PopGosub();
- if( nOp1 )
- StepJUMP( nOp1 );
-}
-
-// check FOR-variable (+Endlabel)
-
-void SbiRuntime::StepTESTFOR( sal_uInt32 nOp1 )
-{
- if( !pForStk )
- {
- StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
- return;
- }
-
- bool bEndLoop = false;
- switch( pForStk->eForType )
- {
- case FOR_TO:
- {
- SbxOperator eOp = ( pForStk->refInc->GetDouble() < 0 ) ? SbxLT : SbxGT;
- if( pForStk->refVar->Compare( eOp, *pForStk->refEnd ) )
- bEndLoop = true;
- break;
- }
- case FOR_EACH_ARRAY:
- {
- SbiForStack* p = pForStk;
- if( p->pArrayCurIndices == NULL )
- {
- bEndLoop = true;
- }
- else
- {
- SbxDimArray* pArray = (SbxDimArray*)(SbxVariable*)p->refEnd;
- short nDims = pArray->GetDims();
-
- // Empty array?
- if( nDims == 1 && p->pArrayLowerBounds[0] > p->pArrayUpperBounds[0] )
- {
- bEndLoop = true;
- break;
- }
- SbxVariable* pVal = pArray->Get32( p->pArrayCurIndices );
- *(p->refVar) = *pVal;
-
- bool bFoundNext = false;
- for( short i = 0 ; i < nDims ; i++ )
- {
- if( p->pArrayCurIndices[i] < p->pArrayUpperBounds[i] )
- {
- bFoundNext = true;
- p->pArrayCurIndices[i]++;
- for( short j = i - 1 ; j >= 0 ; j-- )
- p->pArrayCurIndices[j] = p->pArrayLowerBounds[j];
- break;
- }
- }
- if( !bFoundNext )
- {
- delete[] p->pArrayCurIndices;
- p->pArrayCurIndices = NULL;
- }
- }
- break;
- }
- case FOR_EACH_COLLECTION:
- {
- BasicCollection* pCollection = (BasicCollection*)(SbxVariable*)pForStk->refEnd;
- SbxArrayRef xItemArray = pCollection->xItemArray;
- sal_Int32 nCount = xItemArray->Count32();
- if( pForStk->nCurCollectionIndex < nCount )
- {
- SbxVariable* pRes = xItemArray->Get32( pForStk->nCurCollectionIndex );
- pForStk->nCurCollectionIndex++;
- (*pForStk->refVar) = *pRes;
- }
- else
- {
- bEndLoop = true;
- }
- break;
- }
- case FOR_EACH_XENUMERATION:
- {
- SbiForStack* p = pForStk;
- if( p->xEnumeration->hasMoreElements() )
- {
- Any aElem = p->xEnumeration->nextElement();
- SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
- unoToSbxValue( (SbxVariable*)xVar, aElem );
- (*pForStk->refVar) = *xVar;
- }
- else
- {
- bEndLoop = true;
- }
- break;
- }
- }
- if( bEndLoop )
- {
- PopFor();
- StepJUMP( nOp1 );
- }
-}
-
-// Tos+1 <= Tos+2 <= Tos, 2xremove (+Target)
-
-void SbiRuntime::StepCASETO( sal_uInt32 nOp1 )
-{
- if( !refCaseStk || !refCaseStk->Count() )
- StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
- else
- {
- SbxVariableRef xTo = PopVar();
- SbxVariableRef xFrom = PopVar();
- SbxVariableRef xCase = refCaseStk->Get( refCaseStk->Count() - 1 );
- if( *xCase >= *xFrom && *xCase <= *xTo )
- StepJUMP( nOp1 );
- }
-}
-
-
-void SbiRuntime::StepERRHDL( sal_uInt32 nOp1 )
-{
- const sal_uInt8* p = pCode;
- StepJUMP( nOp1 );
- pError = pCode;
- pCode = p;
- pInst->aErrorMsg = OUString();
- pInst->nErr = 0;
- pInst->nErl = 0;
- nError = 0;
- SbxErrObject::getUnoErrObject()->Clear();
-}
-
-// Resume after errors (+0=statement, 1=next or Label)
-
-void SbiRuntime::StepRESUME( sal_uInt32 nOp1 )
-{
- // #32714 Resume without error? -> error
- if( !bInError )
- {
- Error( SbERR_BAD_RESUME );
- return;
- }
- if( nOp1 )
- {
- // set Code-pointer to the next statement
- sal_uInt16 n1, n2;
- pCode = pMod->FindNextStmnt( pErrCode, n1, n2, sal_True, pImg );
- }
- else
- pCode = pErrStmnt;
- if ( pError ) // current in error handler ( and got a Resume Next statement )
- SbxErrObject::getUnoErrObject()->Clear();
-
- if( nOp1 > 1 )
- StepJUMP( nOp1 );
- pInst->aErrorMsg = OUString();
- pInst->nErr = 0;
- pInst->nErl = 0;
- nError = 0;
- bInError = false;
-}
-
-// close channel (+channel, 0=all)
-void SbiRuntime::StepCLOSE( sal_uInt32 nOp1 )
-{
- SbError err;
- if( !nOp1 )
- pIosys->Shutdown();
- else
- {
- err = pIosys->GetError();
- if( !err )
- {
- pIosys->Close();
- }
- }
- err = pIosys->GetError();
- Error( err );
-}
-
-// output character (+char)
-
-void SbiRuntime::StepPRCHAR( sal_uInt32 nOp1 )
-{
- OString s(static_cast<sal_Char>(nOp1));
- pIosys->Write( s );
- Error( pIosys->GetError() );
-}
-
-// check whether TOS is a certain object class (+StringID)
-
-bool SbiRuntime::implIsClass( SbxObject* pObj, const OUString& aClass )
-{
- bool bRet = true;
-
- if( !aClass.isEmpty() )
- {
- bRet = pObj->IsClass( aClass );
- if( !bRet )
- bRet = aClass.equalsIgnoreAsciiCase( "object" );
- if( !bRet )
- {
- OUString aObjClass = pObj->GetClassName();
- SbModule* pClassMod = GetSbData()->pClassFac->FindClass( aObjClass );
- SbClassData* pClassData;
- if( pClassMod && (pClassData=pClassMod->pClassData) != NULL )
- {
- SbxVariable* pClassVar = pClassData->mxIfaces->Find( aClass, SbxCLASS_DONTCARE );
- bRet = (pClassVar != NULL);
- }
- }
- }
- return bRet;
-}
-
-bool SbiRuntime::checkClass_Impl( const SbxVariableRef& refVal,
- const OUString& aClass, bool bRaiseErrors, bool bDefault )
-{
- bool bOk = bDefault;
-
- SbxDataType t = refVal->GetType();
- SbxVariable* pVal = (SbxVariable*)refVal;
- // we don't know the type of uno properties that are (maybevoid)
- if ( t == SbxEMPTY && refVal->ISA(SbUnoProperty) )
- {
- SbUnoProperty* pProp = (SbUnoProperty*)pVal;
- t = pProp->getRealType();
- }
- if( t == SbxOBJECT )
- {
- SbxObject* pObj;
- if( pVal->IsA( TYPE(SbxObject) ) )
- pObj = (SbxObject*) pVal;
- else
- {
- pObj = (SbxObject*) refVal->GetObject();
- if( pObj && !pObj->IsA( TYPE(SbxObject) ) )
- pObj = NULL;
- }
- if( pObj )
- {
- if( !implIsClass( pObj, aClass ) )
- {
- if ( bVBAEnabled && pObj->IsA( TYPE(SbUnoObject) ) )
- {
- SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,pObj);
- bOk = checkUnoObjectType( pUnoObj, aClass );
- }
- else
- bOk = false;
- if ( !bOk )
- {
- if( bRaiseErrors )
- Error( SbERR_INVALID_USAGE_OBJECT );
- }
- }
- else
- {
- bOk = true;
-
- SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pObj);
- if( pClassModuleObject != NULL )
- pClassModuleObject->triggerInitializeEvent();
- }
- }
- }
- else
- {
- if ( !bVBAEnabled )
- {
- if( bRaiseErrors )
- Error( SbERR_NEEDS_OBJECT );
- bOk = false;
- }
- }
- return bOk;
-}
-
-void SbiRuntime::StepSETCLASS_impl( sal_uInt32 nOp1, bool bHandleDflt )
-{
- SbxVariableRef refVal = PopVar();
- SbxVariableRef refVar = PopVar();
- OUString aClass( pImg->GetString( static_cast<short>( nOp1 ) ) );
-
- bool bOk = checkClass_Impl( refVal, aClass, true );
- if( bOk )
- {
- StepSET_Impl( refVal, refVar, bHandleDflt ); // don't do handle dflt prop for a "proper" set
- }
-}
-
-void SbiRuntime::StepVBASETCLASS( sal_uInt32 nOp1 )
-{
- StepSETCLASS_impl( nOp1, false );
-}
-
-void SbiRuntime::StepSETCLASS( sal_uInt32 nOp1 )
-{
- StepSETCLASS_impl( nOp1, true );
-}
-
-void SbiRuntime::StepTESTCLASS( sal_uInt32 nOp1 )
-{
- SbxVariableRef xObjVal = PopVar();
- OUString aClass( pImg->GetString( static_cast<short>( nOp1 ) ) );
- bool bDefault = !bVBAEnabled;
- bool bOk = checkClass_Impl( xObjVal, aClass, false, bDefault );
-
- SbxVariable* pRet = new SbxVariable;
- pRet->PutBool( bOk );
- PushVar( pRet );
-}
-
-// define library for following declare-call
-
-void SbiRuntime::StepLIB( sal_uInt32 nOp1 )
-{
- aLibName = pImg->GetString( static_cast<short>( nOp1 ) );
-}
-
-// TOS is incremented by BASE, BASE is pushed before (+BASE)
-// This opcode is pushed before DIM/REDIM-commands,
-// if there's been only one index named.
-
-void SbiRuntime::StepBASED( sal_uInt32 nOp1 )
-{
- SbxVariable* p1 = new SbxVariable;
- SbxVariableRef x2 = PopVar();
-
- // #109275 Check compatiblity mode
- bool bCompatible = ((nOp1 & 0x8000) != 0);
- sal_uInt16 uBase = static_cast<sal_uInt16>(nOp1 & 1); // Can only be 0 or 1
- p1->PutInteger( uBase );
- if( !bCompatible )
- x2->Compute( SbxPLUS, *p1 );
- PushVar( x2 ); // first the Expr
- PushVar( p1 ); // then the Base
-}
-
-
-
-
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basic/source/runtime/step2.cxx b/basic/source/runtime/step2.cxx
deleted file mode 100644
index 168307538330..000000000000
--- a/basic/source/runtime/step2.cxx
+++ /dev/null
@@ -1,1400 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * 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 .
- */
-
-
-#include "runtime.hxx"
-#include "iosys.hxx"
-#include "image.hxx"
-#include "sbintern.hxx"
-#include "sbunoobj.hxx"
-#include "opcodes.hxx"
-
-#include <com/sun/star/container/XIndexAccess.hpp>
-#include <com/sun/star/script/XDefaultMethod.hpp>
-#include <com/sun/star/beans/XPropertySet.hpp>
-#include <com/sun/star/uno/Any.hxx>
-#include <comphelper/processfactory.hxx>
-#include <comphelper/string.hxx>
-#include <rtl/ustrbuf.hxx>
-
-using namespace com::sun::star::uno;
-using namespace com::sun::star::container;
-using namespace com::sun::star::lang;
-using namespace com::sun::star::beans;
-using namespace com::sun::star::script;
-
-using com::sun::star::uno::Reference;
-
-SbxVariable* getVBAConstant( const OUString& rName );
-
-SbxVariable* getDefaultProp( SbxVariable* pRef );
-
-// the bits in the String-ID:
-// 0x8000 - Argv is reserved
-
-SbxVariable* SbiRuntime::FindElement( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt32 nOp2,
- SbError nNotFound, bool bLocal, bool bStatic )
-{
- bool bIsVBAInterOp = SbiRuntime::isVBAEnabled();
- if( bIsVBAInterOp )
- {
- StarBASIC* pMSOMacroRuntimeLib = GetSbData()->pMSOMacroRuntimLib;
- if( pMSOMacroRuntimeLib != NULL )
- {
- pMSOMacroRuntimeLib->ResetFlag( SBX_EXTSEARCH );
- }
- }
-
- SbxVariable* pElem = NULL;
- if( !pObj )
- {
- Error( SbERR_NO_OBJECT );
- pElem = new SbxVariable;
- }
- else
- {
- bool bFatalError = false;
- SbxDataType t = (SbxDataType) nOp2;
- OUString aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) );
- // Hacky capture of Evaluate [] syntax
- // this should be tackled I feel at the pcode level
- if ( bIsVBAInterOp && aName.indexOf((sal_Unicode)'[') == 0 )
- {
- // emulate pcode here
- StepARGC();
- // psuedo StepLOADSC
- OUString sArg = aName.copy( 1, aName.getLength() - 2 );
- SbxVariable* p = new SbxVariable;
- p->PutString( sArg );
- PushVar( p );
- StepARGV();
- nOp1 = nOp1 | 0x8000; // indicate params are present
- aName = OUString("Evaluate");
- }
- if( bLocal )
- {
- if ( bStatic )
- {
- if ( pMeth )
- {
- pElem = pMeth->GetStatics()->Find( aName, SbxCLASS_DONTCARE );
- }
- }
-
- if ( !pElem )
- {
- pElem = refLocals->Find( aName, SbxCLASS_DONTCARE );
- }
- }
- if( !pElem )
- {
- bool bSave = rBasic.bNoRtl;
- rBasic.bNoRtl = true;
- pElem = pObj->Find( aName, SbxCLASS_DONTCARE );
-
- // #110004, #112015: Make private really private
- if( bLocal && pElem ) // Local as flag for global search
- {
- if( pElem->IsSet( SBX_PRIVATE ) )
- {
- SbiInstance* pInst_ = GetSbData()->pInst;
- if( pInst_ && pInst_->IsCompatibility() && pObj != pElem->GetParent() )
- {
- pElem = NULL; // Found but in wrong module!
- }
- // Interfaces: Use SBX_EXTFOUND
- }
- }
- rBasic.bNoRtl = bSave;
-
- // is it a global uno-identifier?
- if( bLocal && !pElem )
- {
- bool bSetName = true; // preserve normal behaviour
-
- // i#i68894# if VBAInterOp favour searching vba globals
- // over searching for uno classess
- if ( bVBAEnabled )
- {
- // Try Find in VBA symbols space
- pElem = rBasic.VBAFind( aName, SbxCLASS_DONTCARE );
- if ( pElem )
- {
- bSetName = false; // don't overwrite uno name
- }
- else
- {
- pElem = VBAConstantHelper::instance().getVBAConstant( aName );
- }
- }
-
- if( !pElem )
- {
- // #72382 ATTENTION! ALWAYS returns a result now
- // because of unknown modules!
- SbUnoClass* pUnoClass = findUnoClass( aName );
- if( pUnoClass )
- {
- pElem = new SbxVariable( t );
- SbxValues aRes( SbxOBJECT );
- aRes.pObj = pUnoClass;
- pElem->SbxVariable::Put( aRes );
- }
- }
-
- // #62939 If an uno-class has been found, the wrapper
- // object has to be held, because the uno-class, e. g.
- // "stardiv", has to be read out of the registry
- // every time again otherwise
- if( pElem )
- {
- // #63774 May not be saved too!!!
- pElem->SetFlag( SBX_DONTSTORE );
- pElem->SetFlag( SBX_NO_MODIFY);
-
- // #72382 save locally, all variables that have been declared
- // implicit would become global automatically otherwise!
- if ( bSetName )
- {
- pElem->SetName( aName );
- }
- refLocals->Put( pElem, refLocals->Count() );
- }
- }
-
- if( !pElem )
- {
- // not there and not in the object?
- // don't establish if that thing has parameters!
- if( nOp1 & 0x8000 )
- {
- bFatalError = true;
- }
-
- // else, if there are parameters, use different error code
- if( !bLocal || pImg->GetFlag( SBIMG_EXPLICIT ) )
- {
- // #39108 if explicit and as ELEM always a fatal error
- bFatalError = true;
-
-
- if( !( nOp1 & 0x8000 ) && nNotFound == SbERR_PROC_UNDEFINED )
- {
- nNotFound = SbERR_VAR_UNDEFINED;
- }
- }
- if( bFatalError )
- {
- // #39108 use dummy variable instead of fatal error
- if( !xDummyVar.Is() )
- {
- xDummyVar = new SbxVariable( SbxVARIANT );
- }
- pElem = xDummyVar;
-
- ClearArgvStack();
-
- Error( nNotFound, aName );
- }
- else
- {
- if ( bStatic )
- {
- pElem = StepSTATIC_Impl( aName, t );
- }
- if ( !pElem )
- {
- pElem = new SbxVariable( t );
- if( t != SbxVARIANT )
- {
- pElem->SetFlag( SBX_FIXED );
- }
- pElem->SetName( aName );
- refLocals->Put( pElem, refLocals->Count() );
- }
- }
- }
- }
- // #39108 Args can already be deleted!
- if( !bFatalError )
- {
- SetupArgs( pElem, nOp1 );
- }
- // because a particular call-type is requested
- if( pElem->IsA( TYPE(SbxMethod) ) )
- {
- // shall the type be converted?
- SbxDataType t2 = pElem->GetType();
- bool bSet = false;
- if( !( pElem->GetFlags() & SBX_FIXED ) )
- {
- if( t != SbxVARIANT && t != t2 &&
- t >= SbxINTEGER && t <= SbxSTRING )
- {
- pElem->SetType( t ), bSet = true;
- }
- }
- // assign pElem to a Ref, to delete a temp-var if applicable
- SbxVariableRef refTemp = pElem;
-
- // remove potential rests of the last call of the SbxMethod
- // free Write before, so that there's no error
- sal_uInt16 nSavFlags = pElem->GetFlags();
- pElem->SetFlag( SBX_READWRITE | SBX_NO_BROADCAST );
- pElem->SbxValue::Clear();
- pElem->SetFlags( nSavFlags );
-
- // don't touch before setting, as e. g. LEFT()
- // has to know the difference between Left$() and Left()
-
- // because the methods' parameters are cut away in PopVar()
- SbxVariable* pNew = new SbxMethod( *((SbxMethod*)pElem) );
- //OLD: SbxVariable* pNew = new SbxVariable( *pElem );
-
- pElem->SetParameters(0);
- pNew->SetFlag( SBX_READWRITE );
-
- if( bSet )
- {
- pElem->SetType( t2 );
- }
- pElem = pNew;
- }
- // consider index-access for UnoObjects
- // definitely we want this for VBA where properties are often
- // collections ( which need index access ), but lets only do
- // this if we actually have params following
- else if( bVBAEnabled && pElem->ISA(SbUnoProperty) && pElem->GetParameters() )
- {
- SbxVariableRef refTemp = pElem;
-
- // dissolve the notify while copying variable
- SbxVariable* pNew = new SbxVariable( *((SbxVariable*)pElem) );
- pElem->SetParameters( NULL );
- pElem = pNew;
- }
- }
- return CheckArray( pElem );
-}
-
-// for current scope (e. g. query from BASIC-IDE)
-SbxBase* SbiRuntime::FindElementExtern( const OUString& rName )
-{
- // don't expect pMeth to be != 0, as there are none set
- // in the RunInit yet
-
- SbxVariable* pElem = NULL;
- if( !pMod || rName.isEmpty() )
- {
- return NULL;
- }
- if( refLocals )
- {
- pElem = refLocals->Find( rName, SbxCLASS_DONTCARE );
- }
- if ( !pElem && pMeth )
- {
- // for statics, set the method's name in front
- OUString aMethName = pMeth->GetName();
- aMethName += ":";
- aMethName += rName;
- pElem = pMod->Find(aMethName, SbxCLASS_DONTCARE);
- }
-
- // search in parameter list
- if( !pElem && pMeth )
- {
- SbxInfo* pInfo = pMeth->GetInfo();
- if( pInfo && refParams )
- {
- sal_uInt16 nParamCount = refParams->Count();
- sal_uInt16 j = 1;
- const SbxParamInfo* pParam = pInfo->GetParam( j );
- while( pParam )
- {
- if( pParam->aName.equalsIgnoreAsciiCase( rName ) )
- {
- if( j >= nParamCount )
- {
- // Parameter is missing
- pElem = new SbxVariable( SbxSTRING );
- pElem->PutString( OUString("<missing parameter>"));
- }
- else
- {
- pElem = refParams->Get( j );
- }
- break;
- }
- pParam = pInfo->GetParam( ++j );
- }
- }
- }
-
- // search in module
- if( !pElem )
- {
- bool bSave = rBasic.bNoRtl;
- rBasic.bNoRtl = true;
- pElem = pMod->Find( rName, SbxCLASS_DONTCARE );
- rBasic.bNoRtl = bSave;
- }
- return pElem;
-}
-
-
-
-void SbiRuntime::SetupArgs( SbxVariable* p, sal_uInt32 nOp1 )
-{
- if( nOp1 & 0x8000 )
- {
- if( !refArgv )
- {
- StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
- }
- bool bHasNamed = false;
- sal_uInt16 i;
- sal_uInt16 nArgCount = refArgv->Count();
- for( i = 1 ; i < nArgCount ; i++ )
- {
- if( !refArgv->GetAlias(i).isEmpty() )
- {
- bHasNamed = true; break;
- }
- }
- if( bHasNamed )
- {
- SbxInfo* pInfo = p->GetInfo();
- if( !pInfo )
- {
- bool bError_ = true;
-
- SbUnoMethod* pUnoMethod = PTR_CAST(SbUnoMethod,p);
- SbUnoProperty* pUnoProperty = PTR_CAST(SbUnoProperty,p);
- if( pUnoMethod || pUnoProperty )
- {
- SbUnoObject* pParentUnoObj = PTR_CAST( SbUnoObject,p->GetParent() );
- if( pParentUnoObj )
- {
- Any aUnoAny = pParentUnoObj->getUnoAny();
- Reference< XInvocation > xInvocation;
- aUnoAny >>= xInvocation;
- if( xInvocation.is() ) // TODO: if( xOLEAutomation.is() )
- {
- bError_ = false;
-
- sal_uInt16 nCurPar = 1;
- AutomationNamedArgsSbxArray* pArg =
- new AutomationNamedArgsSbxArray( nArgCount );
- OUString* pNames = pArg->getNames().getArray();
- for( i = 1 ; i < nArgCount ; i++ )
- {
- SbxVariable* pVar = refArgv->Get( i );
- const OUString& rName = refArgv->GetAlias( i );
- if( !rName.isEmpty() )
- {
- pNames[i] = rName;
- }
- pArg->Put( pVar, nCurPar++ );
- }
- refArgv = pArg;
- }
- }
- }
- else if( bVBAEnabled && p->GetType() == SbxOBJECT && (!p->ISA(SbxMethod) || !p->IsBroadcaster()) )
- {
- // Check for default method with named parameters
- SbxBaseRef pObj = (SbxBase*)p->GetObject();
- if( pObj && pObj->ISA(SbUnoObject) )
- {
- SbUnoObject* pUnoObj = (SbUnoObject*)(SbxBase*)pObj;
- Any aAny = pUnoObj->getUnoAny();
-
- if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
- {
- Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue();
- Reference< XDefaultMethod > xDfltMethod( x, UNO_QUERY );
-
- OUString sDefaultMethod;
- if ( xDfltMethod.is() )
- {
- sDefaultMethod = xDfltMethod->getDefaultMethodName();
- }
- if ( !sDefaultMethod.isEmpty() )
- {
- SbxVariable* meth = pUnoObj->Find( sDefaultMethod, SbxCLASS_METHOD );
- if( meth != NULL )
- {
- pInfo = meth->GetInfo();
- }
- if( pInfo )
- {
- bError_ = false;
- }
- }
- }
- }
- }
- if( bError_ )
- {
- Error( SbERR_NO_NAMED_ARGS );
- }
- }
- else
- {
- sal_uInt16 nCurPar = 1;
- SbxArray* pArg = new SbxArray;
- for( i = 1 ; i < nArgCount ; i++ )
- {
- SbxVariable* pVar = refArgv->Get( i );
- const OUString& rName = refArgv->GetAlias( i );
- if( !rName.isEmpty() )
- {
- // nCurPar is set to the found parameter
- sal_uInt16 j = 1;
- const SbxParamInfo* pParam = pInfo->GetParam( j );
- while( pParam )
- {
- if( pParam->aName.equalsIgnoreAsciiCase( rName ) )
- {
- nCurPar = j;
- break;
- }
- pParam = pInfo->GetParam( ++j );
- }
- if( !pParam )
- {
- Error( SbERR_NAMED_NOT_FOUND ); break;
- }
- }
- pArg->Put( pVar, nCurPar++ );
- }
- refArgv = pArg;
- }
- }
- // own var as parameter 0
- refArgv->Put( p, 0 );
- p->SetParameters( refArgv );
- PopArgv();
- }
- else
- {
- p->SetParameters( NULL );
- }
-}
-
-// getting an array element
-
-SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem )
-{
- SbxArray* pPar;
- if( ( pElem->GetType() & SbxARRAY ) && (SbxVariable*)refRedim != pElem )
- {
- SbxBase* pElemObj = pElem->GetObject();
- SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
- pPar = pElem->GetParameters();
- if( pDimArray )
- {
- // parameters may be missing, if an array is
- // passed as an argument
- if( pPar )
- pElem = pDimArray->Get( pPar );
- }
- else
- {
- SbxArray* pArray = PTR_CAST(SbxArray,pElemObj);
- if( pArray )
- {
- if( !pPar )
- {
- Error( SbERR_OUT_OF_RANGE );
- pElem = new SbxVariable;
- }
- else
- {
- pElem = pArray->Get( pPar->Get( 1 )->GetInteger() );
- }
- }
- }
-
- // #42940, set parameter 0 to NULL so that var doesn't contain itself
- if( pPar )
- {
- pPar->Put( NULL, 0 );
- }
- }
- // consider index-access for UnoObjects
- else if( pElem->GetType() == SbxOBJECT && !pElem->ISA(SbxMethod) && ( !bVBAEnabled || ( bVBAEnabled && !pElem->ISA(SbxProperty) ) ) )
- {
- pPar = pElem->GetParameters();
- if ( pPar )
- {
- // is it an uno-object?
- SbxBaseRef pObj = (SbxBase*)pElem->GetObject();
- if( pObj )
- {
- if( pObj->ISA(SbUnoObject) )
- {
- SbUnoObject* pUnoObj = (SbUnoObject*)(SbxBase*)pObj;
- Any aAny = pUnoObj->getUnoAny();
-
- if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
- {
- Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue();
- Reference< XIndexAccess > xIndexAccess( x, UNO_QUERY );
- if ( !bVBAEnabled )
- {
- if( xIndexAccess.is() )
- {
- sal_uInt32 nParamCount = (sal_uInt32)pPar->Count() - 1;
- if( nParamCount != 1 )
- {
- StarBASIC::Error( SbERR_BAD_ARGUMENT );
- return pElem;
- }
-
- // get index
- sal_Int32 nIndex = pPar->Get( 1 )->GetLong();
- Reference< XInterface > xRet;
- try
- {
- Any aAny2 = xIndexAccess->getByIndex( nIndex );
- TypeClass eType = aAny2.getValueType().getTypeClass();
- if( eType == TypeClass_INTERFACE )
- {
- xRet = *(Reference< XInterface >*)aAny2.getValue();
- }
- }
- catch (const IndexOutOfBoundsException&)
- {
- // usually expect converting problem
- StarBASIC::Error( SbERR_OUT_OF_RANGE );
- }
-
- // #57847 always create a new variable, else error
- // due to PutObject(NULL) at ReadOnly-properties
- pElem = new SbxVariable( SbxVARIANT );
- if( xRet.is() )
- {
- aAny <<= xRet;
-
- // #67173 don't specify a name so that the real class name is entered
- OUString aName;
- SbxObjectRef xWrapper = (SbxObject*)new SbUnoObject( aName, aAny );
- pElem->PutObject( xWrapper );
- }
- else
- {
- pElem->PutObject( NULL );
- }
- }
- }
- else
- {
- // check if there isn't a default member between the current variable
- // and the params, e.g.
- // Dim rst1 As New ADODB.Recordset
- // "
- // val = rst1("FirstName")
- // has the default 'Fields' member between rst1 and '("FirstName")'
- SbxVariable* pDflt = getDefaultProp( pElem );
- if ( pDflt )
- {
- pDflt->Broadcast( SBX_HINT_DATAWANTED );
- SbxBaseRef pDfltObj = (SbxBase*)pDflt->GetObject();
- if( pDfltObj )
- {
- if( pDfltObj->ISA(SbUnoObject) )
- {
- pUnoObj = (SbUnoObject*)(SbxBase*)pDfltObj;
- Any aUnoAny = pUnoObj->getUnoAny();
-
- if( aUnoAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
- x = *(Reference< XInterface >*)aUnoAny.getValue();
- pElem = pDflt;
- }
- }
- }
- OUString sDefaultMethod;
-
- Reference< XDefaultMethod > xDfltMethod( x, UNO_QUERY );
-
- if ( xDfltMethod.is() )
- {
- sDefaultMethod = xDfltMethod->getDefaultMethodName();
- }
- else if( xIndexAccess.is() )
- {
- sDefaultMethod = OUString( "getByIndex" );
- }
- if ( !sDefaultMethod.isEmpty() )
- {
- SbxVariable* meth = pUnoObj->Find( sDefaultMethod, SbxCLASS_METHOD );
- SbxVariableRef refTemp = meth;
- if ( refTemp )
- {
- meth->SetParameters( pPar );
- SbxVariable* pNew = new SbxMethod( *(SbxMethod*)meth );
- pElem = pNew;
- }
- }
- }
- }
-
- // #42940, set parameter 0 to NULL so that var doesn't contain itself
- pPar->Put( NULL, 0 );
- }
- else if( pObj->ISA(BasicCollection) )
- {
- BasicCollection* pCol = (BasicCollection*)(SbxBase*)pObj;
- pElem = new SbxVariable( SbxVARIANT );
- pPar->Put( pElem, 0 );
- pCol->CollItem( pPar );
- }
- }
- else if( bVBAEnabled ) // !pObj
- {
- SbxArray* pParam = pElem->GetParameters();
- if( pParam != NULL && !pElem->IsSet( SBX_VAR_TO_DIM ) )
- {
- Error( SbERR_NO_OBJECT );
- }
- }
- }
- }
-
- return pElem;
-}
-
-// loading an element from the runtime-library (+StringID+type)
-
-void SbiRuntime::StepRTL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- PushVar( FindElement( rBasic.pRtl, nOp1, nOp2, SbERR_PROC_UNDEFINED, false ) );
-}
-
-void SbiRuntime::StepFIND_Impl( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt32 nOp2,
- SbError nNotFound, bool bLocal, bool bStatic )
-{
- if( !refLocals )
- {
- refLocals = new SbxArray;
- }
- PushVar( FindElement( pObj, nOp1, nOp2, nNotFound, bLocal, bStatic ) );
-}
-// loading a local/global variable (+StringID+type)
-
-void SbiRuntime::StepFIND( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, true );
-}
-
-// Search inside a class module (CM) to enable global search in time
-void SbiRuntime::StepFIND_CM( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
-
- SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pMod);
- if( pClassModuleObject )
- {
- pMod->SetFlag( SBX_GBLSEARCH );
- }
- StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, true );
-
- if( pClassModuleObject )
- {
- pMod->ResetFlag( SBX_GBLSEARCH );
- }
-}
-
-void SbiRuntime::StepFIND_STATIC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, true, true );
-}
-
-// loading an object-element (+StringID+type)
-// the object lies on TOS
-
-void SbiRuntime::StepELEM( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- SbxVariableRef pObjVar = PopVar();
-
- SbxObject* pObj = PTR_CAST(SbxObject,(SbxVariable*) pObjVar);
- if( !pObj )
- {
- SbxBase* pObjVarObj = pObjVar->GetObject();
- pObj = PTR_CAST(SbxObject,pObjVarObj);
- }
-
- // #56368 save reference at StepElem, otherwise objects could
- // lose their reference too early in qualification chains like
- // ActiveComponent.Selection(0).Text
- // #74254 now per list
- if( pObj )
- {
- SaveRef( (SbxVariable*)pObj );
- }
- PushVar( FindElement( pObj, nOp1, nOp2, SbERR_NO_METHOD, false ) );
-}
-
-// loading a parameter (+offset+type)
-// If the data type is wrong, create a copy.
-// The data type SbxEMPTY shows that no parameters are given.
-// Get( 0 ) may be EMPTY
-
-void SbiRuntime::StepPARAM( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- sal_uInt16 i = static_cast<sal_uInt16>( nOp1 & 0x7FFF );
- SbxDataType t = (SbxDataType) nOp2;
- SbxVariable* p;
-
- // #57915 solve missing in a cleaner way
- sal_uInt16 nParamCount = refParams->Count();
- if( i >= nParamCount )
- {
- sal_Int16 iLoop = i;
- while( iLoop >= nParamCount )
- {
- p = new SbxVariable();
-
- if( SbiRuntime::isVBAEnabled() &&
- (t == SbxOBJECT || t == SbxSTRING) )
- {
- if( t == SbxOBJECT )
- {
- p->PutObject( NULL );
- }
- else
- {
- p->PutString( OUString() );
- }
- }
- else
- {
- p->PutErr( 448 ); // like in VB: Error-Code 448 (SbERR_NAMED_NOT_FOUND)
- }
- refParams->Put( p, iLoop );
- iLoop--;
- }
- }
- p = refParams->Get( i );
-
- if( p->GetType() == SbxERROR && ( i ) )
- {
- // if there's a parameter missing, it can be OPTIONAL
- bool bOpt = false;
- if( pMeth )
- {
- SbxInfo* pInfo = pMeth->GetInfo();
- if ( pInfo )
- {
- const SbxParamInfo* pParam = pInfo->GetParam( i );
- if( pParam && ( (pParam->nFlags & SBX_OPTIONAL) != 0 ) )
- {
- // Default value?
- sal_uInt16 nDefaultId = (sal_uInt16)(pParam->nUserData & 0x0ffff);
- if( nDefaultId > 0 )
- {
- OUString aDefaultStr = pImg->GetString( nDefaultId );
- p = new SbxVariable();
- p->PutString( aDefaultStr );
- refParams->Put( p, i );
- }
- bOpt = true;
- }
- }
- }
- if( !bOpt )
- {
- Error( SbERR_NOT_OPTIONAL );
- }
- }
- else if( t != SbxVARIANT && (SbxDataType)(p->GetType() & 0x0FFF ) != t )
- {
- SbxVariable* q = new SbxVariable( t );
- SaveRef( q );
- *q = *p;
- p = q;
- if ( i )
- {
- refParams->Put( p, i );
- }
- }
- SetupArgs( p, nOp1 );
- PushVar( CheckArray( p ) );
-}
-
-// Case-Test (+True-Target+Test-Opcode)
-
-void SbiRuntime::StepCASEIS( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- if( !refCaseStk || !refCaseStk->Count() )
- {
- StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
- }
- else
- {
- SbxVariableRef xComp = PopVar();
- SbxVariableRef xCase = refCaseStk->Get( refCaseStk->Count() - 1 );
- if( xCase->Compare( (SbxOperator) nOp2, *xComp ) )
- {
- StepJUMP( nOp1 );
- }
- }
-}
-
-// call of a DLL-procedure (+StringID+type)
-// the StringID's MSB shows that Argv is occupied
-
-void SbiRuntime::StepCALL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- OUString aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) );
- SbxArray* pArgs = NULL;
- if( nOp1 & 0x8000 )
- {
- pArgs = refArgv;
- }
- DllCall( aName, aLibName, pArgs, (SbxDataType) nOp2, false );
- aLibName = OUString();
- if( nOp1 & 0x8000 )
- {
- PopArgv();
- }
-}
-
-// call of a DLL-procedure after CDecl (+StringID+type)
-
-void SbiRuntime::StepCALLC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- OUString aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) );
- SbxArray* pArgs = NULL;
- if( nOp1 & 0x8000 )
- {
- pArgs = refArgv;
- }
- DllCall( aName, aLibName, pArgs, (SbxDataType) nOp2, true );
- aLibName = OUString();
- if( nOp1 & 0x8000 )
- {
- PopArgv();
- }
-}
-
-
-// beginning of a statement (+Line+Col)
-
-void SbiRuntime::StepSTMNT( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- // If the Expr-Stack at the beginning of a statement constains a variable,
- // some fool has called X as a function, although it's a variable!
- bool bFatalExpr = false;
- OUString sUnknownMethodName;
- if( nExprLvl > 1 )
- {
- bFatalExpr = true;
- }
- else if( nExprLvl )
- {
- SbxVariable* p = refExprStk->Get( 0 );
- if( p->GetRefCount() > 1 &&
- refLocals.Is() && refLocals->Find( p->GetName(), p->GetClass() ) )
- {
- sUnknownMethodName = p->GetName();
- bFatalExpr = true;
- }
- }
-
- ClearExprStack();
-
- ClearRefs();
-
- // We have to cancel hard here because line and column
- // would be wrong later otherwise!
- if( bFatalExpr)
- {
- StarBASIC::FatalError( SbERR_NO_METHOD, sUnknownMethodName );
- return;
- }
- pStmnt = pCode - 9;
- sal_uInt16 nOld = nLine;
- nLine = static_cast<short>( nOp1 );
-
- // #29955 & 0xFF, to filter out for-loop-level
- nCol1 = static_cast<short>( nOp2 & 0xFF );
-
- // find the next STMNT-command to set the final column
- // of this statement
-
- nCol2 = 0xffff;
- sal_uInt16 n1, n2;
- const sal_uInt8* p = pMod->FindNextStmnt( pCode, n1, n2 );
- if( p )
- {
- if( n1 == nOp1 )
- {
- // #29955 & 0xFF, to filter out for-loop-level
- nCol2 = (n2 & 0xFF) - 1;
- }
- }
-
- // #29955 correct for-loop-level, #67452 NOT in the error-handler
- if( !bInError )
- {
- // (there's a difference here in case of a jump out of a loop)
- sal_uInt16 nExspectedForLevel = static_cast<sal_uInt16>( nOp2 / 0x100 );
- if( pGosubStk )
- {
- nExspectedForLevel = nExspectedForLevel + pGosubStk->nStartForLvl;
- }
-
- // if the actual for-level is too small it'd jump out
- // of a loop -> corrected
- while( nForLvl > nExspectedForLevel )
- {
- PopFor();
- }
- }
-
- // 16.10.96: #31460 new concept for StepInto/Over/Out
- // see explanation at _ImplGetBreakCallLevel
- if( pInst->nCallLvl <= pInst->nBreakCallLvl )
- {
- StarBASIC* pStepBasic = GetCurrentBasic( &rBasic );
- sal_uInt16 nNewFlags = pStepBasic->StepPoint( nLine, nCol1, nCol2 );
-
- pInst->CalcBreakCallLevel( nNewFlags );
- }
-
- // break points only at STMNT-commands in a new line!
- else if( ( nOp1 != nOld )
- && ( nFlags & SbDEBUG_BREAK )
- && pMod->IsBP( static_cast<sal_uInt16>( nOp1 ) ) )
- {
- StarBASIC* pBreakBasic = GetCurrentBasic( &rBasic );
- sal_uInt16 nNewFlags = pBreakBasic->BreakPoint( nLine, nCol1, nCol2 );
-
- pInst->CalcBreakCallLevel( nNewFlags );
- }
-}
-
-// (+SvStreamFlags+Flags)
-// Stack: block length
-// channel number
-// file name
-
-void SbiRuntime::StepOPEN( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- SbxVariableRef pName = PopVar();
- SbxVariableRef pChan = PopVar();
- SbxVariableRef pLen = PopVar();
- short nBlkLen = pLen->GetInteger();
- short nChan = pChan->GetInteger();
- OString aName(OUStringToOString(pName->GetOUString(), osl_getThreadTextEncoding()));
- pIosys->Open( nChan, aName, static_cast<short>( nOp1 ),
- static_cast<short>( nOp2 ), nBlkLen );
- Error( pIosys->GetError() );
-}
-
-// create object (+StringID+StringID)
-
-void SbiRuntime::StepCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) );
- SbxObject *pObj = SbxBase::CreateObject( aClass );
- if( !pObj )
- {
- Error( SbERR_INVALID_OBJECT );
- }
- else
- {
- OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
- pObj->SetName( aName );
- // the object must be able to call the BASIC
- pObj->SetParent( &rBasic );
- SbxVariable* pNew = new SbxVariable;
- pNew->PutObject( pObj );
- PushVar( pNew );
- }
-}
-
-void SbiRuntime::StepDCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- StepDCREATE_IMPL( nOp1, nOp2 );
-}
-
-void SbiRuntime::StepDCREATE_REDIMP( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- StepDCREATE_IMPL( nOp1, nOp2 );
-}
-
-
-// Helper function for StepDCREATE_IMPL / bRedimp = true
-void implCopyDimArray_DCREATE( 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_DCREATE( pNewArray, pOldArray, nMaxDimIndex, nActualDim + 1,
- pActualIndices, pLowerBounds, pUpperBounds );
- }
- else
- {
- SbxVariable* pSource = pOldArray->Get32( pActualIndices );
- pNewArray->Put32( pSource, pActualIndices );
- }
- }
-}
-
-// #56204 create object array (+StringID+StringID), DCREATE == Dim-Create
-void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- SbxVariableRef refVar = PopVar();
-
- DimImpl( refVar );
-
- // fill the array with instances of the requested class
- SbxBaseRef xObj = (SbxBase*)refVar->GetObject();
- if( !xObj )
- {
- StarBASIC::Error( SbERR_INVALID_OBJECT );
- return;
- }
-
- SbxDimArray* pArray = 0;
- if( xObj->ISA(SbxDimArray) )
- {
- SbxBase* pObj = (SbxBase*)xObj;
- pArray = (SbxDimArray*)pObj;
-
- short nDims = pArray->GetDims();
- sal_Int32 nTotalSize = 0;
-
- // must be a one-dimensional array
- sal_Int32 nLower, nUpper, nSize;
- sal_Int32 i;
- for( i = 0 ; i < nDims ; i++ )
- {
- pArray->GetDim32( i+1, nLower, nUpper );
- nSize = nUpper - nLower + 1;
- if( i == 0 )
- {
- nTotalSize = nSize;
- }
- else
- {
- nTotalSize *= nSize;
- }
- }
-
- // create objects and insert them into the array
- OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) );
- for( i = 0 ; i < nTotalSize ; i++ )
- {
- SbxObject *pClassObj = SbxBase::CreateObject( aClass );
- if( !pClassObj )
- {
- Error( SbERR_INVALID_OBJECT );
- break;
- }
- else
- {
- OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
- pClassObj->SetName( aName );
- // the object must be able to call the basic
- pClassObj->SetParent( &rBasic );
- pArray->SbxArray::Put32( pClassObj, i );
- }
- }
- }
-
- SbxDimArray* pOldArray = (SbxDimArray*)(SbxArray*)refRedimpArray;
- if( pArray && pOldArray )
- {
- short nDimsNew = pArray->GetDims();
- short nDimsOld = pOldArray->GetDims();
- short nDims = nDimsNew;
- bool bRangeError = 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 = true;
- }
- else
- {
- // Compare bounds
- for( short i = 1 ; i <= nDims ; i++ )
- {
- sal_Int32 lBoundNew, uBoundNew;
- sal_Int32 lBoundOld, uBoundOld;
- pArray->GetDim32( i, lBoundNew, uBoundNew );
- pOldArray->GetDim32( i, lBoundOld, uBoundOld );
-
- 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_DCREATE( pArray, pOldArray, nDims - 1,
- 0, pActualIndices, pLowerBounds, pUpperBounds );
- }
- delete [] pUpperBounds;
- delete [] pLowerBounds;
- delete [] pActualIndices;
- refRedimpArray = NULL;
- }
-}
-
-// create object from user-type (+StringID+StringID)
-
-SbxObject* createUserTypeImpl( const OUString& rClassName ); // sb.cxx
-
-void SbiRuntime::StepTCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
- OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) );
-
- SbxObject* pCopyObj = createUserTypeImpl( aClass );
- if( pCopyObj )
- {
- pCopyObj->SetName( aName );
- }
- SbxVariable* pNew = new SbxVariable;
- pNew->PutObject( pCopyObj );
- pNew->SetDeclareClassName( aClass );
- PushVar( pNew );
-}
-
-void SbiRuntime::implHandleSbxFlags( SbxVariable* pVar, SbxDataType t, sal_uInt32 nOp2 )
-{
- bool bWithEvents = ((t & 0xff) == SbxOBJECT && (nOp2 & SBX_TYPE_WITH_EVENTS_FLAG) != 0);
- if( bWithEvents )
- {
- pVar->SetFlag( SBX_WITH_EVENTS );
- }
- bool bDimAsNew = ((nOp2 & SBX_TYPE_DIM_AS_NEW_FLAG) != 0);
- if( bDimAsNew )
- {
- pVar->SetFlag( SBX_DIM_AS_NEW );
- }
- bool bFixedString = ((t & 0xff) == SbxSTRING && (nOp2 & SBX_FIXED_LEN_STRING_FLAG) != 0);
- if( bFixedString )
- {
- sal_uInt16 nCount = static_cast<sal_uInt16>( nOp2 >> 17 ); // len = all bits above 0x10000
- OUStringBuffer aBuf;
- comphelper::string::padToLength(aBuf, nCount, 0);
- pVar->PutString(aBuf.makeStringAndClear());
- }
-
- bool bVarToDim = ((nOp2 & SBX_TYPE_VAR_TO_DIM_FLAG) != 0);
- if( bVarToDim )
- {
- pVar->SetFlag( SBX_VAR_TO_DIM );
- }
-}
-
-// establishing a local variable (+StringID+type)
-
-void SbiRuntime::StepLOCAL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- if( !refLocals.Is() )
- {
- refLocals = new SbxArray;
- }
- OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
- if( refLocals->Find( aName, SbxCLASS_DONTCARE ) == NULL )
- {
- SbxDataType t = (SbxDataType)(nOp2 & 0xffff);
- SbxVariable* p = new SbxVariable( t );
- p->SetName( aName );
- implHandleSbxFlags( p, t, nOp2 );
- refLocals->Put( p, refLocals->Count() );
- }
-}
-
-// establishing a module-global variable (+StringID+type)
-
-void SbiRuntime::StepPUBLIC_Impl( sal_uInt32 nOp1, sal_uInt32 nOp2, bool bUsedForClassModule )
-{
- OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
- SbxDataType t = (SbxDataType)(SbxDataType)(nOp2 & 0xffff);;
- sal_Bool bFlag = pMod->IsSet( SBX_NO_MODIFY );
- pMod->SetFlag( SBX_NO_MODIFY );
- SbxVariableRef p = pMod->Find( aName, SbxCLASS_PROPERTY );
- if( p.Is() )
- {
- pMod->Remove (p);
- }
- SbProperty* pProp = pMod->GetProperty( aName, t );
- if( !bUsedForClassModule )
- {
- pProp->SetFlag( SBX_PRIVATE );
- }
- if( !bFlag )
- {
- pMod->ResetFlag( SBX_NO_MODIFY );
- }
- if( pProp )
- {
- pProp->SetFlag( SBX_DONTSTORE );
- // from 2.7.1996: HACK because of 'reference can't be saved'
- pProp->SetFlag( SBX_NO_MODIFY);
-
- implHandleSbxFlags( pProp, t, nOp2 );
- }
-}
-
-void SbiRuntime::StepPUBLIC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- StepPUBLIC_Impl( nOp1, nOp2, false );
-}
-
-void SbiRuntime::StepPUBLIC_P( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- // Creates module variable that isn't reinitialised when
- // between invocations ( for VBASupport & document basic only )
- if( pMod->pImage->bFirstInit )
- {
- bool bUsedForClassModule = pImg->GetFlag( SBIMG_CLASSMODULE );
- StepPUBLIC_Impl( nOp1, nOp2, bUsedForClassModule );
- }
-}
-
-// establishing a global variable (+StringID+type)
-
-void SbiRuntime::StepGLOBAL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- if( pImg->GetFlag( SBIMG_CLASSMODULE ) )
- {
- StepPUBLIC_Impl( nOp1, nOp2, true );
- }
- OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
- SbxDataType t = (SbxDataType)(nOp2 & 0xffff);
-
- // Store module scope variables at module scope
- // in non vba mode these are stored at the library level :/
- // not sure if this really should not be enabled for ALL basic
- SbxObject* pStorage = &rBasic;
- if ( SbiRuntime::isVBAEnabled() )
- {
- pStorage = pMod;
- pMod->AddVarName( aName );
- }
-
- sal_Bool bFlag = pStorage->IsSet( SBX_NO_MODIFY );
- rBasic.SetFlag( SBX_NO_MODIFY );
- SbxVariableRef p = pStorage->Find( aName, SbxCLASS_PROPERTY );
- if( p.Is() )
- {
- pStorage->Remove (p);
- }
- p = pStorage->Make( aName, SbxCLASS_PROPERTY, t );
- if( !bFlag )
- {
- pStorage->ResetFlag( SBX_NO_MODIFY );
- }
- if( p )
- {
- p->SetFlag( SBX_DONTSTORE );
- // from 2.7.1996: HACK because of 'reference can't be saved'
- p->SetFlag( SBX_NO_MODIFY);
- }
-}
-
-
-// Creates global variable that isn't reinitialised when
-// basic is restarted, P=PERSIST (+StringID+Typ)
-
-void SbiRuntime::StepGLOBAL_P( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- if( pMod->pImage->bFirstInit )
- {
- StepGLOBAL( nOp1, nOp2 );
- }
-}
-
-
-// Searches for global variable, behavior depends on the fact
-// if the variable is initialised for the first time
-
-void SbiRuntime::StepFIND_G( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- if( pMod->pImage->bFirstInit )
- {
- // Behave like always during first init
- StepFIND( nOp1, nOp2 );
- }
- else
- {
- // Return dummy variable
- SbxDataType t = (SbxDataType) nOp2;
- OUString aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) );
-
- SbxVariable* pDummyVar = new SbxVariable( t );
- pDummyVar->SetName( aName );
- PushVar( pDummyVar );
- }
-}
-
-
-SbxVariable* SbiRuntime::StepSTATIC_Impl( OUString& aName, SbxDataType& t )
-{
- SbxVariable* p = NULL;
- if ( pMeth )
- {
- SbxArray* pStatics = pMeth->GetStatics();
- if( pStatics && ( pStatics->Find( aName, SbxCLASS_DONTCARE ) == NULL ) )
- {
- p = new SbxVariable( t );
- if( t != SbxVARIANT )
- {
- p->SetFlag( SBX_FIXED );
- }
- p->SetName( aName );
- pStatics->Put( p, pStatics->Count() );
- }
- }
- return p;
-}
-// establishing a static variable (+StringID+type)
-void SbiRuntime::StepSTATIC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
-{
- OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
- SbxDataType t = (SbxDataType) nOp2;
- StepSTATIC_Impl( aName, t );
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */