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

Generated by: LCOV version 1.11