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 :
21 : #include "runtime.hxx"
22 : #include "iosys.hxx"
23 : #include "image.hxx"
24 : #include "sbintern.hxx"
25 : #include "sbunoobj.hxx"
26 : #include "opcodes.hxx"
27 :
28 : #include <com/sun/star/container/XIndexAccess.hpp>
29 : #include <com/sun/star/script/XDefaultMethod.hpp>
30 : #include <com/sun/star/beans/XPropertySet.hpp>
31 : #include <com/sun/star/uno/Any.hxx>
32 : #include <comphelper/processfactory.hxx>
33 : #include <comphelper/string.hxx>
34 : #include <rtl/ustrbuf.hxx>
35 :
36 : using namespace com::sun::star::uno;
37 : using namespace com::sun::star::container;
38 : using namespace com::sun::star::lang;
39 : using namespace com::sun::star::beans;
40 : using namespace com::sun::star::script;
41 :
42 : using com::sun::star::uno::Reference;
43 :
44 : SbxVariable* getVBAConstant( const OUString& rName );
45 :
46 :
47 : // the bits in the String-ID:
48 : // 0x8000 - Argv is reserved
49 :
50 67 : SbxVariable* SbiRuntime::FindElement( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt32 nOp2,
51 : SbError nNotFound, bool bLocal, bool bStatic )
52 : {
53 67 : bool bIsVBAInterOp = SbiRuntime::isVBAEnabled();
54 67 : if( bIsVBAInterOp )
55 : {
56 0 : StarBASIC* pMSOMacroRuntimeLib = GetSbData()->pMSOMacroRuntimLib;
57 0 : if( pMSOMacroRuntimeLib != NULL )
58 : {
59 0 : pMSOMacroRuntimeLib->ResetFlag( SBX_EXTSEARCH );
60 : }
61 : }
62 :
63 67 : SbxVariable* pElem = NULL;
64 67 : if( !pObj )
65 : {
66 0 : Error( SbERR_NO_OBJECT );
67 0 : pElem = new SbxVariable;
68 : }
69 : else
70 : {
71 67 : bool bFatalError = false;
72 67 : SbxDataType t = (SbxDataType) nOp2;
73 67 : OUString aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) );
74 : // Hacky capture of Evaluate [] syntax
75 : // this should be tackled I feel at the pcode level
76 67 : if ( bIsVBAInterOp && aName.indexOf((sal_Unicode)'[') == 0 )
77 : {
78 : // emulate pcode here
79 0 : StepARGC();
80 : // psuedo StepLOADSC
81 0 : OUString sArg = aName.copy( 1, aName.getLength() - 2 );
82 0 : SbxVariable* p = new SbxVariable;
83 0 : p->PutString( sArg );
84 0 : PushVar( p );
85 0 : StepARGV();
86 0 : nOp1 = nOp1 | 0x8000; // indicate params are present
87 0 : aName = OUString("Evaluate");
88 : }
89 67 : if( bLocal )
90 : {
91 42 : if ( bStatic )
92 : {
93 0 : if ( pMeth )
94 : {
95 0 : pElem = pMeth->GetStatics()->Find( aName, SbxCLASS_DONTCARE );
96 : }
97 : }
98 :
99 42 : if ( !pElem )
100 : {
101 42 : pElem = refLocals->Find( aName, SbxCLASS_DONTCARE );
102 : }
103 : }
104 67 : if( !pElem )
105 : {
106 26 : bool bSave = rBasic.bNoRtl;
107 26 : rBasic.bNoRtl = true;
108 26 : pElem = pObj->Find( aName, SbxCLASS_DONTCARE );
109 :
110 : // #110004, #112015: Make private really private
111 26 : if( bLocal && pElem ) // Local as flag for global search
112 : {
113 0 : if( pElem->IsSet( SBX_PRIVATE ) )
114 : {
115 0 : SbiInstance* pInst_ = GetSbData()->pInst;
116 0 : if( pInst_ && pInst_->IsCompatibility() && pObj != pElem->GetParent() )
117 : {
118 0 : pElem = NULL; // Found but in wrong module!
119 : }
120 : // Interfaces: Use SBX_EXTFOUND
121 : }
122 : }
123 26 : rBasic.bNoRtl = bSave;
124 :
125 : // is it a global uno-identifier?
126 26 : if( bLocal && !pElem )
127 : {
128 1 : bool bSetName = true; // preserve normal behaviour
129 :
130 : // i#i68894# if VBAInterOp favour searching vba globals
131 : // over searching for uno classess
132 1 : if ( bVBAEnabled )
133 : {
134 : // Try Find in VBA symbols space
135 0 : pElem = rBasic.VBAFind( aName, SbxCLASS_DONTCARE );
136 0 : if ( pElem )
137 : {
138 0 : bSetName = false; // don't overwrite uno name
139 : }
140 : else
141 : {
142 0 : pElem = VBAConstantHelper::instance().getVBAConstant( aName );
143 : }
144 : }
145 :
146 1 : if( !pElem )
147 : {
148 : // #72382 ATTENTION! ALWAYS returns a result now
149 : // because of unknown modules!
150 1 : SbUnoClass* pUnoClass = findUnoClass( aName );
151 1 : if( pUnoClass )
152 : {
153 0 : pElem = new SbxVariable( t );
154 0 : SbxValues aRes( SbxOBJECT );
155 0 : aRes.pObj = pUnoClass;
156 0 : pElem->SbxVariable::Put( aRes );
157 : }
158 : }
159 :
160 : // #62939 If an uno-class has been found, the wrapper
161 : // object has to be held, because the uno-class, e. g.
162 : // "stardiv", has to be read out of the registry
163 : // every time again otherwise
164 1 : if( pElem )
165 : {
166 : // #63774 May not be saved too!!!
167 0 : pElem->SetFlag( SBX_DONTSTORE );
168 0 : pElem->SetFlag( SBX_NO_MODIFY);
169 :
170 : // #72382 save locally, all variables that have been declared
171 : // implicit would become global automatically otherwise!
172 0 : if ( bSetName )
173 : {
174 0 : pElem->SetName( aName );
175 : }
176 0 : refLocals->Put( pElem, refLocals->Count() );
177 : }
178 : }
179 :
180 26 : if( !pElem )
181 : {
182 : // not there and not in the object?
183 : // don't establish if that thing has parameters!
184 1 : if( nOp1 & 0x8000 )
185 : {
186 0 : bFatalError = true;
187 : }
188 :
189 : // else, if there are parameters, use different error code
190 1 : if( !bLocal || pImg->GetFlag( SBIMG_EXPLICIT ) )
191 : {
192 : // #39108 if explicit and as ELEM always a fatal error
193 0 : bFatalError = true;
194 :
195 :
196 0 : if( !( nOp1 & 0x8000 ) && nNotFound == SbERR_PROC_UNDEFINED )
197 : {
198 0 : nNotFound = SbERR_VAR_UNDEFINED;
199 : }
200 : }
201 1 : if( bFatalError )
202 : {
203 : // #39108 use dummy variable instead of fatal error
204 0 : if( !xDummyVar.Is() )
205 : {
206 0 : xDummyVar = new SbxVariable( SbxVARIANT );
207 : }
208 0 : pElem = xDummyVar;
209 :
210 0 : ClearArgvStack();
211 :
212 0 : Error( nNotFound, aName );
213 : }
214 : else
215 : {
216 1 : if ( bStatic )
217 : {
218 0 : pElem = StepSTATIC_Impl( aName, t );
219 : }
220 1 : if ( !pElem )
221 : {
222 1 : pElem = new SbxVariable( t );
223 1 : if( t != SbxVARIANT )
224 : {
225 0 : pElem->SetFlag( SBX_FIXED );
226 : }
227 1 : pElem->SetName( aName );
228 1 : refLocals->Put( pElem, refLocals->Count() );
229 : }
230 : }
231 : }
232 : }
233 : // #39108 Args can already be deleted!
234 67 : if( !bFatalError )
235 : {
236 67 : SetupArgs( pElem, nOp1 );
237 : }
238 : // because a particular call-type is requested
239 67 : if( pElem->IsA( TYPE(SbxMethod) ) )
240 : {
241 : // shall the type be converted?
242 2 : SbxDataType t2 = pElem->GetType();
243 2 : bool bSet = false;
244 2 : if( !( pElem->GetFlags() & SBX_FIXED ) )
245 : {
246 2 : if( t != SbxVARIANT && t != t2 &&
247 : t >= SbxINTEGER && t <= SbxSTRING )
248 : {
249 0 : pElem->SetType( t ), bSet = true;
250 : }
251 : }
252 : // assign pElem to a Ref, to delete a temp-var if applicable
253 2 : SbxVariableRef refTemp = pElem;
254 :
255 : // remove potential rests of the last call of the SbxMethod
256 : // free Write before, so that there's no error
257 2 : sal_uInt16 nSavFlags = pElem->GetFlags();
258 2 : pElem->SetFlag( SBX_READWRITE | SBX_NO_BROADCAST );
259 2 : pElem->SbxValue::Clear();
260 2 : pElem->SetFlags( nSavFlags );
261 :
262 : // don't touch before setting, as e. g. LEFT()
263 : // has to know the difference between Left$() and Left()
264 :
265 : // because the methods' parameters are cut away in PopVar()
266 2 : SbxVariable* pNew = new SbxMethod( *((SbxMethod*)pElem) );
267 : //OLD: SbxVariable* pNew = new SbxVariable( *pElem );
268 :
269 2 : pElem->SetParameters(0);
270 2 : pNew->SetFlag( SBX_READWRITE );
271 :
272 2 : if( bSet )
273 : {
274 0 : pElem->SetType( t2 );
275 : }
276 2 : pElem = pNew;
277 : }
278 : // consider index-access for UnoObjects
279 : // definitely we want this for VBA where properties are often
280 : // collections ( which need index access ), but lets only do
281 : // this if we actually have params following
282 65 : else if( bVBAEnabled && pElem->ISA(SbUnoProperty) && pElem->GetParameters() )
283 : {
284 0 : SbxVariableRef refTemp = pElem;
285 :
286 : // dissolve the notify while copying variable
287 0 : SbxVariable* pNew = new SbxVariable( *((SbxVariable*)pElem) );
288 0 : pElem->SetParameters( NULL );
289 0 : pElem = pNew;
290 67 : }
291 : }
292 67 : return CheckArray( pElem );
293 : }
294 :
295 : // for current scope (e. g. query from BASIC-IDE)
296 0 : SbxBase* SbiRuntime::FindElementExtern( const OUString& rName )
297 : {
298 : // don't expect pMeth to be != 0, as there are none set
299 : // in the RunInit yet
300 :
301 0 : SbxVariable* pElem = NULL;
302 0 : if( !pMod || !rName.getLength() )
303 : {
304 0 : return NULL;
305 : }
306 0 : if( refLocals )
307 : {
308 0 : pElem = refLocals->Find( rName, SbxCLASS_DONTCARE );
309 : }
310 0 : if ( !pElem && pMeth )
311 : {
312 : // for statics, set the method's name in front
313 0 : OUString aMethName = pMeth->GetName();
314 0 : aMethName += ":";
315 0 : aMethName += rName;
316 0 : pElem = pMod->Find(aMethName, SbxCLASS_DONTCARE);
317 : }
318 :
319 : // search in parameter list
320 0 : if( !pElem && pMeth )
321 : {
322 0 : SbxInfo* pInfo = pMeth->GetInfo();
323 0 : if( pInfo && refParams )
324 : {
325 0 : sal_uInt16 nParamCount = refParams->Count();
326 0 : sal_uInt16 j = 1;
327 0 : const SbxParamInfo* pParam = pInfo->GetParam( j );
328 0 : while( pParam )
329 : {
330 0 : if( pParam->aName.equalsIgnoreAsciiCase( rName ) )
331 : {
332 0 : if( j >= nParamCount )
333 : {
334 : // Parameter is missing
335 0 : pElem = new SbxVariable( SbxSTRING );
336 0 : pElem->PutString( OUString("<missing parameter>"));
337 : }
338 : else
339 : {
340 0 : pElem = refParams->Get( j );
341 : }
342 0 : break;
343 : }
344 0 : pParam = pInfo->GetParam( ++j );
345 : }
346 : }
347 : }
348 :
349 : // search in module
350 0 : if( !pElem )
351 : {
352 0 : bool bSave = rBasic.bNoRtl;
353 0 : rBasic.bNoRtl = true;
354 0 : pElem = pMod->Find( rName, SbxCLASS_DONTCARE );
355 0 : rBasic.bNoRtl = bSave;
356 : }
357 0 : return pElem;
358 : }
359 :
360 :
361 :
362 74 : void SbiRuntime::SetupArgs( SbxVariable* p, sal_uInt32 nOp1 )
363 : {
364 74 : if( nOp1 & 0x8000 )
365 : {
366 2 : if( !refArgv )
367 : {
368 0 : StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
369 : }
370 2 : bool bHasNamed = false;
371 : sal_uInt16 i;
372 2 : sal_uInt16 nArgCount = refArgv->Count();
373 6 : for( i = 1 ; i < nArgCount ; i++ )
374 : {
375 4 : if( !refArgv->GetAlias(i).isEmpty() )
376 : {
377 0 : bHasNamed = true; break;
378 : }
379 : }
380 2 : if( bHasNamed )
381 : {
382 0 : SbxInfo* pInfo = p->GetInfo();
383 0 : if( !pInfo )
384 : {
385 0 : bool bError_ = true;
386 :
387 0 : SbUnoMethod* pUnoMethod = PTR_CAST(SbUnoMethod,p);
388 0 : SbUnoProperty* pUnoProperty = PTR_CAST(SbUnoProperty,p);
389 0 : if( pUnoMethod || pUnoProperty )
390 : {
391 0 : SbUnoObject* pParentUnoObj = PTR_CAST( SbUnoObject,p->GetParent() );
392 0 : if( pParentUnoObj )
393 : {
394 0 : Any aUnoAny = pParentUnoObj->getUnoAny();
395 0 : Reference< XInvocation > xInvocation;
396 0 : aUnoAny >>= xInvocation;
397 0 : if( xInvocation.is() ) // TODO: if( xOLEAutomation.is() )
398 : {
399 0 : bError_ = false;
400 :
401 0 : sal_uInt16 nCurPar = 1;
402 : AutomationNamedArgsSbxArray* pArg =
403 0 : new AutomationNamedArgsSbxArray( nArgCount );
404 0 : OUString* pNames = pArg->getNames().getArray();
405 0 : for( i = 1 ; i < nArgCount ; i++ )
406 : {
407 0 : SbxVariable* pVar = refArgv->Get( i );
408 0 : const OUString& rName = refArgv->GetAlias( i );
409 0 : if( rName.getLength() )
410 : {
411 0 : pNames[i] = rName;
412 : }
413 0 : pArg->Put( pVar, nCurPar++ );
414 : }
415 0 : refArgv = pArg;
416 0 : }
417 0 : }
418 : }
419 0 : else if( bVBAEnabled && p->GetType() == SbxOBJECT && (!p->ISA(SbxMethod) || !p->IsBroadcaster()) )
420 : {
421 : // Check for default method with named parameters
422 0 : SbxBaseRef pObj = (SbxBase*)p->GetObject();
423 0 : if( pObj && pObj->ISA(SbUnoObject) )
424 : {
425 0 : SbUnoObject* pUnoObj = (SbUnoObject*)(SbxBase*)pObj;
426 0 : Any aAny = pUnoObj->getUnoAny();
427 :
428 0 : if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
429 : {
430 0 : Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue();
431 0 : Reference< XDefaultMethod > xDfltMethod( x, UNO_QUERY );
432 :
433 0 : OUString sDefaultMethod;
434 0 : if ( xDfltMethod.is() )
435 : {
436 0 : sDefaultMethod = xDfltMethod->getDefaultMethodName();
437 : }
438 0 : if ( !sDefaultMethod.isEmpty() )
439 : {
440 0 : SbxVariable* meth = pUnoObj->Find( sDefaultMethod, SbxCLASS_METHOD );
441 0 : if( meth != NULL )
442 : {
443 0 : pInfo = meth->GetInfo();
444 : }
445 0 : if( pInfo )
446 : {
447 0 : bError_ = false;
448 : }
449 0 : }
450 0 : }
451 0 : }
452 : }
453 0 : if( bError_ )
454 : {
455 0 : Error( SbERR_NO_NAMED_ARGS );
456 : }
457 : }
458 : else
459 : {
460 0 : sal_uInt16 nCurPar = 1;
461 0 : SbxArray* pArg = new SbxArray;
462 0 : for( i = 1 ; i < nArgCount ; i++ )
463 : {
464 0 : SbxVariable* pVar = refArgv->Get( i );
465 0 : const OUString& rName = refArgv->GetAlias( i );
466 0 : if( rName.getLength() )
467 : {
468 : // nCurPar is set to the found parameter
469 0 : sal_uInt16 j = 1;
470 0 : const SbxParamInfo* pParam = pInfo->GetParam( j );
471 0 : while( pParam )
472 : {
473 0 : if( pParam->aName.equalsIgnoreAsciiCase( rName ) )
474 : {
475 0 : nCurPar = j;
476 0 : break;
477 : }
478 0 : pParam = pInfo->GetParam( ++j );
479 : }
480 0 : if( !pParam )
481 : {
482 0 : Error( SbERR_NAMED_NOT_FOUND ); break;
483 : }
484 : }
485 0 : pArg->Put( pVar, nCurPar++ );
486 : }
487 0 : refArgv = pArg;
488 : }
489 : }
490 : // own var as parameter 0
491 2 : refArgv->Put( p, 0 );
492 2 : p->SetParameters( refArgv );
493 2 : PopArgv();
494 : }
495 : else
496 : {
497 72 : p->SetParameters( NULL );
498 : }
499 74 : }
500 :
501 : // getting an array element
502 :
503 74 : SbxVariable* SbiRuntime::CheckArray( SbxVariable* pElem )
504 : {
505 : SbxArray* pPar;
506 74 : if( ( pElem->GetType() & SbxARRAY ) && (SbxVariable*)refRedim != pElem )
507 : {
508 0 : SbxBase* pElemObj = pElem->GetObject();
509 0 : SbxDimArray* pDimArray = PTR_CAST(SbxDimArray,pElemObj);
510 0 : pPar = pElem->GetParameters();
511 0 : if( pDimArray )
512 : {
513 : // parameters may be missing, if an array is
514 : // passed as an argument
515 0 : if( pPar )
516 0 : pElem = pDimArray->Get( pPar );
517 : }
518 : else
519 : {
520 0 : SbxArray* pArray = PTR_CAST(SbxArray,pElemObj);
521 0 : if( pArray )
522 : {
523 0 : if( !pPar )
524 : {
525 0 : Error( SbERR_OUT_OF_RANGE );
526 0 : pElem = new SbxVariable;
527 : }
528 : else
529 : {
530 0 : pElem = pArray->Get( pPar->Get( 1 )->GetInteger() );
531 : }
532 : }
533 : }
534 :
535 : // #42940, set parameter 0 to NULL so that var doesn't contain itself
536 0 : if( pPar )
537 : {
538 0 : pPar->Put( NULL, 0 );
539 : }
540 : }
541 : // consider index-access for UnoObjects
542 74 : else if( pElem->GetType() == SbxOBJECT && !pElem->ISA(SbxMethod) && ( !bVBAEnabled || ( bVBAEnabled && !pElem->ISA(SbxProperty) ) ) )
543 : {
544 40 : pPar = pElem->GetParameters();
545 40 : if ( pPar )
546 : {
547 : // is it an uno-object?
548 0 : SbxBaseRef pObj = (SbxBase*)pElem->GetObject();
549 0 : if( pObj )
550 : {
551 0 : if( pObj->ISA(SbUnoObject) )
552 : {
553 0 : SbUnoObject* pUnoObj = (SbUnoObject*)(SbxBase*)pObj;
554 0 : Any aAny = pUnoObj->getUnoAny();
555 :
556 0 : if( aAny.getValueType().getTypeClass() == TypeClass_INTERFACE )
557 : {
558 0 : Reference< XInterface > x = *(Reference< XInterface >*)aAny.getValue();
559 0 : Reference< XIndexAccess > xIndexAccess( x, UNO_QUERY );
560 0 : if ( !bVBAEnabled )
561 : {
562 0 : if( xIndexAccess.is() )
563 : {
564 0 : sal_uInt32 nParamCount = (sal_uInt32)pPar->Count() - 1;
565 0 : if( nParamCount != 1 )
566 : {
567 0 : StarBASIC::Error( SbERR_BAD_ARGUMENT );
568 0 : return pElem;
569 : }
570 :
571 : // get index
572 0 : sal_Int32 nIndex = pPar->Get( 1 )->GetLong();
573 0 : Reference< XInterface > xRet;
574 : try
575 : {
576 0 : Any aAny2 = xIndexAccess->getByIndex( nIndex );
577 0 : TypeClass eType = aAny2.getValueType().getTypeClass();
578 0 : if( eType == TypeClass_INTERFACE )
579 : {
580 0 : xRet = *(Reference< XInterface >*)aAny2.getValue();
581 0 : }
582 : }
583 0 : catch (const IndexOutOfBoundsException&)
584 : {
585 : // usually expect converting problem
586 0 : StarBASIC::Error( SbERR_OUT_OF_RANGE );
587 : }
588 :
589 : // #57847 always create a new variable, else error
590 : // due to PutObject(NULL) at ReadOnly-properties
591 0 : pElem = new SbxVariable( SbxVARIANT );
592 0 : if( xRet.is() )
593 : {
594 0 : aAny <<= xRet;
595 :
596 : // #67173 don't specify a name so that the real class name is entered
597 0 : OUString aName;
598 0 : SbxObjectRef xWrapper = (SbxObject*)new SbUnoObject( aName, aAny );
599 0 : pElem->PutObject( xWrapper );
600 : }
601 : else
602 : {
603 0 : pElem->PutObject( NULL );
604 0 : }
605 : }
606 : }
607 : else
608 : {
609 0 : OUString sDefaultMethod;
610 :
611 0 : Reference< XDefaultMethod > xDfltMethod( x, UNO_QUERY );
612 :
613 0 : if ( xDfltMethod.is() )
614 : {
615 0 : sDefaultMethod = xDfltMethod->getDefaultMethodName();
616 : }
617 0 : else if( xIndexAccess.is() )
618 : {
619 0 : sDefaultMethod = OUString( RTL_CONSTASCII_USTRINGPARAM( "getByIndex" ) );
620 : }
621 0 : if ( !sDefaultMethod.isEmpty() )
622 : {
623 0 : SbxVariable* meth = pUnoObj->Find( sDefaultMethod, SbxCLASS_METHOD );
624 0 : SbxVariableRef refTemp = meth;
625 0 : if ( refTemp )
626 : {
627 0 : meth->SetParameters( pPar );
628 0 : SbxVariable* pNew = new SbxMethod( *(SbxMethod*)meth );
629 0 : pElem = pNew;
630 0 : }
631 0 : }
632 0 : }
633 : }
634 :
635 : // #42940, set parameter 0 to NULL so that var doesn't contain itself
636 0 : pPar->Put( NULL, 0 );
637 : }
638 0 : else if( pObj->ISA(BasicCollection) )
639 : {
640 0 : BasicCollection* pCol = (BasicCollection*)(SbxBase*)pObj;
641 0 : pElem = new SbxVariable( SbxVARIANT );
642 0 : pPar->Put( pElem, 0 );
643 0 : pCol->CollItem( pPar );
644 : }
645 : }
646 0 : else if( bVBAEnabled ) // !pObj
647 : {
648 0 : SbxArray* pParam = pElem->GetParameters();
649 0 : if( pParam != NULL && !pElem->IsSet( SBX_VAR_TO_DIM ) )
650 : {
651 0 : Error( SbERR_NO_OBJECT );
652 : }
653 0 : }
654 : }
655 : }
656 :
657 74 : return pElem;
658 : }
659 :
660 : // loading an element from the runtime-library (+StringID+type)
661 :
662 2 : void SbiRuntime::StepRTL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
663 : {
664 2 : PushVar( FindElement( rBasic.pRtl, nOp1, nOp2, SbERR_PROC_UNDEFINED, false ) );
665 2 : }
666 :
667 42 : void SbiRuntime::StepFIND_Impl( SbxObject* pObj, sal_uInt32 nOp1, sal_uInt32 nOp2,
668 : SbError nNotFound, bool bLocal, bool bStatic )
669 : {
670 42 : if( !refLocals )
671 : {
672 0 : refLocals = new SbxArray;
673 : }
674 42 : PushVar( FindElement( pObj, nOp1, nOp2, nNotFound, bLocal, bStatic ) );
675 42 : }
676 : // loading a local/global variable (+StringID+type)
677 :
678 42 : void SbiRuntime::StepFIND( sal_uInt32 nOp1, sal_uInt32 nOp2 )
679 : {
680 42 : StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, true );
681 42 : }
682 :
683 : // Search inside a class module (CM) to enable global search in time
684 0 : void SbiRuntime::StepFIND_CM( sal_uInt32 nOp1, sal_uInt32 nOp2 )
685 : {
686 :
687 0 : SbClassModuleObject* pClassModuleObject = PTR_CAST(SbClassModuleObject,pMod);
688 0 : if( pClassModuleObject )
689 : {
690 0 : pMod->SetFlag( SBX_GBLSEARCH );
691 : }
692 0 : StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, true );
693 :
694 0 : if( pClassModuleObject )
695 : {
696 0 : pMod->ResetFlag( SBX_GBLSEARCH );
697 : }
698 0 : }
699 :
700 0 : void SbiRuntime::StepFIND_STATIC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
701 : {
702 0 : StepFIND_Impl( pMod, nOp1, nOp2, SbERR_PROC_UNDEFINED, true, true );
703 0 : }
704 :
705 : // loading an object-element (+StringID+type)
706 : // the object lies on TOS
707 :
708 23 : void SbiRuntime::StepELEM( sal_uInt32 nOp1, sal_uInt32 nOp2 )
709 : {
710 23 : SbxVariableRef pObjVar = PopVar();
711 :
712 23 : SbxObject* pObj = PTR_CAST(SbxObject,(SbxVariable*) pObjVar);
713 23 : if( !pObj )
714 : {
715 23 : SbxBase* pObjVarObj = pObjVar->GetObject();
716 23 : pObj = PTR_CAST(SbxObject,pObjVarObj);
717 : }
718 :
719 : // #56368 save reference at StepElem, otherwise objects could
720 : // lose their reference too early in qualification chains like
721 : // ActiveComponent.Selection(0).Text
722 : // #74254 now per list
723 23 : if( pObj )
724 : {
725 23 : SaveRef( (SbxVariable*)pObj );
726 : }
727 23 : PushVar( FindElement( pObj, nOp1, nOp2, SbERR_NO_METHOD, false ) );
728 23 : }
729 :
730 : // loading a parameter (+offset+type)
731 : // If the data type is wrong, create a copy.
732 : // The data type SbxEMPTY shows that no parameters are given.
733 : // Get( 0 ) may be EMPTY
734 :
735 7 : void SbiRuntime::StepPARAM( sal_uInt32 nOp1, sal_uInt32 nOp2 )
736 : {
737 7 : sal_uInt16 i = static_cast<sal_uInt16>( nOp1 & 0x7FFF );
738 7 : SbxDataType t = (SbxDataType) nOp2;
739 : SbxVariable* p;
740 :
741 : // #57915 solve missing in a cleaner way
742 7 : sal_uInt16 nParamCount = refParams->Count();
743 7 : if( i >= nParamCount )
744 : {
745 0 : sal_Int16 iLoop = i;
746 0 : while( iLoop >= nParamCount )
747 : {
748 0 : p = new SbxVariable();
749 :
750 0 : if( SbiRuntime::isVBAEnabled() &&
751 : (t == SbxOBJECT || t == SbxSTRING) )
752 : {
753 0 : if( t == SbxOBJECT )
754 : {
755 0 : p->PutObject( NULL );
756 : }
757 : else
758 : {
759 0 : p->PutString( OUString() );
760 : }
761 : }
762 : else
763 : {
764 0 : p->PutErr( 448 ); // like in VB: Error-Code 448 (SbERR_NAMED_NOT_FOUND)
765 : }
766 0 : refParams->Put( p, iLoop );
767 0 : iLoop--;
768 : }
769 : }
770 7 : p = refParams->Get( i );
771 :
772 7 : if( p->GetType() == SbxERROR && ( i ) )
773 : {
774 : // if there's a parameter missing, it can be OPTIONAL
775 0 : bool bOpt = false;
776 0 : if( pMeth )
777 : {
778 0 : SbxInfo* pInfo = pMeth->GetInfo();
779 0 : if ( pInfo )
780 : {
781 0 : const SbxParamInfo* pParam = pInfo->GetParam( i );
782 0 : if( pParam && ( (pParam->nFlags & SBX_OPTIONAL) != 0 ) )
783 : {
784 : // Default value?
785 0 : sal_uInt16 nDefaultId = (sal_uInt16)(pParam->nUserData & 0x0ffff);
786 0 : if( nDefaultId > 0 )
787 : {
788 0 : OUString aDefaultStr = pImg->GetString( nDefaultId );
789 0 : p = new SbxVariable();
790 0 : p->PutString( aDefaultStr );
791 0 : refParams->Put( p, i );
792 : }
793 0 : bOpt = true;
794 : }
795 : }
796 : }
797 0 : if( !bOpt )
798 : {
799 0 : Error( SbERR_NOT_OPTIONAL );
800 : }
801 : }
802 7 : else if( t != SbxVARIANT && (SbxDataType)(p->GetType() & 0x0FFF ) != t )
803 : {
804 0 : SbxVariable* q = new SbxVariable( t );
805 0 : SaveRef( q );
806 0 : *q = *p;
807 0 : p = q;
808 0 : if ( i )
809 : {
810 0 : refParams->Put( p, i );
811 : }
812 : }
813 7 : SetupArgs( p, nOp1 );
814 7 : PushVar( CheckArray( p ) );
815 7 : }
816 :
817 : // Case-Test (+True-Target+Test-Opcode)
818 :
819 0 : void SbiRuntime::StepCASEIS( sal_uInt32 nOp1, sal_uInt32 nOp2 )
820 : {
821 0 : if( !refCaseStk || !refCaseStk->Count() )
822 : {
823 0 : StarBASIC::FatalError( SbERR_INTERNAL_ERROR );
824 : }
825 : else
826 : {
827 0 : SbxVariableRef xComp = PopVar();
828 0 : SbxVariableRef xCase = refCaseStk->Get( refCaseStk->Count() - 1 );
829 0 : if( xCase->Compare( (SbxOperator) nOp2, *xComp ) )
830 : {
831 0 : StepJUMP( nOp1 );
832 0 : }
833 : }
834 0 : }
835 :
836 : // call of a DLL-procedure (+StringID+type)
837 : // the StringID's MSB shows that Argv is occupied
838 :
839 0 : void SbiRuntime::StepCALL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
840 : {
841 0 : OUString aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) );
842 0 : SbxArray* pArgs = NULL;
843 0 : if( nOp1 & 0x8000 )
844 : {
845 0 : pArgs = refArgv;
846 : }
847 0 : DllCall( aName, aLibName, pArgs, (SbxDataType) nOp2, false );
848 0 : aLibName = OUString();
849 0 : if( nOp1 & 0x8000 )
850 : {
851 0 : PopArgv();
852 0 : }
853 0 : }
854 :
855 : // call of a DLL-procedure after CDecl (+StringID+type)
856 :
857 0 : void SbiRuntime::StepCALLC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
858 : {
859 0 : OUString aName = pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) );
860 0 : SbxArray* pArgs = NULL;
861 0 : if( nOp1 & 0x8000 )
862 : {
863 0 : pArgs = refArgv;
864 : }
865 0 : DllCall( aName, aLibName, pArgs, (SbxDataType) nOp2, true );
866 0 : aLibName = OUString();
867 0 : if( nOp1 & 0x8000 )
868 : {
869 0 : PopArgv();
870 0 : }
871 0 : }
872 :
873 :
874 : // beginning of a statement (+Line+Col)
875 :
876 50 : void SbiRuntime::StepSTMNT( sal_uInt32 nOp1, sal_uInt32 nOp2 )
877 : {
878 : // If the Expr-Stack at the beginning of a statement constains a variable,
879 : // some fool has called X as a function, although it's a variable!
880 50 : bool bFatalExpr = false;
881 50 : OUString sUnknownMethodName;
882 50 : if( nExprLvl > 1 )
883 : {
884 0 : bFatalExpr = true;
885 : }
886 50 : else if( nExprLvl )
887 : {
888 0 : SbxVariable* p = refExprStk->Get( 0 );
889 0 : if( p->GetRefCount() > 1 &&
890 0 : refLocals.Is() && refLocals->Find( p->GetName(), p->GetClass() ) )
891 : {
892 0 : sUnknownMethodName = p->GetName();
893 0 : bFatalExpr = true;
894 : }
895 : }
896 :
897 50 : ClearExprStack();
898 :
899 50 : ClearRefs();
900 :
901 : // We have to cancel hard here because line and column
902 : // would be wrong later otherwise!
903 50 : if( bFatalExpr)
904 : {
905 0 : StarBASIC::FatalError( SbERR_NO_METHOD, sUnknownMethodName );
906 50 : return;
907 : }
908 50 : pStmnt = pCode - 9;
909 50 : sal_uInt16 nOld = nLine;
910 50 : nLine = static_cast<short>( nOp1 );
911 :
912 : // #29955 & 0xFF, to filter out for-loop-level
913 50 : nCol1 = static_cast<short>( nOp2 & 0xFF );
914 :
915 : // find the next STMNT-command to set the final column
916 : // of this statement
917 :
918 50 : nCol2 = 0xffff;
919 : sal_uInt16 n1, n2;
920 50 : const sal_uInt8* p = pMod->FindNextStmnt( pCode, n1, n2 );
921 50 : if( p )
922 : {
923 43 : if( n1 == nOp1 )
924 : {
925 : // #29955 & 0xFF, to filter out for-loop-level
926 0 : nCol2 = (n2 & 0xFF) - 1;
927 : }
928 : }
929 :
930 : // #29955 correct for-loop-level, #67452 NOT in the error-handler
931 50 : if( !bInError )
932 : {
933 : // (there's a difference here in case of a jump out of a loop)
934 50 : sal_uInt16 nExspectedForLevel = static_cast<sal_uInt16>( nOp2 / 0x100 );
935 50 : if( pGosubStk )
936 : {
937 0 : nExspectedForLevel = nExspectedForLevel + pGosubStk->nStartForLvl;
938 : }
939 :
940 : // if the actual for-level is too small it'd jump out
941 : // of a loop -> corrected
942 100 : while( nForLvl > nExspectedForLevel )
943 : {
944 0 : PopFor();
945 : }
946 : }
947 :
948 : // 16.10.96: #31460 new concept for StepInto/Over/Out
949 : // see explanation at _ImplGetBreakCallLevel
950 50 : if( pInst->nCallLvl <= pInst->nBreakCallLvl )
951 : {
952 0 : StarBASIC* pStepBasic = GetCurrentBasic( &rBasic );
953 0 : sal_uInt16 nNewFlags = pStepBasic->StepPoint( nLine, nCol1, nCol2 );
954 :
955 0 : pInst->CalcBreakCallLevel( nNewFlags );
956 : }
957 :
958 : // break points only at STMNT-commands in a new line!
959 50 : else if( ( nOp1 != nOld )
960 : && ( nFlags & SbDEBUG_BREAK )
961 0 : && pMod->IsBP( static_cast<sal_uInt16>( nOp1 ) ) )
962 : {
963 0 : StarBASIC* pBreakBasic = GetCurrentBasic( &rBasic );
964 0 : sal_uInt16 nNewFlags = pBreakBasic->BreakPoint( nLine, nCol1, nCol2 );
965 :
966 0 : pInst->CalcBreakCallLevel( nNewFlags );
967 50 : }
968 : }
969 :
970 : // (+SvStreamFlags+Flags)
971 : // Stack: block length
972 : // channel number
973 : // file name
974 :
975 0 : void SbiRuntime::StepOPEN( sal_uInt32 nOp1, sal_uInt32 nOp2 )
976 : {
977 0 : SbxVariableRef pName = PopVar();
978 0 : SbxVariableRef pChan = PopVar();
979 0 : SbxVariableRef pLen = PopVar();
980 0 : short nBlkLen = pLen->GetInteger();
981 0 : short nChan = pChan->GetInteger();
982 0 : OString aName(rtl::OUStringToOString(pName->GetOUString(), osl_getThreadTextEncoding()));
983 : pIosys->Open( nChan, aName, static_cast<short>( nOp1 ),
984 0 : static_cast<short>( nOp2 ), nBlkLen );
985 0 : Error( pIosys->GetError() );
986 0 : }
987 :
988 : // create object (+StringID+StringID)
989 :
990 6 : void SbiRuntime::StepCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 )
991 : {
992 6 : OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) );
993 6 : SbxObject *pObj = SbxBase::CreateObject( aClass );
994 6 : if( !pObj )
995 : {
996 0 : Error( SbERR_INVALID_OBJECT );
997 : }
998 : else
999 : {
1000 6 : OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
1001 6 : pObj->SetName( aName );
1002 : // the object must be able to call the BASIC
1003 6 : pObj->SetParent( &rBasic );
1004 6 : SbxVariable* pNew = new SbxVariable;
1005 6 : pNew->PutObject( pObj );
1006 6 : PushVar( pNew );
1007 6 : }
1008 6 : }
1009 :
1010 0 : void SbiRuntime::StepDCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 )
1011 : {
1012 0 : StepDCREATE_IMPL( nOp1, nOp2 );
1013 0 : }
1014 :
1015 0 : void SbiRuntime::StepDCREATE_REDIMP( sal_uInt32 nOp1, sal_uInt32 nOp2 )
1016 : {
1017 0 : StepDCREATE_IMPL( nOp1, nOp2 );
1018 0 : }
1019 :
1020 :
1021 : // Helper function for StepDCREATE_IMPL / bRedimp = true
1022 0 : void implCopyDimArray_DCREATE( SbxDimArray* pNewArray, SbxDimArray* pOldArray, short nMaxDimIndex,
1023 : short nActualDim, sal_Int32* pActualIndices, sal_Int32* pLowerBounds, sal_Int32* pUpperBounds )
1024 : {
1025 0 : sal_Int32& ri = pActualIndices[nActualDim];
1026 0 : for( ri = pLowerBounds[nActualDim] ; ri <= pUpperBounds[nActualDim] ; ri++ )
1027 : {
1028 0 : if( nActualDim < nMaxDimIndex )
1029 : {
1030 : implCopyDimArray_DCREATE( pNewArray, pOldArray, nMaxDimIndex, nActualDim + 1,
1031 0 : pActualIndices, pLowerBounds, pUpperBounds );
1032 : }
1033 : else
1034 : {
1035 0 : SbxVariable* pSource = pOldArray->Get32( pActualIndices );
1036 0 : pNewArray->Put32( pSource, pActualIndices );
1037 : }
1038 : }
1039 0 : }
1040 :
1041 : // #56204 create object array (+StringID+StringID), DCREATE == Dim-Create
1042 0 : void SbiRuntime::StepDCREATE_IMPL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
1043 : {
1044 0 : SbxVariableRef refVar = PopVar();
1045 :
1046 0 : DimImpl( refVar );
1047 :
1048 : // fill the array with instances of the requested class
1049 0 : SbxBaseRef xObj = (SbxBase*)refVar->GetObject();
1050 0 : if( !xObj )
1051 : {
1052 0 : StarBASIC::Error( SbERR_INVALID_OBJECT );
1053 0 : return;
1054 : }
1055 :
1056 0 : SbxDimArray* pArray = 0;
1057 0 : if( xObj->ISA(SbxDimArray) )
1058 : {
1059 0 : SbxBase* pObj = (SbxBase*)xObj;
1060 0 : pArray = (SbxDimArray*)pObj;
1061 :
1062 0 : short nDims = pArray->GetDims();
1063 0 : sal_Int32 nTotalSize = 0;
1064 :
1065 : // must be a one-dimensional array
1066 : sal_Int32 nLower, nUpper, nSize;
1067 : sal_Int32 i;
1068 0 : for( i = 0 ; i < nDims ; i++ )
1069 : {
1070 0 : pArray->GetDim32( i+1, nLower, nUpper );
1071 0 : nSize = nUpper - nLower + 1;
1072 0 : if( i == 0 )
1073 : {
1074 0 : nTotalSize = nSize;
1075 : }
1076 : else
1077 : {
1078 0 : nTotalSize *= nSize;
1079 : }
1080 : }
1081 :
1082 : // create objects and insert them into the array
1083 0 : OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) );
1084 0 : for( i = 0 ; i < nTotalSize ; i++ )
1085 : {
1086 0 : SbxObject *pClassObj = SbxBase::CreateObject( aClass );
1087 0 : if( !pClassObj )
1088 : {
1089 0 : Error( SbERR_INVALID_OBJECT );
1090 0 : break;
1091 : }
1092 : else
1093 : {
1094 0 : OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
1095 0 : pClassObj->SetName( aName );
1096 : // the object must be able to call the basic
1097 0 : pClassObj->SetParent( &rBasic );
1098 0 : pArray->SbxArray::Put32( pClassObj, i );
1099 : }
1100 0 : }
1101 : }
1102 :
1103 0 : SbxDimArray* pOldArray = (SbxDimArray*)(SbxArray*)refRedimpArray;
1104 0 : if( pArray && pOldArray )
1105 : {
1106 0 : short nDimsNew = pArray->GetDims();
1107 0 : short nDimsOld = pOldArray->GetDims();
1108 0 : short nDims = nDimsNew;
1109 0 : bool bRangeError = false;
1110 :
1111 : // Store dims to use them for copying later
1112 0 : sal_Int32* pLowerBounds = new sal_Int32[nDims];
1113 0 : sal_Int32* pUpperBounds = new sal_Int32[nDims];
1114 0 : sal_Int32* pActualIndices = new sal_Int32[nDims];
1115 0 : if( nDimsOld != nDimsNew )
1116 : {
1117 0 : bRangeError = true;
1118 : }
1119 : else
1120 : {
1121 : // Compare bounds
1122 0 : for( short i = 1 ; i <= nDims ; i++ )
1123 : {
1124 : sal_Int32 lBoundNew, uBoundNew;
1125 : sal_Int32 lBoundOld, uBoundOld;
1126 0 : pArray->GetDim32( i, lBoundNew, uBoundNew );
1127 0 : pOldArray->GetDim32( i, lBoundOld, uBoundOld );
1128 :
1129 0 : lBoundNew = std::max( lBoundNew, lBoundOld );
1130 0 : uBoundNew = std::min( uBoundNew, uBoundOld );
1131 0 : short j = i - 1;
1132 0 : pActualIndices[j] = pLowerBounds[j] = lBoundNew;
1133 0 : pUpperBounds[j] = uBoundNew;
1134 : }
1135 : }
1136 :
1137 0 : if( bRangeError )
1138 : {
1139 0 : StarBASIC::Error( SbERR_OUT_OF_RANGE );
1140 : }
1141 : else
1142 : {
1143 : // Copy data from old array by going recursively through all dimensions
1144 : // (It would be faster to work on the flat internal data array of an
1145 : // SbyArray but this solution is clearer and easier)
1146 : implCopyDimArray_DCREATE( pArray, pOldArray, nDims - 1,
1147 0 : 0, pActualIndices, pLowerBounds, pUpperBounds );
1148 : }
1149 0 : delete [] pUpperBounds;
1150 0 : delete [] pLowerBounds;
1151 0 : delete [] pActualIndices;
1152 0 : refRedimpArray = NULL;
1153 0 : }
1154 : }
1155 :
1156 : // create object from user-type (+StringID+StringID)
1157 :
1158 : SbxObject* createUserTypeImpl( const OUString& rClassName ); // sb.cxx
1159 :
1160 0 : void SbiRuntime::StepTCREATE( sal_uInt32 nOp1, sal_uInt32 nOp2 )
1161 : {
1162 0 : OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
1163 0 : OUString aClass( pImg->GetString( static_cast<short>( nOp2 ) ) );
1164 :
1165 0 : SbxObject* pCopyObj = createUserTypeImpl( aClass );
1166 0 : if( pCopyObj )
1167 : {
1168 0 : pCopyObj->SetName( aName );
1169 : }
1170 0 : SbxVariable* pNew = new SbxVariable;
1171 0 : pNew->PutObject( pCopyObj );
1172 0 : pNew->SetDeclareClassName( aClass );
1173 0 : PushVar( pNew );
1174 0 : }
1175 :
1176 11 : void SbiRuntime::implHandleSbxFlags( SbxVariable* pVar, SbxDataType t, sal_uInt32 nOp2 )
1177 : {
1178 11 : bool bWithEvents = ((t & 0xff) == SbxOBJECT && (nOp2 & SBX_TYPE_WITH_EVENTS_FLAG) != 0);
1179 11 : if( bWithEvents )
1180 : {
1181 0 : pVar->SetFlag( SBX_WITH_EVENTS );
1182 : }
1183 11 : bool bDimAsNew = ((nOp2 & SBX_TYPE_DIM_AS_NEW_FLAG) != 0);
1184 11 : if( bDimAsNew )
1185 : {
1186 0 : pVar->SetFlag( SBX_DIM_AS_NEW );
1187 : }
1188 11 : bool bFixedString = ((t & 0xff) == SbxSTRING && (nOp2 & SBX_FIXED_LEN_STRING_FLAG) != 0);
1189 11 : if( bFixedString )
1190 : {
1191 0 : sal_uInt16 nCount = static_cast<sal_uInt16>( nOp2 >> 17 ); // len = all bits above 0x10000
1192 0 : OUStringBuffer aBuf;
1193 0 : comphelper::string::padToLength(aBuf, nCount, 0);
1194 0 : pVar->PutString(aBuf.makeStringAndClear());
1195 : }
1196 :
1197 11 : bool bVarToDim = ((nOp2 & SBX_TYPE_VAR_TO_DIM_FLAG) != 0);
1198 11 : if( bVarToDim )
1199 : {
1200 0 : pVar->SetFlag( SBX_VAR_TO_DIM );
1201 : }
1202 11 : }
1203 :
1204 : // establishing a local variable (+StringID+type)
1205 :
1206 11 : void SbiRuntime::StepLOCAL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
1207 : {
1208 11 : if( !refLocals.Is() )
1209 : {
1210 7 : refLocals = new SbxArray;
1211 : }
1212 11 : OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
1213 11 : if( refLocals->Find( aName, SbxCLASS_DONTCARE ) == NULL )
1214 : {
1215 11 : SbxDataType t = (SbxDataType)(nOp2 & 0xffff);
1216 11 : SbxVariable* p = new SbxVariable( t );
1217 11 : p->SetName( aName );
1218 11 : implHandleSbxFlags( p, t, nOp2 );
1219 11 : refLocals->Put( p, refLocals->Count() );
1220 11 : }
1221 11 : }
1222 :
1223 : // establishing a module-global variable (+StringID+type)
1224 :
1225 0 : void SbiRuntime::StepPUBLIC_Impl( sal_uInt32 nOp1, sal_uInt32 nOp2, bool bUsedForClassModule )
1226 : {
1227 0 : OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
1228 0 : SbxDataType t = (SbxDataType)(SbxDataType)(nOp2 & 0xffff);;
1229 0 : sal_Bool bFlag = pMod->IsSet( SBX_NO_MODIFY );
1230 0 : pMod->SetFlag( SBX_NO_MODIFY );
1231 0 : SbxVariableRef p = pMod->Find( aName, SbxCLASS_PROPERTY );
1232 0 : if( p.Is() )
1233 : {
1234 0 : pMod->Remove (p);
1235 : }
1236 0 : SbProperty* pProp = pMod->GetProperty( aName, t );
1237 0 : if( !bUsedForClassModule )
1238 : {
1239 0 : pProp->SetFlag( SBX_PRIVATE );
1240 : }
1241 0 : if( !bFlag )
1242 : {
1243 0 : pMod->ResetFlag( SBX_NO_MODIFY );
1244 : }
1245 0 : if( pProp )
1246 : {
1247 0 : pProp->SetFlag( SBX_DONTSTORE );
1248 : // from 2.7.1996: HACK because of 'reference can't be saved'
1249 0 : pProp->SetFlag( SBX_NO_MODIFY);
1250 :
1251 0 : implHandleSbxFlags( pProp, t, nOp2 );
1252 0 : }
1253 0 : }
1254 :
1255 0 : void SbiRuntime::StepPUBLIC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
1256 : {
1257 0 : StepPUBLIC_Impl( nOp1, nOp2, false );
1258 0 : }
1259 :
1260 0 : void SbiRuntime::StepPUBLIC_P( sal_uInt32 nOp1, sal_uInt32 nOp2 )
1261 : {
1262 : // Creates module variable that isn't reinitialised when
1263 : // between invocations ( for VBASupport & document basic only )
1264 0 : if( pMod->pImage->bFirstInit )
1265 : {
1266 0 : bool bUsedForClassModule = pImg->GetFlag( SBIMG_CLASSMODULE );
1267 0 : StepPUBLIC_Impl( nOp1, nOp2, bUsedForClassModule );
1268 : }
1269 0 : }
1270 :
1271 : // establishing a global variable (+StringID+type)
1272 :
1273 0 : void SbiRuntime::StepGLOBAL( sal_uInt32 nOp1, sal_uInt32 nOp2 )
1274 : {
1275 0 : if( pImg->GetFlag( SBIMG_CLASSMODULE ) )
1276 : {
1277 0 : StepPUBLIC_Impl( nOp1, nOp2, true );
1278 : }
1279 0 : OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
1280 0 : SbxDataType t = (SbxDataType)(nOp2 & 0xffff);
1281 :
1282 : // Store module scope variables at module scope
1283 : // in non vba mode these are stored at the library level :/
1284 : // not sure if this really should not be enabled for ALL basic
1285 0 : SbxObject* pStorage = &rBasic;
1286 0 : if ( SbiRuntime::isVBAEnabled() )
1287 : {
1288 0 : pStorage = pMod;
1289 0 : pMod->AddVarName( aName );
1290 : }
1291 :
1292 0 : sal_Bool bFlag = pStorage->IsSet( SBX_NO_MODIFY );
1293 0 : rBasic.SetFlag( SBX_NO_MODIFY );
1294 0 : SbxVariableRef p = pStorage->Find( aName, SbxCLASS_PROPERTY );
1295 0 : if( p.Is() )
1296 : {
1297 0 : pStorage->Remove (p);
1298 : }
1299 0 : p = pStorage->Make( aName, SbxCLASS_PROPERTY, t );
1300 0 : if( !bFlag )
1301 : {
1302 0 : pStorage->ResetFlag( SBX_NO_MODIFY );
1303 : }
1304 0 : if( p )
1305 : {
1306 0 : p->SetFlag( SBX_DONTSTORE );
1307 : // from 2.7.1996: HACK because of 'reference can't be saved'
1308 0 : p->SetFlag( SBX_NO_MODIFY);
1309 0 : }
1310 0 : }
1311 :
1312 :
1313 : // Creates global variable that isn't reinitialised when
1314 : // basic is restarted, P=PERSIST (+StringID+Typ)
1315 :
1316 0 : void SbiRuntime::StepGLOBAL_P( sal_uInt32 nOp1, sal_uInt32 nOp2 )
1317 : {
1318 0 : if( pMod->pImage->bFirstInit )
1319 : {
1320 0 : StepGLOBAL( nOp1, nOp2 );
1321 : }
1322 0 : }
1323 :
1324 :
1325 : // Searches for global variable, behavior depends on the fact
1326 : // if the variable is initialised for the first time
1327 :
1328 0 : void SbiRuntime::StepFIND_G( sal_uInt32 nOp1, sal_uInt32 nOp2 )
1329 : {
1330 0 : if( pMod->pImage->bFirstInit )
1331 : {
1332 : // Behave like always during first init
1333 0 : StepFIND( nOp1, nOp2 );
1334 : }
1335 : else
1336 : {
1337 : // Return dummy variable
1338 0 : SbxDataType t = (SbxDataType) nOp2;
1339 0 : OUString aName( pImg->GetString( static_cast<short>( nOp1 & 0x7FFF ) ) );
1340 :
1341 0 : SbxVariable* pDummyVar = new SbxVariable( t );
1342 0 : pDummyVar->SetName( aName );
1343 0 : PushVar( pDummyVar );
1344 : }
1345 0 : }
1346 :
1347 :
1348 0 : SbxVariable* SbiRuntime::StepSTATIC_Impl( OUString& aName, SbxDataType& t )
1349 : {
1350 0 : SbxVariable* p = NULL;
1351 0 : if ( pMeth )
1352 : {
1353 0 : SbxArray* pStatics = pMeth->GetStatics();
1354 0 : if( pStatics && ( pStatics->Find( aName, SbxCLASS_DONTCARE ) == NULL ) )
1355 : {
1356 0 : p = new SbxVariable( t );
1357 0 : if( t != SbxVARIANT )
1358 : {
1359 0 : p->SetFlag( SBX_FIXED );
1360 : }
1361 0 : p->SetName( aName );
1362 0 : pStatics->Put( p, pStatics->Count() );
1363 : }
1364 : }
1365 0 : return p;
1366 : }
1367 : // establishing a static variable (+StringID+type)
1368 0 : void SbiRuntime::StepSTATIC( sal_uInt32 nOp1, sal_uInt32 nOp2 )
1369 : {
1370 0 : OUString aName( pImg->GetString( static_cast<short>( nOp1 ) ) );
1371 0 : SbxDataType t = (SbxDataType) nOp2;
1372 0 : StepSTATIC_Impl( aName, t );
1373 0 : }
1374 :
1375 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|