[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.1' - oox/source sc/qa sc/source

Mike Kaganski mike.kaganski at collabora.com
Mon Dec 5 22:12:29 UTC 2016


 oox/source/core/fragmenthandler2.cxx       |    1 
 oox/source/core/xmlfilterbase.cxx          |    5 
 oox/source/token/namespaces-strict.txt     |    1 
 oox/source/token/namespaces.hxx.tail       |    1 
 oox/source/token/namespaces.txt            |    1 
 oox/source/token/tokens.txt                |    1 
 sc/qa/unit/bugfix-test.cxx                 |   98 ++++------
 sc/qa/unit/data/xlsx/tdf104310-2.xlsx      |binary
 sc/qa/unit/data/xlsx/tdf104310.xlsx        |binary
 sc/source/filter/inc/worksheetfragment.hxx |   77 +++++++-
 sc/source/filter/oox/extlstcontext.cxx     |    8 
 sc/source/filter/oox/worksheetfragment.cxx |  266 ++++++++++++++++++++++-------
 12 files changed, 333 insertions(+), 126 deletions(-)

New commits:
commit da54ed01e4814290299ebf6a0c5d472cb827f77d
Author: Mike Kaganski <mike.kaganski at collabora.com>
Date:   Fri Dec 2 11:20:59 2016 +0300

    tdf#104310: Accept x12ac and x14 extensions in dataValidations
    
    This is backport of commits 0afbe8d5 and ce17ebb6 from master.
    
    Change-Id: I155d160a0d19b037e6e765d960daf4545535c0ed
    Reviewed-on: https://gerrit.libreoffice.org/31527
    Reviewed-by: Kohei Yoshida <libreoffice at kohei.us>
    Tested-by: Kohei Yoshida <libreoffice at kohei.us>

diff --git a/oox/source/core/fragmenthandler2.cxx b/oox/source/core/fragmenthandler2.cxx
index f904069..0e64bb2 100644
--- a/oox/source/core/fragmenthandler2.cxx
+++ b/oox/source/core/fragmenthandler2.cxx
@@ -73,6 +73,7 @@ bool FragmentHandler2::prepareMceContext( sal_Int32 nElement, const AttributeLis
                 {
                     "p14",
                     "p15",
+                    "x12ac",
                 };
 
                 if (std::find(aSupportedNS.begin(), aSupportedNS.end(), aRequires) != aSupportedNS.end())
diff --git a/oox/source/core/xmlfilterbase.cxx b/oox/source/core/xmlfilterbase.cxx
index a2c3b9b..3cda81e 100644
--- a/oox/source/core/xmlfilterbase.cxx
+++ b/oox/source/core/xmlfilterbase.cxx
@@ -137,7 +137,10 @@ struct NamespaceIds: public rtl::StaticWithInit<
             {"http://schemas.microsoft.com/office/powerpoint/2010/main",
              NMSP_p14},
             {"http://schemas.microsoft.com/office/powerpoint/2012/main",
-             NMSP_p15}};
+             NMSP_p15},
+            {"http://schemas.microsoft.com/office/spreadsheetml/2011/1/ac",
+             NMSP_x12ac},
+        };
     }
 };
 
diff --git a/oox/source/token/namespaces-strict.txt b/oox/source/token/namespaces-strict.txt
index f9a4633..0f606f7 100644
--- a/oox/source/token/namespaces-strict.txt
+++ b/oox/source/token/namespaces-strict.txt
@@ -83,6 +83,7 @@ p14                     http://schemas.microsoft.com/office/powerpoint/2010/main
 # MSO 2012/2013 extensions ---------------------------------------------------------
 
 p15                     http://schemas.microsoft.com/office/powerpoint/2012/main
+x12ac                   http://schemas.microsoft.com/office/spreadsheetml/2011/1/ac
 
 # extlst namespaces
 
diff --git a/oox/source/token/namespaces.hxx.tail b/oox/source/token/namespaces.hxx.tail
index 89f8c1c..17770dc 100644
--- a/oox/source/token/namespaces.hxx.tail
+++ b/oox/source/token/namespaces.hxx.tail
@@ -46,6 +46,7 @@ inline sal_Int32 getNamespace( sal_Int32 nToken ) { return nToken & NMSP_MASK; }
 #define R_TOKEN( token )        OOX_TOKEN( officeRel, token )
 #define VML_TOKEN( token )      OOX_TOKEN( vml, token )
 #define VMLX_TOKEN( token )     OOX_TOKEN( vmlExcel, token )
+#define X12AC_TOKEN( token )    OOX_TOKEN( x12ac, token )
 #define XDR_TOKEN( token )      OOX_TOKEN( dmlSpreadDr, token )
 #define XLS_TOKEN( token )      OOX_TOKEN( xls, token )
 #define XLS14_TOKEN( token )    OOX_TOKEN( xls14Lst, token )
diff --git a/oox/source/token/namespaces.txt b/oox/source/token/namespaces.txt
index 7920572..4b6f49a 100644
--- a/oox/source/token/namespaces.txt
+++ b/oox/source/token/namespaces.txt
@@ -83,6 +83,7 @@ p14                     http://schemas.microsoft.com/office/powerpoint/2010/main
 # MSO 2012/2013 extensions ---------------------------------------------------------
 
 p15                     http://schemas.microsoft.com/office/powerpoint/2012/main
+x12ac                   http://schemas.microsoft.com/office/spreadsheetml/2011/1/ac
 
 # extlst namespaces
 
diff --git a/oox/source/token/tokens.txt b/oox/source/token/tokens.txt
index b113c84..6d4fcb8 100644
--- a/oox/source/token/tokens.txt
+++ b/oox/source/token/tokens.txt
@@ -5781,6 +5781,7 @@ writeProtection
 wsDr
 wsp
 x
+x12ac
 x14
 xAlign
 xIllusions
diff --git a/sc/qa/unit/bugfix-test.cxx b/sc/qa/unit/bugfix-test.cxx
index b137cf7..21e66c7 100644
--- a/sc/qa/unit/bugfix-test.cxx
+++ b/sc/qa/unit/bugfix-test.cxx
@@ -7,66 +7,10 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
  */
 
-#include <sal/config.h>
-#include <unotest/filters-test.hxx>
-#include <test/bootstrapfixture.hxx>
-#include <rtl/strbuf.hxx>
-#include <osl/file.hxx>
-
-#include <sfx2/app.hxx>
-#include <sfx2/docfilt.hxx>
-#include <sfx2/docfile.hxx>
-#include <sfx2/sfxmodelfactory.hxx>
-#include <svl/stritem.hxx>
-#include <svx/svdograf.hxx>
-
-#include "drwlayer.hxx"
-#include <svx/svdpage.hxx>
-#include <svx/svdoole2.hxx>
-#include <editeng/wghtitem.hxx>
-#include <editeng/postitem.hxx>
-#include <editeng/udlnitem.hxx>
-#include <editeng/editobj.hxx>
-#include <editeng/borderline.hxx>
-#include <editeng/flditem.hxx>
-#include <dbdata.hxx>
 #include "validat.hxx"
-#include "formulacell.hxx"
-#include "userdat.hxx"
-#include "dpobject.hxx"
-#include "dpsave.hxx"
-#include "stlsheet.hxx"
-#include "docfunc.hxx"
-#include "markdata.hxx"
-#include "colorscale.hxx"
-#include "olinetab.hxx"
-#include "patattr.hxx"
-#include "scitems.hxx"
-#include "docsh.hxx"
-#include "editutil.hxx"
-#include "cellvalue.hxx"
-#include "attrib.hxx"
-#include "dpshttab.hxx"
 #include "tabvwsh.hxx"
-#include <scopetools.hxx>
-#include <columnspanset.hxx>
-#include <tokenstringcontext.hxx>
-
-#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
-#include <com/sun/star/drawing/XControlShape.hpp>
-#include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
-#include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
-#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
-#include <com/sun/star/sheet/GeneralFunction.hpp>
-#include <com/sun/star/container/XIndexAccess.hpp>
-#include <com/sun/star/frame/XModel.hpp>
-#include <com/sun/star/text/textfield/Type.hpp>
-#include <com/sun/star/chart2/XChartDocument.hpp>
-#include <com/sun/star/chart2/data/XDataReceiver.hpp>
 #include <com/sun/star/frame/Desktop.hpp>
