| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sc.hxx" |
| |
| // System - Includes ----------------------------------------------------- |
| |
| |
| |
| #include <tools/debug.hxx> |
| #include <limits.h> |
| |
| // INCLUDE --------------------------------------------------------------- |
| |
| #include "olinetab.hxx" |
| #include "global.hxx" |
| #include "rechead.hxx" |
| #include "address.hxx" |
| #include "table.hxx" |
| |
| //------------------------------------------------------------------------ |
| |
| ScOutlineEntry::ScOutlineEntry( SCCOLROW nNewStart, SCCOLROW nNewSize, bool bNewHidden ) : |
| nStart ( nNewStart ), |
| nSize ( nNewSize ), |
| bHidden ( bNewHidden ), |
| bVisible( sal_True ) |
| { |
| } |
| |
| ScOutlineEntry::ScOutlineEntry( const ScOutlineEntry& rEntry ) : |
| ScDataObject(), |
| nStart ( rEntry.nStart ), |
| nSize ( rEntry.nSize ), |
| bHidden ( rEntry.bHidden ), |
| bVisible( rEntry.bVisible ) |
| { |
| } |
| |
| ScDataObject* ScOutlineEntry::Clone() const |
| { |
| return new ScOutlineEntry( *this ); |
| } |
| |
| void ScOutlineEntry::Move( SCsCOLROW nDelta ) |
| { |
| SCCOLROW nNewPos = nStart + nDelta; |
| if (nNewPos<0) |
| { |
| DBG_ERROR("OutlineEntry < 0"); |
| nNewPos = 0; |
| } |
| nStart = nNewPos; |
| } |
| |
| void ScOutlineEntry::SetSize( SCSIZE nNewSize ) |
| { |
| if (nNewSize>0) |
| nSize = nNewSize; |
| else |
| { |
| DBG_ERROR("ScOutlineEntry Size == 0"); |
| } |
| } |
| |
| void ScOutlineEntry::SetPosSize( SCCOLROW nNewPos, SCSIZE nNewSize ) |
| { |
| nStart = nNewPos; |
| SetSize( nNewSize ); |
| } |
| |
| void ScOutlineEntry::SetHidden( bool bNewHidden ) |
| { |
| bHidden = bNewHidden; |
| } |
| |
| void ScOutlineEntry::SetVisible( bool bNewVisible ) |
| { |
| bVisible = bNewVisible; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| ScOutlineCollection::ScOutlineCollection() : |
| ScSortedCollection( 4,4,sal_False ) |
| { |
| } |
| |
| inline short IntCompare( SCCOLROW nX, SCCOLROW nY ) |
| { |
| if ( nX==nY ) return 0; |
| else if ( nX<nY ) return -1; |
| else return 1; |
| } |
| |
| short ScOutlineCollection::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const |
| { |
| return IntCompare( ((ScOutlineEntry*)pKey1)->GetStart(), |
| ((ScOutlineEntry*)pKey2)->GetStart() ); |
| } |
| |
| sal_uInt16 ScOutlineCollection::FindStart( SCCOLROW nMinStart ) |
| { |
| //! binaer suchen ? |
| |
| sal_uInt16 nPos = 0; |
| sal_uInt16 nLocalCount = GetCount(); |
| while ( (nPos<nLocalCount) ? (((ScOutlineEntry*)At(nPos))->GetStart() < nMinStart) : sal_False ) |
| ++nPos; |
| |
| return nPos; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| ScOutlineArray::ScOutlineArray() : |
| nDepth( 0 ) |
| { |
| } |
| |
| ScOutlineArray::ScOutlineArray( const ScOutlineArray& rArray ) : |
| nDepth( rArray.nDepth ) |
| { |
| for (sal_uInt16 nLevel=0; nLevel<nDepth; nLevel++) |
| { |
| sal_uInt16 nCount = rArray.aCollections[nLevel].GetCount(); |
| for (sal_uInt16 nEntry=0; nEntry<nCount; nEntry++) |
| { |
| ScOutlineEntry* pEntry = (ScOutlineEntry*) rArray.aCollections[nLevel].At(nEntry); |
| aCollections[nLevel].Insert( new ScOutlineEntry( *pEntry ) ); |
| } |
| } |
| } |
| |
| void ScOutlineArray::FindEntry( SCCOLROW nSearchPos, sal_uInt16& rFindLevel, sal_uInt16& rFindIndex, |
| sal_uInt16 nMaxLevel ) |
| { |
| rFindLevel = rFindIndex = 0; |
| |
| if (nMaxLevel > nDepth) |
| nMaxLevel = nDepth; |
| |
| for (sal_uInt16 nLevel=0; nLevel<nMaxLevel; nLevel++) //! rueckwaerts suchen ? |
| { |
| ScOutlineCollection* pCollect = &aCollections[nLevel]; |
| sal_uInt16 nCount = pCollect->GetCount(); |
| for (sal_uInt16 i=0; i<nCount; i++) |
| { |
| ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i); |
| if ( pEntry->GetStart() <= nSearchPos && pEntry->GetEnd() >= nSearchPos ) |
| { |
| rFindLevel = nLevel + 1; // naechster Level (zum Einfuegen) |
| rFindIndex = i; |
| } |
| } |
| } |
| } |
| |
| sal_Bool ScOutlineArray::Insert( SCCOLROW nStartCol, SCCOLROW nEndCol, sal_Bool& rSizeChanged, |
| sal_Bool bHidden, sal_Bool bVisible ) |
| { |
| rSizeChanged = sal_False; |
| |
| sal_uInt16 nStartLevel; |
| sal_uInt16 nStartIndex; |
| sal_uInt16 nEndLevel; |
| sal_uInt16 nEndIndex; |
| sal_Bool bFound = sal_False; |
| |
| sal_Bool bCont; |
| sal_uInt16 nFindMax; |
| FindEntry( nStartCol, nStartLevel, nStartIndex ); // nLevel = neuer Level (alter+1) !!! |
| FindEntry( nEndCol, nEndLevel, nEndIndex ); |
| nFindMax = Max(nStartLevel,nEndLevel); |
| do |
| { |
| bCont = sal_False; |
| |
| if ( nStartLevel == nEndLevel && nStartIndex == nEndIndex && nStartLevel < SC_OL_MAXDEPTH ) |
| bFound = sal_True; |
| |
| if (!bFound) |
| { |
| if (nFindMax>0) |
| { |
| --nFindMax; |
| if (nStartLevel) |
| if ( ((ScOutlineEntry*)aCollections[nStartLevel-1].At(nStartIndex))-> |
| GetStart() == nStartCol ) |
| FindEntry( nStartCol, nStartLevel, nStartIndex, nFindMax ); |
| if (nEndLevel) |
| if ( ((ScOutlineEntry*)aCollections[nEndLevel-1].At(nEndIndex))-> |
| GetEnd() == nEndCol ) |
| FindEntry( nEndCol, nEndLevel, nEndIndex, nFindMax ); |
| bCont = sal_True; |
| } |
| } |
| } |
| while ( !bFound && bCont ); |
| |
| if (!bFound) |
| return sal_False; |
| |
| sal_uInt16 nLevel = nStartLevel; |
| |
| // untere verschieben |
| |
| sal_Bool bNeedSize = sal_False; |
| for ( short nMoveLevel = nDepth-1; nMoveLevel >= (short) nLevel; nMoveLevel-- ) |
| { |
| sal_uInt16 nCount = aCollections[nMoveLevel].GetCount(); |
| sal_Bool bMoved = sal_False; |
| for ( sal_uInt16 i=0; i<nCount; i += bMoved ? 0 : 1 ) |
| { |
| ScOutlineEntry* pEntry = (ScOutlineEntry*) aCollections[nMoveLevel].At(i); |
| SCCOLROW nEntryStart = pEntry->GetStart(); |
| if ( nEntryStart >= nStartCol && nEntryStart <= nEndCol ) |
| { |
| if (nMoveLevel >= SC_OL_MAXDEPTH - 1) |
| { |
| rSizeChanged = sal_False; // kein Platz |
| return sal_False; |
| } |
| aCollections[nMoveLevel+1].Insert( new ScOutlineEntry( *pEntry ) ); |
| aCollections[nMoveLevel].AtFree( i ); |
| nCount = aCollections[nMoveLevel].GetCount(); |
| bMoved = sal_True; |
| if (nMoveLevel == (short) nDepth - 1) |
| bNeedSize = sal_True; |
| } |
| else |
| bMoved = sal_False; |
| } |
| } |
| |
| if (bNeedSize) |
| { |
| ++nDepth; |
| rSizeChanged = sal_True; |
| } |
| |
| if (nDepth <= nLevel) |
| { |
| nDepth = nLevel+1; |
| rSizeChanged = sal_True; |
| } |
| |
| /* nicht zusammenfassen! |
| |
| // zusammenfassen |
| |
| sal_uInt16 nCount = aCollections[nLevel].GetCount(); |
| sal_uInt16 nIndex; |
| bFound = sal_False; |
| for ( nIndex=0; nIndex<nCount && !bFound; nIndex++ ) |
| { |
| if ( ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetEnd() + 1 == nStartCol ) |
| { |
| nStartCol = ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetStart(); |
| aCollections[nLevel].AtFree(nIndex); |
| nCount = aCollections[nLevel].GetCount(); // Daten geaendert |
| bFound = sal_True; |
| } |
| } |
| |
| bFound = sal_False; |
| for ( nIndex=0; nIndex<nCount && !bFound; nIndex++ ) |
| { |
| if ( ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetStart() == nEndCol + 1 ) |
| { |
| nEndCol = ((ScOutlineEntry*) aCollections[nLevel].At(nIndex))->GetEnd(); |
| aCollections[nLevel].AtFree(nIndex); |
| bFound = sal_True; |
| } |
| } |
| */ |
| ScOutlineEntry* pNewEntry = new ScOutlineEntry( nStartCol, nEndCol+1-nStartCol, bHidden ); |
| pNewEntry->SetVisible( bVisible ); |
| aCollections[nLevel].Insert( pNewEntry ); |
| |
| return sal_True; |
| } |
| |
| sal_Bool ScOutlineArray::FindTouchedLevel( SCCOLROW nBlockStart, SCCOLROW nBlockEnd, sal_uInt16& rFindLevel ) const |
| { |
| sal_Bool bFound = sal_False; |
| rFindLevel = 0; |
| |
| for (sal_uInt16 nLevel=0; nLevel<nDepth; nLevel++) |
| { |
| const ScOutlineCollection* pCollect = &aCollections[nLevel]; |
| sal_uInt16 nCount = pCollect->GetCount(); |
| for (sal_uInt16 i=0; i<nCount; i++) |
| { |
| ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i); |
| SCCOLROW nStart = pEntry->GetStart(); |
| SCCOLROW nEnd = pEntry->GetEnd(); |
| |
| if ( ( nBlockStart>=nStart && nBlockStart<=nEnd ) || |
| ( nBlockEnd >=nStart && nBlockEnd <=nEnd ) ) |
| { |
| rFindLevel = nLevel; // wirklicher Level |
| bFound = sal_True; |
| } |
| } |
| } |
| |
| return bFound; |
| } |
| |
| void ScOutlineArray::RemoveSub( SCCOLROW nStartPos, SCCOLROW nEndPos, sal_uInt16 nLevel ) |
| { |
| if ( nLevel >= nDepth ) |
| return; |
| ScOutlineCollection* pCollect = &aCollections[nLevel]; |
| sal_uInt16 nCount = pCollect->GetCount(); |
| sal_Bool bFound = sal_False; |
| for ( sal_uInt16 i=0; i<nCount; i += ( bFound ? 0 : 1 ) ) |
| { |
| bFound = sal_False; |
| ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i); |
| SCCOLROW nStart = pEntry->GetStart(); |
| SCCOLROW nEnd = pEntry->GetEnd(); |
| |
| if ( nStart>=nStartPos && nEnd<=nEndPos ) |
| { |
| RemoveSub( nStart, nEnd, nLevel+1 ); |
| pCollect->AtFree(i); |
| nCount = pCollect->GetCount(); |
| bFound = sal_True; |
| } |
| } |
| } |
| |
| void ScOutlineArray::PromoteSub( SCCOLROW nStartPos, SCCOLROW nEndPos, sal_uInt16 nStartLevel ) |
| { |
| if (nStartLevel==0) |
| { |
| DBG_ERROR("PromoteSub mit Level 0"); |
| return; |
| } |
| |
| for (sal_uInt16 nLevel = nStartLevel; nLevel < nDepth; nLevel++) |
| { |
| ScOutlineCollection* pCollect = &aCollections[nLevel]; |
| sal_uInt16 nCount = pCollect->GetCount(); |
| sal_Bool bFound = sal_False; |
| for ( sal_uInt16 i=0; i<nCount; i += ( bFound ? 0 : 1 ) ) |
| { |
| bFound = sal_False; |
| ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i); |
| SCCOLROW nStart = pEntry->GetStart(); |
| SCCOLROW nEnd = pEntry->GetEnd(); |
| |
| if ( nStart>=nStartPos && nEnd<=nEndPos ) |
| { |
| aCollections[nLevel-1].Insert( new ScOutlineEntry( *pEntry ) ); |
| pCollect->AtFree(i); |
| nCount = pCollect->GetCount(); |
| bFound = sal_True; |
| } |
| } |
| } |
| } |
| |
| sal_Bool ScOutlineArray::DecDepth() // nDepth auf leere Levels anpassen |
| { |
| sal_Bool bChanged = sal_False; |
| sal_Bool bCont; |
| do |
| { |
| bCont = sal_False; |
| if (nDepth) |
| if (aCollections[nDepth-1].GetCount() == 0) |
| { |
| --nDepth; |
| bChanged = sal_True; |
| bCont = sal_True; |
| } |
| } |
| while (bCont); |
| return bChanged; |
| } |
| |
| sal_Bool ScOutlineArray::Remove( SCCOLROW nBlockStart, SCCOLROW nBlockEnd, sal_Bool& rSizeChanged ) |
| { |
| sal_uInt16 nLevel; |
| FindTouchedLevel( nBlockStart, nBlockEnd, nLevel ); |
| |
| ScOutlineCollection* pCollect = &aCollections[nLevel]; |
| sal_uInt16 nCount = pCollect->GetCount(); |
| sal_Bool bFound = sal_False; |
| sal_Bool bAny = sal_False; |
| for ( sal_uInt16 i=0; i<nCount; i += ( bFound ? 0 : 1 ) ) |
| { |
| bFound = sal_False; |
| ScOutlineEntry* pEntry = (ScOutlineEntry*) pCollect->At(i); |
| SCCOLROW nStart = pEntry->GetStart(); |
| SCCOLROW nEnd = pEntry->GetEnd(); |
| |
| if ( nBlockStart<=nEnd && nBlockEnd>=nStart ) |
| { |
| // RemoveSub( nStart, nEnd, nLevel+1 ); |
| pCollect->AtFree(i); |
| PromoteSub( nStart, nEnd, nLevel+1 ); |
| nCount = pCollect->GetCount(); |
| i = pCollect->FindStart( nEnd+1 ); |
| bFound = sal_True; |
| bAny = sal_True; |
| } |
| } |
| |
| if (bAny) // Depth anpassen |
| if (DecDepth()) |
| rSizeChanged = sal_True; |
| |
| return bAny; |
| } |
| |
| ScOutlineEntry* ScOutlineArray::GetEntry( sal_uInt16 nLevel, sal_uInt16 nIndex ) const |
| { |
| return (ScOutlineEntry*)((nLevel < nDepth) ? aCollections[nLevel].At(nIndex) : NULL); |
| } |
| |
| sal_uInt16 ScOutlineArray::GetCount( sal_uInt16 nLevel ) const |
| { |
| return (nLevel < nDepth) ? aCollections[nLevel].GetCount() : 0; |
| } |
| |
| ScOutlineEntry* ScOutlineArray::GetEntryByPos( sal_uInt16 nLevel, SCCOLROW nPos ) const |
| { |
| sal_uInt16 nCount = GetCount( nLevel ); |
| ScOutlineEntry* pEntry; |
| |
| for (sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++) |
| { |
| pEntry = GetEntry( nLevel, nIndex ); |
| if ((pEntry->GetStart() <= nPos) && (nPos <= pEntry->GetEnd())) |
| return pEntry; |
| } |
| return NULL; |
| } |
| |
| sal_Bool ScOutlineArray::GetEntryIndex( sal_uInt16 nLevel, SCCOLROW nPos, sal_uInt16& rnIndex ) const |
| { |
| // found entry contains passed position |
| sal_uInt16 nCount = GetCount( nLevel ); |
| for ( rnIndex = 0; rnIndex < nCount; ++rnIndex ) |
| { |
| const ScOutlineEntry* pEntry = GetEntry( nLevel, rnIndex ); |
| if ( (pEntry->GetStart() <= nPos) && (nPos <= pEntry->GetEnd()) ) |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| sal_Bool ScOutlineArray::GetEntryIndexInRange( |
| sal_uInt16 nLevel, SCCOLROW nBlockStart, SCCOLROW nBlockEnd, sal_uInt16& rnIndex ) const |
| { |
| // found entry will be completely inside of passed range |
| sal_uInt16 nCount = GetCount( nLevel ); |
| for ( rnIndex = 0; rnIndex < nCount; ++rnIndex ) |
| { |
| const ScOutlineEntry* pEntry = GetEntry( nLevel, rnIndex ); |
| if ( (nBlockStart <= pEntry->GetStart()) && (pEntry->GetEnd() <= nBlockEnd) ) |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| void ScOutlineArray::SetVisibleBelow( sal_uInt16 nLevel, sal_uInt16 nEntry, sal_Bool bValue, sal_Bool bSkipHidden ) |
| { |
| ScOutlineEntry* pEntry = GetEntry( nLevel, nEntry ); |
| if( pEntry ) |
| { |
| SCCOLROW nStart = pEntry->GetStart(); |
| SCCOLROW nEnd = pEntry->GetEnd(); |
| |
| for (sal_uInt16 nSubLevel=nLevel+1; nSubLevel<nDepth; nSubLevel++) |
| { |
| sal_uInt16 i = 0; |
| pEntry = (ScOutlineEntry*) aCollections[nSubLevel].At(i); |
| while (pEntry) |
| { |
| if (pEntry->GetStart() >= nStart && pEntry->GetEnd() <= nEnd) |
| { |
| pEntry->SetVisible(bValue); |
| |
| if (bSkipHidden) |
| if (!pEntry->IsHidden()) |
| SetVisibleBelow( nSubLevel, i, bValue, sal_True ); |
| } |
| |
| ++i; |
| pEntry = (ScOutlineEntry*) aCollections[nSubLevel].At(i); |
| } |
| |
| if (bSkipHidden) |
| nSubLevel = nDepth; // Abbruch |
| } |
| } |
| } |
| |
| void ScOutlineArray::GetRange( SCCOLROW& rStart, SCCOLROW& rEnd ) const |
| { |
| sal_uInt16 nCount = aCollections[0].GetCount(); |
| if (nCount) |
| { |
| rStart = ((ScOutlineEntry*) aCollections[0].At(0))->GetStart(); |
| rEnd = ((ScOutlineEntry*) aCollections[0].At(nCount-1))->GetEnd(); |
| } |
| else |
| rStart = rEnd = 0; |
| } |
| |
| void ScOutlineArray::ExtendBlock( sal_uInt16 nLevel, SCCOLROW& rBlkStart, SCCOLROW& rBlkEnd ) |
| { |
| sal_uInt16 nCount; |
| SCCOLROW nStart; |
| SCCOLROW nEnd; |
| sal_uInt16 i; |
| ScOutlineEntry* pEntry; |
| |
| nCount = GetCount(nLevel); |
| for ( i=0; i<nCount; i++ ) |
| { |
| pEntry = (ScOutlineEntry*) aCollections[nLevel].At(i); |
| nStart = pEntry->GetStart(); |
| nEnd = pEntry->GetEnd(); |
| |
| if ( rBlkStart<=nEnd && rBlkEnd>=nStart ) |
| { |
| if (nStart<rBlkStart) rBlkStart = nStart; |
| if (nEnd>rBlkEnd) rBlkEnd = nEnd; |
| } |
| } |
| } |
| |
| sal_Bool ScOutlineArray::TestInsertSpace( SCSIZE nSize, SCCOLROW nMaxVal ) const |
| { |
| sal_uInt16 nCount = aCollections[0].GetCount(); |
| if (nCount) |
| { |
| SCCOLROW nEnd = ((ScOutlineEntry*) aCollections[0].At(nCount-1))->GetEnd(); |
| return ( sal::static_int_cast<SCCOLROW>(nEnd+nSize) <= nMaxVal ); |
| } |
| |
| return sal_True; |
| } |
| |
| void ScOutlineArray::InsertSpace( SCCOLROW nStartPos, SCSIZE nSize ) |
| { |
| ScSubOutlineIterator aIter( this ); |
| ScOutlineEntry* pEntry; |
| while((pEntry=aIter.GetNext())!=NULL) |
| { |
| if ( pEntry->GetStart() >= nStartPos ) |
| pEntry->Move(static_cast<SCsCOLROW>(nSize)); |
| else |
| { |
| SCCOLROW nEnd = pEntry->GetEnd(); |
| // immer erweitern, wenn innerhalb der Gruppe eingefuegt |
| // beim Einfuegen am Ende nur, wenn die Gruppe nicht ausgeblendet ist |
| if ( nEnd >= nStartPos || ( nEnd+1 >= nStartPos && !pEntry->IsHidden() ) ) |
| { |
| SCSIZE nEntrySize = pEntry->GetSize(); |
| nEntrySize += nSize; |
| pEntry->SetSize( nEntrySize ); |
| } |
| } |
| } |
| } |
| |
| sal_Bool ScOutlineArray::DeleteSpace( SCCOLROW nStartPos, SCSIZE nSize ) |
| { |
| SCCOLROW nEndPos = nStartPos + nSize - 1; |
| sal_Bool bNeedSave = sal_False; // Original fuer Undo benoetigt? |
| sal_Bool bChanged = sal_False; // fuer Test auf Level |
| |
| ScSubOutlineIterator aIter( this ); |
| ScOutlineEntry* pEntry; |
| while((pEntry=aIter.GetNext())!=NULL) |
| { |
| SCCOLROW nEntryStart = pEntry->GetStart(); |
| SCCOLROW nEntryEnd = pEntry->GetEnd(); |
| SCSIZE nEntrySize = pEntry->GetSize(); |
| |
| if ( nEntryEnd >= nStartPos ) |
| { |
| if ( nEntryStart > nEndPos ) // rechts |
| pEntry->Move(-(static_cast<SCsCOLROW>(nSize))); |
| else if ( nEntryStart < nStartPos && nEntryEnd >= nEndPos ) // aussen |
| pEntry->SetSize( nEntrySize-nSize ); |
| else |
| { |
| bNeedSave = sal_True; |
| if ( nEntryStart >= nStartPos && nEntryEnd <= nEndPos ) // innen |
| { |
| aIter.DeleteLast(); |
| bChanged = sal_True; |
| } |
| else if ( nEntryStart >= nStartPos ) // rechts ueber |
| pEntry->SetPosSize( nStartPos, static_cast<SCSIZE>(nEntryEnd-nEndPos) ); |
| else // links ueber |
| pEntry->SetSize( static_cast<SCSIZE>(nStartPos-nEntryStart) ); |
| } |
| } |
| } |
| |
| if (bChanged) |
| DecDepth(); |
| |
| return bNeedSave; |
| } |
| |
| bool ScOutlineArray::ManualAction( SCCOLROW nStartPos, SCCOLROW nEndPos, bool bShow, ScTable& rTable, bool bCol ) |
| { |
| bool bModified = false; |
| ScSubOutlineIterator aIter( this ); |
| ScOutlineEntry* pEntry; |
| while((pEntry=aIter.GetNext())!=NULL) |
| { |
| SCCOLROW nEntryStart = pEntry->GetStart(); |
| SCCOLROW nEntryEnd = pEntry->GetEnd(); |
| |
| if (nEntryEnd>=nStartPos && nEntryStart<=nEndPos) |
| { |
| if ( pEntry->IsHidden() == bShow ) |
| { |
| // #i12341# hide if all columns/rows are hidden, show if at least one |
| // is visible |
| SCCOLROW nEnd = rTable.LastHiddenColRow(nEntryStart, bCol); |
| bool bAllHidden = (nEntryEnd <= nEnd && nEnd < |
| ::std::numeric_limits<SCCOLROW>::max()); |
| |
| bool bToggle = ( bShow != bAllHidden ); |
| if ( bToggle ) |
| { |
| pEntry->SetHidden( !bShow ); |
| SetVisibleBelow( aIter.LastLevel(), aIter.LastEntry(), bShow, bShow ); |
| bModified = true; |
| } |
| } |
| } |
| } |
| return bModified; |
| } |
| |
| void ScOutlineArray::RemoveAll() |
| { |
| for (sal_uInt16 nLevel=0; nLevel<nDepth; nLevel++) |
| aCollections[nLevel].FreeAll(); |
| |
| nDepth = 0; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| ScOutlineTable::ScOutlineTable() |
| { |
| } |
| |
| ScOutlineTable::ScOutlineTable( const ScOutlineTable& rOutline ) : |
| aColOutline( rOutline.aColOutline ), |
| aRowOutline( rOutline.aRowOutline ) |
| { |
| } |
| |
| sal_Bool ScOutlineTable::TestInsertCol( SCSIZE nSize ) |
| { |
| return aColOutline.TestInsertSpace( nSize, MAXCOL ); |
| } |
| |
| void ScOutlineTable::InsertCol( SCCOL nStartCol, SCSIZE nSize ) |
| { |
| aColOutline.InsertSpace( nStartCol, nSize ); |
| } |
| |
| sal_Bool ScOutlineTable::DeleteCol( SCCOL nStartCol, SCSIZE nSize ) |
| { |
| return aColOutline.DeleteSpace( nStartCol, nSize ); |
| } |
| |
| sal_Bool ScOutlineTable::TestInsertRow( SCSIZE nSize ) |
| { |
| return aRowOutline.TestInsertSpace( nSize, MAXROW ); |
| } |
| |
| void ScOutlineTable::InsertRow( SCROW nStartRow, SCSIZE nSize ) |
| { |
| aRowOutline.InsertSpace( nStartRow, nSize ); |
| } |
| |
| sal_Bool ScOutlineTable::DeleteRow( SCROW nStartRow, SCSIZE nSize ) |
| { |
| return aRowOutline.DeleteSpace( nStartRow, nSize ); |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| ScSubOutlineIterator::ScSubOutlineIterator( ScOutlineArray* pOutlineArray ) : |
| pArray( pOutlineArray ), |
| nStart( 0 ), |
| nEnd( SCCOLROW_MAX ), // alle durchgehen |
| nSubLevel( 0 ), |
| nSubEntry( 0 ) |
| { |
| nDepth = pArray->nDepth; |
| } |
| |
| ScSubOutlineIterator::ScSubOutlineIterator( ScOutlineArray* pOutlineArray, |
| sal_uInt16 nLevel, sal_uInt16 nEntry ) : |
| pArray( pOutlineArray ) |
| { |
| ScOutlineEntry* pEntry = (ScOutlineEntry*) pArray->aCollections[nLevel].At(nEntry); |
| nStart = pEntry->GetStart(); |
| nEnd = pEntry->GetEnd(); |
| nSubLevel = nLevel + 1; |
| nSubEntry = 0; |
| nDepth = pArray->nDepth; |
| } |
| |
| ScOutlineEntry* ScSubOutlineIterator::GetNext() |
| { |
| ScOutlineEntry* pEntry; |
| sal_Bool bFound = sal_False; |
| do |
| { |
| if (nSubLevel >= nDepth) |
| return NULL; |
| |
| pEntry = (ScOutlineEntry*) pArray->aCollections[nSubLevel].At(nSubEntry); |
| if (!pEntry) |
| { |
| nSubEntry = 0; |
| ++nSubLevel; |
| } |
| else |
| { |
| if ( pEntry->GetStart() >= nStart && pEntry->GetEnd() <= nEnd ) |
| bFound = sal_True; |
| ++nSubEntry; |
| } |
| } |
| while (!bFound); |
| return pEntry; // nSubLevel gueltig, wenn pEntry != 0 |
| } |
| |
| sal_uInt16 ScSubOutlineIterator::LastLevel() const |
| { |
| return nSubLevel; |
| } |
| |
| sal_uInt16 ScSubOutlineIterator::LastEntry() const |
| { |
| if (nSubEntry == 0) |
| { |
| DBG_ERROR("ScSubOutlineIterator::LastEntry vor GetNext"); |
| return 0; |
| } |
| return nSubEntry-1; |
| } |
| |
| void ScSubOutlineIterator::DeleteLast() |
| { |
| if (nSubLevel >= nDepth) |
| { |
| DBG_ERROR("ScSubOutlineIterator::DeleteLast nach Ende"); |
| return; |
| } |
| if (nSubEntry == 0) |
| { |
| DBG_ERROR("ScSubOutlineIterator::DeleteLast vor GetNext"); |
| return; |
| } |
| |
| --nSubEntry; |
| pArray->aCollections[nSubLevel].AtFree(nSubEntry); |
| } |
| |
| |