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