[Libreoffice-commits] .: formula/inc formula/source sc/inc sc/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Wed Jan 9 08:28:41 PST 2013


 formula/inc/formula/FormulaCompiler.hxx     |    3 +-
 formula/source/core/api/FormulaCompiler.cxx |    2 -
 sc/inc/cell.hxx                             |    5 ++++
 sc/inc/compiler.hxx                         |    4 +--
 sc/inc/formularesult.hxx                    |    2 +
 sc/inc/token.hxx                            |    4 +++
 sc/source/core/tool/compiler.cxx            |    2 -
 sc/source/core/tool/formularesult.cxx       |   10 +++++++++
 sc/source/core/tool/interpr1.cxx            |    3 ++
 sc/source/filter/xml/xmlcelli.cxx           |   30 ++++++++++++++++++++--------
 sc/source/filter/xml/xmlimprt.cxx           |   11 ++++++++++
 sc/source/filter/xml/xmlimprt.hxx           |    8 ++++++-
 12 files changed, 70 insertions(+), 14 deletions(-)

New commits:
commit b6fbc8642928893ca608a35b802032cfe42e40bb
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Jan 9 11:17:09 2013 -0500

    fdo#58539: Correctly set cached matrix formula result.
    
    During the import, a cached matrix value only has an empty matrix
    of correct geometry, plus the token type of the top-left cell.  The
    rest of the elements are imported as hybrid values.  For now, this
    seems to do the trick.
    
    In the future we may want to change it to fully populate the matrix
    cache value during the import, and skip setting the hybrid values for
    the non-top-left elements.
    
    This commit also make several other trivial changes:
    
    * Mark pRawToken mutable so that we can mark those IsFoo() methods
      const.
    
    * Move the ScCompiler instance from static instance to member of
      ScXMLImport. Since we don't need the instance to persist once the
      import is over, this is more appropriate.
    
    Change-Id: I1abde03c0fcd91b02ef4dbf8b5526f7965eaf19c

diff --git a/formula/inc/formula/FormulaCompiler.hxx b/formula/inc/formula/FormulaCompiler.hxx
index ce4157d..85295b2 100644
--- a/formula/inc/formula/FormulaCompiler.hxx
+++ b/formula/inc/formula/FormulaCompiler.hxx
@@ -212,6 +212,8 @@ public:
      */
     OpCode GetEnglishOpCode( const String& rName ) const;
 
+    sal_uInt16 GetErrorConstant( const String& rName ) const;
+
     void            SetCompileForFAP( bool bVal )
                         { bCompileForFAP = bVal; bIgnoreErrors = bVal; }
 
@@ -265,7 +267,6 @@ protected:
     virtual void CreateStringFromIndex(rtl::OUStringBuffer& rBuffer,FormulaToken* pTokenP);
     virtual void LocalizeString( String& rName );   // modify rName - input: exact name
 
-    sal_uInt16 GetErrorConstant( const String& rName );
     void AppendErrorConstant( rtl::OUStringBuffer& rBuffer, sal_uInt16 nError );
 
     bool   GetToken();
diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index 29b6694..f79201b 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -816,7 +816,7 @@ void FormulaCompiler::OpCodeMap::copyFrom( const OpCodeMap& r )
 }
 // -----------------------------------------------------------------------------
 
-sal_uInt16 FormulaCompiler::GetErrorConstant( const String& rName )
+sal_uInt16 FormulaCompiler::GetErrorConstant( const String& rName ) const
 {
     sal_uInt16 nError = 0;
     OpCodeHashMap::const_iterator iLook( mxSymbols->getHashMap()->find( rName));
diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx
index ee040a2..716b76f 100644
--- a/sc/inc/cell.hxx
+++ b/sc/inc/cell.hxx
@@ -493,6 +493,11 @@ public:
                                     const formula::FormulaGrammar::Grammar eGrammar )
                         { aResult.SetHybridFormula( r); eTempGrammar = eGrammar; }
 
