Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <tools/stream.hxx>
21 : #include <basic/sbx.hxx>
22 : #include "runtime.hxx"
23 : #include <vector>
24 : using namespace std;
25 :
26 : struct SbxDim { // an array-dimension:
27 : SbxDim* pNext; // Link
28 : sal_Int32 nLbound, nUbound; // Limitations
29 : sal_Int32 nSize; // Number of elements
30 : };
31 :
32 : class SbxVarEntry : public SbxVariableRef {
33 : public:
34 : OUString* pAlias;
35 0 : SbxVarEntry() : SbxVariableRef(), pAlias( NULL ) {}
36 0 : ~SbxVarEntry() { delete pAlias; }
37 : };
38 :
39 : typedef SbxVarEntry* SbxVarEntryPtr;
40 : typedef vector< SbxVarEntryPtr > SbxVarEntryPtrVector;
41 0 : class SbxVarRefs : public SbxVarEntryPtrVector
42 : {
43 : public:
44 0 : SbxVarRefs( void ) {}
45 : };
46 :
47 :
48 0 : TYPEINIT1(SbxArray,SbxBase)
49 0 : TYPEINIT1(SbxDimArray,SbxArray)
50 :
51 : // SbxArray
52 :
53 0 : SbxArray::SbxArray( SbxDataType t ) : SbxBase()
54 : {
55 0 : pData = new SbxVarRefs;
56 0 : eType = t;
57 0 : if( t != SbxVARIANT )
58 0 : SetFlag( SBX_FIXED );
59 0 : }
60 :
61 0 : SbxArray::SbxArray( const SbxArray& rArray ) :
62 0 : SvRefBase( rArray ), SbxBase()
63 : {
64 0 : pData = new SbxVarRefs;
65 0 : if( rArray.eType != SbxVARIANT )
66 0 : SetFlag( SBX_FIXED );
67 0 : *this = rArray;
68 0 : }
69 :
70 0 : SbxArray& SbxArray::operator=( const SbxArray& rArray )
71 : {
72 0 : if( &rArray != this )
73 : {
74 0 : eType = rArray.eType;
75 0 : Clear();
76 0 : SbxVarRefs* pSrc = rArray.pData;
77 0 : for( sal_uInt32 i = 0; i < pSrc->size(); i++ )
78 : {
79 0 : SbxVarEntryPtr pSrcRef = (*pSrc)[i];
80 0 : const SbxVariable* pSrc_ = *pSrcRef;
81 0 : if( !pSrc_ )
82 0 : continue;
83 0 : SbxVarEntryPtr pDstRef = new SbxVarEntry;
84 0 : *((SbxVariableRef*) pDstRef) = *((SbxVariableRef*) pSrcRef);
85 0 : if( pSrcRef->pAlias )
86 : {
87 0 : pDstRef->pAlias = new OUString( *pSrcRef->pAlias );
88 : }
89 0 : if( eType != SbxVARIANT )
90 : {
91 : // Convert no objects
92 0 : if( eType != SbxOBJECT || pSrc_->GetClass() != SbxCLASS_OBJECT )
93 : {
94 0 : ((SbxVariable*) pSrc_)->Convert( eType );
95 : }
96 : }
97 0 : pData->push_back( pDstRef );
98 : }
99 : }
100 0 : return *this;
101 : }
102 :
103 0 : SbxArray::~SbxArray()
104 : {
105 0 : Clear();
106 0 : delete pData;
107 0 : }
108 :
109 0 : SbxDataType SbxArray::GetType() const
110 : {
111 0 : return (SbxDataType) ( eType | SbxARRAY );
112 : }
113 :
114 0 : SbxClassType SbxArray::GetClass() const
115 : {
116 0 : return SbxCLASS_ARRAY;
117 : }
118 :
119 0 : void SbxArray::Clear()
120 : {
121 0 : sal_uInt32 nSize = pData->size();
122 0 : for( sal_uInt32 i = 0 ; i < nSize ; i++ )
123 : {
124 0 : SbxVarEntry* pEntry = (*pData)[i];
125 0 : delete pEntry;
126 : }
127 0 : pData->clear();
128 0 : }
129 :
130 0 : sal_uInt32 SbxArray::Count32() const
131 : {
132 0 : return pData->size();
133 : }
134 :
135 0 : sal_uInt16 SbxArray::Count() const
136 : {
137 0 : sal_uInt32 nCount = pData->size();
138 : DBG_ASSERT( nCount <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" );
139 0 : return (sal_uInt16)nCount;
140 : }
141 :
142 0 : SbxVariableRef& SbxArray::GetRef32( sal_uInt32 nIdx )
143 : {
144 : // If necessary extend the array
145 : DBG_ASSERT( nIdx <= SBX_MAXINDEX32, "SBX: Array-Index > SBX_MAXINDEX32" );
146 : // Very Hot Fix
147 0 : if( nIdx > SBX_MAXINDEX32 )
148 : {
149 0 : SetError( SbxERR_BOUNDS );
150 0 : nIdx = 0;
151 : }
152 0 : while( pData->size() <= nIdx )
153 : {
154 0 : const SbxVarEntryPtr p = new SbxVarEntry;
155 0 : pData->push_back( p );
156 : }
157 0 : return *((*pData)[nIdx]);
158 : }
159 :
160 0 : SbxVariableRef& SbxArray::GetRef( sal_uInt16 nIdx )
161 : {
162 : // If necessary extend the array
163 : DBG_ASSERT( nIdx <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" );
164 : // Very Hot Fix
165 0 : if( nIdx > SBX_MAXINDEX )
166 : {
167 0 : SetError( SbxERR_BOUNDS );
168 0 : nIdx = 0;
169 : }
170 0 : while( pData->size() <= nIdx )
171 : {
172 0 : const SbxVarEntryPtr p = new SbxVarEntry;
173 0 : pData->push_back( p );
174 : }
175 0 : return *((*pData)[nIdx]);
176 : }
177 :
178 0 : SbxVariable* SbxArray::Get32( sal_uInt32 nIdx )
179 : {
180 0 : if( !CanRead() )
181 : {
182 0 : SetError( SbxERR_PROP_WRITEONLY );
183 0 : return NULL;
184 : }
185 0 : SbxVariableRef& rRef = GetRef32( nIdx );
186 :
187 0 : if ( !rRef.Is() )
188 0 : rRef = new SbxVariable( eType );
189 :
190 0 : return rRef;
191 : }
192 :
193 0 : SbxVariable* SbxArray::Get( sal_uInt16 nIdx )
194 : {
195 0 : if( !CanRead() )
196 : {
197 0 : SetError( SbxERR_PROP_WRITEONLY );
198 0 : return NULL;
199 : }
200 0 : SbxVariableRef& rRef = GetRef( nIdx );
201 :
202 0 : if ( !rRef.Is() )
203 0 : rRef = new SbxVariable( eType );
204 :
205 0 : return rRef;
206 : }
207 :
208 0 : void SbxArray::Put32( SbxVariable* pVar, sal_uInt32 nIdx )
209 : {
210 0 : if( !CanWrite() )
211 0 : SetError( SbxERR_PROP_READONLY );
212 : else
213 : {
214 0 : if( pVar )
215 0 : if( eType != SbxVARIANT )
216 : // Convert no objects
217 0 : if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT )
218 0 : pVar->Convert( eType );
219 0 : SbxVariableRef& rRef = GetRef32( nIdx );
220 0 : if( (SbxVariable*) rRef != pVar )
221 : {
222 0 : rRef = pVar;
223 0 : SetFlag( SBX_MODIFIED );
224 : }
225 : }
226 0 : }
227 :
228 0 : void SbxArray::Put( SbxVariable* pVar, sal_uInt16 nIdx )
229 : {
230 0 : if( !CanWrite() )
231 0 : SetError( SbxERR_PROP_READONLY );
232 : else
233 : {
234 0 : if( pVar )
235 0 : if( eType != SbxVARIANT )
236 : // Convert no objects
237 0 : if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT )
238 0 : pVar->Convert( eType );
239 0 : SbxVariableRef& rRef = GetRef( nIdx );
240 0 : if( (SbxVariable*) rRef != pVar )
241 : {
242 0 : rRef = pVar;
243 0 : SetFlag( SBX_MODIFIED );
244 : }
245 : }
246 0 : }
247 :
248 0 : const OUString& SbxArray::GetAlias( sal_uInt16 nIdx )
249 : {
250 0 : static const OUString sEmpty("");
251 :
252 0 : if( !CanRead() )
253 : {
254 0 : SetError( SbxERR_PROP_WRITEONLY );
255 0 : return sEmpty;
256 : }
257 0 : SbxVarEntry& rRef = (SbxVarEntry&) GetRef( nIdx );
258 :
259 0 : if ( !rRef.pAlias )
260 : {
261 0 : return sEmpty;
262 : }
263 :
264 0 : return *rRef.pAlias;
265 : }
266 :
267 0 : void SbxArray::PutAlias( const OUString& rAlias, sal_uInt16 nIdx )
268 : {
269 0 : if( !CanWrite() )
270 : {
271 0 : SetError( SbxERR_PROP_READONLY );
272 : }
273 : else
274 : {
275 0 : SbxVarEntry& rRef = (SbxVarEntry&) GetRef( nIdx );
276 0 : if( !rRef.pAlias )
277 : {
278 0 : rRef.pAlias = new OUString( rAlias );
279 : }
280 : else
281 : {
282 0 : *rRef.pAlias = rAlias;
283 : }
284 : }
285 0 : }
286 :
287 0 : void SbxArray::Insert32( SbxVariable* pVar, sal_uInt32 nIdx )
288 : {
289 : DBG_ASSERT( pData->size() <= SBX_MAXINDEX32, "SBX: Array gets too big" );
290 0 : if( pData->size() > SBX_MAXINDEX32 )
291 : {
292 0 : return;
293 : }
294 0 : SbxVarEntryPtr p = new SbxVarEntry;
295 0 : *((SbxVariableRef*) p) = pVar;
296 0 : SbxVarEntryPtrVector::size_type nSize = pData->size();
297 0 : if( nIdx > nSize )
298 : {
299 0 : nIdx = nSize;
300 : }
301 0 : if( eType != SbxVARIANT && pVar )
302 : {
303 0 : (*p)->Convert( eType );
304 : }
305 0 : if( nIdx == nSize )
306 : {
307 0 : pData->push_back( p );
308 : }
309 : else
310 : {
311 0 : pData->insert( pData->begin() + nIdx, p );
312 : }
313 0 : SetFlag( SBX_MODIFIED );
314 : }
315 :
316 0 : void SbxArray::Insert( SbxVariable* pVar, sal_uInt16 nIdx )
317 : {
318 : DBG_ASSERT( pData->size() <= 0x3FF0, "SBX: Array gets too big" );
319 0 : if( pData->size() > 0x3FF0 )
320 : {
321 0 : return;
322 : }
323 0 : Insert32( pVar, nIdx );
324 : }
325 :
326 0 : void SbxArray::Remove32( sal_uInt32 nIdx )
327 : {
328 0 : if( nIdx < pData->size() )
329 : {
330 0 : SbxVariableRef* pRef = (*pData)[nIdx];
331 0 : pData->erase( pData->begin() + nIdx );
332 0 : delete pRef;
333 0 : SetFlag( SBX_MODIFIED );
334 : }
335 0 : }
336 :
337 0 : void SbxArray::Remove( sal_uInt16 nIdx )
338 : {
339 0 : if( nIdx < pData->size() )
340 : {
341 0 : SbxVariableRef* pRef = (*pData)[nIdx];
342 0 : pData->erase( pData->begin() + nIdx );
343 0 : delete pRef;
344 0 : SetFlag( SBX_MODIFIED );
345 : }
346 0 : }
347 :
348 0 : void SbxArray::Remove( SbxVariable* pVar )
349 : {
350 0 : if( pVar )
351 : {
352 0 : for( sal_uInt32 i = 0; i < pData->size(); i++ )
353 : {
354 0 : SbxVariableRef* pRef = (*pData)[i];
355 0 : if( *pRef == pVar )
356 : {
357 0 : Remove32( i ); break;
358 : }
359 : }
360 : }
361 0 : }
362 :
363 : // Taking over of the data from the passed array, at which
364 : // the variable of the same name will be overwritten.
365 :
366 0 : void SbxArray::Merge( SbxArray* p )
367 : {
368 0 : if( p )
369 : {
370 0 : sal_uInt32 nSize = p->Count();
371 0 : for( sal_uInt32 i = 0; i < nSize; i++ )
372 : {
373 0 : SbxVarEntryPtr pRef1 = (*(p->pData))[i];
374 : // Is the element by name already inside?
375 : // Then overwrite!
376 0 : SbxVariable* pVar = *pRef1;
377 0 : if( pVar )
378 : {
379 0 : OUString aName = pVar->GetName();
380 0 : sal_uInt16 nHash = pVar->GetHashCode();
381 0 : for( sal_uInt32 j = 0; j < pData->size(); j++ )
382 : {
383 0 : SbxVariableRef* pRef2 = (*pData)[j];
384 0 : if( (*pRef2)->GetHashCode() == nHash
385 0 : && (*pRef2)->GetName().equalsIgnoreAsciiCase( aName ) )
386 : {
387 0 : *pRef2 = pVar; pRef1 = NULL;
388 0 : break;
389 : }
390 : }
391 0 : if( pRef1 )
392 : {
393 0 : SbxVarEntryPtr pRef = new SbxVarEntry;
394 0 : const SbxVarEntryPtr pTemp = pRef;
395 0 : pData->push_back( pTemp );
396 0 : *((SbxVariableRef*) pRef) = *((SbxVariableRef*) pRef1);
397 0 : if( pRef1->pAlias )
398 : {
399 0 : pRef->pAlias = new OUString( *pRef1->pAlias );
400 : }
401 0 : }
402 : }
403 : }
404 : }
405 0 : }
406 :
407 : // Search of an element via the user data. If the element is
408 : // object, it will also be scanned.
409 :
410 0 : SbxVariable* SbxArray::FindUserData( sal_uInt32 nData )
411 : {
412 0 : SbxVariable* p = NULL;
413 0 : for( sal_uInt32 i = 0; i < pData->size(); i++ )
414 : {
415 0 : SbxVariableRef* pRef = (*pData)[i];
416 0 : SbxVariable* pVar = *pRef;
417 0 : if( pVar )
418 : {
419 0 : if( pVar->IsVisible() && pVar->GetUserData() == nData )
420 : {
421 0 : p = pVar;
422 0 : p->ResetFlag( SBX_EXTFOUND );
423 0 : break; // JSM 1995-10-06
424 : }
425 : // Did we have an array/object with extended search?
426 0 : else if( pVar->IsSet( SBX_EXTSEARCH ) )
427 : {
428 0 : switch( pVar->GetClass() )
429 : {
430 : case SbxCLASS_OBJECT:
431 : {
432 : // Objects are not allowed to scan their parent.
433 0 : sal_uInt16 nOld = pVar->GetFlags();
434 0 : pVar->ResetFlag( SBX_GBLSEARCH );
435 0 : p = ((SbxObject*) pVar)->FindUserData( nData );
436 0 : pVar->SetFlags( nOld );
437 0 : break;
438 : }
439 : case SbxCLASS_ARRAY:
440 0 : p = ((SbxArray*) pVar)->FindUserData( nData );
441 0 : break;
442 0 : default: break;
443 : }
444 0 : if( p )
445 : {
446 0 : p->SetFlag( SBX_EXTFOUND );
447 0 : break;
448 : }
449 : }
450 : }
451 : }
452 0 : return p;
453 : }
454 :
455 : // Search of an element by his name and type. If an element is an object,
456 : // it will also be scanned..
457 :
458 0 : SbxVariable* SbxArray::Find( const OUString& rName, SbxClassType t )
459 : {
460 0 : SbxVariable* p = NULL;
461 0 : sal_uInt32 nCount = pData->size();
462 0 : if( !nCount )
463 0 : return NULL;
464 0 : bool bExtSearch = IsSet( SBX_EXTSEARCH );
465 0 : sal_uInt16 nHash = SbxVariable::MakeHashCode( rName );
466 0 : for( sal_uInt32 i = 0; i < nCount; i++ )
467 : {
468 0 : SbxVariableRef* pRef = (*pData)[i];
469 0 : SbxVariable* pVar = *pRef;
470 0 : if( pVar && pVar->IsVisible() )
471 : {
472 : // The very secure search works as well, if there is no hashcode!
473 0 : sal_uInt16 nVarHash = pVar->GetHashCode();
474 0 : if( ( !nVarHash || nVarHash == nHash )
475 0 : && ( t == SbxCLASS_DONTCARE || pVar->GetClass() == t )
476 0 : && ( pVar->GetName().equalsIgnoreAsciiCase( rName ) ) )
477 : {
478 0 : p = pVar;
479 0 : p->ResetFlag( SBX_EXTFOUND );
480 0 : break;
481 : }
482 : // Did we have an array/object with extended search?
483 0 : else if( bExtSearch && pVar->IsSet( SBX_EXTSEARCH ) )
484 : {
485 0 : switch( pVar->GetClass() )
486 : {
487 : case SbxCLASS_OBJECT:
488 : {
489 : // Objects are not allowed to scan their parent.
490 0 : sal_uInt16 nOld = pVar->GetFlags();
491 0 : pVar->ResetFlag( SBX_GBLSEARCH );
492 0 : p = ((SbxObject*) pVar)->Find( rName, t );
493 0 : pVar->SetFlags( nOld );
494 0 : break;
495 : }
496 : case SbxCLASS_ARRAY:
497 0 : p = ((SbxArray*) pVar)->Find( rName, t );
498 0 : break;
499 0 : default: break;
500 : }
501 0 : if( p )
502 : {
503 0 : p->SetFlag( SBX_EXTFOUND );
504 0 : break;
505 : }
506 : }
507 : }
508 : }
509 0 : return p;
510 : }
511 :
512 0 : bool SbxArray::LoadData( SvStream& rStrm, sal_uInt16 nVer )
513 : {
514 : sal_uInt16 nElem;
515 0 : Clear();
516 0 : bool bRes = true;
517 0 : sal_uInt16 f = nFlags;
518 0 : nFlags |= SBX_WRITE;
519 0 : rStrm.ReadUInt16( nElem );
520 0 : nElem &= 0x7FFF;
521 0 : for( sal_uInt32 n = 0; n < nElem; n++ )
522 : {
523 : sal_uInt16 nIdx;
524 0 : rStrm.ReadUInt16( nIdx );
525 0 : SbxVariable* pVar = (SbxVariable*) Load( rStrm );
526 0 : if( pVar )
527 : {
528 0 : SbxVariableRef& rRef = GetRef( nIdx );
529 0 : rRef = pVar;
530 : }
531 : else
532 : {
533 0 : bRes = false;
534 0 : break;
535 : }
536 : }
537 0 : if( bRes )
538 0 : bRes = LoadPrivateData( rStrm, nVer );
539 0 : nFlags = f;
540 0 : return bRes;
541 : }
542 :
543 0 : bool SbxArray::StoreData( SvStream& rStrm ) const
544 : {
545 0 : sal_uInt32 nElem = 0;
546 : sal_uInt32 n;
547 : // Which elements are even defined?
548 0 : for( n = 0; n < pData->size(); n++ )
549 : {
550 0 : SbxVariableRef* pRef = (*pData)[n];
551 0 : SbxVariable* p = *pRef;
552 0 : if( p && !( p->GetFlags() & SBX_DONTSTORE ) )
553 0 : nElem++;
554 : }
555 0 : rStrm.WriteUInt16( (sal_uInt16) nElem );
556 0 : for( n = 0; n < pData->size(); n++ )
557 : {
558 0 : SbxVariableRef* pRef = (*pData)[n];
559 0 : SbxVariable* p = *pRef;
560 0 : if( p && !( p->GetFlags() & SBX_DONTSTORE ) )
561 : {
562 0 : rStrm.WriteUInt16( (sal_uInt16) n );
563 0 : if( !p->Store( rStrm ) )
564 0 : return false;
565 : }
566 : }
567 0 : return StorePrivateData( rStrm );
568 : }
569 :
570 : // #100883 Method to set method directly to parameter array
571 0 : void SbxArray::PutDirect( SbxVariable* pVar, sal_uInt32 nIdx )
572 : {
573 0 : SbxVariableRef& rRef = GetRef32( nIdx );
574 0 : rRef = pVar;
575 0 : }
576 :
577 :
578 : // SbxArray
579 :
580 0 : SbxDimArray::SbxDimArray( SbxDataType t ) : SbxArray( t ), mbHasFixedSize( false )
581 : {
582 0 : pFirst = pLast = NULL;
583 0 : nDim = 0;
584 0 : }
585 :
586 0 : SbxDimArray::SbxDimArray( const SbxDimArray& rArray )
587 0 : : SvRefBase( rArray ), SbxArray( rArray.eType )
588 : {
589 0 : pFirst = pLast = NULL;
590 0 : nDim = 0;
591 0 : *this = rArray;
592 0 : }
593 :
594 0 : SbxDimArray& SbxDimArray::operator=( const SbxDimArray& rArray )
595 : {
596 0 : if( &rArray != this )
597 : {
598 0 : SbxArray::operator=( (const SbxArray&) rArray );
599 0 : SbxDim* p = rArray.pFirst;
600 0 : while( p )
601 : {
602 0 : AddDim32( p->nLbound, p->nUbound );
603 0 : p = p->pNext;
604 : }
605 0 : this->mbHasFixedSize = rArray.mbHasFixedSize;
606 : }
607 0 : return *this;
608 : }
609 :
610 0 : SbxDimArray::~SbxDimArray()
611 : {
612 0 : Clear();
613 0 : }
614 :
615 0 : void SbxDimArray::Clear()
616 : {
617 0 : SbxDim* p = pFirst;
618 0 : while( p )
619 : {
620 0 : SbxDim* q = p->pNext;
621 0 : delete p;
622 0 : p = q;
623 : }
624 0 : pFirst = pLast = NULL;
625 0 : nDim = 0;
626 0 : }
627 :
628 : // Add a dimension
629 :
630 0 : void SbxDimArray::AddDimImpl32( sal_Int32 lb, sal_Int32 ub, bool bAllowSize0 )
631 : {
632 0 : SbxError eRes = SbxERR_OK;
633 0 : if( ub < lb && !bAllowSize0 )
634 : {
635 0 : eRes = SbxERR_BOUNDS;
636 0 : ub = lb;
637 : }
638 0 : SbxDim* p = new SbxDim;
639 0 : p->nLbound = lb;
640 0 : p->nUbound = ub;
641 0 : p->nSize = ub - lb + 1;
642 0 : p->pNext = NULL;
643 0 : if( !pFirst )
644 0 : pFirst = pLast = p;
645 : else
646 0 : pLast->pNext = p, pLast = p;
647 0 : nDim++;
648 0 : if( eRes )
649 0 : SetError( eRes );
650 0 : }
651 :
652 0 : short SbxDimArray::GetDims() const
653 : {
654 0 : return nDim;
655 : }
656 :
657 0 : void SbxDimArray::AddDim( short lb, short ub )
658 : {
659 0 : AddDimImpl32( lb, ub, false );
660 0 : }
661 :
662 0 : void SbxDimArray::unoAddDim( short lb, short ub )
663 : {
664 0 : AddDimImpl32( lb, ub, true );
665 0 : }
666 :
667 0 : void SbxDimArray::AddDim32( sal_Int32 lb, sal_Int32 ub )
668 : {
669 0 : AddDimImpl32( lb, ub, false );
670 0 : }
671 :
672 0 : void SbxDimArray::unoAddDim32( sal_Int32 lb, sal_Int32 ub )
673 : {
674 0 : AddDimImpl32( lb, ub, true );
675 0 : }
676 :
677 :
678 : // Readout dimension data
679 :
680 0 : bool SbxDimArray::GetDim32( sal_Int32 n, sal_Int32& rlb, sal_Int32& rub ) const
681 : {
682 0 : if( n < 1 || n > nDim )
683 : {
684 0 : SetError( SbxERR_BOUNDS );
685 0 : rub = rlb = 0;
686 0 : return false;
687 : }
688 0 : SbxDim* p = pFirst;
689 0 : while( --n )
690 0 : p = p->pNext;
691 0 : rub = p->nUbound;
692 0 : rlb = p->nLbound;
693 0 : return true;
694 : }
695 :
696 0 : bool SbxDimArray::GetDim( short n, short& rlb, short& rub ) const
697 : {
698 : sal_Int32 rlb32, rub32;
699 0 : bool bRet = GetDim32( n, rlb32, rub32 );
700 0 : if( bRet )
701 : {
702 0 : if( rlb32 < -SBX_MAXINDEX || rub32 > SBX_MAXINDEX )
703 : {
704 0 : SetError( SbxERR_BOUNDS );
705 0 : return false;
706 : }
707 0 : rub = (short)rub32;
708 0 : rlb = (short)rlb32;
709 : }
710 0 : return bRet;
711 : }
712 :
713 : // Element-Ptr with the help of an index list
714 :
715 0 : sal_uInt32 SbxDimArray::Offset32( const sal_Int32* pIdx )
716 : {
717 0 : sal_uInt32 nPos = 0;
718 0 : for( SbxDim* p = pFirst; p; p = p->pNext )
719 : {
720 0 : sal_Int32 nIdx = *pIdx++;
721 0 : if( nIdx < p->nLbound || nIdx > p->nUbound )
722 : {
723 0 : nPos = (sal_uInt32)SBX_MAXINDEX32 + 1; break;
724 : }
725 0 : nPos = nPos * p->nSize + nIdx - p->nLbound;
726 : }
727 0 : if( nDim == 0 || nPos > SBX_MAXINDEX32 )
728 : {
729 0 : SetError( SbxERR_BOUNDS ); nPos = 0;
730 : }
731 0 : return nPos;
732 : }
733 :
734 0 : sal_uInt16 SbxDimArray::Offset( const short* pIdx )
735 : {
736 0 : long nPos = 0;
737 0 : for( SbxDim* p = pFirst; p; p = p->pNext )
738 : {
739 0 : short nIdx = *pIdx++;
740 0 : if( nIdx < p->nLbound || nIdx > p->nUbound )
741 : {
742 0 : nPos = SBX_MAXINDEX + 1; break;
743 : }
744 0 : nPos = nPos * p->nSize + nIdx - p->nLbound;
745 : }
746 0 : if( nDim == 0 || nPos > SBX_MAXINDEX )
747 : {
748 0 : SetError( SbxERR_BOUNDS ); nPos = 0;
749 : }
750 0 : return (sal_uInt16) nPos;
751 : }
752 :
753 0 : SbxVariable* SbxDimArray::Get( const short* pIdx )
754 : {
755 0 : return SbxArray::Get( Offset( pIdx ) );
756 : }
757 :
758 0 : void SbxDimArray::Put( SbxVariable* p, const short* pIdx )
759 : {
760 0 : SbxArray::Put( p, Offset( pIdx ) );
761 0 : }
762 :
763 0 : SbxVariable* SbxDimArray::Get32( const sal_Int32* pIdx )
764 : {
765 0 : return SbxArray::Get32( Offset32( pIdx ) );
766 : }
767 :
768 0 : void SbxDimArray::Put32( SbxVariable* p, const sal_Int32* pIdx )
769 : {
770 0 : SbxArray::Put32( p, Offset32( pIdx ) );
771 0 : }
772 :
773 :
774 : // Element-Number with the help of Parameter-Array
775 :
776 0 : sal_uInt32 SbxDimArray::Offset32( SbxArray* pPar )
777 : {
778 : #ifndef DISABLE_SCRIPTING
779 0 : if( nDim == 0 || !pPar || ( ( nDim != ( pPar->Count() - 1 ) ) && SbiRuntime::isVBAEnabled() ) )
780 : {
781 0 : SetError( SbxERR_BOUNDS ); return 0;
782 : }
783 : #endif
784 0 : sal_uInt32 nPos = 0;
785 0 : sal_uInt16 nOff = 1; // Non element 0!
786 0 : for( SbxDim* p = pFirst; p && !IsError(); p = p->pNext )
787 : {
788 0 : sal_Int32 nIdx = pPar->Get( nOff++ )->GetLong();
789 0 : if( nIdx < p->nLbound || nIdx > p->nUbound )
790 : {
791 0 : nPos = (sal_uInt32) SBX_MAXINDEX32+1; break;
792 : }
793 0 : nPos = nPos * p->nSize + nIdx - p->nLbound;
794 : }
795 0 : if( nPos > (sal_uInt32) SBX_MAXINDEX32 )
796 : {
797 0 : SetError( SbxERR_BOUNDS ); nPos = 0;
798 : }
799 0 : return nPos;
800 : }
801 :
802 0 : SbxVariable* SbxDimArray::Get( SbxArray* pPar )
803 : {
804 0 : return SbxArray::Get32( Offset32( pPar ) );
805 : }
806 :
807 0 : bool SbxDimArray::LoadData( SvStream& rStrm, sal_uInt16 nVer )
808 : {
809 : short nDimension;
810 0 : rStrm.ReadInt16( nDimension );
811 0 : for( short i = 0; i < nDimension && rStrm.GetError() == SVSTREAM_OK; i++ )
812 : {
813 : sal_Int16 lb, ub;
814 0 : rStrm.ReadInt16( lb ).ReadInt16( ub );
815 0 : AddDim( lb, ub );
816 : }
817 0 : return SbxArray::LoadData( rStrm, nVer );
818 : }
819 :
820 0 : bool SbxDimArray::StoreData( SvStream& rStrm ) const
821 : {
822 0 : rStrm.WriteInt16( (sal_Int16) nDim );
823 0 : for( short i = 0; i < nDim; i++ )
824 : {
825 : short lb, ub;
826 0 : GetDim( i, lb, ub );
827 0 : rStrm.WriteInt16( (sal_Int16) lb ).WriteInt16( (sal_Int16) ub );
828 : }
829 0 : return SbxArray::StoreData( rStrm );
830 : }
831 :
832 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|