| /************************************************************** |
| * |
| * 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; |
| } |
| |
| |
| |