+    void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL )
+    {
+        aResult.SetMatrix(nCols, nRows, pMat, pUL);
+    }
+
     /** For import only: set a double result.
         Use this instead of SetHybridDouble() if there is no (temporary)
         formula string because the formula is present as a token array, as it
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index 4aa393d..d40d261 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -320,7 +320,7 @@ private:
     sal_Unicode cSymbol[MAXSTRLEN];                 // current Symbol
     String      aFormula;                           // formula source code
     xub_StrLen  nSrcPos;                            // tokenizer position (source code)
-    ScRawTokenRef   pRawToken;
+    mutable ScRawTokenRef pRawToken;
 
     const CharClass*    pCharClass;         // which character classification is used for parseAnyToken
     sal_uInt16      mnPredetectedReference;     // reference when reading ODF, 0 (none), 1 (single) or 2 (double)
@@ -386,7 +386,7 @@ public:
 
     // Check if it is a valid english function name
     bool IsEnglishSymbol( const String& rName );
-    bool IsErrorConstant( const String& );
+    bool IsErrorConstant( const String& ) const;
 
     //! _either_ CompileForFAP _or_ AutoCorrection, _not_ both
     // #i101512# SetCompileForFAP is in formula::FormulaCompiler
diff --git a/sc/inc/formularesult.hxx b/sc/inc/formularesult.hxx
index c4f281f..2128636 100644
--- a/sc/inc/formularesult.hxx
+++ b/sc/inc/formularesult.hxx
@@ -179,6 +179,8 @@ public:
         SetHybridFormula() for formula string to be compiled later. */
     SC_DLLPUBLIC void SetHybridFormula( const String & rFormula );
 
+    SC_DLLPUBLIC void SetMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL );
+
     /** Get the const ScMatrixFormulaCellToken* if token is of that type, else
         NULL. */
     const ScMatrixFormulaCellToken* GetMatrixFormulaCellToken() const;
diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx
index c8c8782..e08db6c 100644
--- a/sc/inc/token.hxx
+++ b/sc/inc/token.hxx
@@ -350,6 +350,10 @@ private:
             SCROW               nRows;
             SCCOL               nCols;
 public:
+    ScMatrixFormulaCellToken( SCCOL nC, SCROW nR, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL ) :
+        ScMatrixCellResultToken(pMat, pUL),
+        nRows(nR), nCols(nC) {}
+
                                 ScMatrixFormulaCellToken( SCCOL nC, SCROW nR ) :
                                     ScMatrixCellResultToken( NULL, NULL ),
                                     nRows( nR ), nCols( nC ) {}
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 4656e2b..6de0417 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -3306,7 +3306,7 @@ bool ScCompiler::IsBoolean( const String& rName )
 }
 
 
-bool ScCompiler::IsErrorConstant( const String& rName )
+bool ScCompiler::IsErrorConstant( const String& rName ) const
 {
     sal_uInt16 nError = GetErrorConstant( rName);
     if (nError)
diff --git a/sc/source/core/tool/formularesult.cxx b/sc/source/core/tool/formularesult.cxx
index 3b94481..9e1032e 100644
--- a/sc/source/core/tool/formularesult.cxx
+++ b/sc/source/core/tool/formularesult.cxx
@@ -443,6 +443,16 @@ void ScFormulaResult::SetHybridFormula( const String & rFormula )
     mbToken = true;
 }
 
+void ScFormulaResult::SetMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL )
+{
+    ResetToDefaults();
+    if (mbToken && mpToken)
+        mpToken->DecRef();
+    mpToken = new ScMatrixFormulaCellToken(nCols, nRows, pMat, pUL);
+    mpToken->IncRef();
+    mbToken = true;
+}
+
 const ScMatrixFormulaCellToken* ScFormulaResult::GetMatrixFormulaCellToken() const
 {
     return (GetType() == formula::svMatrixCell ?
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 0b86108..ec85a01 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -135,7 +135,10 @@ void ScInterpreter::ScIfJump()
                 SCSIZE nCols, nRows;
                 pMat->GetDimensions( nCols, nRows );
                 if ( nCols == 0 || nRows == 0 )
+                {
                     PushIllegalArgument();
+                    return;
+                }
                 else if (pTokenMatrixMap && ((aMapIter = pTokenMatrixMap->find(
                                     pCur)) != pTokenMatrixMap->end()))
                     xNew = (*aMapIter).second;
diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx
index e937570..25579f2 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -47,8 +47,6 @@
 #include "scerrors.hxx"
 #include "editutil.hxx"
 #include "cell.hxx"
-#include "compiler.hxx"
-
 
 #include <xmloff/xmltkmap.hxx>
 #include <xmloff/xmltoken.hxx>
@@ -727,9 +725,7 @@ void ScXMLTableRowCellContext::SetFormulaCell(ScFormulaCell* pFCell) const
     {
         if( bFormulaTextResult && pOUTextValue )
         {
-            static ScCompiler aComp(NULL, ScAddress());
-            aComp.SetGrammar(formula::FormulaGrammar::GRAM_ODFF);
-            if(!aComp.IsErrorConstant(*pOUTextValue))
+            if (!GetScImport().IsFormulaErrorConstant(*pOUTextValue))
             {
                 pFCell->SetHybridString( *pOUTextValue );
                 pFCell->ResetDirty();
@@ -1086,11 +1082,29 @@ void ScXMLTableRowCellContext::AddFormulaCell( const ScAddress& rCellPos )
                         std::min<SCROW>(rCellPos.Row() + nMatrixRows - 1, MAXROW),
                         pOUFormula->first, pOUFormula->second, eGrammar);
 
-                //set the value/text of the first matrix position (top-left).
-                //the value/text of the matrix reference cells will be set later.
+                // Set the value/text of the top-left matrix position in its
+                // cached result.  For import, we only need to set the correct
+                // matrix geometry and the value type of the top-left element.
+
                 ScFormulaCell* pFCell =
                     static_cast<ScFormulaCell*>( rXMLImport.GetDocument()->GetCell(rCellPos) );
-                SetFormulaCell(pFCell);
+
+                ScMatrixRef pMat(new ScMatrix(nMatrixCols, nMatrixRows));
+                if (bFormulaTextResult && pOUTextValue)
+                {
+                    if (!GetScImport().IsFormulaErrorConstant(*pOUTextValue))
+                    {
+                        pFCell->SetResultMatrix(
+                            nMatrixCols, nMatrixRows, pMat, new formula::FormulaStringToken(*pOUTextValue));
+                        pFCell->ResetDirty();
+                    }
+                }
+                else if (!rtl::math::isNan(fValue))
+                {
+                    pFCell->SetResultMatrix(
+                        nMatrixCols, nMatrixRows, pMat, new formula::FormulaDoubleToken(fValue));
+                    pFCell->ResetDirty();
+                }
             }
         }
         else
diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx
index 7aae79c..b7f229c 100644
--- a/sc/source/filter/xml/xmlimprt.cxx
+++ b/sc/source/filter/xml/xmlimprt.cxx
@@ -2809,6 +2809,9 @@ throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::R
     if (!pDoc)
         throw lang::IllegalArgumentException();
 
+    mpComp.reset(new ScCompiler(pDoc, ScAddress()));
+    mpComp->SetGrammar(formula::FormulaGrammar::GRAM_ODFF);
+
     bFromWrapper = pDoc->IsXMLFromWrapper();    // UnlockSolarMutex below still works normally
 
     uno::Reference<document::XActionLockable> xActionLockable(xDoc, uno::UNO_QUERY);
@@ -3294,4 +3297,12 @@ void ScXMLImport::ExtractFormulaNamespaceGrammar(
     reGrammar = eDefaultGrammar;
 }
 
+bool ScXMLImport::IsFormulaErrorConstant( const OUString& rStr ) const
+{
+    if (!mpComp)
+        return false;
+
+    return mpComp->GetErrorConstant(rStr) > 0;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx
index c202160..87f3f3e 100644
--- a/sc/source/filter/xml/xmlimprt.hxx
+++ b/sc/source/filter/xml/xmlimprt.hxx
@@ -31,6 +31,7 @@
 #include "xmlsubti.hxx"
 #include "global.hxx"
 #include "formula/grammar.hxx"
+#include "compiler.hxx"
 
 #include "xmlstyle.hxx"
 #include "XMLDetectiveContext.hxx"
@@ -46,6 +47,8 @@
 #include <boost/unordered_map.hpp>
 #include <boost/ptr_container/ptr_list.hpp>
 #include <boost/ptr_container/ptr_map.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/scoped_ptr.hpp>
 
 class ScMyStyleNumberFormats;
 class XMLNumberFormatAttributesExportHelper;
@@ -732,7 +735,7 @@ typedef std::vector<ScMyImportValidation>           ScMyImportValidations;
 typedef std::list<SvXMLImportContext*>              ScMyViewContextList;
 class ScMyStylesImportHelper;
 
-class ScXMLImport: public SvXMLImport
+class ScXMLImport: public SvXMLImport, boost::noncopyable
 {
     typedef ::boost::unordered_map< ::rtl::OUString, sal_Int16, ::rtl::OUStringHash >   CellTypeMap;
     typedef ::boost::ptr_map<SCTAB, ScMyNamedExpressions> SheetNamedExpMap;
@@ -740,6 +743,7 @@ class ScXMLImport: public SvXMLImport
     CellTypeMap             aCellTypeMap;
 
     ScDocument*             pDoc;
+    boost::scoped_ptr<ScCompiler> mpComp; // For error-checking of cached string cell values.
     ScXMLChangeTrackingImportHelper*    pChangeTrackingImportHelper;
     ScMyViewContextList                 aViewContextList;
     ScMyStylesImportHelper*             pStylesImportHelper;
@@ -1141,6 +1145,8 @@ public:
             ::formula::FormulaGrammar::Grammar& reGrammar,
             const ::rtl::OUString& rAttrValue,
             bool bRestrictToExternalNmsp = false ) const;
+
+    bool IsFormulaErrorConstant( const OUString& rStr ) const;
 };
 
 #endif


More information about the Libreoffice-commits mailing list