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