summaryrefslogtreecommitdiffstats
path: root/sc/source/filter/xml/xmltabi.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/xml/xmltabi.cxx')
-rw-r--r--sc/source/filter/xml/xmltabi.cxx470
1 files changed, 470 insertions, 0 deletions
diff --git a/sc/source/filter/xml/xmltabi.cxx b/sc/source/filter/xml/xmltabi.cxx
new file mode 100644
index 000000000..217e08beb
--- /dev/null
+++ b/sc/source/filter/xml/xmltabi.cxx
@@ -0,0 +1,470 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "xmltabi.hxx"
+#include "xmlimprt.hxx"
+#include "xmlrowi.hxx"
+#include "xmlcoli.hxx"
+#include "xmlsceni.hxx"
+#include "xmlexternaltabi.hxx"
+#include "xmlnexpi.hxx"
+#include <document.hxx>
+#include <docuno.hxx>
+#include <olinetab.hxx>
+#include "XMLTableShapesContext.hxx"
+#include "XMLTableSourceContext.hxx"
+#include "XMLStylesImportHelper.hxx"
+#include <rangeutl.hxx>
+#include <externalrefmgr.hxx>
+#include <sheetdata.hxx>
+#include "xmlcondformat.hxx"
+#include "SparklineGroupsImportContext.hxx"
+
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/xmlnamespace.hxx>
+#include <xmloff/XMLEventsImportContext.hxx>
+
+#include <tools/urlobj.hxx>
+#include <sax/fastattribs.hxx>
+#include <com/sun/star/sheet/XSpreadsheet.hpp>
+#include <comphelper/servicehelper.hxx>
+
+using namespace com::sun::star;
+using namespace xmloff::token;
+using ::com::sun::star::uno::Reference;
+using ::com::sun::star::uno::UNO_QUERY;
+using ::com::sun::star::xml::sax::XAttributeList;
+
+/**
+ * Determine whether this table is an external reference cache from its
+ * name. There is currently no way of determining whether a table is a
+ * regular table or an external reference cache other than examining the
+ * name itself. We should probably introduce a new boolean value for
+ * table:table element and use it instead of doing this, to make it more
+ * reliable and future-proof.
+ *
+ * @param rName
+ *
+ * @return
+ */
+static bool lcl_isExternalRefCache(const OUString& rName, OUString& rUrl, OUString& rExtTabName)
+{
+ // 'file:///path/to/file.ods'#MySheet
+ // 'file:///path/to/file.ods'#MySheet with space
+ // 'file:///path/to/file's.ods'#Sheet (Notice the quote in the file name.
+ // That's allowed.)
+
+ if ( rName.toChar() != '\'' ) // initial quote
+ return false;
+
+ // #i114504# Other schemes besides "file:" are also allowed.
+ // CompareProtocolScheme is quick, only looks at the start of the string.
+ INetProtocol eProt = INetURLObject::CompareProtocolScheme( rName.subView(1) );
+ if ( eProt == INetProtocol::NotValid )
+ return false;
+
+ OUString aPrefix = INetURLObject::GetScheme( eProt );
+ sal_Int32 nPrefLen = aPrefix.getLength();
+
+ OUStringBuffer aUrlBuf, aTabNameBuf;
+ aUrlBuf.append( aPrefix );
+ sal_Int32 n = rName.getLength();
+ const sal_Unicode* p = rName.getStr();
+
+ bool bInUrl = true;
+ sal_Unicode cPrev = 0;
+ for (sal_Int32 i = nPrefLen+1; i < n; ++i) // start the loop after quote and prefix
+ {
+ const sal_Unicode c = p[i];
+ if (bInUrl)
+ {
+ // parsing file URL
+ if (c == '#')
+ {
+ if (cPrev != '\'')
+ return false;
+
+ rUrl = aUrlBuf.makeStringAndClear();
+ rUrl = rUrl.copy(0, rUrl.getLength()-1); // remove the trailing single-quote.
+ bInUrl = false;
+ }
+ else
+ aUrlBuf.append(c);
+ }
+ else
+ // parsing sheet name.
+ aTabNameBuf.append(c);
+
+ cPrev = c;
+ }
+
+ if (bInUrl)
+ return false;
+
+ if (aTabNameBuf.isEmpty())
+ return false;
+
+ rExtTabName = aTabNameBuf.makeStringAndClear();
+
+ return true;
+}
+
+ScXMLExternalTabData::ScXMLExternalTabData() :
+ mnRow(0), mnCol(0), mnFileId(0)
+{
+}
+
+ScXMLTableContext::ScXMLTableContext( ScXMLImport& rImport,
+ const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList ) :
+ ScXMLImportContext( rImport ),
+ nStartOffset(-1),
+ bStartFormPage(false),
+ bPrintEntireSheet(true)
+{
+ // get start offset in file (if available)
+ nStartOffset = GetScImport().GetByteOffset();
+
+ ScXMLTabProtectionData aProtectData;
+ OUString sName;
+ OUString sStyleName;
+
+ if ( rAttrList.is() )
+ {
+ for (auto &it : *rAttrList)
+ {
+ switch (it.getToken())
+ {
+ case XML_ELEMENT( TABLE, XML_NAME ):
+ sName = it.toString();
+ break;
+ case XML_ELEMENT( TABLE, XML_STYLE_NAME ):
+ sStyleName = it.toString();
+ break;
+ case XML_ELEMENT( TABLE, XML_PROTECTED ):
+ aProtectData.mbProtected = IsXMLToken( it, XML_TRUE );
+ break;
+ case XML_ELEMENT( TABLE, XML_PRINT_RANGES ):
+ sPrintRanges = it.toString();
+ break;
+ case XML_ELEMENT( TABLE, XML_PROTECTION_KEY ):
+ aProtectData.maPassword = it.toString();
+ break;
+ case XML_ELEMENT( TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM ):
+ aProtectData.meHash1 = ScPassHashHelper::getHashTypeFromURI( it.toString() );
+ break;
+ case XML_ELEMENT( TABLE, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2 ):
+ case XML_ELEMENT( LO_EXT, XML_PROTECTION_KEY_DIGEST_ALGORITHM_2 ):
+ aProtectData.meHash2 = ScPassHashHelper::getHashTypeFromURI( it.toString() );
+ break;
+ case XML_ELEMENT( TABLE, XML_PRINT ):
+ {
+ if ( IsXMLToken( it, XML_FALSE) )
+ bPrintEntireSheet = false;
+ }
+ break;
+ }
+
+ }
+ }
+
+ OUString aExtUrl, aExtTabName;
+ if (lcl_isExternalRefCache(sName, aExtUrl, aExtTabName))
+ {
+ // This is an external ref cache table.
+ pExternalRefInfo.reset(new ScXMLExternalTabData);
+ ScDocument* pDoc = GetScImport().GetDocument();
+ if (pDoc)
+ {
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ pExternalRefInfo->mnFileId = pRefMgr->getExternalFileId(aExtUrl);
+ pExternalRefInfo->mpCacheTable = pRefMgr->getCacheTable(pExternalRefInfo->mnFileId, aExtTabName, true,
+ nullptr, &aExtUrl);
+ pExternalRefInfo->mpCacheTable->setWholeTableCached();
+ }
+ }
+ else
+ {
+ // This is a regular table.
+ GetScImport().GetTables().NewSheet(sName, sStyleName, aProtectData);
+ }
+}
+
+ScXMLTableContext::~ScXMLTableContext()
+{
+}
+
+uno::Reference< xml::sax::XFastContextHandler > SAL_CALL
+ ScXMLTableContext::createFastChildContext( sal_Int32 nElement,
+ const uno::Reference< xml::sax::XFastAttributeList > & xAttrList )
+{
+ sax_fastparser::FastAttributeList *pAttribList =
+ &sax_fastparser::castToFastAttributeList( xAttrList );
+
+ if (pExternalRefInfo)
+ {
+ // We only care about the table-row and table-source elements for
+ // external cache data.
+ switch ( nElement )
+ {
+ case XML_ELEMENT( TABLE, XML_TABLE_ROW_GROUP ):
+ case XML_ELEMENT( TABLE, XML_TABLE_HEADER_ROWS ):
+ case XML_ELEMENT( TABLE, XML_TABLE_ROWS ):
+ // #i101319# don't discard rows in groups or header (repeat range)
+ return new ScXMLExternalRefRowsContext(
+ GetScImport(), *pExternalRefInfo);
+ case XML_ELEMENT( TABLE, XML_TABLE_ROW ):
+ return new ScXMLExternalRefRowContext(
+ GetScImport(), pAttribList, *pExternalRefInfo);
+ case XML_ELEMENT( TABLE, XML_TABLE_SOURCE ):
+ return new ScXMLExternalRefTabSourceContext(
+ GetScImport(), pAttribList, *pExternalRefInfo);
+ default:
+ ;
+ }
+ return nullptr;
+ }
+
+ SvXMLImportContext *pContext(nullptr);
+
+ switch ( nElement )
+ {
+ case XML_ELEMENT( TABLE, XML_NAMED_EXPRESSIONS ):
+ {
+ SCTAB nTab = GetScImport().GetTables().GetCurrentSheet();
+ pContext = new ScXMLNamedExpressionsContext(
+ GetScImport(),
+ std::make_shared<ScXMLNamedExpressionsContext::SheetLocalInserter>(GetScImport(), nTab));
+ }
+ break;
+ case XML_ELEMENT( TABLE, XML_TABLE_COLUMN_GROUP ):
+ pContext = new ScXMLTableColsContext( GetScImport(), pAttribList,
+ false, true );
+ break;
+ case XML_ELEMENT( TABLE, XML_TABLE_HEADER_COLUMNS ):
+ pContext = new ScXMLTableColsContext( GetScImport(), pAttribList,
+ true, false );
+ break;
+ case XML_ELEMENT( TABLE, XML_TABLE_COLUMNS ):
+ pContext = new ScXMLTableColsContext( GetScImport(), pAttribList,
+ false, false );
+ break;
+ case XML_ELEMENT( TABLE, XML_TABLE_COLUMN ):
+ pContext = new ScXMLTableColContext( GetScImport(), pAttribList );
+ break;
+ case XML_ELEMENT( TABLE, XML_TABLE_PROTECTION ):
+ case XML_ELEMENT( LO_EXT, XML_TABLE_PROTECTION ):
+ case XML_ELEMENT( OFFICE_EXT, XML_TABLE_PROTECTION ):
+ pContext = new ScXMLTableProtectionContext( GetScImport(), pAttribList );
+ break;
+ case XML_ELEMENT( TABLE, XML_TABLE_ROW_GROUP ):
+ pContext = new ScXMLTableRowsContext( GetScImport(), pAttribList,
+ false, true );
+ break;
+ case XML_ELEMENT( TABLE, XML_TABLE_HEADER_ROWS ):
+ pContext = new ScXMLTableRowsContext( GetScImport(), pAttribList,
+ true, false );
+ break;
+ case XML_ELEMENT( TABLE, XML_TABLE_ROWS ):
+ pContext = new ScXMLTableRowsContext( GetScImport(), pAttribList,
+ false, false );
+ break;
+ case XML_ELEMENT( TABLE, XML_TABLE_ROW ):
+ pContext = new ScXMLTableRowContext( GetScImport(), pAttribList );
+ break;
+ case XML_ELEMENT( TABLE, XML_TABLE_SOURCE ):
+ pContext = new ScXMLTableSourceContext( GetScImport(), pAttribList);
+ break;
+ case XML_ELEMENT( TABLE, XML_SCENARIO ):
+ pContext = new ScXMLTableScenarioContext( GetScImport(), pAttribList);
+ break;
+ case XML_ELEMENT( TABLE, XML_SHAPES ):
+ pContext = new ScXMLTableShapesContext( GetScImport() );
+ break;
+ case XML_ELEMENT( CALC_EXT, XML_CONDITIONAL_FORMATS ):
+ pContext = new ScXMLConditionalFormatsContext( GetScImport() );
+ break;
+ case XML_ELEMENT(CALC_EXT, XML_SPARKLINE_GROUPS):
+ pContext = new sc::SparklineGroupsImportContext(GetScImport());
+ break;
+ case XML_ELEMENT(OFFICE, XML_EVENT_LISTENERS):
+ case XML_ELEMENT(OFFICE_EXT, XML_EVENT_LISTENERS):
+ {
+ // use XEventsSupplier interface of the sheet
+ uno::Reference<document::XEventsSupplier> xSupplier( GetScImport().GetTables().GetCurrentXSheet(), uno::UNO_QUERY );
+ pContext = new XMLEventsImportContext( GetImport(), xSupplier );
+ }
+ break;
+ case XML_ELEMENT(OFFICE, XML_FORMS):
+ {
+ GetScImport().GetFormImport()->startPage(GetScImport().GetTables().GetCurrentXDrawPage());
+ bStartFormPage = true;
+ pContext = xmloff::OFormLayerXMLImport::createOfficeFormsContext( GetScImport() );
+ }
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN_ELEMENT("sc", nElement);
+ break;
+ }
+
+ return pContext;
+}
+
+void SAL_CALL ScXMLTableContext::endFastElement(sal_Int32 /*nElement*/)
+{
+ ScXMLImport::MutexGuard aMutexGuard(GetScImport());
+ ScXMLImport& rImport = GetScImport();
+ rImport.GetStylesImportHelper()->EndTable();
+ ScDocument* pDoc(rImport.GetDocument());
+ if (!pDoc)
+ return;
+
+ ScMyTables& rTables = rImport.GetTables();
+ SCTAB nCurTab = rTables.GetCurrentSheet();
+ // tdf#51022 process only print ranges of internal sheets
+ if (!pExternalRefInfo)
+ {
+ if (!sPrintRanges.isEmpty())
+ {
+ ScRangeList aRangeList;
+ ScRangeStringConverter::GetRangeListFromString(aRangeList, sPrintRanges, *pDoc, ::formula::FormulaGrammar::CONV_OOO);
+ size_t nCount = aRangeList.size();
+ for (size_t i = 0; i < nCount; i++)
+ {
+ pDoc->AddPrintRange(nCurTab, aRangeList[i]);
+ }
+ }
+ else if (!bPrintEntireSheet)
+ // Sheet has "print entire sheet" option by default. Remove it.
+ pDoc->ClearPrintRanges(nCurTab);
+ }
+
+ ScOutlineTable* pOutlineTable(pDoc->GetOutlineTable(nCurTab));
+ if (pOutlineTable)
+ {
+ ScOutlineArray& rColArray(pOutlineTable->GetColArray());
+ size_t nDepth = rColArray.GetDepth();
+ for (size_t i = 0; i < nDepth; ++i)
+ {
+ size_t nCount = rColArray.GetCount(i);
+ for (size_t j = 0; j < nCount; ++j)
+ {
+ const ScOutlineEntry* pEntry = rColArray.GetEntry(i, j);
+ if (pEntry->IsHidden())
+ rColArray.SetVisibleBelow(i, j, false);
+ }
+ }
+ ScOutlineArray& rRowArray(pOutlineTable->GetRowArray());
+ nDepth = rRowArray.GetDepth();
+ for (size_t i = 0; i < nDepth; ++i)
+ {
+ size_t nCount = rRowArray.GetCount(i);
+ for (size_t j = 0; j < nCount; ++j)
+ {
+ const ScOutlineEntry* pEntry = rRowArray.GetEntry(i, j);
+ if (pEntry->IsHidden())
+ rRowArray.SetVisibleBelow(i, j, false);
+ }
+ }
+ }
+ if (rTables.HasDrawPage())
+ {
+ if (rTables.HasXShapes())
+ {
+ rImport.GetShapeImport()->popGroupAndPostProcess();
+ uno::Reference < drawing::XShapes > xTempShapes(rTables.GetCurrentXShapes());
+ rImport.GetShapeImport()->endPage(xTempShapes);
+ }
+ if (bStartFormPage)
+ rImport.GetFormImport()->endPage();
+ }
+
+ rTables.DeleteTable();
+ rImport.ProgressBarIncrement();
+
+ // store stream positions
+ if (!pExternalRefInfo && nStartOffset >= 0 /* && nEndOffset >= 0 */)
+ {
+ ScSheetSaveData* pSheetData = comphelper::getFromUnoTunnel<ScModelObj>(rImport.GetModel())->GetSheetSaveData();
+ SCTAB nTab = rTables.GetCurrentSheet();
+ // pSheetData->AddStreamPos( nTab, nStartOffset, nEndOffset );
+ pSheetData->StartStreamPos( nTab, nStartOffset );
+ }
+}
+
+ScXMLTableProtectionContext::ScXMLTableProtectionContext(
+ ScXMLImport& rImport,
+ const rtl::Reference<sax_fastparser::FastAttributeList>& rAttrList ) :
+ ScXMLImportContext( rImport )
+{
+ bool bSelectProtectedCells = false;
+ bool bSelectUnprotectedCells = false;
+ bool bInsertColumns = false;
+ bool bInsertRows = false;
+ bool bDeleteColumns = false;
+ bool bDeleteRows = false;
+
+ if ( rAttrList.is() )
+ {
+ for (auto &aIter : *rAttrList)
+ {
+ sal_Int32 nToken = aIter.getToken();
+ switch (nToken)
+ {
+ case XML_ELEMENT( TABLE, XML_SELECT_PROTECTED_CELLS ):
+ case XML_ELEMENT( OFFICE_EXT, XML_SELECT_PROTECTED_CELLS ):
+ case XML_ELEMENT( LO_EXT, XML_SELECT_PROTECTED_CELLS ):
+ bSelectProtectedCells = IsXMLToken(aIter, XML_TRUE);
+ break;
+ case XML_ELEMENT( TABLE, XML_SELECT_UNPROTECTED_CELLS ):
+ case XML_ELEMENT( OFFICE_EXT, XML_SELECT_UNPROTECTED_CELLS ):
+ case XML_ELEMENT( LO_EXT, XML_SELECT_UNPROTECTED_CELLS ):
+ bSelectUnprotectedCells = IsXMLToken(aIter, XML_TRUE);
+ break;
+ case XML_ELEMENT( LO_EXT, XML_INSERT_COLUMNS ):
+ bInsertColumns = IsXMLToken(aIter, XML_TRUE);
+ break;
+ case XML_ELEMENT( LO_EXT, XML_INSERT_ROWS ):
+ bInsertRows = IsXMLToken(aIter, XML_TRUE);
+ break;
+ case XML_ELEMENT( LO_EXT, XML_DELETE_COLUMNS ):
+ bDeleteColumns = IsXMLToken(aIter, XML_TRUE);
+ break;
+ case XML_ELEMENT( LO_EXT, XML_DELETE_ROWS ):
+ bDeleteRows = IsXMLToken(aIter, XML_TRUE);
+ break;
+ default:
+ XMLOFF_WARN_UNKNOWN("sc", aIter);
+ }
+ }
+ }
+
+ ScXMLTabProtectionData& rProtectData = GetScImport().GetTables().GetCurrentProtectionData();
+ rProtectData.mbSelectProtectedCells = bSelectProtectedCells;
+ rProtectData.mbSelectUnprotectedCells = bSelectUnprotectedCells;
+ rProtectData.mbInsertColumns = bInsertColumns;
+ rProtectData.mbInsertRows = bInsertRows;
+ rProtectData.mbDeleteColumns = bDeleteColumns;
+ rProtectData.mbDeleteRows = bDeleteRows;
+}
+
+ScXMLTableProtectionContext::~ScXMLTableProtectionContext()
+{
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */