Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include <vcl/msgbox.hxx>
21 : : #include <tools/fsys.hxx>
22 : :
23 : : #include "errobject.hxx"
24 : : #include "runtime.hxx"
25 : : #include "sbintern.hxx"
26 : : #include "iosys.hxx"
27 : : #include <sb.hrc>
28 : : #include <basrid.hxx>
29 : : #include "sbunoobj.hxx"
30 : : #include "image.hxx"
31 : : #include <com/sun/star/uno/Any.hxx>
32 : : #include <com/sun/star/util/SearchOptions.hpp>
33 : : #include <rtl/instance.hxx>
34 : : #include <vcl/svapp.hxx>
35 : : #include <unotools/textsearch.hxx>
36 : :
37 : : Reference< XInterface > createComListener( const Any& aControlAny, const ::rtl::OUString& aVBAType,
38 : : const ::rtl::OUString& aPrefix, SbxObjectRef xScopeObj );
39 : :
40 : : #include <algorithm>
41 : : #include <boost/unordered_map.hpp>
42 : :
43 : : // for a patch forward declaring these methods below makes sense
44 : : // but, #FIXME lets really just move the methods to the top
45 : : void lcl_clearImpl( SbxVariableRef& refVar, SbxDataType& eType );
46 : : void lcl_eraseImpl( SbxVariableRef& refVar, bool bVBAEnabled );
47 : :
48 : : SbxVariable* getDefaultProp( SbxVariable* pRef );
49 : :
50 : 0 : void SbiRuntime::StepNOP()
51 : 0 : {}
52 : :
53 : 2751 : void SbiRuntime::StepArith( SbxOperator eOp )
54 : : {
55 [ + - ]: 2751 : SbxVariableRef p1 = PopVar();
56 [ + - ]: 2751 : TOSMakeTemp();
57 [ + - ]: 2751 : SbxVariable* p2 = GetTOS();
58 : :
59 : 2751 : p2->ResetFlag( SBX_FIXED );
60 [ + - ]: 2751 : p2->Compute( eOp, *p1 );
61 : :
62 [ + - ][ + - ]: 2751 : checkArithmeticOverflow( p2 );
63 : 2751 : }
64 : :
65 : 108 : void SbiRuntime::StepUnary( SbxOperator eOp )
66 : : {
67 : 108 : TOSMakeTemp();
68 : 108 : SbxVariable* p = GetTOS();
69 : 108 : p->Compute( eOp, *p );
70 : 108 : }
71 : :
72 : 988 : void SbiRuntime::StepCompare( SbxOperator eOp )
73 : : {
74 [ + - ]: 988 : SbxVariableRef p1 = PopVar();
75 [ + - ]: 988 : SbxVariableRef p2 = PopVar();
76 : :
77 : : // Make sure objects with default params have
78 : : // values ( and type ) set as appropriate
79 [ + - ]: 988 : SbxDataType p1Type = p1->GetType();
80 [ + - ]: 988 : SbxDataType p2Type = p2->GetType();
81 [ - + ]: 988 : if ( p1Type == SbxEMPTY )
82 : : {
83 [ # # ]: 0 : p1->Broadcast( SBX_HINT_DATAWANTED );
84 [ # # ]: 0 : p1Type = p1->GetType();
85 : : }
86 [ - + ]: 988 : if ( p2Type == SbxEMPTY )
87 : : {
88 [ # # ]: 0 : p2->Broadcast( SBX_HINT_DATAWANTED );
89 [ # # ]: 0 : p2Type = p2->GetType();
90 : : }
91 [ + + ]: 988 : if ( p1Type == p2Type )
92 : : {
93 : : // if both sides are an object and have default props
94 : : // then we need to use the default props
95 : : // we don't need to worry if only one side ( lhs, rhs ) is an
96 : : // object ( object side will get coerced to correct type in
97 : : // Compare )
98 [ - + ]: 874 : if ( p1Type == SbxOBJECT )
99 : : {
100 [ # # ]: 0 : SbxVariable* pDflt = getDefaultProp( p1 );
101 [ # # ]: 0 : if ( pDflt )
102 : : {
103 [ # # ]: 0 : p1 = pDflt;
104 [ # # ]: 0 : p1->Broadcast( SBX_HINT_DATAWANTED );
105 : : }
106 [ # # ]: 0 : pDflt = getDefaultProp( p2 );
107 [ # # ]: 0 : if ( pDflt )
108 : : {
109 [ # # ]: 0 : p2 = pDflt;
110 [ # # ]: 0 : p2->Broadcast( SBX_HINT_DATAWANTED );
111 : : }
112 : : }
113 : :
114 : : }
115 : : static SbxVariable* pTRUE = NULL;
116 : : static SbxVariable* pFALSE = NULL;
117 : : static SbxVariable* pNULL = NULL;
118 : : // why do this on non-windows ?
119 : : // why do this at all ?
120 : : // I dumbly follow the pattern :-/
121 [ + + ][ + - ]: 988 : if ( bVBAEnabled && ( p1->IsNull() || p2->IsNull() ) )
[ + - ][ + - ]
[ - + ][ - + ]
122 : : {
123 [ # # ]: 0 : if( !pNULL )
124 : : {
125 [ # # ][ # # ]: 0 : pNULL = new SbxVariable;
126 [ # # ]: 0 : pNULL->PutNull();
127 : 0 : pNULL->AddRef();
128 : : }
129 [ # # ]: 0 : PushVar( pNULL );
130 : : }
131 [ + - ][ + + ]: 988 : else if( p2->Compare( eOp, *p1 ) )
132 : : {
133 [ + + ]: 252 : if( !pTRUE )
134 : : {
135 [ + - ][ + - ]: 6 : pTRUE = new SbxVariable;
136 [ + - ]: 6 : pTRUE->PutBool( sal_True );
137 : 6 : pTRUE->AddRef();
138 : : }
139 [ + - ]: 252 : PushVar( pTRUE );
140 : : }
141 : : else
142 : : {
143 [ + + ]: 736 : if( !pFALSE )
144 : : {
145 [ + - ][ + - ]: 6 : pFALSE = new SbxVariable;
146 [ + - ]: 6 : pFALSE->PutBool( sal_False );
147 : 6 : pFALSE->AddRef();
148 : : }
149 [ + - ]: 736 : PushVar( pFALSE );
150 [ + - ][ + - ]: 988 : }
151 : 988 : }
152 : :
153 : 0 : void SbiRuntime::StepEXP() { StepArith( SbxEXP ); }
154 : 0 : void SbiRuntime::StepMUL() { StepArith( SbxMUL ); }
155 : 0 : void SbiRuntime::StepDIV() { StepArith( SbxDIV ); }
156 : 0 : void SbiRuntime::StepIDIV() { StepArith( SbxIDIV ); }
157 : 0 : void SbiRuntime::StepMOD() { StepArith( SbxMOD ); }
158 : 773 : void SbiRuntime::StepPLUS() { StepArith( SbxPLUS ); }
159 : 4 : void SbiRuntime::StepMINUS() { StepArith( SbxMINUS ); }
160 : 50 : void SbiRuntime::StepCAT() { StepArith( SbxCAT ); }
161 : 136 : void SbiRuntime::StepAND() { StepArith( SbxAND ); }
162 : 1788 : void SbiRuntime::StepOR() { StepArith( SbxOR ); }
163 : 0 : void SbiRuntime::StepXOR() { StepArith( SbxXOR ); }
164 : 0 : void SbiRuntime::StepEQV() { StepArith( SbxEQV ); }
165 : 0 : void SbiRuntime::StepIMP() { StepArith( SbxIMP ); }
166 : :
167 : 0 : void SbiRuntime::StepNEG() { StepUnary( SbxNEG ); }
168 : 108 : void SbiRuntime::StepNOT() { StepUnary( SbxNOT ); }
169 : :
170 : 620 : void SbiRuntime::StepEQ() { StepCompare( SbxEQ ); }
171 : 368 : void SbiRuntime::StepNE() { StepCompare( SbxNE ); }
172 : 0 : void SbiRuntime::StepLT() { StepCompare( SbxLT ); }
173 : 0 : void SbiRuntime::StepGT() { StepCompare( SbxGT ); }
174 : 0 : void SbiRuntime::StepLE() { StepCompare( SbxLE ); }
175 : 0 : void SbiRuntime::StepGE() { StepCompare( SbxGE ); }
176 : :
177 : : namespace
178 : : {
179 : 0 : bool NeedEsc(sal_Unicode cCode)
180 : : {
181 [ # # ]: 0 : String sEsc(RTL_CONSTASCII_USTRINGPARAM(".^$+\\|{}()"));
182 [ # # ][ # # ]: 0 : return (STRING_NOTFOUND != sEsc.Search(cCode));
183 : : }
184 : :
185 : 0 : String VBALikeToRegexp(const String &rIn)
186 : : {
187 : 0 : String sResult;
188 : 0 : const sal_Unicode *start = rIn.GetBuffer();
189 : 0 : const sal_Unicode *end = start + rIn.Len();
190 : :
191 : 0 : int seenright = 0;
192 : :
193 [ # # ]: 0 : sResult.Append('^');
194 : :
195 [ # # ]: 0 : while (start < end)
196 : : {
197 [ # # # # : 0 : switch (*start)
# # ]
198 : : {
199 : : case '?':
200 [ # # ]: 0 : sResult.Append('.');
201 : 0 : start++;
202 : 0 : break;
203 : : case '*':
204 [ # # ][ # # ]: 0 : sResult.Append(String(RTL_CONSTASCII_USTRINGPARAM(".*")));
[ # # ]
205 : 0 : start++;
206 : 0 : break;
207 : : case '#':
208 [ # # ][ # # ]: 0 : sResult.Append(String(RTL_CONSTASCII_USTRINGPARAM("[0-9]")));
[ # # ]
209 : 0 : start++;
210 : 0 : break;
211 : : case ']':
212 [ # # ]: 0 : sResult.Append('\\');
213 [ # # ]: 0 : sResult.Append(*start++);
214 : 0 : break;
215 : : case '[':
216 [ # # ]: 0 : sResult.Append(*start++);
217 : 0 : seenright = 0;
218 [ # # ][ # # ]: 0 : while (start < end && !seenright)
[ # # ]
219 : : {
220 [ # # # # ]: 0 : switch (*start)
221 : : {
222 : : case '[':
223 : : case '?':
224 : : case '*':
225 [ # # ]: 0 : sResult.Append('\\');
226 [ # # ]: 0 : sResult.Append(*start);
227 : 0 : break;
228 : : case ']':
229 [ # # ]: 0 : sResult.Append(*start);
230 : 0 : seenright = 1;
231 : 0 : break;
232 : : case '!':
233 [ # # ]: 0 : sResult.Append('^');
234 : 0 : break;
235 : : default:
236 [ # # ][ # # ]: 0 : if (NeedEsc(*start))
237 [ # # ]: 0 : sResult.Append('\\');
238 [ # # ]: 0 : sResult.Append(*start);
239 : 0 : break;
240 : : }
241 : 0 : start++;
242 : : }
243 : 0 : break;
244 : : default:
245 [ # # ][ # # ]: 0 : if (NeedEsc(*start))
246 [ # # ]: 0 : sResult.Append('\\');
247 [ # # ]: 0 : sResult.Append(*start++);
248 : : }
249 : : }
250 : :
251 [ # # ]: 0 : sResult.Append('$');
252 : :
253 : 0 : return sResult;
254 : : }
255 : : }
256 : :
257 : 0 : void SbiRuntime::StepLIKE()
258 : : {
259 [ # # ]: 0 : SbxVariableRef refVar1 = PopVar();
260 [ # # ]: 0 : SbxVariableRef refVar2 = PopVar();
261 : :
262 [ # # ][ # # ]: 0 : String pattern = VBALikeToRegexp(refVar1->GetString());
263 [ # # ][ # # ]: 0 : String value = refVar2->GetString();
264 : :
265 : 0 : com::sun::star::util::SearchOptions aSearchOpt;
266 : :
267 : 0 : aSearchOpt.algorithmType = com::sun::star::util::SearchAlgorithms_REGEXP;
268 : :
269 [ # # ][ # # ]: 0 : aSearchOpt.Locale = Application::GetSettings().GetLocale();
270 [ # # ]: 0 : aSearchOpt.searchString = pattern;
271 : :
272 : 0 : int bTextMode(1);
273 [ # # ][ # # ]: 0 : bool bCompatibility = ( GetSbData()->pInst && GetSbData()->pInst->IsCompatibility() );
[ # # ][ # # ]
274 [ # # ]: 0 : if( bCompatibility )
275 [ # # ]: 0 : bTextMode = GetImageFlag( SBIMG_COMPARETEXT );
276 : :
277 [ # # ]: 0 : if( bTextMode )
278 : 0 : aSearchOpt.transliterateFlags |= com::sun::star::i18n::TransliterationModules_IGNORE_CASE;
279 : :
280 [ # # ][ # # ]: 0 : SbxVariable* pRes = new SbxVariable;
281 [ # # ]: 0 : utl::TextSearch aSearch(aSearchOpt);
282 : 0 : xub_StrLen nStart=0, nEnd=value.Len();
283 [ # # ]: 0 : int bRes = aSearch.SearchFrwrd(value, &nStart, &nEnd);
284 [ # # ]: 0 : pRes->PutBool( bRes != 0 );
285 : :
286 [ # # ][ # # ]: 0 : PushVar( pRes );
[ # # ][ # # ]
[ # # ][ # # ]
287 : 0 : }
288 : :
289 : : // TOS and TOS-1 are both object variables and contain the same pointer
290 : :
291 : 0 : void SbiRuntime::StepIS()
292 : : {
293 [ # # ]: 0 : SbxVariableRef refVar1 = PopVar();
294 [ # # ]: 0 : SbxVariableRef refVar2 = PopVar();
295 : :
296 [ # # ]: 0 : SbxDataType eType1 = refVar1->GetType();
297 [ # # ]: 0 : SbxDataType eType2 = refVar2->GetType();
298 [ # # ]: 0 : if ( eType1 == SbxEMPTY )
299 : : {
300 [ # # ]: 0 : refVar1->Broadcast( SBX_HINT_DATAWANTED );
301 [ # # ]: 0 : eType1 = refVar1->GetType();
302 : : }
303 [ # # ]: 0 : if ( eType2 == SbxEMPTY )
304 : : {
305 [ # # ]: 0 : refVar2->Broadcast( SBX_HINT_DATAWANTED );
306 [ # # ]: 0 : eType2 = refVar2->GetType();
307 : : }
308 : :
309 [ # # ][ # # ]: 0 : sal_Bool bRes = sal_Bool( eType1 == SbxOBJECT && eType2 == SbxOBJECT );
310 [ # # ][ # # ]: 0 : if ( bVBAEnabled && !bRes )
311 [ # # ]: 0 : Error( SbERR_INVALID_USAGE_OBJECT );
312 [ # # ][ # # ]: 0 : bRes = ( bRes && refVar1->GetObject() == refVar2->GetObject() );
[ # # ][ # # ]
313 [ # # ][ # # ]: 0 : SbxVariable* pRes = new SbxVariable;
314 [ # # ]: 0 : pRes->PutBool( bRes );
315 [ # # ][ # # ]: 0 : PushVar( pRes );
[ # # ]
316 : 0 : }
317 : :
318 : : // update the value of TOS
319 : :
320 : 428 : void SbiRuntime::StepGET()
321 : : {
322 : 428 : SbxVariable* p = GetTOS();
323 : 428 : p->Broadcast( SBX_HINT_DATAWANTED );
324 : 428 : }
325 : :
326 : : // #67607 copy Uno-Structs
327 : 2591 : inline bool checkUnoStructCopy( bool bVBA, SbxVariableRef& refVal, SbxVariableRef& refVar )
328 : : {
329 [ + - ]: 2591 : SbxDataType eVarType = refVar->GetType();
330 [ + - ]: 2591 : SbxDataType eValType = refVal->GetType();
331 : :
332 [ + + ][ + - ]: 2591 : if ( !( !bVBA|| ( bVBA && refVar->GetType() != SbxEMPTY ) ) || !refVar->CanWrite() )
[ + - ][ + + ]
[ - + ][ + + ]
333 : 8 : return false;
334 : :
335 [ + + ]: 2583 : if ( eValType != SbxOBJECT )
336 : 2221 : return false;
337 : : // we seem to be duplicating parts of SbxValue=operator, maybe we should just move this to
338 : : // there :-/ not sure if for every '=' we would want struct handling
339 [ + + ]: 362 : if( eVarType != SbxOBJECT )
340 : : {
341 [ + - ][ - + ]: 81 : if ( refVar->IsFixed() )
342 : 0 : return false;
343 : : }
344 : : // #115826: Exclude ProcedureProperties to avoid call to Property Get procedure
345 [ + - ][ + - ]: 281 : else if( refVar->ISA(SbProcedureProperty) )
[ - + ]
346 : 0 : return false;
347 : :
348 [ + - ]: 362 : SbxObjectRef xValObj = (SbxObject*)refVal->GetObject();
349 [ + - ][ + - ]: 362 : if( !xValObj.Is() || xValObj->ISA(SbUnoAnyObject) )
[ - + ][ + + ]
[ + + ]
350 : 4 : return false;
351 : :
352 [ + - ][ + - ]: 358 : SbUnoObject* pUnoVal = PTR_CAST(SbUnoObject,(SbxObject*)xValObj);
[ + - ][ + + ]
353 [ + - ][ + - ]: 358 : SbUnoStructRefObject* pUnoStructVal = PTR_CAST(SbUnoStructRefObject,(SbxObject*)xValObj);
[ + - ][ + + ]
354 [ + + ][ + - ]: 358 : Any aAny = pUnoVal ? pUnoVal->getUnoAny() : pUnoStructVal->getUnoAny();
[ + - ]
355 [ + + ]: 358 : if ( aAny.getValueType().getTypeClass() == TypeClass_STRUCT )
356 : : {
357 [ + - ]: 144 : refVar->SetType( SbxOBJECT );
358 [ + - ]: 144 : SbxObjectRef xVarObj = (SbxObject*)refVar->GetObject();
359 [ + - ][ + - ]: 144 : SbUnoStructRefObject* pUnoStructObj = PTR_CAST(SbUnoStructRefObject,(SbxObject*)xVarObj);
[ + + ][ + + ]
360 : :
361 [ + + ][ - + ]: 144 : if ( ( !pUnoVal && !pUnoStructVal ) )
362 : 0 : return false;
363 : :
364 [ + + ][ + - ]: 144 : String sClassName = pUnoVal ? pUnoVal->GetClassName() : pUnoStructVal->GetClassName();
365 [ + + ][ + - ]: 144 : String sName = pUnoVal ? pUnoVal->GetName() : pUnoStructVal->GetName();
[ + - ][ + - ]
366 : :
367 [ + + ]: 144 : if ( pUnoStructObj )
368 : : {
369 : 9 : StructRefInfo aInfo = pUnoStructObj->getStructInfo();
370 [ + - ]: 9 : aInfo.setValue( aAny );
371 : : }
372 : : else
373 : : {
374 [ + - ][ + - ]: 135 : SbUnoObject* pNewUnoObj = new SbUnoObject( sName, aAny );
[ + - ]
375 : : // #70324: adopt ClassName
376 [ + - ]: 135 : pNewUnoObj->SetClassName( sClassName );
377 [ + - ]: 135 : refVar->PutObject( pNewUnoObj );
378 : : }
379 [ + - ][ + - ]: 144 : return true;
[ + - ]
380 : : }
381 [ + - ]: 2591 : return false;
382 : : }
383 : :
384 : :
385 : : // laying down TOS in TOS-1
386 : :
387 : 2313 : void SbiRuntime::StepPUT()
388 : : {
389 [ + - ]: 2313 : SbxVariableRef refVal = PopVar();
390 [ + - ]: 2313 : SbxVariableRef refVar = PopVar();
391 : : // store on its own method (inside a function)?
392 : 2313 : bool bFlagsChanged = false;
393 : 2313 : sal_uInt16 n = 0;
394 [ + + ]: 2313 : if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
395 : : {
396 : 547 : bFlagsChanged = true;
397 : 547 : n = refVar->GetFlags();
398 : 547 : refVar->SetFlag( SBX_WRITE );
399 : : }
400 : :
401 : : // if left side arg is an object or variant and right handside isn't
402 : : // either an object or a variant then try and see if a default
403 : : // property exists.
404 : : // to use e.g. Range{"A1") = 34
405 : : // could equate to Range("A1").Value = 34
406 [ + + ]: 2313 : if ( bVBAEnabled )
407 : : {
408 [ + - ][ + + ]: 348 : if ( refVar->GetType() == SbxOBJECT )
409 : : {
410 [ + - ]: 4 : SbxVariable* pDflt = getDefaultProp( refVar );
411 [ + - ]: 4 : if ( pDflt )
412 [ + - ]: 4 : refVar = pDflt;
413 : : }
414 [ + - ][ - + ]: 348 : if ( refVal->GetType() == SbxOBJECT )
415 : : {
416 [ # # ]: 0 : SbxVariable* pDflt = getDefaultProp( refVal );
417 [ # # ]: 0 : if ( pDflt )
418 [ # # ]: 0 : refVal = pDflt;
419 : : }
420 : : }
421 : :
422 [ + - ][ + + ]: 2313 : if ( !checkUnoStructCopy( bVBAEnabled, refVal, refVar ) )
423 [ + - ]: 2247 : *refVar = *refVal;
424 : :
425 [ + + ]: 2313 : if( bFlagsChanged )
426 [ + - ][ + - ]: 2313 : refVar->SetFlags( n );
427 : 2313 : }
428 : :
429 : :
430 : : // VBA Dim As New behavior handling, save init object information
431 [ # # ]: 0 : struct DimAsNewRecoverItem
432 : : {
433 : : String m_aObjClass;
434 : : String m_aObjName;
435 : : SbxObject* m_pObjParent;
436 : : SbModule* m_pClassModule;
437 : :
438 : 0 : DimAsNewRecoverItem( void )
439 : : : m_pObjParent( NULL )
440 [ # # ]: 0 : , m_pClassModule( NULL )
441 : 0 : {}
442 : :
443 : 0 : DimAsNewRecoverItem( const String& rObjClass, const String& rObjName,
444 : : SbxObject* pObjParent, SbModule* pClassModule )
445 : : : m_aObjClass( rObjClass )
446 : : , m_aObjName( rObjName )
447 : : , m_pObjParent( pObjParent )
448 [ # # ]: 0 : , m_pClassModule( pClassModule )
449 : 0 : {}
450 : :
451 : : };
452 : :
453 : :
454 : : struct SbxVariablePtrHash
455 : : {
456 : 0 : size_t operator()( SbxVariable* pVar ) const
457 : 0 : { return (size_t)pVar; }
458 : : };
459 : :
460 : : typedef boost::unordered_map< SbxVariable*, DimAsNewRecoverItem,
461 : : SbxVariablePtrHash > DimAsNewRecoverHash;
462 : :
463 : : class GaDimAsNewRecoverHash : public rtl::Static<DimAsNewRecoverHash, GaDimAsNewRecoverHash> {};
464 : :
465 : 0 : void removeDimAsNewRecoverItem( SbxVariable* pVar )
466 : : {
467 [ # # ]: 0 : DimAsNewRecoverHash &rDimAsNewRecoverHash = GaDimAsNewRecoverHash::get();
468 [ # # ]: 0 : DimAsNewRecoverHash::iterator it = rDimAsNewRecoverHash.find( pVar );
469 [ # # ][ # # ]: 0 : if( it != rDimAsNewRecoverHash.end() )
470 [ # # ]: 0 : rDimAsNewRecoverHash.erase( it );
471 : 0 : }
472 : :
473 : :
474 : : // saving object variable
475 : : // not-object variables will cause errors
476 : :
477 : : static const char pCollectionStr[] = "Collection";
478 : :
479 : 278 : void SbiRuntime::StepSET_Impl( SbxVariableRef& refVal, SbxVariableRef& refVar, bool bHandleDefaultProp )
480 : : {
481 : : // #67733 types with array-flag are OK too
482 : :
483 : : // Check var, !object is no error for sure if, only if type is fixed
484 : 278 : SbxDataType eVarType = refVar->GetType();
485 [ + + ][ + - ]: 278 : if( !bHandleDefaultProp && eVarType != SbxOBJECT && !(eVarType & SbxARRAY) && refVar->IsFixed() )
[ - + ][ - + ]
[ + + ]
486 : : {
487 : 0 : Error( SbERR_INVALID_USAGE_OBJECT );
488 : 0 : return;
489 : : }
490 : :
491 : : // Check value, !object is no error for sure if, only if type is fixed
492 : 278 : SbxDataType eValType = refVal->GetType();
493 [ - + ][ # # ]: 278 : if( !bHandleDefaultProp && eValType != SbxOBJECT && !(eValType & SbxARRAY) && refVal->IsFixed() )
[ # # ][ - + ]
[ + + ]
494 : : {
495 : 0 : Error( SbERR_INVALID_USAGE_OBJECT );
496 : 0 : return;
497 : : }
498 : :
499 : : // Getting in here causes problems with objects with default properties
500 : : // if they are SbxEMPTY I guess
501 [ + + ][ + - ]: 278 : if ( !bHandleDefaultProp || ( bHandleDefaultProp && eValType == SbxOBJECT ) )
[ + + ]
502 : : {
503 : : // activate GetOject for collections on refVal
504 : 276 : SbxBase* pObjVarObj = refVal->GetObject();
505 [ + + ]: 276 : if( pObjVarObj )
506 : : {
507 [ + - ][ + - ]: 272 : SbxVariableRef refObjVal = PTR_CAST(SbxObject,pObjVarObj);
[ + - ][ + - ]
508 : :
509 [ + - ]: 272 : if( refObjVal )
510 [ + - ]: 272 : refVal = refObjVal;
511 [ # # ]: 0 : else if( !(eValType & SbxARRAY) )
512 [ # # ][ + - ]: 272 : refVal = NULL;
513 : : }
514 : : }
515 : :
516 : : // #52896 refVal can be invalid here, if uno-sequences - or more
517 : : // general arrays - are assigned to variables that are declared
518 : : // as an object!
519 [ - + ]: 278 : if( !refVal )
520 : : {
521 : 0 : Error( SbERR_INVALID_USAGE_OBJECT );
522 : : }
523 : : else
524 : : {
525 : 278 : bool bFlagsChanged = false;
526 : 278 : sal_uInt16 n = 0;
527 [ + + ]: 278 : if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
528 : : {
529 : 34 : bFlagsChanged = true;
530 : 34 : n = refVar->GetFlags();
531 : 34 : refVar->SetFlag( SBX_WRITE );
532 : : }
533 [ + - ][ + - ]: 278 : SbProcedureProperty* pProcProperty = PTR_CAST(SbProcedureProperty,(SbxVariable*)refVar);
[ + - ][ - + ]
534 [ - + ]: 278 : if( pProcProperty )
535 : 0 : pProcProperty->setSet( true );
536 : :
537 [ + + ]: 278 : if ( bHandleDefaultProp )
538 : : {
539 : : // get default properties for lhs & rhs where necessary
540 : : // SbxVariable* defaultProp = NULL; unused variable
541 : 8 : bool bLHSHasDefaultProp = false;
542 : : // LHS try determine if a default prop exists
543 [ + - ][ + - ]: 8 : if ( refVar->GetType() == SbxOBJECT )
544 : : {
545 [ + - ]: 8 : SbxVariable* pDflt = getDefaultProp( refVar );
546 [ + + ]: 8 : if ( pDflt )
547 : : {
548 [ + - ]: 2 : refVar = pDflt;
549 : 2 : bLHSHasDefaultProp = true;
550 : : }
551 : : }
552 : : // RHS only get a default prop is the rhs has one
553 [ + - ][ + + ]: 8 : if ( refVal->GetType() == SbxOBJECT )
554 : : {
555 : : // check if lhs is a null object
556 : : // if it is then use the object not the default property
557 : 6 : SbxObject* pObj = NULL;
558 : :
559 : :
560 [ + - ][ + - ]: 6 : pObj = PTR_CAST(SbxObject,(SbxVariable*)refVar);
[ + - ][ - + ]
561 : :
562 : : // calling GetObject on a SbxEMPTY variable raises
563 : : // object not set errors, make sure its an Object
564 [ + - ][ + - ]: 6 : if ( !pObj && refVar->GetType() == SbxOBJECT )
[ + - ][ + - ]
565 : : {
566 [ + - ]: 6 : SbxBase* pObjVarObj = refVar->GetObject();
567 [ + - ][ + - ]: 6 : pObj = PTR_CAST(SbxObject,pObjVarObj);
[ + - ][ + - ]
568 : : }
569 : 6 : SbxVariable* pDflt = NULL;
570 [ - + ][ # # ]: 6 : if ( pObj || bLHSHasDefaultProp )
571 : : // lhs is either a valid object || or has a defaultProp
572 [ + - ]: 6 : pDflt = getDefaultProp( refVal );
573 [ - + ]: 6 : if ( pDflt )
574 [ # # ]: 0 : refVal = pDflt;
575 : : }
576 : : }
577 : :
578 : : // Handle Dim As New
579 [ + + ][ - + ]: 278 : bool bDimAsNew = bVBAEnabled && refVar->IsSet( SBX_DIM_AS_NEW );
580 : 278 : SbxBaseRef xPrevVarObj;
581 [ - + ]: 278 : if( bDimAsNew )
582 [ # # ][ # # ]: 0 : xPrevVarObj = refVar->GetObject();
583 : :
584 : : // Handle withevents
585 : 278 : sal_Bool bWithEvents = refVar->IsSet( SBX_WITH_EVENTS );
586 [ - + ]: 278 : if ( bWithEvents )
587 : : {
588 : 0 : Reference< XInterface > xComListener;
589 : :
590 [ # # ]: 0 : SbxBase* pObj = refVal->GetObject();
591 [ # # ][ # # ]: 0 : SbUnoObject* pUnoObj = (pObj != NULL) ? PTR_CAST(SbUnoObject,pObj) : NULL;
[ # # ][ # # ]
[ # # ]
592 [ # # ]: 0 : if( pUnoObj != NULL )
593 : : {
594 [ # # ]: 0 : Any aControlAny = pUnoObj->getUnoAny();
595 [ # # ][ # # ]: 0 : String aDeclareClassName = refVar->GetDeclareClassName();
596 [ # # ]: 0 : ::rtl::OUString aVBAType = aDeclareClassName;
597 [ # # ][ # # ]: 0 : ::rtl::OUString aPrefix = refVar->GetName();
598 [ # # ]: 0 : SbxObjectRef xScopeObj = refVar->GetParent();
599 [ # # ][ # # ]: 0 : xComListener = createComListener( aControlAny, aVBAType, aPrefix, xScopeObj );
[ # # ]
600 : :
601 [ # # ]: 0 : refVal->SetDeclareClassName( aDeclareClassName );
602 [ # # ][ # # ]: 0 : refVal->SetComListener( xComListener, &rBasic ); // Hold reference
[ # # ]
603 : 0 : }
604 : :
605 : : }
606 : :
607 : : // lhs is a property who's value is currently (Empty e.g. no broadcast yet)
608 : : // in this case if there is a default prop involved the value of the
609 : : // default property may infact be void so the type will also be SbxEMPTY
610 : : // in this case we do not want to call checkUnoStructCopy 'cause that will
611 : : // cause an error also
612 [ + - ][ + + ]: 278 : if ( !checkUnoStructCopy( bHandleDefaultProp, refVal, refVar ) )
613 [ + - ]: 200 : *refVar = *refVal;
614 : :
615 [ - + ]: 278 : if ( bDimAsNew )
616 : : {
617 [ # # ][ # # ]: 0 : if( !refVar->ISA(SbxObject) )
[ # # ]
618 : : {
619 [ # # ]: 0 : SbxBase* pValObjBase = refVal->GetObject();
620 [ # # ]: 0 : if( pValObjBase == NULL )
621 : : {
622 [ # # ]: 0 : if( xPrevVarObj.Is() )
623 : : {
624 : : // Object is overwritten with NULL, instantiate init object
625 [ # # ]: 0 : DimAsNewRecoverHash &rDimAsNewRecoverHash = GaDimAsNewRecoverHash::get();
626 [ # # ]: 0 : DimAsNewRecoverHash::iterator it = rDimAsNewRecoverHash.find( refVar );
627 [ # # ][ # # ]: 0 : if( it != rDimAsNewRecoverHash.end() )
628 : : {
629 [ # # ]: 0 : const DimAsNewRecoverItem& rItem = it->second;
630 [ # # ]: 0 : if( rItem.m_pClassModule != NULL )
631 : : {
632 [ # # ][ # # ]: 0 : SbClassModuleObject* pNewObj = new SbClassModuleObject( rItem.m_pClassModule );
633 [ # # ]: 0 : pNewObj->SetName( rItem.m_aObjName );
634 [ # # ]: 0 : pNewObj->SetParent( rItem.m_pObjParent );
635 [ # # ]: 0 : refVar->PutObject( pNewObj );
636 : : }
637 [ # # ][ # # ]: 0 : else if( rItem.m_aObjClass.EqualsIgnoreCaseAscii( pCollectionStr ) )
638 : : {
639 [ # # ][ # # ]: 0 : BasicCollection* pNewCollection = new BasicCollection( String( RTL_CONSTASCII_USTRINGPARAM(pCollectionStr) ) );
[ # # ][ # # ]
[ # # ]
640 [ # # ]: 0 : pNewCollection->SetName( rItem.m_aObjName );
641 [ # # ]: 0 : pNewCollection->SetParent( rItem.m_pObjParent );
642 [ # # ]: 0 : refVar->PutObject( pNewCollection );
643 : : }
644 : : }
645 : : }
646 : : }
647 : : else
648 : : {
649 : : // Does old value exist?
650 : 0 : bool bFirstInit = !xPrevVarObj.Is();
651 [ # # ]: 0 : if( bFirstInit )
652 : : {
653 : : // Store information to instantiate object later
654 [ # # ][ # # ]: 0 : SbxObject* pValObj = PTR_CAST(SbxObject,pValObjBase);
[ # # ][ # # ]
655 [ # # ]: 0 : if( pValObj != NULL )
656 : : {
657 [ # # ]: 0 : String aObjClass = pValObj->GetClassName();
658 : :
659 [ # # ][ # # ]: 0 : SbClassModuleObject* pClassModuleObj = PTR_CAST(SbClassModuleObject,pValObjBase);
[ # # ][ # # ]
660 [ # # ]: 0 : DimAsNewRecoverHash &rDimAsNewRecoverHash = GaDimAsNewRecoverHash::get();
661 [ # # ]: 0 : if( pClassModuleObj != NULL )
662 : : {
663 : 0 : SbModule* pClassModule = pClassModuleObj->getClassModule();
664 [ # # ]: 0 : rDimAsNewRecoverHash[refVar] =
665 [ # # ][ # # ]: 0 : DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), pClassModule );
[ # # ][ # # ]
[ # # ]
666 : : }
667 [ # # ][ # # ]: 0 : else if( aObjClass.EqualsIgnoreCaseAscii( "Collection" ) )
668 : : {
669 [ # # ]: 0 : rDimAsNewRecoverHash[refVar] =
670 [ # # ][ # # ]: 0 : DimAsNewRecoverItem( aObjClass, pValObj->GetName(), pValObj->GetParent(), NULL );
[ # # ][ # # ]
[ # # ]
671 [ # # ]: 0 : }
672 : : }
673 : : }
674 : : }
675 : : }
676 : : }
677 : :
678 : :
679 [ + + ]: 278 : if( bFlagsChanged )
680 [ + - ]: 278 : refVar->SetFlags( n );
681 : : }
682 : : }
683 : :
684 : 268 : void SbiRuntime::StepSET()
685 : : {
686 [ + - ]: 268 : SbxVariableRef refVal = PopVar();
687 [ + - ]: 268 : SbxVariableRef refVar = PopVar();
688 [ + - ][ + - ]: 268 : StepSET_Impl( refVal, refVar, bVBAEnabled ); // this is really assigment
[ + - ]
689 : 268 : }
690 : :
691 : 4 : void SbiRuntime::StepVBASET()
692 : : {
693 [ + - ]: 4 : SbxVariableRef refVal = PopVar();
694 [ + - ]: 4 : SbxVariableRef refVar = PopVar();
695 : : // don't handle default property
696 [ + - ][ + - ]: 4 : StepSET_Impl( refVal, refVar, false ); // set obj = something
[ + - ]
697 : 4 : }
698 : :
699 : :
700 : 0 : void SbiRuntime::StepLSET()
701 : : {
702 [ # # ]: 0 : SbxVariableRef refVal = PopVar();
703 [ # # ]: 0 : SbxVariableRef refVar = PopVar();
704 [ # # ][ # # ]: 0 : if( refVar->GetType() != SbxSTRING
[ # # ][ # # ]
705 [ # # ]: 0 : || refVal->GetType() != SbxSTRING )
706 [ # # ]: 0 : Error( SbERR_INVALID_USAGE_OBJECT );
707 : : else
708 : : {
709 : 0 : sal_uInt16 n = refVar->GetFlags();
710 [ # # ]: 0 : if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
711 : 0 : refVar->SetFlag( SBX_WRITE );
712 [ # # ][ # # ]: 0 : String aRefVarString = refVar->GetString();
713 [ # # ][ # # ]: 0 : String aRefValString = refVal->GetString();
714 : :
715 : 0 : sal_uInt16 nVarStrLen = aRefVarString.Len();
716 : 0 : sal_uInt16 nValStrLen = aRefValString.Len();
717 [ # # ]: 0 : String aNewStr;
718 [ # # ]: 0 : if( nVarStrLen > nValStrLen )
719 : : {
720 [ # # ]: 0 : aRefVarString.Fill(nVarStrLen,' ');
721 [ # # ][ # # ]: 0 : aNewStr = aRefValString.Copy( 0, nValStrLen );
[ # # ]
722 [ # # ][ # # ]: 0 : aNewStr += aRefVarString.Copy( nValStrLen, nVarStrLen - nValStrLen );
[ # # ]
723 : : }
724 : : else
725 : : {
726 [ # # ][ # # ]: 0 : aNewStr = aRefValString.Copy( 0, nVarStrLen );
[ # # ]
727 : : }
728 : :
729 [ # # ][ # # ]: 0 : refVar->PutString( aNewStr );
730 [ # # ][ # # ]: 0 : refVar->SetFlags( n );
[ # # ]
731 [ # # ][ # # ]: 0 : }
732 : 0 : }
733 : :
734 : 0 : void SbiRuntime::StepRSET()
735 : : {
736 [ # # ]: 0 : SbxVariableRef refVal = PopVar();
737 [ # # ]: 0 : SbxVariableRef refVar = PopVar();
738 [ # # ][ # # ]: 0 : if( refVar->GetType() != SbxSTRING
[ # # ][ # # ]
739 [ # # ]: 0 : || refVal->GetType() != SbxSTRING )
740 [ # # ]: 0 : Error( SbERR_INVALID_USAGE_OBJECT );
741 : : else
742 : : {
743 : 0 : sal_uInt16 n = refVar->GetFlags();
744 [ # # ]: 0 : if( (SbxVariable*) refVar == (SbxVariable*) pMeth )
745 : 0 : refVar->SetFlag( SBX_WRITE );
746 [ # # ][ # # ]: 0 : String aRefVarString = refVar->GetString();
747 [ # # ][ # # ]: 0 : String aRefValString = refVal->GetString();
748 : :
749 : 0 : sal_uInt16 nPos = 0;
750 : 0 : sal_uInt16 nVarStrLen = aRefVarString.Len();
751 [ # # ]: 0 : if( nVarStrLen > aRefValString.Len() )
752 : : {
753 [ # # ]: 0 : aRefVarString.Fill(nVarStrLen,' ');
754 : 0 : nPos = nVarStrLen - aRefValString.Len();
755 : : }
756 [ # # ][ # # ]: 0 : aRefVarString = aRefVarString.Copy( 0, nPos );
[ # # ]
757 [ # # ][ # # ]: 0 : aRefVarString += aRefValString.Copy( 0, nVarStrLen - nPos );
[ # # ]
758 [ # # ][ # # ]: 0 : refVar->PutString(aRefVarString);
759 : :
760 [ # # ][ # # ]: 0 : refVar->SetFlags( n );
761 [ # # ][ # # ]: 0 : }
762 : 0 : }
763 : :
764 : : // laying down TOS in TOS-1, then set ReadOnly-Bit
765 : :
766 : 184 : void SbiRuntime::StepPUTC()
767 : : {
768 [ + - ]: 184 : SbxVariableRef refVal = PopVar();
769 [ + - ]: 184 : SbxVariableRef refVar = PopVar();
770 : 184 : refVar->SetFlag( SBX_WRITE );
771 [ + - ]: 184 : *refVar = *refVal;
772 : 184 : refVar->ResetFlag( SBX_WRITE );
773 [ + - ][ + - ]: 184 : refVar->SetFlag( SBX_CONST );
774 : 184 : }
775 : :
776 : : // DIM
777 : : // TOS = variable for the array with dimension information as parameter
778 : :
779 : 100 : void SbiRuntime::StepDIM()
780 : : {
781 [ + - ]: 100 : SbxVariableRef refVar = PopVar();
782 [ + - ][ + - ]: 100 : DimImpl( refVar );
[ + - ]
783 : 100 : }
784 : :
785 : : // #56204 swap out DIM-functionality into a help method (step0.cxx)
786 : 112 : void SbiRuntime::DimImpl( SbxVariableRef refVar )
787 : : {
788 : : // If refDim then this DIM statement is terminating a ReDIM and
789 : : // previous StepERASE_CLEAR for an array, the following actions have
790 : : // been delayed from ( StepERASE_CLEAR ) 'till here
791 [ - + ]: 112 : if ( refRedim )
792 : : {
793 [ # # ]: 0 : if ( !refRedimpArray ) // only erase the array not ReDim Preserve
794 [ # # ]: 0 : lcl_eraseImpl( refVar, bVBAEnabled );
795 [ # # ]: 0 : SbxDataType eType = refVar->GetType();
796 [ # # ]: 0 : lcl_clearImpl( refVar, eType );
797 [ # # ]: 0 : refRedim = NULL;
798 : : }
799 : 112 : SbxArray* pDims = refVar->GetParameters();
800 : : // must have an even number of arguments
801 : : // have in mind that Arg[0] does not count!
802 [ - + ][ - + ]: 112 : if( pDims && !( pDims->Count() & 1 ) )
[ + + ]
803 : 0 : StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
804 : : else
805 : : {
806 [ + + ]: 112 : SbxDataType eType = refVar->IsFixed() ? refVar->GetType() : SbxVARIANT;
807 [ + - ]: 112 : SbxDimArray* pArray = new SbxDimArray( eType );
808 : : // allow arrays without dimension information, too (VB-compatible)
809 [ + + ]: 112 : if( pDims )
810 : : {
811 : 68 : refVar->ResetFlag( SBX_VAR_TO_DIM );
812 : :
813 [ + + ]: 140 : for( sal_uInt16 i = 1; i < pDims->Count(); )
814 : : {
815 : 72 : sal_Int32 lb = pDims->Get( i++ )->GetLong();
816 : 72 : sal_Int32 ub = pDims->Get( i++ )->GetLong();
817 [ - + ]: 72 : if( ub < lb )
818 : 0 : Error( SbERR_OUT_OF_RANGE ), ub = lb;
819 : 72 : pArray->AddDim32( lb, ub );
820 [ + + ]: 72 : if ( lb != ub )
821 : 16 : pArray->setHasFixedSize( true );
822 : : }
823 : : }
824 : : else
825 : : {
826 : : // #62867 On creating an array of the length 0, create
827 : : // a dimension (like for Uno-Sequences of the length 0)
828 : 44 : pArray->unoAddDim( 0, -1 );
829 : : }
830 : 112 : sal_uInt16 nSavFlags = refVar->GetFlags();
831 : 112 : refVar->ResetFlag( SBX_FIXED );
832 : 112 : refVar->PutObject( pArray );
833 : 112 : refVar->SetFlags( nSavFlags );
834 : 112 : refVar->SetParameters( NULL );
835 : : }
836 : 112 : }
837 : :
838 : : // REDIM
839 : : // TOS = variable for the array
840 : : // argv = dimension information
841 : :
842 : 0 : void SbiRuntime::StepREDIM()
843 : : {
844 : : // Nothing different than dim at the moment because
845 : : // a double dim is already recognized by the compiler.
846 : 0 : StepDIM();
847 : 0 : }
848 : :
849 : :
850 : : // Helper function for StepREDIMP
851 : 0 : void implCopyDimArray( SbxDimArray* pNewArray, SbxDimArray* pOldArray, short nMaxDimIndex,
852 : : short nActualDim, sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds )
853 : : {
854 : 0 : sal_Int32& ri = pActualIndices[nActualDim];
855 [ # # ]: 0 : for( ri = pLowerBounds[nActualDim] ; ri <= pUpperBounds[nActualDim] ; ri++ )
856 : : {
857 [ # # ]: 0 : if( nActualDim < nMaxDimIndex )
858 : : {
859 : : implCopyDimArray( pNewArray, pOldArray, nMaxDimIndex, nActualDim + 1,
860 : 0 : pActualIndices, pLowerBounds, pUpperBounds );
861 : : }
862 : : else
863 : : {
864 : 0 : SbxVariable* pSource = pOldArray->Get32( pActualIndices );
865 : 0 : SbxVariable* pDest = pNewArray->Get32( pActualIndices );
866 [ # # ][ # # ]: 0 : if( pSource && pDest )
867 : 0 : *pDest = *pSource;
868 : : }
869 : : }
870 : 0 : }
871 : :
872 : : // REDIM PRESERVE
873 : : // TOS = variable for the array
874 : : // argv = dimension information
875 : :
876 : 0 : void SbiRuntime::StepREDIMP()
877 : : {
878 [ # # ]: 0 : SbxVariableRef refVar = PopVar();
879 [ # # ][ # # ]: 0 : DimImpl( refVar );
880 : :
881 : : // Now check, if we can copy from the old array
882 [ # # ]: 0 : if( refRedimpArray.Is() )
883 : : {
884 [ # # ]: 0 : SbxBase* pElemObj = refVar->GetObject();
885 [ # # ][ # # ]: 0 : SbxDimArray* pNewArray = PTR_CAST(SbxDimArray,pElemObj);
[ # # ][ # # ]
886 : 0 : SbxDimArray* pOldArray = (SbxDimArray*)(SbxArray*)refRedimpArray;
887 [ # # ]: 0 : if( pNewArray )
888 : : {
889 [ # # ]: 0 : short nDimsNew = pNewArray->GetDims();
890 [ # # ]: 0 : short nDimsOld = pOldArray->GetDims();
891 : 0 : short nDims = nDimsNew;
892 : 0 : bool bRangeError = false;
893 : :
894 : : // Store dims to use them for copying later
895 [ # # ]: 0 : sal_Int32* pLowerBounds = new sal_Int32[nDims];
896 [ # # ]: 0 : sal_Int32* pUpperBounds = new sal_Int32[nDims];
897 [ # # ]: 0 : sal_Int32* pActualIndices = new sal_Int32[nDims];
898 : :
899 [ # # ]: 0 : if( nDimsOld != nDimsNew )
900 : : {
901 : 0 : bRangeError = true;
902 : : }
903 : : else
904 : : {
905 : : // Compare bounds
906 [ # # ]: 0 : for( short i = 1 ; i <= nDims ; i++ )
907 : : {
908 : : sal_Int32 lBoundNew, uBoundNew;
909 : : sal_Int32 lBoundOld, uBoundOld;
910 [ # # ]: 0 : pNewArray->GetDim32( i, lBoundNew, uBoundNew );
911 [ # # ]: 0 : pOldArray->GetDim32( i, lBoundOld, uBoundOld );
912 [ # # ]: 0 : lBoundNew = std::max( lBoundNew, lBoundOld );
913 [ # # ]: 0 : uBoundNew = std::min( uBoundNew, uBoundOld );
914 : 0 : short j = i - 1;
915 : 0 : pActualIndices[j] = pLowerBounds[j] = lBoundNew;
916 : 0 : pUpperBounds[j] = uBoundNew;
917 : : }
918 : : }
919 : :
920 [ # # ]: 0 : if( bRangeError )
921 : : {
922 [ # # ]: 0 : StarBASIC::Error( SbERR_OUT_OF_RANGE );
923 : : }
924 : : else
925 : : {
926 : : // Copy data from old array by going recursively through all dimensions
927 : : // (It would be faster to work on the flat internal data array of an
928 : : // SbyArray but this solution is clearer and easier)
929 : : implCopyDimArray( pNewArray, pOldArray, nDims - 1,
930 [ # # ]: 0 : 0, pActualIndices, pLowerBounds, pUpperBounds );
931 : : }
932 : :
933 [ # # ]: 0 : delete[] pUpperBounds;
934 [ # # ]: 0 : delete[] pLowerBounds;
935 [ # # ]: 0 : delete[] pActualIndices;
936 [ # # ]: 0 : refRedimpArray = NULL;
937 : : }
938 [ # # ]: 0 : }
939 : :
940 : 0 : }
941 : :
942 : : // REDIM_COPY
943 : : // TOS = Array-Variable, Reference to array is copied
944 : : // Variable is cleared as in ERASE
945 : :
946 : 0 : void SbiRuntime::StepREDIMP_ERASE()
947 : : {
948 [ # # ]: 0 : SbxVariableRef refVar = PopVar();
949 [ # # ]: 0 : refRedim = refVar;
950 [ # # ]: 0 : SbxDataType eType = refVar->GetType();
951 [ # # ]: 0 : if( eType & SbxARRAY )
952 : : {
953 [ # # ]: 0 : SbxBase* pElemObj = refVar->GetObject();
954 [ # # ][ # # ]: 0 : SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
[ # # ][ # # ]
955 [ # # ]: 0 : if( pDimArray )
956 : : {
957 [ # # ]: 0 : refRedimpArray = pDimArray;
958 : : }
959 : :
960 : : }
961 : : else
962 [ # # ][ # # ]: 0 : if( refVar->IsFixed() )
963 [ # # ]: 0 : refVar->Clear();
964 : : else
965 [ # # ][ # # ]: 0 : refVar->SetType( SbxEMPTY );
966 : 0 : }
967 : :
968 : 0 : void lcl_clearImpl( SbxVariableRef& refVar, SbxDataType& eType )
969 : : {
970 : 0 : sal_uInt16 nSavFlags = refVar->GetFlags();
971 : 0 : refVar->ResetFlag( SBX_FIXED );
972 : 0 : refVar->SetType( SbxDataType(eType & 0x0FFF) );
973 : 0 : refVar->SetFlags( nSavFlags );
974 : 0 : refVar->Clear();
975 : 0 : }
976 : :
977 : 0 : void lcl_eraseImpl( SbxVariableRef& refVar, bool bVBAEnabled )
978 : : {
979 [ # # ]: 0 : SbxDataType eType = refVar->GetType();
980 [ # # ]: 0 : if( eType & SbxARRAY )
981 : : {
982 [ # # ]: 0 : if ( bVBAEnabled )
983 : : {
984 [ # # ]: 0 : SbxBase* pElemObj = refVar->GetObject();
985 [ # # ][ # # ]: 0 : SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
[ # # ][ # # ]
986 : 0 : bool bClearValues = true;
987 [ # # ]: 0 : if( pDimArray )
988 : : {
989 [ # # ]: 0 : if ( pDimArray->hasFixedSize() )
990 : : {
991 : : // Clear all Value(s)
992 [ # # ]: 0 : pDimArray->SbxArray::Clear();
993 : 0 : bClearValues = false;
994 : : }
995 : : else
996 [ # # ]: 0 : pDimArray->Clear(); // clear Dims
997 : : }
998 [ # # ]: 0 : if ( bClearValues )
999 : : {
1000 [ # # ][ # # ]: 0 : SbxArray* pArray = PTR_CAST(SbxArray,pElemObj);
[ # # ][ # # ]
1001 [ # # ]: 0 : if ( pArray )
1002 [ # # ]: 0 : pArray->Clear();
1003 : : }
1004 : : }
1005 : : else
1006 : : // Arrays have on an erase to VB quite a complex behaviour. Here are
1007 : : // only the type problems at REDIM (#26295) removed at first:
1008 : : // Set type hard onto the array-type, because a variable with array is
1009 : : // SbxOBJECT. At REDIM there's an SbxOBJECT-array generated then and
1010 : : // the original type is lost -> runtime error
1011 [ # # ]: 0 : lcl_clearImpl( refVar, eType );
1012 : : }
1013 : : else
1014 [ # # ][ # # ]: 0 : if( refVar->IsFixed() )
1015 [ # # ]: 0 : refVar->Clear();
1016 : : else
1017 [ # # ]: 0 : refVar->SetType( SbxEMPTY );
1018 : 0 : }
1019 : :
1020 : : // delete variable
1021 : : // TOS = variable
1022 : :
1023 : 0 : void SbiRuntime::StepERASE()
1024 : : {
1025 [ # # ]: 0 : SbxVariableRef refVar = PopVar();
1026 [ # # ][ # # ]: 0 : lcl_eraseImpl( refVar, bVBAEnabled );
1027 : 0 : }
1028 : :
1029 : 0 : void SbiRuntime::StepERASE_CLEAR()
1030 : : {
1031 [ # # ]: 0 : refRedim = PopVar();
1032 : 0 : }
1033 : :
1034 : 0 : void SbiRuntime::StepARRAYACCESS()
1035 : : {
1036 [ # # ]: 0 : if( !refArgv )
1037 [ # # ]: 0 : StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
1038 [ # # ]: 0 : SbxVariableRef refVar = PopVar();
1039 [ # # ]: 0 : refVar->SetParameters( refArgv );
1040 [ # # ]: 0 : PopArgv();
1041 [ # # ][ # # ]: 0 : PushVar( CheckArray( refVar ) );
[ # # ]
1042 : 0 : }
1043 : :
1044 : 0 : void SbiRuntime::StepBYVAL()
1045 : : {
1046 : : // Copy variable on stack to break call by reference
1047 [ # # ]: 0 : SbxVariableRef pVar = PopVar();
1048 [ # # ]: 0 : SbxDataType t = pVar->GetType();
1049 : :
1050 [ # # ][ # # ]: 0 : SbxVariable* pCopyVar = new SbxVariable( t );
1051 : 0 : pCopyVar->SetFlag( SBX_READWRITE );
1052 [ # # ]: 0 : *pCopyVar = *pVar;
1053 : :
1054 [ # # ][ # # ]: 0 : PushVar( pCopyVar );
1055 : 0 : }
1056 : :
1057 : : // establishing an argv
1058 : : // nOp1 stays as it is -> 1st element is the return value
1059 : :
1060 : 2518 : void SbiRuntime::StepARGC()
1061 : : {
1062 : 2518 : PushArgv();
1063 [ + - ]: 2518 : refArgv = new SbxArray;
1064 : 2518 : nArgc = 1;
1065 : 2518 : }
1066 : :
1067 : : // storing an argument in Argv
1068 : :
1069 : 4260 : void SbiRuntime::StepARGV()
1070 : : {
1071 [ - + ]: 4260 : if( !refArgv )
1072 : 0 : StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
1073 : : else
1074 : : {
1075 [ + - ]: 4260 : SbxVariableRef pVal = PopVar();
1076 : :
1077 : : // Before fix of #94916:
1078 [ + - ][ + - ]: 4260 : if( pVal->ISA(SbxMethod) || pVal->ISA(SbUnoProperty) || pVal->ISA(SbProcedureProperty) )
[ + + ][ + - ]
[ + - ][ + + ]
[ + - ][ + - ]
[ - + ][ + + ]
1079 : : {
1080 : : // evaluate methods and properties!
1081 [ + - ][ + - ]: 272 : SbxVariable* pRes = new SbxVariable( *pVal );
1082 [ + - ]: 272 : pVal = pRes;
1083 : : }
1084 [ + - ][ + - ]: 4260 : refArgv->Put( pVal, nArgc++ );
1085 : : }
1086 : 4260 : }
1087 : :
1088 : : // Input to Variable. The variable is on TOS and is
1089 : : // is removed afterwards.
1090 : :
1091 : 0 : void SbiRuntime::StepINPUT()
1092 : : {
1093 [ # # ]: 0 : String s;
1094 : 0 : char ch = 0;
1095 : : SbError err;
1096 : : // Skip whitespace
1097 [ # # ][ # # ]: 0 : while( ( err = pIosys->GetError() ) == 0 )
1098 : : {
1099 [ # # ]: 0 : ch = pIosys->Read();
1100 [ # # ][ # # ]: 0 : if( ch != ' ' && ch != '\t' && ch != '\n' )
[ # # ]
1101 : 0 : break;
1102 : : }
1103 [ # # ]: 0 : if( !err )
1104 : : {
1105 : : // Scan until comma or whitespace
1106 [ # # ]: 0 : char sep = ( ch == '"' ) ? ch : 0;
1107 [ # # ][ # # ]: 0 : if( sep ) ch = pIosys->Read();
1108 [ # # ][ # # ]: 0 : while( ( err = pIosys->GetError() ) == 0 )
1109 : : {
1110 [ # # ]: 0 : if( ch == sep )
1111 : : {
1112 [ # # ]: 0 : ch = pIosys->Read();
1113 [ # # ]: 0 : if( ch != sep )
1114 : 0 : break;
1115 : : }
1116 [ # # ][ # # ]: 0 : else if( !sep && (ch == ',' || ch == '\n') )
[ # # ]
1117 : 0 : break;
1118 [ # # ]: 0 : s += ch;
1119 [ # # ]: 0 : ch = pIosys->Read();
1120 : : }
1121 : : // skip whitespace
1122 [ # # ][ # # ]: 0 : if( ch == ' ' || ch == '\t' )
1123 [ # # ][ # # ]: 0 : while( ( err = pIosys->GetError() ) == 0 )
1124 : : {
1125 [ # # ][ # # ]: 0 : if( ch != ' ' && ch != '\t' && ch != '\n' )
[ # # ]
1126 : 0 : break;
1127 [ # # ]: 0 : ch = pIosys->Read();
1128 : : }
1129 : : }
1130 [ # # ]: 0 : if( !err )
1131 : : {
1132 [ # # ]: 0 : SbxVariableRef pVar = GetTOS();
1133 : : // try to fill the variable with a numeric value first,
1134 : : // then with a string value
1135 [ # # ][ # # ]: 0 : if( !pVar->IsFixed() || pVar->IsNumeric() )
[ # # ][ # # ]
[ # # ]
1136 : : {
1137 : 0 : sal_uInt16 nLen = 0;
1138 [ # # ][ # # ]: 0 : if( !pVar->Scan( s, &nLen ) )
1139 : : {
1140 [ # # ]: 0 : err = SbxBase::GetError();
1141 [ # # ]: 0 : SbxBase::ResetError();
1142 : : }
1143 : : // the value has to be scanned in completely
1144 [ # # ][ # # ]: 0 : else if( nLen != s.Len() && !pVar->PutString( s ) )
[ # # ][ # # ]
[ # # ]
[ # # # # ]
1145 : : {
1146 [ # # ]: 0 : err = SbxBase::GetError();
1147 [ # # ]: 0 : SbxBase::ResetError();
1148 : : }
1149 [ # # ][ # # ]: 0 : else if( nLen != s.Len() && pVar->IsNumeric() )
[ # # ][ # # ]
1150 : : {
1151 [ # # ]: 0 : err = SbxBase::GetError();
1152 [ # # ]: 0 : SbxBase::ResetError();
1153 [ # # ]: 0 : if( !err )
1154 : 0 : err = SbERR_CONVERSION;
1155 : : }
1156 : : }
1157 : : else
1158 : : {
1159 [ # # ][ # # ]: 0 : pVar->PutString( s );
1160 [ # # ]: 0 : err = SbxBase::GetError();
1161 [ # # ]: 0 : SbxBase::ResetError();
1162 [ # # ]: 0 : }
1163 : : }
1164 [ # # ]: 0 : if( err == SbERR_USER_ABORT )
1165 [ # # ]: 0 : Error( err );
1166 [ # # ]: 0 : else if( err )
1167 : : {
1168 [ # # ][ # # ]: 0 : if( pRestart && !pIosys->GetChannel() )
[ # # ]
1169 : 0 : pCode = pRestart;
1170 : : else
1171 [ # # ]: 0 : Error( err );
1172 : : }
1173 : : else
1174 : : {
1175 [ # # ][ # # ]: 0 : PopVar();
1176 [ # # ]: 0 : }
1177 : 0 : }
1178 : :
1179 : : // Line Input to Variable. The variable is on TOS and is
1180 : : // deleted afterwards.
1181 : :
1182 : 0 : void SbiRuntime::StepLINPUT()
1183 : : {
1184 : 0 : rtl::OString aInput;
1185 [ # # ]: 0 : pIosys->Read( aInput );
1186 [ # # ][ # # ]: 0 : Error( pIosys->GetError() );
1187 [ # # ]: 0 : SbxVariableRef p = PopVar();
1188 [ # # ][ # # ]: 0 : p->PutString(rtl::OStringToOUString(aInput, osl_getThreadTextEncoding()));
[ # # ][ # # ]
1189 : 0 : }
1190 : :
1191 : : // end of program
1192 : :
1193 : 0 : void SbiRuntime::StepSTOP()
1194 : : {
1195 : 0 : pInst->Stop();
1196 : 0 : }
1197 : :
1198 : :
1199 : 64 : void SbiRuntime::StepINITFOR()
1200 : : {
1201 : 64 : PushFor();
1202 : 64 : }
1203 : :
1204 : 0 : void SbiRuntime::StepINITFOREACH()
1205 : : {
1206 : 0 : PushForEach();
1207 : 0 : }
1208 : :
1209 : : // increment FOR-variable
1210 : :
1211 : 420 : void SbiRuntime::StepNEXT()
1212 : : {
1213 [ - + ]: 420 : if( !pForStk )
1214 : : {
1215 : 0 : StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
1216 : 420 : return;
1217 : : }
1218 [ + - ]: 420 : if( pForStk->eForType == FOR_TO )
1219 : 420 : pForStk->refVar->Compute( SbxPLUS, *pForStk->refInc );
1220 : : }
1221 : :
1222 : : // beginning CASE: TOS in CASE-stack
1223 : :
1224 : 220 : void SbiRuntime::StepCASE()
1225 : : {
1226 [ + - ]: 220 : if( !refCaseStk.Is() )
1227 [ + - ][ + - ]: 220 : refCaseStk = new SbxArray;
[ + - ]
1228 [ + - ]: 220 : SbxVariableRef xVar = PopVar();
1229 [ + - ][ + - ]: 220 : refCaseStk->Put( xVar, refCaseStk->Count() );
[ + - ]
1230 : 220 : }
1231 : :
1232 : : // end CASE: free variable
1233 : :
1234 : 220 : void SbiRuntime::StepENDCASE()
1235 : : {
1236 [ + - ][ - + ]: 220 : if( !refCaseStk || !refCaseStk->Count() )
[ - + ]
1237 : 0 : StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
1238 : : else
1239 : 220 : refCaseStk->Remove( refCaseStk->Count() - 1 );
1240 : 220 : }
1241 : :
1242 : :
1243 : 0 : void SbiRuntime::StepSTDERROR()
1244 : : {
1245 : 0 : pError = NULL; bError = true;
1246 [ # # ]: 0 : pInst->aErrorMsg = String();
1247 : 0 : pInst->nErr = 0L;
1248 : 0 : pInst->nErl = 0;
1249 : 0 : nError = 0L;
1250 [ # # ][ # # ]: 0 : SbxErrObject::getUnoErrObject()->Clear();
1251 : 0 : }
1252 : :
1253 : 0 : void SbiRuntime::StepNOERROR()
1254 : : {
1255 [ # # ]: 0 : pInst->aErrorMsg = String();
1256 : 0 : pInst->nErr = 0L;
1257 : 0 : pInst->nErl = 0;
1258 : 0 : nError = 0L;
1259 [ # # ][ # # ]: 0 : SbxErrObject::getUnoErrObject()->Clear();
1260 : 0 : bError = false;
1261 : 0 : }
1262 : :
1263 : : // leave UP
1264 : :
1265 : 921 : void SbiRuntime::StepLEAVE()
1266 : : {
1267 : 921 : bRun = false;
1268 : : // If VBA and we are leaving an ErrorHandler then clear the error ( it's been processed )
1269 [ + + ][ + - ]: 921 : if ( bInError && pError )
1270 [ + - ][ + - ]: 4 : SbxErrObject::getUnoErrObject()->Clear();
1271 : 921 : }
1272 : :
1273 : 206 : void SbiRuntime::StepCHANNEL() // TOS = channel number
1274 : : {
1275 [ + - ]: 206 : SbxVariableRef pChan = PopVar();
1276 [ + - ]: 206 : short nChan = pChan->GetInteger();
1277 : 206 : pIosys->SetChannel( nChan );
1278 [ + - ][ + - ]: 206 : Error( pIosys->GetError() );
[ + - ]
1279 : 206 : }
1280 : :
1281 : 184 : void SbiRuntime::StepCHANNEL0()
1282 : : {
1283 : 184 : pIosys->ResetChannel();
1284 : 184 : }
1285 : :
1286 : 182 : void SbiRuntime::StepPRINT() // print TOS
1287 : : {
1288 [ + - ]: 182 : SbxVariableRef p = PopVar();
1289 [ + - ][ + - ]: 182 : String s1 = p->GetString();
1290 [ + - ]: 182 : String s;
1291 [ + - ][ + - ]: 182 : if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
[ + - ][ - + ]
[ - + ]
1292 [ # # ]: 0 : s = ' '; // one blank before
1293 [ + - ]: 182 : s += s1;
1294 [ + - ][ + - ]: 182 : rtl::OString aByteStr(rtl::OUStringToOString(s, osl_getThreadTextEncoding()));
[ + - ]
1295 [ + - ]: 182 : pIosys->Write( aByteStr );
1296 [ + - ][ + - ]: 182 : Error( pIosys->GetError() );
[ + - ][ + - ]
[ + - ]
1297 : 182 : }
1298 : :
1299 : 0 : void SbiRuntime::StepPRINTF() // print TOS in field
1300 : : {
1301 [ # # ]: 0 : SbxVariableRef p = PopVar();
1302 [ # # ][ # # ]: 0 : String s1 = p->GetString();
1303 [ # # ]: 0 : String s;
1304 [ # # ][ # # ]: 0 : if( p->GetType() >= SbxINTEGER && p->GetType() <= SbxDOUBLE )
[ # # ][ # # ]
[ # # ]
1305 [ # # ]: 0 : s = ' ';
1306 [ # # ]: 0 : s += s1;
1307 [ # # ]: 0 : s.Expand( 14, ' ' );
1308 [ # # ][ # # ]: 0 : rtl::OString aByteStr(rtl::OUStringToOString(s, osl_getThreadTextEncoding()));
[ # # ]
1309 [ # # ]: 0 : pIosys->Write( aByteStr );
1310 [ # # ][ # # ]: 0 : Error( pIosys->GetError() );
[ # # ][ # # ]
[ # # ]
1311 : 0 : }
1312 : :
1313 : 0 : void SbiRuntime::StepWRITE() // write TOS
1314 : : {
1315 [ # # ]: 0 : SbxVariableRef p = PopVar();
1316 : : // Does the string have to be encapsulated?
1317 : 0 : char ch = 0;
1318 [ # # ]: 0 : switch (p->GetType() )
[ # # # ]
1319 : : {
1320 : 0 : case SbxSTRING: ch = '"'; break;
1321 : : case SbxCURRENCY:
1322 : : case SbxBOOL:
1323 : 0 : case SbxDATE: ch = '#'; break;
1324 : 0 : default: break;
1325 : : }
1326 [ # # ]: 0 : String s;
1327 [ # # ]: 0 : if( ch )
1328 [ # # ]: 0 : s += ch;
1329 [ # # ][ # # ]: 0 : s += p->GetString();
1330 [ # # ]: 0 : if( ch )
1331 [ # # ]: 0 : s += ch;
1332 [ # # ][ # # ]: 0 : rtl::OString aByteStr(rtl::OUStringToOString(s, osl_getThreadTextEncoding()));
[ # # ]
1333 [ # # ]: 0 : pIosys->Write( aByteStr );
1334 [ # # ][ # # ]: 0 : Error( pIosys->GetError() );
[ # # ][ # # ]
1335 : 0 : }
1336 : :
1337 : 0 : void SbiRuntime::StepRENAME() // Rename Tos+1 to Tos
1338 : : {
1339 [ # # ]: 0 : SbxVariableRef pTos1 = PopVar();
1340 [ # # ]: 0 : SbxVariableRef pTos = PopVar();
1341 [ # # ][ # # ]: 0 : String aDest = pTos1->GetString();
1342 [ # # ][ # # ]: 0 : String aSource = pTos->GetString();
1343 : :
1344 [ # # ][ # # ]: 0 : if( hasUno() )
1345 : : {
1346 [ # # ]: 0 : implStepRenameUCB( aSource, aDest );
1347 : : }
1348 : : else
1349 : : {
1350 [ # # ]: 0 : implStepRenameOSL( aSource, aDest );
1351 [ # # ][ # # ]: 0 : }
[ # # ][ # # ]
1352 : 0 : }
1353 : :
1354 : : // TOS = Prompt
1355 : :
1356 : 0 : void SbiRuntime::StepPROMPT()
1357 : : {
1358 [ # # ]: 0 : SbxVariableRef p = PopVar();
1359 [ # # ][ # # ]: 0 : rtl::OString aStr(rtl::OUStringToOString(p->GetString(), osl_getThreadTextEncoding()));
[ # # ][ # # ]
1360 [ # # ]: 0 : pIosys->SetPrompt( aStr );
1361 : 0 : }
1362 : :
1363 : : // Set Restart point
1364 : :
1365 : 0 : void SbiRuntime::StepRESTART()
1366 : : {
1367 : 0 : pRestart = pCode;
1368 : 0 : }
1369 : :
1370 : : // empty expression on stack for missing parameter
1371 : :
1372 : 0 : void SbiRuntime::StepEMPTY()
1373 : : {
1374 : : // #57915 The semantics of StepEMPTY() is the representation of a missing argument.
1375 : : // This is represented by the value 448 (SbERR_NAMED_NOT_FOUND) of the type error
1376 : : // in VB. StepEmpty should now rather be named StepMISSING() but the name is kept
1377 : : // to simplify matters.
1378 [ # # ][ # # ]: 0 : SbxVariableRef xVar = new SbxVariable( SbxVARIANT );
1379 [ # # ]: 0 : xVar->PutErr( 448 );
1380 [ # # ][ # # ]: 0 : PushVar( xVar );
1381 : 0 : }
1382 : :
1383 : : // TOS = error code
1384 : :
1385 : 0 : void SbiRuntime::StepERROR()
1386 : : {
1387 [ # # ]: 0 : SbxVariableRef refCode = PopVar();
1388 [ # # ]: 0 : sal_uInt16 n = refCode->GetUShort();
1389 [ # # ]: 0 : SbError error = StarBASIC::GetSfxFromVBError( n );
1390 [ # # ]: 0 : if ( bVBAEnabled )
1391 [ # # ]: 0 : pInst->Error( error );
1392 : : else
1393 [ # # ][ # # ]: 0 : Error( error );
1394 : 0 : }
1395 : :
1396 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|