xref: /trunk/main/basic/source/sbx/sbxarray.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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