| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_basic.hxx" |
| |
| #include "runtime.hxx" |
| #ifndef GCC |
| #endif |
| #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> |
| |
| 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 String& rName ); |
| |
| // Suchen eines Elements |
| // Die Bits im String-ID: |
| // 0x8000 - Argv ist belegt |
| |
| SbxVariable* SbiRuntime::FindElement |
| ( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt32 nOp2, SbError nNotFound, sal_Bool bLocal, sal_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 |
| { |
| sal_Bool bFatalError = sal_False; |
| SbxDataType t = (SbxDataType) nOp2; |
| String 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.Search('[') == 0 ) |
| { |
| // emulate pcode here |
| StepARGC(); |
| // psuedo StepLOADSC |
| String sArg = aName.Copy( 1, aName.Len() - 2 ); |
| SbxVariable* p = new SbxVariable; |
| p->PutString( sArg ); |
| PushVar( p ); |
| // |
| StepARGV(); |
| nOp1 = nOp1 | 0x8000; // indicate params are present |
| aName = String::CreateFromAscii("Evaluate"); |
| } |
| if( bLocal ) |
| { |
| if ( bStatic ) |
| { |
| if ( pMeth ) |
| pElem = pMeth->GetStatics()->Find( aName, SbxCLASS_DONTCARE ); |
| } |
| |
| if ( !pElem ) |
| pElem = refLocals->Find( aName, SbxCLASS_DONTCARE ); |
| } |
| if( !pElem ) |
| { |
| // Die RTL brauchen wir nicht mehr zu durchsuchen! |
| sal_Bool bSave = rBasic.bNoRtl; |
| rBasic.bNoRtl = sal_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_ = pINST; |
| if( pInst_ && pInst_->IsCompatibility() && pObj != pElem->GetParent() ) |
| pElem = NULL; // Found but in wrong module! |
| |
| // Interfaces: Use SBX_EXTFOUND |
| } |
| } |
| rBasic.bNoRtl = bSave; |
| |
| // Ist es ein globaler Uno-Bezeichner? |
| 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 = getVBAConstant( aName ); |
| } |
| |
| if( !pElem ) |
| { |
| // #72382 VORSICHT! Liefert jetzt wegen unbekannten |
| // Modulen IMMER ein Ergebnis! |
| SbUnoClass* pUnoClass = findUnoClass( aName ); |
| if( pUnoClass ) |
| { |
| pElem = new SbxVariable( t ); |
| SbxValues aRes( SbxOBJECT ); |
| aRes.pObj = pUnoClass; |
| pElem->SbxVariable::Put( aRes ); |
| } |
| } |
| |
| // #62939 Wenn eine Uno-Klasse gefunden wurde, muss |
| // das Wrapper-Objekt gehalten werden, da sonst auch |
| // die Uno-Klasse, z.B. "stardiv" immer wieder neu |
| // aus der Registry gelesen werden muss |
| if( pElem ) |
| { |
| // #63774 Darf nicht mit gespeichert werden!!! |
| pElem->SetFlag( SBX_DONTSTORE ); |
| pElem->SetFlag( SBX_NO_MODIFY); |
| |
| // #72382 Lokal speichern, sonst werden alle implizit |
| // deklarierten Vars automatisch global ! |
| if ( bSetName ) |
| pElem->SetName( aName ); |
| refLocals->Put( pElem, refLocals->Count() ); |
| } |
| } |
| |
| if( !pElem ) |
| { |
| // Nicht da und nicht im Objekt? |
| // Hat das Ding Parameter, nicht einrichten! |
| if( nOp1 & 0x8000 ) |
| bFatalError = sal_True; |
| // ALT: StarBASIC::FatalError( nNotFound ); |
| |
| // Sonst, falls keine Parameter sind, anderen Error Code verwenden |
| if( !bLocal || pImg->GetFlag( SBIMG_EXPLICIT ) ) |
| { |
| // #39108 Bei explizit und als ELEM immer ein Fatal Error |
| bFatalError = sal_True; |
| |
| // Falls keine Parameter sind, anderen Error Code verwenden |
| if( !( nOp1 & 0x8000 ) && nNotFound == SbERR_PROC_UNDEFINED ) |
| nNotFound = SbERR_VAR_UNDEFINED; |
| } |
| if( bFatalError ) |
| { |
| // #39108 Statt FatalError zu setzen, Dummy-Variable liefern |
| if( !xDummyVar.Is() ) |
| xDummyVar = new SbxVariable( SbxVARIANT ); |
| pElem = xDummyVar; |
| |
| // Parameter von Hand loeschen |
| ClearArgvStack(); |
| |
| // Normalen Error setzen |
| Error( nNotFound, aName ); |
| } |
| else |
| { |
| if ( bStatic ) |
| pElem = StepSTATIC_Impl( aName, t ); |
| if ( !pElem ) |
| { |
| // Sonst Variable neu anlegen |
| pElem = new SbxVariable( t ); |
| if( t != SbxVARIANT ) |
| pElem->SetFlag( SBX_FIXED ); |
| pElem->SetName( aName ); |
| refLocals->Put( pElem, refLocals->Count() ); |
| } |
| } |
| } |
| } |
| // #39108 Args koennen schon geloescht sein! |
| if( !bFatalError ) |
| SetupArgs( pElem, nOp1 ); |
| // Ein bestimmter Call-Type wurde gewuenscht, daher muessen |
| // wir hier den Typ setzen und das Ding anfassen, um den |
| // korrekten Returnwert zu erhalten! |
| if( pElem->IsA( TYPE(SbxMethod) ) ) |
| { |
| // Soll der Typ konvertiert werden? |
| SbxDataType t2 = pElem->GetType(); |
| sal_Bool bSet = sal_False; |
| if( !( pElem->GetFlags() & SBX_FIXED ) ) |
| { |
| if( t != SbxVARIANT && t != t2 && |
| t >= SbxINTEGER && t <= SbxSTRING ) |
| pElem->SetType( t ), bSet = sal_True; |
| } |
| // pElem auf eine Ref zuweisen, um ggf. eine Temp-Var zu loeschen |
| SbxVariableRef refTemp = pElem; |
| |
| // Moegliche Reste vom letzten Aufruf der SbxMethod beseitigen |
| // Vorher Schreiben freigeben, damit kein Error gesetzt wird. |
| sal_uInt16 nSavFlags = pElem->GetFlags(); |
| pElem->SetFlag( SBX_READWRITE | SBX_NO_BROADCAST ); |
| pElem->SbxValue::Clear(); |
| pElem->SetFlags( nSavFlags ); |
| |
| // Erst nach dem Setzen anfassen, da z.B. LEFT() |
| // den Unterschied zwischen Left$() und Left() kennen muss |
| |
| // AB 12.8.96: Da in PopVar() die Parameter von Methoden weggehauen |
| // werden, muessen wir hier explizit eine neue SbxMethod anlegen |
| SbxVariable* pNew = new SbxMethod( *((SbxMethod*)pElem) ); // das ist der Call! |
| //ALT: SbxVariable* pNew = new SbxVariable( *pElem ); // das ist der Call! |
| |
| pElem->SetParameters(0); // sonst bleibt Ref auf sich selbst |
| pNew->SetFlag( SBX_READWRITE ); |
| |
| // den Datentypen zuruecksetzen? |
| if( bSet ) |
| pElem->SetType( t2 ); |
| pElem = pNew; |
| } |
| // Index-Access bei UnoObjekten beruecksichtigen |
| // 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() ) |
| { |
| // pElem auf eine Ref zuweisen, um ggf. eine Temp-Var zu loeschen |
| SbxVariableRef refTemp = pElem; |
| |
| // Variable kopieren und dabei den Notify aufloesen |
| SbxVariable* pNew = new SbxVariable( *((SbxVariable*)pElem) ); // das ist der Call! |
| pElem->SetParameters( NULL ); // sonst bleibt Ref auf sich selbst |
| pElem = pNew; |
| } |
| } |
| return CheckArray( pElem ); |
| } |
| |
| // Find-Funktion ueber Name fuer aktuellen Scope (z.B. Abfrage aus BASIC-IDE) |
| SbxBase* SbiRuntime::FindElementExtern( const String& rName ) |
| { |
| // Hinweis zu #35281#: Es darf nicht davon ausgegangen werden, dass |
| // pMeth != null, da im RunInit noch keine gesetzt ist. |
| |
| SbxVariable* pElem = NULL; |
| if( !pMod || !rName.Len() ) |
| return NULL; |
| |
| // Lokal suchen |
| if( refLocals ) |
| pElem = refLocals->Find( rName, SbxCLASS_DONTCARE ); |
| |
| // In Statics suchen |
| if ( !pElem && pMeth ) |
| { |
| // Bei Statics, Name der Methode davor setzen |
| String aMethName = pMeth->GetName(); |
| aMethName += ':'; |
| aMethName += rName; |
| pElem = pMod->Find(aMethName, SbxCLASS_DONTCARE); |
| } |
| |
| // In Parameter-Liste suchen |
| 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.EqualsIgnoreCaseAscii( rName ) ) |
| { |
| if( j >= nParamCount ) |
| { |
| // Parameter is missing |
| pElem = new SbxVariable( SbxSTRING ); |
| pElem->PutString( String( RTL_CONSTASCII_USTRINGPARAM("<missing parameter>" ) ) ); |
| } |
| else |
| { |
| pElem = refParams->Get( j ); |
| } |
| break; |
| } |
| pParam = pInfo->GetParam( ++j ); |
| } |
| } |
| } |
| |
| // Im Modul suchen |
| if( !pElem ) |
| { |
| // RTL nicht durchsuchen! |
| sal_Bool bSave = rBasic.bNoRtl; |
| rBasic.bNoRtl = sal_True; |
| pElem = pMod->Find( rName, SbxCLASS_DONTCARE ); |
| rBasic.bNoRtl = bSave; |
| } |
| return pElem; |
| } |
| |
| |
| // Argumente eines Elements setzen |
| // Dabei auch die Argumente umsetzen, falls benannte Parameter |
| // verwendet wurden |
| |
| void SbiRuntime::SetupArgs( SbxVariable* p, sal_uInt32 nOp1 ) |
| { |
| if( nOp1 & 0x8000 ) |
| { |
| if( !refArgv ) |
| StarBASIC::FatalError( SbERR_INTERNAL_ERROR ); |
| sal_Bool bHasNamed = sal_False; |
| sal_uInt16 i; |
| sal_uInt16 nArgCount = refArgv->Count(); |
| for( i = 1 ; i < nArgCount ; i++ ) |
| { |
| if( refArgv->GetAlias( i ).Len() ) |
| { |
| bHasNamed = sal_True; break; |
| } |
| } |
| if( bHasNamed ) |
| { |
| // Wir haben mindestens einen benannten Parameter! |
| // Wir muessen also umsortieren |
| // Gibt es Parameter-Infos? |
| 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 ); |
| ::rtl::OUString* pNames = pArg->getNames().getArray(); |
| for( i = 1 ; i < nArgCount ; i++ ) |
| { |
| SbxVariable* pVar = refArgv->Get( i ); |
| const String& rName = refArgv->GetAlias( i ); |
| if( rName.Len() ) |
| 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 ); |
| |
| rtl::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 String& rName = refArgv->GetAlias( i ); |
| if( rName.Len() ) |
| { |
| // nCurPar wird auf den gefundenen Parameter gesetzt |
| sal_uInt16 j = 1; |
| const SbxParamInfo* pParam = pInfo->GetParam( j ); |
| while( pParam ) |
| { |
| if( pParam->aName.EqualsIgnoreCaseAscii( rName ) ) |
| { |
| nCurPar = j; |
| break; |
| } |
| pParam = pInfo->GetParam( ++j ); |
| } |
| if( !pParam ) |
| { |
| Error( SbERR_NAMED_NOT_FOUND ); break; |
| } |
| } |
| pArg->Put( pVar, nCurPar++ ); |
| } |
| refArgv = pArg; |
| } |
| } |
| // Eigene Var als Parameter 0 |
| refArgv->Put( p, 0 ); |
| p->SetParameters( refArgv ); |
| PopArgv(); |
| } |
| else |
| p->SetParameters( NULL ); |
| } |
| |
| // Holen eines Array-Elements |
| |
| SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem ) |
| { |
| // Falls wir ein Array haben, wollen wir bitte das Array-Element! |
| SbxArray* pPar; |
| if( pElem->GetType() & SbxARRAY ) |
| { |
| SbxBase* pElemObj = pElem->GetObject(); |
| SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj); |
| pPar = pElem->GetParameters(); |
| if( pDimArray ) |
| { |
| // Die Parameter koennen fehlen, wenn ein Array als |
| // Argument uebergeben wird. |
| 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, 0.Parameter zu NULL setzen, damit sich Var nicht selbst haelt |
| if( pPar ) |
| pPar->Put( NULL, 0 ); |
| } |
| // Index-Access bei UnoObjekten beruecksichtigen |
| else if( pElem->GetType() == SbxOBJECT && (!pElem->ISA(SbxMethod) || (bVBAEnabled && !pElem->IsBroadcaster()) ) ) |
| { |
| pPar = pElem->GetParameters(); |
| if ( pPar ) |
| { |
| // Ist es ein Uno-Objekt? |
| 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 ) |
| { |
| // Haben wir Index-Access? |
| if( xIndexAccess.is() ) |
| { |
| sal_uInt32 nParamCount = (sal_uInt32)pPar->Count() - 1; |
| if( nParamCount != 1 ) |
| { |
| StarBASIC::Error( SbERR_BAD_ARGUMENT ); |
| return pElem; |
| } |
| |
| // Index holen |
| 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 (IndexOutOfBoundsException&) |
| { |
| // Bei Exception erstmal immer von Konvertierungs-Problem ausgehen |
| StarBASIC::Error( SbERR_OUT_OF_RANGE ); |
| } |
| |
| // #57847 Immer neue Variable anlegen, sonst Fehler |
| // durch PutObject(NULL) bei ReadOnly-Properties. |
| pElem = new SbxVariable( SbxVARIANT ); |
| if( xRet.is() ) |
| { |
| aAny <<= xRet; |
| |
| // #67173 Kein Namen angeben, damit echter Klassen-Namen eintragen wird |
| String aName; |
| SbxObjectRef xWrapper = (SbxObject*)new SbUnoObject( aName, aAny ); |
| pElem->PutObject( xWrapper ); |
| } |
| else |
| { |
| pElem->PutObject( NULL ); |
| } |
| } |
| } |
| else |
| { |
| rtl::OUString sDefaultMethod; |
| |
| Reference< XDefaultMethod > xDfltMethod( x, UNO_QUERY ); |
| |
| if ( xDfltMethod.is() ) |
| sDefaultMethod = xDfltMethod->getDefaultMethodName(); |
| else if( xIndexAccess.is() ) |
| sDefaultMethod = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "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, 0.Parameter zu NULL setzen, damit sich Var nicht selbst haelt |
| 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; |
| } |
| |
| // Laden eines Elements aus der Runtime-Library (+StringID+Typ) |
| |
| void SbiRuntime::StepRTL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) |
| { |
| PushVar( FindElement( rBasic.pRtl, nOp1, nOp2, SbERR_PROC_UNDEFINED, sal_False ) ); |
| } |
| |
| void |
| SbiRuntime::StepFIND_Impl( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt32 nOp2, SbError nNotFound, sal_Bool bLocal, sal_Bool bStatic ) |
| { |
| if( !refLocals ) |
| refLocals = new SbxArray; |
| PushVar( FindElement( pObj, nOp1, nOp2, nNotFound, bLocal, bStatic ) ); |
| } |
| // Laden einer lokalen/globalen Variablen (+StringID+Typ) |
| |
| void SbiRuntime::StepFIND( sal_uInt32 nOp1, sal_uInt32 nOp2 ) |
| { |
| StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, sal_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, sal_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, sal_True, sal_True ); |
| } |
| |
| // Laden eines Objekt-Elements (+StringID+Typ) |
| // Das Objekt liegt auf TOS |
| |
| void SbiRuntime::StepELEM( sal_uInt32 nOp1, sal_uInt32 nOp2 ) |
| { |
| // Liegt auf dem TOS ein Objekt? |
| SbxVariableRef pObjVar = PopVar(); |
| |
| SbxObject* pObj = PTR_CAST(SbxObject,(SbxVariable*) pObjVar); |
| if( !pObj ) |
| { |
| SbxBase* pObjVarObj = pObjVar->GetObject(); |
| pObj = PTR_CAST(SbxObject,pObjVarObj); |
| } |
| |
| // #56368 Bei StepElem Referenz sichern, sonst koennen Objekte |
| // in Qualifizierungsketten wie ActiveComponent.Selection(0).Text |
| // zu fueh die Referenz verlieren |
| // #74254 Jetzt per Liste |
| if( pObj ) |
| SaveRef( (SbxVariable*)pObj ); |
| |
| PushVar( FindElement( pObj, nOp1, nOp2, SbERR_NO_METHOD, sal_False ) ); |
| } |
| |
| // Laden eines Parameters (+Offset+Typ) |
| // Wenn der Datentyp nicht stimmen sollte, eine Kopie anlegen |
| // Der Datentyp SbxEMPTY zeigt an, daa kein Parameter angegeben ist. |
| // Get( 0 ) darf EMPTY sein |
| |
| 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 Missing sauberer loesen |
| 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( String() ); |
| } |
| else |
| p->PutErr( 448 ); // Wie in VB: Error-Code 448 (SbERR_NAMED_NOT_FOUND) |
| |
| refParams->Put( p, iLoop ); |
| iLoop--; |
| } |
| } |
| p = refParams->Get( i ); |
| |
| if( p->GetType() == SbxERROR && ( i ) ) |
| //if( p->GetType() == SbxEMPTY && ( i ) ) |
| { |
| // Wenn ein Parameter fehlt, kann er OPTIONAL sein |
| sal_Bool bOpt = sal_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::static_int_cast< sal_uInt16 >( |
| pParam->nUserData & 0xffff ); |
| if( nDefaultId > 0 ) |
| { |
| String aDefaultStr = pImg->GetString( nDefaultId ); |
| p = new SbxVariable(); |
| p->PutString( aDefaultStr ); |
| refParams->Put( p, i ); |
| } |
| bOpt = sal_True; |
| } |
| } |
| } |
| if( bOpt == sal_False ) |
| Error( SbERR_NOT_OPTIONAL ); |
| } |
| else if( t != SbxVARIANT && (SbxDataType)(p->GetType() & 0x0FFF ) != t ) |
| { |
| SbxVariable* q = new SbxVariable( t ); |
| SaveRef( q ); |
| *q = *p; |
| p = q; |
| } |
| 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 ); |
| } |
| } |
| |
| // Aufruf einer DLL-Prozedur (+StringID+Typ) |
| // Auch hier zeigt das MSB des StringIDs an, dass Argv belegt ist |
| |
| void SbiRuntime::StepCALL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) |
| { |
| String aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ); |
| SbxArray* pArgs = NULL; |
| if( nOp1 & 0x8000 ) |
| pArgs = refArgv; |
| DllCall( aName, aLibName, pArgs, (SbxDataType) nOp2, sal_False ); |
| aLibName = String(); |
| if( nOp1 & 0x8000 ) |
| PopArgv(); |
| } |
| |
| // Aufruf einer DLL-Prozedur nach CDecl (+StringID+Typ) |
| // Auch hier zeigt das MSB des StringIDs an, dass Argv belegt ist |
| |
| void SbiRuntime::StepCALLC( sal_uInt32 nOp1, sal_uInt32 nOp2 ) |
| { |
| String aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ); |
| SbxArray* pArgs = NULL; |
| if( nOp1 & 0x8000 ) |
| pArgs = refArgv; |
| DllCall( aName, aLibName, pArgs, (SbxDataType) nOp2, sal_True ); |
| aLibName = String(); |
| if( nOp1 & 0x8000 ) |
| PopArgv(); |
| } |
| |
| |
| // Beginn eines Statements (+Line+Col) |
| |
| void SbiRuntime::StepSTMNT( sal_uInt32 nOp1, sal_uInt32 nOp2 ) |
| { |
| // Wenn der Expr-Stack am Anfang einen Statements eine Variable enthaelt, |
| // hat ein Trottel X als Funktion aufgerufen, obwohl es eine Variable ist! |
| sal_Bool bFatalExpr = sal_False; |
| String sUnknownMethodName; |
| if( nExprLvl > 1 ) |
| bFatalExpr = sal_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 = sal_True; |
| } |
| } |
| // Der Expr-Stack ist nun nicht mehr notwendig |
| ClearExprStack(); |
| |
| // #56368 Kuenstliche Referenz fuer StepElem wieder freigeben, |
| // damit sie nicht ueber ein Statement hinaus erhalten bleibt |
| //refSaveObj = NULL; |
| // #74254 Jetzt per Liste |
| ClearRefs(); |
| |
| // Wir muessen hier hart abbrechen, da sonst Zeile und Spalte nicht mehr |
| // stimmen! |
| if( bFatalExpr) |
| { |
| StarBASIC::FatalError( SbERR_NO_METHOD, sUnknownMethodName ); |
| return; |
| } |
| pStmnt = pCode - 9; |
| sal_uInt16 nOld = nLine; |
| nLine = static_cast<short>( nOp1 ); |
| |
| // #29955 & 0xFF, um for-Schleifen-Ebene wegzufiltern |
| nCol1 = static_cast<short>( nOp2 & 0xFF ); |
| |
| // Suchen des naechsten STMNT-Befehls, |
| // um die End-Spalte dieses Statements zu setzen |
| // Searches of the next STMNT instruction, |
| // around the final column of this statement to set |
| |
| nCol2 = 0xffff; |
| sal_uInt16 n1, n2; |
| const sal_uInt8* p = pMod->FindNextStmnt( pCode, n1, n2 ); |
| if( p ) |
| { |
| if( n1 == nOp1 ) |
| { |
| // #29955 & 0xFF, um for-Schleifen-Ebene wegzufiltern |
| nCol2 = (n2 & 0xFF) - 1; |
| } |
| } |
| |
| // #29955 for-Schleifen-Ebene korrigieren, #67452 NICHT im Error-Handler sonst Chaos |
| if( !bInError ) |
| { |
| // (Bei Sprüngen aus Schleifen tritt hier eine Differenz auf) |
| sal_uInt16 nExspectedForLevel = static_cast<sal_uInt16>( nOp2 / 0x100 ); |
| if( pGosubStk ) |
| nExspectedForLevel = nExspectedForLevel + pGosubStk->nStartForLvl; |
| |
| // Wenn der tatsaechliche For-Level zu klein ist, wurde aus |
| // einer Schleife heraus gesprungen -> korrigieren |
| while( nForLvl > nExspectedForLevel ) |
| PopFor(); |
| } |
| |
| // 16.10.96: #31460 Neues Konzept fuer StepInto/Over/Out |
| // Erklärung siehe bei _ImplGetBreakCallLevel. |
| if( pInst->nCallLvl <= pInst->nBreakCallLvl ) |
| //if( nFlags & SbDEBUG_STEPINTO ) |
| { |
| StarBASIC* pStepBasic = GetCurrentBasic( &rBasic ); |
| sal_uInt16 nNewFlags = pStepBasic->StepPoint( nLine, nCol1, nCol2 ); |
| |
| // Neuen BreakCallLevel ermitteln |
| pInst->CalcBreakCallLevel( nNewFlags ); |
| } |
| |
| // Breakpoints nur bei STMNT-Befehlen in neuer Zeile! |
| 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 ); |
| |
| // Neuen BreakCallLevel ermitteln |
| pInst->CalcBreakCallLevel( nNewFlags ); |
| //16.10.96, ALT: |
| //if( nNewFlags != SbDEBUG_CONTINUE ) |
| // nFlags = nNewFlags; |
| } |
| } |
| |
| // (+SvStreamFlags+Flags) |
| // Stack: Blocklaenge |
| // Kanalnummer |
| // Dateiname |
| |
| 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(); |
| ByteString aName( pName->GetString(), gsl_getSystemTextEncoding() ); |
| pIosys->Open( nChan, aName, static_cast<short>( nOp1 ), |
| static_cast<short>( nOp2 ), nBlkLen ); |
| Error( pIosys->GetError() ); |
| } |
| |
| // Objekt kreieren (+StringID+StringID) |
| |
| void SbiRuntime::StepCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 ) |
| { |
| String aClass( pImg->GetString( static_cast<short>( nOp2 ) ) ); |
| SbxObject *pObj = SbxBase::CreateObject( aClass ); |
| if( !pObj ) |
| Error( SbERR_INVALID_OBJECT ); |
| else |
| { |
| String aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); |
| pObj->SetName( aName ); |
| // Das Objekt muss BASIC rufen koennen |
| 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 Objekt-Array kreieren (+StringID+StringID), DCREATE == Dim-Create |
| void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) |
| { |
| SbxVariableRef refVar = PopVar(); |
| |
| DimImpl( refVar ); |
| |
| // Das Array mit Instanzen der geforderten Klasse fuellen |
| 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; |
| |
| // Dimensionen auswerten |
| short nDims = pArray->GetDims(); |
| sal_Int32 nTotalSize = 0; |
| |
| // es muss ein eindimensionales Array sein |
| 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; |
| } |
| |
| // Objekte anlegen und ins Array eintragen |
| String 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 |
| { |
| String aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); |
| pClassObj->SetName( aName ); |
| // Das Objekt muss BASIC rufen koennen |
| 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; |
| sal_Bool bRangeError = sal_False; |
| |
| // Store dims to use them for copying later |
| sal_Int32* pLowerBounds = new sal_Int32[nDims]; |
| sal_Int32* pUpperBounds = new sal_Int32[nDims]; |
| sal_Int32* pActualIndices = new sal_Int32[nDims]; |
| if( nDimsOld != nDimsNew ) |
| { |
| bRangeError = sal_True; |
| } |
| else |
| { |
| // Compare bounds |
| for( short i = 1 ; i <= nDims ; i++ ) |
| { |
| sal_Int32 lBoundNew, uBoundNew; |
| sal_Int32 lBoundOld, uBoundOld; |
| 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; |
| } |
| } |
| |
| // Objekt aus User-Type kreieren (+StringID+StringID) |
| |
| SbxObject* createUserTypeImpl( const String& rClassName ); // sb.cxx |
| |
| void SbiRuntime::StepTCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 ) |
| { |
| String aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); |
| String 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 |
| String aStr; |
| aStr.Fill( nCount, 0 ); |
| pVar->PutString( aStr ); |
| } |
| |
| bool bVarToDim = ((nOp2 & SBX_TYPE_VAR_TO_DIM_FLAG) != 0); |
| if( bVarToDim ) |
| pVar->SetFlag( SBX_VAR_TO_DIM ); |
| } |
| |
| // Einrichten einer lokalen Variablen (+StringID+Typ) |
| |
| void SbiRuntime::StepLOCAL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) |
| { |
| if( !refLocals.Is() ) |
| refLocals = new SbxArray; |
| String 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() ); |
| } |
| } |
| |
| // Einrichten einer modulglobalen Variablen (+StringID+Typ) |
| |
| void SbiRuntime::StepPUBLIC_Impl( sal_uInt32 nOp1, sal_uInt32 nOp2, bool bUsedForClassModule ) |
| { |
| String 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 ); |
| // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden' |
| 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 ); |
| } |
| } |
| |
| // Einrichten einer globalen Variablen (+StringID+Typ) |
| |
| void SbiRuntime::StepGLOBAL( sal_uInt32 nOp1, sal_uInt32 nOp2 ) |
| { |
| if( pImg->GetFlag( SBIMG_CLASSMODULE ) ) |
| StepPUBLIC_Impl( nOp1, nOp2, true ); |
| |
| String 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 ); |
| // AB: 2.7.1996: HACK wegen 'Referenz kann nicht gesichert werden' |
| 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; |
| String aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) ); |
| |
| SbxVariable* pDummyVar = new SbxVariable( t ); |
| pDummyVar->SetName( aName ); |
| PushVar( pDummyVar ); |
| } |
| } |
| |
| |
| SbxVariable* SbiRuntime::StepSTATIC_Impl( String& 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; |
| } |
| // Einrichten einer statischen Variablen (+StringID+Typ) |
| void SbiRuntime::StepSTATIC( sal_uInt32 nOp1, sal_uInt32 nOp2 ) |
| { |
| String aName( pImg->GetString( static_cast<short>( nOp1 ) ) ); |
| SbxDataType t = (SbxDataType) nOp2; |
| StepSTATIC_Impl( aName, t ); |
| } |
| |