Blob Blame History Raw
From 68e5de5b163a29637aeff243998a33e93feac432 Mon Sep 17 00:00:00 2001
Message-Id: <68e5de5b163a29637aeff243998a33e93feac432.1434660767.git.erack@redhat.com>
From: Eike Rathke <erack@redhat.com>
Date: Wed, 17 Jun 2015 17:12:49 +0200
Subject: [PATCH] Resolves: tdf#83365 push proper references in INDIRECT
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------erAck-patch-parts"

This is a multi-part message in MIME format.
--------------erAck-patch-parts
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit


... that take relative/absolute addressing and sheet 3D flag into
account to be fed to reference extension via range operator.

(cherry picked from commit fb6dd2a73074b9695bd8ddf7ba40f1819b03024e)

properly inherit relative and 3D flags when extending, tdf#83365 related

Commit 194e9f9bae28bdf22a9ed4779c1656ee693f3302 oversimplified things.

(cherry picked from commit e503addfbbe45efe1a3c06392c66fb79c3c72d07)

ea6a84c4a7be49af036690afbb1512ae2c1045a2

Conflicts:
	sc/inc/refdata.hxx
	sc/source/core/tool/refdata.cxx

Change-Id: Iabe13ae384577e2d71ca87af6482ddccbf7ad0ac
---
 sc/inc/refdata.hxx               |  5 +++
 sc/source/core/inc/interpre.hxx  |  2 ++
 sc/source/core/tool/interpr1.cxx |  5 ++-
 sc/source/core/tool/interpr4.cxx | 20 +++++++++++
 sc/source/core/tool/refdata.cxx  | 73 +++++++++++++++++++++++++++++++++++++++-
 5 files changed, 101 insertions(+), 4 deletions(-)


--------------erAck-patch-parts
Content-Type: text/x-patch; name="0001-Resolves-tdf-83365-push-proper-references-in-INDIREC.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0001-Resolves-tdf-83365-push-proper-references-in-INDIREC.patch"

diff --git a/sc/inc/refdata.hxx b/sc/inc/refdata.hxx
index 53a356c..4d1e790 100644
--- a/sc/inc/refdata.hxx
+++ b/sc/inc/refdata.hxx
@@ -57,6 +57,8 @@ public:
     void InitAddress( SCCOL nCol, SCROW nRow, SCTAB nTab );
     /// InitAddressRel: InitFlags and set address, everything relative to rPos
     void InitAddressRel( const ScAddress& rAdr, const ScAddress& rPos );
+    /// InitFlags and set address, relative to rPos if rRef says so.
+    void InitFromRefAddress( const ScRefAddress& rRef, const ScAddress& rPos );
     sal_uInt8 FlagValue() const;
 
     void SetColRel( bool bVal ) { Flags.bColRel = bVal; }
@@ -135,6 +137,9 @@ struct ScComplexRefData
             Ref2.InitAddress( nCol2, nRow2, nTab2 );
         }
 
+    /// InitFlags and set range, relative to rPos if rRef1 and rRef2 say so.
+    void InitFromRefAddresses( const ScRefAddress& rRef1, const ScRefAddress& rRef2, const ScAddress& rPos );
+
     bool Valid() const;
 
     /** In external references nTab is -1 for the start tab and -1 for the end
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 9122e0a..ede3e5c 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -332,6 +332,8 @@ void PushExternalSingleRef(sal_uInt16 nFileId, const OUString& rTabName,
 void PushExternalDoubleRef(sal_uInt16 nFileId, const OUString& rTabName,
                            SCCOL nCol1, SCROW nRow1, SCTAB nTab1,
                            SCCOL nCol2, SCROW nRow2, SCTAB nTab2);
+void PushSingleRef( const ScRefAddress& rRef );
+void PushDoubleRef( const ScRefAddress& rRef1, const ScRefAddress& rRef2 );
 void PushMatrix( const sc::RangeMatrix& rMat );
 void PushMatrix(const ScMatrixRef& pMat);
 void PushError( sal_uInt16 nError );
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 55917d7..c12fb39 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -7164,8 +7164,7 @@ void ScInterpreter::ScIndirect()
                     aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab());
             }
             else
-                PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(),
-                        aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() );
+                PushDoubleRef( aRefAd, aRefAd2);
         }
         else if (ConvertSingleRef(pDok, sRefStr, nTab, aRefAd, aDetails, &aExtInfo))
         {
@@ -7175,7 +7174,7 @@ void ScInterpreter::ScIndirect()
                     aExtInfo.mnFileId, aExtInfo.maTabName, aRefAd.Col(), aRefAd.Row(), aRefAd.Tab());
             }
             else
-                PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() );
+                PushSingleRef( aRefAd);
         }
         else
         {
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 473f40d..428fd9e 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -2002,6 +2002,26 @@ void ScInterpreter::PushExternalDoubleRef(
     }
 }
 
+void ScInterpreter::PushSingleRef( const ScRefAddress& rRef )
+{
+    if (!IfErrorPushError())
+    {
+        ScSingleRefData aRef;
+        aRef.InitFromRefAddress( rRef, aPos);
+        PushTempTokenWithoutError( new ScSingleRefToken( aRef ) );
+    }
+}
+
+void ScInterpreter::PushDoubleRef( const ScRefAddress& rRef1, const ScRefAddress& rRef2 )
+{
+    if (!IfErrorPushError())
+    {
+        ScComplexRefData aRef;
+        aRef.InitFromRefAddresses( rRef1, rRef2, aPos);
+        PushTempTokenWithoutError( new ScDoubleRefToken( aRef ) );
+    }
+}
+
 void ScInterpreter::PushMatrix( const sc::RangeMatrix& rMat )
 {
     if (!rMat.isRangeValid())
diff --git a/sc/source/core/tool/refdata.cxx b/sc/source/core/tool/refdata.cxx
index 9a5bb0c..7990df0 100644
--- a/sc/source/core/tool/refdata.cxx
+++ b/sc/source/core/tool/refdata.cxx
@@ -46,6 +46,16 @@ sal_uInt8 ScSingleRefData::FlagValue() const
     return mnFlagValue;
 }
 
+void ScSingleRefData::InitFromRefAddress( const ScRefAddress& rRef, const ScAddress& rPos )
+{
+    InitFlags();
+    SetColRel( rRef.IsRelCol());
+    SetRowRel( rRef.IsRelRow());
+    SetTabRel( rRef.IsRelTab());
+    SetFlag3D( rRef.Tab() != rPos.Tab());
+    SetAddress( rRef.GetAddress(), rPos);
+}
+
 void ScSingleRefData::SetAbsCol( SCCOL nVal )
 {
     Flags.bColRel = false;
@@ -277,10 +287,38 @@ void ScSingleRefData::Dump( int nIndent ) const
 }
 #endif
 
+void ScComplexRefData::InitFromRefAddresses( const ScRefAddress& rRef1, const ScRefAddress& rRef2, const ScAddress& rPos )
+{
+    InitFlags();
+    Ref1.SetColRel( rRef1.IsRelCol());
+    Ref1.SetRowRel( rRef1.IsRelRow());
+    Ref1.SetTabRel( rRef1.IsRelTab());
+    Ref1.SetFlag3D( rRef1.Tab() != rPos.Tab() || rRef1.Tab() != rRef2.Tab());
+    Ref2.SetColRel( rRef2.IsRelCol());
+    Ref2.SetRowRel( rRef2.IsRelRow());
+    Ref2.SetTabRel( rRef2.IsRelTab());
+    Ref2.SetFlag3D( rRef1.Tab() != rRef2.Tab());
+    SetRange( ScRange( rRef1.GetAddress(), rRef2.GetAddress()), rPos);
+}
+
 ScComplexRefData& ScComplexRefData::Extend( const ScSingleRefData & rRef, const ScAddress & rPos )
 {
+    bool bInherit3D = (Ref1.IsFlag3D() && !Ref2.IsFlag3D() && !rRef.IsFlag3D());
     ScRange aAbsRange = toAbs(rPos);
-    ScAddress aAbs = rRef.toAbs(rPos);
+
+    ScSingleRefData aRef = rRef;
+    // If no sheet was given in the extending part, let it point to the same
+    // sheet as this reference's end point, inheriting the absolute/relative
+    // mode.
+    // [$]Sheet1.A5:A6:A7 on Sheet2 do still reference only Sheet1.
+    if (!rRef.IsFlag3D())
+    {
+        if (Ref2.IsTabRel())
+            aRef.SetRelTab( Ref2.Tab());
+        else
+            aRef.SetAbsTab( Ref2.Tab());
+    }
+    ScAddress aAbs = aRef.toAbs(rPos);
 
     if (aAbs.Col() < aAbsRange.aStart.Col())
         aAbsRange.aStart.SetCol(aAbs.Col());
@@ -300,6 +338,39 @@ ScComplexRefData& ScComplexRefData::Extend( const ScSingleRefData & rRef, const
     if (aAbsRange.aEnd.Tab() < aAbs.Tab())
         aAbsRange.aEnd.SetTab(aAbs.Tab());
 
+    // In Ref2 inherit absolute/relative addressing from the extending part.
+    // A$5:A5 => A$5:A$5:A5 => A$5:A5, and not A$5:A$5
+    // A$6:$A5 => A$6:A$6:$A5 => A5:$A$6
+    if (aAbsRange.aEnd.Col() == aAbs.Col())
+        Ref2.SetColRel( rRef.IsColRel());
+    if (aAbsRange.aEnd.Row() == aAbs.Row())
+        Ref2.SetRowRel( rRef.IsRowRel());
+
+    // In Ref1 inherit relative sheet from extending part if given.
+    if (aAbsRange.aStart.Tab() == aAbs.Tab() && rRef.IsFlag3D())
+        Ref1.SetTabRel( rRef.IsTabRel());
+
+    // In Ref2 inherit relative sheet from either Ref1 or extending part.
+    // Use the original 3D flags to determine which.
+    // $Sheet1.$A$5:$A$6 => $Sheet1.$A$5:$A$5:$A$6 => $Sheet1.$A$5:$A$6, and
+    // not $Sheet1.$A$5:Sheet1.$A$6 (with invisible second 3D, but relative).
+    if (aAbsRange.aEnd.Tab() == aAbs.Tab())
+        Ref2.SetTabRel( bInherit3D ? Ref1.IsTabRel() : rRef.IsTabRel());
+
+    // Force 3D flag in Ref1 if different sheet or more than one sheet
+    // referenced.
+    if (aAbsRange.aStart.Tab() != rPos.Tab() || aAbsRange.aStart.Tab() != aAbsRange.aEnd.Tab())
+        Ref1.SetFlag3D(true);
+
+    // Force 3D flag in Ref2 if more than one sheet referenced.
+    if (aAbsRange.aStart.Tab() != aAbsRange.aEnd.Tab())
+        Ref2.SetFlag3D(true);
+
+    // Inherit 3D flag in Ref1 from extending part in case range wasn't
+    // extended as in A5:A5:Sheet1.A5 if on Sheet1.
+    if (rRef.IsFlag3D())
+        Ref1.SetFlag3D( true);
+
     SetRange(aAbsRange, rPos);
 
     return *this;

--------------erAck-patch-parts--