Files
libreoffice/sc/source/core/data/markarr.cxx
Thomas Arnhold d8afc8e5e9 Remove superfluous include comments
Change-Id: Ie5792855761b9be209bf3fa2cba9e6998523c982
2012-06-09 04:39:01 +02:00

397 lines
11 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
*
* OpenOffice.org - a multi-platform office productivity suite
*
* This file is part of OpenOffice.org.
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
*
************************************************************************/
#include "markarr.hxx"
#include "global.hxx"
#include "address.hxx"
// STATIC DATA -----------------------------------------------------------
//------------------------------------------------------------------------
ScMarkArray::ScMarkArray() :
nCount( 0 ),
nLimit( 0 ),
pData( NULL )
{
// special case "no marks" with pData = NULL
}
//------------------------------------------------------------------------
ScMarkArray::~ScMarkArray()
{
delete[] pData;
}
//------------------------------------------------------------------------
void ScMarkArray::Reset( sal_Bool bMarked )
{
// always create pData here
// (or have separate method to ensure pData)
delete[] pData;
nCount = nLimit = 1;
pData = new ScMarkEntry[1];
pData[0].nRow = MAXROW;
pData[0].bMarked = bMarked;
}
//------------------------------------------------------------------------
sal_Bool ScMarkArray::Search( SCROW nRow, SCSIZE& nIndex ) const
{
long nHi = static_cast<long>(nCount) - 1;
long i = 0;
sal_Bool bFound = (nCount == 1);
if (pData)
{
long nLo = 0;
long nStartRow = 0;
while ( !bFound && nLo <= nHi )
{
i = (nLo + nHi) / 2;
if (i > 0)
nStartRow = (long) pData[i - 1].nRow;
else
nStartRow = -1;
long nEndRow = (long) pData[i].nRow;
if (nEndRow < (long) nRow)
nLo = ++i;
else
if (nStartRow >= (long) nRow)
nHi = --i;
else
bFound = sal_True;
}
}
else
bFound = false;
if (bFound)
nIndex=(SCSIZE)i;
else
nIndex=0;
return bFound;
}
sal_Bool ScMarkArray::GetMark( SCROW nRow ) const
{
SCSIZE i;
if (Search( nRow, i ))
return pData[i].bMarked;
else
return false;
}
//------------------------------------------------------------------------
void ScMarkArray::SetMarkArea( SCROW nStartRow, SCROW nEndRow, sal_Bool bMarked )
{
if (ValidRow(nStartRow) && ValidRow(nEndRow))
{
if ((nStartRow == 0) && (nEndRow == MAXROW))
{
Reset(bMarked);
}
else
{
if (!pData)
Reset(false); // create pData for further processing - could use special case handling!
SCSIZE nNeeded = nCount + 2;
if ( nLimit < nNeeded )
{
nLimit += SC_MARKARRAY_DELTA;
if ( nLimit < nNeeded )
nLimit = nNeeded;
ScMarkEntry* pNewData = new ScMarkEntry[nLimit];
memcpy( pNewData, pData, nCount*sizeof(ScMarkEntry) );
delete[] pData;
pData = pNewData;
}
SCSIZE ni; // number of entries in beginning
SCSIZE nInsert; // insert position (MAXROW+1 := no insert)
sal_Bool bCombined = false;
sal_Bool bSplit = false;
if ( nStartRow > 0 )
{
// skip beginning
SCSIZE nIndex;
Search( nStartRow, nIndex );
ni = nIndex;
nInsert = MAXROWCOUNT;
if ( pData[ni].bMarked != bMarked )
{
if ( ni == 0 || (pData[ni-1].nRow < nStartRow - 1) )
{ // may be a split or a simple insert or just a shrink,
// row adjustment is done further down
if ( pData[ni].nRow > nEndRow )
bSplit = sal_True;
ni++;
nInsert = ni;
}
else if ( ni > 0 && pData[ni-1].nRow == nStartRow - 1 )
nInsert = ni;
}
if ( ni > 0 && pData[ni-1].bMarked == bMarked )
{ // combine
pData[ni-1].nRow = nEndRow;
nInsert = MAXROWCOUNT;
bCombined = sal_True;
}
}
else
{
nInsert = 0;
ni = 0;
}
SCSIZE nj = ni; // stop position of range to replace
while ( nj < nCount && pData[nj].nRow <= nEndRow )
nj++;
if ( !bSplit )
{
if ( nj < nCount && pData[nj].bMarked == bMarked )
{ // combine
if ( ni > 0 )
{
if ( pData[ni-1].bMarked == bMarked )
{ // adjacent entries
pData[ni-1].nRow = pData[nj].nRow;
nj++;
}
else if ( ni == nInsert )
pData[ni-1].nRow = nStartRow - 1; // shrink
}
nInsert = MAXROWCOUNT;
bCombined = sal_True;
}
else if ( ni > 0 && ni == nInsert )
pData[ni-1].nRow = nStartRow - 1; // shrink
}
if ( ni < nj )
{ // remove middle entries
if ( !bCombined )
{ // replace one entry
pData[ni].nRow = nEndRow;
pData[ni].bMarked = bMarked;
ni++;
nInsert = MAXROWCOUNT;
}
if ( ni < nj )
{ // remove entries
memmove( pData + ni, pData + nj, (nCount - nj) * sizeof(ScMarkEntry) );
nCount -= nj - ni;
}
}
if ( nInsert < sal::static_int_cast<SCSIZE>(MAXROWCOUNT) )
{ // insert or append new entry
if ( nInsert <= nCount )
{
if ( !bSplit )
memmove( pData + nInsert + 1, pData + nInsert,
(nCount - nInsert) * sizeof(ScMarkEntry) );
else
{
memmove( pData + nInsert + 2, pData + nInsert,
(nCount - nInsert) * sizeof(ScMarkEntry) );
pData[nInsert+1] = pData[nInsert-1];
nCount++;
}
}
if ( nInsert )
pData[nInsert-1].nRow = nStartRow - 1;
pData[nInsert].nRow = nEndRow;
pData[nInsert].bMarked = bMarked;
nCount++;
}
}
}
}
sal_Bool ScMarkArray::IsAllMarked( SCROW nStartRow, SCROW nEndRow ) const
{
SCSIZE nStartIndex;
SCSIZE nEndIndex;
if (Search( nStartRow, nStartIndex ))
if (pData[nStartIndex].bMarked)
if (Search( nEndRow, nEndIndex ))
if (nEndIndex==nStartIndex)
return sal_True;
return false;
}
sal_Bool ScMarkArray::HasOneMark( SCROW& rStartRow, SCROW& rEndRow ) const
{
sal_Bool bRet = false;
if ( nCount == 1 )
{
if ( pData[0].bMarked )
{
rStartRow = 0;
rEndRow = MAXROW;
bRet = sal_True;
}
}
else if ( nCount == 2 )
{
if ( pData[0].bMarked )
{
rStartRow = 0;
rEndRow = pData[0].nRow;
}
else
{
rStartRow = pData[0].nRow + 1;
rEndRow = MAXROW;
}
bRet = sal_True;
}
else if ( nCount == 3 )
{
if ( pData[1].bMarked )
{
rStartRow = pData[0].nRow + 1;
rEndRow = pData[1].nRow;
bRet = sal_True;
}
}
return bRet;
}
void ScMarkArray::CopyMarksTo( ScMarkArray& rDestMarkArray ) const
{
delete[] rDestMarkArray.pData;
if (pData)
{
rDestMarkArray.pData = new ScMarkEntry[nCount];
memmove( rDestMarkArray.pData, pData, nCount * sizeof(ScMarkEntry) );
}
else
rDestMarkArray.pData = NULL;
rDestMarkArray.nCount = rDestMarkArray.nLimit = nCount;
}
SCsROW ScMarkArray::GetNextMarked( SCsROW nRow, sal_Bool bUp ) const
{
if (!pData)
const_cast<ScMarkArray*>(this)->Reset(false); // create pData for further processing
SCsROW nRet = nRow;
if (VALIDROW(nRow))
{
SCSIZE nIndex;
Search(nRow, nIndex);
if (!pData[nIndex].bMarked)
{
if (bUp)
{
if (nIndex>0)
nRet = pData[nIndex-1].nRow;
else
nRet = -1;
}
else
nRet = pData[nIndex].nRow + 1;
}
}
return nRet;
}
SCROW ScMarkArray::GetMarkEnd( SCROW nRow, sal_Bool bUp ) const
{
if (!pData)
const_cast<ScMarkArray*>(this)->Reset(false); // create pData for further processing
SCROW nRet;
SCSIZE nIndex;
Search(nRow, nIndex);
OSL_ENSURE( pData[nIndex].bMarked, "GetMarkEnd ohne bMarked" );
if (bUp)
{
if (nIndex>0)
nRet = pData[nIndex-1].nRow + 1;
else
nRet = 0;
}
else
nRet = pData[nIndex].nRow;
return nRet;
}
//
// -------------- Iterator ----------------------------------------------
//
ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) :
pArray( pNewArray ),
nPos( 0 )
{
}
ScMarkArrayIter::~ScMarkArrayIter()
{
}
sal_Bool ScMarkArrayIter::Next( SCROW& rTop, SCROW& rBottom )
{
if ( nPos >= pArray->nCount )
return false;
while (!pArray->pData[nPos].bMarked)
{
++nPos;
if ( nPos >= pArray->nCount )
return false;
}
rBottom = pArray->pData[nPos].nRow;
if (nPos==0)
rTop = 0;
else
rTop = pArray->pData[nPos-1].nRow + 1;
++nPos;
return sal_True;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */