LibreOffice Module basic (master) 1
sbxobj.cxx
Go to the documentation of this file.
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 <sal/config.h>
21#include <sal/log.hxx>
22
23#include <iomanip>
24
25#include <tools/debug.hxx>
26#include <tools/stream.hxx>
27#include <basic/sbx.hxx>
28#include <basic/sberrors.hxx>
29#include <basic/sbxmeth.hxx>
30#include <sbxprop.hxx>
32#include "sbxdec.hxx"
33#include "sbxres.hxx"
34#include <filefmt.hxx>
35
36
37static OUString pNameProp; // Name-Property
38static OUString pParentProp; // Parent-Property
39
40static sal_uInt16 nNameHash = 0, nParentHash = 0;
41
42
43SbxObject::SbxObject( const OUString& rClass )
44 : SbxVariable( SbxOBJECT ), aClassName( rClass )
45{
46 aData.pObj = this;
47 if( !nNameHash )
48 {
53 }
55 SbxObject::SetName( rClass );
56}
57
59 : SvRefBase( rObj ), SbxVariable( rObj.GetType() ),
60 SfxListener( rObj )
61{
62 *this = rObj;
63}
64
66{
67 if( &r != this )
68 {
71 pMethods = new SbxArray;
72 pProps = new SbxArray;
73 pObjs = new SbxArray( SbxOBJECT );
74 // The arrays were copied, the content taken over
76 *pProps = *r.pProps;
77 *pObjs = *r.pObjs;
78 // Because the variables were taken over, this is OK
80 SetName( r.GetName() );
81 SetFlags( r.GetFlags() );
82 SetModified( true );
83 }
84 return *this;
85}
86
87static void CheckParentsOnDelete( SbxObject* pObj, SbxArray* p )
88{
89 for (sal_uInt32 i = 0; i < p->Count(); i++)
90 {
91 SbxVariableRef& rRef = p->GetRef(i);
92 if( rRef->IsBroadcaster() )
93 {
94 pObj->EndListening( rRef->GetBroadcaster(), true );
95 }
96 // does the element have more than one reference and still a Listener?
97 if( rRef->GetRefCount() > 1 )
98 {
99 rRef->SetParent( nullptr );
100 SAL_INFO_IF(rRef->IsBroadcaster() && rRef->GetBroadcaster().GetListenerCount(), "basic.sbx", "Object element with dangling parent");
101 }
102 }
103}
104
106{
109 CheckParentsOnDelete( this, pObjs.get() );
110
111 // avoid handling in ~SbxVariable as SbxFlagBits::DimAsNew == SbxFlagBits::GlobalSearch
113}
114
116{
117 return SbxOBJECT;
118}
119
121{
123}
124
126{
127 pMethods = new SbxArray;
128 pProps = new SbxArray;
129 pObjs = new SbxArray( SbxOBJECT );
130 SbxVariable* p;
132 p->SetFlag( SbxFlagBits::DontStore );
134 p->ResetFlag( SbxFlagBits::Write );
135 p->SetFlag( SbxFlagBits::DontStore );
136 pDfltProp = nullptr;
137 SetModified( false );
138}
139
141{
142 const SbxHint* p = dynamic_cast<const SbxHint*>(&rHint);
143 if( !p )
144 return;
145
146 const SfxHintId nId = p->GetId();
147 bool bRead = ( nId == SfxHintId::BasicDataWanted );
148 bool bWrite = ( nId == SfxHintId::BasicDataChanged );
149 SbxVariable* pVar = p->GetVar();
150 if( !(bRead || bWrite) )
151 return;
152
153 OUString aVarName( pVar->GetName() );
154 sal_uInt16 nHash_ = MakeHashCode( aVarName );
155 if( nHash_ == nNameHash && aVarName.equalsIgnoreAsciiCase( pNameProp ) )
156 {
157 if( bRead )
158 {
159 pVar->PutString( GetName() );
160 }
161 else
162 {
163 SetName( pVar->GetOUString() );
164 }
165 }
166 else if( nHash_ == nParentHash && aVarName.equalsIgnoreAsciiCase( pParentProp ) )
167 {
168 SbxObject* p_ = GetParent();
169 if( !p_ )
170 {
171 p_ = this;
172 }
173 pVar->PutObject( p_ );
174 }
175}
176
177bool SbxObject::IsClass( const OUString& rName ) const
178{
179 return aClassName.equalsIgnoreAsciiCase( rName );
180}
181
182SbxVariable* SbxObject::Find( const OUString& rName, SbxClassType t )
183{
184#ifdef DBG_UTIL
185 static int nLvl = 1;
186 static const char* pCls[] = { "DontCare","Array","Value","Variable","Method","Property","Object" };
187 SAL_INFO(
188 "basic.sbx",
189 "search" << std::setw(nLvl) << " "
191 ? pCls[static_cast<int>(t) - 1] : "Unknown class")
192 << " " << rName << " in " << SbxVariable::GetName());
193 ++nLvl;
194#endif
195
196 SbxVariable* pRes = nullptr;
197 pObjs->SetFlag( SbxFlagBits::ExtSearch );
199 {
200 pRes = pMethods->Find( rName, SbxClassType::Method );
201 if( !pRes )
202 {
203 pRes = pProps->Find( rName, SbxClassType::Property );
204 }
205 if( !pRes )
206 {
207 pRes = pObjs->Find( rName, t );
208 }
209 }
210 else
211 {
212 SbxArray* pArray = nullptr;
213 switch( t )
214 {
216 case SbxClassType::Property: pArray = pProps.get(); break;
217 case SbxClassType::Method: pArray = pMethods.get(); break;
218 case SbxClassType::Object: pArray = pObjs.get(); break;
219 default: SAL_WARN( "basic.sbx", "Invalid SBX-Class" ); break;
220 }
221 if( pArray )
222 {
223 pRes = pArray->Find( rName, t );
224 }
225 }
226 // Extended Search in the Object-Array?
227 // For objects and DontCare the array of objects has already been searched
228 if( !pRes && ( t == SbxClassType::Method || t == SbxClassType::Property ) )
229 pRes = pObjs->Find( rName, t );
230 // Search in the parents?
231 if( !pRes && IsSet( SbxFlagBits::GlobalSearch ) )
232 {
233 SbxObject* pCur = this;
234 while( !pRes && pCur->pParent )
235 {
236 // I myself was already searched!
237 SbxFlagBits nOwn = pCur->GetFlags();
239 // I search already global!
240 SbxFlagBits nPar = pCur->pParent->GetFlags();
242 pRes = pCur->pParent->Find( rName, t );
243 pCur->SetFlags( nOwn );
244 pCur->pParent->SetFlags( nPar );
245 pCur = pCur->pParent;
246 }
247 }
248#ifdef DBG_UTIL
249 --nLvl;
251 pRes, "basic.sbx",
252 "found" << std::setw(nLvl) << " " << rName << " in "
254#endif
255 return pRes;
256}
257
258// Abbreviated version: The parent-string will be searched
259// The whole thing recursive, because Call() might be overridden
260// Qualified names are allowed
261
262bool SbxObject::Call( const OUString& rName, SbxArray* pParam )
263{
265 if( dynamic_cast<const SbxMethod*>( pMeth) )
266 {
267 // tdf#149622 - clear return value of the method before calling it
268 pMeth->Clear();
269
270 // FindQualified() might have struck already!
271 if( pParam )
272 {
273 pMeth->SetParameters( pParam );
274 }
275 pMeth->Broadcast( SfxHintId::BasicDataWanted );
276 pMeth->SetParameters( nullptr );
277 return true;
278 }
280 return false;
281}
282
284{
285 if ( !pDfltProp && !aDfltPropName.isEmpty() )
286 {
288 if( !pDfltProp )
289 {
291 }
292 }
293 return pDfltProp;
294}
295void SbxObject::SetDfltProperty( const OUString& rName )
296{
297 if ( rName != aDfltPropName )
298 {
299 pDfltProp = nullptr;
300 }
301 aDfltPropName = rName;
302 SetModified( true );
303}
304
305// Search of an already available variable. If it was located,
306// the index will be set, otherwise the Count of the Array will be returned.
307// In any case the correct Array will be returned.
308
309SbxArray* SbxObject::FindVar( SbxVariable const * pVar, sal_uInt32& nArrayIdx )
310{
311 SbxArray* pArray = nullptr;
312 if( pVar )
313 {
314 switch( pVar->GetClass() )
315 {
317 case SbxClassType::Property: pArray = pProps.get(); break;
318 case SbxClassType::Method: pArray = pMethods.get(); break;
319 case SbxClassType::Object: pArray = pObjs.get(); break;
320 default: SAL_WARN( "basic.sbx", "Invalid SBX-Class" ); break;
321 }
322 }
323 if( pArray )
324 {
325 nArrayIdx = pArray->Count();
326 // Is the variable per name available?
328 SbxVariable* pOld = pArray->Find( pVar->GetName(), pVar->GetClass() );
329 if( pOld )
330 {
331 for (sal_uInt32 i = 0; i < pArray->Count(); i++)
332 {
333 SbxVariableRef& rRef = pArray->GetRef(i);
334 if( rRef.get() == pOld )
335 {
336 nArrayIdx = i; break;
337 }
338 }
339 }
340 }
341 return pArray;
342}
343
344// If a new object will be established, this object will be indexed,
345// if an object of this name exists already.
346
347SbxVariable* SbxObject::Make( const OUString& rName, SbxClassType ct, SbxDataType dt, bool bIsRuntimeFunction )
348{
349 // Is the object already available?
350 SbxArray* pArray = nullptr;
351 switch( ct )
352 {
354 case SbxClassType::Property: pArray = pProps.get(); break;
355 case SbxClassType::Method: pArray = pMethods.get(); break;
356 case SbxClassType::Object: pArray = pObjs.get(); break;
357 default: SAL_WARN( "basic.sbx", "Invalid SBX-Class" ); break;
358 }
359 if( !pArray )
360 {
361 return nullptr;
362 }
363 // Collections may contain objects of the same name
364 if( ct != SbxClassType::Object || dynamic_cast<const SbxCollection*>( this ) == nullptr )
365 {
366 SbxVariable* pRes = pArray->Find( rName, ct );
367 if( pRes )
368 {
369 return pRes;
370 }
371 }
372 SbxVariableRef pVar;
373 switch( ct )
374 {
377 pVar = new SbxProperty( rName, dt );
378 break;
380 pVar = new SbxMethod( rName, dt, bIsRuntimeFunction );
381 break;
383 pVar = CreateObject( rName ).get();
384 break;
385 default:
386 break;
387 }
388 pVar->SetParent( this );
389 pArray->Put(pVar.get(), pArray->Count());
390 SetModified( true );
391 // The object listen always
392 StartListening(pVar->GetBroadcaster(), DuplicateHandling::Prevent);
393 return pVar.get();
394}
395
397{
398 sal_uInt32 nIdx;
399 SbxArray* pArray = FindVar( pVar, nIdx );
400 if( !pArray )
401 return;
402
403 // Into with it. But you should pay attention at the Pointer!
404 if (nIdx < pArray->Count())
405 {
406 // Then this element exists already
407 // There are objects of the same name allowed at collections
408 if( pArray == pObjs.get() && dynamic_cast<const SbxCollection*>( this ) != nullptr )
409 {
410 nIdx = pArray->Count();
411 }
412 else
413 {
414 SbxVariable* pOld = pArray->Get(nIdx);
415 // already inside: overwrite
416 if( pOld == pVar )
417 {
418 return;
419 }
420 EndListening( pOld->GetBroadcaster(), true );
421 if( pVar->GetClass() == SbxClassType::Property )
422 {
423 if( pOld == pDfltProp )
424 {
425 pDfltProp = static_cast<SbxProperty*>(pVar);
426 }
427 }
428 }
429 }
430 StartListening(pVar->GetBroadcaster(), DuplicateHandling::Prevent);
431 pArray->Put(pVar, nIdx);
432 if( pVar->GetParent() != this )
433 {
434 pVar->SetParent( this );
435 }
436 SetModified( true );
437#ifdef DBG_UTIL
438 static const char* pCls[] =
439 { "DontCare","Array","Value","Variable","Method","Property","Object" };
440 OUString aVarName( pVar->GetName() );
441 if (const SbxObject *pSbxObj = aVarName.isEmpty() ? dynamic_cast<const SbxObject*>(pVar) : nullptr)
442 {
443 aVarName = pSbxObj->GetClassName();
444 }
445 SAL_INFO(
446 "basic.sbx",
447 "insert "
448 << ((pVar->GetClass() >= SbxClassType::DontCare
449 && pVar->GetClass() <= SbxClassType::Object)
450 ? pCls[static_cast<int>(pVar->GetClass()) - 1] : "Unknown class")
451 << " " << aVarName << " in " << SbxVariable::GetName());
452#endif
453}
454
455// Optimisation, Insertion without checking about
456// double entry and without broadcasts, will only be used in SO2/auto.cxx
458{
459 SbxArray* pArray = nullptr;
460 if( pVar )
461 {
462 switch( pVar->GetClass() )
463 {
465 case SbxClassType::Property: pArray = pProps.get(); break;
466 case SbxClassType::Method: pArray = pMethods.get(); break;
467 case SbxClassType::Object: pArray = pObjs.get(); break;
468 default: SAL_WARN( "basic.sbx", "Invalid SBX-Class" ); break;
469 }
470 }
471 if( !pArray )
472 return;
473
474 StartListening(pVar->GetBroadcaster(), DuplicateHandling::Prevent);
475 pArray->Put(pVar, pArray->Count());
476 if( pVar->GetParent() != this )
477 {
478 pVar->SetParent( this );
479 }
480 SetModified( true );
481#ifdef DBG_UTIL
482 static const char* pCls[] =
483 { "DontCare","Array","Value","Variable","Method","Property","Object" };
484 OUString aVarName( pVar->GetName() );
485 if (const SbxObject *pSbxObj = aVarName.isEmpty() ? dynamic_cast<const SbxObject*>(pVar) : nullptr)
486 {
487 aVarName = pSbxObj->GetClassName();
488 }
489 SAL_INFO(
490 "basic.sbx",
491 "insert "
492 << ((pVar->GetClass() >= SbxClassType::DontCare
493 && pVar->GetClass() <= SbxClassType::Object)
494 ? pCls[static_cast<int>(pVar->GetClass()) - 1] : "Unknown class")
495 << " " << aVarName << " in " << SbxVariable::GetName());
496#endif
497}
498
499void SbxObject::Remove( const OUString& rName, SbxClassType t )
500{
501 Remove( SbxObject::Find( rName, t ) );
502}
503
505{
506 sal_uInt32 nIdx;
507 SbxArray* pArray = FindVar( pVar, nIdx );
508 if (!(pArray && nIdx < pArray->Count()))
509 return;
510
511#ifdef DBG_UTIL
512 OUString aVarName( pVar->GetName() );
513 if (const SbxObject *pSbxObj = aVarName.isEmpty() ? dynamic_cast<const SbxObject*>(pVar) : nullptr)
514 {
515 aVarName = pSbxObj->GetClassName();
516 }
517 SAL_INFO(
518 "basic.sbx",
519 "remove " << aVarName << " in " << SbxVariable::GetName());
520#endif
521 SbxVariableRef pVar_ = pArray->Get(nIdx);
522 if( pVar_->IsBroadcaster() )
523 {
524 EndListening( pVar_->GetBroadcaster(), true );
525 }
526 if( pVar_.get() == pDfltProp )
527 {
528 pDfltProp = nullptr;
529 }
530 pArray->Remove( nIdx );
531 if( pVar_->GetParent() == this )
532 {
533 pVar_->SetParent( nullptr );
534 }
535 SetModified( true );
536}
537
538static bool LoadArray( SvStream& rStrm, SbxObject* pThis, SbxArray* pArray )
539{
540 SbxArrayRef p = static_cast<SbxArray*>( SbxBase::Load( rStrm ).get() );
541 if( !p.is() )
542 {
543 return false;
544 }
545 for (sal_uInt32 i = 0; i < p->Count(); i++)
546 {
547 SbxVariableRef& r = p->GetRef(i);
548 SbxVariable* pVar = r.get();
549 if( pVar )
550 {
551 pVar->SetParent( pThis );
552 pThis->StartListening(pVar->GetBroadcaster(), DuplicateHandling::Prevent);
553 }
554 }
555 pArray->Merge( p.get() );
556 return true;
557}
558
559// The load of an object is additive!
560
561bool SbxObject::LoadData( SvStream& rStrm, sal_uInt16 nVer )
562{
563 // Help for the read in of old objects: just return TRUE,
564 // LoadPrivateData() has to set the default status up
565 if( !nVer )
566 {
567 return true;
568 }
569 pDfltProp = nullptr;
570 if( !SbxVariable::LoadData( rStrm, nVer ) )
571 {
572 return false;
573 }
574 // If it contains no alien object, insert ourselves
575 if( aData.eType == SbxOBJECT && !aData.pObj )
576 {
577 aData.pObj = this;
578 }
579 sal_uInt32 nSize;
580 OUString aDfltProp;
581 aClassName = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm, RTL_TEXTENCODING_ASCII_US);
582 aDfltProp = read_uInt16_lenPrefixed_uInt8s_ToOUString(rStrm, RTL_TEXTENCODING_ASCII_US);
583 sal_uInt64 nPos = rStrm.Tell();
584 rStrm.ReadUInt32( nSize );
585 sal_uInt64 const nNewPos = rStrm.Tell();
586 nPos += nSize;
587 DBG_ASSERT( nPos >= nNewPos, "SBX: Loaded too much data" );
588 if( nPos != nNewPos )
589 {
590 rStrm.Seek( nPos );
591 }
592 if( !LoadArray( rStrm, this, pMethods.get() ) ||
593 !LoadArray( rStrm, this, pProps.get() ) ||
594 !LoadArray( rStrm, this, pObjs.get() ) )
595 {
596 return false;
597 }
598 // Set properties
599 if( !aDfltProp.isEmpty() )
600 {
601 pDfltProp = static_cast<SbxProperty*>( pProps->Find( aDfltProp, SbxClassType::Property ) );
602 }
603 SetModified( false );
604 return true;
605}
606
607std::pair<bool, sal_uInt32> SbxObject::StoreData( SvStream& rStrm ) const
608{
610 {
611 return { false, 0 };
612 }
613 OUString aDfltProp;
614 if( pDfltProp )
615 {
616 aDfltProp = pDfltProp->GetName();
617 }
619 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aDfltProp, RTL_TEXTENCODING_ASCII_US);
620 sal_uInt64 const nPos = rStrm.Tell();
621 rStrm.WriteUInt32( 0 );
622 sal_uInt64 const nNew = rStrm.Tell();
623 rStrm.Seek( nPos );
624 rStrm.WriteUInt32( nNew - nPos );
625 rStrm.Seek( nNew );
626 const auto& [bSuccess, nVersion] = pMethods->Store( rStrm );
627 if( !bSuccess )
628 {
629 return { false, 0 };
630 }
631 if( !pProps->Store( rStrm ).first )
632 {
633 return { false, 0 };
634 }
635 if( !pObjs->Store( rStrm ).first )
636 {
637 return { false, 0 };
638 }
639 const_cast<SbxObject*>(this)->SetModified( false );
640 return { true, nVersion };
641}
642
643static bool CollectAttrs( const SbxBase* p, OUString& rRes )
644{
645 OUString aAttrs;
646 if( p->IsHidden() )
647 {
648 aAttrs = "Hidden";
649 }
650 if( p->IsSet( SbxFlagBits::ExtSearch ) )
651 {
652 if( !aAttrs.isEmpty() )
653 {
654 aAttrs += ",";
655 }
656 aAttrs += "ExtSearch";
657 }
658 if( !p->IsVisible() )
659 {
660 if( !aAttrs.isEmpty() )
661 {
662 aAttrs += ",";
663 }
664 aAttrs += "Invisible";
665 }
666 if( p->IsSet( SbxFlagBits::DontStore ) )
667 {
668 if( !aAttrs.isEmpty() )
669 {
670 aAttrs += ",";
671 }
672 aAttrs += "DontStore";
673 }
674 if( !aAttrs.isEmpty() )
675 {
676 rRes = " (" + aAttrs + ")";
677 return true;
678 }
679 else
680 {
681 rRes.clear();
682 return false;
683 }
684}
685
686void SbxObject::Dump( SvStream& rStrm, bool bFill )
687{
688 // Shifting
689 static sal_uInt16 nLevel = 0;
690 if ( nLevel > 10 )
691 {
692 rStrm.WriteOString( "<too deep>" ) << endl;
693 return;
694 }
695 ++nLevel;
696 OUString aIndent("");
697 for ( sal_uInt16 n = 1; n < nLevel; ++n )
698 {
699 aIndent += " ";
700 }
701 // Output the data of the object itself
702 OString aNameStr(OUStringToOString(GetName(), RTL_TEXTENCODING_ASCII_US));
703 OString aClassNameStr(OUStringToOString(aClassName, RTL_TEXTENCODING_ASCII_US));
704 rStrm.WriteOString( "Object( " )
705 .WriteOString( OString::number(reinterpret_cast<sal_IntPtr>(this)) ).WriteOString( "=='" )
706 .WriteOString( aNameStr.isEmpty() ? "<unnamed>" : aNameStr ).WriteOString( "', " )
707 .WriteOString( "of class '" ).WriteOString( aClassNameStr ).WriteOString( "', " )
708 .WriteOString( "counts " )
709 .WriteOString( OString::number(GetRefCount()) )
710 .WriteOString( " refs, " );
711 if ( GetParent() )
712 {
713 OString aParentNameStr(OUStringToOString(GetName(), RTL_TEXTENCODING_ASCII_US));
714 rStrm.WriteOString( "in parent " )
715 .WriteOString( OString::number(reinterpret_cast<sal_IntPtr>(GetParent())) )
716 .WriteOString( "=='" ).WriteOString( aParentNameStr.isEmpty() ? "<unnamed>" : aParentNameStr ).WriteOString( "'" );
717 }
718 else
719 {
720 rStrm.WriteOString( "no parent " );
721 }
722 rStrm.WriteOString( " )" ) << endl;
723 OString aIndentNameStr(OUStringToOString(aIndent, RTL_TEXTENCODING_ASCII_US));
724 rStrm.WriteOString( aIndentNameStr ).WriteOString( "{" ) << endl;
725
726 // Flags
727 OUString aAttrs;
728 if( CollectAttrs( this, aAttrs ) )
729 {
730 OString aAttrStr(OUStringToOString(aAttrs, RTL_TEXTENCODING_ASCII_US));
731 rStrm.WriteOString( aIndentNameStr ).WriteOString( "- Flags: " ).WriteOString( aAttrStr ) << endl;
732 }
733
734 // Methods
735 rStrm.WriteOString( aIndentNameStr ).WriteOString( "- Methods:" ) << endl;
736 for (sal_uInt32 i = 0; i < pMethods->Count(); i++)
737 {
738 SbxVariableRef& r = pMethods->GetRef(i);
739 SbxVariable* pVar = r.get();
740 if( pVar )
741 {
742 OUString aLine = aIndent + " - " + pVar->GetName( SbxNameType::ShortTypes );
743 OUString aAttrs2;
744 if( CollectAttrs( pVar, aAttrs2 ) )
745 {
746 aLine += aAttrs2;
747 }
748 if( dynamic_cast<const SbxMethod *>(pVar) == nullptr )
749 {
750 aLine += " !! Not a Method !!";
751 }
752 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aLine, RTL_TEXTENCODING_ASCII_US);
753
754 // Output also the object at object-methods
755 if ( pVar->GetValues_Impl().eType == SbxOBJECT &&
756 pVar->GetValues_Impl().pObj &&
757 pVar->GetValues_Impl().pObj != this &&
758 pVar->GetValues_Impl().pObj != GetParent() )
759 {
760 rStrm.WriteOString( " contains " );
761 static_cast<SbxObject*>(pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill );
762 }
763 else
764 {
765 rStrm << endl;
766 }
767 }
768 }
769
770 // Properties
771 rStrm.WriteOString( aIndentNameStr ).WriteOString( "- Properties:" ) << endl;
772 {
773 for (sal_uInt32 i = 0; i < pProps->Count(); i++)
774 {
775 SbxVariableRef& r = pProps->GetRef(i);
776 SbxVariable* pVar = r.get();
777 if( pVar )
778 {
779 OUString aLine = aIndent + " - " + pVar->GetName( SbxNameType::ShortTypes );
780 OUString aAttrs3;
781 if( CollectAttrs( pVar, aAttrs3 ) )
782 {
783 aLine += aAttrs3;
784 }
785 if( dynamic_cast<const SbxProperty *>(pVar) == nullptr )
786 {
787 aLine += " !! Not a Property !!";
788 }
789 write_uInt16_lenPrefixed_uInt8s_FromOUString(rStrm, aLine, RTL_TEXTENCODING_ASCII_US);
790
791 // output also the object at object properties
792 if ( pVar->GetValues_Impl().eType == SbxOBJECT &&
793 pVar->GetValues_Impl().pObj &&
794 pVar->GetValues_Impl().pObj != this &&
795 pVar->GetValues_Impl().pObj != GetParent() )
796 {
797 rStrm.WriteOString( " contains " );
798 static_cast<SbxObject*>(pVar->GetValues_Impl().pObj)->Dump( rStrm, bFill );
799 }
800 else
801 {
802 rStrm << endl;
803 }
804 }
805 }
806 }
807
808 // Objects
809 rStrm.WriteOString( aIndentNameStr ).WriteOString( "- Objects:" ) << endl;
810 {
811 for (sal_uInt32 i = 0; i < pObjs->Count(); i++)
812 {
813 SbxVariableRef& r = pObjs->GetRef(i);
814 SbxVariable* pVar = r.get();
815 if ( pVar )
816 {
817 rStrm.WriteOString( aIndentNameStr ).WriteOString( " - Sub" );
818 if (SbxObject *pSbxObj = dynamic_cast<SbxObject*>(pVar))
819 {
820 pSbxObj->Dump(rStrm, bFill);
821 }
822 else
823 {
824 pVar->Dump(rStrm, bFill);
825 }
826 }
827 }
828 }
829
830 rStrm.WriteOString( aIndentNameStr ).WriteOString( "}" ) << endl << endl;
831 --nLevel;
832}
833
834SbxMethod::SbxMethod( const OUString& r, SbxDataType t, bool bIsRuntimeFunction )
835 : SbxVariable(t)
836 , mbIsRuntimeFunction(bIsRuntimeFunction)
837 , mbRuntimeFunctionReturnType(t)
838{
839 SetName(r);
840}
841
843 : SvRefBase(r)
844 , SbxVariable(r)
845 , mbIsRuntimeFunction(r.IsRuntimeFunction())
846 , mbRuntimeFunctionReturnType(r.GetRuntimeFunctionReturnType())
847{
848}
849
851{
852}
853
855{
857}
858
860{
861 // Release referenced data, and reset data type to the function return type
862 // Implementation similar to SbxValue::SetType
863 // tdf#143582: Don't take "read-only" flag into account, allow clearing method return value
864 switch (aData.eType)
865 {
866 case SbxSTRING:
867 delete aData.pOUString;
868 break;
869 case SbxOBJECT:
870 if (aData.pObj)
871 {
872 if (aData.pObj != this)
873 {
874 bool bParentProp = (GetUserData() & 0xFFFF) == 5345; // See sbxvalue.cxx
875 if (!bParentProp)
877 }
878 }
879 break;
880 case SbxDECIMAL:
882 break;
883 default:
884 break;
885 }
887}
888
890 : SbxVariable( t )
891{
892 SetName( r );
893}
894
896{
897}
898
900{
902}
903
904/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
XPropertyListType t
Definition: sbx.hxx:95
void Merge(SbxArray *)
Definition: sbxarray.cxx:230
SbxVariable * Find(const OUString &, SbxClassType)
Definition: sbxarray.cxx:275
sal_uInt32 Count() const
Definition: sbxarray.cxx:87
void Remove(sal_uInt32)
Definition: sbxarray.cxx:204
SbxVariableRef & GetRef(sal_uInt32)
Definition: sbxarray.cxx:92
SbxVariable * Get(sal_uInt32)
Definition: sbxarray.cxx:108
void Put(SbxVariable *, sal_uInt32)
Definition: sbxarray.cxx:123
static void SetError(ErrCode)
Definition: sbxbase.cxx:116
void SetFlags(SbxFlagBits n)
Definition: sbxcore.hxx:102
bool IsSet(SbxFlagBits n) const
Definition: sbxcore.hxx:114
SbxFlagBits GetFlags() const
Definition: sbxcore.hxx:105
static SbxObjectRef CreateObject(const OUString &)
Definition: sbxbase.cxx:185
static SbxBaseRef Load(SvStream &)
Definition: sbxbase.cxx:212
void ResetFlag(SbxFlagBits n)
Definition: sbxcore.hxx:111
Definition: sbx.hxx:81
virtual SbxClassType GetClass() const override
Definition: sbxobj.cxx:854
virtual ~SbxMethod() override
Definition: sbxobj.cxx:850
SbxMethod(const OUString &r, SbxDataType t, bool bIsRuntimeFunction=false)
Definition: sbxobj.cxx:834
virtual void Clear() override
Definition: sbxobj.cxx:859
void Dump(SvStream &, bool bDumpAll)
Definition: sbxobj.cxx:686
virtual void Clear() override
Definition: sbxobj.cxx:125
SbxProperty * GetDfltProperty()
Definition: sbxobj.cxx:283
virtual void Insert(SbxVariable *)
Definition: sbxobj.cxx:396
virtual SbxClassType GetClass() const override
Definition: sbxobj.cxx:120
virtual SbxVariable * Find(const OUString &, SbxClassType)
Definition: sbxobj.cxx:182
virtual bool Call(const OUString &, SbxArray *=nullptr)
Definition: sbxobj.cxx:262
SbxArrayRef pObjs
Definition: sbxobj.hxx:36
virtual ~SbxObject() override
Definition: sbxobj.cxx:105
SbxVariable * FindQualified(const OUString &, SbxClassType)
Definition: sbxexec.cxx:366
virtual SbxDataType GetType() const override
Definition: sbxobj.cxx:115
OUString aDfltPropName
Definition: sbxobj.hxx:39
void Remove(const OUString &, SbxClassType)
Definition: sbxobj.cxx:499
SbxArrayRef pMethods
Definition: sbxobj.hxx:34
virtual bool LoadData(SvStream &, sal_uInt16) override
Definition: sbxobj.cxx:561
SbxVariable * Make(const OUString &, SbxClassType, SbxDataType, bool bIsRuntimeFunction=false)
Definition: sbxobj.cxx:347
void QuickInsert(SbxVariable *)
Definition: sbxobj.cxx:457
BASIC_DLLPRIVATE SbxArray * FindVar(SbxVariable const *, sal_uInt32 &)
Definition: sbxobj.cxx:309
OUString aClassName
Definition: sbxobj.hxx:38
virtual void Notify(SfxBroadcaster &rBC, const SfxHint &rHint) override
Definition: sbxobj.cxx:140
SbxObject(const OUString &rClassname)
Definition: sbxobj.cxx:43
SbxProperty * pDfltProp
Definition: sbxobj.hxx:37
virtual bool IsClass(const OUString &) const
Definition: sbxobj.cxx:177
SbxObject & operator=(const SbxObject &)
Definition: sbxobj.cxx:65
void SetDfltProperty(const OUString &r)
Definition: sbxobj.cxx:295
SbxArrayRef pProps
Definition: sbxobj.hxx:35
virtual std::pair< bool, sal_uInt32 > StoreData(SvStream &) const override
Definition: sbxobj.cxx:607
virtual SbxClassType GetClass() const override
Definition: sbxobj.cxx:899
SbxProperty(const OUString &r, SbxDataType t)
Definition: sbxobj.cxx:889
virtual ~SbxProperty() override
Definition: sbxobj.cxx:895
OUString GetOUString() const
Definition: sbxvalue.cxx:380
bool PutString(const OUString &)
Definition: sbxvalue.cxx:585
SbxValues aData
Definition: sbxvar.hxx:99
virtual bool IsFixed() const override
Definition: sbxvalue.cxx:618
const SbxValues & GetValues_Impl() const
Definition: sbxvar.hxx:135
bool PutObject(SbxBase *)
virtual void Clear() override
Definition: sbxvalue.cxx:146
SbxVariable & operator=(const SbxVariable &)
Definition: sbxvar.cxx:295
const SbxObject * GetParent() const
Definition: sbxvar.hxx:296
virtual SbxClassType GetClass() const
Definition: sbxvar.cxx:337
virtual bool LoadData(SvStream &, sal_uInt16) override
Definition: sbxvar.cxx:409
SfxBroadcaster & GetBroadcaster()
Definition: sbxvar.cxx:102
void SetName(const OUString &)
Definition: sbxvar.cxx:192
virtual void Broadcast(SfxHintId nHintId) override
Definition: sbxvar.cxx:120
void SetParameters(SbxArray *p)
Definition: sbxvar.cxx:178
void Dump(SvStream &, bool bDumpAll)
Definition: sbxvar.cxx:572
const OUString & GetName(SbxNameType=SbxNameType::NONE) const
Definition: sbxvar.cxx:199
sal_uInt32 GetUserData() const
Definition: sbxvar.hxx:278
static constexpr sal_uInt16 MakeHashCode(std::u16string_view aName)
Definition: sbxvar.hxx:307
virtual std::pair< bool, sal_uInt32 > StoreData(SvStream &) const override
Definition: sbxvar.cxx:519
virtual void SetParent(SbxObject *)
Definition: sbxvar.cxx:355
virtual void SetModified(bool) override
Definition: sbxvar.cxx:342
SbxObject * pParent
Definition: sbxvar.hxx:258
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
unsigned int GetRefCount() const
void ReleaseRef()
sal_uInt64 Tell() const
SvStream & WriteOString(std::string_view rStr)
SvStream & WriteUInt32(sal_uInt32 nUInt32)
SvStream & ReadUInt32(sal_uInt32 &rUInt32)
sal_uInt64 Seek(sal_uInt64 nPos)
T * get() const
#define DBG_ASSERT(sCon, aError)
sal_Int16 nVersion
SfxHintId
void * p
sal_Int64 n
sal_uInt16 nPos
#define SAL_INFO_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
int i
constexpr OUStringLiteral first
void SvStream & rStrm
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
sal_Int16 nId
#define ERRCODE_BASIC_NO_METHOD
Definition: sberrors.hxx:42
void releaseDecimalPtr(SbxDecimal *&rpDecimal)
Definition: sbxdec.cxx:77
SbxDataType
Definition: sbxdef.hxx:37
@ SbxOBJECT
Definition: sbxdef.hxx:47
@ SbxEMPTY
Definition: sbxdef.hxx:38
@ SbxDECIMAL
Definition: sbxdef.hxx:77
@ SbxVARIANT
Definition: sbxdef.hxx:51
@ SbxSTRING
Definition: sbxdef.hxx:46
SbxClassType
Definition: sbxdef.hxx:27
SbxFlagBits
Definition: sbxdef.hxx:131
static bool LoadArray(SvStream &rStrm, SbxObject *pThis, SbxArray *pArray)
Definition: sbxobj.cxx:538
static OUString pParentProp
Definition: sbxobj.cxx:38
static void CheckParentsOnDelete(SbxObject *pObj, SbxArray *p)
Definition: sbxobj.cxx:87
static sal_uInt16 nParentHash
Definition: sbxobj.cxx:40
static sal_uInt16 nNameHash
Definition: sbxobj.cxx:40
static OUString pNameProp
Definition: sbxobj.cxx:37
static bool CollectAttrs(const SbxBase *p, OUString &rRes)
Definition: sbxobj.cxx:643
OUString GetSbxRes(StringId nId)
Definition: sbxres.cxx:75
OUString read_uInt16_lenPrefixed_uInt8s_ToOUString(SvStream &rStrm, rtl_TextEncoding eEnc)
TOOLS_DLLPUBLIC SvStream & endl(SvStream &rStr)
std::size_t write_uInt16_lenPrefixed_uInt8s_FromOUString(SvStream &rStrm, std::u16string_view rStr, rtl_TextEncoding eEnc)
OUString * pOUString
Definition: sbxvar.hxx:58
SbxBase * pObj
Definition: sbxvar.hxx:61
SbxDecimal * pDecimal
Definition: sbxvar.hxx:59
void clear(SbxDataType type)
Definition: sbxvar.hxx:83
SbxDataType eType
Definition: sbxvar.hxx:77
Count