diff options
Diffstat (limited to '')
-rw-r--r-- | xmloff/source/table/XMLTableImport.cxx | 808 |
1 files changed, 808 insertions, 0 deletions
diff --git a/xmloff/source/table/XMLTableImport.cxx b/xmloff/source/table/XMLTableImport.cxx new file mode 100644 index 000000000..47923d66c --- /dev/null +++ b/xmloff/source/table/XMLTableImport.cxx @@ -0,0 +1,808 @@ +/* -*- 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 <sal/config.h> + +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/table/XTableRows.hpp> +#include <com/sun/star/table/XMergeableCell.hpp> +#include <com/sun/star/table/XMergeableCellRange.hpp> +#include <com/sun/star/table/XTable.hpp> +#include <com/sun/star/text/XText.hpp> +#include <com/sun/star/container/XNameContainer.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <com/sun/star/style/XStyle.hpp> +#include <comphelper/sequence.hxx> +#include <tools/diagnose_ex.h> + +#include <xmloff/table/XMLTableImport.hxx> +#include <xmloff/xmlprmap.hxx> +#include <xmloff/txtimp.hxx> +#include <xmloff/xmlimp.hxx> +#include <xmloff/namespacemap.hxx> +#include <xmloff/xmlstyle.hxx> +#include <xmloff/prstylei.hxx> + +#include <xmloff/xmlnamespace.hxx> +#include <xmloff/xmluconv.hxx> +#include "table.hxx" + +#include <sal/log.hxx> + +#include <memory> + +using namespace ::xmloff::token; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::table; +using namespace ::com::sun::star::xml::sax; +using namespace ::com::sun::star::text; +using namespace ::com::sun::star::style; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::container; + +namespace { + +struct ColumnInfo +{ + OUString msStyleName; + OUString msDefaultCellStyleName; +}; + +class XMLProxyContext : public SvXMLImportContext +{ +public: + XMLProxyContext( SvXMLImport& rImport, const SvXMLImportContextRef& xParent ); + + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override; + +private: + SvXMLImportContextRef mxParent; +}; + +struct MergeInfo +{ + sal_Int32 mnStartColumn; + sal_Int32 mnStartRow; + sal_Int32 mnEndColumn; + sal_Int32 mnEndRow; + + MergeInfo( sal_Int32 nStartColumn, sal_Int32 nStartRow, sal_Int32 nColumnSpan, sal_Int32 nRowSpan ) + : mnStartColumn( nStartColumn ), mnStartRow( nStartRow ), mnEndColumn( nStartColumn + nColumnSpan - 1 ), mnEndRow( nStartRow + nRowSpan - 1 ) {}; +}; + +} + +class XMLTableImportContext : public SvXMLImportContext +{ +public: + XMLTableImportContext( const rtl::Reference< XMLTableImport >& xThis, Reference< XColumnRowRange > const & xColumnRowRange ); + + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override; + + virtual void SAL_CALL endFastElement(sal_Int32 nElement) override; + + void InitColumns(); + + SvXMLImportContextRef ImportColumn( const Reference< XFastAttributeList >& xAttrList ); + SvXMLImportContext * ImportRow( const Reference< XFastAttributeList >& xAttrList ); + SvXMLImportContextRef ImportCell( sal_Int32 nElement, const Reference< XFastAttributeList >& xAttrList ); + + OUString GetDefaultCellStyleName() const; + + css::uno::Reference< css::table::XTable > mxTable; + Reference< XTableColumns > mxColumns; + Reference< XTableRows > mxRows; + + std::vector< std::shared_ptr< ColumnInfo > > maColumnInfos; + sal_Int32 mnCurrentRow; + sal_Int32 mnCurrentColumn; + + // default cell style name for the current row + OUString msDefaultCellStyleName; + + std::vector< std::shared_ptr< MergeInfo > > maMergeInfos; +}; + +namespace { + +class XMLCellImportContext : public SvXMLImportContext +{ +public: + XMLCellImportContext( SvXMLImport& rImport, + const Reference< XMergeableCell >& xCell, + const OUString& sDefaultCellStyleName, + sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ); + + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) override; + + virtual void SAL_CALL endFastElement(sal_Int32 nElement) override; + + sal_Int32 getColumnSpan() const { return mnColSpan; } + sal_Int32 getRowSpan() const { return mnRowSpan; } + sal_Int32 getRepeated() const { return mnRepeated; } + + Reference< XMergeableCell > mxCell; + Reference< XTextCursor > mxCursor; + Reference< XTextCursor > mxOldCursor; + bool mbListContextPushed; + + sal_Int32 mnColSpan, mnRowSpan, mnRepeated; +}; + +class XMLTableTemplateContext : public SvXMLStyleContext +{ +public: + XMLTableTemplateContext( SvXMLImport& rImport ); + + // Create child element. + virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext( + sal_Int32 nElement, const css::uno::Reference< css::xml::sax::XFastAttributeList >& AttrList ) override; + + virtual void SAL_CALL endFastElement(sal_Int32 nElement) override; + + virtual void CreateAndInsert( bool bOverwrite ) override; +protected: + virtual void SetAttribute( sal_Int32 nElement, + const OUString& rValue ) override; +private: + XMLTableTemplate maTableTemplate; + OUString msTemplateStyleName; +}; + +} + + +XMLProxyContext::XMLProxyContext( SvXMLImport& rImport, const SvXMLImportContextRef& xParent ) +: SvXMLImportContext( rImport ) +, mxParent( xParent ) +{ +} + +css::uno::Reference< css::xml::sax::XFastContextHandler > XMLProxyContext::createFastChildContext( sal_Int32 nElement, const Reference< XFastAttributeList >& xAttrList ) +{ + if( mxParent.is() ) + return mxParent->createFastChildContext( nElement, xAttrList ); + return nullptr; +} + + +XMLTableImport::XMLTableImport( SvXMLImport& rImport, const rtl::Reference< XMLPropertySetMapper >& xCellPropertySetMapper, const rtl::Reference< XMLPropertyHandlerFactory >& xFactoryRef ) +: mrImport( rImport ) +{ + bool bWriter = false; + // check if called by Writer + Reference<XMultiServiceFactory> xFac(rImport.GetModel(), UNO_QUERY); + if (xFac.is()) try + { + Sequence<OUString> sSNS = xFac->getAvailableServiceNames(); + bWriter = comphelper::findValue(sSNS, "com.sun.star.style.TableStyle") != -1; + } + catch(const Exception&) + { + SAL_WARN("xmloff.table", "Error while checking available service names"); + } + + if (bWriter) + { + mxCellImportPropertySetMapper = XMLTextImportHelper::CreateTableCellExtPropMapper(rImport); + } + else + { + mxCellImportPropertySetMapper = new SvXMLImportPropertyMapper( xCellPropertySetMapper, rImport ); + mxCellImportPropertySetMapper->ChainImportMapper(XMLTextImportHelper::CreateParaExtPropMapper(rImport)); + mxCellImportPropertySetMapper->ChainImportMapper(new SvXMLImportPropertyMapper(new XMLPropertySetMapper(getCellPropertiesMap(), xFactoryRef, true), rImport)); + } + + rtl::Reference < XMLPropertySetMapper > xRowMapper( new XMLPropertySetMapper( getRowPropertiesMap(), xFactoryRef, false ) ); + mxRowImportPropertySetMapper = new SvXMLImportPropertyMapper( xRowMapper, rImport ); + + rtl::Reference < XMLPropertySetMapper > xColMapper( new XMLPropertySetMapper( getColumnPropertiesMap(), xFactoryRef, false ) ); + mxColumnImportPropertySetMapper = new SvXMLImportPropertyMapper( xColMapper, rImport ); +} + +XMLTableImport::~XMLTableImport() +{ +} + +SvXMLImportContext* XMLTableImport::CreateTableContext( Reference< XColumnRowRange > const & xColumnRowRange ) +{ + rtl::Reference< XMLTableImport > xThis( this ); + return new XMLTableImportContext( xThis, xColumnRowRange ); +} + +SvXMLStyleContext* XMLTableImport::CreateTableTemplateContext( sal_Int32 /*nElement*/, const Reference< XFastAttributeList >& /*xAttrList*/ ) +{ + return new XMLTableTemplateContext( mrImport ); +} + +void XMLTableImport::addTableTemplate( const OUString& rsStyleName, XMLTableTemplate& xTableTemplate ) +{ + auto xPtr = std::make_shared<XMLTableTemplate>(); + xPtr->swap( xTableTemplate ); + maTableTemplates[rsStyleName] = xPtr; +} + +void XMLTableImport::insertTabletemplate(const OUString& rsStyleName, bool bOverwrite) +{ + XMLTableTemplateMap::iterator it = maTableTemplates.find(rsStyleName); + if (it == maTableTemplates.end()) + return; + + try + { + Reference<XStyleFamiliesSupplier> xFamiliesSupp(mrImport.GetModel(), UNO_QUERY_THROW); + Reference<XNameAccess> xFamilies(xFamiliesSupp->getStyleFamilies()); + + Reference<XNameContainer> xTableFamily(xFamilies->getByName("TableStyles"), UNO_QUERY_THROW); + Reference<XIndexAccess> xCellFamily(xFamilies->getByName("CellStyles"), UNO_QUERY_THROW); + + const OUString sTemplateName(it->first); + Reference<XMultiServiceFactory> xFactory(mrImport.GetModel(), UNO_QUERY_THROW); + Reference<XNameReplace> xTemplate(xFactory->createInstance("com.sun.star.style.TableStyle"), UNO_QUERY_THROW); + + std::shared_ptr<XMLTableTemplate> xT(it->second); + + for (const auto& rStyle : *xT) try + { + const OUString sPropName(rStyle.first); + const OUString sStyleName(rStyle.second); + // Internally unassigned cell styles are stored by display name. + // However table-template elements reference cell styles by its encoded name. + // This loop is looking for cell style by their encoded names. + sal_Int32 nCount = xCellFamily->getCount(); + for (sal_Int32 i=0; i < nCount; ++i) + { + Any xCellStyle = xCellFamily->getByIndex(i); + OUString sEncodedStyleName = mrImport.GetMM100UnitConverter().encodeStyleName( + xCellStyle.get<Reference<XStyle>>()->getName()); + if (sEncodedStyleName == sStyleName) + { + xTemplate->replaceByName(sPropName, xCellStyle); + break; + } + } + } + catch (Exception const &) + { + TOOLS_WARN_EXCEPTION("xmloff.table", "XMLTableImport::insertTabletemplate()"); + } + + if (xTemplate.is()) + { + if (xTableFamily->hasByName(sTemplateName) && bOverwrite) + xTableFamily->replaceByName(sTemplateName, Any(xTemplate)); + else + xTableFamily->insertByName(sTemplateName, Any(xTemplate)); + } + } + catch (Exception&) + { + TOOLS_WARN_EXCEPTION("xmloff.table", "XMLTableImport::insertTabletemplate()"); + } +} + +void XMLTableImport::finishStyles() +{ + if( maTableTemplates.empty() ) + return; + + try + { + Reference< XStyleFamiliesSupplier > xFamiliesSupp( mrImport.GetModel(), UNO_QUERY_THROW ); + Reference< XNameAccess > xFamilies( xFamiliesSupp->getStyleFamilies() ); + + Reference< XNameContainer > xTableFamily( xFamilies->getByName( "table" ), UNO_QUERY_THROW ); + Reference< XNameAccess > xCellFamily( xFamilies->getByName( "cell" ), UNO_QUERY_THROW ); + + Reference< XSingleServiceFactory > xFactory( xTableFamily, UNO_QUERY_THROW ); + + for( const auto& rTemplate : maTableTemplates ) try + { + const OUString sTemplateName( rTemplate.first ); + Reference< XNameReplace > xTemplate( xFactory->createInstance(), UNO_QUERY_THROW ); + + std::shared_ptr< XMLTableTemplate > xT( rTemplate.second ); + + for( const auto& rStyle : *xT ) try + { + const OUString sPropName( rStyle.first ); + const OUString sStyleName( rStyle.second ); + xTemplate->replaceByName( sPropName, xCellFamily->getByName( sStyleName ) ); + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION("xmloff.table", ""); + } + + if( xTemplate.is() ) + { + if( xTableFamily->hasByName( sTemplateName ) ) + xTableFamily->replaceByName( sTemplateName, Any( xTemplate ) ); + else + xTableFamily->insertByName( sTemplateName, Any( xTemplate ) ); + } + + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION("xmloff.table", ""); + } + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION("xmloff.table", ""); + } +} + + +XMLTableImportContext::XMLTableImportContext( const rtl::Reference< XMLTableImport >& xImporter, Reference< XColumnRowRange > const & xColumnRowRange ) +: SvXMLImportContext( xImporter->mrImport ) +, mxTable( xColumnRowRange, UNO_QUERY ) +, mxColumns( xColumnRowRange->getColumns() ) +, mxRows( xColumnRowRange->getRows() ) +, mnCurrentRow( -1 ) +, mnCurrentColumn( -1 ) +{ +} + +SvXMLImportContextRef XMLTableImportContext::ImportColumn( const Reference< XFastAttributeList >& xAttrList ) +{ + if( mxColumns.is() && (mnCurrentRow == -1) ) try + { + auto xInfo = std::make_shared<ColumnInfo>(); + + sal_Int32 nRepeated = 1; + + // read attributes for the table-column + for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) + { + switch (aIter.getToken()) + { + case XML_ELEMENT(TABLE, XML_NUMBER_COLUMNS_REPEATED): + nRepeated = aIter.toInt32(); + break; + case XML_ELEMENT(TABLE, XML_STYLE_NAME): + xInfo->msStyleName = aIter.toString(); + break; + case XML_ELEMENT(TABLE, XML_DEFAULT_CELL_STYLE_NAME): + xInfo->msDefaultCellStyleName = aIter.toString(); + break; + case XML_ELEMENT(XML, XML_ID): + //FIXME: TODO + break; + } + } + + if( nRepeated <= 1 ) + { + maColumnInfos.push_back( xInfo ); + } + else + { + maColumnInfos.insert( maColumnInfos.end(), nRepeated, xInfo ); + } + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION("xmloff.table", ""); + } + + return nullptr; +} + +void XMLTableImportContext::InitColumns() +{ + if( !mxColumns.is() ) + return; + + try + { + const sal_Int32 nCount1 = mxColumns->getCount(); + const sal_Int32 nCount2 = sal::static_int_cast< sal_Int32 >( maColumnInfos.size() ); + if( nCount1 < nCount2 ) + mxColumns->insertByIndex( nCount1, nCount2 - nCount1 ); + + SvXMLStylesContext * pAutoStyles = GetImport().GetShapeImport()->GetAutoStylesContext(); + + for( sal_Int32 nCol = 0; nCol < nCount2; nCol++ ) + { + std::shared_ptr< ColumnInfo > xInfo( maColumnInfos[nCol] ); + + if( pAutoStyles && !xInfo->msStyleName.isEmpty() ) + { + const XMLPropStyleContext* pStyle = + dynamic_cast< const XMLPropStyleContext* >( + pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_COLUMN, xInfo->msStyleName) ); + + if( pStyle ) + { + Reference< XPropertySet > xColProps( mxColumns->getByIndex(nCol), UNO_QUERY_THROW ); + const_cast< XMLPropStyleContext* >( pStyle )->FillPropertySet( xColProps ); + } + } + + } + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION("xmloff.table", ""); + } +} + +SvXMLImportContext * XMLTableImportContext::ImportRow( const Reference< XFastAttributeList >& xAttrList ) +{ + if( mxRows.is() ) + { + mnCurrentRow++; + if( mnCurrentRow == 0 ) + InitColumns(); // first init columns + + mnCurrentColumn = -1; + + const sal_Int32 nRowCount = mxRows->getCount(); + if( ( nRowCount - 1) < mnCurrentRow ) + { + const sal_Int32 nCount = mnCurrentRow - nRowCount + 1; + mxRows->insertByIndex( nRowCount, nCount ); + } + + Reference< XPropertySet > xRowSet( mxRows->getByIndex(mnCurrentRow), UNO_QUERY ); + + OUString sStyleName; + + // read attributes for the table-row + for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) + { + switch(aIter.getToken()) + { + case XML_ELEMENT(TABLE, XML_STYLE_NAME): + sStyleName = aIter.toString(); + break; + case XML_ELEMENT(TABLE, XML_DEFAULT_CELL_STYLE_NAME): + msDefaultCellStyleName = aIter.toString(); + break; + case XML_ELEMENT(XML, XML_ID): + //FIXME: TODO + break; + } + } + + if( !sStyleName.isEmpty() ) + { + SvXMLStylesContext * pAutoStyles = GetImport().GetShapeImport()->GetAutoStylesContext(); + if( pAutoStyles ) + { + const XMLPropStyleContext* pStyle = + dynamic_cast< const XMLPropStyleContext* >( + pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_ROW, sStyleName) ); + + if( pStyle ) + { + const_cast< XMLPropStyleContext* >( pStyle )->FillPropertySet( xRowSet ); + } + } + } + } + + SvXMLImportContextRef xThis( this ); + return new XMLProxyContext( GetImport(), xThis ); +} + +SvXMLImportContextRef XMLTableImportContext::ImportCell( sal_Int32 nElement, const Reference< XFastAttributeList >& xAttrList ) +{ + mnCurrentColumn++; + if( mxColumns.is() ) try + { + if( mxColumns->getCount() <= mnCurrentColumn ) + mxColumns->insertByIndex( mxColumns->getCount(), mnCurrentColumn - mxColumns->getCount() + 1 ); + + Reference< XMergeableCell > xCell( mxTable->getCellByPosition( mnCurrentColumn, mnCurrentRow ), UNO_QUERY_THROW ); + XMLCellImportContext* pCellContext = new XMLCellImportContext( GetImport(), xCell, GetDefaultCellStyleName(), nElement, xAttrList ); + + const sal_Int32 nColumnSpan = pCellContext->getColumnSpan(); + const sal_Int32 nRowSpan = pCellContext->getRowSpan(); + if( (nColumnSpan > 1) || (nRowSpan > 1) ) + maMergeInfos.push_back( std::make_shared< MergeInfo >( mnCurrentColumn, mnCurrentRow, nColumnSpan, nRowSpan ) ); + + const sal_Int32 nRepeated = pCellContext->getRepeated(); + if( nRepeated > 1 ) + { + OSL_FAIL("xmloff::XMLTableImportContext::ImportCell(), import of repeated Cells not implemented (TODO)"); + mnCurrentColumn += nRepeated - 1; + } + + return pCellContext; + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION("xmloff.table", ""); + } + + return nullptr; +} + +css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTableImportContext::createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) +{ + switch (nElement) + { + case XML_ELEMENT(TABLE, XML_TABLE_CELL): + case XML_ELEMENT(TABLE, XML_COVERED_TABLE_CELL): + return ImportCell( nElement, xAttrList ); + case XML_ELEMENT(TABLE, XML_TABLE_COLUMN): + return ImportColumn( xAttrList ); + case XML_ELEMENT(TABLE, XML_TABLE_ROW): + return ImportRow( xAttrList ); + case XML_ELEMENT(TABLE, XML_TABLE_COLUMNS): + case XML_ELEMENT(TABLE, XML_TABLE_ROWS): + { + SvXMLImportContextRef xThis( this ); + return new XMLProxyContext( GetImport(), xThis ); + } + } + SAL_WARN("xmloff", "unknown element"); + return nullptr; +} + +void XMLTableImportContext::endFastElement(sal_Int32 ) +{ + for( const std::shared_ptr< MergeInfo >& xInfo : maMergeInfos ) + { + if( xInfo ) try + { + Reference< XCellRange > xRange( mxTable->getCellRangeByPosition( xInfo->mnStartColumn, xInfo->mnStartRow, xInfo->mnEndColumn, xInfo->mnEndRow ) ); + Reference< XMergeableCellRange > xCursor( mxTable->createCursorByRange( xRange ), UNO_QUERY_THROW ); + xCursor->merge(); + } + catch( Exception& ) + { + TOOLS_WARN_EXCEPTION("xmloff.table", ""); + } + } +} + +OUString XMLTableImportContext::GetDefaultCellStyleName() const +{ + OUString sStyleName( msDefaultCellStyleName ); + + // if there is still no style name, try default style name from column + if( (sStyleName.isEmpty()) && (mnCurrentColumn < sal::static_int_cast<sal_Int32>(maColumnInfos.size())) ) + sStyleName = maColumnInfos[mnCurrentColumn]->msDefaultCellStyleName; + + return sStyleName; +} + +// XMLCellImportContext + +XMLCellImportContext::XMLCellImportContext( SvXMLImport& rImport, + const Reference< XMergeableCell >& xCell, + const OUString& sDefaultCellStyleName, + sal_Int32 /*nElement*/, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) +: SvXMLImportContext( rImport ) +, mxCell( xCell ) +, mbListContextPushed( false ) +, mnColSpan( 1 ) +, mnRowSpan( 1 ) +, mnRepeated( 1 ) +{ + OUString sStyleName; + + // read attributes for the table-cell + for( auto& aIter : sax_fastparser::castToFastAttributeList(xAttrList) ) + { + switch (aIter.getToken()) + { + case XML_ELEMENT(TABLE, XML_NUMBER_COLUMNS_REPEATED): + mnRepeated = aIter.toInt32(); + break; + case XML_ELEMENT(TABLE, XML_NUMBER_COLUMNS_SPANNED): + mnColSpan = aIter.toInt32(); + break; + case XML_ELEMENT(TABLE, XML_NUMBER_ROWS_SPANNED): + mnRowSpan = aIter.toInt32(); + break; + case XML_ELEMENT(TABLE, XML_STYLE_NAME): + sStyleName = aIter.toString(); + break; + case XML_ELEMENT(XML, XML_ID): +//FIXME: TODO + break; +//FIXME: RDFa (table:table-cell) + default: + XMLOFF_WARN_UNKNOWN("xmloff", aIter); + } + } + + // if there is no style name at the cell, try default style name from row + if( sStyleName.isEmpty() ) + sStyleName = sDefaultCellStyleName; + + if( sStyleName.isEmpty() ) + return; + + SvXMLStylesContext * pAutoStyles = GetImport().GetShapeImport()->GetAutoStylesContext(); + if( !pAutoStyles ) + return; + + const XMLPropStyleContext* pStyle = + dynamic_cast< const XMLPropStyleContext* >( + pAutoStyles->FindStyleChildContext(XmlStyleFamily::TABLE_CELL, sStyleName) ); + + if( pStyle ) + { + Reference< XPropertySet > xCellSet( mxCell, UNO_QUERY ); + if( xCellSet.is() ) + const_cast< XMLPropStyleContext* >( pStyle )->FillPropertySet( xCellSet ); + } +} + +css::uno::Reference< css::xml::sax::XFastContextHandler > XMLCellImportContext::createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) +{ + // create text cursor on demand + if( !mxCursor.is() ) + { + Reference< XText > xText( mxCell, UNO_QUERY ); + if( xText.is() ) + { + rtl::Reference < XMLTextImportHelper > xTxtImport( GetImport().GetTextImport() ); + mxOldCursor = xTxtImport->GetCursor(); + mxCursor = xText->createTextCursor(); + if( mxCursor.is() ) + xTxtImport->SetCursor( mxCursor ); + + // remember old list item and block (#91964#) and reset them + // for the text frame + xTxtImport->PushListContext(); + mbListContextPushed = true; + } + } + + SvXMLImportContext * pContext = nullptr; + + // if we have a text cursor, lets try to import some text + if( mxCursor.is() ) + { + pContext = GetImport().GetTextImport()->CreateTextChildContext( GetImport(), nElement, xAttrList ); + } + + if (!pContext) + XMLOFF_WARN_UNKNOWN_ELEMENT("xmloff", nElement); + return pContext; +} + +void XMLCellImportContext::endFastElement(sal_Int32 ) +{ + if(mxCursor.is()) + { + // delete addition newline + mxCursor->gotoEnd( false ); + mxCursor->goLeft( 1, true ); + mxCursor->setString( "" ); + + // reset cursor + GetImport().GetTextImport()->ResetCursor(); + } + + if(mxOldCursor.is()) + GetImport().GetTextImport()->SetCursor( mxOldCursor ); + + // reinstall old list item (if necessary) #91964# + if (mbListContextPushed) { + GetImport().GetTextImport()->PopListContext(); + } +} + + +XMLTableTemplateContext::XMLTableTemplateContext( SvXMLImport& rImport ) +: SvXMLStyleContext( rImport, XmlStyleFamily::TABLE_TEMPLATE_ID, false ) +{ +} + +void XMLTableTemplateContext::SetAttribute( sal_Int32 nElement, + const OUString& rValue ) +{ + if( nElement == XML_ELEMENT(TEXT, XML_STYLE_NAME) + // Writer specific: according to oasis odf 1.2 prefix should be "table" and element name should be "name" + || nElement == XML_ELEMENT(TABLE, XML_NAME) ) + { + msTemplateStyleName = rValue; + } +} + +void XMLTableTemplateContext::endFastElement(sal_Int32 ) +{ + rtl::Reference< XMLTableImport > xTableImport( GetImport().GetShapeImport()->GetShapeTableImport() ); + if( xTableImport.is() ) + xTableImport->addTableTemplate( msTemplateStyleName, maTableTemplate ); +} + +void XMLTableTemplateContext::CreateAndInsert(bool bOverwrite) +{ + rtl::Reference<XMLTableImport> xTableImport(GetImport().GetShapeImport()->GetShapeTableImport()); + if(xTableImport.is()) + xTableImport->insertTabletemplate(msTemplateStyleName, bOverwrite); +} + +css::uno::Reference< css::xml::sax::XFastContextHandler > XMLTableTemplateContext::createFastChildContext( + sal_Int32 nElement, + const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttrList ) +{ + if( IsTokenInNamespace(nElement, XML_NAMESPACE_TABLE) ) + { + const TableStyleElement* pElements = getTableStyleMap(); + sal_Int32 nLocalName = nElement & TOKEN_MASK; + while( (pElements->meElement != XML_TOKEN_END) && pElements->meElement != nLocalName) + pElements++; + + if( pElements->meElement != XML_TOKEN_END ) + { + for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList )) + { + switch (aIter.getToken()) + { + case XML_ELEMENT(TEXT, XML_STYLE_NAME): + case XML_ELEMENT(TABLE, XML_STYLE_NAME): + maTableTemplate[pElements->msStyleName] = aIter.toString(); + break; + default: + XMLOFF_WARN_UNKNOWN("xmloff", aIter); + } + } + } + } else if (IsTokenInNamespace(nElement, XML_NAMESPACE_LO_EXT)) // Writer specific cell styles + { + const TableStyleElement* pElements = getWriterSpecificTableStyleMap(); + sal_Int32 nLocalName = nElement & TOKEN_MASK; + while( (pElements->meElement != XML_TOKEN_END) && pElements->meElement != nLocalName) + pElements++; + + if (pElements->meElement != XML_TOKEN_END) + { + for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList )) + { + switch (aIter.getToken()) + { + case XML_ELEMENT(TEXT, XML_STYLE_NAME): + case XML_ELEMENT(TABLE, XML_STYLE_NAME): + maTableTemplate[pElements->msStyleName] = aIter.toString(); + break; + default: + XMLOFF_WARN_UNKNOWN("xmloff", aIter); + } + } + } + } + + return nullptr; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |