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