xref: /trunk/main/sc/source/core/data/olinetab.cxx (revision b3f79822)
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