LCOV - code coverage report
Current view: top level - sc/source/core/tool - rangenam.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 426 0.0 %
Date: 2014-04-14 Functions: 0 61 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <string.h>
      21             : #include <boost/scoped_ptr.hpp>
      22             : #include <unotools/collatorwrapper.hxx>
      23             : #include <unotools/transliterationwrapper.hxx>
      24             : #include <com/sun/star/sheet/NamedRangeFlag.hpp>
      25             : 
      26             : #include "token.hxx"
      27             : #include "tokenarray.hxx"
      28             : #include "rangenam.hxx"
      29             : #include "global.hxx"
      30             : #include "compiler.hxx"
      31             : #include "rangeutl.hxx"
      32             : #include "rechead.hxx"
      33             : #include "refupdat.hxx"
      34             : #include "document.hxx"
      35             : #include "refupdatecontext.hxx"
      36             : #include <tokenstringcontext.hxx>
      37             : 
      38             : #include "formula/errorcodes.hxx"
      39             : 
      40             : using namespace formula;
      41             : using ::std::pair;
      42             : using ::std::unary_function;
      43             : 
      44             : // ScRangeData
      45             : 
      46           0 : ScRangeData::ScRangeData( ScDocument* pDok,
      47             :                           const OUString& rName,
      48             :                           const OUString& rSymbol,
      49             :                           const ScAddress& rAddress,
      50             :                           RangeType nType,
      51             :                           const FormulaGrammar::Grammar eGrammar ) :
      52             :                 aName       ( rName ),
      53             :                 aUpperName  ( ScGlobal::pCharClass->uppercase( rName ) ),
      54             :                 pCode       ( NULL ),
      55             :                 aPos        ( rAddress ),
      56             :                 eType       ( nType ),
      57             :                 pDoc        ( pDok ),
      58             :                 eTempGrammar( eGrammar ),
      59             :                 nIndex      ( 0 ),
      60             :                 bModified   ( false ),
      61             :                 mnMaxRow    (-1),
      62           0 :                 mnMaxCol    (-1)
      63             : {
      64           0 :     if (!rSymbol.isEmpty())
      65           0 :         CompileRangeData( rSymbol, pDoc->IsImportingXML());
      66             :         // Let the compiler set an error on unknown names for a subsequent
      67             :         // CompileUnresolvedXML().
      68             :     else
      69             :     {
      70             :         // #i63513#/#i65690# don't leave pCode as NULL.
      71             :         // Copy ctor default-constructs pCode if it was NULL, so it's initialized here, too,
      72             :         // to ensure same behavior if unnecessary copying is left out.
      73             : 
      74           0 :         pCode = new ScTokenArray();
      75             :     }
      76           0 : }
      77             : 
      78           0 : ScRangeData::ScRangeData( ScDocument* pDok,
      79             :                           const OUString& rName,
      80             :                           const ScTokenArray& rArr,
      81             :                           const ScAddress& rAddress,
      82             :                           RangeType nType ) :
      83             :                 aName       ( rName ),
      84             :                 aUpperName  ( ScGlobal::pCharClass->uppercase( rName ) ),
      85           0 :                 pCode       ( new ScTokenArray( rArr ) ),
      86             :                 aPos        ( rAddress ),
      87             :                 eType       ( nType ),
      88             :                 pDoc        ( pDok ),
      89             :                 eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED ),
      90             :                 nIndex      ( 0 ),
      91             :                 bModified   ( false ),
      92             :                 mnMaxRow    (-1),
      93           0 :                 mnMaxCol    (-1)
      94             : {
      95           0 :     InitCode();
      96           0 : }
      97             : 
      98           0 : ScRangeData::ScRangeData( ScDocument* pDok,
      99             :                           const OUString& rName,
     100             :                           const ScAddress& rTarget ) :
     101             :                 aName       ( rName ),
     102             :                 aUpperName  ( ScGlobal::pCharClass->uppercase( rName ) ),
     103           0 :                 pCode       ( new ScTokenArray() ),
     104             :                 aPos        ( rTarget ),
     105             :                 eType       ( RT_NAME ),
     106             :                 pDoc        ( pDok ),
     107             :                 eTempGrammar( FormulaGrammar::GRAM_UNSPECIFIED ),
     108             :                 nIndex      ( 0 ),
     109             :                 bModified   ( false ),
     110             :                 mnMaxRow    (-1),
     111           0 :                 mnMaxCol    (-1)
     112             : {
     113             :     ScSingleRefData aRefData;
     114           0 :     aRefData.InitAddress( rTarget );
     115           0 :     aRefData.SetFlag3D( true );
     116           0 :     pCode->AddSingleReference( aRefData );
     117           0 :     ScCompiler aComp( pDoc, aPos, *pCode );
     118           0 :     aComp.SetGrammar(pDoc->GetGrammar());
     119           0 :     aComp.CompileTokenArray();
     120           0 :     if ( !pCode->GetCodeError() )
     121           0 :         eType |= RT_ABSPOS;
     122           0 : }
     123             : 
     124           0 : ScRangeData::ScRangeData(const ScRangeData& rScRangeData, ScDocument* pDocument) :
     125             :     aName   (rScRangeData.aName),
     126             :     aUpperName  (rScRangeData.aUpperName),
     127           0 :     pCode       (rScRangeData.pCode ? rScRangeData.pCode->Clone() : new ScTokenArray()),   // make real copy (not copy-ctor)
     128             :     aPos        (rScRangeData.aPos),
     129             :     eType       (rScRangeData.eType),
     130             :     pDoc        (pDocument ? pDocument : rScRangeData.pDoc),
     131             :     eTempGrammar(rScRangeData.eTempGrammar),
     132             :     nIndex      (rScRangeData.nIndex),
     133             :     bModified   (rScRangeData.bModified),
     134             :     mnMaxRow    (rScRangeData.mnMaxRow),
     135           0 :     mnMaxCol    (rScRangeData.mnMaxCol)
     136           0 : {}
     137             : 
     138           0 : ScRangeData::~ScRangeData()
     139             : {
     140           0 :     delete pCode;
     141           0 : }
     142             : 
     143           0 : void ScRangeData::CompileRangeData( const OUString& rSymbol, bool bSetError )
     144             : {
     145           0 :     if (eTempGrammar == FormulaGrammar::GRAM_UNSPECIFIED)
     146             :     {
     147             :         OSL_FAIL( "ScRangeData::CompileRangeData: unspecified grammar");
     148             :         // Anything is almost as bad as this, but we might have the best choice
     149             :         // if not loading documents.
     150           0 :         eTempGrammar = FormulaGrammar::GRAM_NATIVE;
     151             :     }
     152             : 
     153           0 :     ScCompiler aComp( pDoc, aPos );
     154           0 :     aComp.SetGrammar( eTempGrammar);
     155           0 :     if (bSetError)
     156           0 :         aComp.SetExtendedErrorDetection( ScCompiler::EXTENDED_ERROR_DETECTION_NAME_NO_BREAK);
     157           0 :     ScTokenArray* pNewCode = aComp.CompileString( rSymbol );
     158           0 :     boost::scoped_ptr<ScTokenArray> pOldCode( pCode);     // old pCode will be deleted
     159           0 :     pCode = pNewCode;
     160           0 :     if( !pCode->GetCodeError() )
     161             :     {
     162           0 :         pCode->Reset();
     163           0 :         FormulaToken* p = pCode->GetNextReference();
     164           0 :         if( p )
     165             :         {
     166             :             // first token is a reference
     167             :             /* FIXME: wouldn't that need a check if it's exactly one reference? */
     168           0 :             if( p->GetType() == svSingleRef )
     169           0 :                 eType = eType | RT_ABSPOS;
     170             :             else
     171           0 :                 eType = eType | RT_ABSAREA;
     172             :         }
     173             :         // For manual input set an error for an incomplete formula.
     174           0 :         if (!pDoc->IsImportingXML())
     175             :         {
     176           0 :             aComp.CompileTokenArray();
     177           0 :             pCode->DelRPN();
     178             :         }
     179           0 :     }
     180           0 : }
     181             : 
     182           0 : void ScRangeData::CompileUnresolvedXML( sc::CompileFormulaContext& rCxt )
     183             : {
     184           0 :     if (pCode->GetCodeError() == errNoName)
     185             :     {
     186             :         // Reconstruct the symbol/formula and then recompile.
     187           0 :         OUString aSymbol;
     188           0 :         rCxt.setGrammar(eTempGrammar);
     189           0 :         ScCompiler aComp(rCxt, aPos, *pCode);
     190           0 :         aComp.CreateStringFromTokenArray( aSymbol);
     191             :         // Don't let the compiler set an error for unknown names on final
     192             :         // compile, errors are handled by the interpreter thereafter.
     193           0 :         CompileRangeData( aSymbol, false);
     194             :     }
     195           0 : }
     196             : 
     197             : #if DEBUG_FORMULA_COMPILER
     198             : void ScRangeData::Dump() const
     199             : {
     200             :     cout << "-- ScRangeData" << endl;
     201             :     cout << "  name: " << aName << endl;
     202             :     cout << "  ref position: (col=" << aPos.Col() << ", row=" << aPos.Row() << ", sheet=" << aPos.Tab() << ")" << endl;
     203             : 
     204             :     if (pCode)
     205             :         pCode->Dump();
     206             : }
     207             : #endif
     208             : 
     209           0 : void ScRangeData::GuessPosition()
     210             : {
     211             :     // set a position that allows "absoluting" of all relative references
     212             :     // in CalcAbsIfRel without errors
     213             : 
     214             :     OSL_ENSURE(aPos == ScAddress(), "position will go lost now");
     215             : 
     216           0 :     SCsCOL nMinCol = 0;
     217           0 :     SCsROW nMinRow = 0;
     218           0 :     SCsTAB nMinTab = 0;
     219             : 
     220             :     ScToken* t;
     221           0 :     pCode->Reset();
     222           0 :     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
     223             :     {
     224           0 :         ScSingleRefData& rRef1 = t->GetSingleRef();
     225           0 :         if ( rRef1.IsColRel() && rRef1.Col() < nMinCol )
     226           0 :             nMinCol = rRef1.Col();
     227           0 :         if ( rRef1.IsRowRel() && rRef1.Row() < nMinRow )
     228           0 :             nMinRow = rRef1.Row();
     229           0 :         if ( rRef1.IsTabRel() && rRef1.Tab() < nMinTab )
     230           0 :             nMinTab = rRef1.Tab();
     231             : 
     232           0 :         if ( t->GetType() == svDoubleRef )
     233             :         {
     234           0 :             ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
     235           0 :             if ( rRef2.IsColRel() && rRef2.Col() < nMinCol )
     236           0 :                 nMinCol = rRef2.Col();
     237           0 :             if ( rRef2.IsRowRel() && rRef2.Row() < nMinRow )
     238           0 :                 nMinRow = rRef2.Row();
     239           0 :             if ( rRef2.IsTabRel() && rRef2.Tab() < nMinTab )
     240           0 :                 nMinTab = rRef2.Tab();
     241             :         }
     242             :     }
     243             : 
     244           0 :     aPos = ScAddress( (SCCOL)(-nMinCol), (SCROW)(-nMinRow), (SCTAB)(-nMinTab) );
     245           0 : }
     246             : 
     247           0 : void ScRangeData::GetSymbol( OUString& rSymbol, const FormulaGrammar::Grammar eGrammar ) const
     248             : {
     249           0 :     ScCompiler aComp(pDoc, aPos, *pCode);
     250           0 :     aComp.SetGrammar(eGrammar);
     251           0 :     aComp.CreateStringFromTokenArray( rSymbol );
     252           0 : }
     253             : 
     254           0 : void ScRangeData::GetSymbol( OUString& rSymbol, const ScAddress& rPos, const FormulaGrammar::Grammar eGrammar ) const
     255             : {
     256           0 :     OUString aStr;
     257           0 :     ScCompiler aComp(pDoc, rPos, *pCode);
     258           0 :     aComp.SetGrammar(eGrammar);
     259           0 :     aComp.CreateStringFromTokenArray( aStr );
     260           0 :     rSymbol = aStr;
     261           0 : }
     262             : 
     263           0 : void ScRangeData::UpdateSymbol( OUStringBuffer& rBuffer, const ScAddress& rPos,
     264             :                                 const FormulaGrammar::Grammar eGrammar )
     265             : {
     266           0 :     boost::scoped_ptr<ScTokenArray> pTemp( pCode->Clone() );
     267           0 :     ScCompiler aComp( pDoc, rPos, *pTemp.get());
     268           0 :     aComp.SetGrammar(eGrammar);
     269           0 :     aComp.MoveRelWrap(GetMaxCol(), GetMaxRow());
     270           0 :     aComp.CreateStringFromTokenArray( rBuffer );
     271           0 : }
     272             : 
     273           0 : void ScRangeData::UpdateReference( sc::RefUpdateContext& rCxt, SCTAB nLocalTab )
     274             : {
     275           0 :     sc::RefUpdateResult aRes = pCode->AdjustReferenceInName(rCxt, aPos);
     276           0 :     bModified = aRes.mbReferenceModified;
     277           0 :     if (aRes.mbReferenceModified)
     278           0 :         rCxt.maUpdatedNames.setUpdatedName(nLocalTab, nIndex);
     279           0 : }
     280             : 
     281           0 : void ScRangeData::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest )
     282             : {
     283           0 :     bool bChanged = false;
     284             : 
     285             :     ScToken* t;
     286           0 :     pCode->Reset();
     287             : 
     288           0 :     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
     289             :     {
     290           0 :         if( t->GetType() != svIndex )
     291             :         {
     292           0 :             SingleDoubleRefModifier aMod( *t );
     293           0 :             ScComplexRefData& rRef = aMod.Ref();
     294           0 :             if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
     295           0 :                     (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
     296           0 :                 ( t->GetType() == svSingleRef ||
     297           0 :                 (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
     298           0 :                     (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
     299             :             {
     300           0 :                 ScRange aAbs = rRef.toAbs(aPos);
     301           0 :                 if (ScRefUpdate::UpdateTranspose(pDoc, rSource, rDest, aAbs) != UR_NOTHING)
     302             :                 {
     303           0 :                     rRef.SetRange(aAbs, aPos);
     304           0 :                     bChanged = true;
     305             :                 }
     306           0 :             }
     307             :         }
     308             :     }
     309             : 
     310           0 :     bModified = bChanged;
     311           0 : }
     312             : 
     313           0 : void ScRangeData::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
     314             : {
     315           0 :     bool bChanged = false;
     316             : 
     317             :     ScToken* t;
     318           0 :     pCode->Reset();
     319             : 
     320           0 :     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
     321             :     {
     322           0 :         if( t->GetType() != svIndex )
     323             :         {
     324           0 :             SingleDoubleRefModifier aMod( *t );
     325           0 :             ScComplexRefData& rRef = aMod.Ref();
     326           0 :             if (!rRef.Ref1.IsColRel() && !rRef.Ref1.IsRowRel() &&
     327           0 :                     (!rRef.Ref1.IsFlag3D() || !rRef.Ref1.IsTabRel()) &&
     328           0 :                 ( t->GetType() == svSingleRef ||
     329           0 :                 (!rRef.Ref2.IsColRel() && !rRef.Ref2.IsRowRel() &&
     330           0 :                     (!rRef.Ref2.IsFlag3D() || !rRef.Ref2.IsTabRel()))))
     331             :             {
     332           0 :                 ScRange aAbs = rRef.toAbs(aPos);
     333           0 :                 if (ScRefUpdate::UpdateGrow(rArea, nGrowX, nGrowY, aAbs) != UR_NOTHING)
     334             :                 {
     335           0 :                     rRef.SetRange(aAbs, aPos);
     336           0 :                     bChanged = true;
     337             :                 }
     338           0 :             }
     339             :         }
     340             :     }
     341             : 
     342           0 :     bModified = bChanged;           // has to be evaluated immediately afterwards
     343           0 : }
     344             : 
     345           0 : bool ScRangeData::operator== (const ScRangeData& rData) const       // for Undo
     346             : {
     347           0 :     if ( nIndex != rData.nIndex ||
     348           0 :          aName  != rData.aName  ||
     349           0 :          aPos   != rData.aPos   ||
     350           0 :          eType  != rData.eType     ) return false;
     351             : 
     352           0 :     sal_uInt16 nLen = pCode->GetLen();
     353           0 :     if ( nLen != rData.pCode->GetLen() ) return false;
     354             : 
     355           0 :     FormulaToken** ppThis = pCode->GetArray();
     356           0 :     FormulaToken** ppOther = rData.pCode->GetArray();
     357             : 
     358           0 :     for ( sal_uInt16 i=0; i<nLen; i++ )
     359           0 :         if ( ppThis[i] != ppOther[i] && !(*ppThis[i] == *ppOther[i]) )
     360           0 :             return false;
     361             : 
     362           0 :     return true;
     363             : }
     364             : 
     365           0 : bool ScRangeData::IsRangeAtBlock( const ScRange& rBlock ) const
     366             : {
     367           0 :     bool bRet = false;
     368           0 :     ScRange aRange;
     369           0 :     if ( IsReference(aRange) )
     370           0 :         bRet = ( rBlock == aRange );
     371           0 :     return bRet;
     372             : }
     373             : 
     374           0 : bool ScRangeData::IsReference( ScRange& rRange ) const
     375             : {
     376           0 :     if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS )) && pCode )
     377           0 :         return pCode->IsReference(rRange, aPos);
     378             : 
     379           0 :     return false;
     380             : }
     381             : 
     382           0 : bool ScRangeData::IsReference( ScRange& rRange, const ScAddress& rPos ) const
     383             : {
     384           0 :     if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode )
     385           0 :         return pCode->IsReference(rRange, rPos);
     386             : 
     387           0 :     return false;
     388             : }
     389             : 
     390           0 : bool ScRangeData::IsValidReference( ScRange& rRange ) const
     391             : {
     392           0 :     if ( (eType & ( RT_ABSAREA | RT_REFAREA | RT_ABSPOS ) ) && pCode )
     393           0 :         return pCode->IsValidReference(rRange, aPos);
     394             : 
     395           0 :     return false;
     396             : }
     397             : 
     398           0 : void ScRangeData::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt, SCTAB nLocalTab )
     399             : {
     400           0 :     sc::RefUpdateResult aRes = pCode->AdjustReferenceOnInsertedTab(rCxt, aPos);
     401           0 :     if (aRes.mbReferenceModified)
     402           0 :         rCxt.maUpdatedNames.setUpdatedName(nLocalTab, nIndex);
     403             : 
     404           0 :     if (rCxt.mnInsertPos <= aPos.Tab())
     405           0 :         aPos.IncTab(rCxt.mnSheets);
     406           0 : }
     407             : 
     408           0 : void ScRangeData::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt, SCTAB nLocalTab )
     409             : {
     410           0 :     sc::RefUpdateResult aRes = pCode->AdjustReferenceOnDeletedTab(rCxt, aPos);
     411           0 :     if (aRes.mbReferenceModified)
     412           0 :         rCxt.maUpdatedNames.setUpdatedName(nLocalTab, nIndex);
     413             : 
     414           0 :     if (rCxt.mnDeletePos <= aPos.Tab())
     415           0 :         aPos.IncTab(-rCxt.mnSheets);
     416           0 : }
     417             : 
     418           0 : void ScRangeData::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt, SCTAB nLocalTab )
     419             : {
     420           0 :     sc::RefUpdateResult aRes = pCode->AdjustReferenceOnMovedTab(rCxt, aPos);
     421           0 :     if (aRes.mbReferenceModified)
     422           0 :         rCxt.maUpdatedNames.setUpdatedName(nLocalTab, nIndex);
     423             : 
     424           0 :     aPos.SetTab(rCxt.getNewTab(aPos.Tab()));
     425           0 : }
     426             : 
     427           0 : void ScRangeData::MakeValidName( OUString& rName )
     428             : {
     429             : 
     430             :     // strip leading invalid characters
     431           0 :     sal_Int32 nPos = 0;
     432           0 :     sal_Int32 nLen = rName.getLength();
     433           0 :     while ( nPos < nLen && !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
     434           0 :         ++nPos;
     435           0 :     if ( nPos>0 )
     436           0 :         rName = rName.copy(nPos);
     437             : 
     438             :     // if the first character is an invalid start character, precede with '_'
     439           0 :     if ( !rName.isEmpty() && !ScCompiler::IsCharFlagAllConventions( rName, 0, SC_COMPILER_C_CHAR_NAME ) )
     440           0 :         rName = "_" + rName;
     441             : 
     442             :     // replace invalid with '_'
     443           0 :     nLen = rName.getLength();
     444           0 :     for (nPos=0; nPos<nLen; nPos++)
     445             :     {
     446           0 :         if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
     447           0 :             rName = rName.replaceAt( nPos, 1, "_" );
     448             :     }
     449             : 
     450             :     // Ensure that the proposed name is not a reference under any convention,
     451             :     // same as in IsNameValid()
     452           0 :     ScAddress aAddr;
     453           0 :     ScRange aRange;
     454           0 :     for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
     455             :     {
     456           0 :         ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
     457             :         // Don't check Parse on VALID, any partial only VALID may result in
     458             :         // #REF! during compile later!
     459           0 :         while (aRange.Parse( rName, NULL, details) || aAddr.Parse( rName, NULL, details))
     460             :         {
     461             :             //! Range Parse is partially valid also with invalid sheet name,
     462             :             //! Address Parse dito, during compile name would generate a #REF!
     463           0 :             if ( rName.indexOf( '.' ) == -1 )
     464           0 :                 rName = rName.replaceFirst( ".", "_" );
     465             :             else
     466           0 :                 rName = "_" + rName;
     467             :         }
     468             :     }
     469           0 : }
     470             : 
     471           0 : bool ScRangeData::IsNameValid( const OUString& rName, ScDocument* pDoc )
     472             : {
     473             :     /* XXX If changed, sc/source/filter/ftools/ftools.cxx
     474             :      * ScfTools::ConvertToScDefinedName needs to be changed too. */
     475           0 :     sal_Char a('.');
     476           0 :     if (rName.indexOf(a) != -1)
     477           0 :         return false;
     478           0 :     sal_Int32 nPos = 0;
     479           0 :     sal_Int32 nLen = rName.getLength();
     480           0 :     if ( !nLen || !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_CHAR_NAME ) )
     481           0 :         return false;
     482           0 :     while ( nPos < nLen )
     483             :     {
     484           0 :         if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_NAME ) )
     485           0 :             return false;
     486             :     }
     487           0 :     ScAddress aAddr;
     488           0 :     ScRange aRange;
     489           0 :     for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
     490             :     {
     491           0 :         ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
     492             :         // Don't check Parse on VALID, any partial only VALID may result in
     493             :         // #REF! during compile later!
     494           0 :         if (aRange.Parse( rName, pDoc, details) || aAddr.Parse( rName, pDoc, details))
     495           0 :             return false;
     496             :     }
     497           0 :     return true;
     498             : }
     499             : 
     500           0 : SCROW ScRangeData::GetMaxRow() const
     501             : {
     502           0 :     return mnMaxRow >= 0 ? mnMaxRow : MAXROW;
     503             : }
     504             : 
     505           0 : SCCOL ScRangeData::GetMaxCol() const
     506             : {
     507           0 :     return mnMaxCol >= 0 ? mnMaxCol : MAXCOL;
     508             : }
     509             : 
     510           0 : sal_uInt16 ScRangeData::GetErrCode() const
     511             : {
     512           0 :     return pCode ? pCode->GetCodeError() : 0;
     513             : }
     514             : 
     515           0 : bool ScRangeData::HasReferences() const
     516             : {
     517           0 :     return pCode->HasReferences();
     518             : }
     519             : 
     520           0 : sal_uInt32 ScRangeData::GetUnoType() const
     521             : {
     522           0 :     sal_uInt32 nUnoType = 0;
     523           0 :     if ( HasType(RT_CRITERIA) )  nUnoType |= com::sun::star::sheet::NamedRangeFlag::FILTER_CRITERIA;
     524           0 :     if ( HasType(RT_PRINTAREA) ) nUnoType |= com::sun::star::sheet::NamedRangeFlag::PRINT_AREA;
     525           0 :     if ( HasType(RT_COLHEADER) ) nUnoType |= com::sun::star::sheet::NamedRangeFlag::COLUMN_HEADER;
     526           0 :     if ( HasType(RT_ROWHEADER) ) nUnoType |= com::sun::star::sheet::NamedRangeFlag::ROW_HEADER;
     527           0 :     return nUnoType;
     528             : }
     529             : 
     530           0 : void ScRangeData::ValidateTabRefs()
     531             : {
     532             :     //  try to make sure all relative references and the reference position
     533             :     //  are within existing tables, so they can be represented as text
     534             :     //  (if the range of used tables is more than the existing tables,
     535             :     //  the result may still contain invalid tables, because the relative
     536             :     //  references aren't changed so formulas stay the same)
     537             : 
     538             :     //  find range of used tables
     539             : 
     540           0 :     SCTAB nMinTab = aPos.Tab();
     541           0 :     SCTAB nMaxTab = nMinTab;
     542             :     ScToken* t;
     543           0 :     pCode->Reset();
     544           0 :     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
     545             :     {
     546           0 :         ScSingleRefData& rRef1 = t->GetSingleRef();
     547           0 :         ScAddress aAbs = rRef1.toAbs(aPos);
     548           0 :         if ( rRef1.IsTabRel() && !rRef1.IsTabDeleted() )
     549             :         {
     550           0 :             if (aAbs.Tab() < nMinTab)
     551           0 :                 nMinTab = aAbs.Tab();
     552           0 :             if (aAbs.Tab() > nMaxTab)
     553           0 :                 nMaxTab = aAbs.Tab();
     554             :         }
     555           0 :         if ( t->GetType() == svDoubleRef )
     556             :         {
     557           0 :             ScSingleRefData& rRef2 = t->GetDoubleRef().Ref2;
     558           0 :             aAbs = rRef2.toAbs(aPos);
     559           0 :             if ( rRef2.IsTabRel() && !rRef2.IsTabDeleted() )
     560             :             {
     561           0 :                 if (aAbs.Tab() < nMinTab)
     562           0 :                     nMinTab = aAbs.Tab();
     563           0 :                 if (aAbs.Tab() > nMaxTab)
     564           0 :                     nMaxTab = aAbs.Tab();
     565             :             }
     566             :         }
     567             :     }
     568             : 
     569           0 :     SCTAB nTabCount = pDoc->GetTableCount();
     570           0 :     if ( nMaxTab >= nTabCount && nMinTab > 0 )
     571             :     {
     572             :         //  move position and relative tab refs
     573             :         //  The formulas that use the name are not changed by this
     574             : 
     575           0 :         SCTAB nMove = nMinTab;
     576           0 :         ScAddress aOldPos = aPos;
     577           0 :         aPos.SetTab( aPos.Tab() - nMove );
     578             : 
     579           0 :         pCode->Reset();
     580           0 :         while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
     581             :         {
     582           0 :             switch (t->GetType())
     583             :             {
     584             :                 case svSingleRef:
     585             :                 {
     586           0 :                     ScSingleRefData& rRef = t->GetSingleRef();
     587           0 :                     if (!rRef.IsTabDeleted())
     588             :                     {
     589           0 :                         ScAddress aAbs = rRef.toAbs(aOldPos);
     590           0 :                         rRef.SetAddress(aAbs, aPos);
     591             :                     }
     592             :                 }
     593           0 :                 break;
     594             :                 case svDoubleRef:
     595             :                 {
     596           0 :                     ScComplexRefData& rRef = t->GetDoubleRef();
     597           0 :                     if (!rRef.Ref1.IsTabDeleted())
     598             :                     {
     599           0 :                         ScAddress aAbs = rRef.Ref1.toAbs(aOldPos);
     600           0 :                         rRef.Ref1.SetAddress(aAbs, aPos);
     601             :                     }
     602           0 :                     if (!rRef.Ref2.IsTabDeleted())
     603             :                     {
     604           0 :                         ScAddress aAbs = rRef.Ref2.toAbs(aOldPos);
     605           0 :                         rRef.Ref2.SetAddress(aAbs, aPos);
     606             :                     }
     607             :                 }
     608           0 :                 break;
     609             :                 default:
     610             :                     ;
     611             :             }
     612             :         }
     613             :     }
     614           0 : }
     615             : 
     616           0 : void ScRangeData::SetCode( ScTokenArray& rArr )
     617             : {
     618           0 :     boost::scoped_ptr<ScTokenArray> pOldCode( pCode); // old pCode will be deleted
     619           0 :     pCode = new ScTokenArray( rArr );
     620           0 :     InitCode();
     621           0 : }
     622             : 
     623           0 : void ScRangeData::InitCode()
     624             : {
     625           0 :     if( !pCode->GetCodeError() )
     626             :     {
     627           0 :         pCode->Reset();
     628           0 :         FormulaToken* p = pCode->GetNextReference();
     629           0 :         if( p )   // exact one reference at first
     630             :         {
     631           0 :             if( p->GetType() == svSingleRef )
     632           0 :                 eType = eType | RT_ABSPOS;
     633             :             else
     634           0 :                 eType = eType | RT_ABSAREA;
     635             :         }
     636             :     }
     637           0 : }
     638             : 
     639             : extern "C"
     640           0 : int SAL_CALL ScRangeData_QsortNameCompare( const void* p1, const void* p2 )
     641             : {
     642             :     return (int) ScGlobal::GetCollator()->compareString(
     643           0 :             (*(const ScRangeData**)p1)->GetName(),
     644           0 :             (*(const ScRangeData**)p2)->GetName() );
     645             : }
     646             : 
     647           0 : bool operator<(const ScRangeData& left, const ScRangeData& right)
     648             : {
     649           0 :     return left.GetName() < right.GetName();
     650             : }
     651             : 
     652             : namespace {
     653             : 
     654             : /**
     655             :  * Predicate to check if the name references the specified range.
     656             :  */
     657             : class MatchByRange : public unary_function<ScRangeData, bool>
     658             : {
     659             :     const ScRange& mrRange;
     660             : public:
     661           0 :     MatchByRange(const ScRange& rRange) : mrRange(rRange) {}
     662             :     template < typename Pair >
     663           0 :     bool operator() ( Pair const& r) const
     664             :     {
     665           0 :         return r.second->IsRangeAtBlock(mrRange);
     666             :     }
     667             : };
     668             : 
     669             : }
     670             : 
     671           0 : ScRangeName::ScRangeName() {}
     672             : 
     673           0 : ScRangeName::ScRangeName(const ScRangeName& r) :
     674           0 :     maData(r.maData)
     675             : {
     676             :     // boost::ptr_set clones and deletes, so each collection needs its own
     677             :     // index to data.
     678           0 :     maIndexToData.resize( r.maIndexToData.size(), NULL);
     679           0 :     DataType::const_iterator itr = maData.begin(), itrEnd = maData.end();
     680           0 :     for (; itr != itrEnd; ++itr)
     681             :     {
     682           0 :         size_t nPos = itr->second->GetIndex() - 1;
     683           0 :         if (nPos >= maIndexToData.size())
     684             :         {
     685             :             OSL_FAIL( "ScRangeName copy-ctor: maIndexToData size doesn't fit");
     686           0 :             maIndexToData.resize(nPos+1, NULL);
     687             :         }
     688           0 :         maIndexToData[nPos] = const_cast<ScRangeData*>(itr->second);
     689             :     }
     690           0 : }
     691             : 
     692           0 : const ScRangeData* ScRangeName::findByRange(const ScRange& rRange) const
     693             : {
     694             :     DataType::const_iterator itr = std::find_if(
     695           0 :         maData.begin(), maData.end(), MatchByRange(rRange));
     696           0 :     return itr == maData.end() ? NULL : itr->second;
     697             : }
     698             : 
     699           0 : ScRangeData* ScRangeName::findByUpperName(const OUString& rName)
     700             : {
     701           0 :     DataType::iterator itr = maData.find(rName);
     702           0 :     return itr == maData.end() ? NULL : itr->second;
     703             : }
     704             : 
     705           0 : const ScRangeData* ScRangeName::findByUpperName(const OUString& rName) const
     706             : {
     707           0 :     DataType::const_iterator itr = maData.find(rName);
     708           0 :     return itr == maData.end() ? NULL : itr->second;
     709             : }
     710             : 
     711           0 : ScRangeData* ScRangeName::findByIndex(sal_uInt16 i) const
     712             : {
     713           0 :     if (!i)
     714             :         // index should never be zero.
     715           0 :         return NULL;
     716             : 
     717           0 :     size_t nPos = i - 1;
     718           0 :     return nPos < maIndexToData.size() ? maIndexToData[nPos] : NULL;
     719             : }
     720             : 
     721           0 : void ScRangeName::UpdateReference(sc::RefUpdateContext& rCxt, SCTAB nLocalTab )
     722             : {
     723           0 :     DataType::iterator itr = maData.begin(), itrEnd = maData.end();
     724           0 :     for (; itr != itrEnd; ++itr)
     725           0 :         itr->second->UpdateReference(rCxt, nLocalTab);
     726           0 : }
     727             : 
     728           0 : void ScRangeName::UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt, SCTAB nLocalTab )
     729             : {
     730           0 :     DataType::iterator itr = maData.begin(), itrEnd = maData.end();
     731           0 :     for (; itr != itrEnd; ++itr)
     732           0 :         itr->second->UpdateInsertTab(rCxt, nLocalTab);
     733           0 : }
     734             : 
     735           0 : void ScRangeName::UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt, SCTAB nLocalTab )
     736             : {
     737           0 :     DataType::iterator itr = maData.begin(), itrEnd = maData.end();
     738           0 :     for (; itr != itrEnd; ++itr)
     739           0 :         itr->second->UpdateDeleteTab(rCxt, nLocalTab);
     740           0 : }
     741             : 
     742           0 : void ScRangeName::UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt, SCTAB nLocalTab )
     743             : {
     744           0 :     DataType::iterator itr = maData.begin(), itrEnd = maData.end();
     745           0 :     for (; itr != itrEnd; ++itr)
     746           0 :         itr->second->UpdateMoveTab(rCxt, nLocalTab);
     747           0 : }
     748             : 
     749           0 : void ScRangeName::UpdateTranspose(const ScRange& rSource, const ScAddress& rDest)
     750             : {
     751           0 :     DataType::iterator itr = maData.begin(), itrEnd = maData.end();
     752           0 :     for (; itr != itrEnd; ++itr)
     753           0 :         itr->second->UpdateTranspose(rSource, rDest);
     754           0 : }
     755             : 
     756           0 : void ScRangeName::UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY)
     757             : {
     758           0 :     DataType::iterator itr = maData.begin(), itrEnd = maData.end();
     759           0 :     for (; itr != itrEnd; ++itr)
     760           0 :         itr->second->UpdateGrow(rArea, nGrowX, nGrowY);
     761           0 : }
     762             : 
     763           0 : void ScRangeName::CompileUnresolvedXML( sc::CompileFormulaContext& rCxt )
     764             : {
     765           0 :     DataType::iterator itr = maData.begin(), itrEnd = maData.end();
     766           0 :     for (; itr != itrEnd; ++itr)
     767           0 :         itr->second->CompileUnresolvedXML(rCxt);
     768           0 : }
     769             : 
     770           0 : ScRangeName::const_iterator ScRangeName::begin() const
     771             : {
     772           0 :     return maData.begin();
     773             : }
     774             : 
     775           0 : ScRangeName::const_iterator ScRangeName::end() const
     776             : {
     777           0 :     return maData.end();
     778             : }
     779             : 
     780           0 : ScRangeName::iterator ScRangeName::begin()
     781             : {
     782           0 :     return maData.begin();
     783             : }
     784             : 
     785           0 : ScRangeName::iterator ScRangeName::end()
     786             : {
     787           0 :     return maData.end();
     788             : }
     789             : 
     790           0 : size_t ScRangeName::size() const
     791             : {
     792           0 :     return maData.size();
     793             : }
     794             : 
     795           0 : bool ScRangeName::empty() const
     796             : {
     797           0 :     return maData.empty();
     798             : }
     799             : 
     800           0 : bool ScRangeName::insert(ScRangeData* p)
     801             : {
     802           0 :     if (!p)
     803           0 :         return false;
     804             : 
     805           0 :     if (!p->GetIndex())
     806             :     {
     807             :         // Assign a new index.  An index must be unique and is never 0.
     808             :         IndexDataType::iterator itr = std::find(
     809           0 :             maIndexToData.begin(), maIndexToData.end(), static_cast<ScRangeData*>(NULL));
     810           0 :         if (itr != maIndexToData.end())
     811             :         {
     812             :             // Empty slot exists.  Re-use it.
     813           0 :             size_t nPos = std::distance(maIndexToData.begin(), itr);
     814           0 :             p->SetIndex(nPos + 1);
     815             :         }
     816             :         else
     817             :             // No empty slot.  Append it to the end.
     818           0 :             p->SetIndex(maIndexToData.size() + 1);
     819             :     }
     820             : 
     821           0 :     OUString aName(p->GetUpperName());
     822           0 :     erase(aName); // ptr_map won't insert it if a duplicate name exists.
     823           0 :     pair<DataType::iterator, bool> r = maData.insert(aName, p);
     824           0 :     if (r.second)
     825             :     {
     826             :         // Data inserted.  Store its index for mapping.
     827           0 :         size_t nPos = p->GetIndex() - 1;
     828           0 :         if (nPos >= maIndexToData.size())
     829           0 :             maIndexToData.resize(nPos+1, NULL);
     830           0 :         maIndexToData[nPos] = p;
     831             :     }
     832           0 :     return r.second;
     833             : }
     834             : 
     835           0 : void ScRangeName::erase(const ScRangeData& r)
     836             : {
     837           0 :     erase(r.GetUpperName());
     838           0 : }
     839             : 
     840           0 : void ScRangeName::erase(const OUString& rName)
     841             : {
     842           0 :     DataType::iterator itr = maData.find(rName);
     843           0 :     if (itr != maData.end())
     844           0 :         erase(itr);
     845           0 : }
     846             : 
     847           0 : void ScRangeName::erase(const iterator& itr)
     848             : {
     849           0 :     sal_uInt16 nIndex = itr->second->GetIndex();
     850           0 :     maData.erase(itr);
     851             :     OSL_ENSURE( 0 < nIndex && nIndex <= maIndexToData.size(), "ScRangeName::erase: bad index");
     852           0 :     if (0 < nIndex && nIndex <= maIndexToData.size())
     853           0 :         maIndexToData[nIndex-1] = NULL;
     854           0 : }
     855             : 
     856           0 : void ScRangeName::clear()
     857             : {
     858           0 :     maData.clear();
     859           0 :     maIndexToData.clear();
     860           0 : }
     861             : 
     862           0 : bool ScRangeName::operator== (const ScRangeName& r) const
     863             : {
     864           0 :     return maData == r.maData;
     865             : }
     866             : 
     867             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10