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 284663 : struct SbxVarEntry
32 : {
33 : SbxVariableRef mpVar;
34 : boost::optional<OUString> maAlias;
35 : };
36 :
37 297 : TYPEINIT1(SbxArray,SbxBase)
38 28531 : TYPEINIT1(SbxDimArray,SbxArray)
39 :
40 : // SbxArray
41 :
42 125332 : SbxArray::SbxArray( SbxDataType t ) : SbxBase()
43 : {
44 125332 : mpVarEntries = new VarEntriesType;
45 125332 : eType = t;
46 125332 : if( t != SbxVARIANT )
47 37085 : SetFlag( SBX_FIXED );
48 125332 : }
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 6 : SbxArray& SbxArray::operator=( const SbxArray& rArray )
60 : {
61 6 : if( &rArray != this )
62 : {
63 6 : eType = rArray.eType;
64 6 : Clear();
65 6 : VarEntriesType* pSrc = rArray.mpVarEntries;
66 10 : for( size_t i = 0; i < pSrc->size(); i++ )
67 : {
68 4 : SbxVarEntry* pSrcRef = (*pSrc)[i];
69 4 : SbxVariableRef pSrc_ = pSrcRef->mpVar;
70 4 : if( !pSrc_ )
71 0 : continue;
72 4 : SbxVarEntry* pDstRef = new SbxVarEntry;
73 4 : pDstRef->mpVar = pSrcRef->mpVar;
74 :
75 4 : if (pSrcRef->maAlias)
76 0 : pDstRef->maAlias.reset(*pSrcRef->maAlias);
77 :
78 4 : 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 4 : mpVarEntries->push_back( pDstRef );
87 4 : }
88 : }
89 6 : return *this;
90 : }
91 :
92 470004 : SbxArray::~SbxArray()
93 : {
94 117568 : Clear();
95 117568 : delete mpVarEntries;
96 352436 : }
97 :
98 1389 : SbxDataType SbxArray::GetType() const
99 : {
100 1389 : return (SbxDataType) ( eType | SbxARRAY );
101 : }
102 :
103 0 : SbxClassType SbxArray::GetClass() const
104 : {
105 0 : return SbxCLASS_ARRAY;
106 : }
107 :
108 129619 : void SbxArray::Clear()
109 : {
110 129619 : sal_uInt32 nSize = mpVarEntries->size();
111 211666 : for( sal_uInt32 i = 0 ; i < nSize ; i++ )
112 : {
113 82047 : SbxVarEntry* pEntry = (*mpVarEntries)[i];
114 82047 : delete pEntry;
115 : }
116 129619 : mpVarEntries->clear();
117 129619 : }
118 :
119 5 : sal_uInt32 SbxArray::Count32() const
120 : {
121 5 : return mpVarEntries->size();
122 : }
123 :
124 1384820 : sal_uInt16 SbxArray::Count() const
125 : {
126 1384820 : sal_uInt32 nCount = mpVarEntries->size();
127 : DBG_ASSERT( nCount <= SBX_MAXINDEX, "SBX: Array-Index > SBX_MAXINDEX" );
128 1384820 : return (sal_uInt16)nCount;
129 : }
130 :
131 4669 : 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 4669 : if( nIdx > SBX_MAXINDEX32 )
137 : {
138 0 : SetError( SbxERR_BOUNDS );
139 0 : nIdx = 0;
140 : }
141 13011 : while( mpVarEntries->size() <= nIdx )
142 : {
143 3673 : mpVarEntries->push_back(new SbxVarEntry);
144 : }
145 4669 : return (*mpVarEntries)[nIdx]->mpVar;
146 : }
147 :
148 655430 : 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 655430 : if( nIdx > SBX_MAXINDEX )
154 : {
155 0 : SetError( SbxERR_BOUNDS );
156 0 : nIdx = 0;
157 : }
158 1453417 : while( mpVarEntries->size() <= nIdx )
159 : {
160 142557 : mpVarEntries->push_back(new SbxVarEntry);
161 : }
162 655430 : return (*mpVarEntries)[nIdx]->mpVar;
163 : }
164 :
165 815 : SbxVariable* SbxArray::Get32( sal_uInt32 nIdx )
166 : {
167 815 : if( !CanRead() )
168 : {
169 0 : SetError( SbxERR_PROP_WRITEONLY );
170 0 : return NULL;
171 : }
172 815 : SbxVariableRef& rRef = GetRef32( nIdx );
173 :
174 815 : if ( !rRef.Is() )
175 240 : rRef = new SbxVariable( eType );
176 :
177 815 : return rRef;
178 : }
179 :
180 165338 : SbxVariable* SbxArray::Get( sal_uInt16 nIdx )
181 : {
182 165338 : if( !CanRead() )
183 : {
184 0 : SetError( SbxERR_PROP_WRITEONLY );
185 0 : return NULL;
186 : }
187 165338 : SbxVariableRef& rRef = GetRef( nIdx );
188 :
189 165338 : if ( !rRef.Is() )
190 94 : rRef = new SbxVariable( eType );
191 :
192 165338 : return rRef;
193 : }
194 :
195 3430 : void SbxArray::Put32( SbxVariable* pVar, sal_uInt32 nIdx )
196 : {
197 3430 : if( !CanWrite() )
198 0 : SetError( SbxERR_PROP_READONLY );
199 : else
200 : {
201 3430 : if( pVar )
202 3430 : if( eType != SbxVARIANT )
203 : // Convert no objects
204 9 : if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT )
205 7 : pVar->Convert( eType );
206 3430 : SbxVariableRef& rRef = GetRef32( nIdx );
207 3430 : if( static_cast<SbxVariable*>(rRef) != pVar )
208 : {
209 3430 : rRef = pVar;
210 3430 : SetFlag( SBX_MODIFIED );
211 : }
212 : }
213 3430 : }
214 :
215 172777 : void SbxArray::Put( SbxVariable* pVar, sal_uInt16 nIdx )
216 : {
217 172777 : if( !CanWrite() )
218 0 : SetError( SbxERR_PROP_READONLY );
219 : else
220 : {
221 172777 : if( pVar )
222 172051 : if( eType != SbxVARIANT )
223 : // Convert no objects
224 26167 : if( eType != SbxOBJECT || pVar->GetClass() != SbxCLASS_OBJECT )
225 12 : pVar->Convert( eType );
226 172777 : SbxVariableRef& rRef = GetRef( nIdx );
227 172777 : if( static_cast<SbxVariable*>(rRef) != pVar )
228 : {
229 172680 : rRef = pVar;
230 172680 : SetFlag( SBX_MODIFIED );
231 : }
232 : }
233 172777 : }
234 :
235 6656 : OUString SbxArray::GetAlias( sal_uInt16 nIdx )
236 : {
237 6656 : if( !CanRead() )
238 : {
239 0 : SetError( SbxERR_PROP_WRITEONLY );
240 0 : return OUString();
241 : }
242 6656 : SbxVarEntry& rRef = reinterpret_cast<SbxVarEntry&>(GetRef( nIdx ));
243 :
244 6656 : if (!rRef.maAlias)
245 6452 : return OUString();
246 :
247 204 : return *rRef.maAlias;
248 : }
249 :
250 2419 : void SbxArray::PutAlias( const OUString& rAlias, sal_uInt16 nIdx )
251 : {
252 2419 : if( !CanWrite() )
253 : {
254 0 : SetError( SbxERR_PROP_READONLY );
255 : }
256 : else
257 : {
258 2419 : SbxVarEntry& rRef = reinterpret_cast<SbxVarEntry&>( GetRef( nIdx ) );
259 2419 : rRef.maAlias.reset(rAlias);
260 : }
261 2419 : }
262 :
263 278 : void SbxArray::Insert32( SbxVariable* pVar, sal_uInt32 nIdx )
264 : {
265 : DBG_ASSERT( mpVarEntries->size() <= SBX_MAXINDEX32, "SBX: Array gets too big" );
266 278 : if( mpVarEntries->size() > SBX_MAXINDEX32 )
267 : {
268 278 : return;
269 : }
270 278 : SbxVarEntry* p = new SbxVarEntry;
271 278 : p->mpVar = pVar;
272 278 : size_t nSize = mpVarEntries->size();
273 278 : if( nIdx > nSize )
274 : {
275 0 : nIdx = nSize;
276 : }
277 278 : if( eType != SbxVARIANT && pVar )
278 : {
279 0 : p->mpVar->Convert(eType);
280 : }
281 278 : if( nIdx == nSize )
282 : {
283 278 : mpVarEntries->push_back( p );
284 : }
285 : else
286 : {
287 0 : mpVarEntries->insert( mpVarEntries->begin() + nIdx, p );
288 : }
289 278 : SetFlag( SBX_MODIFIED );
290 : }
291 :
292 278 : void SbxArray::Insert( SbxVariable* pVar, sal_uInt16 nIdx )
293 : {
294 : DBG_ASSERT( mpVarEntries->size() <= 0x3FF0, "SBX: Array gets too big" );
295 278 : if( mpVarEntries->size() > 0x3FF0 )
296 : {
297 278 : return;
298 : }
299 278 : 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 56104 : void SbxArray::Remove( sal_uInt16 nIdx )
314 : {
315 56104 : if( nIdx < mpVarEntries->size() )
316 : {
317 56104 : SbxVarEntry* pRef = (*mpVarEntries)[nIdx];
318 56104 : mpVarEntries->erase( mpVarEntries->begin() + nIdx );
319 56104 : delete pRef;
320 56104 : SetFlag( SBX_MODIFIED );
321 : }
322 56104 : }
323 :
324 0 : void SbxArray::Remove( SbxVariable* pVar )
325 : {
326 0 : if( pVar )
327 : {
328 0 : for( size_t 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 3217727 : SbxVariable* SbxArray::Find( const OUString& rName, SbxClassType t )
441 : {
442 3217727 : SbxVariable* p = NULL;
443 3217727 : sal_uInt32 nCount = mpVarEntries->size();
444 3217727 : if( !nCount )
445 1835664 : return NULL;
446 1382063 : bool bExtSearch = IsSet( SBX_EXTSEARCH );
447 1382063 : sal_uInt16 nHash = SbxVariable::MakeHashCode( rName );
448 4537886 : for( sal_uInt32 i = 0; i < nCount; i++ )
449 : {
450 3330820 : SbxVarEntry* pEntry = (*mpVarEntries)[i];
451 3330820 : if (!pEntry->mpVar || !pEntry->mpVar->IsVisible())
452 0 : continue;
453 :
454 : // The very secure search works as well, if there is no hashcode!
455 3330820 : sal_uInt16 nVarHash = pEntry->mpVar->GetHashCode();
456 6661640 : if ( (!nVarHash || nVarHash == nHash)
457 186091 : && (t == SbxCLASS_DONTCARE || pEntry->mpVar->GetClass() == t)
458 3516911 : && (pEntry->mpVar->GetName().equalsIgnoreAsciiCase(rName)))
459 : {
460 174996 : p = &pEntry->mpVar;
461 174996 : p->ResetFlag(SBX_EXTFOUND);
462 174996 : break;
463 : }
464 :
465 : // Did we have an array/object with extended search?
466 3155824 : if (bExtSearch && pEntry->mpVar->IsSet(SBX_EXTSEARCH))
467 : {
468 535401 : switch (pEntry->mpVar->GetClass())
469 : {
470 : case SbxCLASS_OBJECT:
471 : {
472 : // Objects are not allowed to scan their parent.
473 535401 : SbxFlagBits nOld = pEntry->mpVar->GetFlags();
474 535401 : pEntry->mpVar->ResetFlag(SBX_GBLSEARCH);
475 535401 : p = static_cast<SbxObject&>(*pEntry->mpVar).Find(rName, t);
476 535401 : pEntry->mpVar->SetFlags(nOld);
477 : }
478 535401 : 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 535401 : if (p)
488 : {
489 1 : p->SetFlag(SBX_EXTFOUND);
490 1 : break;
491 : }
492 : }
493 : }
494 1382063 : 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 424 : void SbxArray::PutDirect( SbxVariable* pVar, sal_uInt32 nIdx )
555 : {
556 424 : SbxVariableRef& rRef = GetRef32( nIdx );
557 424 : rRef = pVar;
558 424 : }
559 :
560 :
561 : // SbxArray
562 :
563 134 : SbxDimArray::SbxDimArray( SbxDataType t ) : SbxArray( t ), mbHasFixedSize( false )
564 : {
565 134 : }
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 536 : SbxDimArray::~SbxDimArray()
585 : {
586 134 : Clear();
587 402 : }
588 :
589 142 : void SbxDimArray::Clear()
590 : {
591 142 : m_vDimensions.clear();
592 142 : }
593 :
594 : // Add a dimension
595 :
596 167 : void SbxDimArray::AddDimImpl32( sal_Int32 lb, sal_Int32 ub, bool bAllowSize0 )
597 : {
598 167 : SbxError eRes = SbxERR_OK;
599 167 : if( ub < lb && !bAllowSize0 )
600 : {
601 0 : eRes = SbxERR_BOUNDS;
602 0 : ub = lb;
603 : }
604 : SbxDim d;
605 167 : d.nLbound = lb;
606 167 : d.nUbound = ub;
607 167 : d.nSize = ub - lb + 1;
608 167 : m_vDimensions.push_back(d);
609 167 : if( eRes )
610 0 : SetError( eRes );
611 167 : }
612 :
613 :
614 24 : void SbxDimArray::AddDim( short lb, short ub )
615 : {
616 24 : AddDimImpl32( lb, ub, false );
617 24 : }
618 :
619 34 : void SbxDimArray::unoAddDim( short lb, short ub )
620 : {
621 34 : AddDimImpl32( lb, ub, true );
622 34 : }
623 :
624 40 : void SbxDimArray::AddDim32( sal_Int32 lb, sal_Int32 ub )
625 : {
626 40 : AddDimImpl32( lb, ub, false );
627 40 : }
628 :
629 69 : void SbxDimArray::unoAddDim32( sal_Int32 lb, sal_Int32 ub )
630 : {
631 69 : AddDimImpl32( lb, ub, true );
632 69 : }
633 :
634 :
635 : // Readout dimension data
636 :
637 148 : bool SbxDimArray::GetDim32( sal_Int32 n, sal_Int32& rlb, sal_Int32& rub ) const
638 : {
639 148 : 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 148 : SbxDim d = m_vDimensions[n - 1];
646 148 : rub = d.nUbound;
647 148 : rlb = d.nLbound;
648 148 : 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 3528 : sal_uInt32 SbxDimArray::Offset32( const sal_Int32* pIdx )
671 : {
672 3528 : sal_uInt32 nPos = 0;
673 31458 : for( std::vector<SbxDim>::const_iterator it = m_vDimensions.begin();
674 20972 : it != m_vDimensions.end(); ++it )
675 : {
676 6958 : sal_Int32 nIdx = *pIdx++;
677 6958 : if( nIdx < it->nLbound || nIdx > it->nUbound )
678 : {
679 0 : nPos = (sal_uInt32)SBX_MAXINDEX32 + 1; break;
680 : }
681 6958 : nPos = nPos * it->nSize + nIdx - it->nLbound;
682 : }
683 3528 : if( m_vDimensions.empty() || nPos > SBX_MAXINDEX32 )
684 : {
685 0 : SetError( SbxERR_BOUNDS );
686 0 : nPos = 0;
687 : }
688 3528 : return nPos;
689 : }
690 :
691 78 : sal_uInt16 SbxDimArray::Offset( const short* pIdx )
692 : {
693 78 : long nPos = 0;
694 468 : for( std::vector<SbxDim>::const_iterator it = m_vDimensions.begin();
695 312 : it != m_vDimensions.end(); ++it )
696 : {
697 78 : short nIdx = *pIdx++;
698 78 : if( nIdx < it->nLbound || nIdx > it->nUbound )
699 : {
700 0 : nPos = SBX_MAXINDEX + 1;
701 0 : break;
702 : }
703 78 : nPos = nPos * it->nSize + nIdx - it->nLbound;
704 : }
705 78 : if( m_vDimensions.empty() || nPos > SBX_MAXINDEX )
706 : {
707 0 : SetError( SbxERR_BOUNDS );
708 0 : nPos = 0;
709 : }
710 78 : 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 78 : void SbxDimArray::Put( SbxVariable* p, const short* pIdx )
719 : {
720 78 : SbxArray::Put( p, Offset( pIdx ) );
721 78 : }
722 :
723 100 : SbxVariable* SbxDimArray::Get32( const sal_Int32* pIdx )
724 : {
725 100 : return SbxArray::Get32( Offset32( pIdx ) );
726 : }
727 :
728 3428 : void SbxDimArray::Put32( SbxVariable* p, const sal_Int32* pIdx )
729 : {
730 3428 : SbxArray::Put32( p, Offset32( pIdx ) );
731 3428 : }
732 :
733 : // Element-Number with the help of Parameter-Array
734 685 : sal_uInt32 SbxDimArray::Offset32( SbxArray* pPar )
735 : {
736 : #if HAVE_FEATURE_SCRIPTING
737 1370 : if (m_vDimensions.empty() || !pPar ||
738 685 : ((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 685 : sal_uInt32 nPos = 0;
746 685 : sal_uInt16 nOff = 1; // Non element 0!
747 5403 : for( std::vector<SbxDim>::const_iterator it = m_vDimensions.begin();
748 5403 : it != m_vDimensions.end() && !IsError(); ++it )
749 : {
750 1116 : sal_Int32 nIdx = pPar->Get( nOff++ )->GetLong();
751 1116 : if( nIdx < it->nLbound || nIdx > it->nUbound )
752 : {
753 0 : nPos = (sal_uInt32) SBX_MAXINDEX32+1;
754 0 : break;
755 : }
756 1116 : nPos = nPos * it->nSize + nIdx - it->nLbound;
757 : }
758 685 : if( nPos > (sal_uInt32) SBX_MAXINDEX32 )
759 : {
760 0 : SetError( SbxERR_BOUNDS );
761 0 : nPos = 0;
762 : }
763 685 : return nPos;
764 : }
765 :
766 685 : SbxVariable* SbxDimArray::Get( SbxArray* pPar )
767 : {
768 685 : 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: */
|