fdo#74697 Add Bluez 5 support for impress remote.
[LibreOffice.git] / basic / source / sbx / sbxarray.cxx
blobded3f2e3e42fe884cc5382de70039bd50aa70245
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 <tools/stream.hxx>
21 #include <basic/sbx.hxx>
22 #include "runtime.hxx"
23 #include <vector>
24 using namespace std;
26 struct SbxDim { // an array-dimension:
27 SbxDim* pNext; // Link
28 sal_Int32 nLbound, nUbound; // Limitations
29 sal_Int32 nSize; // Number of elements
32 class SbxVarEntry : public SbxVariableRef {
33 public:
34 OUString* pAlias;
35 SbxVarEntry() : SbxVariableRef(), pAlias( NULL ) {}
36 ~SbxVarEntry() { delete pAlias; }
39 typedef SbxVarEntry* SbxVarEntryPtr;
40 typedef vector< SbxVarEntryPtr > SbxVarEntryPtrVector;
41 class SbxVarRefs : public SbxVarEntryPtrVector
43 public:
44 SbxVarRefs( void ) {}
48 TYPEINIT1(SbxArray,SbxBase)
49 TYPEINIT1(SbxDimArray,SbxArray)
51 // SbxArray
53 SbxArray::SbxArray( SbxDataType t ) : SbxBase()
55 pData = new SbxVarRefs;
56 eType = t;
57 if( t != SbxVARIANT )
58 SetFlag( SBX_FIXED );
61 SbxArray::SbxArray( const SbxArray& rArray ) :
62 SvRefBase( rArray ), SbxBase()
64 pData = new SbxVarRefs;
65 if( rArray.eType != SbxVARIANT )
66 SetFlag( SBX_FIXED );
67 *this = rArray;
70 SbxArray& SbxArray::operator=( const SbxArray& rArray )
72 if( &rArray != this )
74 eType = rArray.eType;
75 Clear();
76 SbxVarRefs* pSrc = rArray.pData;
77 for( sal_uInt32 i = 0; i < pSrc->size(); i++ )
79 SbxVarEntryPtr pSrcRef = (*pSrc)[i];
80 const SbxVariable* pSrc_ = *pSrcRef;
81 if( !pSrc_ )
82 continue;
83 SbxVarEntryPtr pDstRef = new SbxVarEntry;
84 *((SbxVariableRef*) pDstRef) = *((SbxVariableRef*) pSrcRef);
85 if( pSrcRef->pAlias )
87 pDstRef->pAlias = new OUString( *pSrcRef->pAlias );
89 if( eType != SbxVARIANT )
91 // Convert no objects
92 if( eType != SbxOBJECT || pSrc_->GetClass() != SbxCLASS_OBJECT )
94 ((SbxVariable*) pSrc_)->Convert( eType );
97 pData->push_back( pDstRef );
100 return *this;
103 SbxArray::~SbxArray()
105 Clear();
106 delete pData;
109 SbxDataType SbxArray::GetType() const
111 return (SbxDataType) ( eType | SbxARRAY );
114 SbxClassType SbxArray::GetClass() const
116 return SbxCLASS_ARRAY;
119 void SbxArray::Clear()
121 sal_uInt32 nSize = pData->size();
122 for( sal_uInt32 i = 0 ; i < nSize ; i++ )
124 SbxVarEntry* pEntry = (*pData)[i];
125 delete pEntry;
127 pData->clear();
130 sal_uInt32 SbxArray::Count32() const
132 return pData->size();
135 sal_uInt16 SbxArray::Count() const
137 sal_uInt32 nCount = pData->size();
138 DBG_ASSERT( nCount <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" );
139 return (sal_uInt16)nCount;
142 SbxVariableRef& SbxArray::GetRef32( sal_uInt32 nIdx )
144 // If necessary extend the array
145 DBG_ASSERT( nIdx <= SBX_MAXINDEX32, "SBX: Array-Index > SBX_MAXINDEX32" );
146 // Very Hot Fix
147 if( nIdx > SBX_MAXINDEX32 )
149 SetError( SbxERR_BOUNDS );
150 nIdx = 0;
152 while( pData->size() <= nIdx )
154 const SbxVarEntryPtr p = new SbxVarEntry;
155 pData->push_back( p );
157 return *((*pData)[nIdx]);
160 SbxVariableRef& SbxArray::GetRef( sal_uInt16 nIdx )
162 // If necessary extend the array
163 DBG_ASSERT( nIdx <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" );
164 // Very Hot Fix
165 if( nIdx > SBX_MAXINDEX )
167 SetError( SbxERR_BOUNDS );
168 nIdx = 0;
170 while( pData->size() <= nIdx )
172 const SbxVarEntryPtr p = new SbxVarEntry;
173 pData->push_back( p );
175 return *((*pData)[nIdx]);
178 SbxVariable* SbxArray::Get32( sal_uInt32 nIdx )
180 if( !CanRead() )
182 SetError( SbxERR_PROP_WRITEONLY );
183 return NULL;
185 SbxVariableRef& rRef = GetRef32( nIdx );
187 if ( !rRef.Is() )
188 rRef = new SbxVariable( eType );
189 #ifdef DBG_UTIL
190 else
191 DBG_CHKOBJ( rRef, SbxBase, 0 );
192 #endif
194 return rRef;
197 SbxVariable* SbxArray::Get( sal_uInt16 nIdx )
199 if( !CanRead() )
201 SetError( SbxERR_PROP_WRITEONLY );
202 return NULL;
204 SbxVariableRef& rRef = GetRef( nIdx );
206 if ( !rRef.Is() )
207 rRef = new SbxVariable( eType );
208 #ifdef DBG_UTIL
209 else
210 DBG_CHKOBJ( rRef, SbxBase, 0 );
211 #endif
213 return rRef;
216 void SbxArray::Put32( SbxVariable* pVar, sal_uInt32 nIdx )
218 if( !CanWrite() )
219 SetError( SbxERR_PROP_READONLY );
220 else
222 if( pVar )
223 if( eType != SbxVARIANT )
224 // Convert no objects
225 if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT )
226 pVar->Convert( eType );
227 SbxVariableRef& rRef = GetRef32( nIdx );
228 if( (SbxVariable*) rRef != pVar )
230 rRef = pVar;
231 SetFlag( SBX_MODIFIED );
236 void SbxArray::Put( SbxVariable* pVar, sal_uInt16 nIdx )
238 if( !CanWrite() )
239 SetError( SbxERR_PROP_READONLY );
240 else
242 if( pVar )
243 if( eType != SbxVARIANT )
244 // Convert no objects
245 if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT )
246 pVar->Convert( eType );
247 SbxVariableRef& rRef = GetRef( nIdx );
248 if( (SbxVariable*) rRef != pVar )
250 rRef = pVar;
251 SetFlag( SBX_MODIFIED );
256 const OUString& SbxArray::GetAlias( sal_uInt16 nIdx )
258 static const OUString sEmpty("");
260 if( !CanRead() )
262 SetError( SbxERR_PROP_WRITEONLY );
263 return sEmpty;
265 SbxVarEntry& rRef = (SbxVarEntry&) GetRef( nIdx );
267 if ( !rRef.pAlias )
269 return sEmpty;
271 #ifdef DBG_UTIL
272 else
274 DBG_CHKOBJ( rRef, SbxBase, 0 );
276 #endif
278 return *rRef.pAlias;
281 void SbxArray::PutAlias( const OUString& rAlias, sal_uInt16 nIdx )
283 if( !CanWrite() )
285 SetError( SbxERR_PROP_READONLY );
287 else
289 SbxVarEntry& rRef = (SbxVarEntry&) GetRef( nIdx );
290 if( !rRef.pAlias )
292 rRef.pAlias = new OUString( rAlias );
294 else
296 *rRef.pAlias = rAlias;
301 void SbxArray::Insert32( SbxVariable* pVar, sal_uInt32 nIdx )
303 DBG_ASSERT( pData->size() <= SBX_MAXINDEX32, "SBX: Array gets too big" );
304 if( pData->size() > SBX_MAXINDEX32 )
306 return;
308 SbxVarEntryPtr p = new SbxVarEntry;
309 *((SbxVariableRef*) p) = pVar;
310 SbxVarEntryPtrVector::size_type nSize = pData->size();
311 if( nIdx > nSize )
313 nIdx = nSize;
315 if( eType != SbxVARIANT && pVar )
317 (*p)->Convert( eType );
319 if( nIdx == nSize )
321 pData->push_back( p );
323 else
325 pData->insert( pData->begin() + nIdx, p );
327 SetFlag( SBX_MODIFIED );
330 void SbxArray::Insert( SbxVariable* pVar, sal_uInt16 nIdx )
332 DBG_ASSERT( pData->size() <= 0x3FF0, "SBX: Array gets too big" );
333 if( pData->size() > 0x3FF0 )
335 return;
337 Insert32( pVar, nIdx );
340 void SbxArray::Remove32( sal_uInt32 nIdx )
342 if( nIdx < pData->size() )
344 SbxVariableRef* pRef = (*pData)[nIdx];
345 pData->erase( pData->begin() + nIdx );
346 delete pRef;
347 SetFlag( SBX_MODIFIED );
351 void SbxArray::Remove( sal_uInt16 nIdx )
353 if( nIdx < pData->size() )
355 SbxVariableRef* pRef = (*pData)[nIdx];
356 pData->erase( pData->begin() + nIdx );
357 delete pRef;
358 SetFlag( SBX_MODIFIED );
362 void SbxArray::Remove( SbxVariable* pVar )
364 if( pVar )
366 for( sal_uInt32 i = 0; i < pData->size(); i++ )
368 SbxVariableRef* pRef = (*pData)[i];
369 if( *pRef == pVar )
371 Remove32( i ); break;
377 // Taking over of the data from the passed array, at which
378 // the variable of the same name will be overwritten.
380 void SbxArray::Merge( SbxArray* p )
382 if( p )
384 sal_uInt32 nSize = p->Count();
385 for( sal_uInt32 i = 0; i < nSize; i++ )
387 SbxVarEntryPtr pRef1 = (*(p->pData))[i];
388 // Is the element by name already inside?
389 // Then overwrite!
390 SbxVariable* pVar = *pRef1;
391 if( pVar )
393 OUString aName = pVar->GetName();
394 sal_uInt16 nHash = pVar->GetHashCode();
395 for( sal_uInt32 j = 0; j < pData->size(); j++ )
397 SbxVariableRef* pRef2 = (*pData)[j];
398 if( (*pRef2)->GetHashCode() == nHash
399 && (*pRef2)->GetName().equalsIgnoreAsciiCase( aName ) )
401 *pRef2 = pVar; pRef1 = NULL;
402 break;
405 if( pRef1 )
407 SbxVarEntryPtr pRef = new SbxVarEntry;
408 const SbxVarEntryPtr pTemp = pRef;
409 pData->push_back( pTemp );
410 *((SbxVariableRef*) pRef) = *((SbxVariableRef*) pRef1);
411 if( pRef1->pAlias )
413 pRef->pAlias = new OUString( *pRef1->pAlias );
421 // Search of an element via the user data. If the element is
422 // object, it will also be scanned.
424 SbxVariable* SbxArray::FindUserData( sal_uInt32 nData )
426 SbxVariable* p = NULL;
427 for( sal_uInt32 i = 0; i < pData->size(); i++ )
429 SbxVariableRef* pRef = (*pData)[i];
430 SbxVariable* pVar = *pRef;
431 if( pVar )
433 if( pVar->IsVisible() && pVar->GetUserData() == nData )
435 p = pVar;
436 p->ResetFlag( SBX_EXTFOUND );
437 break; // JSM 1995-10-06
439 // Did we have an array/object with extended search?
440 else if( pVar->IsSet( SBX_EXTSEARCH ) )
442 switch( pVar->GetClass() )
444 case SbxCLASS_OBJECT:
446 // Objects are not allowed to scan their parent.
447 sal_uInt16 nOld = pVar->GetFlags();
448 pVar->ResetFlag( SBX_GBLSEARCH );
449 p = ((SbxObject*) pVar)->FindUserData( nData );
450 pVar->SetFlags( nOld );
451 break;
453 case SbxCLASS_ARRAY:
454 p = ((SbxArray*) pVar)->FindUserData( nData );
455 break;
456 default: break;
458 if( p )
460 p->SetFlag( SBX_EXTFOUND );
461 break;
466 return p;
469 // Search of an element by his name and type. If an element is an object,
470 // it will also be scanned..
472 SbxVariable* SbxArray::Find( const OUString& rName, SbxClassType t )
474 SbxVariable* p = NULL;
475 sal_uInt32 nCount = pData->size();
476 if( !nCount )
477 return NULL;
478 sal_Bool bExtSearch = IsSet( SBX_EXTSEARCH );
479 sal_uInt16 nHash = SbxVariable::MakeHashCode( rName );
480 for( sal_uInt32 i = 0; i < nCount; i++ )
482 SbxVariableRef* pRef = (*pData)[i];
483 SbxVariable* pVar = *pRef;
484 if( pVar && pVar->IsVisible() )
486 // The very secure search works as well, if there is no hashcode!
487 sal_uInt16 nVarHash = pVar->GetHashCode();
488 if( ( !nVarHash || nVarHash == nHash )
489 && ( t == SbxCLASS_DONTCARE || pVar->GetClass() == t )
490 && ( pVar->GetName().equalsIgnoreAsciiCase( rName ) ) )
492 p = pVar;
493 p->ResetFlag( SBX_EXTFOUND );
494 break;
496 // Did we have an array/object with extended search?
497 else if( bExtSearch && pVar->IsSet( SBX_EXTSEARCH ) )
499 switch( pVar->GetClass() )
501 case SbxCLASS_OBJECT:
503 // Objects are not allowed to scan their parent.
504 sal_uInt16 nOld = pVar->GetFlags();
505 pVar->ResetFlag( SBX_GBLSEARCH );
506 p = ((SbxObject*) pVar)->Find( rName, t );
507 pVar->SetFlags( nOld );
508 break;
510 case SbxCLASS_ARRAY:
511 p = ((SbxArray*) pVar)->Find( rName, t );
512 break;
513 default: break;
515 if( p )
517 p->SetFlag( SBX_EXTFOUND );
518 break;
523 return p;
526 sal_Bool SbxArray::LoadData( SvStream& rStrm, sal_uInt16 nVer )
528 sal_uInt16 nElem;
529 Clear();
530 sal_Bool bRes = sal_True;
531 sal_uInt16 f = nFlags;
532 nFlags |= SBX_WRITE;
533 rStrm >> nElem;
534 nElem &= 0x7FFF;
535 for( sal_uInt32 n = 0; n < nElem; n++ )
537 sal_uInt16 nIdx;
538 rStrm >> nIdx;
539 SbxVariable* pVar = (SbxVariable*) Load( rStrm );
540 if( pVar )
542 SbxVariableRef& rRef = GetRef( nIdx );
543 rRef = pVar;
545 else
547 bRes = sal_False; break;
550 if( bRes )
551 bRes = LoadPrivateData( rStrm, nVer );
552 nFlags = f;
553 return bRes;
556 sal_Bool SbxArray::StoreData( SvStream& rStrm ) const
558 sal_uInt32 nElem = 0;
559 sal_uInt32 n;
560 // Which elements are even defined?
561 for( n = 0; n < pData->size(); n++ )
563 SbxVariableRef* pRef = (*pData)[n];
564 SbxVariable* p = *pRef;
565 if( p && !( p->GetFlags() & SBX_DONTSTORE ) )
566 nElem++;
568 rStrm << (sal_uInt16) nElem;
569 for( n = 0; n < pData->size(); n++ )
571 SbxVariableRef* pRef = (*pData)[n];
572 SbxVariable* p = *pRef;
573 if( p && !( p->GetFlags() & SBX_DONTSTORE ) )
575 rStrm << (sal_uInt16) n;
576 if( !p->Store( rStrm ) )
577 return sal_False;
580 return StorePrivateData( rStrm );
583 // #100883 Method to set method directly to parameter array
584 void SbxArray::PutDirect( SbxVariable* pVar, sal_uInt32 nIdx )
586 SbxVariableRef& rRef = GetRef32( nIdx );
587 rRef = pVar;
591 // SbxArray
593 SbxDimArray::SbxDimArray( SbxDataType t ) : SbxArray( t ), mbHasFixedSize( false )
595 pFirst = pLast = NULL;
596 nDim = 0;
599 SbxDimArray::SbxDimArray( const SbxDimArray& rArray )
600 : SvRefBase( rArray ), SbxArray( rArray.eType )
602 pFirst = pLast = NULL;
603 nDim = 0;
604 *this = rArray;
607 SbxDimArray& SbxDimArray::operator=( const SbxDimArray& rArray )
609 if( &rArray != this )
611 SbxArray::operator=( (const SbxArray&) rArray );
612 SbxDim* p = rArray.pFirst;
613 while( p )
615 AddDim32( p->nLbound, p->nUbound );
616 p = p->pNext;
618 this->mbHasFixedSize = rArray.mbHasFixedSize;
620 return *this;
623 SbxDimArray::~SbxDimArray()
625 Clear();
628 void SbxDimArray::Clear()
630 SbxDim* p = pFirst;
631 while( p )
633 SbxDim* q = p->pNext;
634 delete p;
635 p = q;
637 pFirst = pLast = NULL;
638 nDim = 0;
641 // Add a dimension
643 void SbxDimArray::AddDimImpl32( sal_Int32 lb, sal_Int32 ub, sal_Bool bAllowSize0 )
645 SbxError eRes = SbxERR_OK;
646 if( ub < lb && !bAllowSize0 )
648 eRes = SbxERR_BOUNDS;
649 ub = lb;
651 SbxDim* p = new SbxDim;
652 p->nLbound = lb;
653 p->nUbound = ub;
654 p->nSize = ub - lb + 1;
655 p->pNext = NULL;
656 if( !pFirst )
657 pFirst = pLast = p;
658 else
659 pLast->pNext = p, pLast = p;
660 nDim++;
661 if( eRes )
662 SetError( eRes );
665 short SbxDimArray::GetDims() const
667 return nDim;
670 void SbxDimArray::AddDim( short lb, short ub )
672 AddDimImpl32( lb, ub, sal_False );
675 void SbxDimArray::unoAddDim( short lb, short ub )
677 AddDimImpl32( lb, ub, sal_True );
680 void SbxDimArray::AddDim32( sal_Int32 lb, sal_Int32 ub )
682 AddDimImpl32( lb, ub, sal_False );
685 void SbxDimArray::unoAddDim32( sal_Int32 lb, sal_Int32 ub )
687 AddDimImpl32( lb, ub, sal_True );
691 // Readout dimension data
693 sal_Bool SbxDimArray::GetDim32( sal_Int32 n, sal_Int32& rlb, sal_Int32& rub ) const
695 if( n < 1 || n > nDim )
697 SetError( SbxERR_BOUNDS ); rub = rlb = 0; return sal_False;
699 SbxDim* p = pFirst;
700 while( --n )
701 p = p->pNext;
702 rub = p->nUbound;
703 rlb = p->nLbound;
704 return sal_True;
707 sal_Bool SbxDimArray::GetDim( short n, short& rlb, short& rub ) const
709 sal_Int32 rlb32, rub32;
710 sal_Bool bRet = GetDim32( n, rlb32, rub32 );
711 if( bRet )
713 if( rlb32 < -SBX_MAXINDEX || rub32 > SBX_MAXINDEX )
715 SetError( SbxERR_BOUNDS );
716 return sal_False;
718 rub = (short)rub32;
719 rlb = (short)rlb32;
721 return bRet;
724 // Element-Ptr with the help of an index list
726 sal_uInt32 SbxDimArray::Offset32( const sal_Int32* pIdx )
728 sal_uInt32 nPos = 0;
729 for( SbxDim* p = pFirst; p; p = p->pNext )
731 sal_Int32 nIdx = *pIdx++;
732 if( nIdx < p->nLbound || nIdx > p->nUbound )
734 nPos = (sal_uInt32)SBX_MAXINDEX32 + 1; break;
736 nPos = nPos * p->nSize + nIdx - p->nLbound;
738 if( nDim == 0 || nPos > SBX_MAXINDEX32 )
740 SetError( SbxERR_BOUNDS ); nPos = 0;
742 return nPos;
745 sal_uInt16 SbxDimArray::Offset( const short* pIdx )
747 long nPos = 0;
748 for( SbxDim* p = pFirst; p; p = p->pNext )
750 short nIdx = *pIdx++;
751 if( nIdx < p->nLbound || nIdx > p->nUbound )
753 nPos = SBX_MAXINDEX + 1; break;
755 nPos = nPos * p->nSize + nIdx - p->nLbound;
757 if( nDim == 0 || nPos > SBX_MAXINDEX )
759 SetError( SbxERR_BOUNDS ); nPos = 0;
761 return (sal_uInt16) nPos;
764 SbxVariable* SbxDimArray::Get( const short* pIdx )
766 return SbxArray::Get( Offset( pIdx ) );
769 void SbxDimArray::Put( SbxVariable* p, const short* pIdx )
771 SbxArray::Put( p, Offset( pIdx ) );
774 SbxVariable* SbxDimArray::Get32( const sal_Int32* pIdx )
776 return SbxArray::Get32( Offset32( pIdx ) );
779 void SbxDimArray::Put32( SbxVariable* p, const sal_Int32* pIdx )
781 SbxArray::Put32( p, Offset32( pIdx ) );
785 // Element-Number with the help of Parameter-Array
787 sal_uInt32 SbxDimArray::Offset32( SbxArray* pPar )
789 #ifndef DISABLE_SCRIPTING
790 if( nDim == 0 || !pPar || ( ( nDim != ( pPar->Count() - 1 ) ) && SbiRuntime::isVBAEnabled() ) )
792 SetError( SbxERR_BOUNDS ); return 0;
794 #endif
795 sal_uInt32 nPos = 0;
796 sal_uInt16 nOff = 1; // Non element 0!
797 for( SbxDim* p = pFirst; p && !IsError(); p = p->pNext )
799 sal_Int32 nIdx = pPar->Get( nOff++ )->GetLong();
800 if( nIdx < p->nLbound || nIdx > p->nUbound )
802 nPos = (sal_uInt32) SBX_MAXINDEX32+1; break;
804 nPos = nPos * p->nSize + nIdx - p->nLbound;
806 if( nPos > (sal_uInt32) SBX_MAXINDEX32 )
808 SetError( SbxERR_BOUNDS ); nPos = 0;
810 return nPos;
813 SbxVariable* SbxDimArray::Get( SbxArray* pPar )
815 return SbxArray::Get32( Offset32( pPar ) );
818 sal_Bool SbxDimArray::LoadData( SvStream& rStrm, sal_uInt16 nVer )
820 short nDimension;
821 rStrm >> nDimension;
822 for( short i = 0; i < nDimension && rStrm.GetError() == SVSTREAM_OK; i++ )
824 sal_Int16 lb, ub;
825 rStrm >> lb >> ub;
826 AddDim( lb, ub );
828 return SbxArray::LoadData( rStrm, nVer );
831 sal_Bool SbxDimArray::StoreData( SvStream& rStrm ) const
833 rStrm << (sal_Int16) nDim;
834 for( short i = 0; i < nDim; i++ )
836 short lb, ub;
837 GetDim( i, lb, ub );
838 rStrm << (sal_Int16) lb << (sal_Int16) ub;
840 return SbxArray::StoreData( rStrm );
843 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */