sc/source/core/tool/interpr7.cxx |  119 +++++++++++++++++++++++++++++++++------
 1 file changed, 101 insertions(+), 18 deletions(-)

New commits:
commit 7d733e16513a1b9413303d60feb03c5a0de941fc
Author: Eike Rathke <er...@redhat.com>
Date:   Wed Aug 17 15:58:42 2016 +0200

    Resolves: tdf#88257 handle FILTERXML array/matrix context
    
    ... in which subsequent node elements are to be stored in the result
    matrix.
    
    Change-Id: Ia980a99a2b9ffba0e651f5d4c2420c8acfb80615

diff --git a/sc/source/core/tool/interpr7.cxx b/sc/source/core/tool/interpr7.cxx
index 7b2624b..2d48c6b 100644
--- a/sc/source/core/tool/interpr7.cxx
+++ b/sc/source/core/tool/interpr7.cxx
@@ -8,6 +8,9 @@
  */
 
 #include "interpre.hxx"
+#include "jumpmatrix.hxx"
+#include "formulacell.hxx"
+#include "scmatrix.hxx"
 #include <rtl/strbuf.hxx>
 #include <formula/errorcodes.hxx>
 #include <svtools/miscopt.hxx>
@@ -33,6 +36,54 @@ void ScInterpreter::ScFilterXML()
     sal_uInt8 nParamCount = GetByte();
     if (MustHaveParamCount( nParamCount, 2 ) )
     {
+        SCSIZE nMatCols = 1, nMatRows = 1, nNode = 0;
+        const ScMatrix* pPathMatrix = nullptr;
+        // In array/matrix context node elements' results are to be
+        // subsequently stored. Check this before obtaining any argument from
+        // the stack so the stack type can be used.
+        if (pJumpMatrix || bMatrixFormula || pCur->IsInForceArray())
+        {
+            if (pJumpMatrix)
+            {
+                // Single result, GetString() will retrieve the corresponding
+                // argument and JumpMatrix() will store it at the proper
+                // position. Note that nMatCols and nMatRows are still 1.
+                SCSIZE nCurCol = 0, nCurRow = 0;
+                pJumpMatrix->GetPos( nCurCol, nCurRow);
+                nNode = nCurRow;
+            }
+            else if (bMatrixFormula)
+            {
+                // If there is no formula cell then continue with a single
+                // result.
+                if (pMyFormulaCell)
+                {
+                    SCCOL nCols;
+                    SCROW nRows;
+                    pMyFormulaCell->GetMatColsRows( nCols, nRows);
+                    nMatCols = nCols;
+                    nMatRows = nRows;
+                }
+            }
+            else if (GetStackType() == formula::svMatrix)
+            {
+                pPathMatrix = pStack[sp-1]->GetMatrix();
+                if (!pPathMatrix)
+                {
+                    PushIllegalParameter();
+                    return;
+                }
+                pPathMatrix->GetDimensions( nMatCols, nMatRows);
+
+                /* TODO: it is unclear what should happen if there are
+                 * different path arguments in matrix elements. We may have to
+                 * evaluate each, and for repeated identical paths use
+                 * subsequent nodes. As is, the path at 0,0 is used as obtained
+                 * by GetString(). */
+
+            }
+        }
+
         OUString aXPathExpression = GetString().getString();
         OUString aString = GetString().getString();
         if(aString.isEmpty() || aXPathExpression.isEmpty())
@@ -70,8 +121,6 @@ void ScInterpreter::ScFilterXML()
             return;
         }
 
-        rtl::OUString aResult;
-
         switch(pXPathObj->type)
         {
             case XPATH_UNDEFINED:
@@ -85,30 +134,64 @@ void ScInterpreter::ScFilterXML()
                         return;
                     }
 
-                    size_t nSize = pNodeSet->nodeNr;
-                    if( nSize >= 1 )
+                    const size_t nSize = pNodeSet->nodeNr;
+                    if (nNode >= nSize)
+                    {
+                        // For pJumpMatrix
+                        PushError( formula::NOTAVAILABLE);
+                        return;
+                    }
+
+                    /* TODO: for nMatCols>1 IF stack type is svMatrix, i.e.
+                     * pPathMatrix!=nullptr, we may want a result matrix with
+                     * nMatCols columns as well, but clarify first how to treat
+                     * differing path elements. */
+
+                    ScMatrixRef xResMat;
+                    if (nMatRows > 1)
                     {
-                        if(pNodeSet->nodeTab[0]->type == XML_NAMESPACE_DECL)
+                        xResMat = GetNewMat( 1, nMatRows, true);
+                        if (!xResMat)
                         {
-                            xmlNsPtr ns = 
reinterpret_cast<xmlNsPtr>(pNodeSet->nodeTab[0]);
-                            xmlNodePtr cur = 
reinterpret_cast<xmlNodePtr>(ns->next);
-                            std::shared_ptr<xmlChar> 
pChar2(xmlNodeGetContent(cur), xmlFree);
-                            aResult = 
OStringToOUString(OString(reinterpret_cast<char*>(pChar2.get())), 
RTL_TEXTENCODING_UTF8);
+                            PushError( formula::errCodeOverflow);
+                            return;
+                        }
+                    }
+
+                    for ( ; nNode < nMatRows; ++nNode)
+                    {
+                        if( nSize > nNode )
+                        {
+                            rtl::OUString aResult;
+                            if(pNodeSet->nodeTab[nNode]->type == 
XML_NAMESPACE_DECL)
+                            {
+                                xmlNsPtr ns = 
reinterpret_cast<xmlNsPtr>(pNodeSet->nodeTab[nNode]);
+                                xmlNodePtr cur = 
reinterpret_cast<xmlNodePtr>(ns->next);
+                                std::shared_ptr<xmlChar> 
pChar2(xmlNodeGetContent(cur), xmlFree);
+                                aResult = 
OStringToOUString(OString(reinterpret_cast<char*>(pChar2.get())), 
RTL_TEXTENCODING_UTF8);
+                            }
+                            else
+                            {
+                                xmlNodePtr cur = pNodeSet->nodeTab[nNode];
+                                std::shared_ptr<xmlChar> 
pChar2(xmlNodeGetContent(cur), xmlFree);
+                                aResult = 
OStringToOUString(OString(reinterpret_cast<char*>(pChar2.get())), 
RTL_TEXTENCODING_UTF8);
+                            }
+                            if (xResMat)
+                                xResMat->PutString( mrStrPool.intern( 
aResult), 0, nNode);
+                            else
+                                PushString(aResult);
                         }
                         else
                         {
-                            xmlNodePtr cur = pNodeSet->nodeTab[0];
-                            std::shared_ptr<xmlChar> 
pChar2(xmlNodeGetContent(cur), xmlFree);
-                            aResult = 
OStringToOUString(OString(reinterpret_cast<char*>(pChar2.get())), 
RTL_TEXTENCODING_UTF8);
+                            if (xResMat)
+                                xResMat->PutError( formula::NOTAVAILABLE, 0, 
nNode);
+                            else
+                                PushError( formula::NOTAVAILABLE );
                         }
                     }
-                    else
-                    {
-                        PushError( formula::errNoValue );
-                        return;
-                    }
+                    if (xResMat)
+                        PushMatrix( xResMat);
                 }
-                PushString(aResult);
                 break;
             case XPATH_BOOLEAN:
                 {
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to