Colibre: Fix wrong color, the ones which doesn not follow Monoline
[LibreOffice.git] / basic / source / sbx / sbxvar.cxx
blob8fb11bf9f2a2d41e2fdb204c6479b2b5aab41a56
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_features.h>
22 #include <tools/stream.hxx>
23 #include <svl/SfxBroadcaster.hxx>
25 #include <basic/sbx.hxx>
26 #include <runtime.hxx>
27 #include "sbxres.hxx"
28 #include "sbxconv.hxx"
29 #include <rtlproto.hxx>
30 #include <sbunoobj.hxx>
31 #include <rtl/ustrbuf.hxx>
32 #include <sal/log.hxx>
34 #include <com/sun/star/uno/XInterface.hpp>
35 using namespace com::sun::star::uno;
37 // SbxVariable
39 SbxVariable::SbxVariable()
43 SbxVariable::SbxVariable( const SbxVariable& r )
44 : SvRefBase( r ),
45 SbxValue( r ),
46 m_aDeclareClassName( r.m_aDeclareClassName ),
47 m_xComListener( r.m_xComListener),
48 mpPar( r.mpPar ),
49 pInfo( r.pInfo )
51 #if HAVE_FEATURE_SCRIPTING
52 if( r.m_xComListener.is() )
54 registerComListenerVariableForBasic( this, r.m_pComListenerParentBasic );
56 #endif
57 if( r.CanRead() )
59 pParent = r.pParent;
60 nUserData = r.nUserData;
61 maName = r.maName;
62 nHash = r.nHash;
66 SbxEnsureParentVariable::SbxEnsureParentVariable(const SbxVariable& r)
67 : SbxVariable(r)
68 , xParent(const_cast<SbxVariable&>(r).GetParent())
70 assert(GetParent() == xParent.get());
73 void SbxEnsureParentVariable::SetParent(SbxObject* p)
75 assert(GetParent() == xParent.get());
76 SbxVariable::SetParent(p);
77 xParent = SbxObjectRef(p);
78 assert(GetParent() == xParent.get());
81 SbxVariable::SbxVariable( SbxDataType t ) : SbxValue( t )
85 SbxVariable::~SbxVariable()
87 #if HAVE_FEATURE_SCRIPTING
88 if( IsSet( SbxFlagBits::DimAsNew ))
90 removeDimAsNewRecoverItem( this );
92 #endif
93 mpBroadcaster.reset();
96 // Broadcasting
98 SfxBroadcaster& SbxVariable::GetBroadcaster()
100 if( !mpBroadcaster )
102 mpBroadcaster.reset( new SfxBroadcaster );
104 return *mpBroadcaster;
107 SbxArray* SbxVariable::GetParameters() const
109 return mpPar.get();
113 // Perhaps some day one could cut the parameter 0.
114 // Then the copying will be dropped...
116 void SbxVariable::Broadcast( SfxHintId nHintId )
118 if( !mpBroadcaster || IsSet( SbxFlagBits::NoBroadcast ) )
119 return;
121 // Because the method could be called from outside, check the
122 // rights here again
123 if( nHintId == SfxHintId::BasicDataWanted )
125 if( !CanRead() )
127 return;
130 if( nHintId == SfxHintId::BasicDataChanged )
132 if( !CanWrite() )
134 return;
138 //fdo#86843 Add a ref during the following block to guard against
139 //getting deleted before completing this method
140 SbxVariableRef aBroadcastGuard(this);
142 // Avoid further broadcasting
143 std::unique_ptr<SfxBroadcaster> pSave = std::move(mpBroadcaster);
144 SbxFlagBits nSaveFlags = GetFlags();
145 SetFlag( SbxFlagBits::ReadWrite );
146 if( mpPar.is() )
148 // Register this as element 0, but don't change over the parent!
149 mpPar->GetRef(0) = this;
151 pSave->Broadcast( SbxHint( nHintId, this ) );
152 mpBroadcaster = std::move(pSave);
153 SetFlags( nSaveFlags );
156 SbxInfo* SbxVariable::GetInfo()
158 if( !pInfo.is() )
160 Broadcast( SfxHintId::BasicInfoWanted );
161 if( pInfo.is() )
163 SetModified( true );
166 return pInfo.get();
169 void SbxVariable::SetInfo( SbxInfo* p )
171 pInfo = p;
174 void SbxVariable::SetParameters( SbxArray* p )
176 mpPar = p;
180 // Name of the variables
182 void SbxVariable::SetName( const OUString& rName )
184 maName = rName;
185 nHash = MakeHashCode( rName );
188 const OUString& SbxVariable::GetName( SbxNameType t ) const
190 static const char cSuffixes[] = " %&!#@ $";
191 if( t == SbxNameType::NONE )
193 return maName;
195 // Request parameter-information (not for objects)
196 const_cast<SbxVariable*>(this)->GetInfo();
197 // Append nothing, if it is a simple property (no empty brackets)
198 if (!pInfo.is() || (pInfo->m_Params.empty() && GetClass() == SbxClassType::Property))
200 return maName;
202 sal_Unicode cType = ' ';
203 OUStringBuffer aTmp( maName );
204 // short type? Then fetch it, possible this is 0.
205 SbxDataType et = GetType();
206 if( t == SbxNameType::ShortTypes )
208 if( et <= SbxSTRING )
210 cType = cSuffixes[ et ];
212 if( cType != ' ' )
214 aTmp.append(cType);
217 aTmp.append("(");
219 for (SbxParams::const_iterator iter = pInfo->m_Params.begin(); iter != pInfo->m_Params.end(); ++iter)
221 auto const& i = *iter;
222 int nt = i->eType & 0x0FFF;
223 if (iter != pInfo->m_Params.begin())
225 aTmp.append(",");
227 if( i->nFlags & SbxFlagBits::Optional )
229 aTmp.append( GetSbxRes( StringId::Optional ) );
231 if( i->eType & SbxBYREF )
233 aTmp.append( GetSbxRes( StringId::ByRef ) );
235 aTmp.append( i->aName );
236 cType = ' ';
237 // short type? Then fetch it, possible this is 0.
238 if( t == SbxNameType::ShortTypes )
240 if( nt <= SbxSTRING )
242 cType = cSuffixes[ nt ];
245 if( cType != ' ' )
247 aTmp.append(cType);
248 if( i->eType & SbxARRAY )
250 aTmp.append("()");
253 else
255 if( i->eType & SbxARRAY )
257 aTmp.append("()");
259 // long type?
260 aTmp.append(GetSbxRes( StringId::As ));
261 if( nt < 32 )
263 aTmp.append(GetSbxRes( static_cast<StringId>( static_cast<int>( StringId::Types ) + nt ) ));
265 else
267 aTmp.append(GetSbxRes( StringId::Any ));
271 aTmp.append(")");
272 const_cast<SbxVariable*>(this)->aToolString = aTmp.makeStringAndClear();
273 return aToolString;
276 // Operators
278 SbxVariable& SbxVariable::operator=( const SbxVariable& r )
280 if (this != &r)
282 SbxValue::operator=( r );
283 // tdf#144353 - copy information about a missing parameter. See SbiRuntime::SetIsMissing.
284 // We cannot unconditionally assign the data about a variable because we would overwrite
285 // the information about parameters (name, type, flags, and ids). For instance, in the case
286 // where a method will be initialized with a literal.
287 if (!pInfo)
288 pInfo = r.pInfo;
289 m_aDeclareClassName = r.m_aDeclareClassName;
290 m_xComListener = r.m_xComListener;
291 m_pComListenerParentBasic = r.m_pComListenerParentBasic;
292 #if HAVE_FEATURE_SCRIPTING
293 if( m_xComListener.is() )
295 registerComListenerVariableForBasic( this, m_pComListenerParentBasic );
297 #endif
299 return *this;
302 // Conversion
304 SbxDataType SbxVariable::GetType() const
306 if( aData.eType == SbxOBJECT )
308 return aData.pObj ? aData.pObj->GetType() : SbxOBJECT;
310 else if( aData.eType == SbxVARIANT )
312 return aData.pObj ? aData.pObj->GetType() : SbxVARIANT;
314 else
316 return aData.eType;
320 SbxClassType SbxVariable::GetClass() const
322 return SbxClassType::Variable;
325 void SbxVariable::SetModified( bool b )
327 if( IsSet( SbxFlagBits::NoModify ) )
329 return;
331 SbxBase::SetModified( b );
332 if( pParent && pParent != this ) //??? HotFix: Recursion out here MM
334 pParent->SetModified( b );
338 void SbxVariable::SetParent( SbxObject* p )
340 #ifdef DBG_UTIL
341 // Will the parent of a SbxObject be set?
342 if (p && dynamic_cast<SbxObject*>(this))
344 // then this had to be a child of the new parent
345 bool bFound = false;
346 SbxArray *pChildren = p->GetObjects();
347 if ( pChildren )
349 for (sal_uInt32 nIdx = 0; !bFound && nIdx < pChildren->Count(); ++nIdx)
351 bFound = (this == pChildren->Get(nIdx));
354 SAL_INFO_IF(
355 !bFound, "basic.sbx",
356 "dangling: [" << GetName() << "].SetParent([" << p->GetName()
357 << "])");
359 #endif
361 pParent = p;
364 const OUString& SbxVariable::GetDeclareClassName() const
366 return m_aDeclareClassName;
369 void SbxVariable::SetDeclareClassName( const OUString& rDeclareClassName )
371 m_aDeclareClassName = rDeclareClassName;
374 void SbxVariable::SetComListener( const css::uno::Reference< css::uno::XInterface >& xComListener,
375 StarBASIC* pParentBasic )
377 m_xComListener = xComListener;
378 m_pComListenerParentBasic = pParentBasic;
379 #if HAVE_FEATURE_SCRIPTING
380 registerComListenerVariableForBasic( this, pParentBasic );
381 #endif
384 void SbxVariable::ClearComListener()
386 m_xComListener.clear();
390 // Loading/Saving
392 bool SbxVariable::LoadData( SvStream& rStrm, sal_uInt16 nVer )
394 sal_uInt8 cMark;
395 rStrm.ReadUChar( cMark );
396 if( cMark == 0xFF )
398 if( !SbxValue::LoadData( rStrm, nVer ) )
400 return false;
402 maName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
403 RTL_TEXTENCODING_ASCII_US);
404 sal_uInt32 nTemp;
405 rStrm.ReadUInt32( nTemp );
406 nUserData = nTemp;
408 else
410 sal_uInt16 nType;
411 rStrm.SeekRel( -1 );
412 rStrm.ReadUInt16( nType );
413 maName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
414 RTL_TEXTENCODING_ASCII_US);
415 sal_uInt32 nTemp;
416 rStrm.ReadUInt32( nTemp );
417 nUserData = nTemp;
418 // correction: old methods have instead of SbxNULL now SbxEMPTY
419 if( nType == SbxNULL && GetClass() == SbxClassType::Method )
421 nType = SbxEMPTY;
423 SbxValues aTmp;
424 OUString aTmpString;
425 OUString aVal;
426 aTmp.eType = aData.eType = static_cast<SbxDataType>(nType);
427 aTmp.pOUString = &aVal;
428 switch( nType )
430 case SbxBOOL:
431 case SbxERROR:
432 case SbxINTEGER:
433 rStrm.ReadInt16( aTmp.nInteger ); break;
434 case SbxLONG:
435 rStrm.ReadInt32( aTmp.nLong ); break;
436 case SbxSINGLE:
438 // Floats as ASCII
439 aTmpString = read_uInt16_lenPrefixed_uInt8s_ToOUString(
440 rStrm, RTL_TEXTENCODING_ASCII_US);
441 double d;
442 SbxDataType t;
443 if( ImpScan( aTmpString, d, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE || t == SbxDOUBLE )
445 aTmp.nSingle = 0;
446 return false;
448 aTmp.nSingle = static_cast<float>(d);
449 break;
451 case SbxDATE:
452 case SbxDOUBLE:
454 // Floats as ASCII
455 aTmpString = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
456 RTL_TEXTENCODING_ASCII_US);
457 SbxDataType t;
458 if( ImpScan( aTmpString, aTmp.nDouble, t, nullptr, !LibreOffice6FloatingPointMode() ) != ERRCODE_NONE )
460 aTmp.nDouble = 0;
461 return false;
463 break;
465 case SbxSTRING:
466 aVal = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm,
467 RTL_TEXTENCODING_ASCII_US);
468 break;
469 case SbxEMPTY:
470 case SbxNULL:
471 break;
472 default:
473 aData.eType = SbxNULL;
474 SAL_WARN( "basic.sbx", "Loaded a non-supported data type" );
475 return false;
477 // putt value
478 if( nType != SbxNULL && nType != SbxEMPTY && !Put( aTmp ) )
480 return false;
483 rStrm.ReadUChar( cMark );
484 // cMark is also a version number!
485 // 1: initial version
486 // 2: with nUserData
487 if( cMark )
489 if( cMark > 2 )
491 return false;
493 pInfo = new SbxInfo;
494 pInfo->LoadData( rStrm, static_cast<sal_uInt16>(cMark) );
496 Broadcast( SfxHintId::BasicDataChanged );
497 nHash = MakeHashCode( maName );
498 SetModified( true );
499 return true;
502 bool SbxVariable::StoreData( SvStream& rStrm ) const
504 rStrm.WriteUChar( 0xFF ); // Marker
505 bool bValStore;
506 if( dynamic_cast<const SbxMethod *>(this) != nullptr )
508 // #50200 Avoid that objects , which during the runtime
509 // as return-value are saved in the method as a value were saved
510 SbxVariable* pThis = const_cast<SbxVariable*>(this);
511 SbxFlagBits nSaveFlags = GetFlags();
512 pThis->SetFlag( SbxFlagBits::Write );
513 pThis->SbxValue::Clear();
514 pThis->SetFlags( nSaveFlags );
516 // So that the method will not be executed in any case!
517 // CAST, to avoid const!
518 pThis->SetFlag( SbxFlagBits::NoBroadcast );
519 bValStore = SbxValue::StoreData( rStrm );
520 pThis->ResetFlag( SbxFlagBits::NoBroadcast );
522 else
524 bValStore = SbxValue::StoreData( rStrm );
526 if( !bValStore )
528 return false;
530 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, maName,
531 RTL_TEXTENCODING_ASCII_US);
532 rStrm.WriteUInt32( nUserData );
533 if( pInfo.is() )
535 rStrm.WriteUChar( 2 ); // Version 2: with UserData!
536 pInfo->StoreData( rStrm );
538 else
540 rStrm.WriteUChar( 0 );
542 return true;
545 // SbxInfo
547 SbxInfo::SbxInfo()
548 : nHelpId(0)
551 SbxInfo::SbxInfo( const OUString& r, sal_uInt32 n )
552 : aHelpFile( r ), nHelpId( n )
555 void SbxVariable::Dump( SvStream& rStrm, bool bFill )
557 OString aBNameStr(OUStringToOString(GetName( SbxNameType::ShortTypes ), RTL_TEXTENCODING_ASCII_US));
558 rStrm.WriteCharPtr( "Variable( " )
559 .WriteOString( OString::number(reinterpret_cast<sal_Int64>(this)) ).WriteCharPtr( "==" )
560 .WriteOString( aBNameStr );
561 OString aBParentNameStr(OUStringToOString(GetParent()->GetName(), RTL_TEXTENCODING_ASCII_US));
562 if ( GetParent() )
564 rStrm.WriteCharPtr( " in parent '" ).WriteOString( aBParentNameStr ).WriteCharPtr( "'" );
566 else
568 rStrm.WriteCharPtr( " no parent" );
570 rStrm.WriteCharPtr( " ) " );
572 // output also the object at object-vars
573 if ( GetValues_Impl().eType == SbxOBJECT &&
574 GetValues_Impl().pObj &&
575 GetValues_Impl().pObj != this &&
576 GetValues_Impl().pObj != GetParent() )
578 rStrm.WriteCharPtr( " contains " );
579 static_cast<SbxObject*>(GetValues_Impl().pObj)->Dump( rStrm, bFill );
581 else
583 rStrm << endl;
587 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */