Resolves: tdf#154125 Fix INDEX() one-dimensional vector access

For i62850 a (not documented by Excel in
https://support.microsoft.com/en-us/office/index-function-a5dcf0dd-996d-40a4-a822-b56b061328bd?ui=en-us&rs=en-us&ad=us)
one-dimensional vector's element access was implemented with
non-sufficient conditions that prevented returning an entire
vector. Later ODFF defined proper conditions for that, see
https://docs.oasis-open.org/office/OpenDocument/v1.3/os/part4-formula/OpenDocument-v1.3-os-part4-formula.html#INDEX

Also, that vector element case assumed vector replication to the
other dimension as usual, which is not the case here, access to
the other dimension's index >1 must return error.

Change-Id: I604c2355f0aca2988cb13f0d4f54ccd2d74c3b0d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148736
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
(cherry picked from commit df706f47a2b62248d222911db12c674e6507e5c6)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148755
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 5673bb7..ac0fb22 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -8674,10 +8674,17 @@ void ScInterpreter::ScIndex()
        nArea = GetUInt32();
    else
        nArea = 1;
    bool bColMissing;
    if (nParamCount >= 3)
    {
        bColMissing = IsMissing();
        nCol = static_cast<SCCOL>(GetInt16());
    }
    else
    {
        bColMissing = false;
        nCol = 0;
    }
    if (nParamCount >= 2)
        nRow = static_cast<SCROW>(GetInt32());
    else
@@ -8710,25 +8717,57 @@ void ScInterpreter::ScIndex()
                {
                    SCSIZE nC, nR;
                    pMat->GetDimensions(nC, nR);

                    // Access one element of a vector independent of col/row
                    // orientation?
                    bool bVector = ((nCol == 0 || nRow == 0) && (nC == 1 || nR == 1));
                    SCSIZE nElement = ::std::max( static_cast<SCSIZE>(nCol),
                            static_cast<SCSIZE>(nRow));
                    // orientation. Excel documentation does not mention, but
                    // i62850 had a .xls example of a row vector accessed by
                    // row number returning one element. This
                    // INDEX(row_vector;element) behaves the same as
                    // INDEX(row_vector;0;element) and thus contradicts Excel
                    // documentation where the second parameter is always
                    // row_num.
                    //
                    // ODFF v1.3 in 6.14.6 INDEX states "If DataSource is a
                    // one-dimensional row vector, Row is optional, which
                    // effectively makes Row act as the column offset into the
                    // vector". Guess the first Row is a typo and should read
                    // Column instead.

                    const bool bRowVectorSpecial = (nParamCount == 2 || bColMissing);
                    const bool bRowVectorElement = (nR == 1 && (nCol != 0 || (bRowVectorSpecial && nRow != 0)));
                    const bool bVectorElement = (bRowVectorElement || (nC == 1 && nRow != 0));

                    if (nC == 0 || nR == 0 ||
                            (!bVector && (o3tl::make_unsigned(nCol) > nC ||
                                          o3tl::make_unsigned(nRow) > nR)) ||
                            (bVector && nElement > nC * nR))
                            (!bVectorElement && (o3tl::make_unsigned(nCol) > nC ||
                                                 o3tl::make_unsigned(nRow) > nR)))
                        PushIllegalArgument();
                    else if (nCol == 0 && nRow == 0)
                        sp = nOldSp;
                    else if (bVector)
                    else if (bVectorElement)
                    {
                        --nElement;
                        if (pMat->IsStringOrEmpty( nElement))
                            PushString( pMat->GetString(nElement).getString());
                        // Vectors here don't replicate to the other dimension.
                        SCSIZE nElement, nOtherDimension;
                        if (bRowVectorElement && !bRowVectorSpecial)
                        {
                            nElement = o3tl::make_unsigned(nCol);
                            nOtherDimension = o3tl::make_unsigned(nRow);
                        }
                        else
                            PushDouble( pMat->GetDouble( nElement));
                        {
                            nElement = o3tl::make_unsigned(nRow);
                            nOtherDimension = o3tl::make_unsigned(nCol);
                        }

                        if (nElement == 0 || nElement > nC * nR || nOtherDimension > 1)
                            PushIllegalArgument();
                        else
                        {
                            --nElement;
                            if (pMat->IsStringOrEmpty( nElement))
                                PushString( pMat->GetString(nElement).getString());
                            else
                                PushDouble( pMat->GetDouble( nElement));
                        }
                    }
                    else if (nCol == 0)
                    {