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