LCOV - code coverage report
Current view: top level - libreoffice/sc/source/core/data - cell2.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 206 834 24.7 %
Date: 2012-12-27 Functions: 24 69 34.8 %
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 <algorithm>
      21             : #include <deque>
      22             : 
      23             : #include <boost/bind.hpp>
      24             : #include <sal/macros.h>
      25             : #include <vcl/mapmod.hxx>
      26             : #include <editeng/editobj.hxx>
      27             : #include <editeng/editstat.hxx>
      28             : #include "editeng/fieldupdater.hxx"
      29             : 
      30             : #include "cell.hxx"
      31             : #include "compiler.hxx"
      32             : #include "formula/errorcodes.hxx"
      33             : #include "document.hxx"
      34             : #include "rangenam.hxx"
      35             : #include "rechead.hxx"
      36             : #include "refupdat.hxx"
      37             : #include "scmatrix.hxx"
      38             : #include "editutil.hxx"
      39             : #include "chgtrack.hxx"
      40             : #include "externalrefmgr.hxx"
      41             : #include "scitems.hxx"
      42             : #include "patattr.hxx"
      43             : #include <rtl/strbuf.hxx>
      44             : 
      45             : using namespace formula;
      46             : 
      47             : // STATIC DATA -----------------------------------------------------------
      48             : 
      49             : #ifdef USE_MEMPOOL
      50           5 : IMPL_FIXEDMEMPOOL_NEWDEL( ScEditCell )
      51             : #endif
      52             : 
      53             : // ============================================================================
      54             : 
      55          55 : ScEditCell::ScEditCell( const EditTextObject* pObject, ScDocument* pDocP,
      56             :             const SfxItemPool* pFromPool )  :
      57             :         ScBaseCell( CELLTYPE_EDIT ),
      58             :         pString( NULL ),
      59          55 :         pDoc( pDocP )
      60             : {
      61          55 :     SetTextObject( pObject, pFromPool );
      62          55 : }
      63             : 
      64           0 : ScEditCell::ScEditCell(const ScEditCell& rCell, ScDocument& rDoc, const ScAddress& rDestPos) :
      65           0 :     ScBaseCell(rCell), pString(NULL), pDoc(&rDoc)
      66             : {
      67           0 :     SetTextObject( rCell.pData, rCell.pDoc->GetEditPool() );
      68           0 :     UpdateFields(rDestPos.Tab());
      69           0 : }
      70             : 
      71          29 : ScEditCell::ScEditCell( const rtl::OUString& rString, ScDocument* pDocP )  :
      72             :         ScBaseCell( CELLTYPE_EDIT ),
      73             :         pString( NULL ),
      74          29 :         pDoc( pDocP )
      75             : {
      76             :     OSL_ENSURE( rString.indexOf('\n') != -1 ||
      77             :                 rString.indexOf(CHAR_CR) != -1,
      78             :                 "EditCell mit einfachem Text !?!?" );
      79             : 
      80          29 :     EditEngine& rEngine = pDoc->GetEditEngine();
      81          29 :     rEngine.SetText( rString );
      82          29 :     pData = rEngine.CreateTextObject();
      83          29 : }
      84             : 
      85         168 : ScEditCell::~ScEditCell()
      86             : {
      87          84 :     delete pData;
      88          84 :     delete pString;
      89             : 
      90             : #if OSL_DEBUG_LEVEL > 0
      91             :     eCellType = CELLTYPE_DESTROYED;
      92             : #endif
      93          84 : }
      94             : 
      95           0 : void ScEditCell::SetData( const EditTextObject* pObject,
      96             :             const SfxItemPool* pFromPool )
      97             : {
      98           0 :     if ( pString )
      99             :     {
     100           0 :         delete pString;
     101           0 :         pString = NULL;
     102             :     }
     103           0 :     delete pData;
     104           0 :     SetTextObject( pObject, pFromPool );
     105           0 : }
     106             : 
     107          17 : void ScEditCell::GetData( const EditTextObject*& rpObject ) const
     108             : {
     109          17 :     rpObject = pData;
     110          17 : }
     111             : 
     112          51 : rtl::OUString ScEditCell::GetString() const
     113             : {
     114          51 :     if ( pString )
     115          32 :         return *pString;
     116             : 
     117          19 :     if ( pData )
     118             :     {
     119             :         // Also Text from URL fields, Doc-Engine is a ScFieldEditEngine
     120          19 :         EditEngine& rEngine = pDoc->GetEditEngine();
     121          19 :         rEngine.SetText( *pData );
     122          19 :         rtl::OUString sRet = ScEditUtil::GetMultilineString(rEngine); // string with line separators between paragraphs
     123             :         // cache short strings for formulas
     124          19 :         if ( sRet.getLength() < 256 )
     125          19 :             pString = new rtl::OUString(sRet);   //! non-const
     126          19 :         return sRet;
     127             :     }
     128             : 
     129           0 :     return rtl::OUString();
     130             : }
     131             : 
     132           0 : void ScEditCell::RemoveCharAttribs( const ScPatternAttr& rAttr )
     133             : {
     134             :     const struct {
     135             :         sal_uInt16 nAttrType;
     136             :         sal_uInt16 nCharType;
     137             :     } AttrTypeMap[] = {
     138             :         { ATTR_FONT,        EE_CHAR_FONTINFO },
     139             :         { ATTR_FONT_HEIGHT, EE_CHAR_FONTHEIGHT },
     140             :         { ATTR_FONT_WEIGHT, EE_CHAR_WEIGHT },
     141             :         { ATTR_FONT_COLOR,  EE_CHAR_COLOR }
     142           0 :     };
     143           0 :     sal_uInt16 nMapCount = sizeof (AttrTypeMap) / sizeof (AttrTypeMap[0]);
     144             : 
     145           0 :     const SfxItemSet& rSet = rAttr.GetItemSet();
     146             :     const SfxPoolItem* pItem;
     147           0 :     for (sal_uInt16 i = 0; i < nMapCount; ++i)
     148             :     {
     149           0 :         if ( rSet.GetItemState(AttrTypeMap[i].nAttrType, false, &pItem) == SFX_ITEM_SET )
     150           0 :             pData->RemoveCharAttribs(AttrTypeMap[i].nCharType);
     151             :     }
     152           0 : }
     153             : 
     154           0 : void ScEditCell::UpdateFields(SCTAB nTab)
     155             : {
     156           0 :     editeng::FieldUpdater aUpdater = pData->GetFieldUpdater();
     157           0 :     aUpdater.updateTableFields(nTab);
     158           0 : }
     159             : 
     160          55 : void ScEditCell::SetTextObject( const EditTextObject* pObject,
     161             :             const SfxItemPool* pFromPool )
     162             : {
     163          55 :     if ( pObject )
     164             :     {
     165          55 :         if ( pFromPool && pDoc->GetEditPool() == pFromPool )
     166          55 :             pData = pObject->Clone();
     167             :         else
     168             :         {   //! another "spool"
     169             :             // Sadly there is no other way to change the Pool than to
     170             :             // "spool" the Object through a corresponding Engine
     171           0 :             EditEngine& rEngine = pDoc->GetEditEngine();
     172           0 :             if ( pObject->HasOnlineSpellErrors() )
     173             :             {
     174           0 :                 sal_uLong nControl = rEngine.GetControlWord();
     175           0 :                 const sal_uLong nSpellControl = EE_CNTRL_ONLINESPELLING | EE_CNTRL_ALLOWBIGOBJS;
     176           0 :                 bool bNewControl = ( (nControl & nSpellControl) != nSpellControl );
     177           0 :                 if ( bNewControl )
     178           0 :                     rEngine.SetControlWord( nControl | nSpellControl );
     179           0 :                 rEngine.SetText( *pObject );
     180           0 :                 pData = rEngine.CreateTextObject();
     181           0 :                 if ( bNewControl )
     182           0 :                     rEngine.SetControlWord( nControl );
     183             :             }
     184             :             else
     185             :             {
     186           0 :                 rEngine.SetText( *pObject );
     187           0 :                 pData = rEngine.CreateTextObject();
     188             :             }
     189             :         }
     190             :     }
     191             :     else
     192           0 :         pData = NULL;
     193          55 : }
     194             : 
     195           0 : ScEditDataArray::ScEditDataArray()
     196             : {
     197           0 : }
     198             : 
     199           0 : ScEditDataArray::~ScEditDataArray()
     200             : {
     201           0 : }
     202             : 
     203           0 : void ScEditDataArray::AddItem(SCTAB nTab, SCCOL nCol, SCROW nRow,
     204             :                               EditTextObject* pOldData, EditTextObject* pNewData)
     205             : {
     206           0 :     maArray.push_back(Item(nTab, nCol, nRow, pOldData, pNewData));
     207           0 : }
     208             : 
     209           0 : const ScEditDataArray::Item* ScEditDataArray::First()
     210             : {
     211           0 :     maIter = maArray.begin();
     212           0 :     if (maIter == maArray.end())
     213           0 :         return NULL;
     214           0 :     return &(*maIter++);
     215             : }
     216             : 
     217           0 : const ScEditDataArray::Item* ScEditDataArray::Next()
     218             : {
     219           0 :     if (maIter == maArray.end())
     220           0 :         return NULL;
     221           0 :     return &(*maIter++);
     222             : }
     223             : 
     224             : // ============================================================================
     225             : 
     226           0 : ScEditDataArray::Item::Item(SCTAB nTab, SCCOL nCol, SCROW nRow,
     227             :                             EditTextObject* pOldData, EditTextObject* pNewData) :
     228             :     mnTab(nTab),
     229             :     mnCol(nCol),
     230           0 :     mnRow(nRow)
     231             : {
     232           0 :     mpOldData.reset(pOldData);
     233           0 :     mpNewData.reset(pNewData);
     234           0 : }
     235             : 
     236           0 : ScEditDataArray::Item::~Item()
     237             : {
     238           0 : }
     239             : 
     240           0 : const EditTextObject* ScEditDataArray::Item::GetOldData() const
     241             : {
     242           0 :     return mpOldData.get();
     243             : }
     244             : 
     245           0 : const EditTextObject* ScEditDataArray::Item::GetNewData() const
     246             : {
     247           0 :     return mpNewData.get();
     248             : }
     249             : 
     250           0 : SCTAB ScEditDataArray::Item::GetTab() const
     251             : {
     252           0 :     return mnTab;
     253             : }
     254             : 
     255           0 : SCCOL ScEditDataArray::Item::GetCol() const
     256             : {
     257           0 :     return mnCol;
     258             : }
     259             : 
     260           0 : SCROW ScEditDataArray::Item::GetRow() const
     261             : {
     262           0 :     return mnRow;
     263             : }
     264             : 
     265             : // ============================================================================
     266             : 
     267             : namespace
     268             : {
     269             : 
     270             : using std::deque;
     271             : 
     272             : typedef SCCOLROW(*DimensionSelector)(const ScSingleRefData&);
     273             : 
     274             : 
     275           0 : static SCCOLROW lcl_GetCol(const ScSingleRefData& rData)
     276             : {
     277           0 :     return rData.nCol;
     278             : }
     279             : 
     280             : 
     281           0 : static SCCOLROW lcl_GetRow(const ScSingleRefData& rData)
     282             : {
     283           0 :     return rData.nRow;
     284             : }
     285             : 
     286             : 
     287           0 : static SCCOLROW lcl_GetTab(const ScSingleRefData& rData)
     288             : {
     289           0 :     return rData.nTab;
     290             : }
     291             : 
     292             : 
     293             : /** Check if both references span the same range in selected dimension.
     294             :  */
     295             : static bool
     296           0 : lcl_checkRangeDimension(
     297             :         const SingleDoubleRefProvider& rRef1,
     298             :         const SingleDoubleRefProvider& rRef2,
     299             :         const DimensionSelector aWhich)
     300             : {
     301             :     return
     302           0 :         aWhich(rRef1.Ref1) == aWhich(rRef2.Ref1)
     303           0 :         && aWhich(rRef1.Ref2) == aWhich(rRef2.Ref2);
     304             : }
     305             : 
     306             : 
     307             : static bool
     308           0 : lcl_checkRangeDimensions(
     309             :         const SingleDoubleRefProvider& rRef1,
     310             :         const SingleDoubleRefProvider& rRef2,
     311             :         bool& bCol, bool& bRow, bool& bTab)
     312             : {
     313           0 :     const bool bSameCols(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetCol));
     314           0 :     const bool bSameRows(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetRow));
     315           0 :     const bool bSameTabs(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetTab));
     316             : 
     317             :     // Test if exactly two dimensions are equal
     318           0 :     if (!(bSameCols ^ bSameRows ^ bSameTabs)
     319             :             && (bSameCols || bSameRows || bSameTabs))
     320             :     {
     321           0 :         bCol = !bSameCols;
     322           0 :         bRow = !bSameRows;
     323           0 :         bTab = !bSameTabs;
     324           0 :         return true;
     325             :     }
     326           0 :     return false;
     327             : }
     328             : 
     329             : 
     330             : /** Check if references in given reference list can possibly
     331             :     form a range. To do that, two of their dimensions must be the same.
     332             :  */
     333             : static bool
     334           0 : lcl_checkRangeDimensions(
     335             :         const deque<ScToken*>::const_iterator aBegin,
     336             :         const deque<ScToken*>::const_iterator aEnd,
     337             :         bool& bCol, bool& bRow, bool& bTab)
     338             : {
     339           0 :     deque<ScToken*>::const_iterator aCur(aBegin);
     340           0 :     ++aCur;
     341           0 :     const SingleDoubleRefProvider aRef(**aBegin);
     342           0 :     bool bOk(false);
     343             :     {
     344           0 :         const SingleDoubleRefProvider aRefCur(**aCur);
     345           0 :         bOk = lcl_checkRangeDimensions(aRef, aRefCur, bCol, bRow, bTab);
     346             :     }
     347           0 :     while (bOk && aCur != aEnd)
     348             :     {
     349           0 :         const SingleDoubleRefProvider aRefCur(**aCur);
     350           0 :         bool bColTmp(false);
     351           0 :         bool bRowTmp(false);
     352           0 :         bool bTabTmp(false);
     353           0 :         bOk = lcl_checkRangeDimensions(aRef, aRefCur, bColTmp, bRowTmp, bTabTmp);
     354           0 :         bOk = bOk && (bCol == bColTmp && bRow == bRowTmp && bTab == bTabTmp);
     355           0 :         ++aCur;
     356           0 :     }
     357             : 
     358           0 :     if (bOk && aCur == aEnd)
     359             :     {
     360           0 :         return true;
     361             :     }
     362           0 :     return false;
     363             : }
     364             : 
     365             : 
     366             : bool
     367           0 : lcl_lessReferenceBy(
     368             :         const ScToken* const pRef1, const ScToken* const pRef2,
     369             :         const DimensionSelector aWhich)
     370             : {
     371           0 :     const SingleDoubleRefProvider rRef1(*pRef1);
     372           0 :     const SingleDoubleRefProvider rRef2(*pRef2);
     373           0 :     return aWhich(rRef1.Ref1) < aWhich(rRef2.Ref1);
     374             : }
     375             : 
     376             : 
     377             : /** Returns true if range denoted by token pRef2 starts immediately after
     378             :     range denoted by token pRef1. Dimension, in which the comparison takes
     379             :     place, is given by aWhich.
     380             :  */
     381             : bool
     382           0 : lcl_isImmediatelyFollowing(
     383             :         const ScToken* const pRef1, const ScToken* const pRef2,
     384             :         const DimensionSelector aWhich)
     385             : {
     386           0 :     const SingleDoubleRefProvider rRef1(*pRef1);
     387           0 :     const SingleDoubleRefProvider rRef2(*pRef2);
     388           0 :     return aWhich(rRef2.Ref1) - aWhich(rRef1.Ref2) == 1;
     389             : }
     390             : 
     391             : 
     392             : static bool
     393           0 : lcl_checkIfAdjacent(
     394             :         const deque<ScToken*>& rReferences,
     395             :         const DimensionSelector aWhich)
     396             : {
     397             :     typedef deque<ScToken*>::const_iterator Iter;
     398           0 :     Iter aBegin(rReferences.begin());
     399           0 :     Iter aEnd(rReferences.end());
     400           0 :     Iter aBegin1(aBegin);
     401           0 :     ++aBegin1, --aEnd;
     402             :     return std::equal(
     403             :             aBegin, aEnd, aBegin1,
     404           0 :             boost::bind(lcl_isImmediatelyFollowing, _1, _2, aWhich));
     405             : }
     406             : 
     407             : 
     408             : static void
     409           0 : lcl_fillRangeFromRefList(
     410             :         const deque<ScToken*>& rReferences, ScRange& rRange)
     411             : {
     412             :     const ScSingleRefData aStart(
     413           0 :             SingleDoubleRefProvider(*rReferences.front()).Ref1);
     414           0 :     rRange.aStart.Set(aStart.nCol, aStart.nRow, aStart.nTab);
     415             :     const ScSingleRefData aEnd(
     416           0 :             SingleDoubleRefProvider(*rReferences.back()).Ref2);
     417           0 :     rRange.aEnd.Set(aEnd.nCol, aEnd.nRow, aEnd.nTab);
     418           0 : }
     419             : 
     420             : 
     421             : static bool
     422           0 : lcl_refListFormsOneRange(
     423             :         const ScAddress& aPos, deque<ScToken*>& rReferences,
     424             :         ScRange& rRange)
     425             : {
     426             :     std::for_each(
     427             :             rReferences.begin(), rReferences.end(),
     428             :             bind(&ScToken::CalcAbsIfRel, _1, aPos))
     429           0 :         ;
     430           0 :     if (rReferences.size() == 1) {
     431           0 :         lcl_fillRangeFromRefList(rReferences, rRange);
     432           0 :         return true;
     433             :     }
     434             : 
     435           0 :     bool bCell(false);
     436           0 :     bool bRow(false);
     437           0 :     bool bTab(false);
     438           0 :     if (lcl_checkRangeDimensions(rReferences.begin(), rReferences.end(),
     439           0 :             bCell, bRow, bTab))
     440             :     {
     441             :         DimensionSelector aWhich;
     442           0 :         if (bCell)
     443             :         {
     444           0 :             aWhich = lcl_GetCol;
     445             :         }
     446           0 :         else if (bRow)
     447             :         {
     448           0 :             aWhich = lcl_GetRow;
     449             :         }
     450           0 :         else if (bTab)
     451             :         {
     452           0 :             aWhich = lcl_GetTab;
     453             :         }
     454             :         else
     455             :         {
     456             :             OSL_FAIL( "lcl_checkRangeDimensions shouldn't allow that!");
     457           0 :             aWhich = lcl_GetRow;    // initialize to avoid warning
     458             :         }
     459             :         // Sort the references by start of range
     460             :         std::sort(rReferences.begin(), rReferences.end(),
     461           0 :                 boost::bind(lcl_lessReferenceBy, _1, _2, aWhich));
     462           0 :         if (lcl_checkIfAdjacent(rReferences, aWhich))
     463             :         {
     464           0 :             lcl_fillRangeFromRefList(rReferences, rRange);
     465           0 :             return true;
     466             :         }
     467             :     }
     468           0 :     return false;
     469             : }
     470             : 
     471             : 
     472           0 : bool lcl_isReference(const FormulaToken& rToken)
     473             : {
     474             :     return
     475           0 :         rToken.GetType() == svSingleRef ||
     476           0 :         rToken.GetType() == svDoubleRef;
     477             : }
     478             : 
     479             : }
     480             : 
     481          53 : bool ScFormulaCell::IsEmpty()
     482             : {
     483          53 :     MaybeInterpret();
     484          53 :     return aResult.GetCellResultType() == formula::svEmptyCell;
     485             : }
     486             : 
     487         514 : bool ScFormulaCell::IsEmptyDisplayedAsString()
     488             : {
     489         514 :     MaybeInterpret();
     490         514 :     return aResult.IsEmptyDisplayedAsString();
     491             : }
     492             : 
     493        3904 : bool ScFormulaCell::IsValue()
     494             : {
     495        3904 :     MaybeInterpret();
     496        3904 :     return aResult.IsValue();
     497             : }
     498             : 
     499        3282 : double ScFormulaCell::GetValue()
     500             : {
     501        3282 :     MaybeInterpret();
     502        6564 :     if ((!pCode->GetCodeError() || pCode->GetCodeError() == errDoubleRef) &&
     503        3282 :             !aResult.GetResultError())
     504        3281 :         return aResult.GetDouble();
     505           1 :     return 0.0;
     506             : }
     507             : 
     508           0 : double ScFormulaCell::GetValueAlways()
     509             : {
     510             :     // for goal seek: return result value even if error code is set
     511           0 :     MaybeInterpret();
     512           0 :     return aResult.GetDouble();
     513             : }
     514             : 
     515         124 : rtl::OUString ScFormulaCell::GetString()
     516             : {
     517         124 :     MaybeInterpret();
     518         232 :     if ((!pCode->GetCodeError() || pCode->GetCodeError() == errDoubleRef) &&
     519         108 :             !aResult.GetResultError())
     520         108 :         return aResult.GetString();
     521          16 :     return rtl::OUString();
     522             : }
     523             : 
     524          42 : const ScMatrix* ScFormulaCell::GetMatrix()
     525             : {
     526          42 :     if ( pDocument->GetAutoCalc() )
     527             :     {
     528         210 :         if( IsDirtyOrInTableOpDirty()
     529             :         // Was stored !bDirty but an accompanying matrix cell was bDirty?
     530         168 :         || (!bDirty && cMatrixFlag == MM_FORMULA && !aResult.GetMatrix()))
     531           8 :             Interpret();
     532             :     }
     533          42 :     return aResult.GetMatrix().get();
     534             : }
     535             : 
     536           0 : bool ScFormulaCell::GetMatrixOrigin( ScAddress& rPos ) const
     537             : {
     538           0 :     switch ( cMatrixFlag )
     539             :     {
     540             :         case MM_FORMULA :
     541           0 :             rPos = aPos;
     542           0 :             return true;
     543             :         case MM_REFERENCE :
     544             :         {
     545           0 :             pCode->Reset();
     546           0 :             ScToken* t = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
     547           0 :             if( t )
     548             :             {
     549           0 :                 ScSingleRefData& rRef = t->GetSingleRef();
     550           0 :                 rRef.CalcAbsIfRel( aPos );
     551           0 :                 if ( rRef.Valid() )
     552             :                 {
     553           0 :                     rPos.Set( rRef.nCol, rRef.nRow, rRef.nTab );
     554           0 :                     return true;
     555             :                 }
     556             :             }
     557             :         }
     558           0 :         break;
     559             :     }
     560           0 :     return false;
     561             : }
     562             : 
     563             : 
     564             : /*
     565             :  Edge-Values:
     566             : 
     567             :    8
     568             :  4   16
     569             :    2
     570             : 
     571             :  inside: 1
     572             :  outside: 0
     573             :  (reserved: open: 32)
     574             :  */
     575             : 
     576           0 : sal_uInt16 ScFormulaCell::GetMatrixEdge( ScAddress& rOrgPos )
     577             : {
     578           0 :     switch ( cMatrixFlag )
     579             :     {
     580             :         case MM_FORMULA :
     581             :         case MM_REFERENCE :
     582             :         {
     583             :             static SCCOL nC;
     584             :             static SCROW nR;
     585           0 :             ScAddress aOrg;
     586           0 :             if ( !GetMatrixOrigin( aOrg ) )
     587           0 :                 return 0;               // bad luck..
     588           0 :             if ( aOrg != rOrgPos )
     589             :             {   // First time or a different matrix than last time.
     590           0 :                 rOrgPos = aOrg;
     591             :                 ScFormulaCell* pFCell;
     592           0 :                 if ( cMatrixFlag == MM_REFERENCE )
     593           0 :                     pFCell = (ScFormulaCell*) pDocument->GetCell( aOrg );
     594             :                 else
     595           0 :                     pFCell = this;      // this MM_FORMULA
     596             :                 // There's only one this, don't compare pFCell==this.
     597           0 :                 if ( pFCell && pFCell->GetCellType() == CELLTYPE_FORMULA
     598             :                   && pFCell->cMatrixFlag == MM_FORMULA )
     599             :                 {
     600           0 :                     pFCell->GetMatColsRows( nC, nR );
     601           0 :                     if ( nC == 0 || nR == 0 )
     602             :                     {
     603             :                         // No ScMatrixFormulaCellToken available yet, calculate new.
     604           0 :                         nC = 1;
     605           0 :                         nR = 1;
     606           0 :                         ScAddress aTmpOrg;
     607             :                         ScBaseCell* pCell;
     608           0 :                         ScAddress aAdr( aOrg );
     609           0 :                         aAdr.IncCol();
     610           0 :                         bool bCont = true;
     611           0 :                         do
     612             :                         {
     613           0 :                             pCell = pDocument->GetCell( aAdr );
     614           0 :                             if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA
     615           0 :                               && ((ScFormulaCell*)pCell)->cMatrixFlag == MM_REFERENCE
     616           0 :                               && ((ScFormulaCell*)pCell)->GetMatrixOrigin( aTmpOrg )
     617           0 :                               && aTmpOrg == aOrg )
     618             :                             {
     619           0 :                                 nC++;
     620           0 :                                 aAdr.IncCol();
     621             :                             }
     622             :                             else
     623           0 :                                 bCont = false;
     624             :                         } while ( bCont );
     625           0 :                         aAdr = aOrg;
     626           0 :                         aAdr.IncRow();
     627           0 :                         bCont = true;
     628           0 :                         do
     629             :                         {
     630           0 :                             pCell = pDocument->GetCell( aAdr );
     631           0 :                             if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA
     632           0 :                               && ((ScFormulaCell*)pCell)->cMatrixFlag == MM_REFERENCE
     633           0 :                               && ((ScFormulaCell*)pCell)->GetMatrixOrigin( aTmpOrg )
     634           0 :                               && aTmpOrg == aOrg )
     635             :                             {
     636           0 :                                 nR++;
     637           0 :                                 aAdr.IncRow();
     638             :                             }
     639             :                             else
     640           0 :                                 bCont = false;
     641             :                         } while ( bCont );
     642           0 :                         pFCell->SetMatColsRows( nC, nR );
     643             :                     }
     644             :                 }
     645             :                 else
     646             :                 {
     647             : #if OSL_DEBUG_LEVEL > 0
     648             :                     rtl::OUString aTmp;
     649             :                     rtl::OStringBuffer aMsg(RTL_CONSTASCII_STRINGPARAM(
     650             :                         "broken Matrix, no MatFormula at origin, Pos: "));
     651             :                     aPos.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
     652             :                     aMsg.append(rtl::OUStringToOString(aTmp, RTL_TEXTENCODING_ASCII_US));
     653             :                     aMsg.append(RTL_CONSTASCII_STRINGPARAM(", MatOrg: "));
     654             :                     aOrg.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
     655             :                     aMsg.append(rtl::OUStringToOString(aTmp, RTL_TEXTENCODING_ASCII_US));
     656             :                     OSL_FAIL(aMsg.getStr());
     657             : #endif
     658           0 :                     return 0;           // bad luck ...
     659             :                 }
     660             :             }
     661             :             // here we are, healthy and clean, somewhere in between
     662           0 :             SCsCOL dC = aPos.Col() - aOrg.Col();
     663           0 :             SCsROW dR = aPos.Row() - aOrg.Row();
     664           0 :             sal_uInt16 nEdges = 0;
     665           0 :             if ( dC >= 0 && dR >= 0 && dC < nC && dR < nR )
     666             :             {
     667           0 :                 if ( dC == 0 )
     668           0 :                     nEdges |= 4;            // left edge
     669           0 :                 if ( dC+1 == nC )
     670           0 :                     nEdges |= 16;           // right edge
     671           0 :                 if ( dR == 0 )
     672           0 :                     nEdges |= 8;            // top edge
     673           0 :                 if ( dR+1 == nR )
     674           0 :                     nEdges |= 2;            // bottom edge
     675           0 :                 if ( !nEdges )
     676           0 :                     nEdges = 1;             // inside
     677             :             }
     678             : #if OSL_DEBUG_LEVEL > 0
     679             :             else
     680             :             {
     681             :                 rtl::OUString aTmp;
     682             :                 rtl::OStringBuffer aMsg( "broken Matrix, Pos: " );
     683             :                 aPos.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
     684             :                 aMsg.append(rtl::OUStringToOString(aTmp, RTL_TEXTENCODING_UTF8 ));
     685             :                 aMsg.append(RTL_CONSTASCII_STRINGPARAM(", MatOrg: "));
     686             :                 aOrg.Format( aTmp, SCA_VALID_COL | SCA_VALID_ROW, pDocument );
     687             :                 aMsg.append(rtl::OUStringToOString(aTmp, RTL_TEXTENCODING_UTF8 ));
     688             :                 aMsg.append(RTL_CONSTASCII_STRINGPARAM(", MatCols: "));
     689             :                 aMsg.append(static_cast<sal_Int32>( nC ));
     690             :                 aMsg.append(RTL_CONSTASCII_STRINGPARAM(", MatRows: "));
     691             :                 aMsg.append(static_cast<sal_Int32>( nR ));
     692             :                 aMsg.append(RTL_CONSTASCII_STRINGPARAM(", DiffCols: "));
     693             :                 aMsg.append(static_cast<sal_Int32>( dC ));
     694             :                 aMsg.append(RTL_CONSTASCII_STRINGPARAM(", DiffRows: "));
     695             :                 aMsg.append(static_cast<sal_Int32>( dR ));
     696             :                 OSL_FAIL( aMsg.makeStringAndClear().getStr());
     697             :             }
     698             : #endif
     699           0 :             return nEdges;
     700             : //            break;
     701             :         }
     702             :         default:
     703           0 :             return 0;
     704             :     }
     705             : }
     706             : 
     707        3177 : sal_uInt16 ScFormulaCell::GetErrCode()
     708             : {
     709        3177 :     MaybeInterpret();
     710             : 
     711             :     /* FIXME: If ScTokenArray::SetCodeError() was really only for code errors
     712             :      * and not also abused for signaling other error conditions we could bail
     713             :      * out even before attempting to interpret broken code. */
     714        3177 :     sal_uInt16 nErr =  pCode->GetCodeError();
     715        3177 :     if (nErr)
     716           0 :         return nErr;
     717        3177 :     return aResult.GetResultError();
     718             : }
     719             : 
     720           0 : sal_uInt16 ScFormulaCell::GetRawError()
     721             : {
     722           0 :     sal_uInt16 nErr =  pCode->GetCodeError();
     723           0 :     if (nErr)
     724           0 :         return nErr;
     725           0 :     return aResult.GetResultError();
     726             : }
     727             : 
     728           0 : bool ScFormulaCell::HasOneReference( ScRange& r ) const
     729             : {
     730           0 :     pCode->Reset();
     731           0 :     ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
     732           0 :     if( p && !pCode->GetNextReferenceRPN() )        // only one!
     733             :     {
     734           0 :         p->CalcAbsIfRel( aPos );
     735           0 :         SingleDoubleRefProvider aProv( *p );
     736             :         r.aStart.Set( aProv.Ref1.nCol,
     737             :                       aProv.Ref1.nRow,
     738           0 :                       aProv.Ref1.nTab );
     739             :         r.aEnd.Set( aProv.Ref2.nCol,
     740             :                     aProv.Ref2.nRow,
     741           0 :                     aProv.Ref2.nTab );
     742           0 :         return true;
     743             :     }
     744             :     else
     745           0 :         return false;
     746             : }
     747             : 
     748             : bool
     749           0 : ScFormulaCell::HasRefListExpressibleAsOneReference(ScRange& rRange) const
     750             : {
     751             :     /* If there appears just one reference in the formula, it's the same
     752             :        as HasOneReference(). If there are more of them, they can denote
     753             :        one range if they are (sole) arguments of one function.
     754             :        Union of these references must form one range and their
     755             :        intersection must be empty set.
     756             :     */
     757             : 
     758             :     // Detect the simple case of exactly one reference in advance without all
     759             :     // overhead.
     760             :     // #i107741# Doing so actually makes outlines using SUBTOTAL(x;reference)
     761             :     // work again, where the function does not have only references.
     762           0 :     if (HasOneReference( rRange))
     763           0 :         return true;
     764             : 
     765           0 :     pCode->Reset();
     766             :     // Get first reference, if any
     767             :     ScToken* const pFirstReference(
     768           0 :             dynamic_cast<ScToken*>(pCode->GetNextReferenceRPN()));
     769           0 :     if (pFirstReference)
     770             :     {
     771             :         // Collect all consecutive references, starting by the one
     772             :         // already found
     773           0 :         std::deque<ScToken*> aReferences;
     774           0 :         aReferences.push_back(pFirstReference);
     775           0 :         FormulaToken* pToken(pCode->NextRPN());
     776           0 :         FormulaToken* pFunction(0);
     777           0 :         while (pToken)
     778             :         {
     779           0 :             if (lcl_isReference(*pToken))
     780             :             {
     781           0 :                 aReferences.push_back(dynamic_cast<ScToken*>(pToken));
     782           0 :                 pToken = pCode->NextRPN();
     783             :             }
     784             :             else
     785             :             {
     786           0 :                 if (pToken->IsFunction())
     787             :                 {
     788           0 :                     pFunction = pToken;
     789             :                 }
     790           0 :                 break;
     791             :             }
     792             :         }
     793           0 :         if (pFunction && !pCode->GetNextReferenceRPN()
     794           0 :                 && (pFunction->GetParamCount() == aReferences.size()))
     795             :         {
     796           0 :             return lcl_refListFormsOneRange(aPos, aReferences, rRange);
     797           0 :         }
     798             :     }
     799           0 :     return false;
     800             : }
     801             : 
     802          20 : bool ScFormulaCell::HasRelNameReference() const
     803             : {
     804          20 :     pCode->Reset();
     805             :     ScToken* t;
     806          20 :     while ( ( t = static_cast<ScToken*>(pCode->GetNextReferenceRPN()) ) != NULL )
     807             :     {
     808          49 :         if ( t->GetSingleRef().IsRelName() ||
     809          24 :                 (t->GetType() == formula::svDoubleRef &&
     810           1 :                 t->GetDoubleRef().Ref2.IsRelName()) )
     811           0 :             return true;
     812             :     }
     813          20 :     return false;
     814             : }
     815             : 
     816           0 : bool ScFormulaCell::HasColRowName() const
     817             : {
     818           0 :     pCode->Reset();
     819           0 :     return (pCode->GetNextColRowName() != NULL);
     820             : }
     821             : 
     822          16 : bool ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
     823             :                                     const ScRange& r,
     824             :                                     SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
     825             :                                     ScDocument* pUndoDoc, const ScAddress* pUndoCellPos )
     826             : {
     827          16 :     bool bCellStateChanged = false;
     828             : 
     829          16 :     SCCOL nCol1 = r.aStart.Col();
     830          16 :     SCROW nRow1 = r.aStart.Row();
     831          16 :     SCTAB nTab1 = r.aStart.Tab();
     832          16 :     SCCOL nCol2 = r.aEnd.Col();
     833          16 :     SCROW nRow2 = r.aEnd.Row();
     834          16 :     SCTAB nTab2 = r.aEnd.Tab();
     835          16 :     SCCOL nCol = aPos.Col();
     836          16 :     SCROW nRow = aPos.Row();
     837          16 :     SCTAB nTab = aPos.Tab();
     838          16 :     ScAddress aUndoPos( aPos );         // position for undo cell in pUndoDoc
     839          16 :     if ( pUndoCellPos )
     840           4 :         aUndoPos = *pUndoCellPos;
     841          16 :     ScAddress aOldPos( aPos );
     842             : //  bool bPosChanged = false;           // if this cell was moved
     843          16 :     bool bIsInsert = false;
     844          16 :     if (eUpdateRefMode == URM_INSDEL)
     845             :     {
     846           4 :         bIsInsert = (nDx >= 0 && nDy >= 0 && nDz >= 0);
     847           4 :         if ( nDx && nRow >= nRow1 && nRow <= nRow2 &&
     848             :             nTab >= nTab1 && nTab <= nTab2 )
     849             :         {
     850           0 :             if (nCol >= nCol1)
     851             :             {
     852           0 :                 nCol = sal::static_int_cast<SCCOL>( nCol + nDx );
     853           0 :                 if ((SCsCOL) nCol < 0)
     854           0 :                     nCol = 0;
     855           0 :                 else if ( nCol > MAXCOL )
     856           0 :                     nCol = MAXCOL;
     857           0 :                 bCellStateChanged = aPos.Col() != nCol;
     858           0 :                 aPos.SetCol( nCol );
     859             :             }
     860             :         }
     861           4 :         if ( nDy && nCol >= nCol1 && nCol <= nCol2 &&
     862             :             nTab >= nTab1 && nTab <= nTab2 )
     863             :         {
     864           0 :             if (nRow >= nRow1)
     865             :             {
     866           0 :                 nRow = sal::static_int_cast<SCROW>( nRow + nDy );
     867           0 :                 if ((SCsROW) nRow < 0)
     868           0 :                     nRow = 0;
     869           0 :                 else if ( nRow > MAXROW )
     870           0 :                     nRow = MAXROW;
     871           0 :                 bCellStateChanged = aPos.Row() != nRow;
     872           0 :                 aPos.SetRow( nRow );
     873             :             }
     874             :         }
     875           4 :         if ( nDz && nCol >= nCol1 && nCol <= nCol2 &&
     876             :             nRow >= nRow1 && nRow <= nRow2 )
     877             :         {
     878           0 :             if (nTab >= nTab1)
     879             :             {
     880           0 :                 SCTAB nMaxTab = pDocument->GetTableCount() - 1;
     881           0 :                 nTab = sal::static_int_cast<SCTAB>( nTab + nDz );
     882           0 :                 if ((SCsTAB) nTab < 0)
     883           0 :                     nTab = 0;
     884           0 :                 else if ( nTab > nMaxTab )
     885           0 :                     nTab = nMaxTab;
     886           0 :                 bCellStateChanged = aPos.Tab() != nTab;
     887           0 :                 aPos.SetTab( nTab );
     888             :             }
     889             :         }
     890             :     }
     891          12 :     else if ( r.In( aPos ) )
     892             :     {
     893          12 :         aOldPos.Set( nCol - nDx, nRow - nDy, nTab - nDz );
     894             :     }
     895             : 
     896          16 :     bool bHasRefs = false;
     897          16 :     bool bHasColRowNames = false;
     898          16 :     bool bOnRefMove = false;
     899          16 :     if ( !pDocument->IsClipOrUndo() )
     900             :     {
     901          16 :         pCode->Reset();
     902          16 :         bHasRefs = (pCode->GetNextReferenceRPN() != NULL);
     903          16 :         if ( !bHasRefs || eUpdateRefMode == URM_COPY )
     904             :         {
     905          12 :             pCode->Reset();
     906          12 :             bHasColRowNames = (pCode->GetNextColRowName() != NULL);
     907          12 :             bHasRefs = bHasRefs || bHasColRowNames;
     908             :         }
     909          16 :         bOnRefMove = pCode->IsRecalcModeOnRefMove();
     910             :     }
     911          16 :     if( bHasRefs || bOnRefMove )
     912             :     {
     913          16 :         ScTokenArray* pOld = pUndoDoc ? pCode->Clone() : NULL;
     914             :         ScRangeData* pRangeData;
     915          16 :         bool bValChanged = false;
     916          16 :         bool bRangeModified = false;    // any range, not only shared formula
     917          16 :         bool bRefSizeChanged = false;
     918          16 :         if ( bHasRefs )
     919             :         {
     920          16 :             ScCompiler aComp(pDocument, aPos, *pCode);
     921          16 :             aComp.SetGrammar(pDocument->GetGrammar());
     922             :             pRangeData = aComp.UpdateReference(eUpdateRefMode, aOldPos, r,
     923             :                                              nDx, nDy, nDz,
     924          16 :                                              bValChanged, bRefSizeChanged);
     925          16 :             bRangeModified = aComp.HasModifiedRange();
     926             :         }
     927             :         else
     928             :         {
     929           0 :             bValChanged = false;
     930           0 :             pRangeData = NULL;
     931           0 :             bRangeModified = false;
     932           0 :             bRefSizeChanged = false;
     933             :         }
     934             : 
     935          16 :         bCellStateChanged |= bValChanged;
     936             : 
     937          16 :         if ( bOnRefMove )
     938           2 :             bOnRefMove = (bValChanged || (aPos != aOldPos));
     939             :             // Cell may reference itself, e.g. ocColumn, ocRow without parameter
     940             : 
     941             :         bool bColRowNameCompile, bHasRelName, bNewListening, bInDeleteUndo;
     942          16 :         if ( bHasRefs )
     943             :         {
     944             :             // Upon Insert ColRowNames have to be recompiled in case the
     945             :             // insertion occurs right in front of the range.
     946             :             bColRowNameCompile =
     947          16 :                 (eUpdateRefMode == URM_INSDEL && (nDx > 0 || nDy > 0));
     948          16 :             if ( bColRowNameCompile )
     949             :             {
     950           4 :                 bColRowNameCompile = false;
     951             :                 ScToken* t;
     952           4 :                 ScRangePairList* pColList = pDocument->GetColNameRanges();
     953           4 :                 ScRangePairList* pRowList = pDocument->GetRowNameRanges();
     954           4 :                 pCode->Reset();
     955           8 :                 while ( !bColRowNameCompile && (t = static_cast<ScToken*>(pCode->GetNextColRowName())) != NULL )
     956             :                 {
     957           0 :                     ScSingleRefData& rRef = t->GetSingleRef();
     958           0 :                     if ( nDy > 0 && rRef.IsColRel() )
     959             :                     {   // ColName
     960           0 :                         rRef.CalcAbsIfRel( aPos );
     961           0 :                         ScAddress aAdr( rRef.nCol, rRef.nRow, rRef.nTab );
     962           0 :                         ScRangePair* pR = pColList->Find( aAdr );
     963           0 :                         if ( pR )
     964             :                         {   // defined
     965           0 :                             if ( pR->GetRange(1).aStart.Row() == nRow1 )
     966           0 :                                 bColRowNameCompile = true;
     967             :                         }
     968             :                         else
     969             :                         {   // on the fly
     970           0 :                             if ( rRef.nRow + 1 == nRow1 )
     971           0 :                                 bColRowNameCompile = true;
     972             :                         }
     973             :                     }
     974           0 :                     if ( nDx > 0 && rRef.IsRowRel() )
     975             :                     {   // RowName
     976           0 :                         rRef.CalcAbsIfRel( aPos );
     977           0 :                         ScAddress aAdr( rRef.nCol, rRef.nRow, rRef.nTab );
     978           0 :                         ScRangePair* pR = pRowList->Find( aAdr );
     979           0 :                         if ( pR )
     980             :                         {   // defined
     981           0 :                             if ( pR->GetRange(1).aStart.Col() == nCol1 )
     982           0 :                                 bColRowNameCompile = true;
     983             :                         }
     984             :                         else
     985             :                         {   // on the fly
     986           0 :                             if ( rRef.nCol + 1 == nCol1 )
     987           0 :                                 bColRowNameCompile = true;
     988             :                         }
     989             :                     }
     990             :                 }
     991             :             }
     992          12 :             else if ( eUpdateRefMode == URM_MOVE )
     993             :             {   // bei Move/D&D neu kompilieren wenn ColRowName verschoben wurde
     994             :                 // oder diese Zelle auf einen zeigt und verschoben wurde
     995             :                 // During Move/D&D was recompiled, when ColRowName had been delayed
     996           0 :                 bColRowNameCompile = bCompile;      // evtl. aus Copy-ctor
     997           0 :                 if ( !bColRowNameCompile )
     998             :                 {
     999           0 :                     bool bMoved = (aPos != aOldPos);
    1000           0 :                     pCode->Reset();
    1001           0 :                     ScToken* t = static_cast<ScToken*>(pCode->GetNextColRowName());
    1002           0 :                     if ( t && bMoved )
    1003           0 :                         bColRowNameCompile = true;
    1004           0 :                     while ( t && !bColRowNameCompile )
    1005             :                     {
    1006           0 :                         ScSingleRefData& rRef = t->GetSingleRef();
    1007           0 :                         rRef.CalcAbsIfRel( aPos );
    1008           0 :                         if ( rRef.Valid() )
    1009             :                         {
    1010           0 :                             ScAddress aAdr( rRef.nCol, rRef.nRow, rRef.nTab );
    1011           0 :                             if ( r.In( aAdr ) )
    1012           0 :                                 bColRowNameCompile = true;
    1013             :                         }
    1014           0 :                         t = static_cast<ScToken*>(pCode->GetNextColRowName());
    1015             :                     }
    1016             :                 }
    1017             :             }
    1018          12 :             else if ( eUpdateRefMode == URM_COPY && bHasColRowNames && bValChanged )
    1019             :             {
    1020           0 :                 bColRowNameCompile = true;
    1021             :             }
    1022          16 :             ScChangeTrack* pChangeTrack = pDocument->GetChangeTrack();
    1023          16 :             if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() )
    1024           0 :                 bInDeleteUndo = true;
    1025             :             else
    1026          16 :                 bInDeleteUndo = false;
    1027             :             // RelNameRefs are always moved
    1028          16 :             bHasRelName = HasRelNameReference();
    1029             :             // Reference changed and new listening needed?
    1030             :             // Except in Insert/Delete without specialties.
    1031             :             bNewListening = (bRangeModified || pRangeData || bColRowNameCompile
    1032             :                     || (bValChanged && (eUpdateRefMode != URM_INSDEL ||
    1033             :                             bInDeleteUndo || bRefSizeChanged)) ||
    1034             :                     (bHasRelName && eUpdateRefMode != URM_COPY))
    1035             :                 // #i36299# Don't duplicate action during cut&paste / drag&drop
    1036             :                 // on a cell in the range moved, start/end listeners is done
    1037             :                 // via ScDocument::DeleteArea() and ScDocument::CopyFromClip().
    1038             :                 && !(eUpdateRefMode == URM_MOVE &&
    1039          16 :                         pDocument->IsInsertingFromOtherDoc() && r.In(aPos));
    1040          16 :             if ( bNewListening )
    1041           0 :                 EndListeningTo( pDocument, pOld, aOldPos );
    1042             :         }
    1043             :         else
    1044             :         {
    1045             :             bColRowNameCompile = bHasRelName = bNewListening = bInDeleteUndo =
    1046           0 :                 false;
    1047             :         }
    1048             : 
    1049          16 :         bool bNeedDirty = false;
    1050             :         // NeedDirty bei Aenderungen ausser Copy und Move/Insert ohne RelNames
    1051          18 :         if ( bRangeModified || pRangeData || bColRowNameCompile ||
    1052             :                 (bValChanged && eUpdateRefMode != URM_COPY &&
    1053             :                  (eUpdateRefMode != URM_MOVE || bHasRelName) &&
    1054           2 :                  (!bIsInsert || bHasRelName || bInDeleteUndo ||
    1055             :                   bRefSizeChanged)) || bOnRefMove)
    1056           2 :             bNeedDirty = true;
    1057             :         else
    1058          14 :             bNeedDirty = false;
    1059          16 :         if (pUndoDoc && (bValChanged || pRangeData || bOnRefMove))
    1060             :         {
    1061             :             //  Copy the cell to aUndoPos, which is its current position in the document,
    1062             :             //  so this works when UpdateReference is called before moving the cells
    1063             :             //  (InsertCells/DeleteCells - aPos is changed above) as well as when UpdateReference
    1064             :             //  is called after moving the cells (MoveBlock/PasteFromClip - aOldPos is changed).
    1065             : 
    1066             :             // If there is already a formula cell in the undo document, don't overwrite it,
    1067             :             // the first (oldest) is the important cell.
    1068           0 :             if ( pUndoDoc->GetCellType( aUndoPos ) != CELLTYPE_FORMULA )
    1069             :             {
    1070             :                 ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aUndoPos,
    1071           0 :                         pOld, eTempGrammar, cMatrixFlag );
    1072           0 :                 pFCell->aResult.SetToken( NULL);  // to recognize it as changed later (Cut/Paste!)
    1073           0 :                 pUndoDoc->PutCell( aUndoPos, pFCell );
    1074             :             }
    1075             :         }
    1076          16 :         bValChanged = false;
    1077          16 :         if ( pRangeData )
    1078             :         {   // Replace shared formula with own formula
    1079           0 :             pDocument->RemoveFromFormulaTree( this );   // update formula count
    1080           0 :             delete pCode;
    1081           0 :             pCode = pRangeData->GetCode()->Clone();
    1082             :             // #i18937# #i110008# call MoveRelWrap, but with the old position
    1083           0 :             ScCompiler::MoveRelWrap(*pCode, pDocument, aOldPos, pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
    1084           0 :             ScCompiler aComp2(pDocument, aPos, *pCode);
    1085           0 :             aComp2.SetGrammar(pDocument->GetGrammar());
    1086             :             aComp2.UpdateSharedFormulaReference( eUpdateRefMode, aOldPos, r,
    1087           0 :                 nDx, nDy, nDz );
    1088           0 :             bValChanged = true;
    1089           0 :             bNeedDirty = true;
    1090             :         }
    1091          16 :         if ( ( bCompile = (bCompile || bValChanged || bRangeModified || bColRowNameCompile) ) != 0 )
    1092             :         {
    1093           0 :             CompileTokenArray( bNewListening ); // no Listening
    1094           0 :             bNeedDirty = true;
    1095             :         }
    1096          16 :         if ( !bInDeleteUndo )
    1097             :         {   // In ChangeTrack Delete-Reject listeners are established in
    1098             :             // InsertCol/InsertRow
    1099          16 :             if ( bNewListening )
    1100             :             {
    1101           0 :                 if ( eUpdateRefMode == URM_INSDEL )
    1102             :                 {
    1103             :                     // Inserts/Deletes re-establish listeners after all
    1104             :                     // UpdateReference calls.
    1105             :                     // All replaced shared formula listeners have to be
    1106             :                     // established after an Insert or Delete. Do nothing here.
    1107           0 :                     SetNeedsListening( true);
    1108             :                 }
    1109             :                 else
    1110           0 :                     StartListeningTo( pDocument );
    1111             :             }
    1112             :         }
    1113          16 :         if ( bNeedDirty && (!(eUpdateRefMode == URM_INSDEL && bHasRelName) || pRangeData) )
    1114             :         {   // Referenzen abgeschnitten, ungueltig o.ae.?
    1115           2 :             bool bOldAutoCalc = pDocument->GetAutoCalc();
    1116             :             // no Interpret in SubMinimalRecalc because of evntual wrong reference
    1117           2 :             pDocument->SetAutoCalc( false );
    1118           2 :             SetDirty();
    1119           2 :             pDocument->SetAutoCalc( bOldAutoCalc );
    1120             :         }
    1121             : 
    1122          16 :         delete pOld;
    1123             :     }
    1124          16 :     return bCellStateChanged;
    1125             : }
    1126             : 
    1127           6 : void ScFormulaCell::UpdateInsertTab(SCTAB nTable, SCTAB nNewSheets)
    1128             : {
    1129           6 :     bool bPosChanged = ( aPos.Tab() >= nTable ? true : false );
    1130           6 :     pCode->Reset();
    1131           6 :     if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
    1132             :     {
    1133           6 :         EndListeningTo( pDocument );
    1134             :         // IncTab _nach_ EndListeningTo und _vor_ Compiler UpdateInsertTab !
    1135           6 :         if ( bPosChanged )
    1136           6 :             aPos.IncTab(nNewSheets);
    1137             :         ScRangeData* pRangeData;
    1138           6 :         ScCompiler aComp(pDocument, aPos, *pCode);
    1139           6 :         aComp.SetGrammar(pDocument->GetGrammar());
    1140           6 :         pRangeData = aComp.UpdateInsertTab( nTable, false, nNewSheets );
    1141           6 :         if (pRangeData)                     // Shared Formula against real Formula
    1142             :         {                                   // exchange
    1143             :             bool bRefChanged;
    1144           0 :             pDocument->RemoveFromFormulaTree( this );   // update formula count
    1145           0 :             delete pCode;
    1146           0 :             pCode = new ScTokenArray( *pRangeData->GetCode() );
    1147           0 :             ScCompiler aComp2(pDocument, aPos, *pCode);
    1148           0 :             aComp2.SetGrammar(pDocument->GetGrammar());
    1149           0 :             aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
    1150           0 :             aComp2.UpdateInsertTab( nTable, false, nNewSheets );
    1151             :             // If the shared formula contained a named range/formula containing
    1152             :             // an absolute reference to a sheet, those have to be readjusted.
    1153           0 :             aComp2.UpdateDeleteTab( nTable, false, true, bRefChanged, nNewSheets );
    1154           0 :             bCompile = true;
    1155           6 :         }
    1156             :         // no StartListeningTo becuase pTab[nTab] does not exsist!
    1157             :     }
    1158           0 :     else if ( bPosChanged )
    1159           0 :         aPos.IncTab();
    1160           6 : }
    1161             : 
    1162          55 : bool ScFormulaCell::UpdateDeleteTab(SCTAB nTable, bool bIsMove, SCTAB nSheets)
    1163             : {
    1164          55 :     bool bRefChanged = false;
    1165          55 :     bool bPosChanged = ( aPos.Tab() >= nTable + nSheets ? true : false );
    1166          55 :     pCode->Reset();
    1167          55 :     if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
    1168             :     {
    1169          54 :         EndListeningTo( pDocument );
    1170             :         // IncTab _after_ EndListeningTo und _before_ Compiler UpdateDeleteTab !
    1171          54 :         if ( bPosChanged )
    1172          12 :             aPos.IncTab(-1*nSheets);
    1173             :         ScRangeData* pRangeData;
    1174          54 :         ScCompiler aComp(pDocument, aPos, *pCode);
    1175          54 :         aComp.SetGrammar(pDocument->GetGrammar());
    1176          54 :         pRangeData = aComp.UpdateDeleteTab(nTable, bIsMove, false, bRefChanged, nSheets);
    1177          54 :         if (pRangeData)                     // Shared Formula against real Formula
    1178             :         {                                   // exchange
    1179           0 :             pDocument->RemoveFromFormulaTree( this );   // update formula count
    1180           0 :             delete pCode;
    1181           0 :             pCode = pRangeData->GetCode()->Clone();
    1182           0 :             ScCompiler aComp2(pDocument, aPos, *pCode);
    1183           0 :             aComp2.SetGrammar(pDocument->GetGrammar());
    1184           0 :             aComp2.CompileTokenArray();
    1185           0 :             aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
    1186           0 :             aComp2.UpdateDeleteTab( nTable, false, false, bRefChanged, nSheets );
    1187             :             // If the shared formula contained a named range/formula containing
    1188             :             // an absolute reference to a sheet, those have to be readjusted.
    1189           0 :             aComp2.UpdateInsertTab( nTable,true, nSheets );
    1190             :             // bRefChanged kann beim letzten UpdateDeleteTab zurueckgesetzt worden sein
    1191           0 :             bRefChanged = true;
    1192           0 :             bCompile = true;
    1193          54 :         }
    1194             :         // no StartListeningTo because pTab[nTab] not yet correct!
    1195             :     }
    1196           1 :     else if ( bPosChanged )
    1197           0 :         aPos.IncTab(-1*nSheets);
    1198             : 
    1199          55 :     return bRefChanged;
    1200             : }
    1201             : 
    1202           0 : void ScFormulaCell::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo )
    1203             : {
    1204           0 :     pCode->Reset();
    1205           0 :     if( pCode->GetNextReferenceRPN() && !pDocument->IsClipOrUndo() )
    1206             :     {
    1207           0 :         EndListeningTo( pDocument );
    1208             :         // SetTab _after_ EndListeningTo und _before_ Compiler UpdateMoveTab !
    1209           0 :         aPos.SetTab( nTabNo );
    1210             :         ScRangeData* pRangeData;
    1211           0 :         ScCompiler aComp(pDocument, aPos, *pCode);
    1212           0 :         aComp.SetGrammar(pDocument->GetGrammar());
    1213           0 :         pRangeData = aComp.UpdateMoveTab( nOldPos, nNewPos, false );
    1214           0 :         if (pRangeData)                     // Shared Formula gegen echte Formel
    1215             :         {                                   // exchange
    1216           0 :             pDocument->RemoveFromFormulaTree( this );   // update formula count
    1217           0 :             delete pCode;
    1218           0 :             pCode = pRangeData->GetCode()->Clone();
    1219           0 :             ScCompiler aComp2(pDocument, aPos, *pCode);
    1220           0 :             aComp2.SetGrammar(pDocument->GetGrammar());
    1221           0 :             aComp2.CompileTokenArray();
    1222           0 :             aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow());
    1223           0 :             aComp2.UpdateMoveTab( nOldPos, nNewPos, true );
    1224           0 :             bCompile = true;
    1225           0 :         }
    1226             :         // no StartListeningTo because pTab[nTab] not yet correct!
    1227             :     }
    1228             :     else
    1229           0 :         aPos.SetTab( nTabNo );
    1230           0 : }
    1231             : 
    1232           0 : void ScFormulaCell::UpdateInsertTabAbs(SCTAB nTable)
    1233             : {
    1234           0 :     if( !pDocument->IsClipOrUndo() )
    1235             :     {
    1236           0 :         pCode->Reset();
    1237           0 :         ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
    1238           0 :         while( p )
    1239             :         {
    1240           0 :             ScSingleRefData& rRef1 = p->GetSingleRef();
    1241           0 :             if( !rRef1.IsTabRel() && (SCsTAB) nTable <= rRef1.nTab )
    1242           0 :                 rRef1.nTab++;
    1243           0 :             if( p->GetType() == formula::svDoubleRef )
    1244             :             {
    1245           0 :                 ScSingleRefData& rRef2 = p->GetDoubleRef().Ref2;
    1246           0 :                 if( !rRef2.IsTabRel() && (SCsTAB) nTable <= rRef2.nTab )
    1247           0 :                     rRef2.nTab++;
    1248             :             }
    1249           0 :             p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
    1250             :         }
    1251             :     }
    1252           0 : }
    1253             : 
    1254           0 : bool ScFormulaCell::TestTabRefAbs(SCTAB nTable)
    1255             : {
    1256           0 :     bool bRet = false;
    1257           0 :     if( !pDocument->IsClipOrUndo() )
    1258             :     {
    1259           0 :         pCode->Reset();
    1260           0 :         ScToken* p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
    1261           0 :         while( p )
    1262             :         {
    1263           0 :             ScSingleRefData& rRef1 = p->GetSingleRef();
    1264           0 :             if( !rRef1.IsTabRel() )
    1265             :             {
    1266           0 :                 if( (SCsTAB) nTable != rRef1.nTab )
    1267           0 :                     bRet = true;
    1268           0 :                 else if (nTable != aPos.Tab())
    1269           0 :                     rRef1.nTab = aPos.Tab();
    1270             :             }
    1271           0 :             if( p->GetType() == formula::svDoubleRef )
    1272             :             {
    1273           0 :                 ScSingleRefData& rRef2 = p->GetDoubleRef().Ref2;
    1274           0 :                 if( !rRef2.IsTabRel() )
    1275             :                 {
    1276           0 :                     if( (SCsTAB) nTable != rRef2.nTab )
    1277           0 :                         bRet = true;
    1278           0 :                     else if (nTable != aPos.Tab())
    1279           0 :                         rRef2.nTab = aPos.Tab();
    1280             :                 }
    1281             :             }
    1282           0 :             p = static_cast<ScToken*>(pCode->GetNextReferenceRPN());
    1283             :         }
    1284             :     }
    1285           0 :     return bRet;
    1286             : }
    1287             : 
    1288          53 : void ScFormulaCell::UpdateCompile( bool bForceIfNameInUse )
    1289             : {
    1290          53 :     if ( bForceIfNameInUse && !bCompile )
    1291           0 :         bCompile = pCode->HasNameOrColRowName();
    1292          53 :     if ( bCompile )
    1293           0 :         pCode->SetCodeError( 0 );   // make sure it will really be compiled
    1294          53 :     CompileTokenArray();
    1295          53 : }
    1296             : 
    1297             : //  Reference transposition is only called in Clipboard Document
    1298           0 : void ScFormulaCell::TransposeReference()
    1299             : {
    1300           0 :     bool bFound = false;
    1301           0 :     pCode->Reset();
    1302             :     ScToken* t;
    1303           0 :     while ( ( t = static_cast<ScToken*>(pCode->GetNextReference()) ) != NULL )
    1304             :     {
    1305           0 :         ScSingleRefData& rRef1 = t->GetSingleRef();
    1306           0 :         if ( rRef1.IsColRel() && rRef1.IsRowRel() )
    1307             :         {
    1308           0 :             bool bDouble = (t->GetType() == formula::svDoubleRef);
    1309           0 :             ScSingleRefData& rRef2 = (bDouble ? t->GetDoubleRef().Ref2 : rRef1);
    1310           0 :             if ( !bDouble || (rRef2.IsColRel() && rRef2.IsRowRel()) )
    1311             :             {
    1312             :                 sal_Int16 nTemp;
    1313             : 
    1314           0 :                 nTemp = rRef1.nRelCol;
    1315           0 :                 rRef1.nRelCol = static_cast<SCCOL>(rRef1.nRelRow);
    1316           0 :                 rRef1.nRelRow = static_cast<SCROW>(nTemp);
    1317             : 
    1318           0 :                 if ( bDouble )
    1319             :                 {
    1320           0 :                     nTemp = rRef2.nRelCol;
    1321           0 :                     rRef2.nRelCol = static_cast<SCCOL>(rRef2.nRelRow);
    1322           0 :                     rRef2.nRelRow = static_cast<SCROW>(nTemp);
    1323             :                 }
    1324             : 
    1325           0 :                 bFound = true;
    1326             :             }
    1327             :         }
    1328             :     }
    1329             : 
    1330           0 :     if (bFound)
    1331           0 :         bCompile = true;
    1332           0 : }
    1333             : 
    1334           0 : void ScFormulaCell::UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
    1335             :                                         ScDocument* pUndoDoc )
    1336             : {
    1337           0 :     EndListeningTo( pDocument );
    1338             : 
    1339           0 :     ScAddress aOldPos = aPos;
    1340           0 :     bool bPosChanged = false;           // If this cell has been moved
    1341             : 
    1342             :     ScRange aDestRange( rDest, ScAddress(
    1343           0 :                 static_cast<SCCOL>(rDest.Col() + rSource.aEnd.Row() - rSource.aStart.Row()),
    1344           0 :                 static_cast<SCROW>(rDest.Row() + rSource.aEnd.Col() - rSource.aStart.Col()),
    1345           0 :                 rDest.Tab() + rSource.aEnd.Tab() - rSource.aStart.Tab() ) );
    1346           0 :     if ( aDestRange.In( aOldPos ) )
    1347             :     {
    1348             :         //  Count back Positions
    1349           0 :         SCsCOL nRelPosX = aOldPos.Col();
    1350           0 :         SCsROW nRelPosY = aOldPos.Row();
    1351           0 :         SCsTAB nRelPosZ = aOldPos.Tab();
    1352           0 :         ScRefUpdate::DoTranspose( nRelPosX, nRelPosY, nRelPosZ, pDocument, aDestRange, rSource.aStart );
    1353           0 :         aOldPos.Set( nRelPosX, nRelPosY, nRelPosZ );
    1354           0 :         bPosChanged = true;
    1355             :     }
    1356             : 
    1357           0 :     ScTokenArray* pOld = pUndoDoc ? pCode->Clone() : NULL;
    1358           0 :     bool bRefChanged = false;
    1359             :     ScToken* t;
    1360             : 
    1361           0 :     ScRangeData* pShared = NULL;
    1362           0 :     pCode->Reset();
    1363           0 :     while( (t = static_cast<ScToken*>(pCode->GetNextReferenceOrName())) != NULL )
    1364             :     {
    1365           0 :         if( t->GetOpCode() == ocName )
    1366             :         {
    1367           0 :             ScRangeData* pName = pDocument->GetRangeName()->findByIndex( t->GetIndex() );
    1368           0 :             if (pName)
    1369             :             {
    1370           0 :                 if (pName->IsModified())
    1371           0 :                     bRefChanged = true;
    1372           0 :                 if (pName->HasType(RT_SHAREDMOD))
    1373           0 :                     pShared = pName;
    1374             :             }
    1375             :         }
    1376           0 :         else if( t->GetType() != svIndex )
    1377             :         {
    1378           0 :             t->CalcAbsIfRel( aOldPos );
    1379             :             bool bMod;
    1380             :             {   // own scope for SingleDoubleRefModifier dtor if SingleRef
    1381           0 :                 SingleDoubleRefModifier aMod( *t );
    1382           0 :                 ScComplexRefData& rRef = aMod.Ref();
    1383             :                 bMod = (ScRefUpdate::UpdateTranspose( pDocument, rSource,
    1384           0 :                     rDest, rRef ) != UR_NOTHING || bPosChanged);
    1385             :             }
    1386           0 :             if ( bMod )
    1387             :             {
    1388           0 :                 t->CalcRelFromAbs( aPos );
    1389           0 :                 bRefChanged = true;
    1390             :             }
    1391             :         }
    1392             :     }
    1393             : 
    1394           0 :     if (pShared)            // Shared Formula against real Formula exchange
    1395             :     {
    1396           0 :         pDocument->RemoveFromFormulaTree( this );   // update formula count
    1397           0 :         delete pCode;
    1398           0 :         pCode = new ScTokenArray( *pShared->GetCode() );
    1399           0 :         bRefChanged = true;
    1400           0 :         pCode->Reset();
    1401           0 :         while( (t = static_cast<ScToken*>(pCode->GetNextReference())) != NULL )
    1402             :         {
    1403           0 :             if( t->GetType() != svIndex )
    1404             :             {
    1405           0 :                 t->CalcAbsIfRel( aOldPos );
    1406             :                 bool bMod;
    1407             :                 {   // own scope for SingleDoubleRefModifier dtor if SingleRef
    1408           0 :                     SingleDoubleRefModifier aMod( *t );
    1409           0 :                     ScComplexRefData& rRef = aMod.Ref();
    1410             :                     bMod = (ScRefUpdate::UpdateTranspose( pDocument, rSource,
    1411           0 :                         rDest, rRef ) != UR_NOTHING || bPosChanged);
    1412             :                 }
    1413           0 :                 if ( bMod )
    1414           0 :                     t->CalcRelFromAbs( aPos );
    1415             :             }
    1416             :         }
    1417             :     }
    1418             : 
    1419           0 :     if (bRefChanged)
    1420             :     {
    1421           0 :         if (pUndoDoc)
    1422             :         {
    1423             :             ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aPos, pOld,
    1424           0 :                     eTempGrammar, cMatrixFlag);
    1425           0 :             pFCell->aResult.SetToken( NULL);  // to recognize it as changed later (Cut/Paste!)
    1426           0 :             pUndoDoc->PutCell( aPos.Col(), aPos.Row(), aPos.Tab(), pFCell );
    1427             :         }
    1428             : 
    1429           0 :         bCompile = true;
    1430           0 :         CompileTokenArray();                // also call StartListeningTo
    1431           0 :         SetDirty();
    1432             :     }
    1433             :     else
    1434           0 :         StartListeningTo( pDocument );      // Listener as previous
    1435             : 
    1436           0 :     delete pOld;
    1437           0 : }
    1438             : 
    1439           0 : void ScFormulaCell::UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY )
    1440             : {
    1441           0 :     EndListeningTo( pDocument );
    1442             : 
    1443           0 :     bool bRefChanged = false;
    1444             :     ScToken* t;
    1445           0 :     ScRangeData* pShared = NULL;
    1446             : 
    1447           0 :     pCode->Reset();
    1448           0 :     while( (t = static_cast<ScToken*>(pCode->GetNextReferenceOrName())) != NULL )
    1449             :     {
    1450           0 :         if( t->GetOpCode() == ocName )
    1451             :         {
    1452           0 :             ScRangeData* pName = pDocument->GetRangeName()->findByIndex( t->GetIndex() );
    1453           0 :             if (pName)
    1454             :             {
    1455           0 :                 if (pName->IsModified())
    1456           0 :                     bRefChanged = true;
    1457           0 :                 if (pName->HasType(RT_SHAREDMOD))
    1458           0 :                     pShared = pName;
    1459             :             }
    1460             :         }
    1461           0 :         else if( t->GetType() != svIndex )
    1462             :         {
    1463           0 :             t->CalcAbsIfRel( aPos );
    1464             :             bool bMod;
    1465             :             {   // own scope for SingleDoubleRefModifier dtor if SingleRef
    1466           0 :                 SingleDoubleRefModifier aMod( *t );
    1467           0 :                 ScComplexRefData& rRef = aMod.Ref();
    1468             :                 bMod = (ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY,
    1469           0 :                     rRef ) != UR_NOTHING);
    1470             :             }
    1471           0 :             if ( bMod )
    1472             :             {
    1473           0 :                 t->CalcRelFromAbs( aPos );
    1474           0 :                 bRefChanged = true;
    1475             :             }
    1476             :         }
    1477             :     }
    1478             : 
    1479           0 :     if (pShared)            // Shared Formula gegen echte Formel austauschen
    1480             :     {
    1481           0 :         pDocument->RemoveFromFormulaTree( this );   // update formula count
    1482           0 :         delete pCode;
    1483           0 :         pCode = new ScTokenArray( *pShared->GetCode() );
    1484           0 :         bRefChanged = true;
    1485           0 :         pCode->Reset();
    1486           0 :         while( (t = static_cast<ScToken*>(pCode->GetNextReference())) != NULL )
    1487             :         {
    1488           0 :             if( t->GetType() != svIndex )
    1489             :             {
    1490           0 :                 t->CalcAbsIfRel( aPos );
    1491             :                 bool bMod;
    1492             :                 {   // own scope for SingleDoubleRefModifier dtor if SingleRef
    1493           0 :                     SingleDoubleRefModifier aMod( *t );
    1494           0 :                     ScComplexRefData& rRef = aMod.Ref();
    1495             :                     bMod = (ScRefUpdate::UpdateGrow( rArea,nGrowX,nGrowY,
    1496           0 :                         rRef ) != UR_NOTHING);
    1497             :                 }
    1498           0 :                 if ( bMod )
    1499           0 :                     t->CalcRelFromAbs( aPos );
    1500             :             }
    1501             :         }
    1502             :     }
    1503             : 
    1504           0 :     if (bRefChanged)
    1505             :     {
    1506           0 :         bCompile = true;
    1507           0 :         CompileTokenArray();                // also call StartListeningTo
    1508           0 :         SetDirty();
    1509             :     }
    1510             :     else
    1511           0 :         StartListeningTo( pDocument );      // Listener as previous
    1512           0 : }
    1513             : 
    1514           3 : static void lcl_FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes, ScTokenArray* pCode, ScRangeName* pNames)
    1515             : {
    1516          13 :     for (FormulaToken* p = pCode->First(); p; p = pCode->Next())
    1517             :     {
    1518          10 :         if (p->GetOpCode() == ocName)
    1519             :         {
    1520           2 :             sal_uInt16 nTokenIndex = p->GetIndex();
    1521           2 :             rIndexes.insert( nTokenIndex );
    1522             : 
    1523           2 :             ScRangeData* pSubName = pNames->findByIndex(p->GetIndex());
    1524           2 :             if (pSubName)
    1525           2 :                 lcl_FindRangeNamesInUse(rIndexes, pSubName->GetCode(), pNames);
    1526             :         }
    1527             :     }
    1528           3 : }
    1529             : 
    1530           1 : void ScFormulaCell::FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes) const
    1531             : {
    1532           1 :     lcl_FindRangeNamesInUse( rIndexes, pCode, pDocument->GetRangeName() );
    1533           1 : }
    1534             : 
    1535           0 : bool ScFormulaCell::IsChanged() const
    1536             : {
    1537           0 :     return bChanged;
    1538             : }
    1539             : 
    1540          23 : void ScFormulaCell::ResetChanged()
    1541             : {
    1542          23 :     bChanged = false;
    1543          23 : }
    1544             : 
    1545           0 : void ScFormulaCell::CompileDBFormula()
    1546             : {
    1547           0 :     for( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
    1548             :     {
    1549           0 :         if ( p->GetOpCode() == ocDBArea
    1550           0 :             || (p->GetOpCode() == ocName && p->GetIndex() >= SC_START_INDEX_DB_COLL) )
    1551             :         {
    1552           0 :             bCompile = true;
    1553           0 :             CompileTokenArray();
    1554           0 :             SetDirty();
    1555           0 :             break;
    1556             :         }
    1557             :     }
    1558           0 : }
    1559             : 
    1560           0 : void ScFormulaCell::CompileDBFormula( bool bCreateFormulaString )
    1561             : {
    1562             :     // two phases must be called after each other
    1563             :     // 1. Formula String with old generated names
    1564             :     // 2. Formula String with new generated names
    1565           0 :     if ( bCreateFormulaString )
    1566             :     {
    1567           0 :         bool bRecompile = false;
    1568           0 :         pCode->Reset();
    1569           0 :         for ( FormulaToken* p = pCode->First(); p && !bRecompile; p = pCode->Next() )
    1570             :         {
    1571           0 :             switch ( p->GetOpCode() )
    1572             :             {
    1573             :                 case ocBad:             // DB-Area eventually goes bad
    1574             :                 case ocColRowName:      // in case of the same names
    1575             :                 case ocDBArea:          // DB-Area
    1576           0 :                     bRecompile = true;
    1577           0 :                 break;
    1578             :                 case ocName:
    1579           0 :                     if ( p->GetIndex() >= SC_START_INDEX_DB_COLL )
    1580           0 :                         bRecompile = true;  // DB-Area
    1581           0 :                 break;
    1582             :                 default:
    1583             :                     ; // nothing
    1584             :             }
    1585             :         }
    1586           0 :         if ( bRecompile )
    1587             :         {
    1588           0 :             rtl::OUString aFormula;
    1589           0 :             GetFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE);
    1590           0 :             if ( GetMatrixFlag() != MM_NONE && !aFormula.isEmpty() )
    1591             :             {
    1592           0 :                 if ( aFormula[ aFormula.getLength()-1 ] == '}' )
    1593           0 :                     aFormula = aFormula.copy( 0, aFormula.getLength()-1 );
    1594           0 :                 if ( aFormula[0] == '{' )
    1595           0 :                     aFormula = aFormula.copy( 1 );
    1596             :             }
    1597           0 :             EndListeningTo( pDocument );
    1598           0 :             pDocument->RemoveFromFormulaTree( this );
    1599           0 :             pCode->Clear();
    1600           0 :             SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE);
    1601             :         }
    1602             :     }
    1603           0 :     else if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
    1604             :     {
    1605           0 :         Compile( aResult.GetHybridFormula(), false, eTempGrammar );
    1606           0 :         aResult.SetToken( NULL);
    1607           0 :         SetDirty();
    1608             :     }
    1609           0 : }
    1610             : 
    1611          34 : void ScFormulaCell::CompileNameFormula( bool bCreateFormulaString )
    1612             : {
    1613             :     // two phases must be called after each other
    1614             :     // 1. Formula String with old generated names
    1615             :     // 2. Formula String with new generated names
    1616          34 :     if ( bCreateFormulaString )
    1617             :     {
    1618           0 :         bool bRecompile = false;
    1619           0 :         pCode->Reset();
    1620           0 :         for ( FormulaToken* p = pCode->First(); p && !bRecompile; p = pCode->Next() )
    1621             :         {
    1622           0 :             switch ( p->GetOpCode() )
    1623             :             {
    1624             :                 case ocBad:             // in case RangeName goes bad
    1625             :                 case ocColRowName:      // in case the names are the same
    1626           0 :                     bRecompile = true;
    1627           0 :                 break;
    1628             :                 default:
    1629           0 :                     if ( p->GetType() == svIndex )
    1630           0 :                         bRecompile = true;  // RangeName
    1631             :             }
    1632             :         }
    1633           0 :         if ( bRecompile )
    1634             :         {
    1635           0 :             rtl::OUString aFormula;
    1636           0 :             GetFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE);
    1637           0 :             if ( GetMatrixFlag() != MM_NONE && !aFormula.isEmpty() )
    1638             :             {
    1639           0 :                 if ( aFormula[ aFormula.getLength()-1 ] == '}' )
    1640           0 :                     aFormula = aFormula.copy( 0, aFormula.getLength()-1 );
    1641           0 :                 if ( aFormula[0] == '{' )
    1642           0 :                     aFormula = aFormula.copy( 1 );
    1643             :             }
    1644           0 :             EndListeningTo( pDocument );
    1645           0 :             pDocument->RemoveFromFormulaTree( this );
    1646           0 :             pCode->Clear();
    1647           0 :             SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE);
    1648             :         }
    1649             :     }
    1650          34 :     else if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() )
    1651             :     {
    1652           0 :         Compile( aResult.GetHybridFormula(), false, eTempGrammar );
    1653           0 :         aResult.SetToken( NULL);
    1654           0 :         SetDirty();
    1655             :     }
    1656          34 : }
    1657             : 
    1658           0 : void ScFormulaCell::CompileColRowNameFormula()
    1659             : {
    1660           0 :     pCode->Reset();
    1661           0 :     for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() )
    1662             :     {
    1663           0 :         if ( p->GetOpCode() == ocColRowName )
    1664             :         {
    1665           0 :             bCompile = true;
    1666           0 :             CompileTokenArray();
    1667           0 :             SetDirty();
    1668           0 :             break;
    1669             :         }
    1670             :     }
    1671          15 : }
    1672             : 
    1673             : // ============================================================================
    1674             : 
    1675             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10