-
 #include "helper/qahelper.hxx"
-#include "helper/shared_test_impl.hxx"
 
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::uno;
@@ -90,6 +34,7 @@ public:
     void testTdf88821();
     void testTdf88821_2();
     void testTdf103960();
+    void testTdf104310();
 
     CPPUNIT_TEST_SUITE(ScFiltersTest);
     CPPUNIT_TEST(testTdf64229);
@@ -102,6 +47,7 @@ public:
     CPPUNIT_TEST(testTdf88821);
     CPPUNIT_TEST(testTdf88821_2);
     CPPUNIT_TEST(testTdf103960);
+    CPPUNIT_TEST(testTdf104310);
     CPPUNIT_TEST_SUITE_END();
 private:
     uno::Reference<uno::XInterface> m_xCalcComponent;
@@ -282,6 +228,46 @@ void ScFiltersTest::testTdf103960()
     xDocSh->DoClose();
 }
 
+void ScFiltersTest::testTdf104310()
+{
+    // 1. Test x14 extension
+    {
+        ScDocShellRef xDocSh = loadDoc("tdf104310.", FORMAT_XLSX);
+        ScDocument& rDoc = xDocSh->GetDocument();
+
+        const ScValidationData* pData = rDoc.GetValidationEntry(1);
+        CPPUNIT_ASSERT(pData);
+
+        // Make sure the list is correct.
+        std::vector<ScTypedStrData> aList;
+        pData->FillSelectionList(aList, ScAddress(0, 1, 0));
+        CPPUNIT_ASSERT_EQUAL(size_t(5), aList.size());
+        for (size_t i = 0; i < 5; ++i)
+            CPPUNIT_ASSERT_DOUBLES_EQUAL(double(i + 1), aList[i].GetValue(), 1e-8);
+
+        xDocSh->DoClose();
+    }
+
+    // 2. Test x12ac extension
+    {
+        ScDocShellRef xDocSh = loadDoc("tdf104310-2.", FORMAT_XLSX);
+        ScDocument& rDoc = xDocSh->GetDocument();
+
+        const ScValidationData* pData = rDoc.GetValidationEntry(1);
+        CPPUNIT_ASSERT(pData);
+
+        // Make sure the list is correct.
+        std::vector<ScTypedStrData> aList;
+        pData->FillSelectionList(aList, ScAddress(0, 1, 0));
+        CPPUNIT_ASSERT_EQUAL(size_t(3), aList.size());
+        CPPUNIT_ASSERT_EQUAL(OUString("1"),   aList[0].GetString());
+        CPPUNIT_ASSERT_EQUAL(OUString("2,3"), aList[1].GetString());
+        CPPUNIT_ASSERT_EQUAL(OUString("4"),   aList[2].GetString());
+
+        xDocSh->DoClose();
+    }
+}
+
 ScFiltersTest::ScFiltersTest()
       : ScBootstrapFixture( "/sc/qa/unit/data" )
 {
diff --git a/sc/qa/unit/data/xlsx/tdf104310-2.xlsx b/sc/qa/unit/data/xlsx/tdf104310-2.xlsx
new file mode 100644
index 0000000..dc5e9ac
Binary files /dev/null and b/sc/qa/unit/data/xlsx/tdf104310-2.xlsx differ
diff --git a/sc/qa/unit/data/xlsx/tdf104310.xlsx b/sc/qa/unit/data/xlsx/tdf104310.xlsx
new file mode 100644
index 0000000..95570d3
Binary files /dev/null and b/sc/qa/unit/data/xlsx/tdf104310.xlsx differ
diff --git a/sc/source/filter/inc/worksheetfragment.hxx b/sc/source/filter/inc/worksheetfragment.hxx
index 0cd02b3..9fc348b 100644
--- a/sc/source/filter/inc/worksheetfragment.hxx
+++ b/sc/source/filter/inc/worksheetfragment.hxx
@@ -25,7 +25,51 @@
 namespace oox {
 namespace xls {
 
-class DataValidationsContext : public WorksheetContextBase
+class DataValidationsContext_Base {
+public:
+                                   DataValidationsContext_Base() {}
+    void                           SetSqref(const OUString& rChars) { mSqref = rChars; }
+    void                           SetFormula1(const OUString& rChars) { mFormula1 = rChars; }
+    void                           SetFormula2(const OUString& rChars) { mFormula2 = rChars; }
+    void                           SetValidation(::oox::xls::WorksheetHelper& rTarget);
+    /** Imports the dataValidation element containing data validation settings. */
+    void                           importDataValidation(const AttributeList& rAttribs);
+    /** Imports the DATAVALIDATION record containing data validation settings. */
+    static void                    importDataValidation(SequenceInputStream& rStrm, ::oox::xls::WorksheetHelper& rTarget);
+    bool                           isFormula1Set() const { return !mFormula1.isEmpty(); }
+    bool                           isFormula2Set() const { return !mFormula2.isEmpty(); }
+private:
+    ::std::unique_ptr< ValidationModel > mxValModel;
+    OUString                             mSqref;
+    OUString                             mFormula1;
+    OUString                             mFormula2;
+};
+
+// For following types of validations:
+//
+//  <dataValidations count="1">
+//    <dataValidation allowBlank="true" operator="equal" showDropDown="false" showErrorMessage="true" showInputMessage="false" sqref="C1:C5" type="list">
+//      <formula1>Sheet1!$A$1:$A$5</formula1>
+//      <formula2>0</formula2>
+//    </dataValidation>
+//  </dataValidations>
+//
+// or
+//
+//  <dataValidations count="1">
+//    <dataValidation type="list" operator="equal" allowBlank="1" showErrorMessage="1" sqref="A1">
+//      <mc:AlternateContent xmlns:x12ac="http://schemas.microsoft.com/office/spreadsheetml/2011/1/ac" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006">
+//        <mc:Choice Requires="x12ac">
+//          <x12ac:list>1,"2,3",4</x12ac:list>
+//        </mc:Choice>
+//        <mc:Fallback>
+//          <formula1>"1,2,3,4"</formula1>
+//        </mc:Fallback>
+//      </mc:AlternateContent>
+//    </dataValidation>
+//  </dataValidations>
+
+class DataValidationsContext : public WorksheetContextBase, private DataValidationsContext_Base
 {
 public:
     explicit            DataValidationsContext( WorksheetFragmentBase& rFragment );
@@ -36,15 +80,34 @@ protected:
     virtual void        onEndElement() override;
 
     virtual ::oox::core::ContextHandlerRef onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm ) override;
+};
 
-private:
-    /** Imports the dataValidation element containing data validation settings. */
-    void                importDataValidation( const AttributeList& rAttribs );
-    /** Imports the DATAVALIDATION record containing data validation settings. */
-    void                importDataValidation( SequenceInputStream& rStrm );
+// For following types of validations:
+//
+//  <extLst>
+//    <ext uri="{CCE6A557-97BC-4b89-ADB6-D9C93CAAB3DF}" xmlns:x14="http://schemas.microsoft.com/office/spreadsheetml/2009/9/main">
+//      <x14:dataValidations count="1" xmlns:xm="http://schemas.microsoft.com/office/excel/2006/main">
+//        <x14:dataValidation type="list" allowBlank="1" showInputMessage="1" showErrorMessage="1">
+//          <x14:formula1>
+//            <xm:f>Sheet1!$A$2:$A$272</xm:f>
+//          </x14:formula1>
+//          <xm:sqref>A6:A22</xm:sqref>
+//        </x14:dataValidation>
+//      </x14:dataValidations>
+//    </ext>
+//  </extLst>
+
+class ExtDataValidationsContext : public WorksheetContextBase, private DataValidationsContext_Base
+{
+public:
+    explicit            ExtDataValidationsContext( WorksheetContextBase& rFragment );
 
+protected:
+    virtual ::oox::core::ContextHandlerRef onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs ) override;
+    virtual void        onCharacters( const OUString& rChars ) override;
+    virtual void        onEndElement() override;
 private:
-    ::std::unique_ptr< ValidationModel > mxValModel;
+    sal_Int32 mCurrFormula;
 };
 
 class WorksheetFragment : public WorksheetFragmentBase
diff --git a/sc/source/filter/oox/extlstcontext.cxx b/sc/source/filter/oox/extlstcontext.cxx
index 1739bcb..0633ccb 100644
--- a/sc/source/filter/oox/extlstcontext.cxx
+++ b/sc/source/filter/oox/extlstcontext.cxx
@@ -226,9 +226,11 @@ ExtGlobalContext::ExtGlobalContext( WorksheetContextBase& rFragment ):
 
 ContextHandlerRef ExtGlobalContext::onCreateContext( sal_Int32 nElement, const AttributeList& /*rAttribs*/ )
 {
-    if (nElement == XLS14_TOKEN(conditionalFormatting))
-        return new ExtConditionalFormattingContext(*this);
-
+    switch (nElement)
+    {
+        case XLS14_TOKEN(conditionalFormatting): return new ExtConditionalFormattingContext(*this);
+        case XLS14_TOKEN(dataValidations):       return new ExtDataValidationsContext(*this);
+    }
     return this;
 }
 
diff --git a/sc/source/filter/oox/worksheetfragment.cxx b/sc/source/filter/oox/worksheetfragment.cxx
index cf78321..660d3ad 100644
--- a/sc/source/filter/oox/worksheetfragment.cxx
+++ b/sc/source/filter/oox/worksheetfragment.cxx
@@ -75,6 +75,81 @@ const sal_uInt16 BIFF12_OLEOBJECT_AUTOLOAD  = 0x0002;
 
 } // namespace
 
