update dev300-m57
[ooovba.git] / sc / source / core / tool / collect.cxx
blobd5982aa9e73caa8ccb85ddf25ccf4f15f6f23bd0
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: collect.cxx,v $
10 * $Revision: 1.14.32.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 #include <string.h>
37 #include <tools/stream.hxx>
38 #include <unotools/transliterationwrapper.hxx>
40 #include "rechead.hxx"
41 #include "collect.hxx"
42 #include "document.hxx" // fuer TypedStrData Konstruktor
44 // -----------------------------------------------------------------------
46 ScDataObject::~ScDataObject()
50 //------------------------------------------------------------------------
51 // Collection
52 //------------------------------------------------------------------------
54 void lcl_DeleteScDataObjects( ScDataObject** p, USHORT nCount )
56 if ( p )
58 for (USHORT i = 0; i < nCount; i++) delete p[i];
59 delete[] p;
60 p = NULL;
64 ScCollection::ScCollection(USHORT nLim, USHORT nDel) :
65 nCount ( 0 ),
66 nLimit ( nLim ),
67 nDelta ( nDel ),
68 pItems ( NULL )
70 if (nDelta > MAXDELTA)
71 nDelta = MAXDELTA;
72 else if (nDelta == 0)
73 nDelta = 1;
74 if (nLimit > MAXCOLLECTIONSIZE)
75 nLimit = MAXCOLLECTIONSIZE;
76 else if (nLimit < nDelta)
77 nLimit = nDelta;
78 pItems = new ScDataObject*[nLimit];
81 ScCollection::ScCollection(const ScCollection& rCollection)
82 : ScDataObject(),
83 nCount ( 0 ),
84 nLimit ( 0 ),
85 nDelta ( 0 ),
86 pItems ( NULL )
88 *this = rCollection;
91 //------------------------------------------------------------------------
93 ScCollection::~ScCollection()
95 lcl_DeleteScDataObjects( pItems, nCount );
98 //------------------------------------------------------------------------
100 void ScCollection::AtFree(USHORT nIndex)
102 if ((pItems) && (nIndex < nCount))
104 delete pItems[nIndex];
105 --nCount; // before memmove
106 memmove ( &pItems[nIndex], &pItems[nIndex + 1], (nCount - nIndex) * sizeof(ScDataObject*));
107 pItems[nCount] = NULL;
111 //------------------------------------------------------------------------
113 void ScCollection::Free(ScDataObject* pScDataObject)
115 AtFree(IndexOf(pScDataObject));
118 //------------------------------------------------------------------------
120 void ScCollection::FreeAll()
122 lcl_DeleteScDataObjects( pItems, nCount );
123 nCount = 0;
124 pItems = new ScDataObject*[nLimit];
127 //------------------------------------------------------------------------
129 BOOL ScCollection::AtInsert(USHORT nIndex, ScDataObject* pScDataObject)
131 if ((nCount < MAXCOLLECTIONSIZE) && (nIndex <= nCount) && pItems)
133 if (nCount == nLimit)
135 ScDataObject** pNewItems = new ScDataObject*[nLimit + nDelta];
136 if (!pNewItems)
137 return FALSE;
138 nLimit = sal::static_int_cast<USHORT>( nLimit + nDelta );
139 memmove(pNewItems, pItems, nCount * sizeof(ScDataObject*));
140 delete[] pItems;
141 pItems = pNewItems;
143 if (nCount > nIndex)
144 memmove(&pItems[nIndex + 1], &pItems[nIndex], (nCount - nIndex) * sizeof(ScDataObject*));
145 pItems[nIndex] = pScDataObject;
146 nCount++;
147 return TRUE;
149 return FALSE;
152 //------------------------------------------------------------------------
154 BOOL ScCollection::Insert(ScDataObject* pScDataObject)
156 return AtInsert(nCount, pScDataObject);
159 //------------------------------------------------------------------------
161 ScDataObject* ScCollection::At(USHORT nIndex) const
163 if (nIndex < nCount)
164 return pItems[nIndex];
165 else
166 return NULL;
169 //------------------------------------------------------------------------
171 USHORT ScCollection::IndexOf(ScDataObject* pScDataObject) const
173 USHORT nIndex = 0xffff;
174 for (USHORT i = 0; ((i < nCount) && (nIndex == 0xffff)); i++)
176 if (pItems[i] == pScDataObject) nIndex = i;
178 return nIndex;
181 //------------------------------------------------------------------------
183 ScCollection& ScCollection::operator=( const ScCollection& r )
185 lcl_DeleteScDataObjects( pItems, nCount );
187 nCount = r.nCount;
188 nLimit = r.nLimit;
189 nDelta = r.nDelta;
190 pItems = new ScDataObject*[nLimit];
191 for ( USHORT i=0; i<nCount; i++ )
192 pItems[i] = r.pItems[i]->Clone();
194 return *this;
197 //------------------------------------------------------------------------
199 ScDataObject* ScCollection::Clone() const
201 return new ScCollection(*this);
204 //------------------------------------------------------------------------
205 // ScSortedCollection
206 //------------------------------------------------------------------------
208 ScSortedCollection::ScSortedCollection(USHORT nLim, USHORT nDel, BOOL bDup) :
209 ScCollection (nLim, nDel),
210 bDuplicates ( bDup)
214 //------------------------------------------------------------------------
216 USHORT ScSortedCollection::IndexOf(ScDataObject* pScDataObject) const
218 USHORT nIndex;
219 if (Search(pScDataObject, nIndex))
220 return nIndex;
221 else
222 return 0xffff;
225 //------------------------------------------------------------------------
227 BOOL ScSortedCollection::Search(ScDataObject* pScDataObject, USHORT& rIndex) const
229 rIndex = nCount;
230 BOOL bFound = FALSE;
231 short nLo = 0;
232 short nHi = nCount - 1;
233 short nIndex;
234 short nCompare;
235 while (nLo <= nHi)
237 nIndex = (nLo + nHi) / 2;
238 nCompare = Compare(pItems[nIndex], pScDataObject);
239 if (nCompare < 0)
240 nLo = nIndex + 1;
241 else
243 nHi = nIndex - 1;
244 if (nCompare == 0)
246 bFound = TRUE;
247 nLo = nIndex;
251 rIndex = nLo;
252 return bFound;
255 //------------------------------------------------------------------------
257 BOOL ScSortedCollection::Insert(ScDataObject* pScDataObject)
259 USHORT nIndex;
260 BOOL bFound = Search(pScDataObject, nIndex);
261 if (bFound)
263 if (bDuplicates)
264 return AtInsert(nIndex, pScDataObject);
265 else
266 return FALSE;
268 else
269 return AtInsert(nIndex, pScDataObject);
272 //------------------------------------------------------------------------
274 BOOL ScSortedCollection::InsertPos(ScDataObject* pScDataObject, USHORT& nIndex)
276 BOOL bFound = Search(pScDataObject, nIndex);
277 if (bFound)
279 if (bDuplicates)
280 return AtInsert(nIndex, pScDataObject);
281 else
282 return FALSE;
284 else
285 return AtInsert(nIndex, pScDataObject);
288 //------------------------------------------------------------------------
290 BOOL ScSortedCollection::operator==(const ScSortedCollection& rCmp) const
292 if ( nCount != rCmp.nCount )
293 return FALSE;
294 for (USHORT i=0; i<nCount; i++)
295 if ( !IsEqual(pItems[i],rCmp.pItems[i]) )
296 return FALSE;
297 return TRUE;
300 //------------------------------------------------------------------------
302 // IsEqual - komplette Inhalte vergleichen
304 BOOL ScSortedCollection::IsEqual(ScDataObject* pKey1, ScDataObject* pKey2) const
306 return ( Compare(pKey1, pKey2) == 0 ); // Default: nur Index vergleichen
309 //------------------------------------------------------------------------
311 ScDataObject* StrData::Clone() const
313 return new StrData(*this);
316 //------------------------------------------------------------------------
318 short ScStrCollection::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const
320 StringCompare eComp = ((StrData*)pKey1)->aStr.CompareTo(((StrData*)pKey2)->aStr);
321 if (eComp == COMPARE_EQUAL)
322 return 0;
323 else if (eComp == COMPARE_LESS)
324 return -1;
325 else
326 return 1;
329 //------------------------------------------------------------------------
331 ScDataObject* ScStrCollection::Clone() const
333 return new ScStrCollection(*this);
336 //------------------------------------------------------------------------
337 // TypedScStrCollection
338 //------------------------------------------------------------------------
340 //UNUSED2008-05 TypedStrData::TypedStrData( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab,
341 //UNUSED2008-05 BOOL bAllStrings )
342 //UNUSED2008-05 {
343 //UNUSED2008-05 if ( pDoc->HasValueData( nCol, nRow, nTab ) )
344 //UNUSED2008-05 {
345 //UNUSED2008-05 pDoc->GetValue( nCol, nRow, nTab, nValue );
346 //UNUSED2008-05 if (bAllStrings)
347 //UNUSED2008-05 pDoc->GetString( nCol, nRow, nTab, aStrValue );
348 //UNUSED2008-05 nStrType = 0;
349 //UNUSED2008-05 }
350 //UNUSED2008-05 else
351 //UNUSED2008-05 {
352 //UNUSED2008-05 pDoc->GetString( nCol, nRow, nTab, aStrValue );
353 //UNUSED2008-05 nValue = 0.0;
354 //UNUSED2008-05 nStrType = 1; //! Typ uebergeben ?
355 //UNUSED2008-05 }
356 //UNUSED2008-05 }
358 ScDataObject* TypedStrData::Clone() const
360 return new TypedStrData(*this);
363 ScDataObject* TypedScStrCollection::Clone() const
365 return new TypedScStrCollection(*this);
368 short TypedScStrCollection::Compare( ScDataObject* pKey1, ScDataObject* pKey2 ) const
370 short nResult = 0;
372 if ( pKey1 && pKey2 )
374 TypedStrData& rData1 = (TypedStrData&)*pKey1;
375 TypedStrData& rData2 = (TypedStrData&)*pKey2;
377 if ( rData1.nStrType > rData2.nStrType )
378 nResult = 1;
379 else if ( rData1.nStrType < rData2.nStrType )
380 nResult = -1;
381 else if ( !rData1.nStrType /* && !rData2.nStrType */ )
383 //--------------------
384 // Zahlen vergleichen:
385 //--------------------
386 if ( rData1.nValue == rData2.nValue )
387 nResult = 0;
388 else if ( rData1.nValue < rData2.nValue )
389 nResult = -1;
390 else
391 nResult = 1;
393 else /* if ( rData1.nStrType && rData2.nStrType ) */
395 //---------------------
396 // Strings vergleichen:
397 //---------------------
398 if ( bCaseSensitive )
399 nResult = (short) ScGlobal::pCaseTransliteration->compareString(
400 rData1.aStrValue, rData2.aStrValue );
401 else
402 nResult = (short) ScGlobal::pTransliteration->compareString(
403 rData1.aStrValue, rData2.aStrValue );
407 return nResult;
410 BOOL TypedScStrCollection::FindText( const String& rStart, String& rResult,
411 USHORT& rPos, BOOL bBack ) const
413 // Die Collection ist nach String-Vergleichen sortiert, darum muss hier
414 // alles durchsucht werden
416 BOOL bFound = FALSE;
418 String aOldResult;
419 if ( rPos != SCPOS_INVALID && rPos < nCount )
421 TypedStrData* pData = (TypedStrData*) pItems[rPos];
422 if (pData->nStrType)
423 aOldResult = pData->aStrValue;
426 if ( bBack ) // rueckwaerts
428 USHORT nStartPos = nCount;
429 if ( rPos != SCPOS_INVALID )
430 nStartPos = rPos; // weitersuchen...
432 for ( USHORT i=nStartPos; i>0; )
434 --i;
435 TypedStrData* pData = (TypedStrData*) pItems[i];
436 if (pData->nStrType)
438 if ( ScGlobal::pTransliteration->isMatch( rStart, pData->aStrValue ) )
440 // If the collection is case sensitive, it may contain several entries
441 // that are equal when compared case-insensitive. They are skipped here.
442 if ( !bCaseSensitive || !aOldResult.Len() ||
443 !ScGlobal::pTransliteration->isEqual(
444 pData->aStrValue, aOldResult ) )
446 rResult = pData->aStrValue;
447 rPos = i;
448 bFound = TRUE;
449 break;
455 else // vorwaerts
457 USHORT nStartPos = 0;
458 if ( rPos != SCPOS_INVALID )
459 nStartPos = rPos + 1; // weitersuchen...
461 for ( USHORT i=nStartPos; i<nCount; i++ )
463 TypedStrData* pData = (TypedStrData*) pItems[i];
464 if (pData->nStrType)
466 if ( ScGlobal::pTransliteration->isMatch( rStart, pData->aStrValue ) )
468 // If the collection is case sensitive, it may contain several entries
469 // that are equal when compared case-insensitive. They are skipped here.
470 if ( !bCaseSensitive || !aOldResult.Len() ||
471 !ScGlobal::pTransliteration->isEqual(
472 pData->aStrValue, aOldResult ) )
474 rResult = pData->aStrValue;
475 rPos = i;
476 bFound = TRUE;
477 break;
484 return bFound;
487 // Gross-/Kleinschreibung anpassen
489 BOOL TypedScStrCollection::GetExactMatch( String& rString ) const
491 for (USHORT i=0; i<nCount; i++)
493 TypedStrData* pData = (TypedStrData*) pItems[i];
494 if ( pData->nStrType && ScGlobal::pTransliteration->isEqual(
495 pData->aStrValue, rString ) )
497 rString = pData->aStrValue; // String anpassen
498 return TRUE;
502 return FALSE;