1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_sc.hxx" 30 31 32 33 #include <string.h> 34 #include <tools/stream.hxx> 35 #include <unotools/transliterationwrapper.hxx> 36 37 #include "rechead.hxx" 38 #include "collect.hxx" 39 #include "document.hxx" // fuer TypedStrData Konstruktor 40 41 // ----------------------------------------------------------------------- 42 43 ScDataObject::~ScDataObject() 44 { 45 } 46 47 //------------------------------------------------------------------------ 48 // Collection 49 //------------------------------------------------------------------------ 50 51 void lcl_DeleteScDataObjects( ScDataObject** p, sal_uInt16 nCount ) 52 { 53 if ( p ) 54 { 55 for (sal_uInt16 i = 0; i < nCount; i++) delete p[i]; 56 delete[] p; 57 p = NULL; 58 } 59 } 60 61 ScCollection::ScCollection(sal_uInt16 nLim, sal_uInt16 nDel) : 62 nCount ( 0 ), 63 nLimit ( nLim ), 64 nDelta ( nDel ), 65 pItems ( NULL ) 66 { 67 if (nDelta > MAXDELTA) 68 nDelta = MAXDELTA; 69 else if (nDelta == 0) 70 nDelta = 1; 71 if (nLimit > MAXCOLLECTIONSIZE) 72 nLimit = MAXCOLLECTIONSIZE; 73 else if (nLimit < nDelta) 74 nLimit = nDelta; 75 pItems = new ScDataObject*[nLimit]; 76 } 77 78 ScCollection::ScCollection(const ScCollection& rCollection) 79 : ScDataObject(), 80 nCount ( 0 ), 81 nLimit ( 0 ), 82 nDelta ( 0 ), 83 pItems ( NULL ) 84 { 85 *this = rCollection; 86 } 87 88 //------------------------------------------------------------------------ 89 90 ScCollection::~ScCollection() 91 { 92 lcl_DeleteScDataObjects( pItems, nCount ); 93 } 94 95 //------------------------------------------------------------------------ 96 sal_uInt16 ScCollection::GetCount() const { return nCount; } 97 void ScCollection::AtFree(sal_uInt16 nIndex) 98 { 99 if ((pItems) && (nIndex < nCount)) 100 { 101 delete pItems[nIndex]; 102 --nCount; // before memmove 103 memmove ( &pItems[nIndex], &pItems[nIndex + 1], (nCount - nIndex) * sizeof(ScDataObject*)); 104 pItems[nCount] = NULL; 105 } 106 } 107 108 //------------------------------------------------------------------------ 109 110 void ScCollection::Free(ScDataObject* pScDataObject) 111 { 112 AtFree(IndexOf(pScDataObject)); 113 } 114 115 //------------------------------------------------------------------------ 116 117 void ScCollection::FreeAll() 118 { 119 lcl_DeleteScDataObjects( pItems, nCount ); 120 nCount = 0; 121 pItems = new ScDataObject*[nLimit]; 122 } 123 124 //------------------------------------------------------------------------ 125 126 sal_Bool ScCollection::AtInsert(sal_uInt16 nIndex, ScDataObject* pScDataObject) 127 { 128 if ((nCount < MAXCOLLECTIONSIZE) && (nIndex <= nCount) && pItems) 129 { 130 if (nCount == nLimit) 131 { 132 ScDataObject** pNewItems = new ScDataObject*[nLimit + nDelta]; 133 if (!pNewItems) 134 return sal_False; 135 nLimit = sal::static_int_cast<sal_uInt16>( nLimit + nDelta ); 136 memmove(pNewItems, pItems, nCount * sizeof(ScDataObject*)); 137 delete[] pItems; 138 pItems = pNewItems; 139 } 140 if (nCount > nIndex) 141 memmove(&pItems[nIndex + 1], &pItems[nIndex], (nCount - nIndex) * sizeof(ScDataObject*)); 142 pItems[nIndex] = pScDataObject; 143 nCount++; 144 return sal_True; 145 } 146 return sal_False; 147 } 148 149 //------------------------------------------------------------------------ 150 151 sal_Bool ScCollection::Insert(ScDataObject* pScDataObject) 152 { 153 return AtInsert(nCount, pScDataObject); 154 } 155 156 //------------------------------------------------------------------------ 157 158 ScDataObject* ScCollection::At(sal_uInt16 nIndex) const 159 { 160 if (nIndex < nCount) 161 return pItems[nIndex]; 162 else 163 return NULL; 164 } 165 166 //------------------------------------------------------------------------ 167 168 sal_uInt16 ScCollection::IndexOf(ScDataObject* pScDataObject) const 169 { 170 sal_uInt16 nIndex = 0xffff; 171 for (sal_uInt16 i = 0; ((i < nCount) && (nIndex == 0xffff)); i++) 172 { 173 if (pItems[i] == pScDataObject) nIndex = i; 174 } 175 return nIndex; 176 } 177 178 //------------------------------------------------------------------------ 179 180 ScCollection& ScCollection::operator=( const ScCollection& r ) 181 { 182 lcl_DeleteScDataObjects( pItems, nCount ); 183 184 nCount = r.nCount; 185 nLimit = r.nLimit; 186 nDelta = r.nDelta; 187 pItems = new ScDataObject*[nLimit]; 188 for ( sal_uInt16 i=0; i<nCount; i++ ) 189 pItems[i] = r.pItems[i]->Clone(); 190 191 return *this; 192 } 193 194 //------------------------------------------------------------------------ 195 196 ScDataObject* ScCollection::Clone() const 197 { 198 return new ScCollection(*this); 199 } 200 201 //------------------------------------------------------------------------ 202 // ScSortedCollection 203 //------------------------------------------------------------------------ 204 205 ScSortedCollection::ScSortedCollection(sal_uInt16 nLim, sal_uInt16 nDel, sal_Bool bDup) : 206 ScCollection (nLim, nDel), 207 bDuplicates ( bDup) 208 { 209 } 210 211 //------------------------------------------------------------------------ 212 213 sal_uInt16 ScSortedCollection::IndexOf(ScDataObject* pScDataObject) const 214 { 215 sal_uInt16 nIndex; 216 if (Search(pScDataObject, nIndex)) 217 return nIndex; 218 else 219 return 0xffff; 220 } 221 222 //------------------------------------------------------------------------ 223 224 sal_Bool ScSortedCollection::Search(ScDataObject* pScDataObject, sal_uInt16& rIndex) const 225 { 226 rIndex = nCount; 227 sal_Bool bFound = sal_False; 228 short nLo = 0; 229 short nHi = nCount - 1; 230 short nIndex; 231 short nCompare; 232 while (nLo <= nHi) 233 { 234 nIndex = (nLo + nHi) / 2; 235 nCompare = Compare(pItems[nIndex], pScDataObject); 236 if (nCompare < 0) 237 nLo = nIndex + 1; 238 else 239 { 240 nHi = nIndex - 1; 241 if (nCompare == 0) 242 { 243 bFound = sal_True; 244 nLo = nIndex; 245 } 246 } 247 } 248 rIndex = nLo; 249 return bFound; 250 } 251 252 //------------------------------------------------------------------------ 253 254 sal_Bool ScSortedCollection::Insert(ScDataObject* pScDataObject) 255 { 256 sal_uInt16 nIndex; 257 sal_Bool bFound = Search(pScDataObject, nIndex); 258 if (bFound) 259 { 260 if (bDuplicates) 261 return AtInsert(nIndex, pScDataObject); 262 else 263 return sal_False; 264 } 265 else 266 return AtInsert(nIndex, pScDataObject); 267 } 268 269 //------------------------------------------------------------------------ 270 271 sal_Bool ScSortedCollection::InsertPos(ScDataObject* pScDataObject, sal_uInt16& nIndex) 272 { 273 sal_Bool bFound = Search(pScDataObject, nIndex); 274 if (bFound) 275 { 276 if (bDuplicates) 277 return AtInsert(nIndex, pScDataObject); 278 else 279 return sal_False; 280 } 281 else 282 return AtInsert(nIndex, pScDataObject); 283 } 284 285 //------------------------------------------------------------------------ 286 287 sal_Bool ScSortedCollection::operator==(const ScSortedCollection& rCmp) const 288 { 289 if ( nCount != rCmp.nCount ) 290 return sal_False; 291 for (sal_uInt16 i=0; i<nCount; i++) 292 if ( !IsEqual(pItems[i],rCmp.pItems[i]) ) 293 return sal_False; 294 return sal_True; 295 } 296 297 //------------------------------------------------------------------------ 298 299 // IsEqual - komplette Inhalte vergleichen 300 301 sal_Bool ScSortedCollection::IsEqual(ScDataObject* pKey1, ScDataObject* pKey2) const 302 { 303 return ( Compare(pKey1, pKey2) == 0 ); // Default: nur Index vergleichen 304 } 305 306 //------------------------------------------------------------------------ 307 308 ScDataObject* StrData::Clone() const 309 { 310 return new StrData(*this); 311 } 312 313 //------------------------------------------------------------------------ 314 315 short ScStrCollection::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const 316 { 317 StringCompare eComp = ((StrData*)pKey1)->aStr.CompareTo(((StrData*)pKey2)->aStr); 318 if (eComp == COMPARE_EQUAL) 319 return 0; 320 else if (eComp == COMPARE_LESS) 321 return -1; 322 else 323 return 1; 324 } 325 326 //------------------------------------------------------------------------ 327 328 ScDataObject* ScStrCollection::Clone() const 329 { 330 return new ScStrCollection(*this); 331 } 332 333 //------------------------------------------------------------------------ 334 // TypedScStrCollection 335 //------------------------------------------------------------------------ 336 337 //UNUSED2008-05 TypedStrData::TypedStrData( ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab, 338 //UNUSED2008-05 sal_Bool bAllStrings ) 339 //UNUSED2008-05 { 340 //UNUSED2008-05 if ( pDoc->HasValueData( nCol, nRow, nTab ) ) 341 //UNUSED2008-05 { 342 //UNUSED2008-05 pDoc->GetValue( nCol, nRow, nTab, nValue ); 343 //UNUSED2008-05 if (bAllStrings) 344 //UNUSED2008-05 pDoc->GetString( nCol, nRow, nTab, aStrValue ); 345 //UNUSED2008-05 nStrType = 0; 346 //UNUSED2008-05 } 347 //UNUSED2008-05 else 348 //UNUSED2008-05 { 349 //UNUSED2008-05 pDoc->GetString( nCol, nRow, nTab, aStrValue ); 350 //UNUSED2008-05 nValue = 0.0; 351 //UNUSED2008-05 nStrType = 1; //! Typ uebergeben ? 352 //UNUSED2008-05 } 353 //UNUSED2008-05 } 354 355 356 ScDataObject* TypedStrData::Clone() const 357 { 358 return new TypedStrData(*this); 359 } 360 361 TypedScStrCollection::TypedScStrCollection( sal_uInt16 nLim , sal_uInt16 nDel , sal_Bool bDup ) 362 : ScSortedCollection( nLim, nDel, bDup ) 363 { 364 bCaseSensitive = sal_False; 365 } 366 367 TypedScStrCollection::~TypedScStrCollection() 368 {} 369 ScDataObject* TypedScStrCollection::Clone() const 370 { 371 return new TypedScStrCollection(*this); 372 } 373 374 TypedStrData* TypedScStrCollection::operator[]( const sal_uInt16 nIndex) const 375 { 376 return (TypedStrData*)At(nIndex); 377 } 378 379 void TypedScStrCollection::SetCaseSensitive( sal_Bool bSet ) 380 { 381 bCaseSensitive = bSet; 382 } 383 384 short TypedScStrCollection::Compare( ScDataObject* pKey1, ScDataObject* pKey2 ) const 385 { 386 short nResult = 0; 387 388 if ( pKey1 && pKey2 ) 389 { 390 TypedStrData& rData1 = (TypedStrData&)*pKey1; 391 TypedStrData& rData2 = (TypedStrData&)*pKey2; 392 393 if ( rData1.nStrType > rData2.nStrType ) 394 nResult = 1; 395 else if ( rData1.nStrType < rData2.nStrType ) 396 nResult = -1; 397 else if ( !rData1.nStrType /* && !rData2.nStrType */ ) 398 { 399 //-------------------- 400 // Zahlen vergleichen: 401 //-------------------- 402 if ( rData1.nValue == rData2.nValue ) 403 nResult = 0; 404 else if ( rData1.nValue < rData2.nValue ) 405 nResult = -1; 406 else 407 nResult = 1; 408 } 409 else /* if ( rData1.nStrType && rData2.nStrType ) */ 410 { 411 //--------------------- 412 // Strings vergleichen: 413 //--------------------- 414 if ( bCaseSensitive ) 415 nResult = (short) ScGlobal::GetCaseTransliteration()->compareString( 416 rData1.aStrValue, rData2.aStrValue ); 417 else 418 nResult = (short) ScGlobal::GetpTransliteration()->compareString( 419 rData1.aStrValue, rData2.aStrValue ); 420 } 421 } 422 423 return nResult; 424 } 425 426 sal_Bool TypedScStrCollection::FindText( const String& rStart, String& rResult, 427 sal_uInt16& rPos, sal_Bool bBack ) const 428 { 429 // Die Collection ist nach String-Vergleichen sortiert, darum muss hier 430 // alles durchsucht werden 431 432 sal_Bool bFound = sal_False; 433 434 String aOldResult; 435 if ( rPos != SCPOS_INVALID && rPos < nCount ) 436 { 437 TypedStrData* pData = (TypedStrData*) pItems[rPos]; 438 if (pData->nStrType) 439 aOldResult = pData->aStrValue; 440 } 441 442 if ( bBack ) // rueckwaerts 443 { 444 sal_uInt16 nStartPos = nCount; 445 if ( rPos != SCPOS_INVALID ) 446 nStartPos = rPos; // weitersuchen... 447 448 for ( sal_uInt16 i=nStartPos; i>0; ) 449 { 450 --i; 451 TypedStrData* pData = (TypedStrData*) pItems[i]; 452 if (pData->nStrType) 453 { 454 if ( ScGlobal::GetpTransliteration()->isMatch( rStart, pData->aStrValue ) ) 455 { 456 // If the collection is case sensitive, it may contain several entries 457 // that are equal when compared case-insensitive. They are skipped here. 458 if ( !bCaseSensitive || !aOldResult.Len() || 459 !ScGlobal::GetpTransliteration()->isEqual( 460 pData->aStrValue, aOldResult ) ) 461 { 462 rResult = pData->aStrValue; 463 rPos = i; 464 bFound = sal_True; 465 break; 466 } 467 } 468 } 469 } 470 } 471 else // vorwaerts 472 { 473 sal_uInt16 nStartPos = 0; 474 if ( rPos != SCPOS_INVALID ) 475 nStartPos = rPos + 1; // weitersuchen... 476 477 for ( sal_uInt16 i=nStartPos; i<nCount; i++ ) 478 { 479 TypedStrData* pData = (TypedStrData*) pItems[i]; 480 if (pData->nStrType) 481 { 482 if ( ScGlobal::GetpTransliteration()->isMatch( rStart, pData->aStrValue ) ) 483 { 484 // If the collection is case sensitive, it may contain several entries 485 // that are equal when compared case-insensitive. They are skipped here. 486 if ( !bCaseSensitive || !aOldResult.Len() || 487 !ScGlobal::GetpTransliteration()->isEqual( 488 pData->aStrValue, aOldResult ) ) 489 { 490 rResult = pData->aStrValue; 491 rPos = i; 492 bFound = sal_True; 493 break; 494 } 495 } 496 } 497 } 498 } 499 500 return bFound; 501 } 502 503 // Gross-/Kleinschreibung anpassen 504 505 sal_Bool TypedScStrCollection::GetExactMatch( String& rString ) const 506 { 507 for (sal_uInt16 i=0; i<nCount; i++) 508 { 509 TypedStrData* pData = (TypedStrData*) pItems[i]; 510 if ( pData->nStrType && ScGlobal::GetpTransliteration()->isEqual( 511 pData->aStrValue, rString ) ) 512 { 513 rString = pData->aStrValue; // String anpassen 514 return sal_True; 515 } 516 } 517 518 return sal_False; 519 } 520 521 522 523