+void DataValidationsContext_Base::SetValidation(::oox::xls::WorksheetHelper& rTarget)
+{
+    if (!mxValModel.get())
+        return;
+
+    rTarget.getAddressConverter().convertToCellRangeList(mxValModel->maRanges, mSqref, rTarget.getSheetIndex(), true);
+    mxValModel->msRef = mSqref;
+
+    mxValModel->maTokens1 = rTarget.getFormulaParser().importFormula(mxValModel->maRanges.getBaseAddress(), mFormula1);
+    // process string list of a list validation (convert to list of string tokens)
+    if (mxValModel->mnType == XML_list)
+        rTarget.getFormulaParser().convertStringToStringList(mxValModel->maTokens1, ',', true);
+
+    mxValModel->maTokens2 = rTarget.getFormulaParser().importFormula(mxValModel->maRanges.getBaseAddress(), mFormula2);
+
+    rTarget.setValidation(*mxValModel);
+    mxValModel.reset();
+}
+
+void DataValidationsContext_Base::importDataValidation(const AttributeList& rAttribs)
+{
+    mxValModel.reset(new ValidationModel);
+    mFormula1.clear();
+    mFormula2.clear();
+    mSqref = rAttribs.getString(XML_sqref, OUString());
+    mxValModel->maInputTitle = rAttribs.getXString(XML_promptTitle, OUString());
+    mxValModel->maInputMessage = rAttribs.getXString(XML_prompt, OUString());
+    mxValModel->maErrorTitle = rAttribs.getXString(XML_errorTitle, OUString());
+    mxValModel->maErrorMessage = rAttribs.getXString(XML_error, OUString());
+    mxValModel->mnType = rAttribs.getToken(XML_type, XML_none);
+    mxValModel->mnOperator = rAttribs.getToken(XML_operator, XML_between);
+    mxValModel->mnErrorStyle = rAttribs.getToken(XML_errorStyle, XML_stop);
+    mxValModel->mbShowInputMsg = rAttribs.getBool(XML_showInputMessage, false);
+    mxValModel->mbShowErrorMsg = rAttribs.getBool(XML_showErrorMessage, false);
+    /*  The attribute showDropDown at dataValidation is in fact a "suppress
+    dropdown" flag, as it was in the BIFF format! ECMA specification
+    and attribute name are plain wrong! */
+    mxValModel->mbNoDropDown = rAttribs.getBool(XML_showDropDown, false);
+    mxValModel->mbAllowBlank = rAttribs.getBool(XML_allowBlank, false);
+}
+
+void DataValidationsContext_Base::importDataValidation(SequenceInputStream& rStrm, ::oox::xls::WorksheetHelper& rTarget)
+{
+    ValidationModel aModel;
+
+    sal_uInt32 nFlags;
+    BinRangeList aRanges;
+    nFlags = rStrm.readuInt32();
+    rStrm >> aRanges >> aModel.maErrorTitle >> aModel.maErrorMessage >> aModel.maInputTitle >> aModel.maInputMessage;
+
+    // equal flags in all BIFFs
+    aModel.setBiffType(extractValue< sal_uInt8 >(nFlags, 0, 4));
+    aModel.setBiffOperator(extractValue< sal_uInt8 >(nFlags, 20, 4));
+    aModel.setBiffErrorStyle(extractValue< sal_uInt8 >(nFlags, 4, 3));
+    aModel.mbAllowBlank = getFlag(nFlags, BIFF_DATAVAL_ALLOWBLANK);
+    aModel.mbNoDropDown = getFlag(nFlags, BIFF_DATAVAL_NODROPDOWN);
+    aModel.mbShowInputMsg = getFlag(nFlags, BIFF_DATAVAL_SHOWINPUT);
+    aModel.mbShowErrorMsg = getFlag(nFlags, BIFF_DATAVAL_SHOWERROR);
+
+    // cell range list
+    rTarget.getAddressConverter().convertToCellRangeList(aModel.maRanges, aRanges, rTarget.getSheetIndex(), true);
+
+    // condition formula(s)
+    FormulaParser& rParser = rTarget.getFormulaParser();
+    CellAddress aBaseAddr = aModel.maRanges.getBaseAddress();
+    aModel.maTokens1 = rParser.importFormula(aBaseAddr, FORMULATYPE_VALIDATION, rStrm);
+    aModel.maTokens2 = rParser.importFormula(aBaseAddr, FORMULATYPE_VALIDATION, rStrm);
+    // process string list of a list validation (convert to list of string tokens)
+    if ((aModel.mnType == XML_list) && getFlag(nFlags, BIFF_DATAVAL_STRINGLIST))
+        rParser.convertStringToStringList(aModel.maTokens1, ',', true);
+
+    // set validation data
+    rTarget.setValidation(aModel);
+}
+
 DataValidationsContext::DataValidationsContext( WorksheetFragmentBase& rFragment ) :
     WorksheetContextBase( rFragment )
 {
@@ -82,7 +157,7 @@ DataValidationsContext::DataValidationsContext( WorksheetFragmentBase& rFragment
 
 ContextHandlerRef DataValidationsContext::onCreateContext( sal_Int32 nElement, const AttributeList& rAttribs )
 {
-    switch( getCurrentElement() )
+    switch( getCurrentElementWithMce() )
     {
         case XLS_TOKEN( dataValidations ):
             if( nElement == XLS_TOKEN( dataValidation ) )
@@ -94,100 +169,173 @@ ContextHandlerRef DataValidationsContext::onCreateContext( sal_Int32 nElement, c
         case XLS_TOKEN( dataValidation ):
             switch( nElement )
             {
+                case MCE_TOKEN( AlternateContent ):
                 case XLS_TOKEN( formula1 ):
                 case XLS_TOKEN( formula2 ):
                     return this;    // collect formulas in onCharacters()
             }
         break;
+        case MCE_TOKEN( AlternateContent ):
+            switch( nElement )
+            {
+                case MCE_TOKEN( Choice ):
+                case MCE_TOKEN( Fallback ):
+                    return this;
+            }
+        break;
+        case MCE_TOKEN( Choice ):
+            switch( nElement )
+            {
+                case X12AC_TOKEN( list ):
+                    return this;
+            }
+        break;
+        case MCE_TOKEN( Fallback ):
+            switch( nElement )
+            {
+                case XLS_TOKEN( formula1 ):
+                    if (!isFormula1Set()) // only if more preferable choice was not used
+                        return this;      // collect formulas in onCharacters()
+                break;
+                case XLS_TOKEN( formula2 ):
+                    if (!isFormula2Set()) // only if more preferable choice was not used
+                        return this;      // collect formulas in onCharacters()
+                break;
+            }
+        break;
     }
     return nullptr;
 }
 
+namespace {
+// Convert strings like 1,"2,3",4 to form "1","2,3","4"
+OUString NormalizeOoxList(const OUString& aList)
+{
+    OUStringBuffer aResult("\"");
+    bool bInsideQuotes = false;
+    const sal_Int32 nLen = aList.getLength();
+    for (sal_Int32 i = 0; i < nLen; ++i)
+    {
+        sal_Unicode ch = aList[i];
+
+        switch (ch)
+        {
+            case L'"':
+                bInsideQuotes = !bInsideQuotes;
+                break;
+            case L',':
+                if (!bInsideQuotes)
+                {
+                    aResult.append("\",\"");
+                    break;
+                }
+                SAL_FALLTHROUGH;
+            default:
+                aResult.append(ch);
+                break;
+        }
+    }
+    return aResult.append('"').makeStringAndClear();
+}
+}
+
 void DataValidationsContext::onCharacters( const OUString& rChars )
 {
-    if( mxValModel.get() ) switch( getCurrentElement() )
+    switch( getCurrentElement() )
     {
         case XLS_TOKEN( formula1 ):
-            mxValModel->maTokens1 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars );
-            // process string list of a list validation (convert to list of string tokens)
-            if( mxValModel->mnType == XML_list )
-                getFormulaParser().convertStringToStringList( mxValModel->maTokens1, ',', true );
+            SetFormula1( rChars );
         break;
         case XLS_TOKEN( formula2 ):
-            mxValModel->maTokens2 = getFormulaParser().importFormula( mxValModel->maRanges.getBaseAddress(), rChars );
+            SetFormula2( rChars );
+        break;
+        case X12AC_TOKEN( list ):
+            SetFormula1( NormalizeOoxList( rChars ) );
         break;
     }
 }
 
 void DataValidationsContext::onEndElement()
 {
-    if( isCurrentElement( XLS_TOKEN( dataValidation ) ) && mxValModel.get() )
+    if( getCurrentElementWithMce() == XLS_TOKEN( dataValidation ) )
     {
-        setValidation( *mxValModel );
-        mxValModel.reset();
+        SetValidation( *this );
     }
 }
 
 ContextHandlerRef DataValidationsContext::onCreateRecordContext( sal_Int32 nRecId, SequenceInputStream& rStrm )
 {
     if( nRecId == BIFF12_ID_DATAVALIDATION )
-        importDataValidation( rStrm );
+        importDataValidation( rStrm, *this );
     return nullptr;
 }
 
-void DataValidationsContext::importDataValidation( const AttributeList& rAttribs )
-{
-    mxValModel.reset( new ValidationModel );
-    getAddressConverter().convertToCellRangeList( mxValModel->maRanges, rAttribs.getString( XML_sqref, OUString() ), getSheetIndex(), true );
-    mxValModel->msRef          = rAttribs.getString( XML_sqref, OUString() );
-    mxValModel->maInputTitle   = rAttribs.getXString( XML_promptTitle, OUString() );
-    mxValModel->maInputMessage = rAttribs.getXString( XML_prompt, OUString() );
-    mxValModel->maErrorTitle   = rAttribs.getXString( XML_errorTitle, OUString() );
-    mxValModel->maErrorMessage = rAttribs.getXString( XML_error, OUString() );
-    mxValModel->mnType         = rAttribs.getToken( XML_type, XML_none );
-    mxValModel->mnOperator     = rAttribs.getToken( XML_operator, XML_between );
-    mxValModel->mnErrorStyle   = rAttribs.getToken( XML_errorStyle, XML_stop );
-    mxValModel->mbShowInputMsg = rAttribs.getBool( XML_showInputMessage, false );
-    mxValModel->mbShowErrorMsg = rAttribs.getBool( XML_showErrorMessage, false );
-    /*  The attribute showDropDown at dataValidation is in fact a "suppress
-        dropdown" flag, as it was in the BIFF format! ECMA specification
-        and attribute name are plain wrong! */
-    mxValModel->mbNoDropDown   = rAttribs.getBool( XML_showDropDown, false );
-    mxValModel->mbAllowBlank   = rAttribs.getBool( XML_allowBlank, false );
+ExtDataValidationsContext::ExtDataValidationsContext( WorksheetContextBase& rFragment ) :
+    WorksheetContextBase( rFragment ), mCurrFormula( 0 )
+{
 }
 
-void DataValidationsContext::importDataValidation( SequenceInputStream& rStrm )
+ContextHandlerRef ExtDataValidationsContext::onCreateContext(sal_Int32 nElement, const AttributeList& rAttribs)
 {
-    ValidationModel aModel;
-
-    sal_uInt32 nFlags;
-    BinRangeList aRanges;
-    nFlags = rStrm.readuInt32();
-    rStrm >> aRanges >> aModel.maErrorTitle >> aModel.maErrorMessage >> aModel.maInputTitle >> aModel.maInputMessage;
-
-    // equal flags in all BIFFs
-    aModel.setBiffType( extractValue< sal_uInt8 >( nFlags, 0, 4 ) );
-    aModel.setBiffOperator( extractValue< sal_uInt8 >( nFlags, 20, 4 ) );
-    aModel.setBiffErrorStyle( extractValue< sal_uInt8 >( nFlags, 4, 3 ) );
-    aModel.mbAllowBlank   = getFlag( nFlags, BIFF_DATAVAL_ALLOWBLANK );
-    aModel.mbNoDropDown   = getFlag( nFlags, BIFF_DATAVAL_NODROPDOWN );
-    aModel.mbShowInputMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWINPUT );
-    aModel.mbShowErrorMsg = getFlag( nFlags, BIFF_DATAVAL_SHOWERROR );
-
-    // cell range list
-    getAddressConverter().convertToCellRangeList( aModel.maRanges, aRanges, getSheetIndex(), true );
+    switch( getCurrentElement() )
+    {
+    case XLS14_TOKEN( dataValidations ):
+        if ( nElement == XLS14_TOKEN( dataValidation ) )
+        {
+            importDataValidation( rAttribs );
+            return this;
+        }
+        break;
+    case XLS14_TOKEN( dataValidation ):
+        switch ( nElement )
+        {
+        case XLS14_TOKEN( formula1 ):
+        case XLS14_TOKEN( formula2 ):
+            mCurrFormula = nElement;
+            return this;
+        case XM_TOKEN( sqref ):
+            return this;    // collect sqref in onCharacters()
+        }
+        break;
+    case XLS14_TOKEN( formula1 ):
+    case XLS14_TOKEN( formula2 ):
+        switch( nElement )
+        {
+        case XM_TOKEN( f ):
+            return this;    // collect formulas in onCharacters()
+        }
+        break;
+    }
+    return nullptr;
+}
 
-    // condition formula(s)
-    FormulaParser& rParser = getFormulaParser();
-    CellAddress aBaseAddr = aModel.maRanges.getBaseAddress();
-    aModel.maTokens1 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm );
-    aModel.maTokens2 = rParser.importFormula( aBaseAddr, FORMULATYPE_VALIDATION, rStrm );
-    // process string list of a list validation (convert to list of string tokens)
-    if( (aModel.mnType == XML_list) && getFlag( nFlags, BIFF_DATAVAL_STRINGLIST ) )
-        rParser.convertStringToStringList( aModel.maTokens1, ',', true );
+void ExtDataValidationsContext::onCharacters( const OUString& rChars )
+{
+    switch( getCurrentElement() )
+    {
+        case XM_TOKEN( f ):
+            switch( mCurrFormula )
+            {
+                case XLS14_TOKEN( formula1 ):
+                    SetFormula1( rChars );
+                break;
+                case XLS14_TOKEN( formula2 ):
+                    SetFormula2( rChars );
+                break;
+            }
+        break;
+        case XM_TOKEN( sqref ):
+            SetSqref( rChars );
+        break;
+    }
+}
 
-    // set validation data
-    setValidation( aModel );
+void ExtDataValidationsContext::onEndElement()
+{
+    if( isCurrentElement( XLS14_TOKEN( dataValidation ) ) )
+    {
+        SetValidation( *this );
+    }
 }
 
 WorksheetFragment::WorksheetFragment( const WorksheetHelper& rHelper, const OUString& rFragmentPath ) :


More information about the Libreoffice-commits mailing list