xref: /aoo42x/main/basic/source/sbx/sbxarray.cxx (revision e1f63238)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_basic.hxx"
26 #include <tools/stream.hxx>
27 #include <basic/sbx.hxx>
28 #include "runtime.hxx"
29 #include <vector>
30 using namespace std;
31 
32 struct SbxDim {                 // eine Array-Dimension:
33 	SbxDim* pNext;              // Link
34 	sal_Int32 nLbound, nUbound;     // Begrenzungen
35 	sal_Int32 nSize;                // Anzahl Elemente
36 };
37 
38 class SbxVarEntry : public SbxVariableRef {
39 public:
40 	XubString* pAlias;
SbxVarEntry()41 	SbxVarEntry() : SbxVariableRef(), pAlias( NULL ) {}
~SbxVarEntry()42    ~SbxVarEntry() { delete pAlias; }
43 };
44 
45 typedef SbxVarEntry* SbxVarEntryPtr;
46 typedef vector< SbxVarEntryPtr > SbxVarEntryPtrVector;
47 class SbxVarRefs : public SbxVarEntryPtrVector
48 {
49 public:
SbxVarRefs(void)50     SbxVarRefs( void ) {}
51 };
52 
53 
TYPEINIT1(SbxArray,SbxBase)54 TYPEINIT1(SbxArray,SbxBase)
55 TYPEINIT1(SbxDimArray,SbxArray)
56 
57 //////////////////////////////////////////////////////////////////////////
58 //
59 //  SbxArray
60 //
61 //////////////////////////////////////////////////////////////////////////
62 
63 SbxArray::SbxArray( SbxDataType t ) : SbxBase()
64 {
65 	pData = new SbxVarRefs;
66 	eType = t;
67 	if( t != SbxVARIANT )
68 		SetFlag( SBX_FIXED );
69 }
70 
SbxArray(const SbxArray & rArray)71 SbxArray::SbxArray( const SbxArray& rArray ) :
72     SvRefBase( rArray ), SbxBase()
73 {
74 	pData = new SbxVarRefs;
75 	if( rArray.eType != SbxVARIANT )
76 		SetFlag( SBX_FIXED );
77 	*this = rArray;
78 }
79 
operator =(const SbxArray & rArray)80 SbxArray& SbxArray::operator=( const SbxArray& rArray )
81 {
82 	if( &rArray != this )
83 	{
84 		eType = rArray.eType;
85 		Clear();
86 		SbxVarRefs* pSrc = rArray.pData;
87 		for( sal_uInt32 i = 0; i < pSrc->size(); i++ )
88 		{
89 			SbxVarEntryPtr pSrcRef = (*pSrc)[i];
90 			const SbxVariable* pSrc_ = *pSrcRef;
91 			if( !pSrc_ )
92 				continue;
93 			SbxVarEntryPtr pDstRef = new SbxVarEntry;
94 			*((SbxVariableRef*) pDstRef) = *((SbxVariableRef*) pSrcRef);
95 			if( pSrcRef->pAlias )
96 				pDstRef->pAlias = new XubString( *pSrcRef->pAlias );
97 			if( eType != SbxVARIANT )
98 				// Keine Objekte konvertieren
99 				if( eType != SbxOBJECT || pSrc_->GetClass() != SbxCLASS_OBJECT )
100 					((SbxVariable*) pSrc_)->Convert( eType );
101 			pData->push_back( pDstRef );
102 		}
103 	}
104 	return *this;
105 }
106 
~SbxArray()107 SbxArray::~SbxArray()
108 {
109     Clear();
110 	delete pData;
111 }
112 
GetType() const113 SbxDataType SbxArray::GetType() const
114 {
115 	return (SbxDataType) ( eType | SbxARRAY );
116 }
117 
GetClass() const118 SbxClassType SbxArray::GetClass() const
119 {
120 	return SbxCLASS_ARRAY;
121 }
122 
Clear()123 void SbxArray::Clear()
124 {
125     sal_uInt32 nSize = pData->size();
126 	for( sal_uInt32 i = 0 ; i < nSize ; i++ )
127     {
128         SbxVarEntry* pEntry = (*pData)[i];
129 		delete pEntry;
130     }
131 	pData->clear();
132 }
133 
Count32() const134 sal_uInt32 SbxArray::Count32() const
135 {
136     return pData->size();
137 }
138 
Count() const139 sal_uInt16 SbxArray::Count() const
140 {
141     sal_uInt32 nCount = pData->size();
142 	DBG_ASSERT( nCount <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" );
143 	return (sal_uInt16)nCount;
144 }
145 
GetRef32(sal_uInt32 nIdx)146 SbxVariableRef& SbxArray::GetRef32( sal_uInt32 nIdx )
147 {
148 	// Array ggf. vergroessern
149 	DBG_ASSERT( nIdx <= SBX_MAXINDEX32, "SBX: Array-Index > SBX_MAXINDEX32" );
150 	// Very Hot Fix
151 	if( nIdx > SBX_MAXINDEX32 )
152 	{
153 		SetError( SbxERR_BOUNDS );
154 		nIdx = 0;
155 	}
156 	while( pData->size() <= nIdx )
157 	{
158 		const SbxVarEntryPtr p = new SbxVarEntry;
159 		pData->push_back( p );
160 	}
161 	return *((*pData)[nIdx]);
162 }
163 
GetRef(sal_uInt16 nIdx)164 SbxVariableRef& SbxArray::GetRef( sal_uInt16 nIdx )
165 {
166 	// Array ggf. vergroessern
167 	DBG_ASSERT( nIdx <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" );
168 	// Very Hot Fix
169 	if( nIdx > SBX_MAXINDEX )
170 	{
171 		SetError( SbxERR_BOUNDS );
172 		nIdx = 0;
173 	}
174 	while( pData->size() <= nIdx )
175 	{
176 		const SbxVarEntryPtr p = new SbxVarEntry;
177 		pData->push_back( p );
178 	}
179 	return *((*pData)[nIdx]);
180 }
181 
Get32(sal_uInt32 nIdx)182 SbxVariable* SbxArray::Get32( sal_uInt32 nIdx )
183 {
184 	if( !CanRead() )
185 	{
186 		SetError( SbxERR_PROP_WRITEONLY );
187 		return NULL;
188 	}
189 	SbxVariableRef& rRef = GetRef32( nIdx );
190 
191 	if ( !rRef.Is() )
192 		rRef = new SbxVariable( eType );
193 #ifdef DBG_UTIL
194 	else
195 		DBG_CHKOBJ( rRef, SbxBase, 0 );
196 #endif
197 
198 	return rRef;
199 }
200 
Get(sal_uInt16 nIdx)201 SbxVariable* SbxArray::Get( sal_uInt16 nIdx )
202 {
203 	if( !CanRead() )
204 	{
205 		SetError( SbxERR_PROP_WRITEONLY );
206 		return NULL;
207 	}
208 	SbxVariableRef& rRef = GetRef( nIdx );
209 
210 	if ( !rRef.Is() )
211 		rRef = new SbxVariable( eType );
212 #ifdef DBG_UTIL
213 	else
214 		DBG_CHKOBJ( rRef, SbxBase, 0 );
215 #endif
216 
217 	return rRef;
218 }
219 
Put32(SbxVariable * pVar,sal_uInt32 nIdx)220 void SbxArray::Put32( SbxVariable* pVar, sal_uInt32 nIdx )
221 {
222 	if( !CanWrite() )
223 		SetError( SbxERR_PROP_READONLY );
224 	else
225 	{
226 		if( pVar )
227 			if( eType != SbxVARIANT )
228 				// Keine Objekte konvertieren
229 				if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT )
230 					pVar->Convert( eType );
231 		SbxVariableRef& rRef = GetRef32( nIdx );
232 		if( (SbxVariable*) rRef != pVar )
233 		{
234 			rRef = pVar;
235 			SetFlag( SBX_MODIFIED );
236 		}
237 	}
238 }
239 
Put(SbxVariable * pVar,sal_uInt16 nIdx)240 void SbxArray::Put( SbxVariable* pVar, sal_uInt16 nIdx )
241 {
242 	if( !CanWrite() )
243 		SetError( SbxERR_PROP_READONLY );
244 	else
245 	{
246 		if( pVar )
247 			if( eType != SbxVARIANT )
248 				// Keine Objekte konvertieren
249 				if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT )
250 					pVar->Convert( eType );
251 		SbxVariableRef& rRef = GetRef( nIdx );
252 		if( (SbxVariable*) rRef != pVar )
253 		{
254 			rRef = pVar;
255 			SetFlag( SBX_MODIFIED );
256 		}
257 	}
258 }
259 
GetAlias(sal_uInt16 nIdx)260 const XubString& SbxArray::GetAlias( sal_uInt16 nIdx )
261 {
262 	if( !CanRead() )
263 	{
264 		SetError( SbxERR_PROP_WRITEONLY );
265 		return String::EmptyString();
266 	}
267 	SbxVarEntry& rRef = (SbxVarEntry&) GetRef( nIdx );
268 
269 	if ( !rRef.pAlias )
270 		return String::EmptyString();
271 #ifdef DBG_UTIL
272 	else
273 		DBG_CHKOBJ( rRef, SbxBase, 0 );
274 #endif
275 
276 	return *rRef.pAlias;
277 }
278 
PutAlias(const XubString & rAlias,sal_uInt16 nIdx)279 void SbxArray::PutAlias( const XubString& rAlias, sal_uInt16 nIdx )
280 {
281 	if( !CanWrite() )
282 		SetError( SbxERR_PROP_READONLY );
283 	else
284 	{
285 		SbxVarEntry& rRef = (SbxVarEntry&) GetRef( nIdx );
286 		if( !rRef.pAlias )
287 			rRef.pAlias = new XubString( rAlias );
288 		else
289 			*rRef.pAlias = rAlias;
290 	}
291 }
292 
Insert32(SbxVariable * pVar,sal_uInt32 nIdx)293 void SbxArray::Insert32( SbxVariable* pVar, sal_uInt32 nIdx )
294 {
295 	DBG_ASSERT( pData->size() <= SBX_MAXINDEX32, "SBX: Array wird zu gross" );
296 	if( pData->size() > SBX_MAXINDEX32 )
297 			return;
298 	SbxVarEntryPtr p = new SbxVarEntry;
299 	*((SbxVariableRef*) p) = pVar;
300     SbxVarEntryPtrVector::size_type nSize = pData->size();
301 	if( nIdx > nSize )
302 		nIdx = nSize;
303 	if( eType != SbxVARIANT && pVar )
304 		(*p)->Convert( eType );
305 	if( nIdx == nSize )
306     {
307         pData->push_back( p );
308     }
309     else
310     {
311 	    pData->insert( pData->begin() + nIdx, p );
312     }
313 	SetFlag( SBX_MODIFIED );
314 }
315 
Insert(SbxVariable * pVar,sal_uInt16 nIdx)316 void SbxArray::Insert( SbxVariable* pVar, sal_uInt16 nIdx )
317 {
318 	DBG_ASSERT( pData->size() <= 0x3FF0, "SBX: Array wird zu gross" );
319 	if( pData->size() > 0x3FF0 )
320 			return;
321     Insert32( pVar, nIdx );
322 }
323 
Remove32(sal_uInt32 nIdx)324 void SbxArray::Remove32( sal_uInt32 nIdx )
325 {
326 	if( nIdx < pData->size() )
327 	{
328 		SbxVariableRef* pRef = (*pData)[nIdx];
329 	    pData->erase( pData->begin() + nIdx );
330 		delete pRef;
331 		SetFlag( SBX_MODIFIED );
332 	}
333 }
334 
Remove(sal_uInt16 nIdx)335 void SbxArray::Remove( sal_uInt16 nIdx )
336 {
337 	if( nIdx < pData->size() )
338 	{
339 		SbxVariableRef* pRef = (*pData)[nIdx];
340 	    pData->erase( pData->begin() + nIdx );
341 		delete pRef;
342 		SetFlag( SBX_MODIFIED );
343 	}
344 }
345 
Remove(SbxVariable * pVar)346 void SbxArray::Remove( SbxVariable* pVar )
347 {
348 	if( pVar )
349 	{
350 		for( sal_uInt32 i = 0; i < pData->size(); i++ )
351 		{
352 			SbxVariableRef* pRef = (*pData)[i];
353 			// SbxVariableRef* pRef = pData->GetObject( i );
354 			if( *pRef == pVar )
355 			{
356 				Remove32( i ); break;
357 			}
358 		}
359 	}
360 }
361 
362 // Uebernahme der Daten aus dem uebergebenen Array, wobei
363 // gleichnamige Variable ueberschrieben werden.
364 
Merge(SbxArray * p)365 void SbxArray::Merge( SbxArray* p )
366 {
367 	if( p )
368 	{
369 		sal_uInt32 nSize = p->Count();
370 		for( sal_uInt32 i = 0; i < nSize; i++ )
371 		{
372 			SbxVarEntryPtr pRef1 = (*(p->pData))[i];
373 			// Ist das Element by name schon drin?
374 			// Dann ueberschreiben!
375 			SbxVariable* pVar = *pRef1;
376 			if( pVar )
377 			{
378 				XubString aName = pVar->GetName();
379 				sal_uInt16 nHash = pVar->GetHashCode();
380 				for( sal_uInt32 j = 0; j < pData->size(); j++ )
381 				{
382 					SbxVariableRef* pRef2 = (*pData)[j];
383 					if( (*pRef2)->GetHashCode() == nHash
384 					 && (*pRef2)->GetName().EqualsIgnoreCaseAscii( aName ) )
385 					{
386 						*pRef2 = pVar; pRef1 = NULL;
387 						break;
388 					}
389 				}
390 				if( pRef1 )
391 				{
392 					SbxVarEntryPtr pRef = new SbxVarEntry;
393 					const SbxVarEntryPtr pTemp = pRef;
394 					pData->push_back( pTemp );
395 					*((SbxVariableRef*) pRef) = *((SbxVariableRef*) pRef1);
396 					if( pRef1->pAlias )
397 						pRef->pAlias = new XubString( *pRef1->pAlias );
398 				}
399 			}
400 		}
401 	}
402 }
403 
404 // Suchen eines Elements ueber die Userdaten. Falls ein Element
405 // ein Objekt ist, wird dieses ebenfalls durchsucht.
406 
FindUserData(sal_uInt32 nData)407 SbxVariable* SbxArray::FindUserData( sal_uInt32 nData )
408 {
409 	SbxVariable* p = NULL;
410 	for( sal_uInt32 i = 0; i < pData->size(); i++ )
411 	{
412 		SbxVariableRef* pRef = (*pData)[i];
413 		SbxVariable* pVar = *pRef;
414 		if( pVar )
415 		{
416 			if( pVar->IsVisible() && pVar->GetUserData() == nData )
417 			{
418 				p = pVar;
419 				p->ResetFlag( SBX_EXTFOUND );
420 				break;	// JSM 06.10.95
421 			}
422 			// Haben wir ein Array/Objekt mit Extended Search?
423 			else if( pVar->IsSet( SBX_EXTSEARCH ) )
424 			{
425 				switch( pVar->GetClass() )
426 				{
427 					case SbxCLASS_OBJECT:
428 					{
429 						// Objekte duerfen ihren Parent nicht durchsuchen
430 						sal_uInt16 nOld = pVar->GetFlags();
431 						pVar->ResetFlag( SBX_GBLSEARCH );
432 						p = ((SbxObject*) pVar)->FindUserData( nData );
433 						pVar->SetFlags( nOld );
434 						break;
435 					}
436 					case SbxCLASS_ARRAY:
437 						p = ((SbxArray*) pVar)->FindUserData( nData );
438 						break;
439 					default: break;
440 				}
441 				if( p )
442 				{
443 					p->SetFlag( SBX_EXTFOUND );
444 					break;
445 				}
446 			}
447 		}
448 	}
449 	return p;
450 }
451 
452 // Suchen eines Elements ueber den Namen und den Typ. Falls ein Element
453 // ein Objekt ist, wird dieses ebenfalls durchsucht.
454 
Find(const XubString & rName,SbxClassType t)455 SbxVariable* SbxArray::Find( const XubString& rName, SbxClassType t )
456 {
457 	SbxVariable* p = NULL;
458 	sal_uInt32 nCount = pData->size();
459 	if( !nCount )
460 		return NULL;
461 	sal_Bool bExtSearch = IsSet( SBX_EXTSEARCH );
462 	sal_uInt16 nHash = SbxVariable::MakeHashCode( rName );
463 	for( sal_uInt32 i = 0; i < nCount; i++ )
464 	{
465 		SbxVariableRef* pRef = (*pData)[i];
466 		SbxVariable* pVar = *pRef;
467 		if( pVar && pVar->IsVisible() )
468 		{
469 			// Die ganz sichere Suche klappt auch, wenn es
470 			// keinen Hascode gibt!
471 			sal_uInt16 nVarHash = pVar->GetHashCode();
472 			if( ( !nVarHash || nVarHash == nHash )
473 				&& ( t == SbxCLASS_DONTCARE || pVar->GetClass() == t )
474 				&& ( pVar->GetName().EqualsIgnoreCaseAscii( rName ) ) )
475 			{
476 				p = pVar;
477 				p->ResetFlag( SBX_EXTFOUND );
478 				break;
479 			}
480 			// Haben wir ein Array/Objekt mit Extended Search?
481 			else if( bExtSearch && pVar->IsSet( SBX_EXTSEARCH ) )
482 			{
483 				switch( pVar->GetClass() )
484 				{
485 					case SbxCLASS_OBJECT:
486 					{
487 						// Objekte duerfen ihren Parent nicht durchsuchen
488 						sal_uInt16 nOld = pVar->GetFlags();
489 						pVar->ResetFlag( SBX_GBLSEARCH );
490 						p = ((SbxObject*) pVar)->Find( rName, t );
491 						pVar->SetFlags( nOld );
492 						break;
493 					}
494 					case SbxCLASS_ARRAY:
495 						p = ((SbxArray*) pVar)->Find( rName, t );
496 						break;
497 					default: break;
498 				}
499 				if( p )
500 				{
501 					p->SetFlag( SBX_EXTFOUND );
502 					break;
503 				}
504 			}
505 		}
506 	}
507 	return p;
508 }
509 
LoadData(SvStream & rStrm,sal_uInt16 nVer)510 sal_Bool SbxArray::LoadData( SvStream& rStrm, sal_uInt16 nVer )
511 {
512 	sal_uInt16 nElem;
513 	Clear();
514 	sal_Bool bRes = sal_True;
515 	sal_uInt16 f = nFlags;
516 	nFlags |= SBX_WRITE;
517 	rStrm >> nElem;
518 	nElem &= 0x7FFF;
519 	for( sal_uInt32 n = 0; n < nElem; n++ )
520 	{
521 		sal_uInt16 nIdx;
522 		rStrm >> nIdx;
523 		SbxVariable* pVar = (SbxVariable*) Load( rStrm );
524 		if( pVar )
525 		{
526 			SbxVariableRef& rRef = GetRef( nIdx );
527 			rRef = pVar;
528 		}
529 		else
530 		{
531 			bRes = sal_False; break;
532 		}
533 	}
534 	if( bRes )
535 		bRes = LoadPrivateData( rStrm, nVer );
536 	nFlags = f;
537 	return bRes;
538 }
539 
StoreData(SvStream & rStrm) const540 sal_Bool SbxArray::StoreData( SvStream& rStrm ) const
541 {
542 	sal_uInt32 nElem = 0;
543 	sal_uInt32 n;
544 	// Welche Elemente sind ueberhaupt definiert?
545 	for( n = 0; n < pData->size(); n++ )
546 	{
547 		SbxVariableRef* pRef = (*pData)[n];
548 		SbxVariable* p = *pRef;
549 		if( p && !( p->GetFlags() & SBX_DONTSTORE ) )
550 			nElem++;
551 	}
552 	rStrm << (sal_uInt16) nElem;
553 	for( n = 0; n < pData->size(); n++ )
554 	{
555 		SbxVariableRef* pRef = (*pData)[n];
556 		SbxVariable* p = *pRef;
557 		if( p && !( p->GetFlags() & SBX_DONTSTORE ) )
558 		{
559 			rStrm << (sal_uInt16) n;
560 			if( !p->Store( rStrm ) )
561 				return sal_False;
562 		}
563 	}
564 	return StorePrivateData( rStrm );
565 }
566 
567 // #100883 Method to set method directly to parameter array
PutDirect(SbxVariable * pVar,sal_uInt32 nIdx)568 void SbxArray::PutDirect( SbxVariable* pVar, sal_uInt32 nIdx )
569 {
570 	SbxVariableRef& rRef = GetRef32( nIdx );
571 	rRef = pVar;
572 }
573 
574 
575 //////////////////////////////////////////////////////////////////////////
576 //
577 //  SbxArray
578 //
579 //////////////////////////////////////////////////////////////////////////
580 
SbxDimArray(SbxDataType t)581 SbxDimArray::SbxDimArray( SbxDataType t ) : SbxArray( t ), mbHasFixedSize( false )
582 {
583 	pFirst = pLast = NULL;
584 	nDim = 0;
585 }
586 
SbxDimArray(const SbxDimArray & rArray)587 SbxDimArray::SbxDimArray( const SbxDimArray& rArray )
588     : SvRefBase( rArray ), SbxArray( rArray.eType )
589 {
590 	pFirst = pLast = NULL;
591 	nDim = 0;
592 	*this = rArray;
593 }
594 
operator =(const SbxDimArray & rArray)595 SbxDimArray& SbxDimArray::operator=( const SbxDimArray& rArray )
596 {
597 	if( &rArray != this )
598 	{
599 		SbxArray::operator=( (const SbxArray&) rArray );
600 		SbxDim* p = rArray.pFirst;
601 		while( p )
602 		{
603 			AddDim32( p->nLbound, p->nUbound );
604 			p = p->pNext;
605 		}
606 		this->mbHasFixedSize = rArray.mbHasFixedSize;
607 	}
608 	return *this;
609 }
610 
~SbxDimArray()611 SbxDimArray::~SbxDimArray()
612 {
613 	Clear();
614 }
615 
Clear()616 void SbxDimArray::Clear()
617 {
618 	SbxDim* p = pFirst;
619 	while( p )
620 	{
621 		SbxDim* q = p->pNext;
622 		delete p;
623 		p = q;
624 	}
625 	pFirst = pLast = NULL;
626 	nDim   = 0;
627 }
628 
629 // Dimension hinzufuegen
630 
AddDimImpl32(sal_Int32 lb,sal_Int32 ub,sal_Bool bAllowSize0)631 void SbxDimArray::AddDimImpl32( sal_Int32 lb, sal_Int32 ub, sal_Bool bAllowSize0 )
632 {
633 	SbxError eRes = SbxERR_OK;
634 	if( ub < lb && !bAllowSize0 )
635 	{
636 		eRes = SbxERR_BOUNDS;
637 		ub = lb;
638 	}
639 	SbxDim* p = new SbxDim;
640 	p->nLbound = lb;
641 	p->nUbound = ub;
642 	p->nSize   = ub - lb + 1;
643 	p->pNext   = NULL;
644 	if( !pFirst )
645 		pFirst = pLast = p;
646 	else
647 		pLast->pNext = p, pLast = p;
648 	nDim++;
649 	if( eRes )
650 		SetError( eRes );
651 }
652 
AddDim(short lb,short ub)653 void SbxDimArray::AddDim( short lb, short ub )
654 {
655 	AddDimImpl32( lb, ub, sal_False );
656 }
657 
unoAddDim(short lb,short ub)658 void SbxDimArray::unoAddDim( short lb, short ub )
659 {
660 	AddDimImpl32( lb, ub, sal_True );
661 }
662 
AddDim32(sal_Int32 lb,sal_Int32 ub)663 void SbxDimArray::AddDim32( sal_Int32 lb, sal_Int32 ub )
664 {
665 	AddDimImpl32( lb, ub, sal_False );
666 }
667 
unoAddDim32(sal_Int32 lb,sal_Int32 ub)668 void SbxDimArray::unoAddDim32( sal_Int32 lb, sal_Int32 ub )
669 {
670 	AddDimImpl32( lb, ub, sal_True );
671 }
672 
673 
674 // Dimensionsdaten auslesen
675 
GetDim32(sal_Int32 n,sal_Int32 & rlb,sal_Int32 & rub) const676 sal_Bool SbxDimArray::GetDim32( sal_Int32 n, sal_Int32& rlb, sal_Int32& rub ) const
677 {
678 	if( n < 1 || n > nDim )
679 	{
680 		SetError( SbxERR_BOUNDS ); rub = rlb = 0; return sal_False;
681 	}
682 	SbxDim* p = pFirst;
683 	while( --n )
684 		p = p->pNext;
685 	rub = p->nUbound;
686 	rlb = p->nLbound;
687 	return sal_True;
688 }
689 
GetDim(short n,short & rlb,short & rub) const690 sal_Bool SbxDimArray::GetDim( short n, short& rlb, short& rub ) const
691 {
692     sal_Int32 rlb32, rub32;
693     sal_Bool bRet = GetDim32( n, rlb32, rub32 );
694     if( bRet )
695     {
696 	    if( rlb32 < -SBX_MAXINDEX || rub32 > SBX_MAXINDEX )
697 	    {
698 		    SetError( SbxERR_BOUNDS );
699             return sal_False;
700         }
701 	    rub = (short)rub32;
702 	    rlb = (short)rlb32;
703     }
704 	return bRet;
705 }
706 
707 // Element-Ptr anhand einer Index-Liste
708 
Offset32(const sal_Int32 * pIdx)709 sal_uInt32 SbxDimArray::Offset32( const sal_Int32* pIdx )
710 {
711 	sal_uInt32 nPos = 0;
712 	for( SbxDim* p = pFirst; p; p = p->pNext )
713 	{
714 		sal_Int32 nIdx = *pIdx++;
715 		if( nIdx < p->nLbound || nIdx > p->nUbound )
716 		{
717 			nPos = (sal_uInt32)SBX_MAXINDEX32 + 1; break;
718 		}
719 		nPos = nPos * p->nSize + nIdx - p->nLbound;
720 	}
721 	if( nDim == 0 || nPos > SBX_MAXINDEX32 )
722 	{
723 		SetError( SbxERR_BOUNDS ); nPos = 0;
724 	}
725 	return nPos;
726 }
727 
Offset(const short * pIdx)728 sal_uInt16 SbxDimArray::Offset( const short* pIdx )
729 {
730 	long nPos = 0;
731 	for( SbxDim* p = pFirst; p; p = p->pNext )
732 	{
733 		short nIdx = *pIdx++;
734 		if( nIdx < p->nLbound || nIdx > p->nUbound )
735 		{
736 			nPos = SBX_MAXINDEX + 1; break;
737 		}
738 		nPos = nPos * p->nSize + nIdx - p->nLbound;
739 	}
740 	if( nDim == 0 || nPos > SBX_MAXINDEX )
741 	{
742 		SetError( SbxERR_BOUNDS ); nPos = 0;
743 	}
744 	return (sal_uInt16) nPos;
745 }
746 
GetRef(const short * pIdx)747 SbxVariableRef& SbxDimArray::GetRef( const short* pIdx )
748 {
749 	return SbxArray::GetRef( Offset( pIdx ) );
750 }
751 
Get(const short * pIdx)752 SbxVariable* SbxDimArray::Get( const short* pIdx )
753 {
754 	return SbxArray::Get( Offset( pIdx ) );
755 }
756 
Put(SbxVariable * p,const short * pIdx)757 void SbxDimArray::Put( SbxVariable* p, const short* pIdx  )
758 {
759 	SbxArray::Put( p, Offset( pIdx ) );
760 }
761 
GetRef32(const sal_Int32 * pIdx)762 SbxVariableRef& SbxDimArray::GetRef32( const sal_Int32* pIdx )
763 {
764 	return SbxArray::GetRef32( Offset32( pIdx ) );
765 }
766 
Get32(const sal_Int32 * pIdx)767 SbxVariable* SbxDimArray::Get32( const sal_Int32* pIdx )
768 {
769 	return SbxArray::Get32( Offset32( pIdx ) );
770 }
771 
Put32(SbxVariable * p,const sal_Int32 * pIdx)772 void SbxDimArray::Put32( SbxVariable* p, const sal_Int32* pIdx  )
773 {
774 	SbxArray::Put32( p, Offset32( pIdx ) );
775 }
776 
777 
778 // Element-Nr anhand eines Parameter-Arrays
779 
Offset32(SbxArray * pPar)780 sal_uInt32 SbxDimArray::Offset32( SbxArray* pPar )
781 {
782 	if( nDim == 0 || !pPar || ( ( nDim != ( pPar->Count() - 1 ) ) && SbiRuntime::isVBAEnabled() ) )
783 	{
784 		SetError( SbxERR_BOUNDS ); return 0;
785 	}
786 	sal_uInt32 nPos = 0;
787 	sal_uInt16 nOff = 1;	// Nicht Element 0!
788 	for( SbxDim* p = pFirst; p && !IsError(); p = p->pNext )
789 	{
790 		sal_Int32 nIdx = pPar->Get( nOff++ )->GetLong();
791 		if( nIdx < p->nLbound || nIdx > p->nUbound )
792 		{
793 			nPos = (sal_uInt32) SBX_MAXINDEX32+1; break;
794 		}
795 		nPos = nPos * p->nSize + nIdx - p->nLbound;
796 	}
797 	if( nPos > (sal_uInt32) SBX_MAXINDEX32 )
798 	{
799 		SetError( SbxERR_BOUNDS ); nPos = 0;
800 	}
801 	return nPos;
802 }
803 
Offset(SbxArray * pPar)804 sal_uInt16 SbxDimArray::Offset( SbxArray* pPar )
805 {
806     sal_uInt32 nPos = Offset32( pPar );
807 	if( nPos > (long) SBX_MAXINDEX )
808 	{
809 		SetError( SbxERR_BOUNDS ); nPos = 0;
810 	}
811 	return (sal_uInt16) nPos;
812 }
813 
GetRef(SbxArray * pPar)814 SbxVariableRef& SbxDimArray::GetRef( SbxArray* pPar )
815 {
816 	return SbxArray::GetRef32( Offset32( pPar ) );
817 }
818 
Get(SbxArray * pPar)819 SbxVariable* SbxDimArray::Get( SbxArray* pPar )
820 {
821 	return SbxArray::Get32( Offset32( pPar ) );
822 }
823 
Put(SbxVariable * p,SbxArray * pPar)824 void SbxDimArray::Put( SbxVariable* p, SbxArray* pPar  )
825 {
826 	SbxArray::Put32( p, Offset32( pPar ) );
827 }
828 
LoadData(SvStream & rStrm,sal_uInt16 nVer)829 sal_Bool SbxDimArray::LoadData( SvStream& rStrm, sal_uInt16 nVer )
830 {
831 	short nDimension;
832 	rStrm >> nDimension;
833 	for( short i = 0; i < nDimension && rStrm.GetError() == SVSTREAM_OK; i++ )
834 	{
835 		sal_Int16 lb, ub;
836 		rStrm >> lb >> ub;
837 		AddDim( lb, ub );
838 	}
839 	return SbxArray::LoadData( rStrm, nVer );
840 }
841 
StoreData(SvStream & rStrm) const842 sal_Bool SbxDimArray::StoreData( SvStream& rStrm ) const
843 {
844 	rStrm << (sal_Int16) nDim;
845 	for( short i = 0; i < nDim; i++ )
846 	{
847 		short lb, ub;
848 		GetDim( i, lb, ub );
849 		rStrm << (sal_Int16) lb << (sal_Int16) ub;
850 	}
851 	return SbxArray::StoreData( rStrm );
852 }
853 
854