xref: /trunk/main/basic/source/runtime/step0.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
29*cdf0e10cSrcweir #include "precompiled_basic.hxx"
30*cdf0e10cSrcweir #include <vcl/msgbox.hxx>
31*cdf0e10cSrcweir #include <tools/fsys.hxx>
32*cdf0e10cSrcweir 
33*cdf0e10cSrcweir #include "errobject.hxx"
34*cdf0e10cSrcweir #include "runtime.hxx"
35*cdf0e10cSrcweir #include "sbintern.hxx"
36*cdf0e10cSrcweir #include "iosys.hxx"
37*cdf0e10cSrcweir #include <sb.hrc>
38*cdf0e10cSrcweir #include <basrid.hxx>
39*cdf0e10cSrcweir #include "sbunoobj.hxx"
40*cdf0e10cSrcweir #include "image.hxx"
41*cdf0e10cSrcweir #include <com/sun/star/uno/Any.hxx>
42*cdf0e10cSrcweir #include <com/sun/star/util/SearchOptions.hdl>
43*cdf0e10cSrcweir #include <vcl/svapp.hxx>
44*cdf0e10cSrcweir #include <unotools/textsearch.hxx>
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir Reference< XInterface > createComListener( const Any& aControlAny, const ::rtl::OUString& aVBAType,
47*cdf0e10cSrcweir                                            const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj );
48*cdf0e10cSrcweir 
49*cdf0e10cSrcweir #include <algorithm>
50*cdf0e10cSrcweir #include <hash_map>
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir SbxVariable* getDefaultProp( SbxVariable* pRef );
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir void SbiRuntime::StepNOP()
55*cdf0e10cSrcweir {}
56*cdf0e10cSrcweir 
57*cdf0e10cSrcweir void SbiRuntime::StepArith( SbxOperator eOp )
58*cdf0e10cSrcweir {
59*cdf0e10cSrcweir     SbxVariableRef p1 = PopVar();
60*cdf0e10cSrcweir     TOSMakeTemp();
61*cdf0e10cSrcweir     SbxVariable* p2 = GetTOS();
62*cdf0e10cSrcweir 
63*cdf0e10cSrcweir 
64*cdf0e10cSrcweir     // This could & should be moved to the MakeTempTOS() method in runtime.cxx
65*cdf0e10cSrcweir     // In the code which this is cut'npaste from there is a check for a ref
66*cdf0e10cSrcweir     // count != 1 based on which the copy of the SbxVariable is done.
67*cdf0e10cSrcweir     // see orig code in MakeTempTOS ( and I'm not sure what the significance,
68*cdf0e10cSrcweir     // of that is )
69*cdf0e10cSrcweir     // here we alway seem to have a refcount of 1. Also it seems that
70*cdf0e10cSrcweir     // MakeTempTOS is called for other operation, so I hold off for now
71*cdf0e10cSrcweir     // until I have a better idea
72*cdf0e10cSrcweir     if ( bVBAEnabled
73*cdf0e10cSrcweir         && ( p2->GetType() == SbxOBJECT || p2->GetType() == SbxVARIANT )
74*cdf0e10cSrcweir     )
75*cdf0e10cSrcweir     {
76*cdf0e10cSrcweir         SbxVariable* pDflt = getDefaultProp( p2 );
77*cdf0e10cSrcweir         if ( pDflt )
78*cdf0e10cSrcweir         {
79*cdf0e10cSrcweir             pDflt->Broadcast( SBX_HINT_DATAWANTED );
80*cdf0e10cSrcweir             // replacing new p2 on stack causes object pointed by
81*cdf0e10cSrcweir             // pDft->pParent to be deleted, when p2->Compute() is
82*cdf0e10cSrcweir             // called below pParent is accessed ( but its deleted )
83*cdf0e10cSrcweir             // so set it to NULL now
84*cdf0e10cSrcweir             pDflt->SetParent( NULL );
85*cdf0e10cSrcweir             p2 = new SbxVariable( *pDflt );
86*cdf0e10cSrcweir             p2->SetFlag( SBX_READWRITE );
87*cdf0e10cSrcweir             refExprStk->Put( p2, nExprLvl - 1 );
88*cdf0e10cSrcweir         }
89*cdf0e10cSrcweir     }
90*cdf0e10cSrcweir 
91*cdf0e10cSrcweir     p2->ResetFlag( SBX_FIXED );
92*cdf0e10cSrcweir     p2->Compute( eOp, *p1 );
93*cdf0e10cSrcweir 
94*cdf0e10cSrcweir     checkArithmeticOverflow( p2 );
95*cdf0e10cSrcweir }
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir void SbiRuntime::StepUnary( SbxOperator eOp )
98*cdf0e10cSrcweir {
99*cdf0e10cSrcweir     TOSMakeTemp();
100*cdf0e10cSrcweir     SbxVariable* p = GetTOS();
101*cdf0e10cSrcweir     p->Compute( eOp, *p );
102*cdf0e10cSrcweir }
103*cdf0e10cSrcweir 
104*cdf0e10cSrcweir void SbiRuntime::StepCompare( SbxOperator eOp )
105*cdf0e10cSrcweir {
106*cdf0e10cSrcweir     SbxVariableRef p1 = PopVar();
107*cdf0e10cSrcweir     SbxVariableRef p2 = PopVar();
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir     // Make sure objects with default params have
110*cdf0e10cSrcweir     // values ( and type ) set as appropriate
111*cdf0e10cSrcweir     SbxDataType p1Type = p1->GetType();
112*cdf0e10cSrcweir     SbxDataType p2Type = p2->GetType();
113*cdf0e10cSrcweir     if ( p1Type == p2Type )
114*cdf0e10cSrcweir     {
115*cdf0e10cSrcweir         if ( p1Type == SbxEMPTY )
116*cdf0e10cSrcweir         {
117*cdf0e10cSrcweir             p1->Broadcast( SBX_HINT_DATAWANTED );
118*cdf0e10cSrcweir             p2->Broadcast( SBX_HINT_DATAWANTED );
119*cdf0e10cSrcweir         }
120*cdf0e10cSrcweir         // if both sides are an object and have default props
121*cdf0e10cSrcweir         // then we need to use the default props
122*cdf0e10cSrcweir         // we don't need to worry if only one side ( lhs, rhs ) is an
123*cdf0e10cSrcweir         // object ( object side will get coerced to correct type in
124*cdf0e10cSrcweir         // Compare )
125*cdf0e10cSrcweir         else if ( p1Type ==  SbxOBJECT )
126*cdf0e10cSrcweir         {
127*cdf0e10cSrcweir             SbxVariable* pDflt = getDefaultProp( p1 );
128*cdf0e10cSrcweir             if ( pDflt )
129*cdf0e10cSrcweir             {
130*cdf0e10cSrcweir                 p1 = pDflt;
131*cdf0e10cSrcweir                 p1->Broadcast( SBX_HINT_DATAWANTED );
132*cdf0e10cSrcweir             }
133*cdf0e10cSrcweir             pDflt = getDefaultProp( p2 );
134*cdf0e10cSrcweir             if ( pDflt )
135*cdf0e10cSrcweir             {
136*cdf0e10cSrcweir                 p2 = pDflt;
137*cdf0e10cSrcweir                 p2->Broadcast( SBX_HINT_DATAWANTED );
138*cdf0e10cSrcweir             }
139*cdf0e10cSrcweir         }
140*cdf0e10cSrcweir 
141*cdf0e10cSrcweir     }
142*cdf0e10cSrcweir     static SbxVariable* pTRUE = NULL;
143*cdf0e10cSrcweir     static SbxVariable* pFALSE = NULL;
144*cdf0e10cSrcweir 
145*cdf0e10cSrcweir     if( p2->Compare( eOp, *p1 ) )
146*cdf0e10cSrcweir     {
147*cdf0e10cSrcweir         if( !pTRUE )
148*cdf0e10cSrcweir         {
149*cdf0e10cSrcweir             pTRUE = new SbxVariable;
150*cdf0e10cSrcweir             pTRUE->PutBool( sal_True );
151*cdf0e10cSrcweir             pTRUE->AddRef();
152*cdf0e10cSrcweir         }
153*cdf0e10cSrcweir         PushVar( pTRUE );
154*cdf0e10cSrcweir     }
155*cdf0e10cSrcweir     else
156*cdf0e10cSrcweir     {
157*cdf0e10cSrcweir         if( !pFALSE )
158*cdf0e10cSrcweir         {
159*cdf0e10cSrcweir             pFALSE = new SbxVariable;
160*cdf0e10cSrcweir             pFALSE->PutBool( sal_False );
161*cdf0e10cSrcweir             pFALSE->AddRef();
162*cdf0e10cSrcweir         }
163*cdf0e10cSrcweir         PushVar( pFALSE );
164*cdf0e10cSrcweir     }
165*cdf0e10cSrcweir }
166*cdf0e10cSrcweir 
167*cdf0e10cSrcweir void SbiRuntime::StepEXP()      { StepArith( SbxEXP );      }
168*cdf0e10cSrcweir void SbiRuntime::StepMUL()      { StepArith( SbxMUL );      }
169*cdf0e10cSrcweir void SbiRuntime::StepDIV()      { StepArith( SbxDIV );      }
170*cdf0e10cSrcweir void SbiRuntime::StepIDIV()     { StepArith( SbxIDIV );     }
171*cdf0e10cSrcweir void SbiRuntime::StepMOD()      { StepArith( SbxMOD );      }
172*cdf0e10cSrcweir void SbiRuntime::StepPLUS()     { StepArith( SbxPLUS );     }
173*cdf0e10cSrcweir void SbiRuntime::StepMINUS()        { StepArith( SbxMINUS );    }
174*cdf0e10cSrcweir void SbiRuntime::StepCAT()      { StepArith( SbxCAT );      }
175*cdf0e10cSrcweir void SbiRuntime::StepAND()      { StepArith( SbxAND );      }
176*cdf0e10cSrcweir void SbiRuntime::StepOR()       { StepArith( SbxOR );       }
177*cdf0e10cSrcweir void SbiRuntime::StepXOR()      { StepArith( SbxXOR );      }
178*cdf0e10cSrcweir void SbiRuntime::StepEQV()      { StepArith( SbxEQV );      }
179*cdf0e10cSrcweir void SbiRuntime::StepIMP()      { StepArith( SbxIMP );      }
180*cdf0e10cSrcweir 
181*cdf0e10cSrcweir void SbiRuntime::StepNEG()      { StepUnary( SbxNEG );      }
182*cdf0e10cSrcweir void SbiRuntime::StepNOT()      { StepUnary( SbxNOT );      }
183*cdf0e10cSrcweir 
184*cdf0e10cSrcweir void SbiRuntime::StepEQ()       { StepCompare( SbxEQ );     }
185*cdf0e10cSrcweir void SbiRuntime::StepNE()       { StepCompare( SbxNE );     }
186*cdf0e10cSrcweir void SbiRuntime::StepLT()       { StepCompare( SbxLT );     }
187*cdf0e10cSrcweir void SbiRuntime::StepGT()       { StepCompare( SbxGT );     }
188*cdf0e10cSrcweir void SbiRuntime::StepLE()       { StepCompare( SbxLE );     }
189*cdf0e10cSrcweir void SbiRuntime::StepGE()       { StepCompare( SbxGE );     }
190*cdf0e10cSrcweir 
191*cdf0e10cSrcweir namespace
192*cdf0e10cSrcweir {
193*cdf0e10cSrcweir     bool NeedEsc(sal_Unicode cCode)
194*cdf0e10cSrcweir     {
195*cdf0e10cSrcweir         String sEsc(RTL_CONSTASCII_USTRINGPARAM(".^$+\\|{}()"));
196*cdf0e10cSrcweir         return (STRING_NOTFOUND != sEsc.Search(cCode));
197*cdf0e10cSrcweir     }
198*cdf0e10cSrcweir 
199*cdf0e10cSrcweir     String VBALikeToRegexp(const String &rIn)
200*cdf0e10cSrcweir     {
201*cdf0e10cSrcweir         String sResult;
202*cdf0e10cSrcweir         const sal_Unicode *start = rIn.GetBuffer();
203*cdf0e10cSrcweir         const sal_Unicode *end = start + rIn.Len();
204*cdf0e10cSrcweir 
205*cdf0e10cSrcweir         int seenright = 0;
206*cdf0e10cSrcweir 
207*cdf0e10cSrcweir         sResult.Append('^');
208*cdf0e10cSrcweir 
209*cdf0e10cSrcweir         while (start < end)
210*cdf0e10cSrcweir         {
211*cdf0e10cSrcweir             switch (*start)
212*cdf0e10cSrcweir             {
213*cdf0e10cSrcweir                 case '?':
214*cdf0e10cSrcweir                     sResult.Append('.');
215*cdf0e10cSrcweir                     start++;
216*cdf0e10cSrcweir                     break;
217*cdf0e10cSrcweir                 case '*':
218*cdf0e10cSrcweir                     sResult.Append(String(RTL_CONSTASCII_USTRINGPARAM(".*")));
219*cdf0e10cSrcweir                     start++;
220*cdf0e10cSrcweir                     break;
221*cdf0e10cSrcweir                 case '#':
222*cdf0e10cSrcweir                     sResult.Append(String(RTL_CONSTASCII_USTRINGPARAM("[0-9]")));
223*cdf0e10cSrcweir                     start++;
224*cdf0e10cSrcweir                     break;
225*cdf0e10cSrcweir                 case ']':
226*cdf0e10cSrcweir                     sResult.Append('\\');
227*cdf0e10cSrcweir                     sResult.Append(*start++);
228*cdf0e10cSrcweir                     break;
229*cdf0e10cSrcweir                 case '[':
230*cdf0e10cSrcweir                     sResult.Append(*start++);
231*cdf0e10cSrcweir                     seenright = 0;
232*cdf0e10cSrcweir                     while (start < end && !seenright)
233*cdf0e10cSrcweir                     {
234*cdf0e10cSrcweir                         switch (*start)
235*cdf0e10cSrcweir                         {
236*cdf0e10cSrcweir                             case '[':
237*cdf0e10cSrcweir                             case '?':
238*cdf0e10cSrcweir                             case '*':
239*cdf0e10cSrcweir                             sResult.Append('\\');
240*cdf0e10cSrcweir                             sResult.Append(*start);
241*cdf0e10cSrcweir                                 break;
242*cdf0e10cSrcweir                             case ']':
243*cdf0e10cSrcweir                             sResult.Append(*start);
244*cdf0e10cSrcweir                                 seenright = 1;
245*cdf0e10cSrcweir                                 break;
246*cdf0e10cSrcweir                             case '!':
247*cdf0e10cSrcweir                                 sResult.Append('^');
248*cdf0e10cSrcweir                                 break;
249*cdf0e10cSrcweir                             default:
250*cdf0e10cSrcweir                             if (NeedEsc(*start))
251*cdf0e10cSrcweir                                     sResult.Append('\\');
252*cdf0e10cSrcweir                             sResult.Append(*start);
253*cdf0e10cSrcweir                                 break;
254*cdf0e10cSrcweir                         }
255*cdf0e10cSrcweir                         start++;
256*cdf0e10cSrcweir                     }
257*cdf0e10cSrcweir                     break;
258*cdf0e10cSrcweir                 default:
259*cdf0e10cSrcweir                     if (NeedEsc(*start))
260*cdf0e10cSrcweir                         sResult.Append('\\');
261*cdf0e10cSrcweir                     sResult.Append(*start++);
262*cdf0e10cSrcweir             }
263*cdf0e10cSrcweir         }
264*cdf0e10cSrcweir 
265*cdf0e10cSrcweir         sResult.Append('$');
266*cdf0e10cSrcweir 
267*cdf0e10cSrcweir         return sResult;
268*cdf0e10cSrcweir     }
269*cdf0e10cSrcweir }
270*cdf0e10cSrcweir 
271*cdf0e10cSrcweir void SbiRuntime::StepLIKE()
272*cdf0e10cSrcweir {
273*cdf0e10cSrcweir     SbxVariableRef refVar1 = PopVar();
274*cdf0e10cSrcweir     SbxVariableRef refVar2 = PopVar();
275*cdf0e10cSrcweir 
276*cdf0e10cSrcweir     String pattern = VBALikeToRegexp(refVar1->GetString());
277*cdf0e10cSrcweir     String value = refVar2->GetString();
278*cdf0e10cSrcweir 
279*cdf0e10cSrcweir     com::sun::star::util::SearchOptions aSearchOpt;
280*cdf0e10cSrcweir 
281*cdf0e10cSrcweir     aSearchOpt.algorithmType = com::sun::star::util::SearchAlgorithms_REGEXP;
282*cdf0e10cSrcweir 
283*cdf0e10cSrcweir     aSearchOpt.Locale = Application::GetSettings().GetLocale();
284*cdf0e10cSrcweir     aSearchOpt.searchString = pattern;
285*cdf0e10cSrcweir 
286*cdf0e10cSrcweir     int bTextMode(1);
287*cdf0e10cSrcweir     bool bCompatibility = ( pINST && pINST->IsCompatibility() );
288*cdf0e10cSrcweir     if( bCompatibility )
289*cdf0e10cSrcweir         bTextMode = GetImageFlag( SBIMG_COMPARETEXT );
290*cdf0e10cSrcweir 
291*cdf0e10cSrcweir     if( bTextMode )
292*cdf0e10cSrcweir         aSearchOpt.transliterateFlags |= com::sun::star::i18n::TransliterationModules_IGNORE_CASE;
293*cdf0e10cSrcweir 
294*cdf0e10cSrcweir     SbxVariable* pRes = new SbxVariable;
295*cdf0e10cSrcweir     utl::TextSearch aSearch(aSearchOpt);
296*cdf0e10cSrcweir     xub_StrLen nStart=0, nEnd=value.Len();
297*cdf0e10cSrcweir     int bRes = aSearch.SearchFrwrd(value, &nStart, &nEnd);
298*cdf0e10cSrcweir     pRes->PutBool( bRes != 0 );
299*cdf0e10cSrcweir 
300*cdf0e10cSrcweir     PushVar( pRes );
301*cdf0e10cSrcweir }
302*cdf0e10cSrcweir 
303*cdf0e10cSrcweir // TOS und TOS-1 sind beides Objektvariable und enthalten den selben Pointer
304*cdf0e10cSrcweir 
305*cdf0e10cSrcweir void SbiRuntime::StepIS()
306*cdf0e10cSrcweir {
307*cdf0e10cSrcweir     SbxVariableRef refVar1 = PopVar();
308*cdf0e10cSrcweir     SbxVariableRef refVar2 = PopVar();
309*cdf0e10cSrcweir 
310*cdf0e10cSrcweir     SbxDataType eType1 = refVar1->GetType();
311*cdf0e10cSrcweir     SbxDataType eType2 = refVar2->GetType();
312*cdf0e10cSrcweir     if ( eType1 == SbxEMPTY )
313*cdf0e10cSrcweir     {
314*cdf0e10cSrcweir         refVar1->Broadcast( SBX_HINT_DATAWANTED );
315*cdf0e10cSrcweir         eType1 = refVar1->GetType();
316*cdf0e10cSrcweir     }
317*cdf0e10cSrcweir     if ( eType2 == SbxEMPTY )
318*cdf0e10cSrcweir     {
319*cdf0e10cSrcweir         refVar2->Broadcast( SBX_HINT_DATAWANTED );
320*cdf0e10cSrcweir         eType2 = refVar2->GetType();
321*cdf0e10cSrcweir     }
322*cdf0e10cSrcweir 
323*cdf0e10cSrcweir     sal_Bool bRes = sal_Bool( eType1 == SbxOBJECT && eType2 == SbxOBJECT );
324*cdf0e10cSrcweir     if ( bVBAEnabled  && !bRes )
325*cdf0e10cSrcweir         Error( SbERR_INVALID_USAGE_OBJECT );
326*cdf0e10cSrcweir     bRes = ( bRes && refVar1->GetObject() == refVar2->GetObject() );
327*cdf0e10cSrcweir     SbxVariable* pRes = new SbxVariable;
328*cdf0e10cSrcweir     pRes->PutBool( bRes );
329*cdf0e10cSrcweir     PushVar( pRes );
330*cdf0e10cSrcweir }
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir // Aktualisieren des Wertes von TOS
333*cdf0e10cSrcweir 
334*cdf0e10cSrcweir void SbiRuntime::StepGET()
335*cdf0e10cSrcweir {
336*cdf0e10cSrcweir     SbxVariable* p = GetTOS();
337*cdf0e10cSrcweir     p->Broadcast( SBX_HINT_DATAWANTED );
338*cdf0e10cSrcweir }
339*cdf0e10cSrcweir 
340*cdf0e10cSrcweir // #67607 Uno-Structs kopieren
341*cdf0e10cSrcweir inline void checkUnoStructCopy( SbxVariableRef& refVal, SbxVariableRef& refVar )
342*cdf0e10cSrcweir {
343*cdf0e10cSrcweir     SbxDataType eVarType = refVar->GetType();
344*cdf0e10cSrcweir     if( eVarType != SbxOBJECT )
345*cdf0e10cSrcweir         return;
346*cdf0e10cSrcweir 
347*cdf0e10cSrcweir     SbxObjectRef xValObj = (SbxObject*)refVal->GetObject();
348*cdf0e10cSrcweir     if( !xValObj.Is() || xValObj->ISA(SbUnoAnyObject) )
349*cdf0e10cSrcweir         return;
350*cdf0e10cSrcweir 
351*cdf0e10cSrcweir     // #115826: Exclude ProcedureProperties to avoid call to Property Get procedure
352*cdf0e10cSrcweir     if( refVar->ISA(SbProcedureProperty) )
353*cdf0e10cSrcweir         return;
354*cdf0e10cSrcweir 
355*cdf0e10cSrcweir     SbxObjectRef xVarObj = (SbxObject*)refVar->GetObject();
356*cdf0e10cSrcweir     SbxDataType eValType = refVal->GetType();
357*cdf0e10cSrcweir     if( eValType == SbxOBJECT && xVarObj == xValObj )
358*cdf0e10cSrcweir     {
359*cdf0e10cSrcweir         SbUnoObject* pUnoObj = PTR_CAST(SbUnoObject,(SbxObject*)xVarObj);
360*cdf0e10cSrcweir         if( pUnoObj )
361*cdf0e10cSrcweir         {
362*cdf0e10cSrcweir             Any aAny = pUnoObj->getUnoAny();
363*cdf0e10cSrcweir             if( aAny.getValueType().getTypeClass() == TypeClass_STRUCT )
364*cdf0e10cSrcweir             {
365*cdf0e10cSrcweir                 SbUnoObject* pNewUnoObj = new SbUnoObject( pUnoObj->GetName(), aAny );
366*cdf0e10cSrcweir                 // #70324: ClassName uebernehmen
367*cdf0e10cSrcweir                 pNewUnoObj->SetClassName( pUnoObj->GetClassName() );
368*cdf0e10cSrcweir                 refVar->PutObject( pNewUnoObj );
369*cdf0e10cSrcweir             }
370*cdf0e10cSrcweir         }
371*cdf0e10cSrcweir     }
372*cdf0e10cSrcweir }
373*cdf0e10cSrcweir 
374*cdf0e10cSrcweir 
375*cdf0e10cSrcweir // Ablage von TOS in TOS-1
376*cdf0e10cSrcweir 
377*cdf0e10cSrcweir void SbiRuntime::StepPUT()
378*cdf0e10cSrcweir {
379*cdf0e10cSrcweir     SbxVariableRef refVal = PopVar();
380*cdf0e10cSrcweir     SbxVariableRef refVar = PopVar();
381*cdf0e10cSrcweir     // Store auf die eigene Methode (innerhalb einer Function)?
382*cdf0e10cSrcweir     sal_Bool bFlagsChanged = sal_False;
383*cdf0e10cSrcweir     sal_uInt16 n = 0;
384*cdf0e10cSrcweir     if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
385*cdf0e10cSrcweir     {
386*cdf0e10cSrcweir         bFlagsChanged = sal_True;
387*cdf0e10cSrcweir         n = refVar->GetFlags();
388*cdf0e10cSrcweir         refVar->SetFlag( SBX_WRITE );
389*cdf0e10cSrcweir     }
390*cdf0e10cSrcweir 
391*cdf0e10cSrcweir     // if left side arg is an object or variant and right handside isn't
392*cdf0e10cSrcweir     // either an object or a variant then try and see if a default
393*cdf0e10cSrcweir     // property exists.
394*cdf0e10cSrcweir     // to use e.g. Range{"A1") = 34
395*cdf0e10cSrcweir     // could equate to Range("A1").Value = 34
396*cdf0e10cSrcweir     if ( bVBAEnabled )
397*cdf0e10cSrcweir     {
398*cdf0e10cSrcweir         if ( refVar->GetType() == SbxOBJECT  )
399*cdf0e10cSrcweir         {
400*cdf0e10cSrcweir             SbxVariable* pDflt = getDefaultProp( refVar );
401*cdf0e10cSrcweir             if ( pDflt )
402*cdf0e10cSrcweir                 refVar = pDflt;
403*cdf0e10cSrcweir         }
404*cdf0e10cSrcweir         if (  refVal->GetType() == SbxOBJECT  )
405*cdf0e10cSrcweir         {
406*cdf0e10cSrcweir             SbxVariable* pDflt = getDefaultProp( refVal );
407*cdf0e10cSrcweir             if ( pDflt )
408*cdf0e10cSrcweir                 refVal = pDflt;
409*cdf0e10cSrcweir         }
410*cdf0e10cSrcweir     }
411*cdf0e10cSrcweir 
412*cdf0e10cSrcweir     *refVar = *refVal;
413*cdf0e10cSrcweir     // lhs is a property who's value is currently null
414*cdf0e10cSrcweir     if ( !bVBAEnabled || ( bVBAEnabled && refVar->GetType() != SbxEMPTY ) )
415*cdf0e10cSrcweir     // #67607 Uno-Structs kopieren
416*cdf0e10cSrcweir         checkUnoStructCopy( refVal, refVar );
417*cdf0e10cSrcweir     if( bFlagsChanged )
418*cdf0e10cSrcweir         refVar->SetFlags( n );
419*cdf0e10cSrcweir }
420*cdf0e10cSrcweir 
421*cdf0e10cSrcweir 
422*cdf0e10cSrcweir // VBA Dim As New behavior handling, save init object information
423*cdf0e10cSrcweir struct DimAsNewRecoverItem
424*cdf0e10cSrcweir {
425*cdf0e10cSrcweir     String          m_aObjClass;
426*cdf0e10cSrcweir     String          m_aObjName;
427*cdf0e10cSrcweir     SbxObject*      m_pObjParent;
428*cdf0e10cSrcweir     SbModule*       m_pClassModule;
429*cdf0e10cSrcweir 
430*cdf0e10cSrcweir     DimAsNewRecoverItem( void )
431*cdf0e10cSrcweir         : m_pObjParent( NULL )
432*cdf0e10cSrcweir         , m_pClassModule( NULL )
433*cdf0e10cSrcweir     {}
434*cdf0e10cSrcweir 
435*cdf0e10cSrcweir     DimAsNewRecoverItem( const String& rObjClass, const String& rObjName,
436*cdf0e10cSrcweir         SbxObject* pObjParent, SbModule* pClassModule )
437*cdf0e10cSrcweir             : m_aObjClass( rObjClass )
438*cdf0e10cSrcweir             , m_aObjName( rObjName )
439*cdf0e10cSrcweir             , m_pObjParent( pObjParent )
440*cdf0e10cSrcweir             , m_pClassModule( pClassModule )
441*cdf0e10cSrcweir     {}
442*cdf0e10cSrcweir 
443*cdf0e10cSrcweir };
444*cdf0e10cSrcweir 
445*cdf0e10cSrcweir 
446*cdf0e10cSrcweir struct SbxVariablePtrHash
447*cdf0e10cSrcweir {
448*cdf0e10cSrcweir     size_t operator()( SbxVariable* pVar ) const
449*cdf0e10cSrcweir         { return (size_t)pVar; }
450*cdf0e10cSrcweir };
451*cdf0e10cSrcweir 
452*cdf0e10cSrcweir typedef std::hash_map< SbxVariable*, DimAsNewRecoverItem, SbxVariablePtrHash >  DimAsNewRecoverHash;
453*cdf0e10cSrcweir 
454*cdf0e10cSrcweir static DimAsNewRecoverHash      GaDimAsNewRecoverHash;
455*cdf0e10cSrcweir 
456*cdf0e10cSrcweir void removeDimAsNewRecoverItem( SbxVariable* pVar )
457*cdf0e10cSrcweir {
458*cdf0e10cSrcweir     DimAsNewRecoverHash::iterator it = GaDimAsNewRecoverHash.find( pVar );
459*cdf0e10cSrcweir     if( it != GaDimAsNewRecoverHash.end() )
460*cdf0e10cSrcweir         GaDimAsNewRecoverHash.erase( it );
461*cdf0e10cSrcweir }
462*cdf0e10cSrcweir 
463*cdf0e10cSrcweir 
464*cdf0e10cSrcweir // Speichern Objektvariable
465*cdf0e10cSrcweir // Nicht-Objekt-Variable fuehren zu Fehlern
466*cdf0e10cSrcweir 
467*cdf0e10cSrcweir static const char pCollectionStr[] = "Collection";
468*cdf0e10cSrcweir 
469*cdf0e10cSrcweir void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, bool bHandleDefaultProp )
470*cdf0e10cSrcweir {
471*cdf0e10cSrcweir     // #67733 Typen mit Array-Flag sind auch ok
472*cdf0e10cSrcweir 
473*cdf0e10cSrcweir     // Check var, !object is no error for sure if, only if type is fixed
474*cdf0e10cSrcweir     SbxDataType eVarType = refVar->GetType();
475*cdf0e10cSrcweir     if( !bHandleDefaultProp && eVarType != SbxOBJECT && !(eVarType & SbxARRAY) && refVar->IsFixed() )
476*cdf0e10cSrcweir     {
477*cdf0e10cSrcweir         Error( SbERR_INVALID_USAGE_OBJECT );
478*cdf0e10cSrcweir         return;
479*cdf0e10cSrcweir     }
480*cdf0e10cSrcweir 
481*cdf0e10cSrcweir     // Check value, !object is no error for sure if, only if type is fixed
482*cdf0e10cSrcweir     SbxDataType eValType = refVal->GetType();
483*cdf0e10cSrcweir //  bool bGetValObject = false;
484*cdf0e10cSrcweir     if( !bHandleDefaultProp && eValType != SbxOBJECT && !(eValType & SbxARRAY) && refVal->IsFixed() )
485*cdf0e10cSrcweir     {
486*cdf0e10cSrcweir         Error( SbERR_INVALID_USAGE_OBJECT );
487*cdf0e10cSrcweir         return;
488*cdf0e10cSrcweir     }
489*cdf0e10cSrcweir 
490*cdf0e10cSrcweir     // Getting in here causes problems with objects with default properties
491*cdf0e10cSrcweir     // if they are SbxEMPTY I guess
492*cdf0e10cSrcweir     if ( !bHandleDefaultProp || ( bHandleDefaultProp && eValType == SbxOBJECT ) )
493*cdf0e10cSrcweir     {
494*cdf0e10cSrcweir     // Auf refVal GetObject fuer Collections ausloesen
495*cdf0e10cSrcweir         SbxBase* pObjVarObj = refVal->GetObject();
496*cdf0e10cSrcweir         if( pObjVarObj )
497*cdf0e10cSrcweir         {
498*cdf0e10cSrcweir             SbxVariableRef refObjVal = PTR_CAST(SbxObject,pObjVarObj);
499*cdf0e10cSrcweir 
500*cdf0e10cSrcweir             // #67733 Typen mit Array-Flag sind auch ok
501*cdf0e10cSrcweir             if( refObjVal )
502*cdf0e10cSrcweir                 refVal = refObjVal;
503*cdf0e10cSrcweir             else if( !(eValType & SbxARRAY) )
504*cdf0e10cSrcweir                 refVal = NULL;
505*cdf0e10cSrcweir         }
506*cdf0e10cSrcweir     }
507*cdf0e10cSrcweir 
508*cdf0e10cSrcweir     // #52896 Wenn Uno-Sequences bzw. allgemein Arrays einer als
509*cdf0e10cSrcweir     // Object deklarierten Variable zugewiesen werden, kann hier
510*cdf0e10cSrcweir     // refVal ungueltig sein!
511*cdf0e10cSrcweir     if( !refVal )
512*cdf0e10cSrcweir     {
513*cdf0e10cSrcweir         Error( SbERR_INVALID_USAGE_OBJECT );
514*cdf0e10cSrcweir     }
515*cdf0e10cSrcweir     else
516*cdf0e10cSrcweir     {
517*cdf0e10cSrcweir         // Store auf die eigene Methode (innerhalb einer Function)?
518*cdf0e10cSrcweir         sal_Bool bFlagsChanged = sal_False;
519*cdf0e10cSrcweir         sal_uInt16 n = 0;
520*cdf0e10cSrcweir         if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
521*cdf0e10cSrcweir         {
522*cdf0e10cSrcweir             bFlagsChanged = sal_True;
523*cdf0e10cSrcweir             n = refVar->GetFlags();
524*cdf0e10cSrcweir             refVar->SetFlag( SBX_WRITE );
525*cdf0e10cSrcweir         }
526*cdf0e10cSrcweir         SbProcedureProperty* pProcProperty = PTR_CAST(SbProcedureProperty,(SbxVariable*)refVar);
527*cdf0e10cSrcweir         if( pProcProperty )
528*cdf0e10cSrcweir             pProcProperty->setSet( true );
529*cdf0e10cSrcweir 
530*cdf0e10cSrcweir         if ( bHandleDefaultProp )
531*cdf0e10cSrcweir         {
532*cdf0e10cSrcweir             // get default properties for lhs & rhs where necessary
533*cdf0e10cSrcweir             // SbxVariable* defaultProp = NULL; unused variable
534*cdf0e10cSrcweir             bool bLHSHasDefaultProp = false;
535*cdf0e10cSrcweir             // LHS try determine if a default prop exists
536*cdf0e10cSrcweir             if ( refVar->GetType() == SbxOBJECT )
537*cdf0e10cSrcweir             {
538*cdf0e10cSrcweir                 SbxVariable* pDflt = getDefaultProp( refVar );
539*cdf0e10cSrcweir                 if ( pDflt )
540*cdf0e10cSrcweir                 {
541*cdf0e10cSrcweir                     refVar = pDflt;
542*cdf0e10cSrcweir                     bLHSHasDefaultProp = true;
543*cdf0e10cSrcweir                 }
544*cdf0e10cSrcweir             }
545*cdf0e10cSrcweir             // RHS only get a default prop is the rhs has one
546*cdf0e10cSrcweir             if (  refVal->GetType() == SbxOBJECT )
547*cdf0e10cSrcweir             {
548*cdf0e10cSrcweir                 // check if lhs is a null object
549*cdf0e10cSrcweir                 // if it is then use the object not the default property
550*cdf0e10cSrcweir                 SbxObject* pObj = NULL;
551*cdf0e10cSrcweir 
552*cdf0e10cSrcweir 
553*cdf0e10cSrcweir                 pObj = PTR_CAST(SbxObject,(SbxVariable*)refVar);
554*cdf0e10cSrcweir 
555*cdf0e10cSrcweir                 // calling GetObject on a SbxEMPTY variable raises
556*cdf0e10cSrcweir                 // object not set errors, make sure its an Object
557*cdf0e10cSrcweir                 if ( !pObj && refVar->GetType() == SbxOBJECT )
558*cdf0e10cSrcweir                 {
559*cdf0e10cSrcweir                     SbxBase* pObjVarObj = refVar->GetObject();
560*cdf0e10cSrcweir                     pObj = PTR_CAST(SbxObject,pObjVarObj);
561*cdf0e10cSrcweir                 }
562*cdf0e10cSrcweir                 SbxVariable* pDflt = NULL;
563*cdf0e10cSrcweir                 if ( pObj || bLHSHasDefaultProp )
564*cdf0e10cSrcweir                     // lhs is either a valid object || or has a defaultProp
565*cdf0e10cSrcweir                     pDflt = getDefaultProp( refVal );
566*cdf0e10cSrcweir                 if ( pDflt )
567*cdf0e10cSrcweir                     refVal = pDflt;
568*cdf0e10cSrcweir             }
569*cdf0e10cSrcweir         }
570*cdf0e10cSrcweir 
571*cdf0e10cSrcweir         // Handle Dim As New
572*cdf0e10cSrcweir         sal_Bool bDimAsNew = bVBAEnabled && refVar->IsSet( SBX_DIM_AS_NEW );
573*cdf0e10cSrcweir         SbxBaseRef xPrevVarObj;
574*cdf0e10cSrcweir         if( bDimAsNew )
575*cdf0e10cSrcweir             xPrevVarObj = refVar->GetObject();
576*cdf0e10cSrcweir 
577*cdf0e10cSrcweir         // Handle withevents
578*cdf0e10cSrcweir         sal_Bool bWithEvents = refVar->IsSet( SBX_WITH_EVENTS );
579*cdf0e10cSrcweir         if ( bWithEvents )
580*cdf0e10cSrcweir         {
581*cdf0e10cSrcweir             Reference< XInterface > xComListener;
582*cdf0e10cSrcweir 
583*cdf0e10cSrcweir             SbxBase* pObj = refVal->GetObject();
584*cdf0e10cSrcweir             SbUnoObject* pUnoObj = (pObj != NULL) ? PTR_CAST(SbUnoObject,pObj) : NULL;
585*cdf0e10cSrcweir             if( pUnoObj != NULL )
586*cdf0e10cSrcweir             {
587*cdf0e10cSrcweir                 Any aControlAny = pUnoObj->getUnoAny();
588*cdf0e10cSrcweir                 String aDeclareClassName = refVar->GetDeclareClassName();
589*cdf0e10cSrcweir                 ::rtl::OUString aVBAType = aDeclareClassName;
590*cdf0e10cSrcweir                 ::rtl::OUString aPrefix = refVar->GetName();
591*cdf0e10cSrcweir                 SbxObjectRef xScopeObj = refVar->GetParent();
592*cdf0e10cSrcweir                 xComListener = createComListener( aControlAny, aVBAType, aPrefix, xScopeObj );
593*cdf0e10cSrcweir 
594*cdf0e10cSrcweir                 refVal->SetDeclareClassName( aDeclareClassName );
595*cdf0e10cSrcweir                 refVal->SetComListener( xComListener, &rBasic );        // Hold reference
596*cdf0e10cSrcweir             }
597*cdf0e10cSrcweir 
598*cdf0e10cSrcweir             *refVar = *refVal;
599*cdf0e10cSrcweir         }
600*cdf0e10cSrcweir         else
601*cdf0e10cSrcweir         {
602*cdf0e10cSrcweir             *refVar = *refVal;
603*cdf0e10cSrcweir         }
604*cdf0e10cSrcweir 
605*cdf0e10cSrcweir         if ( bDimAsNew )
606*cdf0e10cSrcweir         {
607*cdf0e10cSrcweir             if( !refVar->ISA(SbxObject) )
608*cdf0e10cSrcweir             {
609*cdf0e10cSrcweir                 SbxBase* pValObjBase = refVal->GetObject();
610*cdf0e10cSrcweir                 if( pValObjBase == NULL )
611*cdf0e10cSrcweir                 {
612*cdf0e10cSrcweir                     if( xPrevVarObj.Is() )
613*cdf0e10cSrcweir                     {
614*cdf0e10cSrcweir                         // Object is overwritten with NULL, instantiate init object
615*cdf0e10cSrcweir                         DimAsNewRecoverHash::iterator it = GaDimAsNewRecoverHash.find( refVar );
616*cdf0e10cSrcweir                         if( it != GaDimAsNewRecoverHash.end() )
617*cdf0e10cSrcweir                         {
618*cdf0e10cSrcweir                             const DimAsNewRecoverItem& rItem = it->second;
619*cdf0e10cSrcweir                             if( rItem.m_pClassModule != NULL )
620*cdf0e10cSrcweir                             {
621*cdf0e10cSrcweir                                 SbClassModuleObject* pNewObj = new SbClassModuleObject( rItem.m_pClassModule );
622*cdf0e10cSrcweir                                 pNewObj->SetName( rItem.m_aObjName );
623*cdf0e10cSrcweir                                 pNewObj->SetParent( rItem.m_pObjParent );
624*cdf0e10cSrcweir                                 refVar->PutObject( pNewObj );
625*cdf0e10cSrcweir                             }
626*cdf0e10cSrcweir                             else if( rItem.m_aObjClass.EqualsIgnoreCaseAscii( pCollectionStr ) )
627*cdf0e10cSrcweir                             {
628*cdf0e10cSrcweir                                 BasicCollection* pNewCollection = new BasicCollection( String( RTL_CONSTASCII_USTRINGPARAM(pCollectionStr) ) );
629*cdf0e10cSrcweir                                 pNewCollection->SetName( rItem.m_aObjName );
630*cdf0e10cSrcweir                                 pNewCollection->SetParent( rItem.m_pObjParent );
631*cdf0e10cSrcweir                                 refVar->PutObject( pNewCollection );
632*cdf0e10cSrcweir                             }
633*cdf0e10cSrcweir                         }
634*cdf0e10cSrcweir                     }
635*cdf0e10cSrcweir                 }
636*cdf0e10cSrcweir                 else
637*cdf0e10cSrcweir                 {
638*cdf0e10cSrcweir                     // Does old value exist?
639*cdf0e10cSrcweir                     bool bFirstInit = !xPrevVarObj.Is();
640*cdf0e10cSrcweir                     if( bFirstInit )
641*cdf0e10cSrcweir                     {
642*cdf0e10cSrcweir                         // Store information to instantiate object later
643*cdf0e10cSrcweir                         SbxObject* pValObj = PTR_CAST(SbxObject,pValObjBase);
644*cdf0e10cSrcweir                         if( pValObj != NULL )
645*cdf0e10cSrcweir                         {
646*cdf0e10cSrcweir                             String aObjClass = pValObj->GetClassName();
647*cdf0e10cSrcweir 
648*cdf0e10cSrcweir                             SbClassModuleObject* pClassModuleObj = PTR_CAST(SbClassModuleObject,pValObjBase);
649*cdf0e10cSrcweir                             if( pClassModuleObj != NULL )
650*cdf0e10cSrcweir                             {
651*cdf0e10cSrcweir                                 SbModule* pClassModule = pClassModuleObj->getClassModule();
652*cdf0e10cSrcweir                                 GaDimAsNewRecoverHash[refVar] =
653*cdf0e10cSrcweir                                     DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), pClassModule );
654*cdf0e10cSrcweir                             }
655*cdf0e10cSrcweir                             else if( aObjClass.EqualsIgnoreCaseAscii( "Collection" ) )
656*cdf0e10cSrcweir                             {
657*cdf0e10cSrcweir                                 GaDimAsNewRecoverHash[refVar] =
658*cdf0e10cSrcweir                                     DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), NULL );
659*cdf0e10cSrcweir                             }
660*cdf0e10cSrcweir                         }
661*cdf0e10cSrcweir                     }
662*cdf0e10cSrcweir                 }
663*cdf0e10cSrcweir             }
664*cdf0e10cSrcweir         }
665*cdf0e10cSrcweir 
666*cdf0e10cSrcweir 
667*cdf0e10cSrcweir         // lhs is a property who's value is currently (Empty e.g. no broadcast yet)
668*cdf0e10cSrcweir         // in this case if there is a default prop involved the value of the
669*cdf0e10cSrcweir         // default property may infact be void so the type will also be SbxEMPTY
670*cdf0e10cSrcweir         // in this case we do not want to call checkUnoStructCopy 'cause that will
671*cdf0e10cSrcweir         // cause an error also
672*cdf0e10cSrcweir         if ( !bHandleDefaultProp || ( bHandleDefaultProp && ( refVar->GetType() != SbxEMPTY ) ) )
673*cdf0e10cSrcweir         // #67607 Uno-Structs kopieren
674*cdf0e10cSrcweir             checkUnoStructCopy( refVal, refVar );
675*cdf0e10cSrcweir         if( bFlagsChanged )
676*cdf0e10cSrcweir             refVar->SetFlags( n );
677*cdf0e10cSrcweir     }
678*cdf0e10cSrcweir }
679*cdf0e10cSrcweir 
680*cdf0e10cSrcweir void SbiRuntime::StepSET()
681*cdf0e10cSrcweir {
682*cdf0e10cSrcweir     SbxVariableRef refVal = PopVar();
683*cdf0e10cSrcweir     SbxVariableRef refVar = PopVar();
684*cdf0e10cSrcweir     StepSET_Impl( refVal, refVar, bVBAEnabled ); // this is really assigment
685*cdf0e10cSrcweir }
686*cdf0e10cSrcweir 
687*cdf0e10cSrcweir void SbiRuntime::StepVBASET()
688*cdf0e10cSrcweir {
689*cdf0e10cSrcweir     SbxVariableRef refVal = PopVar();
690*cdf0e10cSrcweir     SbxVariableRef refVar = PopVar();
691*cdf0e10cSrcweir     // don't handle default property
692*cdf0e10cSrcweir     StepSET_Impl( refVal, refVar, false ); // set obj = something
693*cdf0e10cSrcweir }
694*cdf0e10cSrcweir 
695*cdf0e10cSrcweir 
696*cdf0e10cSrcweir // JSM 07.10.95
697*cdf0e10cSrcweir void SbiRuntime::StepLSET()
698*cdf0e10cSrcweir {
699*cdf0e10cSrcweir     SbxVariableRef refVal = PopVar();
700*cdf0e10cSrcweir     SbxVariableRef refVar = PopVar();
701*cdf0e10cSrcweir     if( refVar->GetType() != SbxSTRING
702*cdf0e10cSrcweir      || refVal->GetType() != SbxSTRING )
703*cdf0e10cSrcweir         Error( SbERR_INVALID_USAGE_OBJECT );
704*cdf0e10cSrcweir     else
705*cdf0e10cSrcweir     {
706*cdf0e10cSrcweir         // Store auf die eigene Methode (innerhalb einer Function)?
707*cdf0e10cSrcweir         sal_uInt16 n = refVar->GetFlags();
708*cdf0e10cSrcweir         if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
709*cdf0e10cSrcweir             refVar->SetFlag( SBX_WRITE );
710*cdf0e10cSrcweir         String aRefVarString = refVar->GetString();
711*cdf0e10cSrcweir         String aRefValString = refVal->GetString();
712*cdf0e10cSrcweir 
713*cdf0e10cSrcweir         sal_uInt16 nVarStrLen = aRefVarString.Len();
714*cdf0e10cSrcweir         sal_uInt16 nValStrLen = aRefValString.Len();
715*cdf0e10cSrcweir         String aNewStr;
716*cdf0e10cSrcweir         if( nVarStrLen > nValStrLen )
717*cdf0e10cSrcweir         {
718*cdf0e10cSrcweir             aRefVarString.Fill(nVarStrLen,' ');
719*cdf0e10cSrcweir             aNewStr  = aRefValString.Copy( 0, nValStrLen );
720*cdf0e10cSrcweir             aNewStr += aRefVarString.Copy( nValStrLen, nVarStrLen - nValStrLen );
721*cdf0e10cSrcweir         }
722*cdf0e10cSrcweir         else
723*cdf0e10cSrcweir         {
724*cdf0e10cSrcweir             aNewStr = aRefValString.Copy( 0, nVarStrLen );
725*cdf0e10cSrcweir         }
726*cdf0e10cSrcweir 
727*cdf0e10cSrcweir         refVar->PutString( aNewStr );
728*cdf0e10cSrcweir         refVar->SetFlags( n );
729*cdf0e10cSrcweir     }
730*cdf0e10cSrcweir }
731*cdf0e10cSrcweir 
732*cdf0e10cSrcweir // JSM 07.10.95
733*cdf0e10cSrcweir void SbiRuntime::StepRSET()
734*cdf0e10cSrcweir {
735*cdf0e10cSrcweir     SbxVariableRef refVal = PopVar();
736*cdf0e10cSrcweir     SbxVariableRef refVar = PopVar();
737*cdf0e10cSrcweir     if( refVar->GetType() != SbxSTRING
738*cdf0e10cSrcweir      || refVal->GetType() != SbxSTRING )
739*cdf0e10cSrcweir         Error( SbERR_INVALID_USAGE_OBJECT );
740*cdf0e10cSrcweir     else
741*cdf0e10cSrcweir     {
742*cdf0e10cSrcweir         // Store auf die eigene Methode (innerhalb einer Function)?
743*cdf0e10cSrcweir         sal_uInt16 n = refVar->GetFlags();
744*cdf0e10cSrcweir         if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
745*cdf0e10cSrcweir             refVar->SetFlag( SBX_WRITE );
746*cdf0e10cSrcweir         String aRefVarString = refVar->GetString();
747*cdf0e10cSrcweir         String aRefValString = refVal->GetString();
748*cdf0e10cSrcweir 
749*cdf0e10cSrcweir         sal_uInt16 nPos = 0;
750*cdf0e10cSrcweir         sal_uInt16 nVarStrLen = aRefVarString.Len();
751*cdf0e10cSrcweir         if( nVarStrLen > aRefValString.Len() )
752*cdf0e10cSrcweir         {
753*cdf0e10cSrcweir             aRefVarString.Fill(nVarStrLen,' ');
754*cdf0e10cSrcweir             nPos = nVarStrLen - aRefValString.Len();
755*cdf0e10cSrcweir         }
756*cdf0e10cSrcweir         aRefVarString  = aRefVarString.Copy( 0, nPos );
757*cdf0e10cSrcweir         aRefVarString += aRefValString.Copy( 0, nVarStrLen - nPos );
758*cdf0e10cSrcweir         refVar->PutString(aRefVarString);
759*cdf0e10cSrcweir 
760*cdf0e10cSrcweir         refVar->SetFlags( n );
761*cdf0e10cSrcweir     }
762*cdf0e10cSrcweir }
763*cdf0e10cSrcweir 
764*cdf0e10cSrcweir // Ablage von TOS in TOS-1, dann ReadOnly-Bit setzen
765*cdf0e10cSrcweir 
766*cdf0e10cSrcweir void SbiRuntime::StepPUTC()
767*cdf0e10cSrcweir {
768*cdf0e10cSrcweir     SbxVariableRef refVal = PopVar();
769*cdf0e10cSrcweir     SbxVariableRef refVar = PopVar();
770*cdf0e10cSrcweir     refVar->SetFlag( SBX_WRITE );
771*cdf0e10cSrcweir     *refVar = *refVal;
772*cdf0e10cSrcweir     refVar->ResetFlag( SBX_WRITE );
773*cdf0e10cSrcweir     refVar->SetFlag( SBX_CONST );
774*cdf0e10cSrcweir }
775*cdf0e10cSrcweir 
776*cdf0e10cSrcweir // DIM
777*cdf0e10cSrcweir // TOS = Variable fuer das Array mit Dimensionsangaben als Parameter
778*cdf0e10cSrcweir 
779*cdf0e10cSrcweir void SbiRuntime::StepDIM()
780*cdf0e10cSrcweir {
781*cdf0e10cSrcweir     SbxVariableRef refVar = PopVar();
782*cdf0e10cSrcweir     DimImpl( refVar );
783*cdf0e10cSrcweir }
784*cdf0e10cSrcweir 
785*cdf0e10cSrcweir // #56204 DIM-Funktionalitaet in Hilfsmethode auslagern (step0.cxx)
786*cdf0e10cSrcweir void SbiRuntime::DimImpl( SbxVariableRef refVar )
787*cdf0e10cSrcweir {
788*cdf0e10cSrcweir     SbxArray* pDims = refVar->GetParameters();
789*cdf0e10cSrcweir     // Muss eine gerade Anzahl Argumente haben
790*cdf0e10cSrcweir     // Man denke daran, dass Arg[0] nicht zaehlt!
791*cdf0e10cSrcweir     if( pDims && !( pDims->Count() & 1 ) )
792*cdf0e10cSrcweir         StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
793*cdf0e10cSrcweir     else
794*cdf0e10cSrcweir     {
795*cdf0e10cSrcweir         SbxDataType eType = refVar->IsFixed() ? refVar->GetType() : SbxVARIANT;
796*cdf0e10cSrcweir         SbxDimArray* pArray = new SbxDimArray( eType );
797*cdf0e10cSrcweir         // AB 2.4.1996, auch Arrays ohne Dimensionsangaben zulassen (VB-komp.)
798*cdf0e10cSrcweir         if( pDims )
799*cdf0e10cSrcweir         {
800*cdf0e10cSrcweir             refVar->ResetFlag( SBX_VAR_TO_DIM );
801*cdf0e10cSrcweir 
802*cdf0e10cSrcweir             for( sal_uInt16 i = 1; i < pDims->Count(); )
803*cdf0e10cSrcweir             {
804*cdf0e10cSrcweir                 sal_Int32 lb = pDims->Get( i++ )->GetLong();
805*cdf0e10cSrcweir                 sal_Int32 ub = pDims->Get( i++ )->GetLong();
806*cdf0e10cSrcweir                 if( ub < lb )
807*cdf0e10cSrcweir                     Error( SbERR_OUT_OF_RANGE ), ub = lb;
808*cdf0e10cSrcweir                 pArray->AddDim32( lb, ub );
809*cdf0e10cSrcweir                 if ( lb != ub )
810*cdf0e10cSrcweir                     pArray->setHasFixedSize( true );
811*cdf0e10cSrcweir             }
812*cdf0e10cSrcweir         }
813*cdf0e10cSrcweir         else
814*cdf0e10cSrcweir         {
815*cdf0e10cSrcweir             // #62867 Beim Anlegen eines Arrays der Laenge 0 wie bei
816*cdf0e10cSrcweir             // Uno-Sequences der Laenge 0 eine Dimension anlegen
817*cdf0e10cSrcweir             pArray->unoAddDim( 0, -1 );
818*cdf0e10cSrcweir         }
819*cdf0e10cSrcweir         sal_uInt16 nSavFlags = refVar->GetFlags();
820*cdf0e10cSrcweir         refVar->ResetFlag( SBX_FIXED );
821*cdf0e10cSrcweir         refVar->PutObject( pArray );
822*cdf0e10cSrcweir         refVar->SetFlags( nSavFlags );
823*cdf0e10cSrcweir         refVar->SetParameters( NULL );
824*cdf0e10cSrcweir     }
825*cdf0e10cSrcweir }
826*cdf0e10cSrcweir 
827*cdf0e10cSrcweir // REDIM
828*cdf0e10cSrcweir // TOS  = Variable fuer das Array
829*cdf0e10cSrcweir // argv = Dimensionsangaben
830*cdf0e10cSrcweir 
831*cdf0e10cSrcweir void SbiRuntime::StepREDIM()
832*cdf0e10cSrcweir {
833*cdf0e10cSrcweir     // Im Moment ist es nichts anderes als Dim, da doppeltes Dim
834*cdf0e10cSrcweir     // bereits vom Compiler erkannt wird.
835*cdf0e10cSrcweir     StepDIM();
836*cdf0e10cSrcweir }
837*cdf0e10cSrcweir 
838*cdf0e10cSrcweir 
839*cdf0e10cSrcweir // Helper function for StepREDIMP
840*cdf0e10cSrcweir void implCopyDimArray( SbxDimArray* pNewArray, SbxDimArray* pOldArray, short nMaxDimIndex,
841*cdf0e10cSrcweir     short nActualDim, sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds )
842*cdf0e10cSrcweir {
843*cdf0e10cSrcweir     sal_Int32& ri = pActualIndices[nActualDim];
844*cdf0e10cSrcweir     for( ri = pLowerBounds[nActualDim] ; ri <= pUpperBounds[nActualDim] ; ri++ )
845*cdf0e10cSrcweir     {
846*cdf0e10cSrcweir         if( nActualDim < nMaxDimIndex )
847*cdf0e10cSrcweir         {
848*cdf0e10cSrcweir             implCopyDimArray( pNewArray, pOldArray, nMaxDimIndex, nActualDim + 1,
849*cdf0e10cSrcweir                 pActualIndices, pLowerBounds, pUpperBounds );
850*cdf0e10cSrcweir         }
851*cdf0e10cSrcweir         else
852*cdf0e10cSrcweir         {
853*cdf0e10cSrcweir             SbxVariable* pSource = pOldArray->Get32( pActualIndices );
854*cdf0e10cSrcweir             SbxVariable* pDest   = pNewArray->Get32( pActualIndices );
855*cdf0e10cSrcweir             if( pSource && pDest )
856*cdf0e10cSrcweir                 *pDest = *pSource;
857*cdf0e10cSrcweir         }
858*cdf0e10cSrcweir     }
859*cdf0e10cSrcweir }
860*cdf0e10cSrcweir 
861*cdf0e10cSrcweir // REDIM PRESERVE
862*cdf0e10cSrcweir // TOS  = Variable fuer das Array
863*cdf0e10cSrcweir // argv = Dimensionsangaben
864*cdf0e10cSrcweir 
865*cdf0e10cSrcweir void SbiRuntime::StepREDIMP()
866*cdf0e10cSrcweir {
867*cdf0e10cSrcweir     SbxVariableRef refVar = PopVar();
868*cdf0e10cSrcweir     DimImpl( refVar );
869*cdf0e10cSrcweir 
870*cdf0e10cSrcweir     // Now check, if we can copy from the old array
871*cdf0e10cSrcweir     if( refRedimpArray.Is() )
872*cdf0e10cSrcweir     {
873*cdf0e10cSrcweir         SbxBase* pElemObj = refVar->GetObject();
874*cdf0e10cSrcweir         SbxDimArray* pNewArray = PTR_CAST(SbxDimArray,pElemObj);
875*cdf0e10cSrcweir         SbxDimArray* pOldArray = (SbxDimArray*)(SbxArray*)refRedimpArray;
876*cdf0e10cSrcweir         if( pNewArray )
877*cdf0e10cSrcweir         {
878*cdf0e10cSrcweir             short nDimsNew = pNewArray->GetDims();
879*cdf0e10cSrcweir             short nDimsOld = pOldArray->GetDims();
880*cdf0e10cSrcweir             short nDims = nDimsNew;
881*cdf0e10cSrcweir             sal_Bool bRangeError = sal_False;
882*cdf0e10cSrcweir 
883*cdf0e10cSrcweir             // Store dims to use them for copying later
884*cdf0e10cSrcweir             sal_Int32* pLowerBounds = new sal_Int32[nDims];
885*cdf0e10cSrcweir             sal_Int32* pUpperBounds = new sal_Int32[nDims];
886*cdf0e10cSrcweir             sal_Int32* pActualIndices = new sal_Int32[nDims];
887*cdf0e10cSrcweir 
888*cdf0e10cSrcweir             if( nDimsOld != nDimsNew )
889*cdf0e10cSrcweir             {
890*cdf0e10cSrcweir                 bRangeError = sal_True;
891*cdf0e10cSrcweir             }
892*cdf0e10cSrcweir             else
893*cdf0e10cSrcweir             {
894*cdf0e10cSrcweir                 // Compare bounds
895*cdf0e10cSrcweir                 for( short i = 1 ; i <= nDims ; i++ )
896*cdf0e10cSrcweir                 {
897*cdf0e10cSrcweir                     sal_Int32 lBoundNew, uBoundNew;
898*cdf0e10cSrcweir                     sal_Int32 lBoundOld, uBoundOld;
899*cdf0e10cSrcweir                     pNewArray->GetDim32( i, lBoundNew, uBoundNew );
900*cdf0e10cSrcweir                     pOldArray->GetDim32( i, lBoundOld, uBoundOld );
901*cdf0e10cSrcweir 
902*cdf0e10cSrcweir                     /* #69094 Allow all dimensions to be changed
903*cdf0e10cSrcweir                        although Visual Basic is not able to do so.
904*cdf0e10cSrcweir                     // All bounds but the last have to be the same
905*cdf0e10cSrcweir                     if( i < nDims && ( lBoundNew != lBoundOld || uBoundNew != uBoundOld ) )
906*cdf0e10cSrcweir                     {
907*cdf0e10cSrcweir                         bRangeError = sal_True;
908*cdf0e10cSrcweir                         break;
909*cdf0e10cSrcweir                     }
910*cdf0e10cSrcweir                     else
911*cdf0e10cSrcweir                     */
912*cdf0e10cSrcweir                     {
913*cdf0e10cSrcweir                         // #69094: if( i == nDims )
914*cdf0e10cSrcweir                         {
915*cdf0e10cSrcweir                             lBoundNew = std::max( lBoundNew, lBoundOld );
916*cdf0e10cSrcweir                             uBoundNew = std::min( uBoundNew, uBoundOld );
917*cdf0e10cSrcweir                         }
918*cdf0e10cSrcweir                         short j = i - 1;
919*cdf0e10cSrcweir                         pActualIndices[j] = pLowerBounds[j] = lBoundNew;
920*cdf0e10cSrcweir                         pUpperBounds[j] = uBoundNew;
921*cdf0e10cSrcweir                     }
922*cdf0e10cSrcweir                 }
923*cdf0e10cSrcweir             }
924*cdf0e10cSrcweir 
925*cdf0e10cSrcweir             if( bRangeError )
926*cdf0e10cSrcweir             {
927*cdf0e10cSrcweir                 StarBASIC::Error( SbERR_OUT_OF_RANGE );
928*cdf0e10cSrcweir             }
929*cdf0e10cSrcweir             else
930*cdf0e10cSrcweir             {
931*cdf0e10cSrcweir                 // Copy data from old array by going recursively through all dimensions
932*cdf0e10cSrcweir                 // (It would be faster to work on the flat internal data array of an
933*cdf0e10cSrcweir                 // SbyArray but this solution is clearer and easier)
934*cdf0e10cSrcweir                 implCopyDimArray( pNewArray, pOldArray, nDims - 1,
935*cdf0e10cSrcweir                     0, pActualIndices, pLowerBounds, pUpperBounds );
936*cdf0e10cSrcweir             }
937*cdf0e10cSrcweir 
938*cdf0e10cSrcweir             delete[] pUpperBounds;
939*cdf0e10cSrcweir             delete[] pLowerBounds;
940*cdf0e10cSrcweir             delete[] pActualIndices;
941*cdf0e10cSrcweir             refRedimpArray = NULL;
942*cdf0e10cSrcweir         }
943*cdf0e10cSrcweir     }
944*cdf0e10cSrcweir 
945*cdf0e10cSrcweir     //StarBASIC::FatalError( SbERR_NOT_IMPLEMENTED );
946*cdf0e10cSrcweir }
947*cdf0e10cSrcweir 
948*cdf0e10cSrcweir // REDIM_COPY
949*cdf0e10cSrcweir // TOS  = Array-Variable, Reference to array is copied
950*cdf0e10cSrcweir //        Variable is cleared as in ERASE
951*cdf0e10cSrcweir 
952*cdf0e10cSrcweir void SbiRuntime::StepREDIMP_ERASE()
953*cdf0e10cSrcweir {
954*cdf0e10cSrcweir     SbxVariableRef refVar = PopVar();
955*cdf0e10cSrcweir     SbxDataType eType = refVar->GetType();
956*cdf0e10cSrcweir     if( eType & SbxARRAY )
957*cdf0e10cSrcweir     {
958*cdf0e10cSrcweir         SbxBase* pElemObj = refVar->GetObject();
959*cdf0e10cSrcweir         SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
960*cdf0e10cSrcweir         if( pDimArray )
961*cdf0e10cSrcweir         {
962*cdf0e10cSrcweir             refRedimpArray = pDimArray;
963*cdf0e10cSrcweir         }
964*cdf0e10cSrcweir 
965*cdf0e10cSrcweir         // As in ERASE
966*cdf0e10cSrcweir         sal_uInt16 nSavFlags = refVar->GetFlags();
967*cdf0e10cSrcweir         refVar->ResetFlag( SBX_FIXED );
968*cdf0e10cSrcweir         refVar->SetType( SbxDataType(eType & 0x0FFF) );
969*cdf0e10cSrcweir         refVar->SetFlags( nSavFlags );
970*cdf0e10cSrcweir         refVar->Clear();
971*cdf0e10cSrcweir     }
972*cdf0e10cSrcweir     else
973*cdf0e10cSrcweir     if( refVar->IsFixed() )
974*cdf0e10cSrcweir         refVar->Clear();
975*cdf0e10cSrcweir     else
976*cdf0e10cSrcweir         refVar->SetType( SbxEMPTY );
977*cdf0e10cSrcweir }
978*cdf0e10cSrcweir 
979*cdf0e10cSrcweir void lcl_clearImpl( SbxVariableRef& refVar, SbxDataType& eType )
980*cdf0e10cSrcweir {
981*cdf0e10cSrcweir     sal_uInt16 nSavFlags = refVar->GetFlags();
982*cdf0e10cSrcweir     refVar->ResetFlag( SBX_FIXED );
983*cdf0e10cSrcweir     refVar->SetType( SbxDataType(eType & 0x0FFF) );
984*cdf0e10cSrcweir     refVar->SetFlags( nSavFlags );
985*cdf0e10cSrcweir     refVar->Clear();
986*cdf0e10cSrcweir }
987*cdf0e10cSrcweir 
988*cdf0e10cSrcweir void lcl_eraseImpl( SbxVariableRef& refVar, bool bVBAEnabled )
989*cdf0e10cSrcweir {
990*cdf0e10cSrcweir     SbxDataType eType = refVar->GetType();
991*cdf0e10cSrcweir     if( eType & SbxARRAY )
992*cdf0e10cSrcweir     {
993*cdf0e10cSrcweir         if ( bVBAEnabled )
994*cdf0e10cSrcweir         {
995*cdf0e10cSrcweir             SbxBase* pElemObj = refVar->GetObject();
996*cdf0e10cSrcweir             SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
997*cdf0e10cSrcweir             bool bClearValues = true;
998*cdf0e10cSrcweir             if( pDimArray )
999*cdf0e10cSrcweir             {
1000*cdf0e10cSrcweir                 if ( pDimArray->hasFixedSize() )
1001*cdf0e10cSrcweir                 {
1002*cdf0e10cSrcweir                     // Clear all Value(s)
1003*cdf0e10cSrcweir                     pDimArray->SbxArray::Clear();
1004*cdf0e10cSrcweir                     bClearValues = false;
1005*cdf0e10cSrcweir                 }
1006*cdf0e10cSrcweir                 else
1007*cdf0e10cSrcweir                     pDimArray->Clear(); // clear Dims
1008*cdf0e10cSrcweir             }
1009*cdf0e10cSrcweir             if ( bClearValues )
1010*cdf0e10cSrcweir             {
1011*cdf0e10cSrcweir                 SbxArray* pArray = PTR_CAST(SbxArray,pElemObj);
1012*cdf0e10cSrcweir                 if ( pArray )
1013*cdf0e10cSrcweir                     pArray->Clear();
1014*cdf0e10cSrcweir             }
1015*cdf0e10cSrcweir         }
1016*cdf0e10cSrcweir         else
1017*cdf0e10cSrcweir         // AB 2.4.1996
1018*cdf0e10cSrcweir         // Arrays haben bei Erase nach VB ein recht komplexes Verhalten. Hier
1019*cdf0e10cSrcweir         // werden zunaechst nur die Typ-Probleme bei REDIM (#26295) beseitigt:
1020*cdf0e10cSrcweir         // Typ hart auf den Array-Typ setzen, da eine Variable mit Array
1021*cdf0e10cSrcweir         // SbxOBJECT ist. Bei REDIM entsteht dann ein SbxOBJECT-Array und
1022*cdf0e10cSrcweir         // der ursruengliche Typ geht verloren -> Laufzeitfehler
1023*cdf0e10cSrcweir             lcl_clearImpl( refVar, eType );
1024*cdf0e10cSrcweir     }
1025*cdf0e10cSrcweir     else
1026*cdf0e10cSrcweir     if( refVar->IsFixed() )
1027*cdf0e10cSrcweir         refVar->Clear();
1028*cdf0e10cSrcweir     else
1029*cdf0e10cSrcweir         refVar->SetType( SbxEMPTY );
1030*cdf0e10cSrcweir }
1031*cdf0e10cSrcweir 
1032*cdf0e10cSrcweir // Variable loeschen
1033*cdf0e10cSrcweir // TOS = Variable
1034*cdf0e10cSrcweir 
1035*cdf0e10cSrcweir void SbiRuntime::StepERASE()
1036*cdf0e10cSrcweir {
1037*cdf0e10cSrcweir     SbxVariableRef refVar = PopVar();
1038*cdf0e10cSrcweir     lcl_eraseImpl( refVar, bVBAEnabled );
1039*cdf0e10cSrcweir }
1040*cdf0e10cSrcweir 
1041*cdf0e10cSrcweir void SbiRuntime::StepERASE_CLEAR()
1042*cdf0e10cSrcweir {
1043*cdf0e10cSrcweir     SbxVariableRef refVar = PopVar();
1044*cdf0e10cSrcweir     lcl_eraseImpl( refVar, bVBAEnabled );
1045*cdf0e10cSrcweir     SbxDataType eType = refVar->GetType();
1046*cdf0e10cSrcweir     lcl_clearImpl( refVar, eType );
1047*cdf0e10cSrcweir }
1048*cdf0e10cSrcweir 
1049*cdf0e10cSrcweir void SbiRuntime::StepARRAYACCESS()
1050*cdf0e10cSrcweir {
1051*cdf0e10cSrcweir     if( !refArgv )
1052*cdf0e10cSrcweir         StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
1053*cdf0e10cSrcweir     SbxVariableRef refVar = PopVar();
1054*cdf0e10cSrcweir     refVar->SetParameters( refArgv );
1055*cdf0e10cSrcweir     PopArgv();
1056*cdf0e10cSrcweir     PushVar( CheckArray( refVar ) );
1057*cdf0e10cSrcweir }
1058*cdf0e10cSrcweir 
1059*cdf0e10cSrcweir void SbiRuntime::StepBYVAL()
1060*cdf0e10cSrcweir {
1061*cdf0e10cSrcweir     // Copy variable on stack to break call by reference
1062*cdf0e10cSrcweir     SbxVariableRef pVar = PopVar();
1063*cdf0e10cSrcweir     SbxDataType t = pVar->GetType();
1064*cdf0e10cSrcweir 
1065*cdf0e10cSrcweir     SbxVariable* pCopyVar = new SbxVariable( t );
1066*cdf0e10cSrcweir     pCopyVar->SetFlag( SBX_READWRITE );
1067*cdf0e10cSrcweir     *pCopyVar = *pVar;
1068*cdf0e10cSrcweir 
1069*cdf0e10cSrcweir     PushVar( pCopyVar );
1070*cdf0e10cSrcweir }
1071*cdf0e10cSrcweir 
1072*cdf0e10cSrcweir // Einrichten eines Argvs
1073*cdf0e10cSrcweir // nOp1 bleibt so -> 1. Element ist Returnwert
1074*cdf0e10cSrcweir 
1075*cdf0e10cSrcweir void SbiRuntime::StepARGC()
1076*cdf0e10cSrcweir {
1077*cdf0e10cSrcweir     PushArgv();
1078*cdf0e10cSrcweir     refArgv = new SbxArray;
1079*cdf0e10cSrcweir     nArgc = 1;
1080*cdf0e10cSrcweir }
1081*cdf0e10cSrcweir 
1082*cdf0e10cSrcweir // Speichern eines Arguments in Argv
1083*cdf0e10cSrcweir 
1084*cdf0e10cSrcweir void SbiRuntime::StepARGV()
1085*cdf0e10cSrcweir {
1086*cdf0e10cSrcweir     if( !refArgv )
1087*cdf0e10cSrcweir         StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
1088*cdf0e10cSrcweir     else
1089*cdf0e10cSrcweir     {
1090*cdf0e10cSrcweir         SbxVariableRef pVal = PopVar();
1091*cdf0e10cSrcweir 
1092*cdf0e10cSrcweir         // Before fix of #94916:
1093*cdf0e10cSrcweir         // if( pVal->ISA(SbxMethod) || pVal->ISA(SbxProperty) )
1094*cdf0e10cSrcweir         if( pVal->ISA(SbxMethod) || pVal->ISA(SbUnoProperty) || pVal->ISA(SbProcedureProperty) )
1095*cdf0e10cSrcweir         {
1096*cdf0e10cSrcweir             // Methoden und Properties evaluieren!
1097*cdf0e10cSrcweir             SbxVariable* pRes = new SbxVariable( *pVal );
1098*cdf0e10cSrcweir             pVal = pRes;
1099*cdf0e10cSrcweir         }
1100*cdf0e10cSrcweir         refArgv->Put( pVal, nArgc++ );
1101*cdf0e10cSrcweir     }
1102*cdf0e10cSrcweir }
1103*cdf0e10cSrcweir 
1104*cdf0e10cSrcweir // Input to Variable. Die Variable ist auf TOS und wird
1105*cdf0e10cSrcweir // anschliessend entfernt.
1106*cdf0e10cSrcweir 
1107*cdf0e10cSrcweir void SbiRuntime::StepINPUT()
1108*cdf0e10cSrcweir {
1109*cdf0e10cSrcweir     String s;
1110*cdf0e10cSrcweir     char ch = 0;
1111*cdf0e10cSrcweir     SbError err;
1112*cdf0e10cSrcweir     // Skip whitespace
1113*cdf0e10cSrcweir     while( ( err = pIosys->GetError() ) == 0 )
1114*cdf0e10cSrcweir     {
1115*cdf0e10cSrcweir         ch = pIosys->Read();
1116*cdf0e10cSrcweir         if( ch != ' ' && ch != '\t' && ch != '\n' )
1117*cdf0e10cSrcweir             break;
1118*cdf0e10cSrcweir     }
1119*cdf0e10cSrcweir     if( !err )
1120*cdf0e10cSrcweir     {
1121*cdf0e10cSrcweir         // Scan until comma or whitespace
1122*cdf0e10cSrcweir         char sep = ( ch == '"' ) ? ch : 0;
1123*cdf0e10cSrcweir         if( sep ) ch = pIosys->Read();
1124*cdf0e10cSrcweir         while( ( err = pIosys->GetError() ) == 0 )
1125*cdf0e10cSrcweir         {
1126*cdf0e10cSrcweir             if( ch == sep )
1127*cdf0e10cSrcweir             {
1128*cdf0e10cSrcweir                 ch = pIosys->Read();
1129*cdf0e10cSrcweir                 if( ch != sep )
1130*cdf0e10cSrcweir                     break;
1131*cdf0e10cSrcweir             }
1132*cdf0e10cSrcweir             else if( !sep && (ch == ',' || ch == '\n') )
1133*cdf0e10cSrcweir                 break;
1134*cdf0e10cSrcweir             s += ch;
1135*cdf0e10cSrcweir             ch = pIosys->Read();
1136*cdf0e10cSrcweir         }
1137*cdf0e10cSrcweir         // skip whitespace
1138*cdf0e10cSrcweir         if( ch == ' ' || ch == '\t' )
1139*cdf0e10cSrcweir           while( ( err = pIosys->GetError() ) == 0 )
1140*cdf0e10cSrcweir         {
1141*cdf0e10cSrcweir             if( ch != ' ' && ch != '\t' && ch != '\n' )
1142*cdf0e10cSrcweir                 break;
1143*cdf0e10cSrcweir             ch = pIosys->Read();
1144*cdf0e10cSrcweir         }
1145*cdf0e10cSrcweir     }
1146*cdf0e10cSrcweir     if( !err )
1147*cdf0e10cSrcweir     {
1148*cdf0e10cSrcweir         SbxVariableRef pVar = GetTOS();
1149*cdf0e10cSrcweir         // Zuerst versuchen, die Variable mit einem numerischen Wert
1150*cdf0e10cSrcweir         // zu fuellen, dann mit einem Stringwert
1151*cdf0e10cSrcweir         if( !pVar->IsFixed() || pVar->IsNumeric() )
1152*cdf0e10cSrcweir         {
1153*cdf0e10cSrcweir             sal_uInt16 nLen = 0;
1154*cdf0e10cSrcweir             if( !pVar->Scan( s, &nLen ) )
1155*cdf0e10cSrcweir             {
1156*cdf0e10cSrcweir                 err = SbxBase::GetError();
1157*cdf0e10cSrcweir                 SbxBase::ResetError();
1158*cdf0e10cSrcweir             }
1159*cdf0e10cSrcweir             // Der Wert muss komplett eingescant werden
1160*cdf0e10cSrcweir             else if( nLen != s.Len() && !pVar->PutString( s ) )
1161*cdf0e10cSrcweir             {
1162*cdf0e10cSrcweir                 err = SbxBase::GetError();
1163*cdf0e10cSrcweir                 SbxBase::ResetError();
1164*cdf0e10cSrcweir             }
1165*cdf0e10cSrcweir             else if( nLen != s.Len() && pVar->IsNumeric() )
1166*cdf0e10cSrcweir             {
1167*cdf0e10cSrcweir                 err = SbxBase::GetError();
1168*cdf0e10cSrcweir                 SbxBase::ResetError();
1169*cdf0e10cSrcweir                 if( !err )
1170*cdf0e10cSrcweir                     err = SbERR_CONVERSION;
1171*cdf0e10cSrcweir             }
1172*cdf0e10cSrcweir         }
1173*cdf0e10cSrcweir         else
1174*cdf0e10cSrcweir         {
1175*cdf0e10cSrcweir             pVar->PutString( s );
1176*cdf0e10cSrcweir             err = SbxBase::GetError();
1177*cdf0e10cSrcweir             SbxBase::ResetError();
1178*cdf0e10cSrcweir         }
1179*cdf0e10cSrcweir     }
1180*cdf0e10cSrcweir     if( err == SbERR_USER_ABORT )
1181*cdf0e10cSrcweir         Error( err );
1182*cdf0e10cSrcweir     else if( err )
1183*cdf0e10cSrcweir     {
1184*cdf0e10cSrcweir         if( pRestart && !pIosys->GetChannel() )
1185*cdf0e10cSrcweir         {
1186*cdf0e10cSrcweir             BasResId aId( IDS_SBERR_START + 4 );
1187*cdf0e10cSrcweir             String aMsg( aId );
1188*cdf0e10cSrcweir 
1189*cdf0e10cSrcweir             //****** DONT CHECK IN, TEST ONLY *******
1190*cdf0e10cSrcweir             //****** DONT CHECK IN, TEST ONLY *******
1191*cdf0e10cSrcweir             // ErrorBox( NULL, WB_OK, aMsg ).Execute();
1192*cdf0e10cSrcweir             //****** DONT CHECK IN, TEST ONLY *******
1193*cdf0e10cSrcweir             //****** DONT CHECK IN, TEST ONLY *******
1194*cdf0e10cSrcweir 
1195*cdf0e10cSrcweir             pCode = pRestart;
1196*cdf0e10cSrcweir         }
1197*cdf0e10cSrcweir         else
1198*cdf0e10cSrcweir             Error( err );
1199*cdf0e10cSrcweir     }
1200*cdf0e10cSrcweir     else
1201*cdf0e10cSrcweir     {
1202*cdf0e10cSrcweir         // pIosys->ResetChannel();
1203*cdf0e10cSrcweir         PopVar();
1204*cdf0e10cSrcweir     }
1205*cdf0e10cSrcweir }
1206*cdf0e10cSrcweir 
1207*cdf0e10cSrcweir // Line Input to Variable. Die Variable ist auf TOS und wird
1208*cdf0e10cSrcweir // anschliessend entfernt.
1209*cdf0e10cSrcweir 
1210*cdf0e10cSrcweir void SbiRuntime::StepLINPUT()
1211*cdf0e10cSrcweir {
1212*cdf0e10cSrcweir     ByteString aInput;
1213*cdf0e10cSrcweir     pIosys->Read( aInput );
1214*cdf0e10cSrcweir     Error( pIosys->GetError() );
1215*cdf0e10cSrcweir     SbxVariableRef p = PopVar();
1216*cdf0e10cSrcweir     p->PutString( String( aInput, gsl_getSystemTextEncoding() ) );
1217*cdf0e10cSrcweir     // pIosys->ResetChannel();
1218*cdf0e10cSrcweir }
1219*cdf0e10cSrcweir 
1220*cdf0e10cSrcweir // Programmende
1221*cdf0e10cSrcweir 
1222*cdf0e10cSrcweir void SbiRuntime::StepSTOP()
1223*cdf0e10cSrcweir {
1224*cdf0e10cSrcweir     pInst->Stop();
1225*cdf0e10cSrcweir }
1226*cdf0e10cSrcweir 
1227*cdf0e10cSrcweir // FOR-Variable initialisieren
1228*cdf0e10cSrcweir 
1229*cdf0e10cSrcweir void SbiRuntime::StepINITFOR()
1230*cdf0e10cSrcweir {
1231*cdf0e10cSrcweir     PushFor();
1232*cdf0e10cSrcweir }
1233*cdf0e10cSrcweir 
1234*cdf0e10cSrcweir void SbiRuntime::StepINITFOREACH()
1235*cdf0e10cSrcweir {
1236*cdf0e10cSrcweir     PushForEach();
1237*cdf0e10cSrcweir }
1238*cdf0e10cSrcweir 
1239*cdf0e10cSrcweir // FOR-Variable inkrementieren
1240*cdf0e10cSrcweir 
1241*cdf0e10cSrcweir void SbiRuntime::StepNEXT()
1242*cdf0e10cSrcweir {
1243*cdf0e10cSrcweir     if( !pForStk )
1244*cdf0e10cSrcweir     {
1245*cdf0e10cSrcweir         StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
1246*cdf0e10cSrcweir         return;
1247*cdf0e10cSrcweir     }
1248*cdf0e10cSrcweir     if( pForStk->eForType == FOR_TO )
1249*cdf0e10cSrcweir         pForStk->refVar->Compute( SbxPLUS, *pForStk->refInc );
1250*cdf0e10cSrcweir }
1251*cdf0e10cSrcweir 
1252*cdf0e10cSrcweir // Anfang CASE: TOS in CASE-Stack
1253*cdf0e10cSrcweir 
1254*cdf0e10cSrcweir void SbiRuntime::StepCASE()
1255*cdf0e10cSrcweir {
1256*cdf0e10cSrcweir     if( !refCaseStk.Is() )
1257*cdf0e10cSrcweir         refCaseStk = new SbxArray;
1258*cdf0e10cSrcweir     SbxVariableRef xVar = PopVar();
1259*cdf0e10cSrcweir     refCaseStk->Put( xVar, refCaseStk->Count() );
1260*cdf0e10cSrcweir }
1261*cdf0e10cSrcweir 
1262*cdf0e10cSrcweir // Ende CASE: Variable freigeben
1263*cdf0e10cSrcweir 
1264*cdf0e10cSrcweir void SbiRuntime::StepENDCASE()
1265*cdf0e10cSrcweir {
1266*cdf0e10cSrcweir     if( !refCaseStk || !refCaseStk->Count() )
1267*cdf0e10cSrcweir         StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
1268*cdf0e10cSrcweir     else
1269*cdf0e10cSrcweir         refCaseStk->Remove( refCaseStk->Count() - 1 );
1270*cdf0e10cSrcweir }
1271*cdf0e10cSrcweir 
1272*cdf0e10cSrcweir // Standard-Fehlerbehandlung
1273*cdf0e10cSrcweir 
1274*cdf0e10cSrcweir void SbiRuntime::StepSTDERROR()
1275*cdf0e10cSrcweir {
1276*cdf0e10cSrcweir     pError = NULL; bError = sal_True;
1277*cdf0e10cSrcweir     pInst->aErrorMsg = String();
1278*cdf0e10cSrcweir     pInst->nErr = 0L;
1279*cdf0e10cSrcweir     pInst->nErl = 0;
1280*cdf0e10cSrcweir     nError = 0L;
1281*cdf0e10cSrcweir     SbxErrObject::getUnoErrObject()->Clear();
1282*cdf0e10cSrcweir }
1283*cdf0e10cSrcweir 
1284*cdf0e10cSrcweir void SbiRuntime::StepNOERROR()
1285*cdf0e10cSrcweir {
1286*cdf0e10cSrcweir     pInst->aErrorMsg = String();
1287*cdf0e10cSrcweir     pInst->nErr = 0L;
1288*cdf0e10cSrcweir     pInst->nErl = 0;
1289*cdf0e10cSrcweir     nError = 0L;
1290*cdf0e10cSrcweir     SbxErrObject::getUnoErrObject()->Clear();
1291*cdf0e10cSrcweir     bError = sal_False;
1292*cdf0e10cSrcweir }
1293*cdf0e10cSrcweir 
1294*cdf0e10cSrcweir // UP verlassen
1295*cdf0e10cSrcweir 
1296*cdf0e10cSrcweir void SbiRuntime::StepLEAVE()
1297*cdf0e10cSrcweir {
1298*cdf0e10cSrcweir     bRun = sal_False;
1299*cdf0e10cSrcweir         // If VBA and we are leaving an ErrorHandler then clear the error ( it's been processed )
1300*cdf0e10cSrcweir     if ( bInError && pError )
1301*cdf0e10cSrcweir         SbxErrObject::getUnoErrObject()->Clear();
1302*cdf0e10cSrcweir }
1303*cdf0e10cSrcweir 
1304*cdf0e10cSrcweir void SbiRuntime::StepCHANNEL()      // TOS = Kanalnummer
1305*cdf0e10cSrcweir {
1306*cdf0e10cSrcweir     SbxVariableRef pChan = PopVar();
1307*cdf0e10cSrcweir     short nChan = pChan->GetInteger();
1308*cdf0e10cSrcweir     pIosys->SetChannel( nChan );
1309*cdf0e10cSrcweir     Error( pIosys->GetError() );
1310*cdf0e10cSrcweir }
1311*cdf0e10cSrcweir 
1312*cdf0e10cSrcweir void SbiRuntime::StepCHANNEL0()
1313*cdf0e10cSrcweir {
1314*cdf0e10cSrcweir     pIosys->ResetChannel();
1315*cdf0e10cSrcweir }
1316*cdf0e10cSrcweir 
1317*cdf0e10cSrcweir void SbiRuntime::StepPRINT()        // print TOS
1318*cdf0e10cSrcweir {
1319*cdf0e10cSrcweir     SbxVariableRef p = PopVar();
1320*cdf0e10cSrcweir     String s1 = p->GetString();
1321*cdf0e10cSrcweir     String s;
1322*cdf0e10cSrcweir     if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
1323*cdf0e10cSrcweir         s = ' ';    // ein Blank davor
1324*cdf0e10cSrcweir     s += s1;
1325*cdf0e10cSrcweir     ByteString aByteStr( s, gsl_getSystemTextEncoding() );
1326*cdf0e10cSrcweir     pIosys->Write( aByteStr );
1327*cdf0e10cSrcweir     Error( pIosys->GetError() );
1328*cdf0e10cSrcweir }
1329*cdf0e10cSrcweir 
1330*cdf0e10cSrcweir void SbiRuntime::StepPRINTF()       // print TOS in field
1331*cdf0e10cSrcweir {
1332*cdf0e10cSrcweir     SbxVariableRef p = PopVar();
1333*cdf0e10cSrcweir     String s1 = p->GetString();
1334*cdf0e10cSrcweir     String s;
1335*cdf0e10cSrcweir     if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
1336*cdf0e10cSrcweir         s = ' ';    // ein Blank davor
1337*cdf0e10cSrcweir     s += s1;
1338*cdf0e10cSrcweir     s.Expand( 14, ' ' );
1339*cdf0e10cSrcweir     ByteString aByteStr( s, gsl_getSystemTextEncoding() );
1340*cdf0e10cSrcweir     pIosys->Write( aByteStr );
1341*cdf0e10cSrcweir     Error( pIosys->GetError() );
1342*cdf0e10cSrcweir }
1343*cdf0e10cSrcweir 
1344*cdf0e10cSrcweir void SbiRuntime::StepWRITE()        // write TOS
1345*cdf0e10cSrcweir {
1346*cdf0e10cSrcweir     SbxVariableRef p = PopVar();
1347*cdf0e10cSrcweir     // Muss der String gekapselt werden?
1348*cdf0e10cSrcweir     char ch = 0;
1349*cdf0e10cSrcweir     switch (p->GetType() )
1350*cdf0e10cSrcweir     {
1351*cdf0e10cSrcweir         case SbxSTRING: ch = '"'; break;
1352*cdf0e10cSrcweir         case SbxCURRENCY:
1353*cdf0e10cSrcweir         case SbxBOOL:
1354*cdf0e10cSrcweir         case SbxDATE: ch = '#'; break;
1355*cdf0e10cSrcweir         default: break;
1356*cdf0e10cSrcweir     }
1357*cdf0e10cSrcweir     String s;
1358*cdf0e10cSrcweir     if( ch )
1359*cdf0e10cSrcweir         s += ch;
1360*cdf0e10cSrcweir     s += p->GetString();
1361*cdf0e10cSrcweir     if( ch )
1362*cdf0e10cSrcweir         s += ch;
1363*cdf0e10cSrcweir     ByteString aByteStr( s, gsl_getSystemTextEncoding() );
1364*cdf0e10cSrcweir     pIosys->Write( aByteStr );
1365*cdf0e10cSrcweir     Error( pIosys->GetError() );
1366*cdf0e10cSrcweir }
1367*cdf0e10cSrcweir 
1368*cdf0e10cSrcweir void SbiRuntime::StepRENAME()       // Rename Tos+1 to Tos
1369*cdf0e10cSrcweir {
1370*cdf0e10cSrcweir     SbxVariableRef pTos1 = PopVar();
1371*cdf0e10cSrcweir     SbxVariableRef pTos  = PopVar();
1372*cdf0e10cSrcweir     String aDest = pTos1->GetString();
1373*cdf0e10cSrcweir     String aSource = pTos->GetString();
1374*cdf0e10cSrcweir 
1375*cdf0e10cSrcweir     // <-- UCB
1376*cdf0e10cSrcweir     if( hasUno() )
1377*cdf0e10cSrcweir     {
1378*cdf0e10cSrcweir         implStepRenameUCB( aSource, aDest );
1379*cdf0e10cSrcweir     }
1380*cdf0e10cSrcweir     else
1381*cdf0e10cSrcweir     // --> UCB
1382*cdf0e10cSrcweir     {
1383*cdf0e10cSrcweir #ifdef _OLD_FILE_IMPL
1384*cdf0e10cSrcweir         DirEntry aSourceDirEntry( aSource );
1385*cdf0e10cSrcweir         if( aSourceDirEntry.Exists() )
1386*cdf0e10cSrcweir         {
1387*cdf0e10cSrcweir             if( aSourceDirEntry.MoveTo( DirEntry(aDest) ) != FSYS_ERR_OK )
1388*cdf0e10cSrcweir                 StarBASIC::Error( SbERR_PATH_NOT_FOUND );
1389*cdf0e10cSrcweir         }
1390*cdf0e10cSrcweir         else
1391*cdf0e10cSrcweir                 StarBASIC::Error( SbERR_PATH_NOT_FOUND );
1392*cdf0e10cSrcweir #else
1393*cdf0e10cSrcweir         implStepRenameOSL( aSource, aDest );
1394*cdf0e10cSrcweir #endif
1395*cdf0e10cSrcweir     }
1396*cdf0e10cSrcweir }
1397*cdf0e10cSrcweir 
1398*cdf0e10cSrcweir // TOS = Prompt
1399*cdf0e10cSrcweir 
1400*cdf0e10cSrcweir void SbiRuntime::StepPROMPT()
1401*cdf0e10cSrcweir {
1402*cdf0e10cSrcweir     SbxVariableRef p = PopVar();
1403*cdf0e10cSrcweir     ByteString aStr( p->GetString(), gsl_getSystemTextEncoding() );
1404*cdf0e10cSrcweir     pIosys->SetPrompt( aStr );
1405*cdf0e10cSrcweir }
1406*cdf0e10cSrcweir 
1407*cdf0e10cSrcweir // Set Restart point
1408*cdf0e10cSrcweir 
1409*cdf0e10cSrcweir void SbiRuntime::StepRESTART()
1410*cdf0e10cSrcweir {
1411*cdf0e10cSrcweir     pRestart = pCode;
1412*cdf0e10cSrcweir }
1413*cdf0e10cSrcweir 
1414*cdf0e10cSrcweir // Leerer Ausdruck auf Stack fuer fehlenden Parameter
1415*cdf0e10cSrcweir 
1416*cdf0e10cSrcweir void SbiRuntime::StepEMPTY()
1417*cdf0e10cSrcweir {
1418*cdf0e10cSrcweir     // #57915 Die Semantik von StepEMPTY() ist die Repraesentation eines fehlenden
1419*cdf0e10cSrcweir     // Arguments. Dies wird in VB durch ein durch den Wert 448 (SbERR_NAMED_NOT_FOUND)
1420*cdf0e10cSrcweir     // vom Typ Error repraesentiert. StepEmpty jetzt muesste besser StepMISSING()
1421*cdf0e10cSrcweir     // heissen, aber der Name wird der Einfachkeit halber beibehalten.
1422*cdf0e10cSrcweir     SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
1423*cdf0e10cSrcweir     xVar->PutErr( 448 );
1424*cdf0e10cSrcweir     PushVar( xVar );
1425*cdf0e10cSrcweir     // ALT: PushVar( new SbxVariable( SbxEMPTY ) );
1426*cdf0e10cSrcweir }
1427*cdf0e10cSrcweir 
1428*cdf0e10cSrcweir // TOS = Fehlercode
1429*cdf0e10cSrcweir 
1430*cdf0e10cSrcweir void SbiRuntime::StepERROR()
1431*cdf0e10cSrcweir {
1432*cdf0e10cSrcweir     SbxVariableRef refCode = PopVar();
1433*cdf0e10cSrcweir     sal_uInt16 n = refCode->GetUShort();
1434*cdf0e10cSrcweir     SbError error = StarBASIC::GetSfxFromVBError( n );
1435*cdf0e10cSrcweir     if ( bVBAEnabled )
1436*cdf0e10cSrcweir         pInst->Error( error );
1437*cdf0e10cSrcweir     else
1438*cdf0e10cSrcweir         Error( error );
1439*cdf0e10cSrcweir }
1440*cdf0e10cSrcweir 
1441