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_sc.hxx"
26
27 // System - Includes -----------------------------------------------------
28
29
30
31 #include <tools/debug.hxx>
32 #include <limits.h>
33
34 // INCLUDE ---------------------------------------------------------------
35
36 #include "olinetab.hxx"
37 #include "global.hxx"
38 #include "rechead.hxx"
39 #include "address.hxx"
40 #include "table.hxx"
41
42 //------------------------------------------------------------------------
43
ScOutlineEntry(SCCOLROW nNewStart,SCCOLROW nNewSize,bool bNewHidden)44 ScOutlineEntry::ScOutlineEntry( SCCOLROW nNewStart, SCCOLROW nNewSize, bool bNewHidden ) :
45 nStart ( nNewStart ),
46 nSize ( nNewSize ),
47 bHidden ( bNewHidden ),
48 bVisible( sal_True )
49 {
50 }
51
ScOutlineEntry(const ScOutlineEntry & rEntry)52 ScOutlineEntry::ScOutlineEntry( const ScOutlineEntry& rEntry ) :
53 ScDataObject(),
54 nStart ( rEntry.nStart ),
55 nSize ( rEntry.nSize ),
56 bHidden ( rEntry.bHidden ),
57 bVisible( rEntry.bVisible )
58 {
59 }
60
Clone() const61 ScDataObject* ScOutlineEntry::Clone() const
62 {
63 return new ScOutlineEntry( *this );
64 }
65
Move(SCsCOLROW nDelta)66 void ScOutlineEntry::Move( SCsCOLROW nDelta )
67 {
68 SCCOLROW nNewPos = nStart + nDelta;
69 if (nNewPos<0)
70 {
71 DBG_ERROR("OutlineEntry < 0");
72 nNewPos = 0;
73 }
74 nStart = nNewPos;
75 }
76
SetSize(SCSIZE nNewSize)77 void ScOutlineEntry::SetSize( SCSIZE nNewSize )
78 {
79 if (nNewSize>0)
80 nSize = nNewSize;
81 else
82 {
83 DBG_ERROR("ScOutlineEntry Size == 0");
84 }
85 }
86
SetPosSize(SCCOLROW nNewPos,SCSIZE nNewSize)87 void ScOutlineEntry::SetPosSize( SCCOLROW nNewPos, SCSIZE nNewSize )
88 {
89 nStart = nNewPos;
90 SetSize( nNewSize );
91 }
92
SetHidden(bool bNewHidden)93 void ScOutlineEntry::SetHidden( bool bNewHidden )
94 {
95 bHidden = bNewHidden;
96 }
97
SetVisible(bool bNewVisible)98 void ScOutlineEntry::SetVisible( bool bNewVisible )
99 {
100 bVisible = bNewVisible;
101 }
102
103 //------------------------------------------------------------------------
104
ScOutlineCollection()105 ScOutlineCollection::ScOutlineCollection() :
106 ScSortedCollection( 4,4,sal_False )
107 {
108 }
109
IntCompare(SCCOLROW nX,SCCOLROW nY)110 inline short IntCompare( SCCOLROW nX, SCCOLROW nY )
111 {
112 if ( nX==nY ) return 0;
113 else if ( nX<nY ) return -1;
114 else return 1;
115 }
116
Compare(ScDataObject * pKey1,ScDataObject * pKey2) const117 short ScOutlineCollection::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const
118 {
119 return IntCompare( ((ScOutlineEntry*)pKey1)->GetStart(),
120 ((ScOutlineEntry*)pKey2)->GetStart() );
121 }
122
FindStart(SCCOLROW nMinStart)123 sal_uInt16 ScOutlineCollection::FindStart( SCCOLROW nMinStart )
124 {
125 //! binaer suchen ?
126
127 sal_uInt16 nPos = 0;
128 sal_uInt16 nLocalCount = GetCount();
129 while ( (nPos<nLocalCount) ? (((ScOutlineEntry*)At(nPos))->GetStart() < nMinStart) : sal_False )
130 ++nPos;
131
132 return nPos;
133 }
134
135 //------------------------------------------------------------------------
136
ScOutlineArray()137 ScOutlineArray::ScOutlineArray() :
138 nDepth( 0 )
139 {
140 }
141
ScOutlineArray(const ScOutlineArray & rArray)142 ScOutlineArray::ScOutlineArray( const ScOutlineArray& rArray ) :
143 nDepth( rArray.nDepth )
144 {
145 for (sal_uInt16 nLevel=0; nLevel<nDepth; nLevel++)
146 {
147 sal_uInt16 nCount = rArray.aCollections[nLevel].GetCount();
148 for (sal_uInt16 nEntry=0; nEntry<nCount; nEntry++)
149 {
150 ScOutlineEntry* pEntry = (ScOutlineEntry*) rArray.aCollections[nLevel].At(nEntry);
151 aCollections[nLevel].Insert( new ScOutlineEntry( *pEntry ) );
152 }
153 }
154 }
155
FindEntry(SCCOLROW nSearchPos,sal_uInt16 & rFindLevel,sal_uInt16 & rFindIndex,sal_uInt16 nMaxLevel)156 void ScOutlineArray::FindEntry( SCCOLROW nSearchPos, sal_uInt16& rFindLevel, sal_uInt16& rFindIndex,
157 sal_uInt16 nMaxLevel )
158 {
159 rFindLevel = rFindIndex = 0;
160
161 if (nMaxLevel > nDepth)
162 nMaxLevel = nDepth;
163
164 for (sal_uInt16 nLevel=0; nLevel<nMaxLevel; nLevel++) //! rueckwaerts suchen ?
165 {
166 ScOutlineCollection* pCollect = &aCollections[nLevel];
167 sal_uInt16 nCount = pCollect->GetCount();
168 for (sal_uInt16 i=0; i<nCount; i++)
169 {
170 ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i);
171 if ( pEntry->GetStart() <= nSearchPos && pEntry->GetEnd() >= nSearchPos )
172 {
173 rFindLevel = nLevel + 1; // naechster Level (zum Einfuegen)
174 rFindIndex = i;
175 }
176 }
177 }
178 }
179
Insert(SCCOLROW nStartCol,SCCOLROW nEndCol,sal_Bool & rSizeChanged,sal_Bool bHidden,sal_Bool bVisible)180 sal_Bool ScOutlineArray::Insert( SCCOLROW nStartCol, SCCOLROW nEndCol, sal_Bool& rSizeChanged,
181 sal_Bool bHidden, sal_Bool bVisible )
182 {
183 rSizeChanged = sal_False;
184
185 sal_uInt16 nStartLevel;
186 sal_uInt16 nStartIndex;
187 sal_uInt16 nEndLevel;
188 sal_uInt16 nEndIndex;
189 sal_Bool bFound = sal_False;
190
191 sal_Bool bCont;
192 sal_uInt16 nFindMax;
193 FindEntry( nStartCol, nStartLevel, nStartIndex ); // nLevel = neuer Level (alter+1) !!!
194 FindEntry( nEndCol, nEndLevel, nEndIndex );
195 nFindMax = Max(nStartLevel,nEndLevel);
196 do
197 {
198 bCont = sal_False;
199
200 if ( nStartLevel == nEndLevel && nStartIndex == nEndIndex && nStartLevel < SC_OL_MAXDEPTH )
201 bFound = sal_True;
202
203 if (!bFound)
204 {
205 if (nFindMax>0)
206 {
207 --nFindMax;
208 if (nStartLevel)
209 if ( ((ScOutlineEntry*)aCollections[nStartLevel-1].At(nStartIndex))->
210 GetStart() == nStartCol )
211 FindEntry( nStartCol, nStartLevel, nStartIndex, nFindMax );
212 if (nEndLevel)
213 if ( ((ScOutlineEntry*)aCollections[nEndLevel-1].At(nEndIndex))->
214 GetEnd() == nEndCol )
215 FindEntry( nEndCol, nEndLevel, nEndIndex, nFindMax );
216 bCont = sal_True;
217 }
218 }
219 }
220 while ( !bFound && bCont );
221
222 if (!bFound)
223 return sal_False;
224
225 sal_uInt16 nLevel = nStartLevel;
226
227 // untere verschieben
228
229 sal_Bool bNeedSize = sal_False;
230 for ( short nMoveLevel = nDepth-1; nMoveLevel >= (short) nLevel; nMoveLevel-- )
231 {
232 sal_uInt16 nCount = aCollections[nMoveLevel].GetCount();
233 sal_Bool bMoved = sal_False;
234 for ( sal_uInt16 i=0; i<nCount; i += bMoved ? 0 : 1 )
235 {
236 ScOutlineEntry* pEntry = (ScOutlineEntry*) aCollections[nMoveLevel].At(i);
237 SCCOLROW nEntryStart = pEntry->GetStart();
238 if ( nEntryStart >= nStartCol && nEntryStart <= nEndCol )
239 {
240 if (nMoveLevel >= SC_OL_MAXDEPTH - 1)
241 {
242 rSizeChanged = sal_False; // kein Platz
243 return sal_False;
244 }
245 aCollections[nMoveLevel+1].Insert( new ScOutlineEntry( *pEntry ) );
246 aCollections[nMoveLevel].AtFree( i );
247 nCount = aCollections[nMoveLevel].GetCount();
248 bMoved = sal_True;
249 if (nMoveLevel == (short) nDepth - 1)
250 bNeedSize = sal_True;
251 }
252 else
253 bMoved = sal_False;
254 }
255 }
256
257 if (bNeedSize)
258 {
259 ++nDepth;
260 rSizeChanged = sal_True;
261 }
262
263 if (nDepth <= nLevel)
264 {
265 nDepth = nLevel+1;
266 rSizeChanged = sal_True;
267 }
268
269 /* nicht zusammenfassen!
270
271 // zusammenfassen
272
273 sal_uInt16 nCount = aCollections[nLevel].GetCount();
274 sal_uInt16 nIndex;
275 bFound = sal_False;
276 for ( nIndex=0; nIndex<nCount && !bFound; nIndex++ )
277 {
278 if ( ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetEnd() + 1 == nStartCol )
279 {
280 nStartCol = ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetStart();
281 aCollections[nLevel].AtFree(nIndex);
282 nCount = aCollections[nLevel].GetCount(); // Daten geaendert
283 bFound = sal_True;
284 }
285 }
286
287 bFound = sal_False;
288 for ( nIndex=0; nIndex<nCount && !bFound; nIndex++ )
289 {
290 if ( ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetStart() == nEndCol + 1 )
291 {
292 nEndCol = ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetEnd();
293 aCollections[nLevel].AtFree(nIndex);
294 bFound = sal_True;
295 }
296 }
297 */
298 ScOutlineEntry* pNewEntry = new ScOutlineEntry( nStartCol, nEndCol+1-nStartCol, bHidden );
299 pNewEntry->SetVisible( bVisible );
300 aCollections[nLevel].Insert( pNewEntry );
301
302 return sal_True;
303 }
304
FindTouchedLevel(SCCOLROW nBlockStart,SCCOLROW nBlockEnd,sal_uInt16 & rFindLevel) const305 sal_Bool ScOutlineArray::FindTouchedLevel( SCCOLROW nBlockStart, SCCOLROW nBlockEnd, sal_uInt16& rFindLevel ) const
306 {
307 sal_Bool bFound = sal_False;
308 rFindLevel = 0;
309
310 for (sal_uInt16 nLevel=0; nLevel<nDepth; nLevel++)
311 {
312 const ScOutlineCollection* pCollect = &aCollections[nLevel];
313 sal_uInt16 nCount = pCollect->GetCount();
314 for (sal_uInt16 i=0; i<nCount; i++)
315 {
316 ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i);
317 SCCOLROW nStart = pEntry->GetStart();
318 SCCOLROW nEnd = pEntry->GetEnd();
319
320 if ( ( nBlockStart>=nStart && nBlockStart<=nEnd ) ||
321 ( nBlockEnd >=nStart && nBlockEnd <=nEnd ) )
322 {
323 rFindLevel = nLevel; // wirklicher Level
324 bFound = sal_True;
325 }
326 }
327 }
328
329 return bFound;
330 }
331
RemoveSub(SCCOLROW nStartPos,SCCOLROW nEndPos,sal_uInt16 nLevel)332 void ScOutlineArray::RemoveSub( SCCOLROW nStartPos, SCCOLROW nEndPos, sal_uInt16 nLevel )
333 {
334 if ( nLevel >= nDepth )
335 return;
336 ScOutlineCollection* pCollect = &aCollections[nLevel];
337 sal_uInt16 nCount = pCollect->GetCount();
338 sal_Bool bFound = sal_False;
339 for ( sal_uInt16 i=0; i<nCount; i += ( bFound ? 0 : 1 ) )
340 {
341 bFound = sal_False;
342 ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i);
343 SCCOLROW nStart = pEntry->GetStart();
344 SCCOLROW nEnd = pEntry->GetEnd();
345
346 if ( nStart>=nStartPos && nEnd<=nEndPos )
347 {
348 RemoveSub( nStart, nEnd, nLevel+1 );
349 pCollect->AtFree(i);
350 nCount = pCollect->GetCount();
351 bFound = sal_True;
352 }
353 }
354 }
355
PromoteSub(SCCOLROW nStartPos,SCCOLROW nEndPos,sal_uInt16 nStartLevel)356 void ScOutlineArray::PromoteSub( SCCOLROW nStartPos, SCCOLROW nEndPos, sal_uInt16 nStartLevel )
357 {
358 if (nStartLevel==0)
359 {
360 DBG_ERROR("PromoteSub mit Level 0");
361 return;
362 }
363
364 for (sal_uInt16 nLevel = nStartLevel; nLevel < nDepth; nLevel++)
365 {
366 ScOutlineCollection* pCollect = &aCollections[nLevel];
367 sal_uInt16 nCount = pCollect->GetCount();
368 sal_Bool bFound = sal_False;
369 for ( sal_uInt16 i=0; i<nCount; i += ( bFound ? 0 : 1 ) )
370 {
371 bFound = sal_False;
372 ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i);
373 SCCOLROW nStart = pEntry->GetStart();
374 SCCOLROW nEnd = pEntry->GetEnd();
375
376 if ( nStart>=nStartPos && nEnd<=nEndPos )
377 {
378 aCollections[nLevel-1].Insert( new ScOutlineEntry( *pEntry ) );
379 pCollect->AtFree(i);
380 nCount = pCollect->GetCount();
381 bFound = sal_True;
382 }
383 }
384 }
385 }
386
DecDepth()387 sal_Bool ScOutlineArray::DecDepth() // nDepth auf leere Levels anpassen
388 {
389 sal_Bool bChanged = sal_False;
390 sal_Bool bCont;
391 do
392 {
393 bCont = sal_False;
394 if (nDepth)
395 if (aCollections[nDepth-1].GetCount() == 0)
396 {
397 --nDepth;
398 bChanged = sal_True;
399 bCont = sal_True;
400 }
401 }
402 while (bCont);
403 return bChanged;
404 }
405
Remove(SCCOLROW nBlockStart,SCCOLROW nBlockEnd,sal_Bool & rSizeChanged)406 sal_Bool ScOutlineArray::Remove( SCCOLROW nBlockStart, SCCOLROW nBlockEnd, sal_Bool& rSizeChanged )
407 {
408 sal_uInt16 nLevel;
409 FindTouchedLevel( nBlockStart, nBlockEnd, nLevel );
410
411 ScOutlineCollection* pCollect = &aCollections[nLevel];
412 sal_uInt16 nCount = pCollect->GetCount();
413 sal_Bool bFound = sal_False;
414 sal_Bool bAny = sal_False;
415 for ( sal_uInt16 i=0; i<nCount; i += ( bFound ? 0 : 1 ) )
416 {
417 bFound = sal_False;
418 ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i);
419 SCCOLROW nStart = pEntry->GetStart();
420 SCCOLROW nEnd = pEntry->GetEnd();
421
422 if ( nBlockStart<=nEnd && nBlockEnd>=nStart )
423 {
424 // RemoveSub( nStart, nEnd, nLevel+1 );
425 pCollect->AtFree(i);
426 PromoteSub( nStart, nEnd, nLevel+1 );
427 nCount = pCollect->GetCount();
428 i = pCollect->FindStart( nEnd+1 );
429 bFound = sal_True;
430 bAny = sal_True;
431 }
432 }
433
434 if (bAny) // Depth anpassen
435 if (DecDepth())
436 rSizeChanged = sal_True;
437
438 return bAny;
439 }
440
GetEntry(sal_uInt16 nLevel,sal_uInt16 nIndex) const441 ScOutlineEntry* ScOutlineArray::GetEntry( sal_uInt16 nLevel, sal_uInt16 nIndex ) const
442 {
443 return (ScOutlineEntry*)((nLevel < nDepth) ? aCollections[nLevel].At(nIndex) : NULL);
444 }
445
GetCount(sal_uInt16 nLevel) const446 sal_uInt16 ScOutlineArray::GetCount( sal_uInt16 nLevel ) const
447 {
448 return (nLevel < nDepth) ? aCollections[nLevel].GetCount() : 0;
449 }
450
GetEntryByPos(sal_uInt16 nLevel,SCCOLROW nPos) const451 ScOutlineEntry* ScOutlineArray::GetEntryByPos( sal_uInt16 nLevel, SCCOLROW nPos ) const
452 {
453 sal_uInt16 nCount = GetCount( nLevel );
454 ScOutlineEntry* pEntry;
455
456 for (sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++)
457 {
458 pEntry = GetEntry( nLevel, nIndex );
459 if ((pEntry->GetStart() <= nPos) && (nPos <= pEntry->GetEnd()))
460 return pEntry;
461 }
462 return NULL;
463 }
464
GetEntryIndex(sal_uInt16 nLevel,SCCOLROW nPos,sal_uInt16 & rnIndex) const465 sal_Bool ScOutlineArray::GetEntryIndex( sal_uInt16 nLevel, SCCOLROW nPos, sal_uInt16& rnIndex ) const
466 {
467 // found entry contains passed position
468 sal_uInt16 nCount = GetCount( nLevel );
469 for ( rnIndex = 0; rnIndex < nCount; ++rnIndex )
470 {
471 const ScOutlineEntry* pEntry = GetEntry( nLevel, rnIndex );
472 if ( (pEntry->GetStart() <= nPos) && (nPos <= pEntry->GetEnd()) )
473 return sal_True;
474 }
475 return sal_False;
476 }
477
GetEntryIndexInRange(sal_uInt16 nLevel,SCCOLROW nBlockStart,SCCOLROW nBlockEnd,sal_uInt16 & rnIndex) const478 sal_Bool ScOutlineArray::GetEntryIndexInRange(
479 sal_uInt16 nLevel, SCCOLROW nBlockStart, SCCOLROW nBlockEnd, sal_uInt16& rnIndex ) const
480 {
481 // found entry will be completely inside of passed range
482 sal_uInt16 nCount = GetCount( nLevel );
483 for ( rnIndex = 0; rnIndex < nCount; ++rnIndex )
484 {
485 const ScOutlineEntry* pEntry = GetEntry( nLevel, rnIndex );
486 if ( (nBlockStart <= pEntry->GetStart()) && (pEntry->GetEnd() <= nBlockEnd) )
487 return sal_True;
488 }
489 return sal_False;
490 }
491
SetVisibleBelow(sal_uInt16 nLevel,sal_uInt16 nEntry,sal_Bool bValue,sal_Bool bSkipHidden)492 void ScOutlineArray::SetVisibleBelow( sal_uInt16 nLevel, sal_uInt16 nEntry, sal_Bool bValue, sal_Bool bSkipHidden )
493 {
494 ScOutlineEntry* pEntry = GetEntry( nLevel, nEntry );
495 if( pEntry )
496 {
497 SCCOLROW nStart = pEntry->GetStart();
498 SCCOLROW nEnd = pEntry->GetEnd();
499
500 for (sal_uInt16 nSubLevel=nLevel+1; nSubLevel<nDepth; nSubLevel++)
501 {
502 sal_uInt16 i = 0;
503 pEntry = (ScOutlineEntry*) aCollections[nSubLevel].At(i);
504 while (pEntry)
505 {
506 if (pEntry->GetStart() >= nStart && pEntry->GetEnd() <= nEnd)
507 {
508 pEntry->SetVisible(bValue);
509
510 if (bSkipHidden)
511 if (!pEntry->IsHidden())
512 SetVisibleBelow( nSubLevel, i, bValue, sal_True );
513 }
514
515 ++i;
516 pEntry = (ScOutlineEntry*) aCollections[nSubLevel].At(i);
517 }
518
519 if (bSkipHidden)
520 nSubLevel = nDepth; // Abbruch
521 }
522 }
523 }
524
GetRange(SCCOLROW & rStart,SCCOLROW & rEnd) const525 void ScOutlineArray::GetRange( SCCOLROW& rStart, SCCOLROW& rEnd ) const
526 {
527 sal_uInt16 nCount = aCollections[0].GetCount();
528 if (nCount)
529 {
530 rStart = ((ScOutlineEntry*) aCollections[0].At(0))->GetStart();
531 rEnd = ((ScOutlineEntry*) aCollections[0].At(nCount-1))->GetEnd();
532 }
533 else
534 rStart = rEnd = 0;
535 }
536
ExtendBlock(sal_uInt16 nLevel,SCCOLROW & rBlkStart,SCCOLROW & rBlkEnd)537 void ScOutlineArray::ExtendBlock( sal_uInt16 nLevel, SCCOLROW& rBlkStart, SCCOLROW& rBlkEnd )
538 {
539 sal_uInt16 nCount;
540 SCCOLROW nStart;
541 SCCOLROW nEnd;
542 sal_uInt16 i;
543 ScOutlineEntry* pEntry;
544
545 nCount = GetCount(nLevel);
546 for ( i=0; i<nCount; i++ )
547 {
548 pEntry = (ScOutlineEntry*) aCollections[nLevel].At(i);
549 nStart = pEntry->GetStart();
550 nEnd = pEntry->GetEnd();
551
552 if ( rBlkStart<=nEnd && rBlkEnd>=nStart )
553 {
554 if (nStart<rBlkStart) rBlkStart = nStart;
555 if (nEnd>rBlkEnd) rBlkEnd = nEnd;
556 }
557 }
558 }
559
TestInsertSpace(SCSIZE nSize,SCCOLROW nMaxVal) const560 sal_Bool ScOutlineArray::TestInsertSpace( SCSIZE nSize, SCCOLROW nMaxVal ) const
561 {
562 sal_uInt16 nCount = aCollections[0].GetCount();
563 if (nCount)
564 {
565 SCCOLROW nEnd = ((ScOutlineEntry*) aCollections[0].At(nCount-1))->GetEnd();
566 return ( sal::static_int_cast<SCCOLROW>(nEnd+nSize) <= nMaxVal );
567 }
568
569 return sal_True;
570 }
571
InsertSpace(SCCOLROW nStartPos,SCSIZE nSize)572 void ScOutlineArray::InsertSpace( SCCOLROW nStartPos, SCSIZE nSize )
573 {
574 ScSubOutlineIterator aIter( this );
575 ScOutlineEntry* pEntry;
576 while((pEntry=aIter.GetNext())!=NULL)
577 {
578 if ( pEntry->GetStart() >= nStartPos )
579 pEntry->Move(static_cast<SCsCOLROW>(nSize));
580 else
581 {
582 SCCOLROW nEnd = pEntry->GetEnd();
583 // immer erweitern, wenn innerhalb der Gruppe eingefuegt
584 // beim Einfuegen am Ende nur, wenn die Gruppe nicht ausgeblendet ist
585 if ( nEnd >= nStartPos || ( nEnd+1 >= nStartPos && !pEntry->IsHidden() ) )
586 {
587 SCSIZE nEntrySize = pEntry->GetSize();
588 nEntrySize += nSize;
589 pEntry->SetSize( nEntrySize );
590 }
591 }
592 }
593 }
594
DeleteSpace(SCCOLROW nStartPos,SCSIZE nSize)595 sal_Bool ScOutlineArray::DeleteSpace( SCCOLROW nStartPos, SCSIZE nSize )
596 {
597 SCCOLROW nEndPos = nStartPos + nSize - 1;
598 sal_Bool bNeedSave = sal_False; // Original fuer Undo benoetigt?
599 sal_Bool bChanged = sal_False; // fuer Test auf Level
600
601 ScSubOutlineIterator aIter( this );
602 ScOutlineEntry* pEntry;
603 while((pEntry=aIter.GetNext())!=NULL)
604 {
605 SCCOLROW nEntryStart = pEntry->GetStart();
606 SCCOLROW nEntryEnd = pEntry->GetEnd();
607 SCSIZE nEntrySize = pEntry->GetSize();
608
609 if ( nEntryEnd >= nStartPos )
610 {
611 if ( nEntryStart > nEndPos ) // rechts
612 pEntry->Move(-(static_cast<SCsCOLROW>(nSize)));
613 else if ( nEntryStart < nStartPos && nEntryEnd >= nEndPos ) // aussen
614 pEntry->SetSize( nEntrySize-nSize );
615 else
616 {
617 bNeedSave = sal_True;
618 if ( nEntryStart >= nStartPos && nEntryEnd <= nEndPos ) // innen
619 {
620 aIter.DeleteLast();
621 bChanged = sal_True;
622 }
623 else if ( nEntryStart >= nStartPos ) // rechts ueber
624 pEntry->SetPosSize( nStartPos, static_cast<SCSIZE>(nEntryEnd-nEndPos) );
625 else // links ueber
626 pEntry->SetSize( static_cast<SCSIZE>(nStartPos-nEntryStart) );
627 }
628 }
629 }
630
631 if (bChanged)
632 DecDepth();
633
634 return bNeedSave;
635 }
636
ManualAction(SCCOLROW nStartPos,SCCOLROW nEndPos,bool bShow,ScTable & rTable,bool bCol)637 bool ScOutlineArray::ManualAction( SCCOLROW nStartPos, SCCOLROW nEndPos, bool bShow, ScTable& rTable, bool bCol )
638 {
639 bool bModified = false;
640 ScSubOutlineIterator aIter( this );
641 ScOutlineEntry* pEntry;
642 while((pEntry=aIter.GetNext())!=NULL)
643 {
644 SCCOLROW nEntryStart = pEntry->GetStart();
645 SCCOLROW nEntryEnd = pEntry->GetEnd();
646
647 if (nEntryEnd>=nStartPos && nEntryStart<=nEndPos)
648 {
649 if ( pEntry->IsHidden() == bShow )
650 {
651 // #i12341# hide if all columns/rows are hidden, show if at least one
652 // is visible
653 SCCOLROW nEnd = rTable.LastHiddenColRow(nEntryStart, bCol);
654 bool bAllHidden = (nEntryEnd <= nEnd && nEnd <
655 ::std::numeric_limits<SCCOLROW>::max());
656
657 bool bToggle = ( bShow != bAllHidden );
658 if ( bToggle )
659 {
660 pEntry->SetHidden( !bShow );
661 SetVisibleBelow( aIter.LastLevel(), aIter.LastEntry(), bShow, bShow );
662 bModified = true;
663 }
664 }
665 }
666 }
667 return bModified;
668 }
669
RemoveAll()670 void ScOutlineArray::RemoveAll()
671 {
672 for (sal_uInt16 nLevel=0; nLevel<nDepth; nLevel++)
673 aCollections[nLevel].FreeAll();
674
675 nDepth = 0;
676 }
677
678 //------------------------------------------------------------------------
679
ScOutlineTable()680 ScOutlineTable::ScOutlineTable()
681 {
682 }
683
ScOutlineTable(const ScOutlineTable & rOutline)684 ScOutlineTable::ScOutlineTable( const ScOutlineTable& rOutline ) :
685 aColOutline( rOutline.aColOutline ),
686 aRowOutline( rOutline.aRowOutline )
687 {
688 }
689
TestInsertCol(SCSIZE nSize)690 sal_Bool ScOutlineTable::TestInsertCol( SCSIZE nSize )
691 {
692 return aColOutline.TestInsertSpace( nSize, MAXCOL );
693 }
694
InsertCol(SCCOL nStartCol,SCSIZE nSize)695 void ScOutlineTable::InsertCol( SCCOL nStartCol, SCSIZE nSize )
696 {
697 aColOutline.InsertSpace( nStartCol, nSize );
698 }
699
DeleteCol(SCCOL nStartCol,SCSIZE nSize)700 sal_Bool ScOutlineTable::DeleteCol( SCCOL nStartCol, SCSIZE nSize )
701 {
702 return aColOutline.DeleteSpace( nStartCol, nSize );
703 }
704
TestInsertRow(SCSIZE nSize)705 sal_Bool ScOutlineTable::TestInsertRow( SCSIZE nSize )
706 {
707 return aRowOutline.TestInsertSpace( nSize, MAXROW );
708 }
709
InsertRow(SCROW nStartRow,SCSIZE nSize)710 void ScOutlineTable::InsertRow( SCROW nStartRow, SCSIZE nSize )
711 {
712 aRowOutline.InsertSpace( nStartRow, nSize );
713 }
714
DeleteRow(SCROW nStartRow,SCSIZE nSize)715 sal_Bool ScOutlineTable::DeleteRow( SCROW nStartRow, SCSIZE nSize )
716 {
717 return aRowOutline.DeleteSpace( nStartRow, nSize );
718 }
719
720 //------------------------------------------------------------------------
721
ScSubOutlineIterator(ScOutlineArray * pOutlineArray)722 ScSubOutlineIterator::ScSubOutlineIterator( ScOutlineArray* pOutlineArray ) :
723 pArray( pOutlineArray ),
724 nStart( 0 ),
725 nEnd( SCCOLROW_MAX ), // alle durchgehen
726 nSubLevel( 0 ),
727 nSubEntry( 0 )
728 {
729 nDepth = pArray->nDepth;
730 }
731
ScSubOutlineIterator(ScOutlineArray * pOutlineArray,sal_uInt16 nLevel,sal_uInt16 nEntry)732 ScSubOutlineIterator::ScSubOutlineIterator( ScOutlineArray* pOutlineArray,
733 sal_uInt16 nLevel, sal_uInt16 nEntry ) :
734 pArray( pOutlineArray )
735 {
736 ScOutlineEntry* pEntry = (ScOutlineEntry*) pArray->aCollections[nLevel].At(nEntry);
737 nStart = pEntry->GetStart();
738 nEnd = pEntry->GetEnd();
739 nSubLevel = nLevel + 1;
740 nSubEntry = 0;
741 nDepth = pArray->nDepth;
742 }
743
GetNext()744 ScOutlineEntry* ScSubOutlineIterator::GetNext()
745 {
746 ScOutlineEntry* pEntry;
747 sal_Bool bFound = sal_False;
748 do
749 {
750 if (nSubLevel >= nDepth)
751 return NULL;
752
753 pEntry = (ScOutlineEntry*) pArray->aCollections[nSubLevel].At(nSubEntry);
754 if (!pEntry)
755 {
756 nSubEntry = 0;
757 ++nSubLevel;
758 }
759 else
760 {
761 if ( pEntry->GetStart() >= nStart && pEntry->GetEnd() <= nEnd )
762 bFound = sal_True;
763 ++nSubEntry;
764 }
765 }
766 while (!bFound);
767 return pEntry; // nSubLevel gueltig, wenn pEntry != 0
768 }
769
LastLevel() const770 sal_uInt16 ScSubOutlineIterator::LastLevel() const
771 {
772 return nSubLevel;
773 }
774
LastEntry() const775 sal_uInt16 ScSubOutlineIterator::LastEntry() const
776 {
777 if (nSubEntry == 0)
778 {
779 DBG_ERROR("ScSubOutlineIterator::LastEntry vor GetNext");
780 return 0;
781 }
782 return nSubEntry-1;
783 }
784
DeleteLast()785 void ScSubOutlineIterator::DeleteLast()
786 {
787 if (nSubLevel >= nDepth)
788 {
789 DBG_ERROR("ScSubOutlineIterator::DeleteLast nach Ende");
790 return;
791 }
792 if (nSubEntry == 0)
793 {
794 DBG_ERROR("ScSubOutlineIterator::DeleteLast vor GetNext");
795 return;
796 }
797
798 --nSubEntry;
799 pArray->aCollections[nSubLevel].AtFree(nSubEntry);
800 }
801
802
803