1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: step0.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_basic.hxx"
33 #include <vcl/msgbox.hxx>
34 #include <tools/fsys.hxx>
36 #include "errobject.hxx"
37 #include "runtime.hxx"
38 #include "sbintern.hxx"
42 #include "sbunoobj.hxx"
44 #include <com/sun/star/uno/Any.hxx>
45 #include <com/sun/star/util/SearchOptions.hdl>
46 #include <vcl/svapp.hxx>
47 #include <unotools/textsearch.hxx>
51 // for a patch forward declaring these methods below makes sense
52 // but, #FIXME lets really just move the methods to the top
53 void lcl_clearImpl( SbxVariableRef
& refVar
, SbxDataType
& eType
);
54 void lcl_eraseImpl( SbxVariableRef
& refVar
, bool bVBAEnabled
);
56 SbxVariable
* getDefaultProp( SbxVariable
* pRef
);
58 void SbiRuntime::StepNOP()
61 void SbiRuntime::StepArith( SbxOperator eOp
)
63 SbxVariableRef p1
= PopVar();
65 SbxVariable
* p2
= GetTOS();
67 p2
->ResetFlag( SBX_FIXED
);
68 p2
->Compute( eOp
, *p1
);
70 checkArithmeticOverflow( p2
);
73 void SbiRuntime::StepUnary( SbxOperator eOp
)
76 SbxVariable
* p
= GetTOS();
77 p
->Compute( eOp
, *p
);
80 void SbiRuntime::StepCompare( SbxOperator eOp
)
82 SbxVariableRef p1
= PopVar();
83 SbxVariableRef p2
= PopVar();
85 // Make sure objects with default params have
86 // values ( and type ) set as appropriate
87 SbxDataType p1Type
= p1
->GetType();
88 SbxDataType p2Type
= p2
->GetType();
89 if ( p1Type
== SbxEMPTY
)
91 p1
->Broadcast( SBX_HINT_DATAWANTED
);
92 p1Type
= p1
->GetType();
94 if ( p2Type
== SbxEMPTY
)
96 p2
->Broadcast( SBX_HINT_DATAWANTED
);
97 p2Type
= p2
->GetType();
99 if ( p1Type
== p2Type
)
101 // if both sides are an object and have default props
102 // then we need to use the default props
103 // we don't need to worry if only one side ( lhs, rhs ) is an
104 // object ( object side will get coerced to correct type in
106 if ( p1Type
== SbxOBJECT
)
108 SbxVariable
* pDflt
= getDefaultProp( p1
);
112 p1
->Broadcast( SBX_HINT_DATAWANTED
);
114 pDflt
= getDefaultProp( p2
);
118 p2
->Broadcast( SBX_HINT_DATAWANTED
);
124 static SbxVariable
* pTRUE
= NULL
;
125 static SbxVariable
* pFALSE
= NULL
;
126 static SbxVariable
* pNULL
= NULL
;
127 // why do this on non-windows ?
128 // why do this at all ?
129 // I dumbly follow the pattern :-/
130 if ( bVBAEnabled
&& ( p1
->IsNull() || p2
->IsNull() ) )
134 pNULL
= new SbxVariable
;
140 else if( p2
->Compare( eOp
, *p1
) )
144 pTRUE
= new SbxVariable
;
145 pTRUE
->PutBool( TRUE
);
154 pFALSE
= new SbxVariable
;
155 pFALSE
->PutBool( FALSE
);
161 SbxVariable
* pRes
= new SbxVariable
;
162 if ( bVBAEnabled
&& ( p1
->IsNull() || p2
->IsNull() ) )
166 BOOL bRes
= p2
->Compare( eOp
, *p1
);
167 pRes
->PutBool( bRes
);
173 void SbiRuntime::StepEXP() { StepArith( SbxEXP
); }
174 void SbiRuntime::StepMUL() { StepArith( SbxMUL
); }
175 void SbiRuntime::StepDIV() { StepArith( SbxDIV
); }
176 void SbiRuntime::StepIDIV() { StepArith( SbxIDIV
); }
177 void SbiRuntime::StepMOD() { StepArith( SbxMOD
); }
178 void SbiRuntime::StepPLUS() { StepArith( SbxPLUS
); }
179 void SbiRuntime::StepMINUS() { StepArith( SbxMINUS
); }
180 void SbiRuntime::StepCAT() { StepArith( SbxCAT
); }
181 void SbiRuntime::StepAND() { StepArith( SbxAND
); }
182 void SbiRuntime::StepOR() { StepArith( SbxOR
); }
183 void SbiRuntime::StepXOR() { StepArith( SbxXOR
); }
184 void SbiRuntime::StepEQV() { StepArith( SbxEQV
); }
185 void SbiRuntime::StepIMP() { StepArith( SbxIMP
); }
187 void SbiRuntime::StepNEG() { StepUnary( SbxNEG
); }
188 void SbiRuntime::StepNOT() { StepUnary( SbxNOT
); }
190 void SbiRuntime::StepEQ() { StepCompare( SbxEQ
); }
191 void SbiRuntime::StepNE() { StepCompare( SbxNE
); }
192 void SbiRuntime::StepLT() { StepCompare( SbxLT
); }
193 void SbiRuntime::StepGT() { StepCompare( SbxGT
); }
194 void SbiRuntime::StepLE() { StepCompare( SbxLE
); }
195 void SbiRuntime::StepGE() { StepCompare( SbxGE
); }
199 bool NeedEsc(sal_Unicode cCode
)
201 String
sEsc(RTL_CONSTASCII_USTRINGPARAM(".^$+\\|{}()"));
202 return (STRING_NOTFOUND
!= sEsc
.Search(cCode
));
205 String
VBALikeToRegexp(const String
&rIn
)
208 const sal_Unicode
*start
= rIn
.GetBuffer();
209 const sal_Unicode
*end
= start
+ rIn
.Len();
224 sResult
.Append(String(RTL_CONSTASCII_USTRINGPARAM(".*")));
228 sResult
.Append(String(RTL_CONSTASCII_USTRINGPARAM("[0-9]")));
232 sResult
.Append('\\');
233 sResult
.Append(*start
++);
236 sResult
.Append(*start
++);
238 while (start
< end
&& !seenright
)
245 sResult
.Append('\\');
246 sResult
.Append(*start
);
249 sResult
.Append(*start
);
257 sResult
.Append('\\');
258 sResult
.Append(*start
);
266 sResult
.Append('\\');
267 sResult
.Append(*start
++);
277 void SbiRuntime::StepLIKE()
279 SbxVariableRef refVar1
= PopVar();
280 SbxVariableRef refVar2
= PopVar();
282 String pattern
= VBALikeToRegexp(refVar1
->GetString());
283 String value
= refVar2
->GetString();
285 com::sun::star::util::SearchOptions aSearchOpt
;
287 aSearchOpt
.algorithmType
= com::sun::star::util::SearchAlgorithms_REGEXP
;
289 aSearchOpt
.Locale
= Application::GetSettings().GetLocale();
290 aSearchOpt
.searchString
= pattern
;
293 bool bCompatibility
= ( pINST
&& pINST
->IsCompatibility() );
295 bTextMode
= GetImageFlag( SBIMG_COMPARETEXT
);
298 aSearchOpt
.transliterateFlags
|= com::sun::star::i18n::TransliterationModules_IGNORE_CASE
;
300 SbxVariable
* pRes
= new SbxVariable
;
301 utl::TextSearch
aSearch(aSearchOpt
);
302 xub_StrLen nStart
=0, nEnd
=value
.Len();
303 int bRes
= aSearch
.SearchFrwrd(value
, &nStart
, &nEnd
);
304 pRes
->PutBool( bRes
!= 0 );
309 // TOS und TOS-1 sind beides Objektvariable und enthalten den selben Pointer
311 void SbiRuntime::StepIS()
313 SbxVariableRef refVar1
= PopVar();
314 SbxVariableRef refVar2
= PopVar();
316 refVar1
->GetType() == SbxOBJECT
317 && refVar2
->GetType() == SbxOBJECT
);
318 if ( bVBAEnabled
&& !bRes
)
319 Error( SbERR_INVALID_USAGE_OBJECT
);
320 bRes
= ( bRes
&& refVar1
->GetObject() == refVar2
->GetObject() );
321 SbxVariable
* pRes
= new SbxVariable
;
322 pRes
->PutBool( bRes
);
326 // Aktualisieren des Wertes von TOS
328 void SbiRuntime::StepGET()
330 SbxVariable
* p
= GetTOS();
331 p
->Broadcast( SBX_HINT_DATAWANTED
);
334 // #67607 Uno-Structs kopieren
335 inline void checkUnoStructCopy( SbxVariableRef
& refVal
, SbxVariableRef
& refVar
)
337 SbxDataType eVarType
= refVar
->GetType();
338 if( eVarType
!= SbxOBJECT
)
341 SbxObjectRef xValObj
= (SbxObject
*)refVal
->GetObject();
342 if( !xValObj
.Is() || xValObj
->ISA(SbUnoAnyObject
) )
345 // #115826: Exclude ProcedureProperties to avoid call to Property Get procedure
346 if( refVar
->ISA(SbProcedureProperty
) )
349 SbxObjectRef xVarObj
= (SbxObject
*)refVar
->GetObject();
350 SbxDataType eValType
= refVal
->GetType();
351 if( eValType
== SbxOBJECT
&& xVarObj
== xValObj
)
353 SbUnoObject
* pUnoObj
= PTR_CAST(SbUnoObject
,(SbxObject
*)xVarObj
);
356 Any aAny
= pUnoObj
->getUnoAny();
357 if( aAny
.getValueType().getTypeClass() == TypeClass_STRUCT
)
359 SbUnoObject
* pNewUnoObj
= new SbUnoObject( pUnoObj
->GetName(), aAny
);
360 // #70324: ClassName uebernehmen
361 pNewUnoObj
->SetClassName( pUnoObj
->GetClassName() );
362 refVar
->PutObject( pNewUnoObj
);
369 // Ablage von TOS in TOS-1
371 void SbiRuntime::StepPUT()
373 SbxVariableRef refVal
= PopVar();
374 SbxVariableRef refVar
= PopVar();
375 // Store auf die eigene Methode (innerhalb einer Function)?
376 BOOL bFlagsChanged
= FALSE
;
378 if( (SbxVariable
*) refVar
== (SbxVariable
*) pMeth
)
380 bFlagsChanged
= TRUE
;
381 n
= refVar
->GetFlags();
382 refVar
->SetFlag( SBX_WRITE
);
385 // if left side arg is an object or variant and right handside isn't
386 // either an object or a variant then try and see if a default
388 // to use e.g. Range{"A1") = 34
389 // could equate to Range("A1").Value = 34
392 if ( refVar
->GetType() == SbxOBJECT
)
394 SbxVariable
* pDflt
= getDefaultProp( refVar
);
398 if ( refVal
->GetType() == SbxOBJECT
)
400 SbxVariable
* pDflt
= getDefaultProp( refVal
);
407 // lhs is a property who's value is currently null
408 if ( !bVBAEnabled
|| ( bVBAEnabled
&& refVar
->GetType() != SbxEMPTY
) )
409 // #67607 Uno-Structs kopieren
410 checkUnoStructCopy( refVal
, refVar
);
412 refVar
->SetFlags( n
);
416 // Speichern Objektvariable
417 // Nicht-Objekt-Variable fuehren zu Fehlern
419 void SbiRuntime::StepSET_Impl( SbxVariableRef
& refVal
, SbxVariableRef
& refVar
, bool bHandleDefaultProp
)
421 // #67733 Typen mit Array-Flag sind auch ok
422 SbxDataType eValType
= refVal
->GetType();
423 SbxDataType eVarType
= refVar
->GetType();
424 if( (eValType
!= SbxOBJECT
425 && eValType
!= SbxEMPTY
426 // seems like when using the default method its possible for objects
427 // to be empty ( no broadcast has taken place yet ) or the actual value is
429 && !bHandleDefaultProp
430 && !(eValType
& SbxARRAY
)) ||
431 (eVarType
!= SbxOBJECT
432 && eVarType
!= SbxEMPTY
433 && !bHandleDefaultProp
434 && !(eVarType
& SbxARRAY
) ) )
436 Error( SbERR_INVALID_USAGE_OBJECT
);
440 // Getting in here causes problems with objects with default properties
441 // if they are SbxEMPTY I guess
442 if ( !bHandleDefaultProp
|| ( bHandleDefaultProp
&& refVal
->GetType() == SbxOBJECT
) )
444 // Auf refVal GetObject fuer Collections ausloesen
445 SbxBase
* pObjVarObj
= refVal
->GetObject();
448 SbxVariableRef refObjVal
= PTR_CAST(SbxObject
,pObjVarObj
);
450 // #67733 Typen mit Array-Flag sind auch ok
453 else if( !(eValType
& SbxARRAY
) )
458 // #52896 Wenn Uno-Sequences bzw. allgemein Arrays einer als
459 // Object deklarierten Variable zugewiesen werden, kann hier
460 // refVal ungueltig sein!
463 Error( SbERR_INVALID_USAGE_OBJECT
);
467 // Store auf die eigene Methode (innerhalb einer Function)?
468 BOOL bFlagsChanged
= FALSE
;
470 if( (SbxVariable
*) refVar
== (SbxVariable
*) pMeth
)
472 bFlagsChanged
= TRUE
;
473 n
= refVar
->GetFlags();
474 refVar
->SetFlag( SBX_WRITE
);
476 SbProcedureProperty
* pProcProperty
= PTR_CAST(SbProcedureProperty
,(SbxVariable
*)refVar
);
478 pProcProperty
->setSet( true );
480 if ( bHandleDefaultProp
)
482 // get default properties for lhs & rhs where necessary
483 // SbxVariable* defaultProp = NULL; unused variable
484 bool bLHSHasDefaultProp
= false;
485 // LHS try determine if a default prop exists
486 if ( refVar
->GetType() == SbxOBJECT
)
488 SbxVariable
* pDflt
= getDefaultProp( refVar
);
492 bLHSHasDefaultProp
= true;
495 // RHS only get a default prop is the rhs has one
496 if ( refVal
->GetType() == SbxOBJECT
)
498 // check if lhs is a null object
499 // if it is then use the object not the default property
500 SbxObject
* pObj
= NULL
;
503 pObj
= PTR_CAST(SbxObject
,(SbxVariable
*)refVar
);
505 // calling GetObject on a SbxEMPTY variable raises
506 // object not set errors, make sure its an Object
507 if ( !pObj
&& refVar
->GetType() == SbxOBJECT
)
509 SbxBase
* pObjVarObj
= refVar
->GetObject();
510 pObj
= PTR_CAST(SbxObject
,pObjVarObj
);
512 SbxVariable
* pDflt
= NULL
;
513 if ( pObj
|| bLHSHasDefaultProp
)
514 // lhs is either a valid object || or has a defaultProp
515 pDflt
= getDefaultProp( refVal
);
523 // lhs is a property who's value is currently (Empty e.g. no broadcast yet)
524 // in this case if there is a default prop involved the value of the
525 // default property may infact be void so the type will also be SbxEMPTY
526 // in this case we do not want to call checkUnoStructCopy 'cause that will
527 // cause an error also
528 if ( !bHandleDefaultProp
|| ( bHandleDefaultProp
&& ( refVar
->GetType() != SbxEMPTY
) ) )
529 // #67607 Uno-Structs kopieren
530 checkUnoStructCopy( refVal
, refVar
);
532 refVar
->SetFlags( n
);
537 void SbiRuntime::StepSET()
539 SbxVariableRef refVal
= PopVar();
540 SbxVariableRef refVar
= PopVar();
541 StepSET_Impl( refVal
, refVar
, bVBAEnabled
); // this is really assigment
544 void SbiRuntime::StepVBASET()
546 SbxVariableRef refVal
= PopVar();
547 SbxVariableRef refVar
= PopVar();
548 // don't handle default property
549 StepSET_Impl( refVal
, refVar
, false ); // set obj = something
554 void SbiRuntime::StepLSET()
556 SbxVariableRef refVal
= PopVar();
557 SbxVariableRef refVar
= PopVar();
558 if( refVar
->GetType() != SbxSTRING
559 || refVal
->GetType() != SbxSTRING
)
560 Error( SbERR_INVALID_USAGE_OBJECT
);
563 // Store auf die eigene Methode (innerhalb einer Function)?
564 USHORT n
= refVar
->GetFlags();
565 if( (SbxVariable
*) refVar
== (SbxVariable
*) pMeth
)
566 refVar
->SetFlag( SBX_WRITE
);
567 String aRefVarString
= refVar
->GetString();
568 String aRefValString
= refVal
->GetString();
570 USHORT nVarStrLen
= aRefVarString
.Len();
571 USHORT nValStrLen
= aRefValString
.Len();
573 if( nVarStrLen
> nValStrLen
)
575 aRefVarString
.Fill(nVarStrLen
,' ');
576 aNewStr
= aRefValString
.Copy( 0, nValStrLen
);
577 aNewStr
+= aRefVarString
.Copy( nValStrLen
, nVarStrLen
- nValStrLen
);
581 aNewStr
= aRefValString
.Copy( 0, nVarStrLen
);
584 refVar
->PutString( aNewStr
);
585 refVar
->SetFlags( n
);
590 void SbiRuntime::StepRSET()
592 SbxVariableRef refVal
= PopVar();
593 SbxVariableRef refVar
= PopVar();
594 if( refVar
->GetType() != SbxSTRING
595 || refVal
->GetType() != SbxSTRING
)
596 Error( SbERR_INVALID_USAGE_OBJECT
);
599 // Store auf die eigene Methode (innerhalb einer Function)?
600 USHORT n
= refVar
->GetFlags();
601 if( (SbxVariable
*) refVar
== (SbxVariable
*) pMeth
)
602 refVar
->SetFlag( SBX_WRITE
);
603 String aRefVarString
= refVar
->GetString();
604 String aRefValString
= refVal
->GetString();
607 USHORT nVarStrLen
= aRefVarString
.Len();
608 if( nVarStrLen
> aRefValString
.Len() )
610 aRefVarString
.Fill(nVarStrLen
,' ');
611 nPos
= nVarStrLen
- aRefValString
.Len();
613 aRefVarString
= aRefVarString
.Copy( 0, nPos
);
614 aRefVarString
+= aRefValString
.Copy( 0, nVarStrLen
- nPos
);
615 refVar
->PutString(aRefVarString
);
617 refVar
->SetFlags( n
);
621 // Ablage von TOS in TOS-1, dann ReadOnly-Bit setzen
623 void SbiRuntime::StepPUTC()
625 SbxVariableRef refVal
= PopVar();
626 SbxVariableRef refVar
= PopVar();
627 refVar
->SetFlag( SBX_WRITE
);
629 refVar
->ResetFlag( SBX_WRITE
);
630 refVar
->SetFlag( SBX_CONST
);
634 // TOS = Variable fuer das Array mit Dimensionsangaben als Parameter
636 void SbiRuntime::StepDIM()
638 SbxVariableRef refVar
= PopVar();
642 // #56204 DIM-Funktionalitaet in Hilfsmethode auslagern (step0.cxx)
643 void SbiRuntime::DimImpl( SbxVariableRef refVar
)
645 // If refDim then this DIM statement is terminating a ReDIM and
646 // previous StepERASE_CLEAR for an array, the following actions have
647 // been delayed from ( StepERASE_CLEAR ) 'till here
650 if ( !refRedimpArray
) // only erase the array not ReDim Preserve
651 lcl_eraseImpl( refVar
, bVBAEnabled
);
652 SbxDataType eType
= refVar
->GetType();
653 lcl_clearImpl( refVar
, eType
);
656 SbxArray
* pDims
= refVar
->GetParameters();
657 // Muss eine gerade Anzahl Argumente haben
658 // Man denke daran, dass Arg[0] nicht zaehlt!
659 if( pDims
&& !( pDims
->Count() & 1 ) )
660 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
663 SbxDataType eType
= refVar
->IsFixed() ? refVar
->GetType() : SbxVARIANT
;
664 SbxDimArray
* pArray
= new SbxDimArray( eType
);
665 // AB 2.4.1996, auch Arrays ohne Dimensionsangaben zulassen (VB-komp.)
668 for( USHORT i
= 1; i
< pDims
->Count(); )
670 INT32 lb
= pDims
->Get( i
++ )->GetLong();
671 INT32 ub
= pDims
->Get( i
++ )->GetLong();
673 Error( SbERR_OUT_OF_RANGE
), ub
= lb
;
674 pArray
->AddDim32( lb
, ub
);
676 pArray
->setHasFixedSize( true );
681 // #62867 Beim Anlegen eines Arrays der Laenge 0 wie bei
682 // Uno-Sequences der Laenge 0 eine Dimension anlegen
683 pArray
->unoAddDim( 0, -1 );
685 USHORT nSavFlags
= refVar
->GetFlags();
686 refVar
->ResetFlag( SBX_FIXED
);
687 refVar
->PutObject( pArray
);
688 refVar
->SetFlags( nSavFlags
);
689 refVar
->SetParameters( NULL
);
694 // TOS = Variable fuer das Array
695 // argv = Dimensionsangaben
697 void SbiRuntime::StepREDIM()
699 // Im Moment ist es nichts anderes als Dim, da doppeltes Dim
700 // bereits vom Compiler erkannt wird.
705 // Helper function for StepREDIMP
706 void implCopyDimArray( SbxDimArray
* pNewArray
, SbxDimArray
* pOldArray
, short nMaxDimIndex
,
707 short nActualDim
, sal_Int32
* pActualIndices
, sal_Int32
* pLowerBounds
, sal_Int32
* pUpperBounds
)
709 sal_Int32
& ri
= pActualIndices
[nActualDim
];
710 for( ri
= pLowerBounds
[nActualDim
] ; ri
<= pUpperBounds
[nActualDim
] ; ri
++ )
712 if( nActualDim
< nMaxDimIndex
)
714 implCopyDimArray( pNewArray
, pOldArray
, nMaxDimIndex
, nActualDim
+ 1,
715 pActualIndices
, pLowerBounds
, pUpperBounds
);
719 SbxVariable
* pSource
= pOldArray
->Get32( pActualIndices
);
720 SbxVariable
* pDest
= pNewArray
->Get32( pActualIndices
);
721 if( pSource
&& pDest
)
728 // TOS = Variable fuer das Array
729 // argv = Dimensionsangaben
731 void SbiRuntime::StepREDIMP()
733 SbxVariableRef refVar
= PopVar();
736 // Now check, if we can copy from the old array
737 if( refRedimpArray
.Is() )
739 SbxBase
* pElemObj
= refVar
->GetObject();
740 SbxDimArray
* pNewArray
= PTR_CAST(SbxDimArray
,pElemObj
);
741 SbxDimArray
* pOldArray
= (SbxDimArray
*)(SbxArray
*)refRedimpArray
;
744 short nDimsNew
= pNewArray
->GetDims();
745 short nDimsOld
= pOldArray
->GetDims();
746 short nDims
= nDimsNew
;
747 BOOL bRangeError
= FALSE
;
749 // Store dims to use them for copying later
750 sal_Int32
* pLowerBounds
= new sal_Int32
[nDims
];
751 sal_Int32
* pUpperBounds
= new sal_Int32
[nDims
];
752 sal_Int32
* pActualIndices
= new sal_Int32
[nDims
];
754 if( nDimsOld
!= nDimsNew
)
761 for( short i
= 1 ; i
<= nDims
; i
++ )
763 sal_Int32 lBoundNew
, uBoundNew
;
764 sal_Int32 lBoundOld
, uBoundOld
;
765 pNewArray
->GetDim32( i
, lBoundNew
, uBoundNew
);
766 pOldArray
->GetDim32( i
, lBoundOld
, uBoundOld
);
768 /* #69094 Allow all dimensions to be changed
769 although Visual Basic is not able to do so.
770 // All bounds but the last have to be the same
771 if( i < nDims && ( lBoundNew != lBoundOld || uBoundNew != uBoundOld ) )
779 // #69094: if( i == nDims )
781 lBoundNew
= std::max( lBoundNew
, lBoundOld
);
782 uBoundNew
= std::min( uBoundNew
, uBoundOld
);
785 pActualIndices
[j
] = pLowerBounds
[j
] = lBoundNew
;
786 pUpperBounds
[j
] = uBoundNew
;
793 StarBASIC::Error( SbERR_OUT_OF_RANGE
);
797 // Copy data from old array by going recursively through all dimensions
798 // (It would be faster to work on the flat internal data array of an
799 // SbyArray but this solution is clearer and easier)
800 implCopyDimArray( pNewArray
, pOldArray
, nDims
- 1,
801 0, pActualIndices
, pLowerBounds
, pUpperBounds
);
804 delete[] pUpperBounds
;
805 delete[] pLowerBounds
;
806 delete[] pActualIndices
;
807 refRedimpArray
= NULL
;
811 //StarBASIC::FatalError( SbERR_NOT_IMPLEMENTED );
815 // TOS = Array-Variable, Reference to array is copied
816 // Variable is cleared as in ERASE
818 void SbiRuntime::StepREDIMP_ERASE()
820 SbxVariableRef refVar
= PopVar();
822 SbxDataType eType
= refVar
->GetType();
823 if( eType
& SbxARRAY
)
825 SbxBase
* pElemObj
= refVar
->GetObject();
826 SbxDimArray
* pDimArray
= PTR_CAST(SbxDimArray
,pElemObj
);
829 refRedimpArray
= pDimArray
;
834 if( refVar
->IsFixed() )
837 refVar
->SetType( SbxEMPTY
);
840 void lcl_clearImpl( SbxVariableRef
& refVar
, SbxDataType
& eType
)
842 USHORT nSavFlags
= refVar
->GetFlags();
843 refVar
->ResetFlag( SBX_FIXED
);
844 refVar
->SetType( SbxDataType(eType
& 0x0FFF) );
845 refVar
->SetFlags( nSavFlags
);
849 void lcl_eraseImpl( SbxVariableRef
& refVar
, bool bVBAEnabled
)
851 SbxDataType eType
= refVar
->GetType();
852 if( eType
& SbxARRAY
)
856 SbxBase
* pElemObj
= refVar
->GetObject();
857 SbxDimArray
* pDimArray
= PTR_CAST(SbxDimArray
,pElemObj
);
858 bool bClearValues
= true;
861 if ( pDimArray
->hasFixedSize() )
863 // Clear all Value(s)
864 pDimArray
->SbxArray::Clear();
865 bClearValues
= false;
868 pDimArray
->Clear(); // clear Dims
872 SbxArray
* pArray
= PTR_CAST(SbxArray
,pElemObj
);
879 // Arrays haben bei Erase nach VB ein recht komplexes Verhalten. Hier
880 // werden zunaechst nur die Typ-Probleme bei REDIM (#26295) beseitigt:
881 // Typ hart auf den Array-Typ setzen, da eine Variable mit Array
882 // SbxOBJECT ist. Bei REDIM entsteht dann ein SbxOBJECT-Array und
883 // der ursruengliche Typ geht verloren -> Laufzeitfehler
884 lcl_clearImpl( refVar
, eType
);
887 if( refVar
->IsFixed() )
890 refVar
->SetType( SbxEMPTY
);
896 void SbiRuntime::StepERASE()
898 SbxVariableRef refVar
= PopVar();
899 lcl_eraseImpl( refVar
, bVBAEnabled
);
902 void SbiRuntime::StepERASE_CLEAR()
907 void SbiRuntime::StepARRAYACCESS()
910 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
911 SbxVariableRef refVar
= PopVar();
912 refVar
->SetParameters( refArgv
);
914 PushVar( CheckArray( refVar
) );
917 // Einrichten eines Argvs
918 // nOp1 bleibt so -> 1. Element ist Returnwert
920 void SbiRuntime::StepARGC()
923 refArgv
= new SbxArray
;
927 // Speichern eines Arguments in Argv
929 void SbiRuntime::StepARGV()
932 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
935 SbxVariableRef pVal
= PopVar();
937 // Before fix of #94916:
938 // if( pVal->ISA(SbxMethod) || pVal->ISA(SbxProperty) )
939 if( pVal
->ISA(SbxMethod
) || pVal
->ISA(SbUnoProperty
) || pVal
->ISA(SbProcedureProperty
) )
941 // Methoden und Properties evaluieren!
942 SbxVariable
* pRes
= new SbxVariable( *pVal
);
945 refArgv
->Put( pVal
, nArgc
++ );
949 // Input to Variable. Die Variable ist auf TOS und wird
950 // anschliessend entfernt.
952 void SbiRuntime::StepINPUT()
958 while( ( err
= pIosys
->GetError() ) == 0 )
961 if( ch
!= ' ' && ch
!= '\t' && ch
!= '\n' )
966 // Scan until comma or whitespace
967 char sep
= ( ch
== '"' ) ? ch
: 0;
968 if( sep
) ch
= pIosys
->Read();
969 while( ( err
= pIosys
->GetError() ) == 0 )
977 else if( !sep
&& (ch
== ',' || ch
== '\n') )
983 if( ch
== ' ' || ch
== '\t' )
984 while( ( err
= pIosys
->GetError() ) == 0 )
986 if( ch
!= ' ' && ch
!= '\t' && ch
!= '\n' )
993 SbxVariableRef pVar
= GetTOS();
994 // Zuerst versuchen, die Variable mit einem numerischen Wert
995 // zu fuellen, dann mit einem Stringwert
996 if( !pVar
->IsFixed() || pVar
->IsNumeric() )
999 if( !pVar
->Scan( s
, &nLen
) )
1001 err
= SbxBase::GetError();
1002 SbxBase::ResetError();
1004 // Der Wert muss komplett eingescant werden
1005 else if( nLen
!= s
.Len() && !pVar
->PutString( s
) )
1007 err
= SbxBase::GetError();
1008 SbxBase::ResetError();
1010 else if( nLen
!= s
.Len() && pVar
->IsNumeric() )
1012 err
= SbxBase::GetError();
1013 SbxBase::ResetError();
1015 err
= SbERR_CONVERSION
;
1020 pVar
->PutString( s
);
1021 err
= SbxBase::GetError();
1022 SbxBase::ResetError();
1025 if( err
== SbERR_USER_ABORT
)
1029 if( pRestart
&& !pIosys
->GetChannel() )
1031 BasResId
aId( IDS_SBERR_START
+ 4 );
1034 //****** DONT CHECK IN, TEST ONLY *******
1035 //****** DONT CHECK IN, TEST ONLY *******
1036 // ErrorBox( NULL, WB_OK, aMsg ).Execute();
1037 //****** DONT CHECK IN, TEST ONLY *******
1038 //****** DONT CHECK IN, TEST ONLY *******
1047 // pIosys->ResetChannel();
1052 // Line Input to Variable. Die Variable ist auf TOS und wird
1053 // anschliessend entfernt.
1055 void SbiRuntime::StepLINPUT()
1058 pIosys
->Read( aInput
);
1059 Error( pIosys
->GetError() );
1060 SbxVariableRef p
= PopVar();
1061 p
->PutString( String( aInput
, gsl_getSystemTextEncoding() ) );
1062 // pIosys->ResetChannel();
1067 void SbiRuntime::StepSTOP()
1072 // FOR-Variable initialisieren
1074 void SbiRuntime::StepINITFOR()
1079 void SbiRuntime::StepINITFOREACH()
1084 // FOR-Variable inkrementieren
1086 void SbiRuntime::StepNEXT()
1090 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
1093 if( pForStk
->eForType
== FOR_TO
)
1094 pForStk
->refVar
->Compute( SbxPLUS
, *pForStk
->refInc
);
1097 // Anfang CASE: TOS in CASE-Stack
1099 void SbiRuntime::StepCASE()
1101 if( !refCaseStk
.Is() )
1102 refCaseStk
= new SbxArray
;
1103 SbxVariableRef xVar
= PopVar();
1104 refCaseStk
->Put( xVar
, refCaseStk
->Count() );
1107 // Ende CASE: Variable freigeben
1109 void SbiRuntime::StepENDCASE()
1111 if( !refCaseStk
|| !refCaseStk
->Count() )
1112 StarBASIC::FatalError( SbERR_INTERNAL_ERROR
);
1114 refCaseStk
->Remove( refCaseStk
->Count() - 1 );
1117 // Standard-Fehlerbehandlung
1119 void SbiRuntime::StepSTDERROR()
1121 pError
= NULL
; bError
= TRUE
;
1122 pInst
->aErrorMsg
= String();
1126 SbxErrObject::getUnoErrObject()->Clear();
1129 void SbiRuntime::StepNOERROR()
1131 pInst
->aErrorMsg
= String();
1135 SbxErrObject::getUnoErrObject()->Clear();
1141 void SbiRuntime::StepLEAVE()
1144 // If VBA and we are leaving an ErrorHandler then clear the error ( it's been processed )
1145 if ( bInError
&& pError
)
1146 SbxErrObject::getUnoErrObject()->Clear();
1149 void SbiRuntime::StepCHANNEL() // TOS = Kanalnummer
1151 SbxVariableRef pChan
= PopVar();
1152 short nChan
= pChan
->GetInteger();
1153 pIosys
->SetChannel( nChan
);
1154 Error( pIosys
->GetError() );
1157 void SbiRuntime::StepCHANNEL0()
1159 pIosys
->ResetChannel();
1162 void SbiRuntime::StepPRINT() // print TOS
1164 SbxVariableRef p
= PopVar();
1165 String s1
= p
->GetString();
1167 if( p
->GetType() >= SbxINTEGER
&& p
->GetType() <= SbxDOUBLE
)
1168 s
= ' '; // ein Blank davor
1170 ByteString
aByteStr( s
, gsl_getSystemTextEncoding() );
1171 pIosys
->Write( aByteStr
);
1172 Error( pIosys
->GetError() );
1175 void SbiRuntime::StepPRINTF() // print TOS in field
1177 SbxVariableRef p
= PopVar();
1178 String s1
= p
->GetString();
1180 if( p
->GetType() >= SbxINTEGER
&& p
->GetType() <= SbxDOUBLE
)
1181 s
= ' '; // ein Blank davor
1183 s
.Expand( 14, ' ' );
1184 ByteString
aByteStr( s
, gsl_getSystemTextEncoding() );
1185 pIosys
->Write( aByteStr
);
1186 Error( pIosys
->GetError() );
1189 void SbiRuntime::StepWRITE() // write TOS
1191 SbxVariableRef p
= PopVar();
1192 // Muss der String gekapselt werden?
1194 switch (p
->GetType() )
1196 case SbxSTRING
: ch
= '"'; break;
1199 case SbxDATE
: ch
= '#'; break;
1205 s
+= p
->GetString();
1208 ByteString
aByteStr( s
, gsl_getSystemTextEncoding() );
1209 pIosys
->Write( aByteStr
);
1210 Error( pIosys
->GetError() );
1213 void SbiRuntime::StepRENAME() // Rename Tos+1 to Tos
1215 SbxVariableRef pTos1
= PopVar();
1216 SbxVariableRef pTos
= PopVar();
1217 String aDest
= pTos1
->GetString();
1218 String aSource
= pTos
->GetString();
1223 implStepRenameUCB( aSource
, aDest
);
1228 #ifdef _OLD_FILE_IMPL
1229 DirEntry
aSourceDirEntry( aSource
);
1230 if( aSourceDirEntry
.Exists() )
1232 if( aSourceDirEntry
.MoveTo( DirEntry(aDest
) ) != FSYS_ERR_OK
)
1233 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
1236 StarBASIC::Error( SbERR_PATH_NOT_FOUND
);
1238 implStepRenameOSL( aSource
, aDest
);
1245 void SbiRuntime::StepPROMPT()
1247 SbxVariableRef p
= PopVar();
1248 ByteString
aStr( p
->GetString(), gsl_getSystemTextEncoding() );
1249 pIosys
->SetPrompt( aStr
);
1252 // Set Restart point
1254 void SbiRuntime::StepRESTART()
1259 // Leerer Ausdruck auf Stack fuer fehlenden Parameter
1261 void SbiRuntime::StepEMPTY()
1263 // #57915 Die Semantik von StepEMPTY() ist die Repraesentation eines fehlenden
1264 // Arguments. Dies wird in VB durch ein durch den Wert 448 (SbERR_NAMED_NOT_FOUND)
1265 // vom Typ Error repraesentiert. StepEmpty jetzt muesste besser StepMISSING()
1266 // heissen, aber der Name wird der Einfachkeit halber beibehalten.
1267 SbxVariableRef xVar
= new SbxVariable( SbxVARIANT
);
1268 xVar
->PutErr( 448 );
1270 // ALT: PushVar( new SbxVariable( SbxEMPTY ) );
1275 void SbiRuntime::StepERROR()
1277 SbxVariableRef refCode
= PopVar();
1278 USHORT n
= refCode
->GetUShort();
1279 SbError error
= StarBASIC::GetSfxFromVBError( n
);
1280 pInst
->Error( error
);