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 30 #include <tools/debug.hxx> 31 #include <string.h> 32 #include <memory> 33 #include <unotools/collatorwrapper.hxx> 34 #include <unotools/transliterationwrapper.hxx> 35 36 #include "token.hxx" 37 #include "tokenarray.hxx" 38 #include "rangenam.hxx" 39 #include "global.hxx" 40 #include "compiler.hxx" 41 #include "rangeutl.hxx" 42 #include "rechead.hxx" 43 #include "refupdat.hxx" 44 #include "document.hxx" 45 46 using namespace formula; 47 48 //======================================================================== 49 // ScRangeData 50 //======================================================================== 51 52 // Interner ctor fuer das Suchen nach einem Index 53 54 ScRangeData::ScRangeData( sal_uInt16 n ) 55 : pCode( NULL ), nIndex( n ), bModified( sal_False ), mnMaxRow(-1), mnMaxCol(-1) 56 {} 57 58 ScRangeData::ScRangeData( ScDocument* pDok, 59 const String& rName, 60 const String& rSymbol, 61 const ScAddress& rAddress, 62 RangeType nType, 63 const FormulaGrammar::Grammar eGrammar ) : 64 aName ( rName ), 65 aUpperName ( ScGlobal::pCharClass->upper( rName ) ), 66 pCode ( NULL ), 67 aPos ( rAddress ), 68 eType ( nType ), 69 pDoc ( pDok ), 70 nIndex ( 0 ), 71 bModified ( sal_False ), 72 mnMaxRow (-1), 73 mnMaxCol (-1) 74 { 75 if (rSymbol.Len() > 0) 76 { 77 ScCompiler aComp( pDoc, aPos ); 78 aComp.SetGrammar(eGrammar); 79 pCode = aComp.CompileString( rSymbol ); 80 if( !pCode->GetCodeError() ) 81 { 82 pCode->Reset(); 83 FormulaToken* p = pCode->GetNextReference(); 84 if( p )// genau eine Referenz als erstes 85 { 86 if( p->GetType() == svSingleRef ) 87 eType = eType | RT_ABSPOS; 88 else 89 eType = eType | RT_ABSAREA; 90 } 91 // ggf. den Fehlercode wg. unvollstaendiger Formel setzen! 92 // Dies ist fuer die manuelle Eingabe 93 aComp.CompileTokenArray(); 94 pCode->DelRPN(); 95 } 96 } 97 else 98 { 99 // #i63513#/#i65690# don't leave pCode as NULL. 100 // Copy ctor default-constructs pCode if it was NULL, so it's initialized here, too, 101 // to ensure same behavior if unnecessary copying is left out. 102 103 pCode = new ScTokenArray(); 104 } 105 } 106 107 ScRangeData::ScRangeData( ScDocument* pDok, 108 const String& rName, 109 const ScTokenArray& rArr, 110 const ScAddress& rAddress, 111 RangeType nType ) : 112 aName ( rName ), 113 aUpperName ( ScGlobal::pCharClass->upper( rName ) ), 114 pCode ( new ScTokenArray( rArr ) ), 115 aPos ( rAddress ), 116 eType ( nType ), 117 pDoc ( pDok ), 118 nIndex ( 0 ), 119 bModified ( sal_False ), 120 mnMaxRow (-1), 121 mnMaxCol (-1) 122 { 123 if( !pCode->GetCodeError() ) 124 { 125 pCode->Reset(); 126 FormulaToken* p = pCode->GetNextReference(); 127 if( p )// genau eine Referenz als erstes 128 { 129 if( p->GetType() == svSingleRef ) 130 eType = eType | RT_ABSPOS; 131 else 132 eType = eType | RT_ABSAREA; 133 } 134 // Die Importfilter haben diesen Test nicht, 135 // da die benannten Bereiche z.T. noch unvollstaendig sind. 136 // if( !pCode->GetCodeLen() ) 137 // { 138 // // ggf. den Fehlercode wg. unvollstaendiger Formel setzen! 139 // ScCompiler aComp( pDok, aPos, *pCode ); 140 // aComp.CompileTokenArray(); 141 // pCode->DelRPN(); 142 // } 143 } 144 } 145 146 ScRangeData::ScRangeData( ScDocument* pDok, 147 const String& rName, 148 const ScAddress& rTarget ) : 149 aName ( rName ), 150 aUpperName ( ScGlobal::pCharClass->upper( rName ) ), 151 pCode ( new ScTokenArray() ), 152 aPos ( rTarget ), 153 eType ( RT_NAME ), 154 pDoc ( pDok ), 155 nIndex ( 0 ), 156 bModified ( sal_False ), 157 mnMaxRow (-1), 158 mnMaxCol (-1) 159 { 160 ScSingleRefData aRefData; 161 aRefData.InitAddress( rTarget ); 162 aRefData.SetFlag3D( sal_True ); 163 pCode->AddSingleReference( aRefData ); 164 ScCompiler aComp( pDoc, aPos, *pCode ); 165 aComp.SetGrammar(pDoc->GetGrammar()); 166 aComp.CompileTokenArray(); 167 if ( !pCode->GetCodeError() ) 168 eType |= RT_ABSPOS; 169 } 170 171 ScRangeData::ScRangeData(const ScRangeData& rScRangeData) : 172 ScDataObject(), 173 aName (rScRangeData.aName), 174 aUpperName (rScRangeData.aUpperName), 175 pCode (rScRangeData.pCode ? rScRangeData.pCode->Clone() : new ScTokenArray()), // echte Kopie erzeugen (nicht copy-ctor) 176 aPos (rScRangeData.aPos), 177 eType (rScRangeData.eType), 178 pDoc (rScRangeData.pDoc), 179 nIndex (rScRangeData.nIndex), 180 bModified (rScRangeData.bModified), 181 mnMaxRow (rScRangeData.mnMaxRow), 182 mnMaxCol (rScRangeData.mnMaxCol) 183 {} 184 185 ScRangeData::~ScRangeData() 186 { 187 delete pCode; 188 } 189 190 ScDataObject* ScRangeData::Clone() const 191 { 192 return new ScRangeData(*this); 193 } 194 195 void ScRangeData::GuessPosition() 196 { 197 // setzt eine Position, mit der alle relative Referenzen bei CalcAbsIfRel 198 // ohne Fehler verabsolutiert werden koennen 199 200 DBG_ASSERT(aPos == ScAddress(), "die Position geht jetzt verloren"); 201 202 SCsCOL nMinCol = 0; 203 SCsROW nMinRow = 0; 204 SCsTAB nMinTab = 0; 205 206 ScToken* t; 207 pCode->Reset(); 208 while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL ) 209 { 210 ScSingleRefData& rRef1 = t->GetSingleRef(); 211 if ( rRef1.IsColRel() && rRef1.nRelCol < nMinCol ) 212 nMinCol = rRef1.nRelCol; 213 if ( rRef1.IsRowRel() && rRef1.nRelRow < nMinRow ) 214 nMinRow = rRef1.nRelRow; 215 if ( rRef1.IsTabRel() && rRef1.nRelTab < nMinTab ) 216 nMinTab = rRef1.nRelTab; 217 218 if ( t->GetType() == svDoubleRef ) 219 { 220 ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2; 221 if ( rRef2.IsColRel() && rRef2.nRelCol < nMinCol ) 222 nMinCol = rRef2.nRelCol; 223 if ( rRef2.IsRowRel() && rRef2.nRelRow < nMinRow ) 224 nMinRow = rRef2.nRelRow; 225 if ( rRef2.IsTabRel() && rRef2.nRelTab < nMinTab ) 226 nMinTab = rRef2.nRelTab; 227 } 228 } 229 230 aPos = ScAddress( (SCCOL)(-nMinCol), (SCROW)(-nMinRow), (SCTAB)(-nMinTab) ); 231 232 //! Test 233 // DBG_ERROR(String("Pos ")+String((SCCOL)(-nMinCol))+String("/")+ 234 // String((SCROW)(-nMinRow))+String("/")+String((SCTAB)(-nMinTab))); 235 } 236 237 void ScRangeData::GetSymbol( String& rSymbol, const FormulaGrammar::Grammar eGrammar ) const 238 { 239 ScCompiler aComp(pDoc, aPos, *pCode); 240 aComp.SetGrammar(eGrammar); 241 aComp.CreateStringFromTokenArray( rSymbol ); 242 } 243 244 void ScRangeData::UpdateSymbol( rtl::OUStringBuffer& rBuffer, const ScAddress& rPos, 245 const FormulaGrammar::Grammar eGrammar ) 246 { 247 ::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() ); 248 ScCompiler aComp( pDoc, rPos, *pTemp.get()); 249 aComp.SetGrammar(eGrammar); 250 aComp.MoveRelWrap(GetMaxCol(), GetMaxRow()); 251 aComp.CreateStringFromTokenArray( rBuffer ); 252 } 253 254 void ScRangeData::UpdateReference( UpdateRefMode eUpdateRefMode, 255 const ScRange& r, 256 SCsCOL nDx, SCsROW nDy, SCsTAB nDz ) 257 { 258 sal_Bool bChanged = sal_False; 259 260 pCode->Reset(); 261 if( pCode->GetNextReference() ) 262 { 263 sal_Bool bSharedFormula = ((eType & RT_SHARED) == RT_SHARED); 264 ScCompiler aComp( pDoc, aPos, *pCode ); 265 aComp.SetGrammar(pDoc->GetGrammar()); 266 const sal_Bool bRelRef = aComp.UpdateNameReference( eUpdateRefMode, r, 267 nDx, nDy, nDz, 268 bChanged, bSharedFormula); 269 if (bSharedFormula) 270 { 271 if (bRelRef) 272 eType = eType | RT_SHAREDMOD; 273 else 274 eType = eType & ~RT_SHAREDMOD; 275 } 276 } 277 278 bModified = bChanged; 279 } 280 281 282 void ScRangeData::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest ) 283 { 284 sal_Bool bChanged = sal_False; 285 286 ScToken* t; 287 pCode->Reset(); 288 289 while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL ) 290 { 291 if( t->GetType() != svIndex ) 292 { 293 SingleDoubleRefModifier aMod( *t ); 294 ScComplexRefData& rRef = aMod.Ref(); 295 if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && 296 (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) && 297 ( t->GetType() == svSingleRef || 298 (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() && 299 (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel())))) 300 { 301 if ( ScRefUpdate::UpdateTranspose( pDoc, rSource, rDest, rRef ) != UR_NOTHING ) 302 bChanged = sal_True; 303 } 304 } 305 } 306 307 bModified = bChanged; 308 } 309 310 void ScRangeData::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY ) 311 { 312 sal_Bool bChanged = sal_False; 313 314 ScToken* t; 315 pCode->Reset(); 316 317 while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL ) 318 { 319 if( t->GetType() != svIndex ) 320 { 321 SingleDoubleRefModifier aMod( *t ); 322 ScComplexRefData& rRef = aMod.Ref(); 323 if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() && 324 (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) && 325 ( t->GetType() == svSingleRef || 326 (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() && 327 (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel())))) 328 { 329 if ( ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY, rRef ) != UR_NOTHING ) 330 bChanged = sal_True; 331 } 332 } 333 } 334 335 bModified = bChanged; // muss direkt hinterher ausgewertet werden 336 } 337 338 sal_Bool ScRangeData::operator== (const ScRangeData& rData) const // fuer Undo 339 { 340 if ( nIndex != rData.nIndex || 341 aName != rData.aName || 342 aPos != rData.aPos || 343 eType != rData.eType ) return sal_False; 344 345 sal_uInt16 nLen = pCode->GetLen(); 346 if ( nLen != rData.pCode->GetLen() ) return sal_False; 347 348 FormulaToken** ppThis = pCode->GetArray(); 349 FormulaToken** ppOther = rData.pCode->GetArray(); 350 351 for ( sal_uInt16 i=0; i<nLen; i++ ) 352 if ( ppThis[i] != ppOther[i] && !(*ppThis[i] == *ppOther[i]) ) 353 return sal_False; 354 355 return sal_True; 356 } 357 358 //UNUSED2009-05 sal_Bool ScRangeData::IsRangeAtCursor( const ScAddress& rPos, sal_Bool bStartOnly ) const 359 //UNUSED2009-05 { 360 //UNUSED2009-05 sal_Bool bRet = sal_False; 361 //UNUSED2009-05 ScRange aRange; 362 //UNUSED2009-05 if ( IsReference(aRange) ) 363 //UNUSED2009-05 { 364 //UNUSED2009-05 if ( bStartOnly ) 365 //UNUSED2009-05 bRet = ( rPos == aRange.aStart ); 366 //UNUSED2009-05 else 367 //UNUSED2009-05 bRet = ( aRange.In( rPos ) ); 368 //UNUSED2009-05 } 369 //UNUSED2009-05 return bRet; 370 //UNUSED2009-05 } 371 372 sal_Bool ScRangeData::IsRangeAtBlock( const ScRange& rBlock ) const 373 { 374 sal_Bool bRet = sal_False; 375 ScRange aRange; 376 if ( IsReference(aRange) ) 377 bRet = ( rBlock == aRange ); 378 return bRet; 379 } 380 381 sal_Bool ScRangeData::IsReference( ScRange& rRange ) const 382 { 383 if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS )) && pCode ) 384 return pCode->IsReference( rRange ); 385 386 return sal_False; 387 } 388 389 sal_Bool ScRangeData::IsReference( ScRange& rRange, const ScAddress& rPos ) const 390 { 391 if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode ) 392 { 393 ::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() ); 394 ScCompiler aComp( pDoc, rPos, *pTemp); 395 aComp.SetGrammar(pDoc->GetGrammar()); 396 aComp.MoveRelWrap(MAXCOL, MAXROW); 397 return pTemp->IsReference( rRange ); 398 } 399 400 return sal_False; 401 } 402 403 sal_Bool ScRangeData::IsValidReference( ScRange& rRange ) const 404 { 405 if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode ) 406 return pCode->IsValidReference( rRange ); 407 408 return sal_False; 409 } 410 411 void ScRangeData::UpdateTabRef(SCTAB nOldTable, sal_uInt16 nFlag, SCTAB nNewTable) 412 { 413 pCode->Reset(); 414 if( pCode->GetNextReference() ) 415 { 416 ScRangeData* pRangeData = NULL; // must not be dereferenced 417 sal_Bool bChanged; 418 ScCompiler aComp( pDoc, aPos, *pCode); 419 aComp.SetGrammar(pDoc->GetGrammar()); 420 switch (nFlag) 421 { 422 case 1: // einfache InsertTab (doc.cxx) 423 pRangeData = aComp.UpdateInsertTab(nOldTable, sal_True ); // und CopyTab (doc2.cxx) 424 break; 425 case 2: // einfaches delete (doc.cxx) 426 pRangeData = aComp.UpdateDeleteTab(nOldTable, sal_False, sal_True, bChanged); 427 break; 428 case 3: // move (doc2.cxx) 429 { 430 pRangeData = aComp.UpdateMoveTab(nOldTable, nNewTable, sal_True ); 431 } 432 break; 433 default: 434 { 435 DBG_ERROR("ScRangeName::UpdateTabRef: Unknown Flag"); 436 } 437 break; 438 } 439 if (eType&RT_SHARED) 440 { 441 if (pRangeData) 442 eType = eType | RT_SHAREDMOD; 443 else 444 eType = eType & ~RT_SHAREDMOD; 445 } 446 } 447 } 448 449 450 void ScRangeData::MakeValidName( String& rName ) // static 451 { 452 //ScCompiler::InitSymbolsNative(); 453 454 // strip leading invalid characters 455 xub_StrLen nPos = 0; 456 xub_StrLen nLen = rName.Len(); 457 while ( nPos < nLen && !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) ) 458 ++nPos; 459 if ( nPos>0 ) 460 rName.Erase(0,nPos); 461 462 // if the first character is an invalid start character, precede with '_' 463 if ( rName.Len() && !ScCompiler::IsCharFlagAllConventions( rName, 0, SC_COMPILER_C_CHAR_NAME ) ) 464 rName.Insert('_',0); 465 466 // replace invalid with '_' 467 nLen = rName.Len(); 468 for (nPos=0; nPos<nLen; nPos++) 469 { 470 if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) ) 471 rName.SetChar( nPos, '_' ); 472 } 473 474 // Ensure that the proposed name is not a reference under any convention, 475 // same as in IsNameValid() 476 ScAddress aAddr; 477 ScRange aRange; 478 for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; ) 479 { 480 ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) ); 481 // Don't check Parse on VALID, any partial only VALID may result in 482 // #REF! during compile later! 483 while (aRange.Parse( rName, NULL, details) || aAddr.Parse( rName, NULL, details)) 484 { 485 //! Range Parse is partially valid also with invalid sheet name, 486 //! Address Parse dito, during compile name would generate a #REF! 487 if ( rName.SearchAndReplace( '.', '_' ) == STRING_NOTFOUND ) 488 rName.Insert('_',0); 489 } 490 } 491 } 492 493 sal_Bool ScRangeData::IsNameValid( const String& rName, ScDocument* pDoc ) 494 { 495 /* XXX If changed, sc/source/filter/ftools/ftools.cxx 496 * ScfTools::ConvertToScDefinedName needs to be changed too. */ 497 xub_StrLen nPos = 0; 498 xub_StrLen nLen = rName.Len(); 499 if ( !nLen || !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_CHAR_NAME ) ) 500 return sal_False; 501 while ( nPos < nLen ) 502 { 503 if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_NAME ) ) 504 return sal_False; 505 } 506 ScAddress aAddr; 507 ScRange aRange; 508 for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; ) 509 { 510 ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) ); 511 // Don't check Parse on VALID, any partial only VALID may result in 512 // #REF! during compile later! 513 if (aRange.Parse( rName, pDoc, details) || aAddr.Parse( rName, pDoc, details)) 514 return sal_False; 515 } 516 return sal_True; 517 } 518 519 void ScRangeData::SetMaxRow(SCROW nRow) 520 { 521 mnMaxRow = nRow; 522 } 523 524 SCROW ScRangeData::GetMaxRow() const 525 { 526 return mnMaxRow >= 0 ? mnMaxRow : MAXROW; 527 } 528 529 void ScRangeData::SetMaxCol(SCCOL nCol) 530 { 531 mnMaxCol = nCol; 532 } 533 534 SCCOL ScRangeData::GetMaxCol() const 535 { 536 return mnMaxCol >= 0 ? mnMaxCol : MAXCOL; 537 } 538 539 540 sal_uInt16 ScRangeData::GetErrCode() 541 { 542 return pCode ? pCode->GetCodeError() : 0; 543 } 544 545 sal_Bool ScRangeData::HasReferences() const 546 { 547 pCode->Reset(); 548 return sal_Bool( pCode->GetNextReference() != NULL ); 549 } 550 551 // bei TransferTab von einem in ein anderes Dokument anpassen, 552 // um Referenzen auf die eigene Tabelle mitzubekommen 553 554 void ScRangeData::TransferTabRef( SCTAB nOldTab, SCTAB nNewTab ) 555 { 556 long nTabDiff = (long)nNewTab - nOldTab; 557 long nPosDiff = (long)nNewTab - aPos.Tab(); 558 aPos.SetTab( nNewTab ); 559 ScToken* t; 560 pCode->Reset(); 561 while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL ) 562 { 563 ScSingleRefData& rRef1 = t->GetSingleRef(); 564 if ( rRef1.IsTabRel() ) 565 rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + nPosDiff ); 566 else 567 rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab + nTabDiff ); 568 if ( t->GetType() == svDoubleRef ) 569 { 570 ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2; 571 if ( rRef2.IsTabRel() ) 572 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab + nPosDiff ); 573 else 574 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab + nTabDiff ); 575 } 576 } 577 } 578 579 void ScRangeData::ReplaceRangeNamesInUse( const IndexMap& rMap ) 580 { 581 bool bCompile = false; 582 for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() ) 583 { 584 if ( p->GetOpCode() == ocName ) 585 { 586 const sal_uInt16 nOldIndex = p->GetIndex(); 587 IndexMap::const_iterator itr = rMap.find(nOldIndex); 588 const sal_uInt16 nNewIndex = itr == rMap.end() ? nOldIndex : itr->second; 589 if ( nOldIndex != nNewIndex ) 590 { 591 p->SetIndex( nNewIndex ); 592 bCompile = true; 593 } 594 } 595 } 596 if ( bCompile ) 597 { 598 ScCompiler aComp( pDoc, aPos, *pCode); 599 aComp.SetGrammar(pDoc->GetGrammar()); 600 aComp.CompileTokenArray(); 601 } 602 } 603 604 605 void ScRangeData::ValidateTabRefs() 606 { 607 // try to make sure all relative references and the reference position 608 // are within existing tables, so they can be represented as text 609 // (if the range of used tables is more than the existing tables, 610 // the result may still contain invalid tables, because the relative 611 // references aren't changed so formulas stay the same) 612 613 // find range of used tables 614 615 SCTAB nMinTab = aPos.Tab(); 616 SCTAB nMaxTab = nMinTab; 617 ScToken* t; 618 pCode->Reset(); 619 while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL ) 620 { 621 ScSingleRefData& rRef1 = t->GetSingleRef(); 622 if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() ) 623 { 624 if ( rRef1.nTab < nMinTab ) 625 nMinTab = rRef1.nTab; 626 if ( rRef1.nTab > nMaxTab ) 627 nMaxTab = rRef1.nTab; 628 } 629 if ( t->GetType() == svDoubleRef ) 630 { 631 ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2; 632 if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() ) 633 { 634 if ( rRef2.nTab < nMinTab ) 635 nMinTab = rRef2.nTab; 636 if ( rRef2.nTab > nMaxTab ) 637 nMaxTab = rRef2.nTab; 638 } 639 } 640 } 641 642 SCTAB nTabCount = pDoc->GetTableCount(); 643 if ( nMaxTab >= nTabCount && nMinTab > 0 ) 644 { 645 // move position and relative tab refs 646 // The formulas that use the name are not changed by this 647 648 SCTAB nMove = nMinTab; 649 aPos.SetTab( aPos.Tab() - nMove ); 650 651 pCode->Reset(); 652 while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL ) 653 { 654 ScSingleRefData& rRef1 = t->GetSingleRef(); 655 if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() ) 656 rRef1.nTab = sal::static_int_cast<SCsTAB>( rRef1.nTab - nMove ); 657 if ( t->GetType() == svDoubleRef ) 658 { 659 ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2; 660 if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() ) 661 rRef2.nTab = sal::static_int_cast<SCsTAB>( rRef2.nTab - nMove ); 662 } 663 } 664 } 665 } 666 667 668 extern "C" int 669 #ifdef WNT 670 __cdecl 671 #endif 672 ScRangeData_QsortNameCompare( const void* p1, const void* p2 ) 673 { 674 return (int) ScGlobal::GetCollator()->compareString( 675 (*(const ScRangeData**)p1)->GetName(), 676 (*(const ScRangeData**)p2)->GetName() ); 677 } 678 679 680 //======================================================================== 681 // ScRangeName 682 //======================================================================== 683 684 ScRangeName::ScRangeName(const ScRangeName& rScRangeName, ScDocument* pDocument) : 685 ScSortedCollection ( rScRangeName ), 686 pDoc ( pDocument ), 687 nSharedMaxIndex (rScRangeName.nSharedMaxIndex) 688 { 689 for (sal_uInt16 i = 0; i < nCount; i++) 690 { 691 ((ScRangeData*)At(i))->SetDocument(pDocument); 692 ((ScRangeData*)At(i))->SetIndex(((ScRangeData*)rScRangeName.At(i))->GetIndex()); 693 } 694 } 695 696 short ScRangeName::Compare(ScDataObject* pKey1, ScDataObject* pKey2) const 697 { 698 sal_uInt16 i1 = ((ScRangeData*)pKey1)->GetIndex(); 699 sal_uInt16 i2 = ((ScRangeData*)pKey2)->GetIndex(); 700 return (short) i1 - (short) i2; 701 } 702 703 sal_Bool ScRangeName::SearchNameUpper( const String& rUpperName, sal_uInt16& rIndex ) const 704 { 705 // SearchNameUpper must be called with an upper-case search string 706 707 sal_uInt16 i = 0; 708 while (i < nCount) 709 { 710 if ( ((*this)[i])->GetUpperName() == rUpperName ) 711 { 712 rIndex = i; 713 return sal_True; 714 } 715 i++; 716 } 717 return sal_False; 718 } 719 720 sal_Bool ScRangeName::SearchName( const String& rName, sal_uInt16& rIndex ) const 721 { 722 if ( nCount > 0 ) 723 return SearchNameUpper( ScGlobal::pCharClass->upper( rName ), rIndex ); 724 else 725 return sal_False; 726 } 727 728 void ScRangeName::UpdateReference( UpdateRefMode eUpdateRefMode, 729 const ScRange& rRange, 730 SCsCOL nDx, SCsROW nDy, SCsTAB nDz ) 731 { 732 for (sal_uInt16 i=0; i<nCount; i++) 733 ((ScRangeData*)pItems[i])->UpdateReference(eUpdateRefMode, rRange, 734 nDx, nDy, nDz); 735 } 736 737 void ScRangeName::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest ) 738 { 739 for (sal_uInt16 i=0; i<nCount; i++) 740 ((ScRangeData*)pItems[i])->UpdateTranspose( rSource, rDest ); 741 } 742 743 void ScRangeName::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY ) 744 { 745 for (sal_uInt16 i=0; i<nCount; i++) 746 ((ScRangeData*)pItems[i])->UpdateGrow( rArea, nGrowX, nGrowY ); 747 } 748 749 sal_Bool ScRangeName::IsEqual(ScDataObject* pKey1, ScDataObject* pKey2) const 750 { 751 return *(ScRangeData*)pKey1 == *(ScRangeData*)pKey2; 752 } 753 754 sal_Bool ScRangeName::Insert(ScDataObject* pScDataObject) 755 { 756 if (!((ScRangeData*)pScDataObject)->GetIndex()) // schon gesetzt? 757 { 758 ((ScRangeData*)pScDataObject)->SetIndex( GetEntryIndex() ); 759 } 760 761 return ScSortedCollection::Insert(pScDataObject); 762 } 763 764 // Suche nach einem freien Index 765 766 sal_uInt16 ScRangeName::GetEntryIndex() 767 { 768 sal_uInt16 nLast = 0; 769 for ( sal_uInt16 i = 0; i < nCount; i++ ) 770 { 771 sal_uInt16 nIdx = ((ScRangeData*)pItems[i])->GetIndex(); 772 if( nIdx > nLast ) 773 { 774 nLast = nIdx; 775 } 776 } 777 return nLast + 1; 778 } 779 780 ScRangeData* ScRangeName::FindIndex( sal_uInt16 nIndex ) 781 { 782 ScRangeData aDataObj( nIndex ); 783 sal_uInt16 n; 784 if( Search( &aDataObj, n ) ) 785 return (*this)[ n ]; 786 else 787 return NULL; 788 } 789 790 //UNUSED2009-05 ScRangeData* ScRangeName::GetRangeAtCursor( const ScAddress& rPos, sal_Bool bStartOnly ) const 791 //UNUSED2009-05 { 792 //UNUSED2009-05 if ( pItems ) 793 //UNUSED2009-05 { 794 //UNUSED2009-05 for ( sal_uInt16 i = 0; i < nCount; i++ ) 795 //UNUSED2009-05 if ( ((ScRangeData*)pItems[i])->IsRangeAtCursor( rPos, bStartOnly ) ) 796 //UNUSED2009-05 return (ScRangeData*)pItems[i]; 797 //UNUSED2009-05 } 798 //UNUSED2009-05 return NULL; 799 //UNUSED2009-05 } 800 801 ScRangeData* ScRangeName::GetRangeAtBlock( const ScRange& rBlock ) const 802 { 803 if ( pItems ) 804 { 805 for ( sal_uInt16 i = 0; i < nCount; i++ ) 806 if ( ((ScRangeData*)pItems[i])->IsRangeAtBlock( rBlock ) ) 807 return (ScRangeData*)pItems[i]; 808 } 809 return NULL; 810 } 811 812 void ScRangeName::UpdateTabRef(SCTAB nOldTable, sal_uInt16 nFlag, SCTAB nNewTable) 813 { 814 for (sal_uInt16 i=0; i<nCount; i++) 815 ((ScRangeData*)pItems[i])->UpdateTabRef(nOldTable, nFlag, nNewTable); 816 } 817 818 819 820 821