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

Generated by: LCOV version 1.10