LCOV - code coverage report
Current view: top level - sc/source/core/tool - token.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1220 1849 66.0 %
Date: 2014-11-03 Functions: 129 184 70.1 %
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 <cstddef>
      21             : #include <cstdio>
      22             : 
      23             : #include <string.h>
      24             : #include <tools/mempool.hxx>
      25             : #include <osl/diagnose.h>
      26             : #include <sfx2/docfile.hxx>
      27             : 
      28             : #include "token.hxx"
      29             : #include "tokenarray.hxx"
      30             : #include "reftokenhelper.hxx"
      31             : #include "clipparam.hxx"
      32             : #include "compiler.hxx"
      33             : #include <formula/compiler.hrc>
      34             : #include "rechead.hxx"
      35             : #include "parclass.hxx"
      36             : #include "jumpmatrix.hxx"
      37             : #include "rangeseq.hxx"
      38             : #include "externalrefmgr.hxx"
      39             : #include "document.hxx"
      40             : #include "refupdatecontext.hxx"
      41             : #include "tokenstringcontext.hxx"
      42             : #include "types.hxx"
      43             : #include "globstr.hrc"
      44             : #include "addincol.hxx"
      45             : #include <svl/sharedstring.hxx>
      46             : 
      47             : using ::std::vector;
      48             : 
      49             : #include <com/sun/star/sheet/ComplexReference.hpp>
      50             : #include <com/sun/star/sheet/ExternalReference.hpp>
      51             : #include <com/sun/star/sheet/ReferenceFlags.hpp>
      52             : #include <com/sun/star/sheet/NameToken.hpp>
      53             : 
      54             : using namespace formula;
      55             : using namespace com::sun::star;
      56             : 
      57             : namespace
      58             : {
      59         270 :     void lcl_SingleRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI )
      60             :     {
      61         270 :         rRef.InitFlags();
      62             : 
      63         270 :         rRef.SetColRel(     ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
      64         270 :         rRef.SetRowRel(     ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE    ) != 0 );
      65         270 :         rRef.SetTabRel(     ( rAPI.Flags & sheet::ReferenceFlags::SHEET_RELATIVE  ) != 0 );
      66         270 :         rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED  ) != 0 );
      67         270 :         rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED     ) != 0 );
      68         270 :         rRef.SetTabDeleted( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_DELETED   ) != 0 );
      69         270 :         rRef.SetFlag3D(     ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D        ) != 0 );
      70         270 :         rRef.SetRelName(    ( rAPI.Flags & sheet::ReferenceFlags::RELATIVE_NAME   ) != 0 );
      71             : 
      72         270 :         if (rRef.IsColRel())
      73          12 :             rRef.SetRelCol(static_cast<SCCOL>(rAPI.RelativeColumn));
      74             :         else
      75         258 :             rRef.SetAbsCol(static_cast<SCCOL>(rAPI.Column));
      76             : 
      77         270 :         if (rRef.IsRowRel())
      78          12 :             rRef.SetRelRow(static_cast<SCROW>(rAPI.RelativeRow));
      79             :         else
      80         258 :             rRef.SetAbsRow(static_cast<SCROW>(rAPI.Row));
      81             : 
      82         270 :         if (rRef.IsTabRel())
      83          12 :             rRef.SetRelTab(static_cast<SCsTAB>(rAPI.RelativeSheet));
      84             :         else
      85         258 :             rRef.SetAbsTab(static_cast<SCsTAB>(rAPI.Sheet));
      86         270 :     }
      87             : 
      88           0 :     void lcl_ExternalRefToCalc( ScSingleRefData& rRef, const sheet::SingleReference& rAPI )
      89             :     {
      90           0 :         rRef.InitFlags();
      91             : 
      92           0 :         rRef.SetColRel(     ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
      93           0 :         rRef.SetRowRel(     ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE    ) != 0 );
      94           0 :         rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED  ) != 0 );
      95           0 :         rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED     ) != 0 );
      96           0 :         rRef.SetTabDeleted( false );    // sheet must not be deleted for external refs
      97           0 :         rRef.SetFlag3D(     ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D        ) != 0 );
      98           0 :         rRef.SetRelName(    false );
      99             : 
     100           0 :         if (rRef.IsColRel())
     101           0 :             rRef.SetRelCol(static_cast<SCCOL>(rAPI.RelativeColumn));
     102             :         else
     103           0 :             rRef.SetAbsCol(static_cast<SCCOL>(rAPI.Column));
     104             : 
     105           0 :         if (rRef.IsRowRel())
     106           0 :             rRef.SetRelRow(static_cast<SCROW>(rAPI.RelativeRow));
     107             :         else
     108           0 :             rRef.SetAbsRow(static_cast<SCROW>(rAPI.Row));
     109             : 
     110             :         // sheet index must be absolute for external refs
     111           0 :         rRef.SetAbsTab(0);
     112           0 :     }
     113             : 
     114             : } // namespace
     115             : 
     116             : // Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2)
     117             : 
     118             : // Since RawTokens are temporary for the compiler, don't align on 4k and waste memory.
     119             : // ScRawToken size is FixMembers + MAXSTRLEN + ~4 ~= 1036
     120          76 : IMPL_FIXEDMEMPOOL_NEWDEL( ScRawToken )
     121             : // Some ScDoubleRawToken, FixMembers + sizeof(double) ~= 16
     122          76 : IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRawToken )
     123             : 
     124             : // Need a whole bunch of ScSingleRefToken
     125          76 : IMPL_FIXEDMEMPOOL_NEWDEL( ScSingleRefToken )
     126             : // Need quite a lot of ScDoubleRefToken
     127          76 : IMPL_FIXEDMEMPOOL_NEWDEL( ScDoubleRefToken )
     128             : 
     129             : // --- class ScRawToken -----------------------------------------------------
     130             : 
     131         172 : sal_Int32 ScRawToken::GetStrLen( const sal_Unicode* pStr )
     132             : {
     133         172 :     if ( !pStr )
     134           0 :         return 0;
     135         172 :     const sal_Unicode* p = pStr;
     136        8196 :     while ( *p )
     137        7852 :         p++;
     138         172 :     return sal::static_int_cast<sal_Int32>( p - pStr );
     139             : }
     140             : 
     141       61086 : void ScRawToken::SetOpCode( OpCode e )
     142             : {
     143       61086 :     eOp   = e;
     144       61086 :     switch (eOp)
     145             :     {
     146             :         case ocIf:
     147          74 :             eType = svJump;
     148          74 :             nJump[ 0 ] = 3; // If, Else, Behind
     149          74 :             break;
     150             :         case ocIfError:
     151             :         case ocIfNA:
     152          24 :             eType = svJump;
     153          24 :             nJump[ 0 ] = 2; // If, Behind
     154          24 :             break;
     155             :         case ocChose:
     156           2 :             eType = svJump;
     157           2 :             nJump[ 0 ] = FORMULA_MAXJUMPCOUNT + 1;
     158           2 :             break;
     159             :         case ocMissing:
     160           2 :             eType = svMissing;
     161           2 :             break;
     162             :         case ocSep:
     163             :         case ocOpen:
     164             :         case ocClose:
     165             :         case ocArrayRowSep:
     166             :         case ocArrayColSep:
     167             :         case ocArrayOpen:
     168             :         case ocArrayClose:
     169       37630 :             eType = svSep;
     170       37630 :             break;
     171             :         default:
     172       23354 :             eType = svByte;
     173       23354 :             sbyte.cByte = 0;
     174       23354 :             sbyte.bHasForceArray = ScParameterClassification::HasForceArray( eOp);
     175             :     }
     176       61086 :     nRefCnt = 0;
     177       61086 : }
     178             : 
     179        1052 : void ScRawToken::SetString( rtl_uString* pData, rtl_uString* pDataIgoreCase )
     180             : {
     181        1052 :     eOp   = ocPush;
     182        1052 :     eType = svString;
     183        1052 :     nRefCnt = 0;
     184             : 
     185        1052 :     sharedstring.mpData = pData;
     186        1052 :     sharedstring.mpDataIgnoreCase = pDataIgoreCase;
     187        1052 : }
     188             : 
     189        6682 : void ScRawToken::SetSingleReference( const ScSingleRefData& rRef )
     190             : {
     191        6682 :     eOp       = ocPush;
     192        6682 :     eType     = svSingleRef;
     193             :     aRef.Ref1 =
     194        6682 :     aRef.Ref2 = rRef;
     195        6682 :     nRefCnt   = 0;
     196        6682 : }
     197             : 
     198        4646 : void ScRawToken::SetDoubleReference( const ScComplexRefData& rRef )
     199             : {
     200        4646 :     eOp   = ocPush;
     201        4646 :     eType = svDoubleRef;
     202        4646 :     aRef  = rRef;
     203        4646 :     nRefCnt = 0;
     204        4646 : }
     205             : 
     206        4760 : void ScRawToken::SetDouble(double rVal)
     207             : {
     208        4760 :     eOp   = ocPush;
     209        4760 :     eType = svDouble;
     210        4760 :     nValue = rVal;
     211        4760 :     nRefCnt = 0;
     212        4760 : }
     213             : 
     214          46 : void ScRawToken::SetErrorConstant( sal_uInt16 nErr )
     215             : {
     216          46 :     eOp   = ocPush;
     217          46 :     eType = svError;
     218          46 :     nError = nErr;
     219          46 :     nRefCnt = 0;
     220          46 : }
     221             : 
     222         146 : void ScRawToken::SetName(bool bGlobal, sal_uInt16 nIndex)
     223             : {
     224         146 :     eOp = ocName;
     225         146 :     eType = svIndex;
     226         146 :     nRefCnt = 0;
     227             : 
     228         146 :     name.bGlobal = bGlobal;
     229         146 :     name.nIndex = nIndex;
     230         146 : }
     231             : 
     232          76 : void ScRawToken::SetExternalSingleRef( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef )
     233             : {
     234          76 :     eOp = ocPush;
     235          76 :     eType = svExternalSingleRef;
     236          76 :     nRefCnt = 0;
     237             : 
     238          76 :     extref.nFileId = nFileId;
     239             :     extref.aRef.Ref1 =
     240          76 :     extref.aRef.Ref2 = rRef;
     241             : 
     242          76 :     sal_Int32 n = rTabName.getLength();
     243          76 :     memcpy(extref.cTabName, rTabName.getStr(), n*sizeof(sal_Unicode));
     244          76 :     extref.cTabName[n] = 0;
     245          76 : }
     246             : 
     247          24 : void ScRawToken::SetExternalDoubleRef( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef )
     248             : {
     249          24 :     eOp = ocPush;
     250          24 :     eType = svExternalDoubleRef;
     251          24 :     nRefCnt = 0;
     252             : 
     253          24 :     extref.nFileId = nFileId;
     254          24 :     extref.aRef = rRef;
     255             : 
     256          24 :     sal_Int32 n = rTabName.getLength();
     257          24 :     memcpy(extref.cTabName, rTabName.getStr(), n*sizeof(sal_Unicode));
     258          24 :     extref.cTabName[n] = 0;
     259          24 : }
     260             : 
     261           0 : void ScRawToken::SetExternalName( sal_uInt16 nFileId, const OUString& rName )
     262             : {
     263           0 :     eOp = ocPush;
     264           0 :     eType = svExternalName;
     265           0 :     nRefCnt = 0;
     266             : 
     267           0 :     extname.nFileId = nFileId;
     268             : 
     269           0 :     sal_Int32 n = rName.getLength();
     270           0 :     memcpy(extname.cName, rName.getStr(), n*sizeof(sal_Unicode));
     271           0 :     extname.cName[n] = 0;
     272           0 : }
     273             : 
     274         172 : void ScRawToken::SetExternal( const sal_Unicode* pStr )
     275             : {
     276         172 :     eOp   = ocExternal;
     277         172 :     eType = svExternal;
     278         172 :     sal_Int32 nLen = GetStrLen( pStr ) + 1;
     279         172 :     if( nLen >= MAXSTRLEN )
     280           0 :         nLen = MAXSTRLEN-1;
     281             :     // Platz fuer Byte-Parameter lassen!
     282         172 :     memcpy( cStr+1, pStr, GetStrLenBytes( nLen ) );
     283         172 :     cStr[ nLen+1 ] = 0;
     284         172 :     nRefCnt = 0;
     285         172 : }
     286             : 
     287       10780 : bool ScRawToken::IsValidReference() const
     288             : {
     289       10780 :     switch (eType)
     290             :     {
     291             :         case svSingleRef:
     292        6278 :             return aRef.Ref1.Valid();
     293             :         case svDoubleRef:
     294        4428 :             return aRef.Valid();
     295             :         case svExternalSingleRef:
     296             :         case svExternalDoubleRef:
     297          74 :             return true;
     298             :         default:
     299             :             ;   // nothing
     300             :     }
     301           0 :     return false;
     302             : }
     303             : 
     304           0 : sal_uInt16 ScRawToken::sbyteOffset()
     305             : {
     306             :     // offset of sbyte in ScRawToken
     307             :     // offsetof(ScRawToken, sbyte) gives a warning with gcc, because ScRawToken is no POD
     308             : 
     309           0 :     ScRawToken aToken;
     310           0 :     return static_cast<sal_uInt16>( reinterpret_cast<char*>(&aToken.sbyte) - reinterpret_cast<char*>(&aToken) );
     311             : }
     312             : 
     313           0 : ScRawToken* ScRawToken::Clone() const
     314             : {
     315             :     ScRawToken* p;
     316           0 :     if ( eType == svDouble )
     317             :     {
     318           0 :         p = (ScRawToken*) new ScDoubleRawToken;
     319           0 :         p->eOp = eOp;
     320           0 :         p->eType = eType;
     321           0 :         p->nValue = nValue;
     322             :     }
     323             :     else
     324             :     {
     325           0 :         static sal_uInt16 nOffset = sbyteOffset();     // offset of sbyte
     326           0 :         sal_uInt16 n = nOffset;
     327             : 
     328           0 :         switch( eType )
     329             :         {
     330           0 :             case svSep:         break;
     331           0 :             case svByte:        n += sizeof(ScRawToken::sbyte); break;
     332           0 :             case svDouble:      n += sizeof(double); break;
     333           0 :             case svError:       n += sizeof(nError); break;
     334           0 :             case svString:      n += sizeof(sharedstring); break;
     335             :             case svSingleRef:
     336           0 :             case svDoubleRef:   n += sizeof(aRef); break;
     337           0 :             case svMatrix:      n += sizeof(ScMatrix*); break;
     338           0 :             case svIndex:       n += sizeof(name); break;
     339           0 :             case svJump:        n += nJump[ 0 ] * 2 + 2; break;
     340           0 :             case svExternal:    n = sal::static_int_cast<sal_uInt16>( n + GetStrLenBytes( cStr+1 ) + GetStrLenBytes( 2 ) ); break;
     341             : 
     342             :             // external references
     343             :             case svExternalSingleRef:
     344           0 :             case svExternalDoubleRef: n += sizeof(extref); break;
     345           0 :             case svExternalName:      n += sizeof(extname); break;
     346             :             default:
     347             :             {
     348             :                 OSL_TRACE( "unknown ScRawToken::Clone() type %d", int(eType));
     349             :             }
     350             :         }
     351           0 :         p = (ScRawToken*) new sal_uInt8[ n ];
     352           0 :         memcpy( p, this, n * sizeof(sal_uInt8) );
     353             :     }
     354           0 :     p->nRefCnt = 0;
     355           0 :     p->bRaw = false;
     356           0 :     return p;
     357             : }
     358             : 
     359       78690 : FormulaToken* ScRawToken::CreateToken() const
     360             : {
     361             : #if OSL_DEBUG_LEVEL > 1
     362             : #define IF_NOT_OPCODE_ERROR(o,c) if (eOp!=o) OSL_TRACE( #c "::ctor: OpCode %d lost, converted to " #o "; maybe inherit from FormulaToken instead!", int(eOp))
     363             : #else
     364             : #define IF_NOT_OPCODE_ERROR(o,c)
     365             : #endif
     366       78690 :     switch ( GetType() )
     367             :     {
     368             :         case svByte :
     369       23354 :             return new FormulaByteToken( eOp, sbyte.cByte, sbyte.bHasForceArray );
     370             :         case svDouble :
     371             :             IF_NOT_OPCODE_ERROR( ocPush, FormulaDoubleToken);
     372        4760 :             return new FormulaDoubleToken( nValue );
     373             :         case svString :
     374             :         {
     375        1052 :             svl::SharedString aSS(sharedstring.mpData, sharedstring.mpDataIgnoreCase);
     376        1052 :             if (eOp == ocPush)
     377        1020 :                 return new FormulaStringToken(aSS);
     378             :             else
     379          32 :                 return new FormulaStringOpToken(eOp, aSS);
     380             :         }
     381             :         case svSingleRef :
     382        6682 :             if (eOp == ocPush)
     383        6682 :                 return new ScSingleRefToken( aRef.Ref1 );
     384             :             else
     385           0 :                 return new ScSingleRefToken( aRef.Ref1, eOp );
     386             :         case svDoubleRef :
     387        4646 :             if (eOp == ocPush)
     388        4646 :                 return new ScDoubleRefToken( aRef );
     389             :             else
     390           0 :                 return new ScDoubleRefToken( aRef, eOp );
     391             :         case svMatrix :
     392             :             IF_NOT_OPCODE_ERROR( ocPush, ScMatrixToken);
     393           0 :             return new ScMatrixToken( pMat );
     394             :         case svIndex :
     395         146 :             return new FormulaIndexToken( eOp, name.nIndex, name.bGlobal);
     396             :         case svExternalSingleRef:
     397             :             {
     398          76 :                 OUString aTabName(extref.cTabName);
     399          76 :                 return new ScExternalSingleRefToken(extref.nFileId, aTabName, extref.aRef.Ref1);
     400             :             }
     401             :         case svExternalDoubleRef:
     402             :             {
     403          24 :                 OUString aTabName(extref.cTabName);
     404          24 :                 return new ScExternalDoubleRefToken(extref.nFileId, aTabName, extref.aRef);
     405             :             }
     406             :         case svExternalName:
     407             :             {
     408           0 :                 OUString aName(extname.cName);
     409           0 :                 return new ScExternalNameToken( extname.nFileId, aName );
     410             :             }
     411             :         case svJump :
     412         100 :             return new FormulaJumpToken( eOp, (short*) nJump );
     413             :         case svExternal :
     414         172 :             return new FormulaExternalToken( eOp, sbyte.cByte, OUString( cStr+1 ) );
     415             :         case svFAP :
     416           0 :             return new FormulaFAPToken( eOp, sbyte.cByte, NULL );
     417             :         case svMissing :
     418             :             IF_NOT_OPCODE_ERROR( ocMissing, FormulaMissingToken);
     419           2 :             return new FormulaMissingToken;
     420             :         case svSep :
     421       37630 :             return new FormulaToken( svSep,eOp );
     422             :         case svError :
     423          46 :             return new FormulaErrorToken( nError );
     424             :         case svUnknown :
     425           0 :             return new FormulaUnknownToken( eOp );
     426             :         default:
     427             :             {
     428             :                 OSL_TRACE( "unknown ScRawToken::CreateToken() type %d", int(GetType()));
     429           0 :                 return new FormulaUnknownToken( ocBad );
     430             :             }
     431             :     }
     432             : #undef IF_NOT_OPCODE_ERROR
     433             : }
     434             : 
     435           0 : void ScRawToken::Delete()
     436             : {
     437           0 :     if ( bRaw )
     438           0 :         delete this;                            // FixedMemPool ScRawToken
     439             :     else
     440             :     {   // created per Clone
     441           0 :         switch ( eType )
     442             :         {
     443             :             case svDouble :
     444           0 :                 delete (ScDoubleRawToken*) this;    // FixedMemPool ScDoubleRawToken
     445           0 :             break;
     446             :             default:
     447           0 :                 delete [] (sal_uInt8*) this;
     448             :         }
     449             :     }
     450           0 : }
     451             : 
     452             : namespace {
     453             : 
     454             : //  TextEqual: if same formula entered (for optimization in sort)
     455           8 : bool checkTextEqual( const FormulaToken& _rToken1, const FormulaToken& _rToken2 )
     456             : {
     457             :     assert(
     458             :         (_rToken1.GetType() == svSingleRef || _rToken1.GetType() == svDoubleRef)
     459             :         && _rToken1.FormulaToken::operator ==(_rToken2));
     460             : 
     461             :     //  in relative Refs only compare relative parts
     462             : 
     463             :     ScComplexRefData aTemp1;
     464           8 :     if ( _rToken1.GetType() == svSingleRef )
     465             :     {
     466           8 :         aTemp1.Ref1 = *_rToken1.GetSingleRef();
     467           8 :         aTemp1.Ref2 = aTemp1.Ref1;
     468             :     }
     469             :     else
     470           0 :         aTemp1 = *_rToken1.GetDoubleRef();
     471             : 
     472             :     ScComplexRefData aTemp2;
     473           8 :     if ( _rToken2.GetType() == svSingleRef )
     474             :     {
     475           8 :         aTemp2.Ref1 = *_rToken2.GetSingleRef();
     476           8 :         aTemp2.Ref2 = aTemp2.Ref1;
     477             :     }
     478             :     else
     479           0 :         aTemp2 = *_rToken2.GetDoubleRef();
     480             : 
     481           8 :     ScAddress aPos;
     482           8 :     ScRange aRange1 = aTemp1.toAbs(aPos), aRange2 = aTemp2.toAbs(aPos);
     483             : 
     484             :     //  memcmp doesn't work because of the alignment byte after bFlags.
     485             :     //  After SmartRelAbs only absolute parts have to be compared.
     486           8 :     return aRange1 == aRange2 && aTemp1.Ref1.FlagValue() == aTemp2.Ref1.FlagValue() && aTemp1.Ref2.FlagValue() == aTemp2.Ref2.FlagValue();
     487             : }
     488             : 
     489             : }
     490             : 
     491             : #if DEBUG_FORMULA_COMPILER
     492             : void DumpToken(formula::FormulaToken const & rToken)
     493             : {
     494             :     switch (rToken.GetType()) {
     495             :     case svSingleRef:
     496             :         cout << "-- ScSingleRefToken" << endl;
     497             :         rToken.GetSingleRef()->Dump(1);
     498             :         break;
     499             :     case svDoubleRef:
     500             :         cout << "-- ScDoubleRefToken" << endl;
     501             :         rToken.GetDoubleRef()->Dump(1);
     502             :         break;
     503             :     default:
     504             :         cout << "-- FormulaToken" << endl;
     505             :         cout << "  opcode: " << rToken.GetOpCode() << endl;
     506             :         cout << "  type: " << static_cast<int>(rToken.GetType()) << endl;
     507             :         switch (rToken.GetType())
     508             :         {
     509             :         case svDouble:
     510             :             cout << "  value: " << rToken.GetDouble() << endl;
     511             :             break;
     512             :         case svString:
     513             :             cout << "  string: "
     514             :                  << OUStringToOString(rToken.GetString().getString(), RTL_TEXTENCODING_UTF8).getStr()
     515             :                  << endl;
     516             :             break;
     517             :         default:
     518             :             ;
     519             :         }
     520             :         break;
     521             :     }
     522             : }
     523             : #endif
     524             : 
     525           0 : FormulaTokenRef extendRangeReference( FormulaToken & rTok1, FormulaToken & rTok2,
     526             :         const ScAddress & rPos, bool bReuseDoubleRef )
     527             : {
     528             : 
     529             :     StackVar sv1, sv2;
     530             :     // Doing a RangeOp with RefList is probably utter nonsense, but Xcl
     531             :     // supports it, so do we.
     532           0 :     if (((sv1 = rTok1.GetType()) != svSingleRef && sv1 != svDoubleRef && sv1 != svRefList &&
     533           0 :             sv1 != svExternalSingleRef && sv1 != svExternalDoubleRef ) ||
     534           0 :         ((sv2 = rTok2.GetType()) != svSingleRef && sv2 != svDoubleRef && sv2 != svRefList))
     535           0 :         return NULL;
     536             : 
     537           0 :     ScTokenRef xRes;
     538           0 :     bool bExternal = (sv1 == svExternalSingleRef);
     539           0 :     if ((sv1 == svSingleRef || bExternal) && sv2 == svSingleRef)
     540             :     {
     541             :         // Range references like Sheet1.A1:A2 are generalized and built by
     542             :         // first creating a DoubleRef from the first SingleRef, effectively
     543             :         // generating Sheet1.A1:A1, and then extending that with A2 as if
     544             :         // Sheet1.A1:A1:A2 was encountered, so the mechanisms to adjust the
     545             :         // references apply as well.
     546             : 
     547             :         /* Given the current structure of external references an external
     548             :          * reference can only be extended if the second reference does not
     549             :          * point to a different sheet. 'file'#Sheet1.A1:A2 is ok,
     550             :          * 'file'#Sheet1.A1:Sheet2.A2 is not. Since we can't determine from a
     551             :          * svSingleRef whether the sheet would be different from the one given
     552             :          * in the external reference, we have to bail out if there is any sheet
     553             :          * specified. NOTE: Xcl does handle external 3D references as in
     554             :          * '[file]Sheet1:Sheet2'!A1:A2
     555             :          *
     556             :          * FIXME: For OOo syntax be smart and remember an external singleref
     557             :          * encountered and if followed by ocRange and singleref, create an
     558             :          * external singleref for the second singleref. Both could then be
     559             :          * merged here. For Xcl syntax already parse an external range
     560             :          * reference entirely, cumbersome. */
     561             : 
     562           0 :         const ScSingleRefData& rRef2 = *rTok2.GetSingleRef();
     563           0 :         if (bExternal && rRef2.IsFlag3D())
     564           0 :             return NULL;
     565             : 
     566             :         ScComplexRefData aRef;
     567           0 :         aRef.Ref1 = aRef.Ref2 = *rTok1.GetSingleRef();
     568           0 :         aRef.Ref2.SetFlag3D( false);
     569           0 :         aRef.Extend( rRef2, rPos);
     570           0 :         if (bExternal)
     571           0 :             xRes = new ScExternalDoubleRefToken( rTok1.GetIndex(), rTok1.GetString(), aRef);
     572             :         else
     573           0 :             xRes = new ScDoubleRefToken( aRef);
     574             :     }
     575             :     else
     576             :     {
     577           0 :         bExternal |= (sv1 == svExternalDoubleRef);
     578           0 :         const ScRefList* pRefList = NULL;
     579           0 :         if (sv1 == svDoubleRef)
     580             :         {
     581           0 :             xRes = (bReuseDoubleRef && rTok1.GetRef() == 1 ? &rTok1 : rTok1.Clone());
     582           0 :             sv1 = svUnknown;    // mark as handled
     583             :         }
     584           0 :         else if (sv2 == svDoubleRef)
     585             :         {
     586           0 :             xRes = (bReuseDoubleRef && rTok2.GetRef() == 1 ? &rTok2 : rTok2.Clone());
     587           0 :             sv2 = svUnknown;    // mark as handled
     588             :         }
     589           0 :         else if (sv1 == svRefList)
     590           0 :             pRefList = rTok1.GetRefList();
     591           0 :         else if (sv2 == svRefList)
     592           0 :             pRefList = rTok2.GetRefList();
     593           0 :         if (pRefList)
     594             :         {
     595           0 :             if (!pRefList->size())
     596           0 :                 return NULL;
     597           0 :             if (bExternal)
     598           0 :                 return NULL;    // external reference list not possible
     599           0 :             xRes = new ScDoubleRefToken( (*pRefList)[0] );
     600             :         }
     601           0 :         if (!xRes)
     602           0 :             return NULL;    // shouldn't happen..
     603           0 :         StackVar sv[2] = { sv1, sv2 };
     604           0 :         formula::FormulaToken* pt[2] = { &rTok1, &rTok2 };
     605           0 :         ScComplexRefData& rRef = *xRes->GetDoubleRef();
     606           0 :         for (size_t i=0; i<2; ++i)
     607             :         {
     608           0 :             switch (sv[i])
     609             :             {
     610             :                 case svSingleRef:
     611           0 :                     rRef.Extend( *pt[i]->GetSingleRef(), rPos);
     612           0 :                     break;
     613             :                 case svDoubleRef:
     614           0 :                     rRef.Extend( *pt[i]->GetDoubleRef(), rPos);
     615           0 :                     break;
     616             :                 case svRefList:
     617             :                     {
     618           0 :                         const ScRefList* p = pt[i]->GetRefList();
     619           0 :                         if (!p->size())
     620           0 :                             return NULL;
     621           0 :                         ScRefList::const_iterator it( p->begin());
     622           0 :                         ScRefList::const_iterator end( p->end());
     623           0 :                         for ( ; it != end; ++it)
     624             :                         {
     625           0 :                             rRef.Extend( *it, rPos);
     626             :                         }
     627             :                     }
     628           0 :                     break;
     629             :                 case svExternalSingleRef:
     630           0 :                     if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D())
     631           0 :                         return NULL;    // no other sheets with external refs
     632             :                     else
     633           0 :                         rRef.Extend( *pt[i]->GetSingleRef(), rPos);
     634           0 :                     break;
     635             :                 case svExternalDoubleRef:
     636           0 :                     if (rRef.Ref1.IsFlag3D() || rRef.Ref2.IsFlag3D())
     637           0 :                         return NULL;    // no other sheets with external refs
     638             :                     else
     639           0 :                         rRef.Extend( *pt[i]->GetDoubleRef(), rPos);
     640           0 :                     break;
     641             :                 default:
     642             :                     ;   // nothing, prevent compiler warning
     643             :             }
     644             :         }
     645             :     }
     646           0 :     return FormulaTokenRef(xRes.get());
     647             : }
     648             : 
     649             : // real implementations of virtual functions
     650             : 
     651       38152 : const ScSingleRefData*    ScSingleRefToken::GetSingleRef() const  { return &aSingleRef; }
     652      192672 : ScSingleRefData*          ScSingleRefToken::GetSingleRef()        { return &aSingleRef; }
     653           8 : bool ScSingleRefToken::TextEqual( const FormulaToken& _rToken ) const
     654             : {
     655           8 :     return FormulaToken::operator ==(_rToken) && checkTextEqual(*this, _rToken);
     656             : }
     657           6 : bool ScSingleRefToken::operator==( const FormulaToken& r ) const
     658             : {
     659           6 :     return FormulaToken::operator==( r ) && aSingleRef == *r.GetSingleRef();
     660             : }
     661             : 
     662       12818 : const ScSingleRefData*    ScDoubleRefToken::GetSingleRef() const  { return &aDoubleRef.Ref1; }
     663        8074 : ScSingleRefData*          ScDoubleRefToken::GetSingleRef()        { return &aDoubleRef.Ref1; }
     664       16208 : const ScComplexRefData*     ScDoubleRefToken::GetDoubleRef() const  { return &aDoubleRef; }
     665       68868 : ScComplexRefData*           ScDoubleRefToken::GetDoubleRef()        { return &aDoubleRef; }
     666       12794 : const ScSingleRefData*    ScDoubleRefToken::GetSingleRef2() const { return &aDoubleRef.Ref2; }
     667        6542 : ScSingleRefData*          ScDoubleRefToken::GetSingleRef2()       { return &aDoubleRef.Ref2; }
     668           0 : bool ScDoubleRefToken::TextEqual( const FormulaToken& _rToken ) const
     669             : {
     670           0 :     return FormulaToken::operator ==(_rToken) && checkTextEqual(*this, _rToken);
     671             : }
     672          30 : bool ScDoubleRefToken::operator==( const FormulaToken& r ) const
     673             : {
     674          30 :     return FormulaToken::operator==( r ) && aDoubleRef == *r.GetDoubleRef();
     675             : }
     676             : 
     677           0 : const ScRefList*        ScRefListToken::GetRefList() const  { return &aRefList; }
     678           0 :       ScRefList*        ScRefListToken::GetRefList()        { return &aRefList; }
     679           0 : bool ScRefListToken::operator==( const FormulaToken& r ) const
     680             : {
     681           0 :     return FormulaToken::operator==( r ) && &aRefList == r.GetRefList();
     682             : }
     683             : 
     684         386 : ScMatrixToken::ScMatrixToken( const ScMatrixRef& p ) :
     685         386 :     FormulaToken(formula::svMatrix), pMatrix(p) {}
     686             : 
     687          34 : ScMatrixToken::ScMatrixToken( const ScMatrixToken& r ) :
     688          34 :     FormulaToken(r), pMatrix(r.pMatrix) {}
     689             : 
     690          10 : const ScMatrix* ScMatrixToken::GetMatrix() const        { return pMatrix.get(); }
     691         262 : ScMatrix*       ScMatrixToken::GetMatrix()              { return pMatrix.get(); }
     692           0 : bool ScMatrixToken::operator==( const FormulaToken& r ) const
     693             : {
     694           0 :     return FormulaToken::operator==( r ) && pMatrix == r.GetMatrix();
     695             : }
     696             : 
     697           0 : ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRef& p, const ScComplexRefData& rRef ) :
     698           0 :     FormulaToken(formula::svMatrix), mpMatrix(p), maRef(rRef) {}
     699             : 
     700           0 : ScMatrixRangeToken::ScMatrixRangeToken( const sc::RangeMatrix& rMat ) :
     701           0 :     FormulaToken(formula::svMatrix), mpMatrix(rMat.mpMat)
     702             : {
     703           0 :     maRef.InitRange(rMat.mnCol1, rMat.mnRow1, rMat.mnTab1, rMat.mnCol2, rMat.mnRow2, rMat.mnTab2);
     704           0 : }
     705             : 
     706           0 : ScMatrixRangeToken::ScMatrixRangeToken( const ScMatrixRangeToken& r ) :
     707           0 :     FormulaToken(r), mpMatrix(r.mpMatrix), maRef(r.maRef) {}
     708             : 
     709           0 : sal_uInt8 ScMatrixRangeToken::GetByte() const
     710             : {
     711           0 :     return MATRIX_TOKEN_HAS_RANGE;
     712             : }
     713             : 
     714           0 : const ScMatrix* ScMatrixRangeToken::GetMatrix() const
     715             : {
     716           0 :     return mpMatrix.get();
     717             : }
     718             : 
     719           0 : ScMatrix* ScMatrixRangeToken::GetMatrix()
     720             : {
     721           0 :     return mpMatrix.get();
     722             : }
     723             : 
     724           0 : const ScComplexRefData* ScMatrixRangeToken::GetDoubleRef() const
     725             : {
     726           0 :     return &maRef;
     727             : }
     728             : 
     729           0 : ScComplexRefData* ScMatrixRangeToken::GetDoubleRef()
     730             : {
     731           0 :     return &maRef;
     732             : }
     733             : 
     734           0 : bool ScMatrixRangeToken::operator==( const FormulaToken& r ) const
     735             : {
     736           0 :     return FormulaToken::operator==(r) && mpMatrix == r.GetMatrix();
     737             : }
     738             : 
     739           0 : FormulaToken* ScMatrixRangeToken::Clone() const
     740             : {
     741           0 :     return new ScMatrixRangeToken(*this);
     742             : }
     743             : 
     744          88 : ScExternalSingleRefToken::ScExternalSingleRefToken( sal_uInt16 nFileId, const svl::SharedString& rTabName, const ScSingleRefData& r ) :
     745             :     FormulaToken( svExternalSingleRef, ocPush),
     746             :     mnFileId(nFileId),
     747             :     maTabName(rTabName),
     748          88 :     maSingleRef(r)
     749             : {
     750          88 : }
     751             : 
     752         156 : ScExternalSingleRefToken::ScExternalSingleRefToken( const ScExternalSingleRefToken& r ) :
     753             :     FormulaToken(r),
     754             :     mnFileId(r.mnFileId),
     755             :     maTabName(r.maTabName),
     756         156 :     maSingleRef(r.maSingleRef)
     757             : {
     758         156 : }
     759             : 
     760         488 : ScExternalSingleRefToken::~ScExternalSingleRefToken()
     761             : {
     762         488 : }
     763             : 
     764         180 : sal_uInt16 ScExternalSingleRefToken::GetIndex() const
     765             : {
     766         180 :     return mnFileId;
     767             : }
     768             : 
     769         180 : svl::SharedString ScExternalSingleRefToken::GetString() const
     770             : {
     771         180 :     return maTabName;
     772             : }
     773             : 
     774           8 : const ScSingleRefData* ScExternalSingleRefToken::GetSingleRef() const
     775             : {
     776           8 :     return &maSingleRef;
     777             : }
     778             : 
     779         510 : ScSingleRefData* ScExternalSingleRefToken::GetSingleRef()
     780             : {
     781         510 :     return &maSingleRef;
     782             : }
     783             : 
     784           0 : bool ScExternalSingleRefToken::operator ==( const FormulaToken& r ) const
     785             : {
     786           0 :     if (!FormulaToken::operator==(r))
     787           0 :         return false;
     788             : 
     789           0 :     if (mnFileId != r.GetIndex())
     790           0 :         return false;
     791             : 
     792           0 :     if (maTabName != r.GetString())
     793           0 :         return false;
     794             : 
     795           0 :     return maSingleRef == *r.GetSingleRef();
     796             : }
     797             : 
     798          26 : ScExternalDoubleRefToken::ScExternalDoubleRefToken( sal_uInt16 nFileId, const svl::SharedString& rTabName, const ScComplexRefData& r ) :
     799             :     FormulaToken( svExternalDoubleRef, ocPush),
     800             :     mnFileId(nFileId),
     801             :     maTabName(rTabName),
     802          26 :     maDoubleRef(r)
     803             : {
     804          26 : }
     805             : 
     806           2 : ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r ) :
     807             :     FormulaToken(r),
     808             :     mnFileId(r.mnFileId),
     809             :     maTabName(r.maTabName),
     810           2 :     maDoubleRef(r.maDoubleRef)
     811             : {
     812           2 : }
     813             : 
     814          56 : ScExternalDoubleRefToken::~ScExternalDoubleRefToken()
     815             : {
     816          56 : }
     817             : 
     818          40 : sal_uInt16 ScExternalDoubleRefToken::GetIndex() const
     819             : {
     820          40 :     return mnFileId;
     821             : }
     822             : 
     823          40 : svl::SharedString ScExternalDoubleRefToken::GetString() const
     824             : {
     825          40 :     return maTabName;
     826             : }
     827             : 
     828           0 : const ScSingleRefData* ScExternalDoubleRefToken::GetSingleRef() const
     829             : {
     830           0 :     return &maDoubleRef.Ref1;
     831             : }
     832             : 
     833          12 : ScSingleRefData* ScExternalDoubleRefToken::GetSingleRef()
     834             : {
     835          12 :     return &maDoubleRef.Ref1;
     836             : }
     837             : 
     838           0 : const ScSingleRefData* ScExternalDoubleRefToken::GetSingleRef2() const
     839             : {
     840           0 :     return &maDoubleRef.Ref2;
     841             : }
     842             : 
     843           0 : ScSingleRefData* ScExternalDoubleRefToken::GetSingleRef2()
     844             : {
     845           0 :     return &maDoubleRef.Ref2;
     846             : }
     847             : 
     848           0 : const ScComplexRefData* ScExternalDoubleRefToken::GetDoubleRef() const
     849             : {
     850           0 :     return &maDoubleRef;
     851             : }
     852             : 
     853          46 : ScComplexRefData* ScExternalDoubleRefToken::GetDoubleRef()
     854             : {
     855          46 :     return &maDoubleRef;
     856             : }
     857             : 
     858           0 : bool ScExternalDoubleRefToken::operator ==( const FormulaToken& r ) const
     859             : {
     860           0 :     if (!FormulaToken::operator==(r))
     861           0 :         return false;
     862             : 
     863           0 :     if (mnFileId != r.GetIndex())
     864           0 :         return false;
     865             : 
     866           0 :     if (maTabName != r.GetString())
     867           0 :         return false;
     868             : 
     869           0 :     return maDoubleRef == *r.GetDoubleRef();
     870             : }
     871             : 
     872           0 : ScExternalNameToken::ScExternalNameToken( sal_uInt16 nFileId, const svl::SharedString& rName ) :
     873             :     FormulaToken( svExternalName, ocPush),
     874             :     mnFileId(nFileId),
     875           0 :     maName(rName)
     876             : {
     877           0 : }
     878             : 
     879           0 : ScExternalNameToken::ScExternalNameToken( const ScExternalNameToken& r ) :
     880             :     FormulaToken(r),
     881             :     mnFileId(r.mnFileId),
     882           0 :     maName(r.maName)
     883             : {
     884           0 : }
     885             : 
     886           0 : ScExternalNameToken::~ScExternalNameToken() {}
     887             : 
     888           0 : sal_uInt16 ScExternalNameToken::GetIndex() const
     889             : {
     890           0 :     return mnFileId;
     891             : }
     892             : 
     893           0 : svl::SharedString ScExternalNameToken::GetString() const
     894             : {
     895           0 :     return maName;
     896             : }
     897             : 
     898           0 : bool ScExternalNameToken::operator==( const FormulaToken& r ) const
     899             : {
     900           0 :     if ( !FormulaToken::operator==(r) )
     901           0 :         return false;
     902             : 
     903           0 :     if (mnFileId != r.GetIndex())
     904           0 :         return false;
     905             : 
     906           0 :     return maName.getData() == r.GetString().getData();
     907             : }
     908             : 
     909          14 : ScJumpMatrix* ScJumpMatrixToken::GetJumpMatrix() const  { return pJumpMatrix; }
     910           0 : bool ScJumpMatrixToken::operator==( const FormulaToken& r ) const
     911             : {
     912           0 :     return FormulaToken::operator==( r ) && pJumpMatrix == r.GetJumpMatrix();
     913             : }
     914          18 : ScJumpMatrixToken::~ScJumpMatrixToken()
     915             : {
     916           6 :     delete pJumpMatrix;
     917          12 : }
     918             : 
     919           0 : double          ScEmptyCellToken::GetDouble() const     { return 0.0; }
     920             : 
     921           0 : svl::SharedString ScEmptyCellToken::GetString() const
     922             : {
     923           0 :     return svl::SharedString::getEmptyString();
     924             : }
     925             : 
     926           0 : bool ScEmptyCellToken::operator==( const FormulaToken& r ) const
     927             : {
     928           0 :     return FormulaToken::operator==( r ) &&
     929           0 :         bInherited == static_cast< const ScEmptyCellToken & >(r).IsInherited() &&
     930           0 :         bDisplayedAsString == static_cast< const ScEmptyCellToken & >(r).IsDisplayedAsString();
     931             : }
     932             : 
     933         234 : ScMatrixCellResultToken::ScMatrixCellResultToken( const ScConstMatrixRef& pMat, formula::FormulaToken* pUL ) :
     934         234 :     FormulaToken(formula::svMatrixCell), xMatrix(pMat), xUpperLeft(pUL) {}
     935             : 
     936          28 : ScMatrixCellResultToken::ScMatrixCellResultToken( const ScMatrixCellResultToken& r ) :
     937          28 :     FormulaToken(r), xMatrix(r.xMatrix), xUpperLeft(r.xUpperLeft) {}
     938             : 
     939           0 : double          ScMatrixCellResultToken::GetDouble() const  { return xUpperLeft->GetDouble(); }
     940             : 
     941           0 : svl::SharedString ScMatrixCellResultToken::GetString() const
     942             : {
     943           0 :     return xUpperLeft->GetString();
     944             : }
     945             : 
     946         638 : const ScMatrix* ScMatrixCellResultToken::GetMatrix() const  { return xMatrix.get(); }
     947             : // Non-const GetMatrix() is private and unused but must be implemented to
     948             : // satisfy vtable linkage.
     949           0 : ScMatrix* ScMatrixCellResultToken::GetMatrix()
     950             : {
     951           0 :     return const_cast<ScMatrix*>(xMatrix.get());
     952             : }
     953             : 
     954           0 : bool ScMatrixCellResultToken::operator==( const FormulaToken& r ) const
     955             : {
     956           0 :     return FormulaToken::operator==( r ) &&
     957           0 :         xUpperLeft == static_cast<const ScMatrixCellResultToken &>(r).xUpperLeft &&
     958           0 :         xMatrix == static_cast<const ScMatrixCellResultToken &>(r).xMatrix;
     959             : }
     960             : 
     961           0 : FormulaToken* ScMatrixCellResultToken::Clone() const
     962             : {
     963           0 :     return new ScMatrixCellResultToken(*this);
     964             : }
     965             : 
     966          48 : void ScMatrixCellResultToken::Assign( const ScMatrixCellResultToken & r )
     967             : {
     968          48 :     xMatrix = r.xMatrix;
     969          48 :     xUpperLeft = r.xUpperLeft;
     970          48 : }
     971             : 
     972         140 : ScMatrixFormulaCellToken::ScMatrixFormulaCellToken(
     973             :     SCCOL nC, SCROW nR, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL ) :
     974         140 :     ScMatrixCellResultToken(pMat, pUL), nRows(nR), nCols(nC) {}
     975             : 
     976          94 : ScMatrixFormulaCellToken::ScMatrixFormulaCellToken( SCCOL nC, SCROW nR ) :
     977          94 :     ScMatrixCellResultToken(NULL, NULL), nRows(nR), nCols(nC) {}
     978             : 
     979          28 : ScMatrixFormulaCellToken::ScMatrixFormulaCellToken( const ScMatrixFormulaCellToken& r ) :
     980          28 :     ScMatrixCellResultToken(r), nRows(r.nRows), nCols(r.nCols)
     981             : {
     982             :     // xUpperLeft is modifiable through
     983             :     // SetUpperLeftDouble(), so clone it.
     984          28 :     if (xUpperLeft)
     985          28 :         xUpperLeft = xUpperLeft->Clone();
     986          28 : }
     987             : 
     988           0 : bool ScMatrixFormulaCellToken::operator==( const FormulaToken& r ) const
     989             : {
     990           0 :     const ScMatrixFormulaCellToken* p = dynamic_cast<const ScMatrixFormulaCellToken*>(&r);
     991           0 :     return p && ScMatrixCellResultToken::operator==( r ) &&
     992           0 :         nCols == p->nCols && nRows == p->nRows;
     993             : }
     994             : 
     995          48 : void ScMatrixFormulaCellToken::Assign( const ScMatrixCellResultToken & r )
     996             : {
     997          48 :     ScMatrixCellResultToken::Assign( r);
     998          48 : }
     999             : 
    1000          70 : void ScMatrixFormulaCellToken::Assign( const formula::FormulaToken& r )
    1001             : {
    1002          70 :     if (this == &r)
    1003          70 :         return;
    1004          70 :     const ScMatrixCellResultToken* p = dynamic_cast<const ScMatrixCellResultToken*>(&r);
    1005          70 :     if (p)
    1006           0 :         ScMatrixCellResultToken::Assign( *p);
    1007             :     else
    1008             :     {
    1009             :         OSL_ENSURE( r.GetType() != svMatrix, "ScMatrixFormulaCellToken::operator=: assigning ScMatrixToken to ScMatrixFormulaCellToken is not proper, use ScMatrixCellResultToken instead");
    1010          70 :         if (r.GetType() == svMatrix)
    1011             :         {
    1012           0 :             xUpperLeft = NULL;
    1013           0 :             xMatrix = r.GetMatrix();
    1014             :         }
    1015             :         else
    1016             :         {
    1017          70 :             xUpperLeft = &r;
    1018          70 :             xMatrix = NULL;
    1019             :         }
    1020             :     }
    1021             : }
    1022             : 
    1023          32 : void ScMatrixFormulaCellToken::SetUpperLeftDouble( double f )
    1024             : {
    1025          32 :     switch (GetUpperLeftType())
    1026             :     {
    1027             :         case svDouble:
    1028          10 :             const_cast<FormulaToken*>(xUpperLeft.get())->GetDoubleAsReference() = f;
    1029          10 :             break;
    1030             :         case svString:
    1031           2 :             xUpperLeft = new FormulaDoubleToken( f);
    1032           2 :             break;
    1033             :         case svUnknown:
    1034          20 :             if (!xUpperLeft)
    1035             :             {
    1036          20 :                 xUpperLeft = new FormulaDoubleToken( f);
    1037          20 :                 break;
    1038             :             }
    1039             :             // fall thru
    1040             :         default:
    1041             :             {
    1042             :                 OSL_FAIL("ScMatrixFormulaCellToken::SetUpperLeftDouble: not modifying unhandled token type");
    1043             :             }
    1044             :     }
    1045          32 : }
    1046             : 
    1047           0 : void ScMatrixFormulaCellToken::ResetResult()
    1048             : {
    1049           0 :     xMatrix = NULL;
    1050           0 :     xUpperLeft = NULL;
    1051           0 : }
    1052             : 
    1053         244 : ScHybridCellToken::ScHybridCellToken(
    1054             :     double f, const svl::SharedString & rStr, const OUString & rFormula ) :
    1055             :         FormulaToken( formula::svHybridCell ),
    1056             :         mfDouble( f ), maString( rStr ),
    1057         244 :         maFormula( rFormula )
    1058             : {
    1059         244 : }
    1060             : 
    1061           0 : double ScHybridCellToken::GetDouble() const { return mfDouble; }
    1062             : 
    1063         214 : svl::SharedString ScHybridCellToken::GetString() const
    1064             : {
    1065         214 :     return maString;
    1066             : }
    1067             : 
    1068           0 : bool ScHybridCellToken::operator==( const FormulaToken& r ) const
    1069             : {
    1070           0 :     return FormulaToken::operator==( r ) &&
    1071           0 :         mfDouble == r.GetDouble() && maString == r.GetString() &&
    1072           0 :         maFormula == static_cast<const ScHybridCellToken &>(r).GetFormula();
    1073             : }
    1074             : 
    1075         216 : bool ScTokenArray::AddFormulaToken(
    1076             :     const css::sheet::FormulaToken& rToken, svl::SharedStringPool& rSPool, formula::ExternalReferenceHelper* pExtRef)
    1077             : {
    1078         216 :     bool bError = FormulaTokenArray::AddFormulaToken(rToken, rSPool, pExtRef);
    1079         216 :     if ( bError )
    1080             :     {
    1081         182 :         bError = false;
    1082         182 :         const OpCode eOpCode = static_cast<OpCode>(rToken.OpCode);      //! assuming equal values for the moment
    1083             : 
    1084         182 :         const uno::TypeClass eClass = rToken.Data.getValueTypeClass();
    1085         182 :         switch ( eClass )
    1086             :         {
    1087             :             case uno::TypeClass_STRUCT:
    1088             :                 {
    1089         180 :                     uno::Type aType = rToken.Data.getValueType();
    1090         180 :                     if ( aType.equals( cppu::UnoType<sheet::SingleReference>::get() ) )
    1091             :                     {
    1092             :                         ScSingleRefData aSingleRef;
    1093          86 :                         sheet::SingleReference aApiRef;
    1094          86 :                         rToken.Data >>= aApiRef;
    1095          86 :                         lcl_SingleRefToCalc( aSingleRef, aApiRef );
    1096          86 :                         if ( eOpCode == ocPush )
    1097          86 :                             AddSingleReference( aSingleRef );
    1098           0 :                         else if ( eOpCode == ocColRowName )
    1099           0 :                             AddColRowName( aSingleRef );
    1100             :                         else
    1101           0 :                             bError = true;
    1102             :                     }
    1103          94 :                     else if ( aType.equals( cppu::UnoType<sheet::ComplexReference>::get() ) )
    1104             :                     {
    1105             :                         ScComplexRefData aComplRef;
    1106          92 :                         sheet::ComplexReference aApiRef;
    1107          92 :                         rToken.Data >>= aApiRef;
    1108          92 :                         lcl_SingleRefToCalc( aComplRef.Ref1, aApiRef.Reference1 );
    1109          92 :                         lcl_SingleRefToCalc( aComplRef.Ref2, aApiRef.Reference2 );
    1110             : 
    1111          92 :                         if ( eOpCode == ocPush )
    1112          92 :                             AddDoubleReference( aComplRef );
    1113             :                         else
    1114           0 :                             bError = true;
    1115             :                     }
    1116           2 :                     else if ( aType.equals( cppu::UnoType<sheet::NameToken>::get() ) )
    1117             :                     {
    1118           2 :                         sheet::NameToken aTokenData;
    1119           2 :                         rToken.Data >>= aTokenData;
    1120           2 :                         if ( eOpCode == ocName )
    1121           2 :                             AddRangeName(aTokenData.Index, aTokenData.Global);
    1122           0 :                         else if (eOpCode == ocDBArea)
    1123           0 :                             AddDBRange(aTokenData.Index);
    1124             :                         else
    1125           0 :                             bError = true;
    1126             :                     }
    1127           0 :                     else if ( aType.equals( cppu::UnoType<sheet::ExternalReference>::get() ) )
    1128             :                     {
    1129           0 :                         sheet::ExternalReference aApiExtRef;
    1130           0 :                         if( (eOpCode == ocPush) && (rToken.Data >>= aApiExtRef) && (0 <= aApiExtRef.Index) && (aApiExtRef.Index <= SAL_MAX_UINT16) )
    1131             :                         {
    1132           0 :                             sal_uInt16 nFileId = static_cast< sal_uInt16 >( aApiExtRef.Index );
    1133           0 :                             sheet::SingleReference aApiSRef;
    1134           0 :                             sheet::ComplexReference aApiCRef;
    1135           0 :                             OUString aName;
    1136           0 :                             if( aApiExtRef.Reference >>= aApiSRef )
    1137             :                             {
    1138             :                                 // try to resolve cache index to sheet name
    1139           0 :                                 size_t nCacheId = static_cast< size_t >( aApiSRef.Sheet );
    1140           0 :                                 OUString aTabName = pExtRef->getCacheTableName( nFileId, nCacheId );
    1141           0 :                                 if( !aTabName.isEmpty() )
    1142             :                                 {
    1143             :                                     ScSingleRefData aSingleRef;
    1144             :                                     // convert column/row settings, set sheet index to absolute
    1145           0 :                                     lcl_ExternalRefToCalc( aSingleRef, aApiSRef );
    1146           0 :                                     AddExternalSingleReference( nFileId, aTabName, aSingleRef );
    1147             :                                 }
    1148             :                                 else
    1149           0 :                                     bError = true;
    1150             :                             }
    1151           0 :                             else if( aApiExtRef.Reference >>= aApiCRef )
    1152             :                             {
    1153             :                                 // try to resolve cache index to sheet name.
    1154           0 :                                 size_t nCacheId = static_cast< size_t >( aApiCRef.Reference1.Sheet );
    1155           0 :                                 OUString aTabName = pExtRef->getCacheTableName( nFileId, nCacheId );
    1156           0 :                                 if( !aTabName.isEmpty() )
    1157             :                                 {
    1158             :                                     ScComplexRefData aComplRef;
    1159             :                                     // convert column/row settings, set sheet index to absolute
    1160           0 :                                     lcl_ExternalRefToCalc( aComplRef.Ref1, aApiCRef.Reference1 );
    1161           0 :                                     lcl_ExternalRefToCalc( aComplRef.Ref2, aApiCRef.Reference2 );
    1162             :                                     // NOTE: This assumes that cached sheets are in consecutive order!
    1163             :                                     aComplRef.Ref2.SetAbsTab(
    1164           0 :                                         aComplRef.Ref1.Tab() + static_cast<SCTAB>(aApiCRef.Reference2.Sheet - aApiCRef.Reference1.Sheet));
    1165           0 :                                     AddExternalDoubleReference( nFileId, aTabName, aComplRef );
    1166             :                                 }
    1167             :                                 else
    1168           0 :                                     bError = true;
    1169             :                             }
    1170           0 :                             else if( aApiExtRef.Reference >>= aName )
    1171             :                             {
    1172           0 :                                 if( !aName.isEmpty() )
    1173           0 :                                     AddExternalName( nFileId, aName );
    1174             :                                 else
    1175           0 :                                     bError = true;
    1176             :                             }
    1177             :                             else
    1178           0 :                                 bError = true;
    1179             :                         }
    1180             :                         else
    1181           0 :                             bError = true;
    1182             :                     }
    1183             :                     else
    1184           0 :                         bError = true;      // unknown struct
    1185             :                 }
    1186         180 :                 break;
    1187             :             case uno::TypeClass_SEQUENCE:
    1188             :                 {
    1189           2 :                     if ( eOpCode != ocPush )
    1190           0 :                         bError = true;      // not an inline array
    1191           4 :                     else if (!rToken.Data.getValueType().equals( getCppuType(
    1192           4 :                                     (uno::Sequence< uno::Sequence< uno::Any > > *)0)))
    1193           0 :                         bError = true;      // unexpected sequence type
    1194             :                     else
    1195             :                     {
    1196           2 :                         ScMatrixRef xMat = ScSequenceToMatrix::CreateMixedMatrix( rToken.Data);
    1197           2 :                         if (xMat)
    1198           2 :                             AddMatrix( xMat);
    1199             :                         else
    1200           0 :                             bError = true;
    1201             :                     }
    1202             :                 }
    1203           2 :                 break;
    1204             :             default:
    1205           0 :                 bError = true;
    1206             :         }
    1207             :     }
    1208         216 :     return bError;
    1209             : }
    1210             : 
    1211      102928 : void ScTokenArray::CheckToken( const FormulaToken& r )
    1212             : {
    1213      102928 :     if (meVectorState == FormulaVectorDisabled)
    1214             :         // It's already disabled.  No more checking needed.
    1215       20602 :         return;
    1216             : 
    1217       82326 :     OpCode eOp = r.GetOpCode();
    1218             : 
    1219       82326 :     if (SC_OPCODE_START_FUNCTION <= eOp && eOp < SC_OPCODE_STOP_FUNCTION)
    1220             :     {
    1221             :         // We support vectorization for the following opcodes.
    1222        9830 :         switch (eOp)
    1223             :         {
    1224             :             case ocIf:
    1225             :             case ocIfError:
    1226             :             case ocIfNA:
    1227             :             case ocChose:
    1228             :                 // Jump commands are now supported.
    1229           0 :             break;
    1230             :             case ocAverage:
    1231             :             case ocMin:
    1232             :             case ocMinA:
    1233             :             case ocMax:
    1234             :             case ocMaxA:
    1235             :             case ocSum:
    1236             :             case ocSumIfs:
    1237             :             case ocSumProduct:
    1238             :             case ocCount:
    1239             :             case ocCount2:
    1240             :             case ocVLookup:
    1241             :             case ocLIA:
    1242             :             case ocIRR:
    1243             :             case ocMIRR:
    1244             :             case ocRMZ:
    1245             :             case ocZins:
    1246             :             case ocZGZ:
    1247             :             case ocKapz:
    1248             :             case ocFisher:
    1249             :             case ocFisherInv:
    1250             :             case ocGamma:
    1251             :             case ocGammaLn:
    1252             :             case ocNotAvail:
    1253             :             case ocGauss:
    1254             :             case ocGeoMean:
    1255             :             case ocHarMean:
    1256             :             case ocDIA:
    1257             :             case ocCorrel:
    1258             :             case ocNegBinomVert:
    1259             :             case ocPearson:
    1260             :             case ocRSQ:
    1261             :             case ocCos:
    1262             :             case ocCosecant:
    1263             :             case ocCosecantHyp:
    1264             :             case ocISPMT:
    1265             :             case ocLaufz:
    1266             :             case ocSinHyp:
    1267             :             case ocAbs:
    1268             :             case ocBW:
    1269             :             case ocSin:
    1270             :             case ocTan:
    1271             :             case ocTanHyp:
    1272             :             case ocStandard:
    1273             :             case ocWeibull:
    1274             :             case ocMedian:
    1275             :             case ocGDA:
    1276             :             case ocZW:
    1277             :             case ocVBD:
    1278             :             case ocKurt:
    1279             :             case ocZZR:
    1280             :             case ocNormDist:
    1281             :             case ocArcCos:
    1282             :             case ocSqrt:
    1283             :             case ocArcCosHyp:
    1284             :             case ocNPV:
    1285             :             case ocStdNormDist:
    1286             :             case ocNormInv:
    1287             :             case ocSNormInv:
    1288             :             case ocVariationen:
    1289             :             case ocVariationen2:
    1290             :             case ocPhi:
    1291             :             case ocZinsZ:
    1292             :             case ocConfidence:
    1293             :             case ocIntercept:
    1294             :             case ocGDA2:
    1295             :             case ocLogInv:
    1296             :             case ocArcCot:
    1297             :             case ocCosHyp:
    1298             :             case ocKritBinom:
    1299             :             case ocArcCotHyp:
    1300             :             case ocArcSin:
    1301             :             case ocArcSinHyp:
    1302             :             case ocArcTan:
    1303             :             case ocArcTanHyp:
    1304             :             case ocBitAnd:
    1305             :             case ocForecast:
    1306             :             case ocLogNormDist:
    1307             :             case ocGammaDist:
    1308             :             case ocLn:
    1309             :             case ocRound:
    1310             :             case ocCot:
    1311             :             case ocCotHyp:
    1312             :             case ocFDist:
    1313             :             case ocVar:
    1314             :             case ocChiDist:
    1315             :             case ocPower:
    1316             :             case ocOdd:
    1317             :             case ocChiSqDist:
    1318             :             case ocChiSqInv:
    1319             :             case ocGammaInv:
    1320             :             case ocFloor:
    1321             :             case ocFInv:
    1322             :             case ocFTest:
    1323             :             case ocB:
    1324             :             case ocBetaDist:
    1325             :             case ocExp:
    1326             :             case ocLog10:
    1327             :             case ocExpDist:
    1328             :             case ocAverageIfs:
    1329             :             case ocCountIfs:
    1330             :             case ocKombin2:
    1331             :             case ocEven:
    1332             :             case ocLog:
    1333             :             case ocMod:
    1334             :             case ocTrunc:
    1335             :             case ocSchiefe:
    1336             :             case ocArcTan2:
    1337             :             case ocBitOr:
    1338             :             case ocBitLshift:
    1339             :             case ocBitRshift:
    1340             :             case ocBitXor:
    1341             :             case ocChiInv:
    1342             :             case ocPoissonDist:
    1343             :             case ocSumSQ:
    1344             :             case ocSkewp:
    1345             :             case ocBinomDist:
    1346             :             case ocVarP:
    1347             :             case ocCeil:
    1348             :             case ocKombin:
    1349             :             case ocDevSq:
    1350             :             case ocStDev:
    1351             :             case ocSlope:
    1352             :             case ocSTEYX:
    1353             :             case ocZTest:
    1354             :             case ocPi:
    1355             :             case ocRandom:
    1356             :             case ocProduct:
    1357             :             case ocHypGeomDist:
    1358             :             case ocSumX2MY2:
    1359             :             case ocSumX2DY2:
    1360             :             case ocBetaInv:
    1361             :             case ocTTest:
    1362             :             case ocTDist:
    1363             :             case ocTInv:
    1364             :             case ocSumXMY2:
    1365             :             case ocStDevP:
    1366             :             case ocCovar:
    1367             :             case ocAnd:
    1368             :             case ocOr:
    1369             :             case ocNot:
    1370             :             case ocXor:
    1371             :             case ocDBMax:
    1372             :             case ocDBMin:
    1373             :             case ocDBProduct:
    1374             :             case ocDBAverage:
    1375             :             case ocDBStdDev:
    1376             :             case ocDBStdDevP:
    1377             :             case ocDBSum:
    1378             :             case ocDBVar:
    1379             :             case ocDBVarP:
    1380             :             case ocAverageIf:
    1381             :             case ocDBCount:
    1382             :             case ocDBCount2:
    1383             :             case ocDeg:
    1384             :             case ocRoundUp:
    1385             :             case ocRoundDown:
    1386             :             case ocInt:
    1387             :             case ocRad:
    1388             :             case ocCountIf:
    1389             :             case ocIsEven:
    1390             :             case ocIsOdd:
    1391             :             case ocFact:
    1392             :             case ocAverageA:
    1393             :             case ocVarA:
    1394             :             case ocVarPA:
    1395             :             case ocStDevA:
    1396             :             case ocStDevPA:
    1397             :             case ocSecant:
    1398             :             case ocSecantHyp:
    1399             :             case ocSumIf:
    1400             :             case ocNegSub:
    1401             :             case ocAveDev:
    1402             :             // Don't change the state.
    1403        7346 :             break;
    1404             :             default:
    1405        2484 :                 meVectorState = FormulaVectorDisabled;
    1406             :         }
    1407        9830 :         return;
    1408             :     }
    1409             : 
    1410       72496 :     if (eOp == ocPush)
    1411             :     {
    1412             :         // This is a stack variable.  See if this is a reference.
    1413             : 
    1414       33172 :         switch (r.GetType())
    1415             :         {
    1416             :             case svByte:
    1417             :             case svDouble:
    1418             :             case svString:
    1419             :                 // Don't change the state.
    1420       11116 :             break;
    1421             :             case svSingleRef:
    1422             :             case svDoubleRef:
    1423             :                 // Depends on the reference state.
    1424       21846 :                 meVectorState = FormulaVectorCheckReference;
    1425       21846 :             break;
    1426             :             case svError:
    1427             :             case svEmptyCell:
    1428             :             case svExternal:
    1429             :             case svExternalDoubleRef:
    1430             :             case svExternalName:
    1431             :             case svExternalSingleRef:
    1432             :             case svFAP:
    1433             :             case svHybridCell:
    1434             :             case svHybridValueCell:
    1435             :             case svIndex:
    1436             :             case svJump:
    1437             :             case svJumpMatrix:
    1438             :             case svMatrix:
    1439             :             case svMatrixCell:
    1440             :             case svMissing:
    1441             :             case svRefList:
    1442             :             case svSep:
    1443             :             case svSubroutine:
    1444             :             case svUnknown:
    1445             :                 // We don't support vectorization on these.
    1446         210 :                 meVectorState = FormulaVectorDisabled;
    1447             :             default:
    1448             :                 ;
    1449             :         }
    1450             :     }
    1451             : }
    1452             : 
    1453        1752 : bool ScTokenArray::ImplGetReference( ScRange& rRange, const ScAddress& rPos, bool bValidOnly ) const
    1454             : {
    1455        1752 :     bool bIs = false;
    1456        1752 :     if ( pCode && nLen == 1 )
    1457             :     {
    1458        1592 :         const FormulaToken* pToken = pCode[0];
    1459        1592 :         if ( pToken )
    1460             :         {
    1461        1592 :             if ( pToken->GetType() == svSingleRef )
    1462             :             {
    1463        1218 :                 const ScSingleRefData& rRef = *static_cast<const ScSingleRefToken*>(pToken)->GetSingleRef();
    1464        1218 :                 rRange.aStart = rRange.aEnd = rRef.toAbs(rPos);
    1465        1218 :                 bIs = !bValidOnly || ValidAddress(rRange.aStart);
    1466             :             }
    1467         374 :             else if ( pToken->GetType() == svDoubleRef )
    1468             :             {
    1469         354 :                 const ScComplexRefData& rCompl = *static_cast<const ScDoubleRefToken*>(pToken)->GetDoubleRef();
    1470         354 :                 const ScSingleRefData& rRef1 = rCompl.Ref1;
    1471         354 :                 const ScSingleRefData& rRef2 = rCompl.Ref2;
    1472         354 :                 rRange.aStart = rRef1.toAbs(rPos);
    1473         354 :                 rRange.aEnd   = rRef2.toAbs(rPos);
    1474         354 :                 bIs = !bValidOnly || ValidRange(rRange);
    1475             :             }
    1476             :         }
    1477             :     }
    1478        1752 :     return bIs;
    1479             : }
    1480             : 
    1481             : namespace {
    1482             : 
    1483             : // we want to compare for similar not identical formulae
    1484             : // so we can't use actual row & column indices.
    1485       46874 : size_t HashSingleRef( const ScSingleRefData& rRef )
    1486             : {
    1487       46874 :     size_t nVal = 0;
    1488             : 
    1489       46874 :     nVal += size_t(rRef.IsColRel());
    1490       46874 :     nVal += (size_t(rRef.IsRowRel()) << 1);
    1491       46874 :     nVal += (size_t(rRef.IsTabRel()) << 2);
    1492             : 
    1493       46874 :     return nVal;
    1494             : }
    1495             : 
    1496             : }
    1497             : 
    1498       25966 : void ScTokenArray::GenHash()
    1499             : {
    1500             :     static OUStringHash aHasher;
    1501             : 
    1502       25966 :     size_t nHash = 1;
    1503             :     OpCode eOp;
    1504             :     StackVar eType;
    1505             :     const formula::FormulaToken* p;
    1506       25966 :     sal_uInt16 n = std::min<sal_uInt16>(nLen, 20);
    1507      160854 :     for (sal_uInt16 i = 0; i < n; ++i)
    1508             :     {
    1509      134888 :         p = pCode[i];
    1510      134888 :         eOp = p->GetOpCode();
    1511      134888 :         if (eOp == ocPush)
    1512             :         {
    1513             :             // This is stack variable. Do additional differentiation.
    1514       53356 :             eType = p->GetType();
    1515       53356 :             switch (eType)
    1516             :             {
    1517             :                 case svByte:
    1518             :                 {
    1519             :                     // Constant value.
    1520           0 :                     sal_uInt8 nVal = p->GetByte();
    1521           0 :                     nHash += static_cast<size_t>(nVal);
    1522             :                 }
    1523           0 :                 break;
    1524             :                 case svDouble:
    1525             :                 {
    1526             :                     // Constant value.
    1527       12446 :                     double fVal = p->GetDouble();
    1528       12446 :                     nHash += static_cast<size_t>(fVal);
    1529             :                 }
    1530       12446 :                 break;
    1531             :                 case svString:
    1532             :                 {
    1533             :                     // Constant string.
    1534        4128 :                     OUString aStr = p->GetString().getString();
    1535        4128 :                     nHash += aHasher(aStr);
    1536             :                 }
    1537        4128 :                 break;
    1538             :                 case svSingleRef:
    1539             :                 {
    1540       26290 :                     size_t nVal = HashSingleRef(*p->GetSingleRef());
    1541       26290 :                     nHash += nVal;
    1542             :                 }
    1543       26290 :                 break;
    1544             :                 case svDoubleRef:
    1545             :                 {
    1546       10292 :                     const ScComplexRefData& rRef = *p->GetDoubleRef();
    1547       10292 :                     size_t nVal1 = HashSingleRef(rRef.Ref1);
    1548       10292 :                     size_t nVal2 = HashSingleRef(rRef.Ref2);
    1549       10292 :                     nHash += nVal1;
    1550       10292 :                     nHash += nVal2;
    1551             :                 }
    1552       10292 :                 break;
    1553             :                 default:
    1554             :                     // Use the opcode value in all the other cases.
    1555         200 :                     nHash += static_cast<size_t>(eOp);
    1556             :             }
    1557             :         }
    1558             :         else
    1559             :             // Use the opcode value in all the other cases.
    1560       81532 :             nHash += static_cast<size_t>(eOp);
    1561             : 
    1562      134888 :         nHash = (nHash << 4) - nHash;
    1563             :     }
    1564             : 
    1565       25966 :     mnHashValue = nHash;
    1566       25966 : }
    1567             : 
    1568          10 : bool ScTokenArray::IsInvariant() const
    1569             : {
    1570          10 :     FormulaToken** p = pCode;
    1571          10 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    1572          26 :     for (; p != pEnd; ++p)
    1573             :     {
    1574          26 :         switch ((*p)->GetType())
    1575             :         {
    1576             :             case svSingleRef:
    1577             :             case svExternalSingleRef:
    1578             :             {
    1579           2 :                 const ScSingleRefData& rRef = *(*p)->GetSingleRef();
    1580           2 :                 if (rRef.IsRowRel())
    1581           2 :                     return false;
    1582             :             }
    1583           0 :             break;
    1584             :             case svDoubleRef:
    1585             :             case svExternalDoubleRef:
    1586             :             {
    1587           0 :                 const ScComplexRefData& rRef = *(*p)->GetDoubleRef();
    1588           0 :                 if (rRef.Ref1.IsRowRel() || rRef.Ref2.IsRowRel())
    1589           0 :                     return false;
    1590             :             }
    1591           0 :             break;
    1592             :             case svIndex:
    1593           8 :                 return false;
    1594             :             default:
    1595             :                 ;
    1596             :         }
    1597             :     }
    1598             : 
    1599           0 :     return true;
    1600             : }
    1601             : 
    1602         800 : bool ScTokenArray::IsReference( ScRange& rRange, const ScAddress& rPos ) const
    1603             : {
    1604         800 :     return ImplGetReference(rRange, rPos, false);
    1605             : }
    1606             : 
    1607         952 : bool ScTokenArray::IsValidReference( ScRange& rRange, const ScAddress& rPos ) const
    1608             : {
    1609         952 :     return ImplGetReference(rRange, rPos, true);
    1610             : }
    1611             : 
    1612       21070 : ScTokenArray::ScTokenArray() :
    1613             :     FormulaTokenArray(),
    1614             :     mnHashValue(0),
    1615       21070 :     meVectorState(FormulaVectorEnabled)
    1616             : {
    1617       21070 : }
    1618             : 
    1619       21688 : ScTokenArray::ScTokenArray( const ScTokenArray& rArr ) :
    1620             :     FormulaTokenArray(rArr),
    1621             :     mnHashValue(rArr.mnHashValue),
    1622       21688 :     meVectorState(rArr.meVectorState)
    1623             : {
    1624       21688 : }
    1625             : 
    1626       73872 : ScTokenArray::~ScTokenArray()
    1627             : {
    1628       73872 : }
    1629             : 
    1630           0 : ScTokenArray& ScTokenArray::operator=( const ScTokenArray& rArr )
    1631             : {
    1632           0 :     Clear();
    1633           0 :     Assign( rArr );
    1634           0 :     return *this;
    1635             : }
    1636             : 
    1637        6812 : ScTokenArray* ScTokenArray::Clone() const
    1638             : {
    1639        6812 :     ScTokenArray* p = new ScTokenArray();
    1640        6812 :     p->nLen = nLen;
    1641        6812 :     p->nRPN = nRPN;
    1642        6812 :     p->nRefs = nRefs;
    1643        6812 :     p->nMode = nMode;
    1644        6812 :     p->nError = nError;
    1645        6812 :     p->bHyperLink = bHyperLink;
    1646        6812 :     p->mnHashValue = mnHashValue;
    1647        6812 :     p->meVectorState = meVectorState;
    1648             : 
    1649             :     FormulaToken** pp;
    1650        6812 :     if( nLen )
    1651             :     {
    1652        6742 :         pp = p->pCode = new FormulaToken*[ nLen ];
    1653        6742 :         memcpy( pp, pCode, nLen * sizeof( formula::FormulaToken* ) );
    1654       34922 :         for( sal_uInt16 i = 0; i < nLen; i++, pp++ )
    1655             :         {
    1656       28180 :             *pp = (*pp)->Clone();
    1657       28180 :             (*pp)->IncRef();
    1658             :         }
    1659             :     }
    1660        6812 :     if( nRPN )
    1661             :     {
    1662        2816 :         pp = p->pRPN = new FormulaToken*[ nRPN ];
    1663        2816 :         memcpy( pp, pRPN, nRPN * sizeof( formula::FormulaToken* ) );
    1664       11096 :         for( sal_uInt16 i = 0; i < nRPN; i++, pp++ )
    1665             :         {
    1666        8280 :             FormulaToken* t = *pp;
    1667        8280 :             if( t->GetRef() > 1 )
    1668             :             {
    1669        8166 :                 FormulaToken** p2 = pCode;
    1670        8166 :                 sal_uInt16 nIdx = 0xFFFF;
    1671       32644 :                 for( sal_uInt16 j = 0; j < nLen; j++, p2++ )
    1672             :                 {
    1673       32644 :                     if( *p2 == t )
    1674             :                     {
    1675        8166 :                         nIdx = j; break;
    1676             :                     }
    1677             :                 }
    1678        8166 :                 if( nIdx == 0xFFFF )
    1679           0 :                     *pp = t->Clone();
    1680             :                 else
    1681        8166 :                     *pp = p->pCode[ nIdx ];
    1682             :             }
    1683             :             else
    1684         114 :                 *pp = t->Clone();
    1685        8280 :             (*pp)->IncRef();
    1686             :         }
    1687             :     }
    1688        6812 :     return p;
    1689             : }
    1690             : 
    1691       42310 : FormulaToken* ScTokenArray::AddRawToken( const ScRawToken& r )
    1692             : {
    1693       42310 :     return Add( r.CreateToken() );
    1694             : }
    1695             : 
    1696             : // Utility function to ensure that there is strict alternation of values and
    1697             : // separators.
    1698             : static bool
    1699         304 : checkArraySep( bool & bPrevWasSep, bool bNewVal )
    1700             : {
    1701         304 :     bool bResult = (bPrevWasSep == bNewVal);
    1702         304 :     bPrevWasSep = bNewVal;
    1703         304 :     return bResult;
    1704             : }
    1705             : 
    1706          36 : FormulaToken* ScTokenArray::MergeArray( )
    1707             : {
    1708          36 :     int nCol = -1, nRow = 0;
    1709          36 :     int i, nPrevRowSep = -1, nStart = 0;
    1710          36 :     bool bPrevWasSep = false; // top of stack is ocArrayClose
    1711             :     FormulaToken* t;
    1712          36 :     bool bNumeric = false;  // numeric value encountered in current element
    1713             : 
    1714             :     // (1) Iterate from the end to the start to find matrix dims
    1715             :     // and do basic validation.
    1716         378 :     for ( i = nLen ; i-- > nStart ; )
    1717             :     {
    1718         306 :         t = pCode[i];
    1719         306 :         switch ( t->GetOpCode() )
    1720             :         {
    1721             :             case ocPush :
    1722         134 :                 if( checkArraySep( bPrevWasSep, false ) )
    1723             :                 {
    1724           0 :                     return NULL;
    1725             :                 }
    1726             : 
    1727             :                 // no references or nested arrays
    1728         134 :                 if ( t->GetType() != svDouble  && t->GetType() != svString )
    1729             :                 {
    1730           0 :                     return NULL;
    1731             :                 }
    1732         134 :                 bNumeric = (t->GetType() == svDouble);
    1733         134 :             break;
    1734             : 
    1735             :             case ocMissing :
    1736             :             case ocTrue :
    1737             :             case ocFalse :
    1738           0 :                 if( checkArraySep( bPrevWasSep, false ) )
    1739             :                 {
    1740           0 :                     return NULL;
    1741             :                 }
    1742           0 :                 bNumeric = false;
    1743           0 :             break;
    1744             : 
    1745             :             case ocArrayColSep :
    1746             :             case ocSep :
    1747          36 :                 if( checkArraySep( bPrevWasSep, true ) )
    1748             :                 {
    1749           0 :                     return NULL;
    1750             :                 }
    1751          36 :                 bNumeric = false;
    1752          36 :             break;
    1753             : 
    1754             :             case ocArrayClose :
    1755             :                 // not possible with the , but check just in case
    1756             :                 // something changes in the future
    1757          36 :                 if( i != (nLen-1))
    1758             :                 {
    1759           0 :                     return NULL;
    1760             :                 }
    1761             : 
    1762          36 :                 if( checkArraySep( bPrevWasSep, true ) )
    1763             :                 {
    1764           0 :                     return NULL;
    1765             :                 }
    1766             : 
    1767          36 :                 nPrevRowSep = i;
    1768          36 :                 bNumeric = false;
    1769          36 :             break;
    1770             : 
    1771             :             case ocArrayOpen :
    1772          36 :                 nStart = i; // stop iteration
    1773             :                 // fall through to ArrayRowSep
    1774             : 
    1775             :             case ocArrayRowSep :
    1776          98 :                 if( checkArraySep( bPrevWasSep, true ) )
    1777             :                 {
    1778           0 :                     return NULL;
    1779             :                 }
    1780             : 
    1781         196 :                 if( nPrevRowSep < 0 ||              // missing ocArrayClose
    1782          98 :                     ((nPrevRowSep - i) % 2) == 1)   // no complex elements
    1783             :                 {
    1784           0 :                     return NULL;
    1785             :                 }
    1786             : 
    1787          98 :                 if( nCol < 0 )
    1788             :                 {
    1789          36 :                     nCol = (nPrevRowSep - i) / 2;
    1790             :                 }
    1791          62 :                 else if( (nPrevRowSep - i)/2 != nCol)   // irregular array
    1792             :                 {
    1793           0 :                     return NULL;
    1794             :                 }
    1795             : 
    1796          98 :                 nPrevRowSep = i;
    1797          98 :                 nRow++;
    1798          98 :                 bNumeric = false;
    1799          98 :             break;
    1800             : 
    1801             :             case ocNegSub :
    1802             :             case ocAdd :
    1803             :                 // negation or unary plus must precede numeric value
    1804           2 :                 if( !bNumeric )
    1805             :                 {
    1806           0 :                     return NULL;
    1807             :                 }
    1808           2 :                 --nPrevRowSep;      // shorten this row by 1
    1809           2 :                 bNumeric = false;   // one level only, no --42
    1810           2 :             break;
    1811             : 
    1812             :             case ocSpaces :
    1813             :                 // ignore spaces
    1814           0 :                 --nPrevRowSep;      // shorten this row by 1
    1815           0 :             break;
    1816             : 
    1817             :             default :
    1818             :                 // no functions or operators
    1819           0 :                 return NULL;
    1820             :         }
    1821             :     }
    1822          36 :     if( nCol <= 0 || nRow <= 0 )
    1823           0 :         return NULL;
    1824             : 
    1825          36 :     int nSign = 1;
    1826          36 :     ScMatrix* pArray = new ScMatrix(nCol, nRow, 0.0);
    1827         342 :     for ( i = nStart, nCol = 0, nRow = 0 ; i < nLen ; i++ )
    1828             :     {
    1829         306 :         t = pCode[i];
    1830             : 
    1831         306 :         switch ( t->GetOpCode() )
    1832             :         {
    1833             :             case ocPush :
    1834         134 :                 if ( t->GetType() == svDouble )
    1835             :                 {
    1836          56 :                     pArray->PutDouble( t->GetDouble() * nSign, nCol, nRow );
    1837          56 :                     nSign = 1;
    1838             :                 }
    1839          78 :                 else if ( t->GetType() == svString )
    1840             :                 {
    1841          78 :                     pArray->PutString(svl::SharedString(t->GetString()), nCol, nRow);
    1842             :                 }
    1843         134 :             break;
    1844             : 
    1845             :             case ocMissing :
    1846           0 :                 pArray->PutEmpty( nCol, nRow );
    1847           0 :             break;
    1848             : 
    1849             :             case ocTrue :
    1850           0 :                 pArray->PutBoolean( true, nCol, nRow );
    1851           0 :             break;
    1852             : 
    1853             :             case ocFalse :
    1854           0 :                 pArray->PutBoolean( false, nCol, nRow );
    1855           0 :             break;
    1856             : 
    1857             :             case ocArrayColSep :
    1858             :             case ocSep :
    1859          36 :                 nCol++;
    1860          36 :             break;
    1861             : 
    1862             :             case ocArrayRowSep :
    1863          62 :                 nRow++; nCol = 0;
    1864          62 :             break;
    1865             : 
    1866             :             case ocNegSub :
    1867           2 :                 nSign = -nSign;
    1868           2 :             break;
    1869             : 
    1870             :             default :
    1871          72 :                 break;
    1872             :         }
    1873         306 :         pCode[i] = NULL;
    1874         306 :         t->DecRef();
    1875             :     }
    1876          36 :     nLen = sal_uInt16( nStart );
    1877          36 :     return AddMatrix( pArray );
    1878             : }
    1879             : 
    1880           0 : FormulaToken* ScTokenArray::MergeRangeReference( const ScAddress & rPos )
    1881             : {
    1882           0 :     if (!pCode || !nLen)
    1883           0 :         return NULL;
    1884           0 :     sal_uInt16 nIdx = nLen;
    1885             :     FormulaToken *p1, *p2, *p3;      // ref, ocRange, ref
    1886             :     // The actual types are checked in extendRangeReference().
    1887           0 :     if (((p3 = PeekPrev(nIdx)) != 0) &&
    1888           0 :             (((p2 = PeekPrev(nIdx)) != 0) && p2->GetOpCode() == ocRange) &&
    1889           0 :             ((p1 = PeekPrev(nIdx)) != 0))
    1890             :     {
    1891           0 :         FormulaTokenRef p = extendRangeReference( *p1, *p3, rPos, true);
    1892           0 :         if (p)
    1893             :         {
    1894           0 :             p->IncRef();
    1895           0 :             p1->DecRef();
    1896           0 :             p2->DecRef();
    1897           0 :             p3->DecRef();
    1898           0 :             nLen -= 2;
    1899           0 :             pCode[ nLen-1 ] = p.get();
    1900           0 :             nRefs--;
    1901           0 :         }
    1902             :     }
    1903           0 :     return pCode[ nLen-1 ];
    1904             : }
    1905             : 
    1906       41526 : FormulaToken* ScTokenArray::AddOpCode( OpCode e )
    1907             : {
    1908       41526 :     ScRawToken t;
    1909       41526 :     t.SetOpCode( e );
    1910       41526 :     return AddRawToken( t );
    1911             : }
    1912             : 
    1913       10470 : FormulaToken* ScTokenArray::AddSingleReference( const ScSingleRefData& rRef )
    1914             : {
    1915       10470 :     return Add( new ScSingleRefToken( rRef ) );
    1916             : }
    1917             : 
    1918          94 : FormulaToken* ScTokenArray::AddMatrixSingleReference( const ScSingleRefData& rRef )
    1919             : {
    1920          94 :     return Add( new ScSingleRefToken( rRef, ocMatRef ) );
    1921             : }
    1922             : 
    1923        4852 : FormulaToken* ScTokenArray::AddDoubleReference( const ScComplexRefData& rRef )
    1924             : {
    1925        4852 :     return Add( new ScDoubleRefToken( rRef ) );
    1926             : }
    1927             : 
    1928          52 : FormulaToken* ScTokenArray::AddMatrix( const ScMatrixRef& p )
    1929             : {
    1930          52 :     return Add( new ScMatrixToken( p ) );
    1931             : }
    1932             : 
    1933          30 : FormulaToken* ScTokenArray::AddRangeName( sal_uInt16 n, bool bGlobal )
    1934             : {
    1935          30 :     return Add( new FormulaIndexToken( ocName, n, bGlobal));
    1936             : }
    1937             : 
    1938           0 : FormulaToken* ScTokenArray::AddDBRange( sal_uInt16 n )
    1939             : {
    1940           0 :     return Add( new FormulaIndexToken( ocDBArea, n));
    1941             : }
    1942             : 
    1943           0 : FormulaToken* ScTokenArray::AddExternalName( sal_uInt16 nFileId, const OUString& rName )
    1944             : {
    1945           0 :     return Add( new ScExternalNameToken(nFileId, rName) );
    1946             : }
    1947             : 
    1948           4 : FormulaToken* ScTokenArray::AddExternalSingleReference( sal_uInt16 nFileId, const OUString& rTabName, const ScSingleRefData& rRef )
    1949             : {
    1950           4 :     return Add( new ScExternalSingleRefToken(nFileId, rTabName, rRef) );
    1951             : }
    1952             : 
    1953           0 : FormulaToken* ScTokenArray::AddExternalDoubleReference( sal_uInt16 nFileId, const OUString& rTabName, const ScComplexRefData& rRef )
    1954             : {
    1955           0 :     return Add( new ScExternalDoubleRefToken(nFileId, rTabName, rRef) );
    1956             : }
    1957             : 
    1958           0 : FormulaToken* ScTokenArray::AddColRowName( const ScSingleRefData& rRef )
    1959             : {
    1960           0 :     return Add( new ScSingleRefToken( rRef, ocColRowName ) );
    1961             : }
    1962             : 
    1963        1648 : void ScTokenArray::AssignXMLString( const OUString &rText, const OUString &rFormulaNmsp )
    1964             : {
    1965        1648 :     sal_uInt16 nTokens = 1;
    1966             :     FormulaToken *aTokens[2];
    1967             : 
    1968        1648 :     aTokens[0] = new FormulaStringOpToken( ocStringXML, rText );
    1969        1648 :     if( !rFormulaNmsp.isEmpty() )
    1970           0 :         aTokens[ nTokens++ ] = new FormulaStringOpToken( ocStringXML, rFormulaNmsp );
    1971             : 
    1972        1648 :     Assign( nTokens, aTokens );
    1973        1648 : }
    1974             : 
    1975           0 : bool ScTokenArray::GetAdjacentExtendOfOuterFuncRefs( SCCOLROW& nExtend,
    1976             :         const ScAddress& rPos, ScDirection eDir )
    1977             : {
    1978           0 :     SCCOL nCol = 0;
    1979           0 :     SCROW nRow = 0;
    1980           0 :     switch ( eDir )
    1981             :     {
    1982             :         case DIR_BOTTOM :
    1983           0 :             if ( rPos.Row() < MAXROW )
    1984           0 :                 nRow = (nExtend = rPos.Row()) + 1;
    1985             :             else
    1986           0 :                 return false;
    1987           0 :         break;
    1988             :         case DIR_RIGHT :
    1989           0 :             if ( rPos.Col() < MAXCOL )
    1990           0 :                 nCol = static_cast<SCCOL>(nExtend = rPos.Col()) + 1;
    1991             :             else
    1992           0 :                 return false;
    1993           0 :         break;
    1994             :         case DIR_TOP :
    1995           0 :             if ( rPos.Row() > 0 )
    1996           0 :                 nRow = (nExtend = rPos.Row()) - 1;
    1997             :             else
    1998           0 :                 return false;
    1999           0 :         break;
    2000             :         case DIR_LEFT :
    2001           0 :             if ( rPos.Col() > 0 )
    2002           0 :                 nCol = static_cast<SCCOL>(nExtend = rPos.Col()) - 1;
    2003             :             else
    2004           0 :                 return false;
    2005           0 :         break;
    2006             :         default:
    2007             :             OSL_FAIL( "unknown Direction" );
    2008           0 :             return false;
    2009             :     }
    2010           0 :     if ( pRPN && nRPN )
    2011             :     {
    2012           0 :         FormulaToken* t = pRPN[nRPN-1];
    2013           0 :         if ( t->GetType() == svByte )
    2014             :         {
    2015           0 :             sal_uInt8 nParamCount = t->GetByte();
    2016           0 :             if ( nParamCount && nRPN > nParamCount )
    2017             :             {
    2018           0 :                 bool bRet = false;
    2019           0 :                 sal_uInt16 nParam = nRPN - nParamCount - 1;
    2020           0 :                 for ( ; nParam < nRPN-1; nParam++ )
    2021             :                 {
    2022           0 :                     FormulaToken* p = pRPN[nParam];
    2023           0 :                     switch ( p->GetType() )
    2024             :                     {
    2025             :                         case svSingleRef :
    2026             :                         {
    2027           0 :                             ScSingleRefData& rRef = *p->GetSingleRef();
    2028           0 :                             ScAddress aAbs = rRef.toAbs(rPos);
    2029           0 :                             switch ( eDir )
    2030             :                             {
    2031             :                                 case DIR_BOTTOM :
    2032           0 :                                     if (aAbs.Row() == nRow && aAbs.Row() > nExtend)
    2033             :                                     {
    2034           0 :                                         nExtend = aAbs.Row();
    2035           0 :                                         bRet = true;
    2036             :                                     }
    2037           0 :                                 break;
    2038             :                                 case DIR_RIGHT :
    2039           0 :                                     if (aAbs.Col() == nCol && static_cast<SCCOLROW>(aAbs.Col()) > nExtend)
    2040             :                                     {
    2041           0 :                                         nExtend = aAbs.Col();
    2042           0 :                                         bRet = true;
    2043             :                                     }
    2044           0 :                                 break;
    2045             :                                 case DIR_TOP :
    2046           0 :                                     if (aAbs.Row() == nRow && aAbs.Row() < nExtend)
    2047             :                                     {
    2048           0 :                                         nExtend = aAbs.Row();
    2049           0 :                                         bRet = true;
    2050             :                                     }
    2051           0 :                                 break;
    2052             :                                 case DIR_LEFT :
    2053           0 :                                     if (aAbs.Col() == nCol && static_cast<SCCOLROW>(aAbs.Col()) < nExtend)
    2054             :                                     {
    2055           0 :                                         nExtend = aAbs.Col();
    2056           0 :                                         bRet = true;
    2057             :                                     }
    2058           0 :                                 break;
    2059             :                             }
    2060             :                         }
    2061           0 :                         break;
    2062             :                         case svDoubleRef :
    2063             :                         {
    2064           0 :                             ScComplexRefData& rRef = *p->GetDoubleRef();
    2065           0 :                             ScRange aAbs = rRef.toAbs(rPos);
    2066           0 :                             switch ( eDir )
    2067             :                             {
    2068             :                                 case DIR_BOTTOM :
    2069           0 :                                     if (aAbs.aStart.Row() == nRow && aAbs.aEnd.Row() > nExtend)
    2070             :                                     {
    2071           0 :                                         nExtend = aAbs.aEnd.Row();
    2072           0 :                                         bRet = true;
    2073             :                                     }
    2074           0 :                                 break;
    2075             :                                 case DIR_RIGHT :
    2076           0 :                                     if (aAbs.aStart.Col() == nCol && static_cast<SCCOLROW>(aAbs.aEnd.Col()) > nExtend)
    2077             :                                     {
    2078           0 :                                         nExtend = aAbs.aEnd.Col();
    2079           0 :                                         bRet = true;
    2080             :                                     }
    2081           0 :                                 break;
    2082             :                                 case DIR_TOP :
    2083           0 :                                     if (aAbs.aEnd.Row() == nRow && aAbs.aStart.Row() < nExtend)
    2084             :                                     {
    2085           0 :                                         nExtend = aAbs.aStart.Row();
    2086           0 :                                         bRet = true;
    2087             :                                     }
    2088           0 :                                 break;
    2089             :                                 case DIR_LEFT :
    2090           0 :                                     if (aAbs.aEnd.Col() == nCol && static_cast<SCCOLROW>(aAbs.aStart.Col()) < nExtend)
    2091             :                                     {
    2092           0 :                                         nExtend = aAbs.aStart.Col();
    2093           0 :                                         bRet = true;
    2094             :                                     }
    2095           0 :                                 break;
    2096             :                             }
    2097             :                         }
    2098           0 :                         break;
    2099             :                         default:
    2100             :                         {
    2101             :                             // added to avoid warnings
    2102             :                         }
    2103             :                     } // switch
    2104             :                 } // for
    2105           0 :                 return bRet;
    2106             :             }
    2107             :         }
    2108             :     }
    2109           0 :     return false;
    2110             : }
    2111             : 
    2112           0 : void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos,
    2113             :         const ScAddress& rNewPos )
    2114             : {
    2115           0 :     for ( sal_uInt16 j=0; j<nLen; ++j )
    2116             :     {
    2117           0 :         switch ( pCode[j]->GetType() )
    2118             :         {
    2119             :             case svDoubleRef :
    2120             :             {
    2121           0 :                 ScSingleRefData& rRef2 = *pCode[j]->GetSingleRef2();
    2122             :                 // Also adjust if the reference is of the form Sheet1.A2:A3
    2123           0 :                 if ( rRef2.IsFlag3D() || pCode[j]->GetSingleRef()->IsFlag3D() )
    2124             :                 {
    2125           0 :                     ScAddress aAbs = rRef2.toAbs(rOldPos);
    2126           0 :                     rRef2.SetAddress(aAbs, rNewPos);
    2127             :                 }
    2128             :             }
    2129             :             //! fallthru
    2130             :             case svSingleRef :
    2131             :             {
    2132           0 :                 ScSingleRefData& rRef1 = *pCode[j]->GetSingleRef();
    2133           0 :                 if ( rRef1.IsFlag3D() )
    2134             :                 {
    2135           0 :                     ScAddress aAbs = rRef1.toAbs(rOldPos);
    2136           0 :                     rRef1.SetAddress(aAbs, rNewPos);
    2137             :                 }
    2138             :             }
    2139           0 :             break;
    2140             :             case svExternalDoubleRef :
    2141             :             {
    2142           0 :                 ScSingleRefData& rRef2 = *pCode[j]->GetSingleRef2();
    2143           0 :                 ScAddress aAbs = rRef2.toAbs(rOldPos);
    2144           0 :                 rRef2.SetAddress(aAbs, rNewPos);
    2145             :             }
    2146             :             //! fallthru
    2147             :             case svExternalSingleRef :
    2148             :             {
    2149           0 :                 ScSingleRefData& rRef1 = *pCode[j]->GetSingleRef();
    2150           0 :                 ScAddress aAbs = rRef1.toAbs(rOldPos);
    2151           0 :                 rRef1.SetAddress(aAbs, rNewPos);
    2152             :             }
    2153           0 :             break;
    2154             :             default:
    2155             :             {
    2156             :                 // added to avoid warnings
    2157             :             }
    2158             :         }
    2159             :     }
    2160           0 : }
    2161             : 
    2162             : namespace {
    2163             : 
    2164           8 : void GetExternalTableData(const ScDocument* pOldDoc, const ScDocument* pNewDoc, const SCTAB nTab, OUString& rTabName, sal_uInt16& rFileId)
    2165             : {
    2166           8 :     OUString aFileName = pOldDoc->GetFileURL();;
    2167           8 :     rFileId = pNewDoc->GetExternalRefManager()->getExternalFileId(aFileName);
    2168           8 :     rTabName = pOldDoc->GetCopyTabName(nTab);
    2169           8 :     if (rTabName.isEmpty())
    2170           2 :         pOldDoc->GetName(nTab, rTabName);
    2171           8 : }
    2172             : 
    2173         108 : bool IsInCopyRange( const ScRange& rRange, const ScDocument* pClipDoc )
    2174             : {
    2175         108 :     ScClipParam& rClipParam = const_cast<ScDocument*>(pClipDoc)->GetClipParam();
    2176         108 :     return rClipParam.maRanges.In(rRange);
    2177             : }
    2178             : 
    2179        3058 : bool SkipReference(formula::FormulaToken* pToken, const ScAddress& rPos, const ScDocument* pOldDoc, bool bRangeName, bool bCheckCopyArea)
    2180             : {
    2181        3058 :     ScRange aRange;
    2182             : 
    2183        3058 :     if (!ScRefTokenHelper::getRangeFromToken(aRange, pToken, rPos))
    2184           0 :         return true;
    2185             : 
    2186        3058 :     if (bRangeName && aRange.aStart.Tab() == rPos.Tab())
    2187             :     {
    2188           4 :         switch (pToken->GetType())
    2189             :         {
    2190             :             case svDoubleRef:
    2191             :                 {
    2192           0 :                     ScSingleRefData& rRef = *pToken->GetSingleRef2();
    2193           0 :                     if (rRef.IsColRel() || rRef.IsRowRel())
    2194           0 :                         return true;
    2195             :                 } // fall through
    2196             :             case svSingleRef:
    2197             :                 {
    2198           4 :                     ScSingleRefData& rRef = *pToken->GetSingleRef();
    2199           4 :                     if (rRef.IsColRel() || rRef.IsRowRel())
    2200           0 :                         return true;
    2201             :                 }
    2202           4 :                 break;
    2203             :             default:
    2204           0 :                 break;
    2205             :         }
    2206             :     }
    2207             : 
    2208        3058 :     if (bCheckCopyArea && IsInCopyRange(aRange, pOldDoc))
    2209          96 :         return true;
    2210             : 
    2211        2962 :     return false;
    2212             : }
    2213             : 
    2214          48 : void AdjustSingleRefData( ScSingleRefData& rRef, const ScAddress& rOldPos, const ScAddress& rNewPos)
    2215             : {
    2216          48 :     SCsCOL nCols = rNewPos.Col() - rOldPos.Col();
    2217          48 :     SCsROW nRows = rNewPos.Row() - rOldPos.Row();
    2218          48 :     SCsTAB nTabs = rNewPos.Tab() - rOldPos.Tab();
    2219             : 
    2220          48 :     if (!rRef.IsColRel())
    2221           8 :         rRef.IncCol(nCols);
    2222             : 
    2223          48 :     if (!rRef.IsRowRel())
    2224           8 :         rRef.IncRow(nRows);
    2225             : 
    2226          48 :     if (!rRef.IsTabRel())
    2227           4 :         rRef.IncTab(nTabs);
    2228          48 : }
    2229             : 
    2230             : }
    2231             : 
    2232         120 : void ScTokenArray::ReadjustAbsolute3DReferences( const ScDocument* pOldDoc, const ScDocument* pNewDoc, const ScAddress& rPos, bool bRangeName )
    2233             : {
    2234         298 :     for ( sal_uInt16 j=0; j<nLen; ++j )
    2235             :     {
    2236         178 :         switch ( pCode[j]->GetType() )
    2237             :         {
    2238             :             case svDoubleRef :
    2239             :             {
    2240           0 :                 if (SkipReference(pCode[j], rPos, pOldDoc, bRangeName, true))
    2241           0 :                     continue;
    2242             : 
    2243           0 :                 ScComplexRefData& rRef = *pCode[j]->GetDoubleRef();
    2244           0 :                 ScSingleRefData& rRef2 = rRef.Ref2;
    2245           0 :                 ScSingleRefData& rRef1 = rRef.Ref1;
    2246             : 
    2247           0 :                 if ( (rRef2.IsFlag3D() && !rRef2.IsTabRel()) || (rRef1.IsFlag3D() && !rRef1.IsTabRel()) )
    2248             :                 {
    2249           0 :                     OUString aTabName;
    2250             :                     sal_uInt16 nFileId;
    2251           0 :                     GetExternalTableData(pOldDoc, pNewDoc, rRef1.Tab(), aTabName, nFileId);
    2252           0 :                     pCode[j]->DecRef();
    2253           0 :                     ScExternalDoubleRefToken* pToken = new ScExternalDoubleRefToken(nFileId, aTabName, rRef);
    2254           0 :                     pToken->IncRef();
    2255           0 :                     pCode[j] = pToken;
    2256             :                 }
    2257             :             }
    2258           0 :             break;
    2259             :             case svSingleRef :
    2260             :             {
    2261          58 :                 if (SkipReference(pCode[j], rPos, pOldDoc, bRangeName, true))
    2262          48 :                     continue;
    2263             : 
    2264          10 :                 ScSingleRefData& rRef = *pCode[j]->GetSingleRef();
    2265             : 
    2266          10 :                 if ( rRef.IsFlag3D() && !rRef.IsTabRel() )
    2267             :                 {
    2268           8 :                     OUString aTabName;
    2269             :                     sal_uInt16 nFileId;
    2270           8 :                     GetExternalTableData(pOldDoc, pNewDoc, rRef.Tab(), aTabName, nFileId);
    2271             :                     //replace with ScExternalSingleRefToken and adjust references
    2272           8 :                     ScExternalSingleRefToken* pToken = new ScExternalSingleRefToken(nFileId, aTabName, rRef);
    2273           8 :                     pToken->IncRef();
    2274           8 :                     pCode[j]->DecRef(); // ATTENTION: rRef can't be used after this point
    2275           8 :                     pCode[j] = pToken;
    2276             :                 }
    2277             :             }
    2278          10 :             break;
    2279             :             default:
    2280             :             {
    2281             :                 // added to avoid warnings
    2282             :             }
    2283             :         }
    2284             :     }
    2285         120 : }
    2286             : 
    2287        1914 : void ScTokenArray::AdjustAbsoluteRefs( const ScDocument* pOldDoc, const ScAddress& rOldPos, const ScAddress& rNewPos, bool bRangeName, bool bCheckCopyRange)
    2288             : {
    2289       10964 :     for ( sal_uInt16 j=0; j<nLen; ++j )
    2290             :     {
    2291        9050 :         switch ( pCode[j]->GetType() )
    2292             :         {
    2293             :             case svDoubleRef :
    2294             :             {
    2295         268 :                 if (!SkipReference(pCode[j], rOldPos, pOldDoc, false, bCheckCopyRange))
    2296         268 :                     continue;
    2297             : 
    2298           0 :                 ScComplexRefData& rRef = *pCode[j]->GetDoubleRef();
    2299           0 :                 ScSingleRefData& rRef2 = rRef.Ref2;
    2300           0 :                 ScSingleRefData& rRef1 = rRef.Ref1;
    2301             : 
    2302             :                 // for range names only adjust if all parts are absolute
    2303           0 :                 if (!bRangeName || !(rRef1.IsColRel() || rRef1.IsRowRel() || rRef1.IsTabRel()))
    2304           0 :                     AdjustSingleRefData( rRef1, rOldPos, rNewPos );
    2305           0 :                 if (!bRangeName || !(rRef2.IsColRel() || rRef2.IsRowRel() || rRef2.IsTabRel()))
    2306           0 :                     AdjustSingleRefData( rRef2, rOldPos, rNewPos );
    2307             :             }
    2308           0 :             break;
    2309             :             case svSingleRef :
    2310             :             {
    2311        2732 :                 if (!SkipReference(pCode[j], rOldPos, pOldDoc, false, bCheckCopyRange))
    2312        2684 :                     continue;
    2313             : 
    2314          48 :                 ScSingleRefData& rRef = *pCode[j]->GetSingleRef();
    2315             : 
    2316             :                 // for range names only adjust if all parts are absolute
    2317          48 :                 if (!bRangeName || !(rRef.IsColRel() || rRef.IsRowRel() || rRef.IsTabRel()))
    2318          48 :                     AdjustSingleRefData( rRef, rOldPos, rNewPos );
    2319             :             }
    2320          48 :             break;
    2321             :             default:
    2322             :             {
    2323             :                 // added to avoid warnings
    2324             :             }
    2325             :         }
    2326             :     }
    2327        1914 : }
    2328             : 
    2329             : namespace {
    2330             : 
    2331         428 : ScRange getSelectedRange( const sc::RefUpdateContext& rCxt )
    2332             : {
    2333         428 :     ScRange aSelectedRange(ScAddress::INITIALIZE_INVALID);
    2334         428 :     if (rCxt.mnColDelta < 0)
    2335             :     {
    2336             :         // Delete and shift to left.
    2337          68 :         aSelectedRange.aStart = ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta, rCxt.maRange.aStart.Row(), rCxt.maRange.aStart.Tab());
    2338          68 :         aSelectedRange.aEnd = ScAddress(rCxt.maRange.aStart.Col()-1, rCxt.maRange.aEnd.Row(), rCxt.maRange.aEnd.Tab());
    2339             :     }
    2340         360 :     else if (rCxt.mnRowDelta < 0)
    2341             :     {
    2342             :         // Delete and shift up.
    2343         130 :         aSelectedRange.aStart = ScAddress(rCxt.maRange.aStart.Col(), rCxt.maRange.aStart.Row()+rCxt.mnRowDelta, rCxt.maRange.aStart.Tab());
    2344         130 :         aSelectedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), rCxt.maRange.aStart.Row()-1, rCxt.maRange.aEnd.Tab());
    2345             :     }
    2346         230 :     else if (rCxt.mnTabDelta < 0)
    2347             :     {
    2348             :         // Deleting sheets.
    2349             :         // TODO : Figure out what to do here.
    2350             :     }
    2351         230 :     else if (rCxt.mnColDelta > 0)
    2352             :     {
    2353             :         // Insert and shift to the right.
    2354         104 :         aSelectedRange.aStart = rCxt.maRange.aStart;
    2355         104 :         aSelectedRange.aEnd = ScAddress(rCxt.maRange.aStart.Col()+rCxt.mnColDelta-1, rCxt.maRange.aEnd.Row(), rCxt.maRange.aEnd.Tab());
    2356             :     }
    2357         126 :     else if (rCxt.mnRowDelta > 0)
    2358             :     {
    2359             :         // Insert and shift down.
    2360         126 :         aSelectedRange.aStart = rCxt.maRange.aStart;
    2361         126 :         aSelectedRange.aEnd = ScAddress(rCxt.maRange.aEnd.Col(), rCxt.maRange.aStart.Row()+rCxt.mnRowDelta-1, rCxt.maRange.aEnd.Tab());
    2362             :     }
    2363           0 :     else if (rCxt.mnTabDelta > 0)
    2364             :     {
    2365             :         // Inserting sheets.
    2366             :         // TODO : Figure out what to do here.
    2367             :     }
    2368             : 
    2369         428 :     return aSelectedRange;
    2370             : }
    2371             : 
    2372          26 : void setRefDeleted( ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt )
    2373             : {
    2374          26 :     if (rCxt.mnColDelta < 0)
    2375          12 :         rRef.SetColDeleted(true);
    2376          14 :     else if (rCxt.mnRowDelta < 0)
    2377          14 :         rRef.SetRowDeleted(true);
    2378           0 :     else if (rCxt.mnTabDelta < 0)
    2379           0 :         rRef.SetTabDeleted(true);
    2380          26 : }
    2381             : 
    2382          12 : void restoreDeletedRef( ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt )
    2383             : {
    2384          12 :     if (rCxt.mnColDelta)
    2385             :     {
    2386          12 :         if (rRef.IsColDeleted())
    2387          12 :             rRef.SetColDeleted(false);
    2388             :     }
    2389           0 :     else if (rCxt.mnRowDelta)
    2390             :     {
    2391           0 :         if (rRef.IsRowDeleted())
    2392           0 :             rRef.SetRowDeleted(false);
    2393             :     }
    2394           0 :     else if (rCxt.mnTabDelta)
    2395             :     {
    2396           0 :         if (rRef.IsTabDeleted())
    2397           0 :             rRef.SetTabDeleted(false);
    2398             :     }
    2399          12 : }
    2400             : 
    2401           4 : void setRefDeleted( ScComplexRefData& rRef, const sc::RefUpdateContext& rCxt )
    2402             : {
    2403           4 :     if (rCxt.mnColDelta < 0)
    2404             :     {
    2405           0 :         rRef.Ref1.SetColDeleted(true);
    2406           0 :         rRef.Ref2.SetColDeleted(true);
    2407             :     }
    2408           4 :     else if (rCxt.mnRowDelta < 0)
    2409             :     {
    2410           4 :         rRef.Ref1.SetRowDeleted(true);
    2411           4 :         rRef.Ref2.SetRowDeleted(true);
    2412             :     }
    2413           0 :     else if (rCxt.mnTabDelta < 0)
    2414             :     {
    2415           0 :         rRef.Ref1.SetTabDeleted(true);
    2416           0 :         rRef.Ref2.SetTabDeleted(true);
    2417             :     }
    2418           4 : }
    2419             : 
    2420          50 : bool shrinkRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rDeletedRange )
    2421             : {
    2422          50 :     if (!rDeletedRange.Intersects(rRefRange))
    2423           0 :         return false;
    2424             : 
    2425          50 :     if (rCxt.mnColDelta < 0)
    2426             :     {
    2427             :         // Shifting left.
    2428          22 :         if (rRefRange.aStart.Row() < rDeletedRange.aStart.Row() || rDeletedRange.aEnd.Row() < rRefRange.aEnd.Row())
    2429             :             // Deleted range is only partially overlapping in vertical direction. Bail out.
    2430           0 :             return false;
    2431             : 
    2432          22 :         if (rDeletedRange.aStart.Col() <= rRefRange.aStart.Col())
    2433             :         {
    2434           8 :             if (rRefRange.aEnd.Col() <= rDeletedRange.aEnd.Col())
    2435             :             {
    2436             :                 // Reference is entirely deleted.
    2437           0 :                 rRefRange.SetInvalid();
    2438             :             }
    2439             :             else
    2440             :             {
    2441             :                 // The reference range is truncated on the left.
    2442           8 :                 SCCOL nOffset = rDeletedRange.aStart.Col() - rRefRange.aStart.Col();
    2443           8 :                 SCCOL nDelta = rRefRange.aStart.Col() - rDeletedRange.aEnd.Col() - 1;
    2444           8 :                 rRefRange.aStart.IncCol(nOffset);
    2445           8 :                 rRefRange.aEnd.IncCol(nDelta+nOffset);
    2446             :             }
    2447             :         }
    2448          14 :         else if (rDeletedRange.aEnd.Col() < rRefRange.aEnd.Col())
    2449             :         {
    2450             :             // Reference is deleted in the middle. Move the last column
    2451             :             // position to the left.
    2452           6 :             SCCOL nDelta = rDeletedRange.aStart.Col() - rDeletedRange.aEnd.Col() - 1;
    2453           6 :             rRefRange.aEnd.IncCol(nDelta);
    2454             :         }
    2455             :         else
    2456             :         {
    2457             :             // The reference range is truncated on the right.
    2458           8 :             SCCOL nDelta = rDeletedRange.aStart.Col() - rRefRange.aEnd.Col() - 1;
    2459           8 :             rRefRange.aEnd.IncCol(nDelta);
    2460             :         }
    2461          22 :         return true;
    2462             :     }
    2463          28 :     else if (rCxt.mnRowDelta < 0)
    2464             :     {
    2465             :         // Shifting up.
    2466             : 
    2467          28 :         if (rRefRange.aStart.Col() < rDeletedRange.aStart.Col() || rDeletedRange.aEnd.Col() < rRefRange.aEnd.Col())
    2468             :             // Deleted range is only partially overlapping in horizontal direction. Bail out.
    2469           4 :             return false;
    2470             : 
    2471          24 :         if (rDeletedRange.aStart.Row() <= rRefRange.aStart.Row())
    2472             :         {
    2473           8 :             if (rRefRange.aEnd.Row() <= rDeletedRange.aEnd.Row())
    2474             :             {
    2475             :                 // Reference is entirely deleted.
    2476           0 :                 rRefRange.SetInvalid();
    2477             :             }
    2478             :             else
    2479             :             {
    2480             :                 // The reference range is truncated on the top.
    2481           8 :                 SCCOL nOffset = rDeletedRange.aStart.Row() - rRefRange.aStart.Row();
    2482           8 :                 SCCOL nDelta = rRefRange.aStart.Row() - rDeletedRange.aEnd.Row() - 1;
    2483           8 :                 rRefRange.aStart.IncRow(nOffset);
    2484           8 :                 rRefRange.aEnd.IncRow(nDelta+nOffset);
    2485             :             }
    2486             :         }
    2487          16 :         else if (rDeletedRange.aEnd.Row() < rRefRange.aEnd.Row())
    2488             :         {
    2489             :             // Reference is deleted in the middle. Move the last row
    2490             :             // position upward.
    2491           8 :             SCCOL nDelta = rDeletedRange.aStart.Row() - rDeletedRange.aEnd.Row() - 1;
    2492           8 :             rRefRange.aEnd.IncRow(nDelta);
    2493             :         }
    2494             :         else
    2495             :         {
    2496             :             // The reference range is truncated on the bottom.
    2497           8 :             SCCOL nDelta = rDeletedRange.aStart.Row() - rRefRange.aEnd.Row() - 1;
    2498           8 :             rRefRange.aEnd.IncRow(nDelta);
    2499             :         }
    2500          24 :         return true;
    2501             :     }
    2502             : 
    2503           0 :     return false;
    2504             : }
    2505             : 
    2506          86 : bool expandRange( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rSelectedRange )
    2507             : {
    2508          86 :     if (!rSelectedRange.Intersects(rRefRange))
    2509          36 :         return false;
    2510             : 
    2511          50 :     if (rCxt.mnColDelta > 0)
    2512             :     {
    2513             :         // Insert and shifting right.
    2514          24 :         if (rRefRange.aStart.Row() < rSelectedRange.aStart.Row() || rSelectedRange.aEnd.Row() < rRefRange.aEnd.Row())
    2515             :             // Selected range is only partially overlapping in vertical direction. Bail out.
    2516           0 :             return false;
    2517             : 
    2518          24 :         if (!rCxt.mrDoc.IsExpandRefs() && rSelectedRange.aStart.Col() <= rRefRange.aStart.Col())
    2519             :             // Selected range is at the left end and the edge expansion is turned off.  No expansion.
    2520          14 :             return false;
    2521             : 
    2522             :         // Move the last column position to the right.
    2523          10 :         SCCOL nDelta = rSelectedRange.aEnd.Col() - rSelectedRange.aStart.Col() + 1;
    2524          10 :         rRefRange.aEnd.IncCol(nDelta);
    2525          10 :         return true;
    2526             :     }
    2527          26 :     else if (rCxt.mnRowDelta > 0)
    2528             :     {
    2529             :         // Insert and shifting down.
    2530          26 :         if (rRefRange.aStart.Col() < rSelectedRange.aStart.Col() || rSelectedRange.aEnd.Col() < rRefRange.aEnd.Col())
    2531             :             // Selected range is only partially overlapping in horizontal direction. Bail out.
    2532           4 :             return false;
    2533             : 
    2534          22 :         if (!rCxt.mrDoc.IsExpandRefs() && rSelectedRange.aStart.Row() <= rRefRange.aStart.Row())
    2535             :             // Selected range is at the top end and the edge expansion is turned off.  No expansion.
    2536          12 :             return false;
    2537             : 
    2538             :         // Move the last row position down.
    2539          10 :         SCROW nDelta = rSelectedRange.aEnd.Row() - rSelectedRange.aStart.Row() + 1;
    2540          10 :         rRefRange.aEnd.IncRow(nDelta);
    2541          10 :         return true;
    2542             :     }
    2543           0 :     return false;
    2544             : }
    2545             : 
    2546             : /**
    2547             :  * Check if the referenced range is expandable when the selected range is
    2548             :  * not overlapping the referenced range.
    2549             :  */
    2550          66 : bool expandRangeByEdge( const sc::RefUpdateContext& rCxt, ScRange& rRefRange, const ScRange& rSelectedRange )
    2551             : {
    2552          66 :     if (!rCxt.mrDoc.IsExpandRefs())
    2553             :         // Edge-expansion is turned off.
    2554          58 :         return false;
    2555             : 
    2556           8 :     if (rCxt.mnColDelta > 0)
    2557             :     {
    2558             :         // Insert and shift right.
    2559           4 :         if (rRefRange.aStart.Row() < rSelectedRange.aStart.Row() || rSelectedRange.aEnd.Row() < rRefRange.aEnd.Row())
    2560             :             // Selected range is only partially overlapping in vertical direction. Bail out.
    2561           0 :             return false;
    2562             : 
    2563           4 :         if (rSelectedRange.aStart.Col() - rRefRange.aEnd.Col() != 1)
    2564             :             // Selected range is not immediately adjacent. Bail out.
    2565           0 :             return false;
    2566             : 
    2567             :         // Move the last column position to the right.
    2568           4 :         SCCOL nDelta = rSelectedRange.aEnd.Col() - rSelectedRange.aStart.Col() + 1;
    2569           4 :         rRefRange.aEnd.IncCol(nDelta);
    2570           4 :         return true;
    2571             :     }
    2572           4 :     else if (rCxt.mnRowDelta > 0)
    2573             :     {
    2574           4 :         if (rRefRange.aStart.Col() < rSelectedRange.aStart.Col() || rSelectedRange.aEnd.Col() < rRefRange.aEnd.Col())
    2575             :             // Selected range is only partially overlapping in horizontal direction. Bail out.
    2576           0 :             return false;
    2577             : 
    2578           4 :         if (rSelectedRange.aStart.Row() - rRefRange.aEnd.Row() != 1)
    2579             :             // Selected range is not immediately adjacent. Bail out.
    2580           0 :             return false;
    2581             : 
    2582             :         // Move the last row position down.
    2583           4 :         SCROW nDelta = rSelectedRange.aEnd.Row() - rSelectedRange.aStart.Row() + 1;
    2584           4 :         rRefRange.aEnd.IncRow(nDelta);
    2585           4 :         return true;
    2586             :     }
    2587             : 
    2588           0 :     return false;
    2589             : }
    2590             : 
    2591         414 : bool isNameModified( const sc::UpdatedRangeNames& rUpdatedNames, SCTAB nOldTab, const formula::FormulaToken& rToken )
    2592             : {
    2593         414 :     if (rToken.GetOpCode() != ocName)
    2594           0 :         return false;
    2595             : 
    2596         414 :     SCTAB nTab = -1;
    2597         414 :     if (!rToken.IsGlobal())
    2598           4 :         nTab = nOldTab;
    2599             : 
    2600             :     // Check if this named expression has been modified.
    2601         414 :     return rUpdatedNames.isNameUpdated(nTab, rToken.GetIndex());
    2602             : }
    2603             : 
    2604             : }
    2605             : 
    2606         420 : sc::RefUpdateResult ScTokenArray::AdjustReferenceOnShift( const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos )
    2607             : {
    2608         420 :     ScRange aSelectedRange = getSelectedRange(rCxt);
    2609             : 
    2610         420 :     sc::RefUpdateResult aRes;
    2611         420 :     ScAddress aNewPos = rOldPos;
    2612         420 :     bool bCellShifted = rCxt.maRange.In(rOldPos);
    2613         420 :     if (bCellShifted)
    2614         204 :         aNewPos.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
    2615             : 
    2616         420 :     FormulaToken** p = pCode;
    2617         420 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    2618        1590 :     for (; p != pEnd; ++p)
    2619             :     {
    2620        1170 :         switch ((*p)->GetType())
    2621             :         {
    2622             :             case svSingleRef:
    2623             :             {
    2624         230 :                 formula::FormulaToken* pToken = *p;
    2625         230 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    2626         230 :                 ScAddress aAbs = rRef.toAbs(rOldPos);
    2627             : 
    2628         230 :                 if (rCxt.isDeleted() && aSelectedRange.In(aAbs))
    2629             :                 {
    2630             :                     // This reference is in the deleted region.
    2631          26 :                     setRefDeleted(rRef, rCxt);
    2632          26 :                     aRes.mbValueChanged = true;
    2633          64 :                     break;
    2634             :                 }
    2635             : 
    2636         204 :                 if (!rCxt.isDeleted() && rRef.IsDeleted())
    2637             :                 {
    2638             :                     // Check if the token has reference to previously deleted region.
    2639          12 :                     ScAddress aCheckPos = rRef.toAbs(aNewPos);
    2640          12 :                     if (rCxt.maRange.In(aCheckPos))
    2641             :                     {
    2642          12 :                         restoreDeletedRef(rRef, rCxt);
    2643          12 :                         aRes.mbValueChanged = true;
    2644          12 :                         break;
    2645             :                     }
    2646             :                 }
    2647             : 
    2648         192 :                 if (rCxt.maRange.In(aAbs))
    2649             :                 {
    2650         108 :                     aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
    2651         108 :                     aRes.mbReferenceModified = true;
    2652             :                 }
    2653             : 
    2654         192 :                 rRef.SetAddress(aAbs, aNewPos);
    2655             :             }
    2656         192 :             break;
    2657             :             case svDoubleRef:
    2658             :             {
    2659         164 :                 formula::FormulaToken* pToken = *p;
    2660         164 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    2661         164 :                 ScRange aAbs = rRef.toAbs(rOldPos);
    2662             : 
    2663         164 :                 if (rCxt.isDeleted())
    2664             :                 {
    2665          78 :                     if (aSelectedRange.In(aAbs))
    2666             :                     {
    2667             :                         // This reference is in the deleted region.
    2668           4 :                         setRefDeleted(rRef, rCxt);
    2669           4 :                         aRes.mbValueChanged = true;
    2670          82 :                         break;
    2671             :                     }
    2672          74 :                     else if (aSelectedRange.Intersects(aAbs))
    2673             :                     {
    2674          50 :                         if (shrinkRange(rCxt, aAbs, aSelectedRange))
    2675             :                         {
    2676             :                             // The reference range has been shrunk.
    2677          46 :                             rRef.SetRange(aAbs, aNewPos);
    2678          46 :                             aRes.mbValueChanged = true;
    2679          46 :                             aRes.mbReferenceModified = true;
    2680          46 :                             break;
    2681             :                         }
    2682             :                     }
    2683             :                 }
    2684             : 
    2685         114 :                 if (rCxt.isInserted())
    2686             :                 {
    2687          86 :                     if (expandRange(rCxt, aAbs, aSelectedRange))
    2688             :                     {
    2689             :                         // The reference range has been expanded.
    2690          20 :                         rRef.SetRange(aAbs, aNewPos);
    2691          20 :                         aRes.mbValueChanged = true;
    2692          20 :                         aRes.mbReferenceModified = true;
    2693          20 :                         break;
    2694             :                     }
    2695             : 
    2696          66 :                     if (expandRangeByEdge(rCxt, aAbs, aSelectedRange))
    2697             :                     {
    2698             :                         // The reference range has been expanded on the edge.
    2699           8 :                         rRef.SetRange(aAbs, aNewPos);
    2700           8 :                         aRes.mbValueChanged = true;
    2701           8 :                         aRes.mbReferenceModified = true;
    2702           8 :                         break;
    2703             :                     }
    2704             :                 }
    2705             : 
    2706          86 :                 if (rCxt.maRange.In(aAbs))
    2707             :                 {
    2708          48 :                     aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
    2709          48 :                     aRes.mbReferenceModified = true;
    2710             :                 }
    2711          38 :                 else if (rCxt.maRange.Intersects(aAbs))
    2712             :                 {
    2713             :                     // Part of the referenced range is being shifted. This
    2714             :                     // will change the values of the range.
    2715           8 :                     aRes.mbValueChanged = true;
    2716             :                 }
    2717             : 
    2718          86 :                 rRef.SetRange(aAbs, aNewPos);
    2719             :             }
    2720          86 :             break;
    2721             :             case svExternalSingleRef:
    2722             :             {
    2723             :                 // For external reference, just reset the reference with
    2724             :                 // respect to the new cell position.
    2725          18 :                 formula::FormulaToken* pToken = *p;
    2726          18 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    2727          18 :                 ScAddress aAbs = rRef.toAbs(rOldPos);
    2728          18 :                 rRef.SetAddress(aAbs, aNewPos);
    2729             :             }
    2730          18 :             break;
    2731             :             case svExternalDoubleRef:
    2732             :             {
    2733             :                 // Same as above.
    2734           6 :                 formula::FormulaToken* pToken = *p;
    2735           6 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    2736           6 :                 ScRange aAbs = rRef.toAbs(rOldPos);
    2737           6 :                 rRef.SetRange(aAbs, aNewPos);
    2738             :             }
    2739           6 :             break;
    2740             :             case svIndex:
    2741             :             {
    2742          16 :                 if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p))
    2743          10 :                     aRes.mbNameModified = true;
    2744             :             }
    2745          16 :             break;
    2746             :             default:
    2747             :                 ;
    2748             :         }
    2749             :     }
    2750             : 
    2751         420 :     return aRes;
    2752             : }
    2753             : 
    2754          66 : sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMove(
    2755             :     const sc::RefUpdateContext& rCxt, const ScAddress& rOldPos, const ScAddress& rNewPos )
    2756             : {
    2757          66 :     sc::RefUpdateResult aRes;
    2758             : 
    2759          66 :     if (!rCxt.mnColDelta && !rCxt.mnRowDelta && !rCxt.mnTabDelta)
    2760             :         // The cell hasn't moved at all.
    2761           0 :         return aRes;
    2762             : 
    2763             :     // When moving, the range is the destination range. We need to use the old
    2764             :     // range prior to the move for hit analysis.
    2765          66 :     ScRange aOldRange = rCxt.maRange;
    2766          66 :     aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
    2767             : 
    2768          66 :     bool b3DFlag = rOldPos.Tab() != rNewPos.Tab() || rCxt.mnTabDelta;
    2769             : 
    2770          66 :     FormulaToken** p = pCode;
    2771          66 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    2772         262 :     for (; p != pEnd; ++p)
    2773             :     {
    2774         196 :         switch ((*p)->GetType())
    2775             :         {
    2776             :             case svSingleRef:
    2777             :             {
    2778          48 :                 formula::FormulaToken* pToken = *p;
    2779          48 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    2780          48 :                 ScAddress aAbs = rRef.toAbs(rOldPos);
    2781          48 :                 if (aOldRange.In(aAbs))
    2782             :                 {
    2783          32 :                     aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
    2784          32 :                     aRes.mbReferenceModified = true;
    2785             :                 }
    2786             : 
    2787          48 :                 rRef.SetAddress(aAbs, rNewPos);
    2788          48 :                 if (b3DFlag)
    2789           6 :                     rRef.SetFlag3D(b3DFlag);
    2790             :             }
    2791          48 :             break;
    2792             :             case svDoubleRef:
    2793             :             {
    2794          20 :                 formula::FormulaToken* pToken = *p;
    2795          20 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    2796          20 :                 ScRange aAbs = rRef.toAbs(rOldPos);
    2797          20 :                 if (aOldRange.In(aAbs))
    2798             :                 {
    2799           8 :                     aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
    2800           8 :                     aRes.mbReferenceModified = true;
    2801             :                 }
    2802             : 
    2803          20 :                 rRef.SetRange(aAbs, rNewPos);
    2804          20 :                 if (b3DFlag)
    2805           2 :                     rRef.Ref1.SetFlag3D(true);
    2806             :             }
    2807          20 :             break;
    2808             :             case svIndex:
    2809             :             {
    2810           8 :                 if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p))
    2811           8 :                     aRes.mbNameModified = true;
    2812             :             }
    2813           8 :             break;
    2814             :             default:
    2815             :                 ;
    2816             :         }
    2817             :     }
    2818             : 
    2819          66 :     return aRes;
    2820             : }
    2821             : 
    2822          22 : sc::RefUpdateResult ScTokenArray::MoveReference( const ScAddress& rPos, const sc::RefUpdateContext& rCxt )
    2823             : {
    2824          22 :     sc::RefUpdateResult aRes;
    2825             : 
    2826          22 :     ScRange aOldRange = rCxt.maRange;
    2827          22 :     aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
    2828             : 
    2829          22 :     FormulaToken** p = pCode;
    2830          22 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    2831          84 :     for (; p != pEnd; ++p)
    2832             :     {
    2833          62 :         switch ((*p)->GetType())
    2834             :         {
    2835             :             case svSingleRef:
    2836             :             {
    2837          22 :                 formula::FormulaToken* pToken = *p;
    2838          22 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    2839          22 :                 ScAddress aAbs = rRef.toAbs(rPos);
    2840          22 :                 if (aOldRange.In(aAbs))
    2841             :                 {
    2842          20 :                     aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
    2843          20 :                     rRef.SetAddress(aAbs, rPos);
    2844          20 :                     if (rCxt.mnTabDelta)
    2845           2 :                         rRef.SetFlag3D(aAbs.Tab()!=rPos.Tab());
    2846             :                 }
    2847             :             }
    2848          22 :             break;
    2849             :             case svDoubleRef:
    2850             :             {
    2851           4 :                 formula::FormulaToken* pToken = *p;
    2852           4 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    2853           4 :                 ScRange aAbs = rRef.toAbs(rPos);
    2854           4 :                 if (aOldRange.In(aAbs))
    2855             :                 {
    2856           4 :                     aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
    2857           4 :                     rRef.SetRange(aAbs, rPos);
    2858           4 :                     if (rCxt.mnTabDelta)
    2859           0 :                         rRef.Ref1.SetFlag3D(aAbs.aStart.Tab()!=rPos.Tab());
    2860             :                 }
    2861             :             }
    2862           4 :             break;
    2863             :             case svIndex:
    2864             :             {
    2865           4 :                 if (isNameModified(rCxt.maUpdatedNames, aOldRange.aStart.Tab(), **p))
    2866           4 :                     aRes.mbNameModified = true;
    2867             :             }
    2868           4 :             break;
    2869             :             default:
    2870             :                 ;
    2871             :         }
    2872             :     }
    2873             : 
    2874          22 :     return aRes;
    2875             : }
    2876             : 
    2877           2 : void ScTokenArray::MoveReferenceColReorder(
    2878             :     const ScAddress& rPos, SCTAB nTab, SCROW nRow1, SCROW nRow2, const sc::ColRowReorderMapType& rColMap )
    2879             : {
    2880           2 :     FormulaToken** p = pCode;
    2881           2 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    2882          18 :     for (; p != pEnd; ++p)
    2883             :     {
    2884          16 :         switch ((*p)->GetType())
    2885             :         {
    2886             :             case svSingleRef:
    2887             :             {
    2888           4 :                 formula::FormulaToken* pToken = *p;
    2889           4 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    2890           4 :                 ScAddress aAbs = rRef.toAbs(rPos);
    2891             : 
    2892           4 :                 if (aAbs.Tab() == nTab && nRow1 <= aAbs.Row() && aAbs.Row() <= nRow2)
    2893             :                 {
    2894             :                     // Inside reordered row range.
    2895           4 :                     sc::ColRowReorderMapType::const_iterator it = rColMap.find(aAbs.Col());
    2896           4 :                     if (it != rColMap.end())
    2897             :                     {
    2898             :                         // This column is reordered.
    2899           4 :                         SCCOL nNewCol = it->second;
    2900           4 :                         aAbs.SetCol(nNewCol);
    2901           4 :                         rRef.SetAddress(aAbs, rPos);
    2902             :                     }
    2903             :                 }
    2904             :             }
    2905           4 :             break;
    2906             :             case svDoubleRef:
    2907             :             {
    2908           0 :                 formula::FormulaToken* pToken = *p;
    2909           0 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    2910           0 :                 ScRange aAbs = rRef.toAbs(rPos);
    2911             : 
    2912           0 :                 if (aAbs.aStart.Tab() != aAbs.aEnd.Tab())
    2913             :                     // Must be a single-sheet reference.
    2914           0 :                     break;
    2915             : 
    2916           0 :                 if (aAbs.aStart.Col() != aAbs.aEnd.Col())
    2917             :                     // Whole range must fit in a single column.
    2918           0 :                     break;
    2919             : 
    2920           0 :                 if (aAbs.aStart.Tab() == nTab && nRow1 <= aAbs.aStart.Row() && aAbs.aEnd.Row() <= nRow2)
    2921             :                 {
    2922             :                     // Inside reordered row range.
    2923           0 :                     sc::ColRowReorderMapType::const_iterator it = rColMap.find(aAbs.aStart.Col());
    2924           0 :                     if (it != rColMap.end())
    2925             :                     {
    2926             :                         // This column is reordered.
    2927           0 :                         SCCOL nNewCol = it->second;
    2928           0 :                         aAbs.aStart.SetCol(nNewCol);
    2929           0 :                         aAbs.aEnd.SetCol(nNewCol);
    2930           0 :                         rRef.SetRange(aAbs, rPos);
    2931             :                     }
    2932             :                 }
    2933             :             }
    2934           0 :             break;
    2935             :             default:
    2936             :                 ;
    2937             :         }
    2938             :     }
    2939           2 : }
    2940             : 
    2941         236 : void ScTokenArray::MoveReferenceRowReorder( const ScAddress& rPos, SCTAB nTab, SCCOL nCol1, SCCOL nCol2, const sc::ColRowReorderMapType& rRowMap )
    2942             : {
    2943         236 :     FormulaToken** p = pCode;
    2944         236 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    2945         804 :     for (; p != pEnd; ++p)
    2946             :     {
    2947         568 :         switch ((*p)->GetType())
    2948             :         {
    2949             :             case svSingleRef:
    2950             :             {
    2951         210 :                 formula::FormulaToken* pToken = *p;
    2952         210 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    2953         210 :                 ScAddress aAbs = rRef.toAbs(rPos);
    2954             : 
    2955         210 :                 if (aAbs.Tab() == nTab && nCol1 <= aAbs.Col() && aAbs.Col() <= nCol2)
    2956             :                 {
    2957             :                     // Inside reordered column range.
    2958         210 :                     sc::ColRowReorderMapType::const_iterator it = rRowMap.find(aAbs.Row());
    2959         210 :                     if (it != rRowMap.end())
    2960             :                     {
    2961             :                         // This column is reordered.
    2962         210 :                         SCROW nNewRow = it->second;
    2963         210 :                         aAbs.SetRow(nNewRow);
    2964         210 :                         rRef.SetAddress(aAbs, rPos);
    2965             :                     }
    2966             :                 }
    2967             :             }
    2968         210 :             break;
    2969             :             case svDoubleRef:
    2970             :             {
    2971          40 :                 formula::FormulaToken* pToken = *p;
    2972          40 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    2973          40 :                 ScRange aAbs = rRef.toAbs(rPos);
    2974             : 
    2975          40 :                 if (aAbs.aStart.Tab() != aAbs.aEnd.Tab())
    2976             :                     // Must be a single-sheet reference.
    2977           0 :                     break;
    2978             : 
    2979          40 :                 if (aAbs.aStart.Row() != aAbs.aEnd.Row())
    2980             :                     // Whole range must fit in a single row.
    2981           0 :                     break;
    2982             : 
    2983          40 :                 if (aAbs.aStart.Tab() == nTab && nCol1 <= aAbs.aStart.Col() && aAbs.aEnd.Col() <= nCol2)
    2984             :                 {
    2985             :                     // Inside reordered column range.
    2986          40 :                     sc::ColRowReorderMapType::const_iterator it = rRowMap.find(aAbs.aStart.Row());
    2987          40 :                     if (it != rRowMap.end())
    2988             :                     {
    2989             :                         // This row is reordered.
    2990          40 :                         SCCOL nNewRow = it->second;
    2991          40 :                         aAbs.aStart.SetRow(nNewRow);
    2992          40 :                         aAbs.aEnd.SetRow(nNewRow);
    2993          40 :                         rRef.SetRange(aAbs, rPos);
    2994             :                     }
    2995             :                 }
    2996             :             }
    2997          40 :             break;
    2998             :             default:
    2999             :                 ;
    3000             :         }
    3001             :     }
    3002         236 : }
    3003             : 
    3004             : namespace {
    3005             : 
    3006          12 : bool adjustSingleRefInName(
    3007             :     ScSingleRefData& rRef, const sc::RefUpdateContext& rCxt, const ScAddress& rPos )
    3008             : {
    3009          12 :     ScAddress aAbs = rRef.toAbs(rPos);
    3010             : 
    3011          12 :     if (aAbs.Tab() < rCxt.maRange.aStart.Tab() || rCxt.maRange.aEnd.Tab() < aAbs.Tab())
    3012             :     {
    3013             :         // This references a sheet that has not shifted. Don't change it.
    3014           2 :         return false;
    3015             :     }
    3016             : 
    3017          10 :     if (rRef.IsColRel() || rRef.IsRowRel())
    3018             :     {
    3019             :         // Adjust references only when both column and row are absolute.
    3020           6 :         return false;
    3021             :     }
    3022             : 
    3023           4 :     bool bChanged = false;
    3024             : 
    3025           4 :     if (rCxt.mnColDelta)
    3026             :     {
    3027             :         // Adjust absolute column reference.
    3028           4 :         if (rCxt.maRange.aStart.Col() <= rRef.Col() && rRef.Col() <= rCxt.maRange.aEnd.Col())
    3029             :         {
    3030           4 :             rRef.IncCol(rCxt.mnColDelta);
    3031           4 :             bChanged = true;
    3032             :         }
    3033             :     }
    3034             : 
    3035           4 :     if (rCxt.mnRowDelta)
    3036             :     {
    3037             :         // Adjust absolute row reference.
    3038           0 :         if (rCxt.maRange.aStart.Row() <= rRef.Row() && rRef.Row() <= rCxt.maRange.aEnd.Row())
    3039             :         {
    3040           0 :             rRef.IncRow(rCxt.mnRowDelta);
    3041           0 :             bChanged = true;
    3042             :         }
    3043             :     }
    3044             : 
    3045           4 :     if (!rRef.IsTabRel() && rCxt.mnTabDelta)
    3046             :     {
    3047             :         // Sheet range has already been checked above.
    3048           0 :         rRef.IncTab(rCxt.mnTabDelta);
    3049           0 :         bChanged = true;
    3050             :     }
    3051             : 
    3052           4 :     return bChanged;
    3053             : }
    3054             : 
    3055          10 : bool adjustDoubleRefInName(
    3056             :     ScComplexRefData& rRef, const sc::RefUpdateContext& rCxt, const ScAddress& rPos )
    3057             : {
    3058          10 :     bool bRefChanged = false;
    3059          10 :     if (rCxt.mnRowDelta > 0 && rCxt.mrDoc.IsExpandRefs() && !rRef.Ref1.IsRowRel() && !rRef.Ref2.IsRowRel())
    3060             :     {
    3061             :         // Check and see if we should expand the range at the top.
    3062           8 :         ScRange aSelectedRange = getSelectedRange(rCxt);
    3063           8 :         ScRange aAbs = rRef.toAbs(rPos);
    3064           8 :         if (aSelectedRange.Intersects(aAbs))
    3065             :         {
    3066             :             // Selection intersects the referenced range. Only expand the
    3067             :             // bottom position.
    3068           8 :             rRef.Ref2.IncRow(rCxt.mnRowDelta);
    3069           8 :             return true;
    3070             :         }
    3071             :     }
    3072             : 
    3073           2 :     if (adjustSingleRefInName(rRef.Ref1, rCxt, rPos))
    3074           2 :         bRefChanged = true;
    3075             : 
    3076           2 :     if (adjustSingleRefInName(rRef.Ref2, rCxt, rPos))
    3077           2 :         bRefChanged = true;
    3078             : 
    3079           2 :     return bRefChanged;
    3080             : }
    3081             : 
    3082             : }
    3083             : 
    3084          62 : sc::RefUpdateResult ScTokenArray::AdjustReferenceInName(
    3085             :     const sc::RefUpdateContext& rCxt, const ScAddress& rPos )
    3086             : {
    3087          62 :     if (rCxt.meMode == URM_MOVE)
    3088          16 :         return AdjustReferenceInMovedName(rCxt, rPos);
    3089             : 
    3090          46 :     sc::RefUpdateResult aRes;
    3091             : 
    3092          46 :     FormulaToken** p = pCode;
    3093          46 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    3094         108 :     for (; p != pEnd; ++p)
    3095             :     {
    3096          62 :         switch ((*p)->GetType())
    3097             :         {
    3098             :             case svSingleRef:
    3099             :             {
    3100           8 :                 formula::FormulaToken* pToken = *p;
    3101           8 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    3102           8 :                 if (adjustSingleRefInName(rRef, rCxt, rPos))
    3103           0 :                     aRes.mbReferenceModified = true;
    3104             :             }
    3105           8 :             break;
    3106             :             case svDoubleRef:
    3107             :             {
    3108          46 :                 formula::FormulaToken* pToken = *p;
    3109          46 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    3110          46 :                 ScRange aAbs = rRef.toAbs(rPos);
    3111          46 :                 if (rCxt.maRange.In(aAbs))
    3112             :                 {
    3113             :                     // This range is entirely within the shifted region.
    3114           6 :                     if (adjustDoubleRefInName(rRef, rCxt, rPos))
    3115           6 :                         aRes.mbReferenceModified = true;
    3116             :                 }
    3117          40 :                 else if (rCxt.mnRowDelta < 0)
    3118             :                 {
    3119             :                     // row(s) deleted.
    3120          12 :                     if (rRef.Ref1.IsRowRel() || rRef.Ref2.IsRowRel())
    3121             :                         // Don't modify relative references in names.
    3122           6 :                         break;
    3123             : 
    3124          12 :                     if (aAbs.aStart.Col() < rCxt.maRange.aStart.Col() || rCxt.maRange.aEnd.Col() < aAbs.aEnd.Col())
    3125             :                         // column range of the reference is not entirely in the deleted column range.
    3126           6 :                         break;
    3127             : 
    3128           6 :                     ScRange aDeleted = rCxt.maRange;
    3129           6 :                     aDeleted.aStart.IncRow(rCxt.mnRowDelta);
    3130           6 :                     aDeleted.aEnd.SetRow(aDeleted.aStart.Row()-rCxt.mnRowDelta-1);
    3131             : 
    3132           6 :                     if (aAbs.aEnd.Row() < aDeleted.aStart.Row() || aDeleted.aEnd.Row() < aAbs.aStart.Row())
    3133             :                         // reference range doesn't intersect with the deleted range.
    3134           0 :                         break;
    3135             : 
    3136           6 :                     if (aDeleted.aStart.Row() <= aAbs.aStart.Row() && aAbs.aEnd.Row() <= aDeleted.aEnd.Row())
    3137             :                     {
    3138             :                         // This reference is entirely deleted.
    3139           0 :                         rRef.Ref1.SetRowDeleted(true);
    3140           0 :                         rRef.Ref2.SetRowDeleted(true);
    3141           0 :                         aRes.mbReferenceModified = true;
    3142           0 :                         break;
    3143             :                     }
    3144             : 
    3145           6 :                     if (aAbs.aStart.Row() < aDeleted.aStart.Row())
    3146             :                     {
    3147           4 :                         if (aDeleted.aEnd.Row() < aAbs.aEnd.Row())
    3148             :                             // Deleted in the middle.  Make the reference shorter.
    3149           2 :                             rRef.Ref2.IncRow(rCxt.mnRowDelta);
    3150             :                         else
    3151             :                             // Deleted at tail end.  Cut off the lower part.
    3152           2 :                             rRef.Ref2.SetAbsRow(aDeleted.aStart.Row()-1);
    3153             :                     }
    3154             :                     else
    3155             :                     {
    3156             :                         // Deleted at the top.  Cut the top off and shift up.
    3157           2 :                         rRef.Ref1.SetAbsRow(aDeleted.aEnd.Row()+1);
    3158           2 :                         rRef.Ref1.IncRow(rCxt.mnRowDelta);
    3159           2 :                         rRef.Ref2.IncRow(rCxt.mnRowDelta);
    3160             :                     }
    3161             : 
    3162           6 :                     aRes.mbReferenceModified = true;
    3163             :                 }
    3164          28 :                 else if (rCxt.maRange.Intersects(aAbs))
    3165             :                 {
    3166           8 :                     if (rCxt.mnColDelta && rCxt.maRange.aStart.Row() <= aAbs.aStart.Row() && aAbs.aEnd.Row() <= rCxt.maRange.aEnd.Row())
    3167             :                     {
    3168           0 :                         if (adjustDoubleRefInName(rRef, rCxt, rPos))
    3169           0 :                             aRes.mbReferenceModified = true;
    3170             :                     }
    3171           8 :                     if (rCxt.mnRowDelta && rCxt.maRange.aStart.Col() <= aAbs.aStart.Col() && aAbs.aEnd.Col() <= rCxt.maRange.aEnd.Col())
    3172             :                     {
    3173           4 :                         if (adjustDoubleRefInName(rRef, rCxt, rPos))
    3174           4 :                             aRes.mbReferenceModified = true;
    3175             :                     }
    3176             :                 }
    3177          20 :                 else if (rCxt.mnRowDelta > 0 && rCxt.mrDoc.IsExpandRefs())
    3178             :                 {
    3179             :                     // Check if we could expand range reference by the bottom
    3180             :                     // edge. For named expressions, we only expand absolute
    3181             :                     // references.
    3182           4 :                     if (!rRef.Ref1.IsRowRel() && !rRef.Ref2.IsRowRel() && aAbs.aEnd.Row()+1 == rCxt.maRange.aStart.Row())
    3183             :                     {
    3184             :                         // Expand by the bottom edge.
    3185           4 :                         rRef.Ref2.IncRow(rCxt.mnRowDelta);
    3186           4 :                         aRes.mbReferenceModified = true;
    3187             :                     }
    3188             :                 }
    3189             :             }
    3190          40 :             break;
    3191             :             default:
    3192             :                 ;
    3193             :         }
    3194             :     }
    3195             : 
    3196          46 :     return aRes;
    3197             : }
    3198             : 
    3199          16 : sc::RefUpdateResult ScTokenArray::AdjustReferenceInMovedName( const sc::RefUpdateContext& rCxt, const ScAddress& rPos )
    3200             : {
    3201             :     // When moving, the range is the destination range.
    3202          16 :     ScRange aOldRange = rCxt.maRange;
    3203          16 :     aOldRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
    3204             : 
    3205             :     // In a named expression, we'll move the reference only when the reference
    3206             :     // is entirely absolute.
    3207             : 
    3208          16 :     sc::RefUpdateResult aRes;
    3209             : 
    3210          16 :     FormulaToken** p = pCode;
    3211          16 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    3212          36 :     for (; p != pEnd; ++p)
    3213             :     {
    3214          20 :         switch ((*p)->GetType())
    3215             :         {
    3216             :             case svSingleRef:
    3217             :             {
    3218           2 :                 formula::FormulaToken* pToken = *p;
    3219           2 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    3220           2 :                 if (rRef.IsColRel() || rRef.IsRowRel() || rRef.IsTabRel())
    3221           0 :                     continue;
    3222             : 
    3223           2 :                 ScAddress aAbs = rRef.toAbs(rPos);
    3224           2 :                 if (aOldRange.In(aAbs))
    3225             :                 {
    3226           2 :                     aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
    3227           2 :                     aRes.mbReferenceModified = true;
    3228             :                 }
    3229             : 
    3230           2 :                 rRef.SetAddress(aAbs, rPos);
    3231             :             }
    3232           2 :             break;
    3233             :             case svDoubleRef:
    3234             :             {
    3235          16 :                 formula::FormulaToken* pToken = *p;
    3236          16 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    3237          64 :                 if (rRef.Ref1.IsColRel() || rRef.Ref1.IsRowRel() || rRef.Ref1.IsTabRel() ||
    3238          48 :                     rRef.Ref2.IsColRel() || rRef.Ref2.IsRowRel() || rRef.Ref2.IsTabRel())
    3239           0 :                     continue;
    3240             : 
    3241          16 :                 ScRange aAbs = rRef.toAbs(rPos);
    3242          16 :                 if (aOldRange.In(aAbs))
    3243             :                 {
    3244          10 :                     aAbs.Move(rCxt.mnColDelta, rCxt.mnRowDelta, rCxt.mnTabDelta);
    3245          10 :                     aRes.mbReferenceModified = true;
    3246             :                 }
    3247             : 
    3248          16 :                 rRef.SetRange(aAbs, rPos);
    3249             :             }
    3250          16 :             break;
    3251             :             default:
    3252             :                 ;
    3253             :         }
    3254             :     }
    3255             : 
    3256          16 :     return aRes;
    3257             : }
    3258             : 
    3259             : namespace {
    3260             : 
    3261         340 : bool adjustSingleRefOnDeletedTab( ScSingleRefData& rRef, SCTAB nDelPos, SCTAB nSheets, const ScAddress& rOldPos, const ScAddress& rNewPos )
    3262             : {
    3263         340 :     ScAddress aAbs = rRef.toAbs(rOldPos);
    3264         340 :     if (nDelPos <= aAbs.Tab() && aAbs.Tab() < nDelPos + nSheets)
    3265             :     {
    3266          80 :         rRef.SetTabDeleted(true);
    3267          80 :         return true;
    3268             :     }
    3269             : 
    3270         260 :     if (nDelPos < aAbs.Tab())
    3271             :     {
    3272             :         // Reference sheet needs to be adjusted.
    3273          74 :         aAbs.IncTab(-1*nSheets);
    3274          74 :         rRef.SetAddress(aAbs, rNewPos);
    3275          74 :         return true;
    3276             :     }
    3277         186 :     else if (rOldPos.Tab() != rNewPos.Tab())
    3278             :     {
    3279             :         // Cell itself has moved.
    3280           8 :         rRef.SetAddress(aAbs, rNewPos);
    3281           8 :         return true;
    3282             :     }
    3283             : 
    3284         178 :     return false;
    3285             : }
    3286             : 
    3287         330 : bool adjustSingleRefOnInsertedTab( ScSingleRefData& rRef, SCTAB nInsPos, SCTAB nSheets, const ScAddress& rOldPos, const ScAddress& rNewPos )
    3288             : {
    3289         330 :     ScAddress aAbs = rRef.toAbs(rOldPos);
    3290         330 :     if (nInsPos <= aAbs.Tab())
    3291             :     {
    3292             :         // Reference sheet needs to be adjusted.
    3293         320 :         aAbs.IncTab(nSheets);
    3294         320 :         rRef.SetAddress(aAbs, rNewPos);
    3295         320 :         return true;
    3296             :     }
    3297          10 :     else if (rOldPos.Tab() != rNewPos.Tab())
    3298             :     {
    3299             :         // Cell itself has moved.
    3300           8 :         rRef.SetAddress(aAbs, rNewPos);
    3301           8 :         return true;
    3302             :     }
    3303             : 
    3304           2 :     return false;
    3305             : }
    3306             : 
    3307             : }
    3308             : 
    3309         268 : sc::RefUpdateResult ScTokenArray::AdjustReferenceOnDeletedTab( sc::RefUpdateDeleteTabContext& rCxt, const ScAddress& rOldPos )
    3310             : {
    3311         268 :     sc::RefUpdateResult aRes;
    3312         268 :     ScAddress aNewPos = rOldPos;
    3313         268 :     if (rCxt.mnDeletePos < rOldPos.Tab())
    3314          50 :         aNewPos.IncTab(-1*rCxt.mnSheets);
    3315             : 
    3316         268 :     FormulaToken** p = pCode;
    3317         268 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    3318         888 :     for (; p != pEnd; ++p)
    3319             :     {
    3320         620 :         switch ((*p)->GetType())
    3321             :         {
    3322             :             case svSingleRef:
    3323             :             {
    3324         244 :                 formula::FormulaToken* pToken = *p;
    3325         244 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    3326         244 :                 if (adjustSingleRefOnDeletedTab(rRef, rCxt.mnDeletePos, rCxt.mnSheets, rOldPos, aNewPos))
    3327         130 :                     aRes.mbReferenceModified = true;
    3328             :             }
    3329         244 :             break;
    3330             :             case svDoubleRef:
    3331             :             {
    3332          48 :                 formula::FormulaToken* pToken = *p;
    3333          48 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    3334          48 :                 if (adjustSingleRefOnDeletedTab(rRef.Ref1, rCxt.mnDeletePos, rCxt.mnSheets, rOldPos, aNewPos))
    3335          16 :                     aRes.mbReferenceModified = true;
    3336          48 :                 if (adjustSingleRefOnDeletedTab(rRef.Ref2, rCxt.mnDeletePos, rCxt.mnSheets, rOldPos, aNewPos))
    3337          16 :                     aRes.mbReferenceModified = true;
    3338             :             }
    3339          48 :             break;
    3340             :             case svIndex:
    3341             :             {
    3342          22 :                 if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p))
    3343          10 :                     aRes.mbNameModified = true;
    3344             :             }
    3345          22 :             break;
    3346             :             default:
    3347             :                 ;
    3348             :         }
    3349             :     }
    3350         268 :     return aRes;
    3351             : }
    3352             : 
    3353         600 : sc::RefUpdateResult ScTokenArray::AdjustReferenceOnInsertedTab( sc::RefUpdateInsertTabContext& rCxt, const ScAddress& rOldPos )
    3354             : {
    3355         600 :     sc::RefUpdateResult aRes;
    3356         600 :     ScAddress aNewPos = rOldPos;
    3357         600 :     if (rCxt.mnInsertPos <= rOldPos.Tab())
    3358         598 :         aNewPos.IncTab(rCxt.mnSheets);
    3359             : 
    3360         600 :     FormulaToken** p = pCode;
    3361         600 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    3362        1434 :     for (; p != pEnd; ++p)
    3363             :     {
    3364         834 :         switch ((*p)->GetType())
    3365             :         {
    3366             :             case svSingleRef:
    3367             :             {
    3368         310 :                 formula::FormulaToken* pToken = *p;
    3369         310 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    3370         310 :                 if (adjustSingleRefOnInsertedTab(rRef, rCxt.mnInsertPos, rCxt.mnSheets, rOldPos, aNewPos))
    3371         308 :                     aRes.mbReferenceModified = true;
    3372             :             }
    3373         310 :             break;
    3374             :             case svDoubleRef:
    3375             :             {
    3376          10 :                 formula::FormulaToken* pToken = *p;
    3377          10 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    3378          10 :                 if (adjustSingleRefOnInsertedTab(rRef.Ref1, rCxt.mnInsertPos, rCxt.mnSheets, rOldPos, aNewPos))
    3379          10 :                     aRes.mbReferenceModified = true;
    3380          10 :                 if (adjustSingleRefOnInsertedTab(rRef.Ref2, rCxt.mnInsertPos, rCxt.mnSheets, rOldPos, aNewPos))
    3381          10 :                     aRes.mbReferenceModified = true;
    3382             :             }
    3383          10 :             break;
    3384             :             case svIndex:
    3385             :             {
    3386         364 :                 if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p))
    3387         364 :                     aRes.mbNameModified = true;
    3388             :             }
    3389         364 :             break;
    3390             :             default:
    3391             :                 ;
    3392             :         }
    3393             :     }
    3394         600 :     return aRes;
    3395             : }
    3396             : 
    3397             : namespace {
    3398             : 
    3399         106 : bool adjustTabOnMove( ScAddress& rPos, sc::RefUpdateMoveTabContext& rCxt )
    3400             : {
    3401         106 :     SCTAB nNewTab = rCxt.getNewTab(rPos.Tab());
    3402         106 :     if (nNewTab == rPos.Tab())
    3403          40 :         return false;
    3404             : 
    3405          66 :     rPos.SetTab(nNewTab);
    3406          66 :     return true;
    3407             : }
    3408             : 
    3409             : }
    3410             : 
    3411          36 : sc::RefUpdateResult ScTokenArray::AdjustReferenceOnMovedTab( sc::RefUpdateMoveTabContext& rCxt, const ScAddress& rOldPos )
    3412             : {
    3413          36 :     sc::RefUpdateResult aRes;
    3414          36 :     if (rCxt.mnOldPos == rCxt.mnNewPos)
    3415           0 :         return aRes;
    3416             : 
    3417          36 :     ScAddress aNewPos = rOldPos;
    3418          36 :     if (adjustTabOnMove(aNewPos, rCxt))
    3419          28 :         aRes.mbReferenceModified = true;
    3420             : 
    3421          36 :     FormulaToken** p = pCode;
    3422          36 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    3423         168 :     for (; p != pEnd; ++p)
    3424             :     {
    3425         132 :         switch ((*p)->GetType())
    3426             :         {
    3427             :             case svSingleRef:
    3428             :             {
    3429           2 :                 formula::FormulaToken* pToken = *p;
    3430           2 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    3431           2 :                 ScAddress aAbs = rRef.toAbs(rOldPos);
    3432           2 :                 if (adjustTabOnMove(aAbs, rCxt))
    3433           2 :                     aRes.mbReferenceModified = true;
    3434           2 :                 rRef.SetAddress(aAbs, aNewPos);
    3435             :             }
    3436           2 :             break;
    3437             :             case svDoubleRef:
    3438             :             {
    3439          34 :                 formula::FormulaToken* pToken = *p;
    3440          34 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    3441          34 :                 ScRange aAbs = rRef.toAbs(rOldPos);
    3442          34 :                 if (adjustTabOnMove(aAbs.aStart, rCxt))
    3443          18 :                     aRes.mbReferenceModified = true;
    3444          34 :                 if (adjustTabOnMove(aAbs.aEnd, rCxt))
    3445          18 :                     aRes.mbReferenceModified = true;
    3446          34 :                 rRef.SetRange(aAbs, aNewPos);
    3447             :             }
    3448          34 :             break;
    3449             :             case svIndex:
    3450             :             {
    3451           0 :                 if (isNameModified(rCxt.maUpdatedNames, rOldPos.Tab(), **p))
    3452           0 :                     aRes.mbNameModified = true;
    3453             :             }
    3454           0 :             break;
    3455             :             default:
    3456             :                 ;
    3457             :         }
    3458             :     }
    3459             : 
    3460          36 :     return aRes;
    3461             : }
    3462             : 
    3463         344 : void ScTokenArray::AdjustReferenceOnMovedOrigin( const ScAddress& rOldPos, const ScAddress& rNewPos )
    3464             : {
    3465         344 :     FormulaToken** p = pCode;
    3466         344 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    3467         962 :     for (; p != pEnd; ++p)
    3468             :     {
    3469         618 :         switch ((*p)->GetType())
    3470             :         {
    3471             :             case svSingleRef:
    3472             :             case svExternalSingleRef:
    3473             :             {
    3474         312 :                 formula::FormulaToken* pToken = *p;
    3475         312 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    3476         312 :                 ScAddress aAbs = rRef.toAbs(rOldPos);
    3477         312 :                 rRef.SetAddress(aAbs, rNewPos);
    3478             :             }
    3479         312 :             break;
    3480             :             case svDoubleRef:
    3481             :             case svExternalDoubleRef:
    3482             :             {
    3483          40 :                 formula::FormulaToken* pToken = *p;
    3484          40 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    3485          40 :                 ScRange aAbs = rRef.toAbs(rOldPos);
    3486          40 :                 rRef.SetRange(aAbs, rNewPos);
    3487             :             }
    3488          40 :             break;
    3489             :             default:
    3490             :                 ;
    3491             :         }
    3492             :     }
    3493         344 : }
    3494             : 
    3495             : namespace {
    3496             : 
    3497           2 : void clearTabDeletedFlag( ScSingleRefData& rRef, const ScAddress& rPos, SCTAB nStartTab, SCTAB nEndTab )
    3498             : {
    3499           2 :     if (!rRef.IsTabDeleted())
    3500           2 :         return;
    3501             : 
    3502           2 :     ScAddress aAbs = rRef.toAbs(rPos);
    3503           2 :     if (nStartTab <=  aAbs.Tab() && aAbs.Tab() <= nEndTab)
    3504           2 :         rRef.SetTabDeleted(false);
    3505             : }
    3506             : 
    3507             : }
    3508             : 
    3509           2 : void ScTokenArray::ClearTabDeleted( const ScAddress& rPos, SCTAB nStartTab, SCTAB nEndTab )
    3510             : {
    3511           2 :     if (nEndTab < nStartTab)
    3512           2 :         return;
    3513             : 
    3514           2 :     FormulaToken** p = pCode;
    3515           2 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    3516           4 :     for (; p != pEnd; ++p)
    3517             :     {
    3518           2 :         switch ((*p)->GetType())
    3519             :         {
    3520             :             case svSingleRef:
    3521             :             {
    3522           2 :                 formula::FormulaToken* pToken = *p;
    3523           2 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    3524           2 :                 clearTabDeletedFlag(rRef, rPos, nStartTab, nEndTab);
    3525             :             }
    3526           2 :             break;
    3527             :             case svDoubleRef:
    3528             :             {
    3529           0 :                 formula::FormulaToken* pToken = *p;
    3530           0 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    3531           0 :                 clearTabDeletedFlag(rRef.Ref1, rPos, nStartTab, nEndTab);
    3532           0 :                 clearTabDeletedFlag(rRef.Ref2, rPos, nStartTab, nEndTab);
    3533             :             }
    3534           0 :             break;
    3535             :             default:
    3536             :                 ;
    3537             :         }
    3538             :     }
    3539             : }
    3540             : 
    3541             : namespace {
    3542             : 
    3543          78 : void checkBounds(
    3544             :     const ScAddress& rPos, SCROW nGroupLen, const ScRange& rCheckRange,
    3545             :     const ScSingleRefData& rRef, std::vector<SCROW>& rBounds )
    3546             : {
    3547          78 :     if (!rRef.IsRowRel())
    3548          28 :         return;
    3549             : 
    3550          78 :     ScRange aAbs(rRef.toAbs(rPos));
    3551          78 :     aAbs.aEnd.IncRow(nGroupLen-1);
    3552          78 :     if (!rCheckRange.Intersects(aAbs))
    3553          28 :         return;
    3554             : 
    3555             :     // Get the boundary row positions.
    3556          50 :     if (aAbs.aEnd.Row() < rCheckRange.aStart.Row())
    3557             :         // No intersections.
    3558           0 :         return;
    3559             : 
    3560          50 :     if (aAbs.aStart.Row() <= rCheckRange.aStart.Row())
    3561             :     {
    3562             :         //    +-+ <---- top
    3563             :         //    | |
    3564             :         // +--+-+--+ <---- boundary row position
    3565             :         // |  | |  |
    3566             :         // |       |
    3567             :         // +-------+
    3568             : 
    3569             :         // Add offset from the reference top to the cell position.
    3570          28 :         SCROW nOffset = rCheckRange.aStart.Row() - aAbs.aStart.Row();
    3571          28 :         rBounds.push_back(rPos.Row()+nOffset);
    3572             :     }
    3573             : 
    3574          50 :     if (aAbs.aEnd.Row() >= rCheckRange.aEnd.Row())
    3575             :     {
    3576             :         // only check for end range
    3577             : 
    3578             :         // +-------+
    3579             :         // |       |
    3580             :         // |  | |  |
    3581             :         // +--+-+--+ <---- boundary row position
    3582             :         //    | |
    3583             :         //    +-+
    3584             : 
    3585             :         // Ditto.
    3586          16 :         SCROW nOffset = rCheckRange.aEnd.Row() + 1 - aAbs.aStart.Row();
    3587          16 :         rBounds.push_back(rPos.Row()+nOffset);
    3588             :     }
    3589             : }
    3590             : 
    3591          86 : void checkBounds(
    3592             :     const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen,
    3593             :     const ScSingleRefData& rRef, std::vector<SCROW>& rBounds)
    3594             : {
    3595          86 :     if (!rRef.IsRowRel())
    3596          98 :         return;
    3597             : 
    3598          74 :     ScRange aCheckRange = rCxt.maRange;
    3599          74 :     if (rCxt.meMode == URM_MOVE)
    3600             :         // Check bounds against the old range prior to the move.
    3601          10 :         aCheckRange.Move(-rCxt.mnColDelta, -rCxt.mnRowDelta, -rCxt.mnTabDelta);
    3602             : 
    3603          74 :     checkBounds(rPos, nGroupLen, aCheckRange, rRef, rBounds);
    3604             : }
    3605             : 
    3606             : }
    3607             : 
    3608          90 : void ScTokenArray::CheckRelativeReferenceBounds(
    3609             :     const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const
    3610             : {
    3611          90 :     FormulaToken** p = pCode;
    3612          90 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    3613         256 :     for (; p != pEnd; ++p)
    3614             :     {
    3615         166 :         switch ((*p)->GetType())
    3616             :         {
    3617             :             case svSingleRef:
    3618             :             {
    3619          82 :                 formula::FormulaToken* pToken = *p;
    3620          82 :                 checkBounds(rCxt, rPos, nGroupLen, *pToken->GetSingleRef(), rBounds);
    3621             :             }
    3622          82 :             break;
    3623             :             case svDoubleRef:
    3624             :             {
    3625           2 :                 formula::FormulaToken* pToken = *p;
    3626           2 :                 const ScComplexRefData& rRef = *pToken->GetDoubleRef();
    3627           2 :                 checkBounds(rCxt, rPos, nGroupLen, rRef.Ref1, rBounds);
    3628           2 :                 checkBounds(rCxt, rPos, nGroupLen, rRef.Ref2, rBounds);
    3629             :             }
    3630           2 :             break;
    3631             :             default:
    3632             :                 ;
    3633             :         }
    3634             :     }
    3635          90 : }
    3636             : 
    3637           2 : void ScTokenArray::CheckRelativeReferenceBounds(
    3638             :     const ScAddress& rPos, SCROW nGroupLen, const ScRange& rRange, std::vector<SCROW>& rBounds ) const
    3639             : {
    3640           2 :     FormulaToken** p = pCode;
    3641           2 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    3642          18 :     for (; p != pEnd; ++p)
    3643             :     {
    3644          16 :         switch ((*p)->GetType())
    3645             :         {
    3646             :             case svSingleRef:
    3647             :             {
    3648           4 :                 formula::FormulaToken* pToken = *p;
    3649           4 :                 const ScSingleRefData& rRef = *pToken->GetSingleRef();
    3650           4 :                 checkBounds(rPos, nGroupLen, rRange, rRef, rBounds);
    3651             :             }
    3652           4 :             break;
    3653             :             case svDoubleRef:
    3654             :             {
    3655           0 :                 formula::FormulaToken* pToken = *p;
    3656           0 :                 const ScComplexRefData& rRef = *pToken->GetDoubleRef();
    3657           0 :                 checkBounds(rPos, nGroupLen, rRange, rRef.Ref1, rBounds);
    3658           0 :                 checkBounds(rPos, nGroupLen, rRange, rRef.Ref2, rBounds);
    3659             :             }
    3660           0 :             break;
    3661             :             default:
    3662             :                 ;
    3663             :         }
    3664             :     }
    3665           2 : }
    3666             : 
    3667             : namespace {
    3668             : 
    3669        1748 : void appendDouble( sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, double fVal )
    3670             : {
    3671        1748 :     if (rCxt.mxOpCodeMap->isEnglish())
    3672             :     {
    3673             :         rtl::math::doubleToUStringBuffer(
    3674        1748 :             rBuf, fVal, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
    3675             :     }
    3676             :     else
    3677             :     {
    3678           0 :         SvtSysLocale aSysLocale;
    3679             :         rtl::math::doubleToUStringBuffer(
    3680             :             rBuf, fVal,
    3681             :             rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max,
    3682           0 :             aSysLocale.GetLocaleDataPtr()->getNumDecimalSep()[0], true);
    3683             :     }
    3684        1748 : }
    3685             : 
    3686          16 : void appendString( OUStringBuffer& rBuf, const OUString& rStr )
    3687             : {
    3688          16 :     rBuf.append('"');
    3689          16 :     rBuf.append(rStr.replaceAll("\"", "\"\""));
    3690          16 :     rBuf.append('"');
    3691          16 : }
    3692             : 
    3693       17140 : void appendTokenByType( sc::TokenStringContext& rCxt, OUStringBuffer& rBuf, const FormulaToken& rToken, const ScAddress& rPos )
    3694             : {
    3695       17140 :     if (rToken.IsExternalRef())
    3696             :     {
    3697           6 :         size_t nFileId = rToken.GetIndex();
    3698           6 :         OUString aTabName = rToken.GetString().getString();
    3699           6 :         if (nFileId >= rCxt.maExternalFileNames.size())
    3700             :             // out of bound
    3701           0 :             return;
    3702             : 
    3703          12 :         OUString aFileName = rCxt.maExternalFileNames[nFileId];
    3704             : 
    3705           6 :         switch (rToken.GetType())
    3706             :         {
    3707             :             case svExternalName:
    3708           0 :                 rBuf.append(rCxt.mpRefConv->makeExternalNameStr(nFileId, aFileName, aTabName));
    3709           0 :             break;
    3710             :             case svExternalSingleRef:
    3711             :                 rCxt.mpRefConv->makeExternalRefStr(
    3712           6 :                        rBuf, rPos, nFileId, aFileName, aTabName, *rToken.GetSingleRef());
    3713           6 :             break;
    3714             :             case svExternalDoubleRef:
    3715             :             {
    3716             :                 sc::TokenStringContext::IndexNamesMapType::const_iterator it =
    3717           0 :                     rCxt.maExternalCachedTabNames.find(nFileId);
    3718             : 
    3719           0 :                 if (it == rCxt.maExternalCachedTabNames.end())
    3720           0 :                     return;
    3721             : 
    3722             :                 rCxt.mpRefConv->makeExternalRefStr(
    3723           0 :                         rBuf, rPos, nFileId, aFileName, it->second, aTabName,
    3724           0 :                         *rToken.GetDoubleRef());
    3725             :             }
    3726           0 :             break;
    3727             :             default:
    3728             :                 // warning, not error, otherwise we may end up with a never
    3729             :                 // ending message box loop if this was the cursor cell to be redrawn.
    3730             :                 OSL_FAIL("appendTokenByType: unknown type of ocExternalRef");
    3731             :         }
    3732          12 :         return;
    3733             :     }
    3734             : 
    3735       17134 :     OpCode eOp = rToken.GetOpCode();
    3736       17134 :     switch (rToken.GetType())
    3737             :     {
    3738             :         case svDouble:
    3739        1748 :             appendDouble(rCxt, rBuf, rToken.GetDouble());
    3740        1748 :         break;
    3741             :         case svString:
    3742             :         {
    3743          16 :             OUString aStr = rToken.GetString().getString();
    3744          16 :             if (eOp == ocBad || eOp == ocStringXML)
    3745             :             {
    3746           0 :                 rBuf.append(aStr);
    3747           0 :                 return;
    3748             :             }
    3749             : 
    3750          16 :             appendString(rBuf, aStr);
    3751             :         }
    3752          16 :         break;
    3753             :         case svSingleRef:
    3754             :         {
    3755        3518 :             if (rCxt.mpRefConv)
    3756             :             {
    3757        3518 :                 const ScSingleRefData& rRef = *rToken.GetSingleRef();
    3758             :                 ScComplexRefData aRef;
    3759        3518 :                 aRef.Ref1 = rRef;
    3760        3518 :                 aRef.Ref2 = rRef;
    3761        3518 :                 rCxt.mpRefConv->makeRefStr(rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, aRef, true);
    3762             :             }
    3763             :             else
    3764           0 :                 rBuf.append(rCxt.maErrRef);
    3765             :         }
    3766        3518 :         break;
    3767             :         case svDoubleRef:
    3768             :         {
    3769         912 :             if (rCxt.mpRefConv)
    3770             :             {
    3771         912 :                 const ScComplexRefData& rRef = *rToken.GetDoubleRef();
    3772         912 :                 rCxt.mpRefConv->makeRefStr(rBuf, rCxt.meGram, rPos, rCxt.maErrRef, rCxt.maTabNames, rRef, false);
    3773             :             }
    3774             :             else
    3775           0 :                 rBuf.append(rCxt.maErrRef);
    3776             :         }
    3777         912 :         break;
    3778             :         case svMatrix:
    3779             :         {
    3780           0 :             const ScMatrix* pMat = rToken.GetMatrix();
    3781           0 :             if (!pMat)
    3782           0 :                 return;
    3783             : 
    3784             :             size_t nC, nMaxC, nR, nMaxR;
    3785           0 :             pMat->GetDimensions(nMaxC, nMaxR);
    3786             : 
    3787           0 :             rBuf.append(rCxt.mxOpCodeMap->getSymbol(ocArrayOpen));
    3788           0 :             for (nR = 0 ; nR < nMaxR ; ++nR)
    3789             :             {
    3790           0 :                 if (nR > 0)
    3791             :                 {
    3792           0 :                     rBuf.append(rCxt.mxOpCodeMap->getSymbol(ocArrayRowSep));
    3793             :                 }
    3794             : 
    3795           0 :                 for (nC = 0 ; nC < nMaxC ; ++nC)
    3796             :                 {
    3797           0 :                     if (nC > 0)
    3798             :                     {
    3799           0 :                         rBuf.append(rCxt.mxOpCodeMap->getSymbol(ocArrayColSep));
    3800             :                     }
    3801             : 
    3802           0 :                     if (pMat->IsValue(nC, nR))
    3803             :                     {
    3804           0 :                         if (pMat->IsBoolean(nC, nR))
    3805             :                         {
    3806           0 :                             bool bVal = pMat->GetDouble(nC, nR) != 0.0;
    3807           0 :                             rBuf.append(rCxt.mxOpCodeMap->getSymbol(bVal ? ocTrue : ocFalse));
    3808             :                         }
    3809             :                         else
    3810             :                         {
    3811           0 :                             sal_uInt16 nErr = pMat->GetError(nC, nR);
    3812           0 :                             if (nErr)
    3813           0 :                                 rBuf.append(ScGlobal::GetErrorString(nErr));
    3814             :                             else
    3815           0 :                                 appendDouble(rCxt, rBuf, pMat->GetDouble(nC, nR));
    3816             :                         }
    3817             :                     }
    3818           0 :                     else if (pMat->IsEmpty(nC, nR))
    3819             :                     {
    3820             :                         // Skip it.
    3821             :                     }
    3822           0 :                     else if (pMat->IsString(nC, nR))
    3823           0 :                         appendString(rBuf, pMat->GetString(nC, nR).getString());
    3824             :                 }
    3825             :             }
    3826           0 :             rBuf.append(rCxt.mxOpCodeMap->getSymbol(ocArrayClose));
    3827             :         }
    3828           0 :         break;
    3829             :         case svIndex:
    3830             :         {
    3831             :             typedef sc::TokenStringContext::IndexNameMapType NameType;
    3832             : 
    3833          12 :             sal_uInt16 nIndex = rToken.GetIndex();
    3834          12 :             switch (eOp)
    3835             :             {
    3836             :                 case ocName:
    3837             :                 {
    3838          12 :                     if (rToken.IsGlobal())
    3839             :                     {
    3840             :                         // global named range
    3841           6 :                         NameType::const_iterator it = rCxt.maGlobalRangeNames.find(nIndex);
    3842           6 :                         if (it == rCxt.maGlobalRangeNames.end())
    3843             :                         {
    3844           0 :                             rBuf.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
    3845           0 :                             break;
    3846             :                         }
    3847             : 
    3848           6 :                         rBuf.append(it->second);
    3849             :                     }
    3850             :                     else
    3851             :                     {
    3852             :                         // sheet-local named range
    3853           6 :                         sc::TokenStringContext::TabIndexMapType::const_iterator itTab = rCxt.maSheetRangeNames.find(rPos.Tab());
    3854           6 :                         if (itTab == rCxt.maSheetRangeNames.end())
    3855             :                         {
    3856           0 :                             rBuf.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
    3857           0 :                             break;
    3858             :                         }
    3859             : 
    3860           6 :                         const NameType& rNames = itTab->second;
    3861           6 :                         NameType::const_iterator it = rNames.find(nIndex);
    3862           6 :                         if (it == rNames.end())
    3863             :                         {
    3864           0 :                             rBuf.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
    3865           0 :                             break;
    3866             :                         }
    3867             : 
    3868           6 :                         rBuf.append(it->second);
    3869             :                     }
    3870             :                 }
    3871          12 :                 break;
    3872             :                 case ocDBArea:
    3873             :                 {
    3874           0 :                     NameType::const_iterator it = rCxt.maNamedDBs.find(nIndex);
    3875           0 :                     if (it != rCxt.maNamedDBs.end())
    3876           0 :                         rBuf.append(it->second);
    3877             :                 }
    3878           0 :                 break;
    3879             :                 default:
    3880           0 :                     rBuf.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
    3881             :             }
    3882             :         }
    3883          12 :         break;
    3884             :         case svExternal:
    3885             :         {
    3886             :             // mapped or translated name of AddIns
    3887           0 :             OUString aAddIn = rToken.GetExternal();
    3888           0 :             bool bMapped = rCxt.mxOpCodeMap->isPODF();     // ODF 1.1 directly uses programmatical name
    3889           0 :             if (!bMapped && rCxt.mxOpCodeMap->hasExternals())
    3890             :             {
    3891           0 :                 const ExternalHashMap& rExtMap = *rCxt.mxOpCodeMap->getReverseExternalHashMap();
    3892           0 :                 ExternalHashMap::const_iterator it = rExtMap.find(aAddIn);
    3893           0 :                 if (it != rExtMap.end())
    3894             :                 {
    3895           0 :                     aAddIn = it->second;
    3896           0 :                     bMapped = true;
    3897             :                 }
    3898             :             }
    3899             : 
    3900           0 :             if (!bMapped && !rCxt.mxOpCodeMap->isEnglish())
    3901           0 :                 ScGlobal::GetAddInCollection()->LocalizeString(aAddIn);
    3902             : 
    3903           0 :             rBuf.append(aAddIn);
    3904             :         }
    3905           0 :         break;
    3906             :         case svError:
    3907             :         {
    3908           0 :             sal_uInt16 nErr = rToken.GetError();
    3909             :             OpCode eOpErr;
    3910           0 :             switch (nErr)
    3911             :             {
    3912             :                 break;
    3913             :                 case errDivisionByZero:
    3914           0 :                     eOpErr = ocErrDivZero;
    3915           0 :                 break;
    3916             :                 case errNoValue:
    3917           0 :                     eOpErr = ocErrValue;
    3918           0 :                 break;
    3919             :                 case errNoRef:
    3920           0 :                     eOpErr = ocErrRef;
    3921           0 :                 break;
    3922             :                 case errNoName:
    3923           0 :                     eOpErr = ocErrName;
    3924           0 :                 break;
    3925             :                 case errIllegalFPOperation:
    3926           0 :                     eOpErr = ocErrNum;
    3927           0 :                 break;
    3928             :                 case NOTAVAILABLE:
    3929           0 :                     eOpErr = ocErrNA;
    3930           0 :                 break;
    3931             :                 case errNoCode:
    3932             :                 default:
    3933           0 :                     eOpErr = ocErrNull;
    3934             :             }
    3935           0 :             rBuf.append(rCxt.mxOpCodeMap->getSymbol(eOpErr));
    3936             :         }
    3937           0 :         break;
    3938             :         case svByte:
    3939             :         case svJump:
    3940             :         case svFAP:
    3941             :         case svMissing:
    3942             :         case svSep:
    3943             :         default:
    3944             :             ;
    3945             :     }
    3946             : }
    3947             : 
    3948             : }
    3949             : 
    3950        1982 : OUString ScTokenArray::CreateString( sc::TokenStringContext& rCxt, const ScAddress& rPos ) const
    3951             : {
    3952        1982 :     if (!nLen)
    3953           0 :         return OUString();
    3954             : 
    3955        1982 :     OUStringBuffer aBuf;
    3956             : 
    3957        1982 :     FormulaToken** p = pCode;
    3958        1982 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    3959       19756 :     for (; p != pEnd; ++p)
    3960             :     {
    3961       17774 :         const FormulaToken* pToken = *p;
    3962       17774 :         OpCode eOp = pToken->GetOpCode();
    3963       17774 :         bool bCheckType = true;
    3964       17774 :         if (eOp == ocSpaces)
    3965             :         {
    3966             :             // TODO : Handle intersection operator '!!'.
    3967         634 :             aBuf.append(' ');
    3968         634 :             continue;
    3969             :         }
    3970             : 
    3971       17140 :         if (eOp < rCxt.mxOpCodeMap->getSymbolCount())
    3972       17140 :             aBuf.append(rCxt.mxOpCodeMap->getSymbol(eOp));
    3973             : 
    3974       17140 :         if (bCheckType)
    3975       17140 :             appendTokenByType(rCxt, aBuf, *pToken, rPos);
    3976             :     }
    3977             : 
    3978        1982 :     return aBuf.makeStringAndClear();
    3979             : }
    3980             : 
    3981             : namespace {
    3982             : 
    3983       22214 : void wrapAddress( ScAddress& rPos, SCCOL nMaxCol, SCROW nMaxRow )
    3984             : {
    3985       22214 :     if (rPos.Col() > nMaxCol)
    3986        1452 :         rPos.SetCol(rPos.Col() - nMaxCol - 1);
    3987       22214 :     if (rPos.Row() > nMaxRow)
    3988           0 :         rPos.SetRow(rPos.Row() - nMaxRow - 1);
    3989       22214 : }
    3990             : 
    3991             : }
    3992             : 
    3993        6980 : void ScTokenArray::WrapReference( const ScAddress& rPos, SCCOL nMaxCol, SCROW nMaxRow )
    3994             : {
    3995        6980 :     FormulaToken** p = pCode;
    3996        6980 :     FormulaToken** pEnd = p + static_cast<size_t>(nLen);
    3997       80768 :     for (; p != pEnd; ++p)
    3998             :     {
    3999       73788 :         switch ((*p)->GetType())
    4000             :         {
    4001             :             case svSingleRef:
    4002             :             {
    4003       12810 :                 formula::FormulaToken* pToken = *p;
    4004       12810 :                 ScSingleRefData& rRef = *pToken->GetSingleRef();
    4005       12810 :                 ScAddress aAbs = rRef.toAbs(rPos);
    4006       12810 :                 wrapAddress(aAbs, nMaxCol, nMaxRow);
    4007       12810 :                 rRef.SetAddress(aAbs, rPos);
    4008             :             }
    4009       12810 :             break;
    4010             :             case svDoubleRef:
    4011             :             {
    4012        4702 :                 formula::FormulaToken* pToken = *p;
    4013        4702 :                 ScComplexRefData& rRef = *pToken->GetDoubleRef();
    4014        4702 :                 ScRange aAbs = rRef.toAbs(rPos);
    4015        4702 :                 wrapAddress(aAbs.aStart, nMaxCol, nMaxRow);
    4016        4702 :                 wrapAddress(aAbs.aEnd, nMaxCol, nMaxRow);
    4017        4702 :                 aAbs.PutInOrder();
    4018        4702 :                 rRef.SetRange(aAbs, rPos);
    4019             :             }
    4020        4702 :             break;
    4021             :             default:
    4022             :                 ;
    4023             :         }
    4024             :     }
    4025        7208 : }
    4026             : 
    4027             : #if DEBUG_FORMULA_COMPILER
    4028             : 
    4029             : void ScTokenArray::Dump() const
    4030             : {
    4031             :     cout << "+++ Normal Tokens +++" << endl;
    4032             :     for (sal_uInt16 i = 0; i < nLen; ++i)
    4033             :     {
    4034             :         DumpToken(*pCode[i]);
    4035             :     }
    4036             : 
    4037             :     cout << "+++ RPN Tokens +++" << endl;
    4038             :     for (sal_uInt16 i = 0; i < nRPN; ++i)
    4039             :     {
    4040             :         DumpToken(*pRPN[i]);
    4041             :     }
    4042             : }
    4043             : #endif
    4044             : 
    4045             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10