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

Generated by: LCOV version 1.11