blob: d297e096fc786f362ffc2edbc52b92ba412efa55 [file] [log] [blame]
/**************************************************************
*
* 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"
#include <string.h>
#include <tools/stream.hxx>
#include <unotools/transliterationwrapper.hxx>
#include "rechead.hxx"
#include "collect.hxx"
#include "document.hxx" // fuer TypedStrData Konstruktor
// -----------------------------------------------------------------------
ScDataObject::~ScDataObject()
{
}
//------------------------------------------------------------------------
// Collection
//------------------------------------------------------------------------
void lcl_DeleteScDataObjects( ScDataObject** p, sal_uInt16 nCount )
{
if ( p )
{
for (sal_uInt16 i = 0; i < nCount; i++) delete p[i];
delete[] p;
p = NULL;
}
}
ScCollection::ScCollection(sal_uInt16 nLim, sal_uInt16 nDel) :
nCount ( 0 ),
nLimit ( nLim ),
nDelta ( nDel ),
pItems ( NULL )
{
if (nDelta > MAXDELTA)
nDelta = MAXDELTA;
else if (nDelta == 0)
nDelta = 1;
if (nLimit > MAXCOLLECTIONSIZE)
nLimit = MAXCOLLECTIONSIZE;
else if (nLimit < nDelta)
nLimit = nDelta;
pItems = new ScDataObject*[nLimit];
}
ScCollection::ScCollection(const ScCollection& rCollection)
: ScDataObject(),
nCount ( 0 ),
nLimit ( 0 ),
nDelta ( 0 ),
pItems ( NULL )
{
*this = rCollection;
}
//------------------------------------------------------------------------
ScCollection::~ScCollection()
{
lcl_DeleteScDataObjects( pItems, nCount );
}
//------------------------------------------------------------------------
sal_uInt16 ScCollection::GetCount() const { return nCount; }
void ScCollection::AtFree(sal_uInt16 nIndex)
{
if ((pItems) && (nIndex < nCount))
{
delete pItems[nIndex];
--nCount; // before memmove
memmove ( &pItems[nIndex], &pItems[nIndex + 1], (nCount - nIndex) * sizeof(ScDataObject*));
pItems[nCount] = NULL;
}
}
//------------------------------------------------------------------------
void ScCollection::Free(ScDataObject* pScDataObject)
{
AtFree(IndexOf(pScDataObject));
}
//------------------------------------------------------------------------
void ScCollection::FreeAll()
{
lcl_DeleteScDataObjects( pItems, nCount );
nCount = 0;
pItems = new ScDataObject*[nLimit];
}
//------------------------------------------------------------------------
sal_Bool ScCollection::AtInsert(sal_uInt16 nIndex, ScDataObject* pScDataObject)
{
if ((nCount < MAXCOLLECTIONSIZE) && (nIndex <= nCount) && pItems)
{
if (nCount == nLimit)
{
ScDataObject** pNewItems = new ScDataObject*[nLimit + nDelta];
if (!pNewItems)
return sal_False;
nLimit = sal::static_int_cast<sal_uInt16>( nLimit + nDelta );
memmove(pNewItems, pItems, nCount * sizeof(ScDataObject*));
delete[] pItems;
pItems = pNewItems;
}
if (nCount > nIndex)
memmove(&pItems[nIndex + 1], &pItems[nIndex], (nCount - nIndex) * sizeof(ScDataObject*));
pItems[nIndex] = pScDataObject;
nCount++;
return sal_True;
}
return sal_False;
}
//------------------------------------------------------------------------
sal_Bool ScCollection::Insert(ScDataObject* pScDataObject)
{
return AtInsert(nCount, pScDataObject);
}
//------------------------------------------------------------------------
ScDataObject* ScCollection::At(sal_uInt16 nIndex) const
{
if (nIndex < nCount)
return pItems[nIndex];
else
return NULL;
}
//------------------------------------------------------------------------
sal_uInt16 ScCollection::IndexOf(ScDataObject* pScDataObject) const
{
sal_uInt16 nIndex = 0xffff;
for (sal_uInt16 i = 0; ((i < nCount) && (nIndex == 0xffff)); i++)
{
if (pItems[i] == pScDataObject) nIndex = i;
}
return nIndex;
}
//------------------------------------------------------------------------
ScCollection& ScCollection::operator=( const ScCollection& r )
{
lcl_DeleteScDataObjects( pItems, nCount );
nCount = r.nCount;
nLimit = r.nLimit;
nDelta = r.nDelta;
pItems = new ScDataObject*[nLimit];
for ( sal_uInt16 i=0; i<nCount; i++ )
pItems[i] = r.pItems[i]->Clone();
return *this;
}
//------------------------------------------------------------------------
ScDataObject* ScCollection::Clone() const
{
return new ScCollection(*this);
}
//------------------------------------------------------------------------
// ScSortedCollection
//------------------------------------------------------------------------
ScSortedCollection::ScSortedCollection(sal_uInt16 nLim, sal_uInt16 nDel, sal_Bool bDup) :
ScCollection (nLim, nDel),
bDuplicates ( bDup)
{
}
//------------------------------------------------------------------------
sal_uInt16 ScSortedCollection::IndexOf(ScDataObject* pScDataObject) const
{
sal_uInt16 nIndex;
if (Search(pScDataObject, nIndex))
return nIndex;
else
return 0xffff;
}
//------------------------------------------------------------------------
sal_Bool ScSortedCollection::Search(ScDataObject* pScDataObject, sal_uInt16& rIndex) const
{
rIndex = nCount;
sal_Bool bFound = sal_False;
short nLo = 0;
short nHi = nCount - 1;
short nIndex;
short nCompare;
while (nLo <= nHi)
{
nIndex = (nLo + nHi) / 2;
nCompare = Compare(pItems[nIndex], pScDataObject);
if (nCompare < 0)
nLo = nIndex + 1;
else
{
nHi = nIndex - 1;
if (nCompare == 0)
{
bFound = sal_True;
nLo = nIndex;
}
}
}
rIndex = nLo;
return bFound;
}
//------------------------------------------------------------------------
sal_Bool ScSortedCollection::Insert(ScDataObject* pScDataObject)
{
sal_uInt16 nIndex;
sal_Bool bFound = Search(pScDataObject, nIndex);
if (bFound)
{
if (bDuplicates)
return AtInsert(nIndex, pScDataObject);
else
return sal_False;
}
else
return AtInsert(nIndex, pScDataObject);
}
//------------------------------------------------------------------------
sal_Bool ScSortedCollection::InsertPos(ScDataObject* pScDataObject, sal_uInt16& nIndex)
{
sal_Bool bFound = Search(pScDataObject, nIndex);
if (bFound)
{
if (bDuplicates)
return AtInsert(nIndex, pScDataObject);
else
return sal_False;
}
else
return AtInsert(nIndex, pScDataObject);
}
//------------------------------------------------------------------------
sal_Bool ScSortedCollection::operator==(const ScSortedCollection& rCmp) const
{
if ( nCount != rCmp.nCount )
return sal_False;
for (sal_uInt16 i=0; i<nCount; i++)
if ( !IsEqual(pItems[i],rCmp.pItems[i]) )
return sal_False;
return sal_True;
}
//------------------------------------------------------------------------
// IsEqual - komplette Inhalte vergleichen
sal_Bool ScSortedCollection::IsEqual(ScDataObject* pKey1, ScDataObject* pKey2) const
{
return ( Compare(pKey1, pKey2) == 0 ); // Default: nur Index vergleichen
}
//------------------------------------------------------------------------
ScDataObject* StrData::Clone() const
{
return new StrData(*this);
}
//------------------------------------------------------------------------
short ScStrCollection::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const
{
StringCompare eComp = ((StrData*)pKey1)->aStr.CompareTo(((StrData*)pKey2)->aStr);
if (eComp == COMPARE_EQUAL)
return 0;
else if (eComp == COMPARE_LESS)
return -1;
else
return 1;
}
//------------------------------------------------------------------------
ScDataObject* ScStrCollection::Clone() const
{
return new ScStrCollection(*this);
}
//------------------------------------------------------------------------
// TypedScStrCollection
//------------------------------------------------------------------------
//UNUSED2008-05 TypedStrData::TypedStrData( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab,
//UNUSED2008-05 sal_Bool bAllStrings )
//UNUSED2008-05 {
//UNUSED2008-05 if ( pDoc->HasValueData( nCol, nRow, nTab ) )
//UNUSED2008-05 {
//UNUSED2008-05 pDoc->GetValue( nCol, nRow, nTab, nValue );
//UNUSED2008-05 if (bAllStrings)
//UNUSED2008-05 pDoc->GetString( nCol, nRow, nTab, aStrValue );
//UNUSED2008-05 nStrType = 0;
//UNUSED2008-05 }
//UNUSED2008-05 else
//UNUSED2008-05 {
//UNUSED2008-05 pDoc->GetString( nCol, nRow, nTab, aStrValue );
//UNUSED2008-05 nValue = 0.0;
//UNUSED2008-05 nStrType = 1; //! Typ uebergeben ?
//UNUSED2008-05 }
//UNUSED2008-05 }
ScDataObject* TypedStrData::Clone() const
{
return new TypedStrData(*this);
}
TypedScStrCollection::TypedScStrCollection( sal_uInt16 nLim , sal_uInt16 nDel , sal_Bool bDup )
: ScSortedCollection( nLim, nDel, bDup )
{
bCaseSensitive = sal_False;
}
TypedScStrCollection::~TypedScStrCollection()
{}
ScDataObject* TypedScStrCollection::Clone() const
{
return new TypedScStrCollection(*this);
}
TypedStrData* TypedScStrCollection::operator[]( const sal_uInt16 nIndex) const
{
return (TypedStrData*)At(nIndex);
}
void TypedScStrCollection::SetCaseSensitive( sal_Bool bSet )
{
bCaseSensitive = bSet;
}
short TypedScStrCollection::Compare( ScDataObject* pKey1, ScDataObject* pKey2 ) const
{
short nResult = 0;
if ( pKey1 && pKey2 )
{
TypedStrData& rData1 = (TypedStrData&)*pKey1;
TypedStrData& rData2 = (TypedStrData&)*pKey2;
if ( rData1.nStrType > rData2.nStrType )
nResult = 1;
else if ( rData1.nStrType < rData2.nStrType )
nResult = -1;
else if ( !rData1.nStrType /* && !rData2.nStrType */ )
{
//--------------------
// Zahlen vergleichen:
//--------------------
if ( rData1.nValue == rData2.nValue )
nResult = 0;
else if ( rData1.nValue < rData2.nValue )
nResult = -1;
else
nResult = 1;
}
else /* if ( rData1.nStrType && rData2.nStrType ) */
{
//---------------------
// Strings vergleichen:
//---------------------
if ( bCaseSensitive )
nResult = (short) ScGlobal::GetCaseTransliteration()->compareString(
rData1.aStrValue, rData2.aStrValue );
else
nResult = (short) ScGlobal::GetpTransliteration()->compareString(
rData1.aStrValue, rData2.aStrValue );
}
}
return nResult;
}
sal_Bool TypedScStrCollection::FindText( const String& rStart, String& rResult,
sal_uInt16& rPos, sal_Bool bBack ) const
{
// Die Collection ist nach String-Vergleichen sortiert, darum muss hier
// alles durchsucht werden
sal_Bool bFound = sal_False;
String aOldResult;
if ( rPos != SCPOS_INVALID && rPos < nCount )
{
TypedStrData* pData = (TypedStrData*) pItems[rPos];
if (pData->nStrType)
aOldResult = pData->aStrValue;
}
if ( bBack ) // rueckwaerts
{
sal_uInt16 nStartPos = nCount;
if ( rPos != SCPOS_INVALID )
nStartPos = rPos; // weitersuchen...
for ( sal_uInt16 i=nStartPos; i>0; )
{
--i;
TypedStrData* pData = (TypedStrData*) pItems[i];
if (pData->nStrType)
{
if ( ScGlobal::GetpTransliteration()->isMatch( rStart, pData->aStrValue ) )
{
// If the collection is case sensitive, it may contain several entries
// that are equal when compared case-insensitive. They are skipped here.
if ( !bCaseSensitive || !aOldResult.Len() ||
!ScGlobal::GetpTransliteration()->isEqual(
pData->aStrValue, aOldResult ) )
{
rResult = pData->aStrValue;
rPos = i;
bFound = sal_True;
break;
}
}
}
}
}
else // vorwaerts
{
sal_uInt16 nStartPos = 0;
if ( rPos != SCPOS_INVALID )
nStartPos = rPos + 1; // weitersuchen...
for ( sal_uInt16 i=nStartPos; i<nCount; i++ )
{
TypedStrData* pData = (TypedStrData*) pItems[i];
if (pData->nStrType)
{
if ( ScGlobal::GetpTransliteration()->isMatch( rStart, pData->aStrValue ) )
{
// If the collection is case sensitive, it may contain several entries
// that are equal when compared case-insensitive. They are skipped here.
if ( !bCaseSensitive || !aOldResult.Len() ||
!ScGlobal::GetpTransliteration()->isEqual(
pData->aStrValue, aOldResult ) )
{
rResult = pData->aStrValue;
rPos = i;
bFound = sal_True;
break;
}
}
}
}
}
return bFound;
}
// Gross-/Kleinschreibung anpassen
sal_Bool TypedScStrCollection::GetExactMatch( String& rString ) const
{
for (sal_uInt16 i=0; i<nCount; i++)
{
TypedStrData* pData = (TypedStrData*) pItems[i];
if ( pData->nStrType && ScGlobal::GetpTransliteration()->isEqual(
pData->aStrValue, rString ) )
{
rString = pData->aStrValue; // String anpassen
return sal_True;
}
}
return sal_False;
}