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