summaryrefslogtreecommitdiff
path: root/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'writerfilter/source/dmapper/DomainMapperTableHandler.cxx')
-rw-r--r--writerfilter/source/dmapper/DomainMapperTableHandler.cxx1697
1 files changed, 0 insertions, 1697 deletions
diff --git a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx b/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
deleted file mode 100644
index fd21827211bb..000000000000
--- a/writerfilter/source/dmapper/DomainMapperTableHandler.cxx
+++ /dev/null
@@ -1,1697 +0,0 @@
-/* -*- 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 <string_view>
-
-#include "DomainMapperTableHandler.hxx"
-#include "DomainMapper_Impl.hxx"
-#include "StyleSheetTable.hxx"
-#include <com/sun/star/style/ParagraphAdjust.hpp>
-#include <com/sun/star/table/TableBorderDistances.hpp>
-#include <com/sun/star/table/TableBorder.hpp>
-#include <com/sun/star/table/BorderLine2.hpp>
-#include <com/sun/star/table/BorderLineStyle.hpp>
-#include <com/sun/star/table/XCellRange.hpp>
-#include <com/sun/star/text/HoriOrientation.hpp>
-#include <com/sun/star/text/SizeType.hpp>
-#include <com/sun/star/text/XTextField.hpp>
-#include <com/sun/star/text/XTextRangeCompare.hpp>
-#include <com/sun/star/beans/XPropertySet.hpp>
-#include <com/sun/star/beans/XPropertyState.hpp>
-#include <com/sun/star/container/XEnumeration.hpp>
-#include <com/sun/star/container/XEnumerationAccess.hpp>
-#include <com/sun/star/drawing/FillStyle.hpp>
-#include "TablePositionHandler.hxx"
-#include "TagLogger.hxx"
-#include "util.hxx"
-#include <osl/diagnose.h>
-#include <sal/log.hxx>
-#include <tools/diagnose_ex.h>
-#include <comphelper/sequence.hxx>
-#include <comphelper/propertyvalue.hxx>
-#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
-#include <boost/lexical_cast.hpp>
-
-#ifdef DBG_UTIL
-#include "PropertyMapHelper.hxx"
-#include <rtl/ustring.hxx>
-#endif
-
-namespace writerfilter::dmapper {
-
-using namespace ::com::sun::star;
-using namespace ::std;
-
-#define DEF_BORDER_DIST 190 //0,19cm
-#define CNF_FIRST_ROW 0x800
-#define CNF_LAST_ROW 0x400
-#define CNF_FIRST_COLUMN 0x200
-#define CNF_LAST_COLUMN 0x100
-#define CNF_ODD_VBAND 0x080
-#define CNF_EVEN_VBAND 0x040
-#define CNF_ODD_HBAND 0x020
-#define CNF_EVEN_HBAND 0x010
-#define CNF_FIRST_ROW_LAST_COLUMN 0x008
-#define CNF_FIRST_ROW_FIRST_COLUMN 0x004
-#define CNF_LAST_ROW_LAST_COLUMN 0x002
-#define CNF_LAST_ROW_FIRST_COLUMN 0x001
-#define CNF_ALL 0xFFF
-
-// total number of table columns
-#define MAXTABLECELLS 63
-
-DomainMapperTableHandler::DomainMapperTableHandler(
- css::uno::Reference<css::text::XTextAppendAndConvert> const& xText,
- DomainMapper_Impl& rDMapper_Impl)
- : m_xText(xText),
- m_rDMapper_Impl( rDMapper_Impl ),
- m_bHadFootOrEndnote(false)
-{
-}
-
-DomainMapperTableHandler::~DomainMapperTableHandler()
-{
-}
-
-void DomainMapperTableHandler::startTable(const TablePropertyMapPtr& pProps)
-{
- m_aTableProperties = pProps;
- m_aTableRanges.clear();
-
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("tablehandler.table");
-
- if (pProps)
- pProps->dumpXml();
-#endif
-}
-
-static void lcl_mergeBorder( PropertyIds nId, const PropertyMapPtr& pOrig, const PropertyMapPtr& pDest )
-{
- std::optional<PropertyMap::Property> pOrigVal = pOrig->getProperty(nId);
-
- if ( pOrigVal )
- {
- pDest->Insert( nId, pOrigVal->second, false );
- }
-}
-
-static void lcl_computeCellBorders( const PropertyMapPtr& pTableBorders, const PropertyMapPtr& pCellProps,
- sal_uInt32 nCell, sal_uInt32 nFirstCell, sal_uInt32 nLastCell, sal_Int32 nRow, bool bIsEndRow, bool bMergedVertically )
-{
- const bool bIsStartCol = nCell == nFirstCell;
- const bool bIsEndCol = nCell == nLastCell;
- std::optional<PropertyMap::Property> pVerticalVal = pCellProps->getProperty(META_PROP_VERTICAL_BORDER);
- std::optional<PropertyMap::Property> pHorizontalVal = pCellProps->getProperty(META_PROP_HORIZONTAL_BORDER);
-
- // Handle the vertical and horizontal borders
- uno::Any aVertProp;
- if ( !pVerticalVal)
- {
- pVerticalVal = pTableBorders->getProperty(META_PROP_VERTICAL_BORDER);
- if ( pVerticalVal )
- aVertProp = pVerticalVal->second;
- }
- else
- {
- aVertProp = pVerticalVal->second;
- pCellProps->Erase( pVerticalVal->first );
- }
-
- uno::Any aHorizProp;
- if ( !pHorizontalVal )
- {
- pHorizontalVal = pTableBorders->getProperty(META_PROP_HORIZONTAL_BORDER);
- if ( pHorizontalVal )
- aHorizProp = pHorizontalVal->second;
- }
- else
- {
- aHorizProp = pHorizontalVal->second;
- pCellProps->Erase( pHorizontalVal->first );
- }
-
- if ( bIsStartCol )
- lcl_mergeBorder( PROP_LEFT_BORDER, pTableBorders, pCellProps );
-
- if ( bIsEndCol )
- lcl_mergeBorder( PROP_RIGHT_BORDER, pTableBorders, pCellProps );
-
- // <w:insideV> counts if there are multiple cells in this row.
- if ( pVerticalVal )
- {
- if ( !bIsEndCol && nCell >= nFirstCell )
- pCellProps->Insert( PROP_RIGHT_BORDER, aVertProp, false );
- if ( !bIsStartCol && nCell <= nLastCell )
- pCellProps->Insert( PROP_LEFT_BORDER, aVertProp, false );
- }
-
- if ( nRow == 0 )
- {
- lcl_mergeBorder( PROP_TOP_BORDER, pTableBorders, pCellProps );
- if ( pHorizontalVal && !bMergedVertically )
- pCellProps->Insert( PROP_BOTTOM_BORDER, aHorizProp, false );
- }
-
- if ( bMergedVertically )
- lcl_mergeBorder( PROP_BOTTOM_BORDER, pTableBorders, pCellProps );
-
- if ( bIsEndRow )
- {
- lcl_mergeBorder( PROP_BOTTOM_BORDER, pTableBorders, pCellProps );
- if ( pHorizontalVal )
- pCellProps->Insert( PROP_TOP_BORDER, aHorizProp, false );
- }
-
- if ( nRow > 0 && !bIsEndRow )
- {
- if ( pHorizontalVal )
- {
- pCellProps->Insert( PROP_TOP_BORDER, aHorizProp, false );
- pCellProps->Insert( PROP_BOTTOM_BORDER, aHorizProp, false );
- }
- }
-}
-
-#ifdef DBG_UTIL
-
-static void lcl_debug_BorderLine(table::BorderLine const & rLine)
-{
- TagLogger::getInstance().startElement("BorderLine");
- TagLogger::getInstance().attribute("Color", rLine.Color);
- TagLogger::getInstance().attribute("InnerLineWidth", rLine.InnerLineWidth);
- TagLogger::getInstance().attribute("OuterLineWidth", rLine.OuterLineWidth);
- TagLogger::getInstance().attribute("LineDistance", rLine.LineDistance);
- TagLogger::getInstance().endElement();
-}
-
-static void lcl_debug_TableBorder(table::TableBorder const & rBorder)
-{
- TagLogger::getInstance().startElement("TableBorder");
- lcl_debug_BorderLine(rBorder.TopLine);
- TagLogger::getInstance().attribute("IsTopLineValid", sal_uInt32(rBorder.IsTopLineValid));
- lcl_debug_BorderLine(rBorder.BottomLine);
- TagLogger::getInstance().attribute("IsBottomLineValid", sal_uInt32(rBorder.IsBottomLineValid));
- lcl_debug_BorderLine(rBorder.LeftLine);
- TagLogger::getInstance().attribute("IsLeftLineValid", sal_uInt32(rBorder.IsLeftLineValid));
- lcl_debug_BorderLine(rBorder.RightLine);
- TagLogger::getInstance().attribute("IsRightLineValid", sal_uInt32(rBorder.IsRightLineValid));
- lcl_debug_BorderLine(rBorder.VerticalLine);
- TagLogger::getInstance().attribute("IsVerticalLineValid", sal_uInt32(rBorder.IsVerticalLineValid));
- lcl_debug_BorderLine(rBorder.HorizontalLine);
- TagLogger::getInstance().attribute("IsHorizontalLineValid", sal_uInt32(rBorder.IsHorizontalLineValid));
- TagLogger::getInstance().attribute("Distance", rBorder.Distance);
- TagLogger::getInstance().attribute("IsDistanceValid", sal_uInt32(rBorder.IsDistanceValid));
- TagLogger::getInstance().endElement();
-}
-#endif
-
-struct TableInfo
-{
- sal_Int32 nLeftBorderDistance;
- sal_Int32 nRightBorderDistance;
- sal_Int32 nTopBorderDistance;
- sal_Int32 nBottomBorderDistance;
- sal_Int32 nTblLook;
- sal_Int32 nNestLevel;
- PropertyMapPtr pTableDefaults;
- PropertyMapPtr pTableBorders;
- TableStyleSheetEntry* pTableStyle;
- css::beans::PropertyValues aTableProperties;
- std::vector< PropertyIds > aTablePropertyIds;
-
- TableInfo()
- : nLeftBorderDistance(DEF_BORDER_DIST)
- , nRightBorderDistance(DEF_BORDER_DIST)
- , nTopBorderDistance(0)
- , nBottomBorderDistance(0)
- , nTblLook(0x4a0)
- , nNestLevel(0)
- , pTableDefaults(new PropertyMap)
- , pTableBorders(new PropertyMap)
- , pTableStyle(nullptr)
- {
- }
-
-};
-
-namespace
-{
-
-bool lcl_extractTableBorderProperty(const PropertyMapPtr& pTableProperties, const PropertyIds nId, TableInfo const & rInfo, table::BorderLine2& rLine)
-{
- if (!pTableProperties)
- return false;
-
- const std::optional<PropertyMap::Property> aTblBorder = pTableProperties->getProperty(nId);
- if( aTblBorder )
- {
- OSL_VERIFY(aTblBorder->second >>= rLine);
-
- rInfo.pTableBorders->Insert( nId, uno::makeAny( rLine ) );
- rInfo.pTableDefaults->Erase( nId );
-
- return true;
- }
-
- return false;
-}
-
-void lcl_extractHoriOrient(std::vector<beans::PropertyValue>& rFrameProperties, sal_Int32& nHoriOrient)
-{
- // Shifts the frame left by the given value.
- for (const beans::PropertyValue & rFrameProperty : rFrameProperties)
- {
- if (rFrameProperty.Name == "HoriOrient")
- {
- sal_Int32 nValue = rFrameProperty.Value.get<sal_Int32>();
- if (nValue != text::HoriOrientation::NONE)
- nHoriOrient = nValue;
- return;
- }
- }
-}
-
-void lcl_DecrementHoriOrientPosition(std::vector<beans::PropertyValue>& rFrameProperties, sal_Int32 nAmount)
-{
- // Shifts the frame left by the given value.
- for (beans::PropertyValue & rPropertyValue : rFrameProperties)
- {
- if (rPropertyValue.Name == "HoriOrientPosition")
- {
- sal_Int32 nValue = rPropertyValue.Value.get<sal_Int32>();
- nValue -= nAmount;
- rPropertyValue.Value <<= nValue;
- return;
- }
- }
-}
-
-void lcl_adjustBorderDistance(TableInfo& rInfo, const table::BorderLine2& rLeftBorder,
- const table::BorderLine2& rRightBorder)
-{
- // MS Word appears to do these things to adjust the cell horizontal area:
- //
- // bll = left borderline width
- // blr = right borderline width
- // cea = cell's edit area rectangle
- // cea_w = cea width
- // cml = cell's left margin (padding) defined in cell settings
- // cmr = cell's right margin (padding) defined in cell settings
- // cw = cell width (distance between middles of left borderline and right borderline)
- // pad_l = actual cea left padding = (its left pos relative to middle of bll)
- // pad_r = actual cea right padding = abs (its right pos relative to middle of blr)
- //
- // pad_l = max(bll/2, cml) -> cea does not overlap left borderline
- // cea_w = cw-max(pad_l+blr/2, cml+cmr) -> cea does not overlap right borderline
- // pad_r = max(pad_l+blr/2, cml+cmr) - pad_l
- //
- // It means that e.g. for border widths of 6 pt (~2.12 mm), left margin 0 mm, and right margin
- // 2 mm, actual left and right margins will (unexpectedly) coincide with inner edges of cell's
- // borderlines - the right margin won't create spacing between right of edit rectangle and the
- // inner edge of right borderline.
-
- const sal_Int32 nActualL
- = std::max<sal_Int32>(rLeftBorder.LineWidth / 2, rInfo.nLeftBorderDistance);
- const sal_Int32 nActualR
- = std::max<sal_Int32>(nActualL + rRightBorder.LineWidth / 2,
- rInfo.nLeftBorderDistance + rInfo.nRightBorderDistance)
- - nActualL;
- rInfo.nLeftBorderDistance = nActualL;
- rInfo.nRightBorderDistance = nActualR;
-}
-
-}
-
-TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo & rInfo, std::vector<beans::PropertyValue>& rFrameProperties)
-{
- // will receive the table style if any
- TableStyleSheetEntry* pTableStyle = nullptr;
-
- if( m_aTableProperties )
- {
- //create properties from the table attributes
- //...pPropMap->Insert( PROP_LEFT_MARGIN, uno::makeAny( m_nLeftMargin - m_nGapHalf ));
- //pPropMap->Insert( PROP_HORI_ORIENT, uno::makeAny( text::HoriOrientation::RIGHT ));
- sal_Int32 nGapHalf = 0;
- sal_Int32 nLeftMargin = 0;
-
- comphelper::SequenceAsHashMap aGrabBag;
-
- if (nullptr != m_rDMapper_Impl.getTableManager().getCurrentTableRealPosition())
- {
- TablePositionHandler *pTablePositions = m_rDMapper_Impl.getTableManager().getCurrentTableRealPosition();
-
- uno::Sequence< beans::PropertyValue > aGrabBagTS( 10 );
-
- aGrabBagTS[0].Name = "bottomFromText";
- aGrabBagTS[0].Value <<= pTablePositions->getBottomFromText();
-
- aGrabBagTS[1].Name = "horzAnchor";
- aGrabBagTS[1].Value <<= pTablePositions->getHorzAnchor();
-
- aGrabBagTS[2].Name = "leftFromText";
- aGrabBagTS[2].Value <<= pTablePositions->getLeftFromText();
-
- aGrabBagTS[3].Name = "rightFromText";
- aGrabBagTS[3].Value <<= pTablePositions->getRightFromText();
-
- aGrabBagTS[4].Name = "tblpX";
- aGrabBagTS[4].Value <<= pTablePositions->getX();
-
- aGrabBagTS[5].Name = "tblpXSpec";
- aGrabBagTS[5].Value <<= pTablePositions->getXSpec();
-
- aGrabBagTS[6].Name = "tblpY";
- aGrabBagTS[6].Value <<= pTablePositions->getY();
-
- aGrabBagTS[7].Name = "tblpYSpec";
- aGrabBagTS[7].Value <<= pTablePositions->getYSpec();
-
- aGrabBagTS[8].Name = "topFromText";
- aGrabBagTS[8].Value <<= pTablePositions->getTopFromText();
-
- aGrabBagTS[9].Name = "vertAnchor";
- aGrabBagTS[9].Value <<= pTablePositions->getVertAnchor();
-
- aGrabBag["TablePosition"] <<= aGrabBagTS;
- }
-
- std::optional<PropertyMap::Property> aTableStyleVal = m_aTableProperties->getProperty(META_PROP_TABLE_STYLE_NAME);
- if(aTableStyleVal)
- {
- // Apply table style properties recursively
- OUString sTableStyleName;
- aTableStyleVal->second >>= sTableStyleName;
- StyleSheetTablePtr pStyleSheetTable = m_rDMapper_Impl.GetStyleSheetTable();
- const StyleSheetEntryPtr pStyleSheet = pStyleSheetTable->FindStyleSheetByISTD( sTableStyleName );
- pTableStyle = dynamic_cast<TableStyleSheetEntry*>( pStyleSheet.get( ) );
- m_aTableProperties->Erase( aTableStyleVal->first );
-
- aGrabBag["TableStyleName"] <<= sTableStyleName;
-
- if( pStyleSheet )
- {
- // First get the style properties, then the table ones
- PropertyMapPtr pTableProps( m_aTableProperties.get() );
- TablePropertyMapPtr pEmptyProps( new TablePropertyMap );
-
- m_aTableProperties = pEmptyProps;
-
- PropertyMapPtr pMergedProperties = pStyleSheet->GetMergedInheritedProperties(pStyleSheetTable);
-
- table::BorderLine2 aBorderLine;
- TableInfo rStyleInfo;
- if (lcl_extractTableBorderProperty(pMergedProperties, PROP_TOP_BORDER, rStyleInfo, aBorderLine))
- {
- aGrabBag["TableStyleTopBorder"] <<= aBorderLine;
- }
- if (lcl_extractTableBorderProperty(pMergedProperties, PROP_BOTTOM_BORDER, rStyleInfo, aBorderLine))
- {
- aGrabBag["TableStyleBottomBorder"] <<= aBorderLine;
- }
- if (lcl_extractTableBorderProperty(pMergedProperties, PROP_LEFT_BORDER, rStyleInfo, aBorderLine))
- {
- aGrabBag["TableStyleLeftBorder"] <<= aBorderLine;
- }
- if (lcl_extractTableBorderProperty(pMergedProperties, PROP_RIGHT_BORDER, rStyleInfo, aBorderLine))
- {
- aGrabBag["TableStyleRightBorder"] <<= aBorderLine;
- }
-
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("mergedProps");
- if (pMergedProperties)
- pMergedProperties->dumpXml();
- TagLogger::getInstance().endElement();
-#endif
-
- m_aTableProperties->InsertProps(pMergedProperties);
- m_aTableProperties->InsertProps(pTableProps);
-
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("TableProperties");
- m_aTableProperties->dumpXml();
- TagLogger::getInstance().endElement();
-#endif
- if (pTableStyle)
- {
- // apply tblHeader setting of the table style
- PropertyMapPtr pHeaderStyleProps = pTableStyle->GetProperties(CNF_FIRST_ROW);
- if ( pHeaderStyleProps->getProperty(PROP_HEADER_ROW_COUNT) )
- m_aTableProperties->Insert(PROP_HEADER_ROW_COUNT, uno::makeAny( sal_Int32(1)), false);
- }
- }
- }
-
- // This is the one preserving just all the table look attributes.
- std::optional<PropertyMap::Property> oTableLook = m_aTableProperties->getProperty(META_PROP_TABLE_LOOK);
- if (oTableLook)
- {
- aGrabBag["TableStyleLook"] = oTableLook->second;
- m_aTableProperties->Erase(oTableLook->first);
- }
-
- // This is just the "val" attribute's numeric value.
- const std::optional<PropertyMap::Property> aTblLook = m_aTableProperties->getProperty(PROP_TBL_LOOK);
- if(aTblLook)
- {
- aTblLook->second >>= rInfo.nTblLook;
- m_aTableProperties->Erase( aTblLook->first );
- }
-
- // apply cell margin settings of the table style
- const std::optional<PropertyMap::Property> oLeftMargin = m_aTableProperties->getProperty(META_PROP_CELL_MAR_LEFT);
- if (oLeftMargin)
- {
- oLeftMargin->second >>= rInfo.nLeftBorderDistance;
- m_aTableProperties->Erase(oLeftMargin->first);
- }
- const std::optional<PropertyMap::Property> oRightMargin = m_aTableProperties->getProperty(META_PROP_CELL_MAR_RIGHT);
- if (oRightMargin)
- {
- oRightMargin->second >>= rInfo.nRightBorderDistance;
- m_aTableProperties->Erase(oRightMargin->first);
- }
- const std::optional<PropertyMap::Property> oTopMargin = m_aTableProperties->getProperty(META_PROP_CELL_MAR_TOP);
- if (oTopMargin)
- {
- oTopMargin->second >>= rInfo.nTopBorderDistance;
- m_aTableProperties->Erase(oTopMargin->first);
- }
- const std::optional<PropertyMap::Property> oBottomMargin = m_aTableProperties->getProperty(META_PROP_CELL_MAR_BOTTOM);
- if (oBottomMargin)
- {
- oBottomMargin->second >>= rInfo.nBottomBorderDistance;
- m_aTableProperties->Erase(oBottomMargin->first);
- }
-
- // Set the table default attributes for the cells
- rInfo.pTableDefaults->InsertProps(m_aTableProperties.get());
-
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("TableDefaults");
- rInfo.pTableDefaults->dumpXml();
- TagLogger::getInstance().endElement();
-#endif
-
- if (!aGrabBag.empty())
- {
- m_aTableProperties->Insert( PROP_TABLE_INTEROP_GRAB_BAG, uno::makeAny( aGrabBag.getAsConstPropertyValueList() ) );
- }
-
- m_aTableProperties->getValue( TablePropertyMap::GAP_HALF, nGapHalf );
-
- std::optional<PropertyMap::Property> oLeftMarginFromStyle = m_aTableProperties->getProperty(PROP_LEFT_MARGIN);
- if (oLeftMarginFromStyle)
- {
- oLeftMarginFromStyle->second >>= nLeftMargin;
- // don't need to erase, we will push back the adjusted value
- // of this (or the direct formatting, if that exists) later
- }
- m_aTableProperties->getValue( TablePropertyMap::LEFT_MARGIN, nLeftMargin );
-
- m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_LEFT,
- rInfo.nLeftBorderDistance );
- m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_RIGHT,
- rInfo.nRightBorderDistance );
- m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_TOP,
- rInfo.nTopBorderDistance );
- m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_BOTTOM,
- rInfo.nBottomBorderDistance );
-
- table::TableBorderDistances aDistances;
- aDistances.IsTopDistanceValid =
- aDistances.IsBottomDistanceValid =
- aDistances.IsLeftDistanceValid =
- aDistances.IsRightDistanceValid = true;
- aDistances.TopDistance = static_cast<sal_Int16>( rInfo.nTopBorderDistance );
- aDistances.BottomDistance = static_cast<sal_Int16>( rInfo.nBottomBorderDistance );
- aDistances.LeftDistance = static_cast<sal_Int16>( rInfo.nLeftBorderDistance );
- aDistances.RightDistance = static_cast<sal_Int16>( rInfo.nRightBorderDistance );
-
- m_aTableProperties->Insert( PROP_TABLE_BORDER_DISTANCES, uno::makeAny( aDistances ) );
-
- if (!rFrameProperties.empty())
- lcl_DecrementHoriOrientPosition(rFrameProperties, rInfo.nLeftBorderDistance);
-
- // Set table above/bottom spacing to 0.
- m_aTableProperties->Insert( PROP_TOP_MARGIN, uno::makeAny( sal_Int32( 0 ) ) );
- m_aTableProperties->Insert( PROP_BOTTOM_MARGIN, uno::makeAny( sal_Int32( 0 ) ) );
-
- //table border settings
- table::TableBorder aTableBorder;
- table::BorderLine2 aBorderLine, aLeftBorder, aRightBorder;
-
- if (lcl_extractTableBorderProperty(m_aTableProperties.get(), PROP_TOP_BORDER, rInfo, aBorderLine))
- {
- aTableBorder.TopLine = aBorderLine;
- aTableBorder.IsTopLineValid = true;
- }
- if (lcl_extractTableBorderProperty(m_aTableProperties.get(), PROP_BOTTOM_BORDER, rInfo, aBorderLine))
- {
- aTableBorder.BottomLine = aBorderLine;
- aTableBorder.IsBottomLineValid = true;
- }
- if (lcl_extractTableBorderProperty(m_aTableProperties.get(), PROP_LEFT_BORDER, rInfo, aLeftBorder))
- {
- aTableBorder.LeftLine = aLeftBorder;
- aTableBorder.IsLeftLineValid = true;
- }
- if (lcl_extractTableBorderProperty(m_aTableProperties.get(), PROP_RIGHT_BORDER, rInfo,
- aRightBorder))
- {
- aTableBorder.RightLine = aRightBorder;
- aTableBorder.IsRightLineValid = true;
- }
- if (lcl_extractTableBorderProperty(m_aTableProperties.get(), META_PROP_HORIZONTAL_BORDER, rInfo, aBorderLine))
- {
- aTableBorder.HorizontalLine = aBorderLine;
- aTableBorder.IsHorizontalLineValid = true;
- }
- if (lcl_extractTableBorderProperty(m_aTableProperties.get(), META_PROP_VERTICAL_BORDER, rInfo, aBorderLine))
- {
- aTableBorder.VerticalLine = aBorderLine;
- aTableBorder.IsVerticalLineValid = true;
- }
-
- aTableBorder.Distance = 0;
- aTableBorder.IsDistanceValid = false;
-
- m_aTableProperties->Insert( PROP_TABLE_BORDER, uno::makeAny( aTableBorder ) );
-
-#ifdef DBG_UTIL
- lcl_debug_TableBorder(aTableBorder);
-#endif
-
- // Table position in Office is computed in 2 different ways :
- // - top level tables: the goal is to have in-cell text starting at table indent pos (tblInd),
- // so table's position depends on table's cells margin
- // - nested tables: the goal is to have left-most border starting at table_indent pos
-
- // Only top level table position depends on border width of Column A.
- if ( !m_aCellProperties.empty() && !m_aCellProperties[0].empty() )
- {
- // aLeftBorder already contains tblBorder; overwrite if cell is different.
- std::optional<PropertyMap::Property> aCellBorder
- = m_aCellProperties[0][0]->getProperty(PROP_LEFT_BORDER);
- if ( aCellBorder )
- aCellBorder->second >>= aLeftBorder;
- aCellBorder = m_aCellProperties[0][0]->getProperty(PROP_RIGHT_BORDER);
- if (aCellBorder)
- aCellBorder->second >>= aRightBorder;
- }
- if (rInfo.nNestLevel == 1 && aLeftBorder.LineWidth && !rFrameProperties.empty())
- {
- lcl_DecrementHoriOrientPosition(rFrameProperties, aLeftBorder.LineWidth * 0.5);
- }
- lcl_adjustBorderDistance(rInfo, aLeftBorder, aRightBorder);
-
- // tdf#106742: since MS Word 2013 (compatibilityMode >= 15), top-level tables are handled the same as nested tables;
- // the default behavior when DOCX doesn't define "compatibilityMode" option is to add the cell spacing
-
- // Undefined should not be possible any more for DOCX, but it is for RTF.
- // In any case, continue to treat undefined as version 12 during import.
- sal_Int32 nMode = m_rDMapper_Impl.GetSettingsTable()->GetWordCompatibilityMode();
-
- if (((nMode < 0) || (0 < nMode && nMode <= 14)) && rInfo.nNestLevel == 1)
- {
- const sal_Int32 nAdjustedMargin = nLeftMargin - nGapHalf - rInfo.nLeftBorderDistance;
- m_aTableProperties->Insert( PROP_LEFT_MARGIN, uno::makeAny( nAdjustedMargin ) );
- }
- else
- {
- // Writer starts a table in the middle of the border.
- // Word starts a table at the left edge of the border,
- // so emulate that by adding the half the width. (also see docxattributeoutput)
- if ( rInfo.nNestLevel > 1 && nLeftMargin < 0 )
- nLeftMargin = 0;
- const sal_Int32 nAdjustedMargin = nLeftMargin - nGapHalf + (aLeftBorder.LineWidth / 2);
- m_aTableProperties->Insert( PROP_LEFT_MARGIN, uno::makeAny( nAdjustedMargin ) );
- }
-
- sal_Int32 nTableWidth = 0;
- sal_Int32 nTableWidthType = text::SizeType::FIX;
- m_aTableProperties->getValue( TablePropertyMap::TABLE_WIDTH, nTableWidth );
- m_aTableProperties->getValue( TablePropertyMap::TABLE_WIDTH_TYPE, nTableWidthType );
- if( nTableWidthType == text::SizeType::FIX )
- {
- if( nTableWidth > 0 )
- m_aTableProperties->Insert( PROP_WIDTH, uno::makeAny( nTableWidth ));
- else
- {
- // tdf#109524: If there is no width for the table, make it simply 100% by default.
- // TODO: use cell contents to evaluate width (according to ECMA-376-1:2016 17.18.87)
- nTableWidth = 100;
- nTableWidthType = text::SizeType::VARIABLE;
- }
- }
- if (nTableWidthType != text::SizeType::FIX)
- {
- m_aTableProperties->Insert( PROP_RELATIVE_WIDTH, uno::makeAny( sal_Int16( nTableWidth ) ) );
- m_aTableProperties->Insert( PROP_IS_WIDTH_RELATIVE, uno::makeAny( true ) );
- }
-
- sal_Int32 nHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH;
- // Fetch Horizontal Orientation in rFrameProperties if not set in m_aTableProperties
- if ( !m_aTableProperties->getValue( TablePropertyMap::HORI_ORIENT, nHoriOrient ) )
- lcl_extractHoriOrient( rFrameProperties, nHoriOrient );
- m_aTableProperties->Insert( PROP_HORI_ORIENT, uno::makeAny( sal_Int16(nHoriOrient) ) );
- //fill default value - if not available
- m_aTableProperties->Insert( PROP_HEADER_ROW_COUNT, uno::makeAny( sal_Int32(0)), false);
-
- // if table is only a single row, and row is set as don't split, set the same value for the whole table.
- if( m_aRowProperties.size() == 1 && m_aRowProperties[0] )
- {
- std::optional<PropertyMap::Property> oSplitAllowed = m_aRowProperties[0]->getProperty(PROP_IS_SPLIT_ALLOWED);
- if( oSplitAllowed )
- {
- bool bRowCanSplit = true;
- oSplitAllowed->second >>= bRowCanSplit;
- if( !bRowCanSplit )
- m_aTableProperties->Insert( PROP_SPLIT, uno::makeAny(bRowCanSplit) );
- }
- }
-
- rInfo.aTableProperties = m_aTableProperties->GetPropertyValues();
- rInfo.aTablePropertyIds = m_aTableProperties->GetPropertyIds();
-
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("debug.tableprops");
- m_aTableProperties->dumpXml();
- TagLogger::getInstance().endElement();
-#endif
-
- }
-
- return pTableStyle;
-}
-
-CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(TableInfo & rInfo, std::vector<HorizontallyMergedCell>& rMerges)
-{
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("getCellProperties");
-#endif
-
- CellPropertyValuesSeq_t aCellProperties( m_aCellProperties.size() );
-
- if ( m_aCellProperties.empty() )
- {
- #ifdef DBG_UTIL
- TagLogger::getInstance().endElement();
- #endif
- return aCellProperties;
- }
- // std::vector< std::vector<PropertyMapPtr> > m_aCellProperties
- PropertyMapVector2::const_iterator aRowOfCellsIterator = m_aCellProperties.begin();
- PropertyMapVector2::const_iterator aRowOfCellsIteratorEnd = m_aCellProperties.end();
- PropertyMapVector2::const_iterator aLastRowIterator = m_aCellProperties.end() - 1;
- sal_Int32 nRow = 0;
-
- css::uno::Sequence<css::beans::PropertyValues>* pCellProperties = aCellProperties.getArray();
- PropertyMapVector1::const_iterator aRowIter = m_aRowProperties.begin();
- while( aRowOfCellsIterator != aRowOfCellsIteratorEnd )
- {
- //aRowOfCellsIterator points to a vector of PropertyMapPtr
- PropertyMapVector1::const_iterator aCellIterator = aRowOfCellsIterator->begin();
- PropertyMapVector1::const_iterator aCellIteratorEnd = aRowOfCellsIterator->end();
-
- sal_Int32 nRowStyleMask = 0;
-
- if (aRowOfCellsIterator==m_aCellProperties.begin())
- {
- if(rInfo.nTblLook&0x20)
- nRowStyleMask |= CNF_FIRST_ROW; // first row style used
- }
- else if (aRowOfCellsIterator==aLastRowIterator)
- {
- if(rInfo.nTblLook&0x40)
- nRowStyleMask |= CNF_LAST_ROW; // last row style used
- }
- else if (*aRowIter && (*aRowIter)->isSet(PROP_TBL_HEADER))
- nRowStyleMask |= CNF_FIRST_ROW; // table header implies first row
- if(!nRowStyleMask) // if no row style used yet
- {
- // banding used only if not first and or last row style used
- if(!(rInfo.nTblLook&0x200))
- { // hbanding used
- int n = nRow + 1;
- if(rInfo.nTblLook&0x20)
- n++;
- if(n & 1)
- nRowStyleMask = CNF_ODD_HBAND;
- else
- nRowStyleMask = CNF_EVEN_HBAND;
- }
- }
-
- // Note that this is intentionally called "cell" and not "column".
- // Don't make the mistake that all cell x's will be in the same column.
- // Merged cells (grid span) in a row will affect the actual column. (fake cells were added to handle gridBefore/After)
- sal_Int32 nCell = 0;
- pCellProperties[nRow].realloc( aRowOfCellsIterator->size() );
- beans::PropertyValues* pSingleCellProperties = pCellProperties[nRow].getArray();
-
- while( aCellIterator != aCellIteratorEnd )
- {
- PropertyMapPtr pAllCellProps( new PropertyMap );
-
- PropertyMapVector1::const_iterator aLastCellIterator = aRowOfCellsIterator->end() - 1;
- bool bIsEndCol = aCellIterator == aLastCellIterator;
- bool bIsEndRow = aRowOfCellsIterator == aLastRowIterator;
-
- //aCellIterator points to a PropertyMapPtr;
- if( *aCellIterator )
- {
- // remove directly applied insideV/H borders since they are meaningless without a context (tdf#82177)
- (*aCellIterator)->Erase(META_PROP_VERTICAL_BORDER);
- (*aCellIterator)->Erase(META_PROP_HORIZONTAL_BORDER);
-
- pAllCellProps->InsertProps(rInfo.pTableDefaults);
-
- sal_Int32 nCellStyleMask = 0;
- if (aCellIterator==aRowOfCellsIterator->begin())
- {
- if(rInfo.nTblLook&0x80)
- nCellStyleMask = CNF_FIRST_COLUMN; // first col style used
- }
- else if (bIsEndCol)
- {
- if(rInfo.nTblLook&0x100)
- nCellStyleMask = CNF_LAST_COLUMN; // last col style used
- }
- if(!nCellStyleMask) // if no cell style is used yet
- {
- if(!(rInfo.nTblLook&0x400))
- { // vbanding used
- int n = nCell + 1;
- if(rInfo.nTblLook&0x80)
- n++;
- if(n & 1)
- nCellStyleMask = CNF_ODD_VBAND;
- else
- nCellStyleMask = CNF_EVEN_VBAND;
- }
- }
- sal_Int32 nCnfStyleMask = nCellStyleMask + nRowStyleMask;
- if(nCnfStyleMask == CNF_FIRST_COLUMN + CNF_FIRST_ROW)
- nCnfStyleMask |= CNF_FIRST_ROW_FIRST_COLUMN;
- else if(nCnfStyleMask == CNF_FIRST_COLUMN + CNF_LAST_ROW)
- nCnfStyleMask |= CNF_LAST_ROW_FIRST_COLUMN;
- else if(nCnfStyleMask == CNF_LAST_COLUMN + CNF_FIRST_ROW)
- nCnfStyleMask |= CNF_FIRST_ROW_LAST_COLUMN;
- else if(nCnfStyleMask == CNF_LAST_COLUMN + CNF_LAST_ROW)
- nCnfStyleMask |= CNF_LAST_ROW_LAST_COLUMN;
-
- if ( rInfo.pTableStyle )
- {
- PropertyMapPtr pStyleProps = rInfo.pTableStyle->GetProperties( nCnfStyleMask );
-
- // Check if we need to clean up some empty border definitions to match what Word does.
- static const PropertyIds pBorders[] =
- {
- PROP_TOP_BORDER, PROP_LEFT_BORDER, PROP_BOTTOM_BORDER, PROP_RIGHT_BORDER
- };
- for (const PropertyIds& rBorder : pBorders)
- {
- std::optional<PropertyMap::Property> oStyleCellBorder = pStyleProps->getProperty(rBorder);
- std::optional<PropertyMap::Property> oDirectCellBorder = (*aCellIterator)->getProperty(rBorder);
- if (oStyleCellBorder && oDirectCellBorder)
- {
- // We have a cell border from the table style and as direct formatting as well.
- table::BorderLine2 aStyleCellBorder = oStyleCellBorder->second.get<table::BorderLine2>();
- table::BorderLine2 aDirectCellBorder = oDirectCellBorder->second.get<table::BorderLine2>();
- if (aStyleCellBorder.LineStyle != table::BorderLineStyle::NONE && aDirectCellBorder.LineStyle == table::BorderLineStyle::NONE)
- {
- // The style one would be visible, but then cleared away as direct formatting.
- // Delete both, so that table formatting can become visible.
- pStyleProps->Erase(rBorder);
- (*aCellIterator)->Erase(rBorder);
- }
- else
- {
- std::optional<PropertyMap::Property> oTableBorder = rInfo.pTableBorders->getProperty(rBorder);
- if (oTableBorder)
- {
- table::BorderLine2 aTableBorder = oTableBorder->second.get<table::BorderLine2>();
- // Both style and direct formatting says that the cell has no border.
- bool bNoCellBorder = aStyleCellBorder.LineStyle == table::BorderLineStyle::NONE && aDirectCellBorder.LineStyle == table::BorderLineStyle::NONE;
- if (aTableBorder.LineStyle != table::BorderLineStyle::NONE && bNoCellBorder)
- {
- // But at a table-level, there is a border, then again delete both cell properties.
- pStyleProps->Erase(rBorder);
- (*aCellIterator)->Erase(rBorder);
- }
- }
- }
- }
- }
-
- pAllCellProps->InsertProps( pStyleProps );
- }
-
- // Remove properties from style/row that aren't allowed in cells
- pAllCellProps->Erase( PROP_HEADER_ROW_COUNT );
- pAllCellProps->Erase( PROP_TBL_HEADER );
-
- // Then add the cell properties
- pAllCellProps->InsertProps(*aCellIterator);
- std::swap(*(*aCellIterator), *pAllCellProps );
-
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("cell");
- TagLogger::getInstance().attribute("cell", nCell);
- TagLogger::getInstance().attribute("row", nRow);
-#endif
-
- // Do not apply horizontal and vertical borders to a one cell table.
- if (m_aCellProperties.size() <= 1 && aRowOfCellsIterator->size() <= 1)
- {
- rInfo.pTableBorders->Erase(META_PROP_HORIZONTAL_BORDER);
- rInfo.pTableBorders->Erase(META_PROP_VERTICAL_BORDER);
- }
- // Do not apply vertical borders to a one column table.
- else if (m_aCellProperties.size() > 1 && aRowOfCellsIterator->size() <= 1)
- {
- bool isOneCol = true;
- for (size_t i = nRow; i < m_aCellProperties.size(); i++)
- {
- if (m_aCellProperties[i].size() > 1)
- {
- isOneCol = false;
- break;
- }
- }
- if (isOneCol)
- rInfo.pTableBorders->Erase(META_PROP_VERTICAL_BORDER);
- }
- // Do not apply horizontal borders to a one row table.
- else if (m_aCellProperties.size() == 1 && aRowOfCellsIterator->size() > 1)
- {
- rInfo.pTableBorders->Erase(META_PROP_HORIZONTAL_BORDER);
- }
-
- // tdf#129452 Checking if current cell is vertically merged with all the other cells below to the bottom.
- // This must be done in order to apply the bottom border of the table to the first cell in a vertical merge.
- std::optional<PropertyMap::Property> oProp = m_aCellProperties[nRow][nCell]->getProperty(PROP_VERTICAL_MERGE);
- bool bMergedVertically = oProp && oProp->second.get<bool>(); // starting cell
- if ( bMergedVertically )
- {
- const sal_uInt32 nColumn = m_rDMapper_Impl.getTableManager().findColumn(nRow, nCell);
- sal_Int32 nLastMergedRow = 0;
- for (size_t i = nRow + 1; bMergedVertically && i < m_aCellProperties.size(); i++)
- {
- const sal_uInt32 nColumnCell = m_rDMapper_Impl.getTableManager().findColumnCell(i, nColumn);
- if ( m_aCellProperties[i].size() > sal::static_int_cast<std::size_t>(nColumnCell) )
- {
- oProp = m_aCellProperties[i][nColumnCell]->getProperty(PROP_VERTICAL_MERGE);
- bMergedVertically = oProp && !oProp->second.get<bool>(); //continuing cell
- if ( bMergedVertically )
- nLastMergedRow = i;
- }
- else
- bMergedVertically = false;
- }
-
- // Only consider the bottom border setting from the last merged cell.
- // Note: in MSO, left/right apply per-unmerged-row. Can't do that in LO, so just using the top cell's borders should be fine.
- if ( nRow < nLastMergedRow )
- {
- (*aCellIterator)->Erase(PROP_BOTTOM_BORDER);
- const sal_uInt32 nColumnCell = m_rDMapper_Impl.getTableManager().findColumnCell(nLastMergedRow, nColumn);
- lcl_mergeBorder( PROP_BOTTOM_BORDER, m_aCellProperties[nLastMergedRow][nColumnCell], *aCellIterator );
- }
- }
-
- const sal_uInt32 nFirstCell = m_rDMapper_Impl.getTableManager().getGridBefore(nRow);
- const sal_uInt32 nLastCell = m_aCellProperties[nRow].size() - m_rDMapper_Impl.getTableManager().getGridAfter(nRow) - 1;
- lcl_computeCellBorders( rInfo.pTableBorders, *aCellIterator, nCell, nFirstCell, nLastCell, nRow, bIsEndRow, bMergedVertically );
-
- //now set the default left+right border distance TODO: there's an sprm containing the default distance!
- aCellIterator->get()->Insert( PROP_LEFT_BORDER_DISTANCE,
- uno::makeAny(rInfo.nLeftBorderDistance ), false);
- aCellIterator->get()->Insert( PROP_RIGHT_BORDER_DISTANCE,
- uno::makeAny(rInfo.nRightBorderDistance ), false);
- aCellIterator->get()->Insert( PROP_TOP_BORDER_DISTANCE,
- uno::makeAny(rInfo.nTopBorderDistance ), false);
- aCellIterator->get()->Insert( PROP_BOTTOM_BORDER_DISTANCE,
- uno::makeAny(rInfo.nBottomBorderDistance ), false);
-
- // Horizontal merge is not a UNO property, extract that info here to rMerges, and then remove it from the map.
- const std::optional<PropertyMap::Property> aHorizontalMergeVal = (*aCellIterator)->getProperty(PROP_HORIZONTAL_MERGE);
- if (aHorizontalMergeVal)
- {
- if (aHorizontalMergeVal->second.get<bool>())
- {
- // first cell in a merge
- HorizontallyMergedCell aMerge(nRow, nCell);
- rMerges.push_back(aMerge);
- }
- else if (!rMerges.empty())
- {
- // resuming an earlier merge
- HorizontallyMergedCell& rMerge = rMerges.back();
- rMerge.m_nLastRow = nRow;
- rMerge.m_nLastCol = nCell;
- }
- (*aCellIterator)->Erase(PROP_HORIZONTAL_MERGE);
- }
- pSingleCellProperties[nCell] = (*aCellIterator)->GetPropertyValues();
-#ifdef DBG_UTIL
- TagLogger::getInstance().endElement();
-#endif
- }
- ++nCell;
- ++aCellIterator;
- }
- ++nRow;
- ++aRowOfCellsIterator;
- ++aRowIter;
- }
-
-#ifdef DBG_UTIL
- TagLogger::getInstance().endElement();
-#endif
-
- return aCellProperties;
-}
-
-/// Do all cells in this row have a CellHideMark property?
-static bool lcl_hideMarks(PropertyMapVector1& rCellProperties)
-{
- for (const PropertyMapPtr & p : rCellProperties)
- {
- // if anything is vertically merged, the row must not be set to fixed
- // as Writer's layout doesn't handle that well
- if (!p->isSet(PROP_CELL_HIDE_MARK) || p->isSet(PROP_VERTICAL_MERGE))
- return false;
- }
- return true;
-}
-
-/// Are all cells in this row empty?
-static bool lcl_emptyRow(std::vector<RowSequence_t>& rTableRanges, sal_Int32 nRow)
-{
- if (nRow >= static_cast<sal_Int32>(rTableRanges.size()))
- {
- SAL_WARN("writerfilter.dmapper", "m_aCellProperties not in sync with rTableRanges?");
- return false;
- }
-
- RowSequence_t rRowSeq = rTableRanges[nRow];
- if (!rRowSeq.hasElements())
- {
- SAL_WARN("writerfilter.dmapper", "m_aCellProperties not in sync with rTableRanges?");
- return false;
- }
-
- if (!rRowSeq[0][0].is())
- {
- // This can happen when we can't import the table, e.g. we're inside a
- // comment.
- SAL_WARN("writerfilter.dmapper", "rRowSeq[0][0] is an empty reference");
- return false;
- }
-
- uno::Reference<text::XTextRangeCompare> xTextRangeCompare(rRowSeq[0][0]->getText(), uno::UNO_QUERY);
- try
- {
- // See SwXText::Impl::ConvertCell(), we need to compare the start of
- // the start and the end of the end. However for our text ranges, only
- // the starts are set, so compareRegionStarts() does what we need.
- bool bRangesAreNotEqual = std::any_of(rRowSeq.begin(), rRowSeq.end(),
- [&xTextRangeCompare](const CellSequence_t& rCellSeq) {
- return xTextRangeCompare->compareRegionStarts(rCellSeq[0], rCellSeq[1]) != 0; });
- if (bRangesAreNotEqual)
- return false;
- }
- catch (const lang::IllegalArgumentException&)
- {
- TOOLS_WARN_EXCEPTION( "writerfilter.dmapper", "compareRegionStarts() failed");
- return false;
- }
- return true;
-}
-
-css::uno::Sequence<css::beans::PropertyValues> DomainMapperTableHandler::endTableGetRowProperties()
-{
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("getRowProperties");
-#endif
-
- css::uno::Sequence<css::beans::PropertyValues> aRowProperties( m_aRowProperties.size() );
- sal_Int32 nRow = 0;
- for( const auto& rRow : m_aRowProperties )
- {
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("rowProps.row");
-#endif
- if (rRow)
- {
- //set default to 'break across pages"
- rRow->Insert( PROP_IS_SPLIT_ALLOWED, uno::makeAny(true ), false );
- // tblHeader is only our property, remove before the property map hits UNO
- rRow->Erase(PROP_TBL_HEADER);
-
- if (lcl_hideMarks(m_aCellProperties[nRow]) && lcl_emptyRow(m_aTableRanges, nRow))
- {
- // We have CellHideMark on all cells, and also all cells are empty:
- // Force the row height to be exactly as specified, and not just as the minimum suggestion.
- rRow->Insert(PROP_SIZE_TYPE, uno::makeAny(text::SizeType::FIX));
- }
-
- aRowProperties[nRow] = rRow->GetPropertyValues();
-#ifdef DBG_UTIL
- rRow->dumpXml();
- lcl_DumpPropertyValues(aRowProperties[nRow]);
-#endif
- }
- ++nRow;
-#ifdef DBG_UTIL
- TagLogger::getInstance().endElement();
-#endif
- }
-
-#ifdef DBG_UTIL
- TagLogger::getInstance().endElement();
-#endif
-
- return aRowProperties;
-}
-
-// table style has got bigger precedence than docDefault style,
-// but lower precedence than the paragraph styles and direct paragraph formatting
-void DomainMapperTableHandler::ApplyParagraphPropertiesFromTableStyle(TableParagraph rParaProp, std::vector< PropertyIds > aAllTableParaProperties, css::beans::PropertyValues rCellProperties)
-{
- for( auto const& eId : aAllTableParaProperties )
- {
- // apply paragraph and character properties of the table style on table paragraphs
- // if there is no direct paragraph formatting
- bool bIsParaLevel = rParaProp.m_pPropertyMap->isSet(eId);
- if ( !bIsParaLevel || isCharacterProperty(eId) )
- {
- if ( (eId == PROP_PARA_LEFT_MARGIN || eId == PROP_PARA_FIRST_LINE_INDENT) &&
- rParaProp.m_pPropertyMap->isSet(PROP_NUMBERING_RULES) )
- {
- // indentation of direct numbering has bigger precedence, than table style
- continue;
- }
-
- OUString sPropertyName = getPropertyName(eId);
-
- if ( bIsParaLevel && ( rParaProp.m_aParaOverrideApplied.find(sPropertyName) != rParaProp.m_aParaOverrideApplied.end() ||
- sPropertyName.startsWith("CharFontName") ) )
- {
- // don't apply table style, if this character property was applied on paragraph level
- // (or in the case of paragraph level font name settings to avoid regressions)
- continue;
- }
-
- auto pCellProp = std::find_if(rCellProperties.begin(), rCellProperties.end(),
- [&](const beans::PropertyValue& rProp) { return rProp.Name == sPropertyName; });
- // this cell applies the table style property
- if (pCellProp != rCellProperties.end())
- {
- bool bDocDefault;
- // handle paragraph background color defined in CellColorHandler
- if (eId == PROP_FILL_COLOR)
- {
- // table style defines paragraph background color, use the correct property name
- auto pFillStyleProp = std::find_if(rCellProperties.begin(), rCellProperties.end(),
- [&](const beans::PropertyValue& rProp) { return rProp.Name == "FillStyle"; });
- if ( pFillStyleProp != rCellProperties.end() &&
- pFillStyleProp->Value == uno::makeAny(drawing::FillStyle_SOLID) )
- {
- sPropertyName = "ParaBackColor";
- }
- else
- {
- // FillStyle_NONE, skip table style usage for paragraph background color
- continue;
- }
- }
- OUString sParaStyleName;
- rParaProp.m_rPropertySet->getPropertyValue("ParaStyleName") >>= sParaStyleName;
- StyleSheetEntryPtr pEntry = m_rDMapper_Impl.GetStyleSheetTable()->FindStyleSheetByConvertedStyleName(sParaStyleName);
- uno::Any aParaStyle = m_rDMapper_Impl.GetPropertyFromStyleSheet(eId, pEntry, true, true, &bDocDefault);
- // A very strange compatibility rule says that the DEFAULT style's specified fontsize of 11 or 12
- // or a specified left justify will always be overridden by the table-style.
- // Normally this rule is applied, so always do this unless a compatSetting indicates otherwise.
- bool bCompatOverride = false;
- if ( (eId == PROP_CHAR_HEIGHT || eId == PROP_PARA_ADJUST) && sParaStyleName == m_rDMapper_Impl.GetDefaultParaStyleName() )
- {
- if ( eId == PROP_CHAR_HEIGHT )
- bCompatOverride = aParaStyle == uno::Any(double(11)) || aParaStyle == uno::Any(double(12));
- else if ( eId == PROP_PARA_ADJUST )
- {
- style::ParagraphAdjust eAdjust(style::ParagraphAdjust_CENTER);
- aParaStyle >>= eAdjust;
- bCompatOverride = eAdjust == style::ParagraphAdjust_LEFT;
- }
-
- // The wording is confusing here. Normally, the paragraph style DOES override the table-style.
- // But for these two special situations, do not override the table-style. So the default is false.
- // If false, then "CompatOverride" the normal behaviour, and apply the table-style's value.
- bCompatOverride &= !m_rDMapper_Impl.GetSettingsTable()->GetCompatSettingValue(u"overrideTableStyleFontSizeAndJustification");
- }
-
- // use table style when no paragraph style setting or a docDefault value is applied instead of it
- if ( aParaStyle == uno::Any() || bDocDefault || bCompatOverride ) try
- {
- // check property state of paragraph
- uno::Reference<text::XParagraphCursor> xParagraph(
- rParaProp.m_rEndParagraph->getText()->createTextCursorByRange(rParaProp.m_rEndParagraph), uno::UNO_QUERY_THROW );
- // select paragraph
- xParagraph->gotoStartOfParagraph( true );
- uno::Reference< beans::XPropertyState > xParaProperties( xParagraph, uno::UNO_QUERY_THROW );
- if ( xParaProperties->getPropertyState(sPropertyName) == css::beans::PropertyState_DEFAULT_VALUE )
- {
- if ( eId != PROP_FILL_COLOR )
- {
- // apply style setting when the paragraph doesn't modify it
- rParaProp.m_rPropertySet->setPropertyValue( sPropertyName, pCellProp->Value );
- }
- else
- {
- // we need this for complete import of table-style based paragraph background color
- rParaProp.m_rPropertySet->setPropertyValue( "FillColor", pCellProp->Value );
- rParaProp.m_rPropertySet->setPropertyValue( "FillStyle", uno::makeAny(drawing::FillStyle_SOLID) );
- }
- }
- else
- {
- // apply style setting only on text portions without direct modification of it
- uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xParagraph, uno::UNO_QUERY);
- uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
- uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY);
- uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
- while ( xRunEnum->hasMoreElements() )
- {
- uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY);
- uno::Reference< beans::XPropertyState > xRunProperties( xRun, uno::UNO_QUERY_THROW );
- if ( xRunProperties->getPropertyState(sPropertyName) == css::beans::PropertyState_DEFAULT_VALUE )
- {
- uno::Reference< beans::XPropertySet > xRunPropertySet( xRun, uno::UNO_QUERY_THROW );
- xRunPropertySet->setPropertyValue( sPropertyName, pCellProp->Value );
- }
- }
- }
- }
- catch ( const uno::Exception & )
- {
- TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table style correction");
- }
- }
- }
- }
-}
-
-// convert formula range identifier ABOVE, BELOW, LEFT and RIGHT
-static void lcl_convertFormulaRanges(const uno::Reference<text::XTextTable> & xTable)
-{
- uno::Reference<table::XCellRange> xCellRange(xTable, uno::UNO_QUERY_THROW);
- uno::Reference<container::XIndexAccess> xTableRows(xTable->getRows(), uno::UNO_QUERY_THROW);
- sal_Int32 nRows = xTableRows->getCount();
- for (sal_Int32 nRow = 0; nRow < nRows; ++nRow)
- {
- for (sal_Int16 nCol = 0; nCol < MAXTABLECELLS; ++nCol)
- {
- try
- {
- uno::Reference<beans::XPropertySet> xCellProperties(xCellRange->getCellByPosition(nCol, nRow), uno::UNO_QUERY_THROW);
- uno::Sequence<beans::PropertyValue> aCellGrabBag;
- xCellProperties->getPropertyValue("CellInteropGrabBag") >>= aCellGrabBag;
- OUString sFormula;
- bool bReplace = false;
- for (const auto& rProp : std::as_const(aCellGrabBag))
- {
- if ( rProp.Name == "CellFormulaConverted" )
- {
- rProp.Value >>= sFormula;
- struct RangeDirection
- {
- OUString m_sName;
- sal_Int16 m_nCol;
- sal_Int16 m_nRow;
- };
- static const RangeDirection pDirections[] =
- {
- { OUString(" LEFT "), -1, 0},
- { OUString(" RIGHT "), 1, 0},
- { OUString(" ABOVE "), 0, -1},
- { OUString(" BELOW "), 0, 1 }
- };
- for (const RangeDirection& rRange : pDirections)
- {
- if ( sFormula.indexOf(rRange.m_sName) > -1 )
- {
- // range starts at the first cell above/below/left/right, but ends at the
- // table border or at the first non-value cell after a value cell
- bool bFoundFirst = false;
- OUString sNextCell;
- OUString sLastCell;
- OUString sLastValueCell;
- // walk through the cells of the range
- try
- {
- sal_Int32 nCell = 0;
- while (++nCell)
- {
- uno::Reference<beans::XPropertySet> xCell(
- xCellRange->getCellByPosition(nCol + nCell * rRange.m_nCol, nRow + nCell * rRange.m_nRow),
- uno::UNO_QUERY_THROW);
- // empty cell or cell with text content is end of the range
- uno::Reference<text::XText> xText(xCell, uno::UNO_QUERY_THROW);
- sLastCell = xCell->getPropertyValue("CellName").get<OUString>();
- if (sNextCell.isEmpty())
- sNextCell = sLastCell;
- try
- {
- // accept numbers with comma and percent
- OUString sCellText = xText->getString().replace(',', '.');
- if (sCellText.endsWith("%"))
- sCellText = sCellText.copy(0, sCellText.getLength()-1);
- boost::lexical_cast<double>(sCellText);
- }
- catch( boost::bad_lexical_cast const& )
- {
- if ( !bFoundFirst )
- {
- // still search value cells
- continue;
- }
- else
- {
- // end of range
- break;
- }
- }
- sLastValueCell = sLastCell;
- bFoundFirst = true;
- }
- }
- catch ( const lang::IndexOutOfBoundsException & )
- {
- }
-
- if ( !sNextCell.isEmpty() )
- {
- OUString sRange = "<" + sNextCell + ":" +
- ( sLastValueCell.isEmpty() ? sLastCell : sLastValueCell ) + ">";
- sFormula = sFormula.replaceAll(rRange.m_sName, sRange);
- bReplace = true;
- }
- }
- }
-
- // update formula field
- if (bReplace)
- {
- uno::Reference<text::XText> xCell(xCellRange->getCellByPosition(nCol, nRow), uno::UNO_QUERY);
- uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xCell, uno::UNO_QUERY);
- uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
- uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY);
- uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration();
- while ( xRunEnum->hasMoreElements() )
- {
- uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY);
- uno::Reference< beans::XPropertySet > xRunProperties( xRun, uno::UNO_QUERY_THROW );
- if ( xRunProperties->getPropertyValue("TextPortionType") == uno::makeAny(OUString("TextField")) )
- {
- uno::Reference<text::XTextField> const xField(xRunProperties->getPropertyValue("TextField").get<uno::Reference<text::XTextField>>());
- uno::Reference< beans::XPropertySet > xFieldProperties( xField, uno::UNO_QUERY_THROW );
- // cell can contain multiple text fields, but only one is handled now (~formula cell)
- if ( rProp.Value != xFieldProperties->getPropertyValue("Content") )
- continue;
- xFieldProperties->setPropertyValue("Content", uno::makeAny(sFormula));
- // update grab bag
- auto aGrabBag = comphelper::sequenceToContainer< std::vector<beans::PropertyValue> >(aCellGrabBag);
- beans::PropertyValue aValue;
- aValue.Name = "CellFormulaConverted";
- aValue.Value <<= sFormula;
- aGrabBag.push_back(aValue);
- xCellProperties->setPropertyValue("CellInteropGrabBag", uno::makeAny(comphelper::containerToSequence(aGrabBag)));
- }
- }
- }
- }
- }
- }
- catch ( const lang::IndexOutOfBoundsException & )
- {
- // jump to next table row
- break;
- }
- }
- }
-}
-
-void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel, bool bTableStartsAtCellStart)
-{
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("tablehandler.endTable");
-#endif
-
- // If we want to make this table a floating one.
- std::vector<beans::PropertyValue> aFrameProperties = comphelper::sequenceToContainer<std::vector<beans::PropertyValue> >
- (m_rDMapper_Impl.getTableManager().getCurrentTablePosition());
- TableInfo aTableInfo;
- aTableInfo.nNestLevel = nestedTableLevel;
- aTableInfo.pTableStyle = endTableGetTableStyle(aTableInfo, aFrameProperties);
- // expands to uno::Sequence< Sequence< beans::PropertyValues > >
-
- std::vector<HorizontallyMergedCell> aMerges;
- CellPropertyValuesSeq_t aCellProperties = endTableGetCellProperties(aTableInfo, aMerges);
-
- css::uno::Sequence<css::beans::PropertyValues> aRowProperties = endTableGetRowProperties();
-
-#ifdef DBG_UTIL
- lcl_DumpPropertyValueSeq(aRowProperties);
-#endif
-
- if (!m_aTableRanges.empty())
- {
- uno::Reference<text::XTextRange> xStart;
- uno::Reference<text::XTextRange> xEnd;
-
- bool bFloating = !aFrameProperties.empty();
-
- // OOXML table style may contain paragraph properties, apply these on cell paragraphs
- if ( m_aTableRanges[0].hasElements() && m_aTableRanges[0][0].hasElements() )
- {
- // collect all paragraph properties used in table styles
- PropertyMapPtr pAllTableProps( new PropertyMap );
- pAllTableProps->InsertProps(aTableInfo.pTableDefaults);
- if ( aTableInfo.pTableStyle )
- pAllTableProps->InsertProps(aTableInfo.pTableStyle->GetProperties( CNF_ALL ));
- for (const auto& eId : pAllTableProps->GetPropertyIds())
- {
- if ( !isParagraphProperty(eId) && !isCharacterProperty(eId) )
- pAllTableProps->Erase(eId);
- }
- std::vector< PropertyIds > aAllTableParaProperties = pAllTableProps->GetPropertyIds();
-
- if ( !aAllTableParaProperties.empty() )
- {
- TableParagraphVectorPtr pTableParagraphs = m_rDMapper_Impl.getTableManager().getCurrentParagraphs();
- for (size_t nRow = 0; nRow < m_aTableRanges.size(); ++nRow)
- {
- // Note that this is "cell" since you must not treat it as "column".
- for (size_t nCell = 0; nCell < m_aTableRanges[nRow].size(); ++nCell)
- {
- auto rStartPara = m_aTableRanges[nRow][nCell][0];
- if (!rStartPara.is())
- continue;
- auto rEndPara = m_aTableRanges[nRow][nCell][1];
- uno::Reference<text::XTextRangeCompare> xTextRangeCompare(rStartPara->getText(), uno::UNO_QUERY);
- bool bApply = false;
- // search paragraphs of the cell
- std::vector<TableParagraph>::iterator aIt = pTableParagraphs->begin();
- while ( aIt != pTableParagraphs->end() ) try
- {
- if (!bApply && xTextRangeCompare->compareRegionStarts(rStartPara, aIt->m_rStartParagraph) == 0)
- bApply = true;
- if (bApply)
- {
- bool bEndOfApply = (xTextRangeCompare->compareRegionEnds(rEndPara, aIt->m_rEndParagraph) == 0);
- ApplyParagraphPropertiesFromTableStyle(*aIt, aAllTableParaProperties, aCellProperties[nRow][nCell]);
- // erase processed paragraph from list of pending paragraphs
- aIt = pTableParagraphs->erase(aIt);
- if (bEndOfApply)
- break;
- }
- else
- ++aIt;
- }
- catch( const lang::IllegalArgumentException & )
- {
- // skip compareRegion with nested tables
- ++aIt;
- }
- }
- }
- }
- }
-
- // Additional checks: if we can do this.
- if (bFloating && m_aTableRanges[0].hasElements() && m_aTableRanges[0][0].hasElements())
- {
- xStart = m_aTableRanges[0][0][0];
- uno::Sequence< uno::Sequence< uno::Reference<text::XTextRange> > >& rLastRow = m_aTableRanges[m_aTableRanges.size() - 1];
- if (rLastRow.hasElements())
- {
- uno::Sequence< uno::Reference<text::XTextRange> >& rLastCell = rLastRow[rLastRow.getLength() - 1];
- xEnd = rLastCell[1];
- }
- }
- uno::Reference<text::XTextTable> xTable;
- try
- {
- if (m_xText.is())
- {
- xTable = m_xText->convertToTable(comphelper::containerToSequence(m_aTableRanges), aCellProperties, aRowProperties, aTableInfo.aTableProperties);
-
- if (xTable.is())
- {
- if (!aMerges.empty())
- {
- static const std::vector<std::u16string_view> aBorderNames
- = { u"TopBorder", u"LeftBorder", u"BottomBorder", u"RightBorder" };
-
- // Perform horizontal merges in reverse order, so the fact that merging changes the position of cells won't cause a problem for us.
- for (std::vector<HorizontallyMergedCell>::reverse_iterator it = aMerges.rbegin(); it != aMerges.rend(); ++it)
- {
- uno::Reference<table::XCellRange> xCellRange(xTable, uno::UNO_QUERY_THROW);
- uno::Reference<beans::XPropertySet> xFirstCell(
- xCellRange->getCellByPosition(it->m_nFirstCol, it->m_nFirstRow),
- uno::UNO_QUERY_THROW);
- OUString aFirst
- = xFirstCell->getPropertyValue("CellName").get<OUString>();
- // tdf#105852: Only try to merge if m_nLastCol is set (i.e. there were some merge continuation cells)
- if (it->m_nLastCol != -1)
- {
- // Save border properties of the first cell
- // before merge.
- table::BorderLine2 aBorderValues[4];
- for (size_t i = 0; i < aBorderNames.size(); ++i)
- xFirstCell->getPropertyValue(OUString(aBorderNames[i]))
- >>= aBorderValues[i];
-
- uno::Reference<beans::XPropertySet> xLastCell(
- xCellRange->getCellByPosition(it->m_nLastCol, it->m_nLastRow),
- uno::UNO_QUERY_THROW);
- OUString aLast
- = xLastCell->getPropertyValue("CellName").get<OUString>();
-
- uno::Reference<text::XTextTableCursor> xCursor = xTable->createCursorByCellName(aFirst);
- xCursor->gotoCellByName(aLast, true);
-
- xCursor->mergeRange();
-
- // Handle conflicting properties: mergeRange()
- // takes the last cell, Word takes the first
- // cell.
- for (size_t i = 0; i < aBorderNames.size(); ++i)
- {
- if (aBorderValues[i].LineStyle != table::BorderLineStyle::NONE)
- xFirstCell->setPropertyValue(
- OUString(aBorderNames[i]), uno::makeAny(aBorderValues[i]));
- }
- }
- }
- }
-
- // convert special range IDs ABOVE, BELOW, LEFT and RIGHT
- lcl_convertFormulaRanges(xTable);
- }
- }
- }
- catch ( const lang::IllegalArgumentException & )
- {
- TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Conversion to table error");
-#ifdef DBG_UTIL
- TagLogger::getInstance().chars(std::string("failed to import table!"));
-#endif
- }
- catch ( const uno::Exception & )
- {
- TOOLS_INFO_EXCEPTION("writerfilter.dmapper", "Exception during table creation");
- }
-
- // If we have a table with a start and an end position, we should make it a floating one.
- // Unless the table had a foot or endnote, as Writer doesn't support those in TextFrames.
- if (xTable.is() && xStart.is() && xEnd.is() && !m_bHadFootOrEndnote)
- {
- uno::Reference<beans::XPropertySet> xTableProperties(xTable, uno::UNO_QUERY);
- bool bIsRelative = false;
- xTableProperties->getPropertyValue("IsWidthRelative") >>= bIsRelative;
- if (!bIsRelative)
- {
- beans::PropertyValue aValue;
- aValue.Name = "Width";
- aValue.Value = xTableProperties->getPropertyValue("Width");
- aFrameProperties.push_back(aValue);
- }
- else
- {
- beans::PropertyValue aValue;
- aValue.Name = "FrameWidthPercent";
- aValue.Value = xTableProperties->getPropertyValue("RelativeWidth");
- aFrameProperties.push_back(aValue);
-
- // Applying the relative width to the frame, needs to have the table width to be 100% of the frame width
- xTableProperties->setPropertyValue("RelativeWidth", uno::makeAny(sal_Int16(100)));
- }
-
- // A non-zero left margin would move the table out of the frame, move the frame itself instead.
- xTableProperties->setPropertyValue("LeftMargin", uno::makeAny(sal_Int32(0)));
-
- if (nestedTableLevel >= 2)
- {
- // Floating tables inside a table always stay inside the cell.
- aFrameProperties.push_back(
- comphelper::makePropertyValue("IsFollowingTextFlow", true));
- }
-
- // In case the document ends with a table, we're called after
- // SectionPropertyMap::CloseSectionGroup(), so we'll have no idea
- // about the text area width, nor can fix this by delaying the text
- // frame conversion: just do it here.
- // Also, when the anchor is within a table, then do it here as well,
- // as xStart/xEnd would not point to the start/end at conversion
- // time anyway.
- // Next exception: it's pointless to delay the conversion if the
- // table is not in the body text.
- sal_Int32 nTableWidth = 0;
- m_aTableProperties->getValue(TablePropertyMap::TABLE_WIDTH, nTableWidth);
- sal_Int32 nTableWidthType = text::SizeType::FIX;
- m_aTableProperties->getValue(TablePropertyMap::TABLE_WIDTH_TYPE, nTableWidthType);
- if (m_rDMapper_Impl.GetSectionContext() && nestedTableLevel <= 1 && !m_rDMapper_Impl.IsInHeaderFooter())
- m_rDMapper_Impl.m_aPendingFloatingTables.emplace_back(xStart, xEnd, comphelper::containerToSequence(aFrameProperties), nTableWidth, nTableWidthType);
- else
- {
- // m_xText points to the body text, get the current xText from m_rDMapper_Impl, in case e.g. we would be in a header.
- uno::Reference<text::XTextAppendAndConvert> xTextAppendAndConvert(m_rDMapper_Impl.GetTopTextAppend(), uno::UNO_QUERY);
- // Only execute the conversion if the table is not anchored at
- // the start of an outer table cell, that's not yet
- // implemented.
- if (xTextAppendAndConvert.is() && !bTableStartsAtCellStart)
- xTextAppendAndConvert->convertToTextFrame(xStart, xEnd, comphelper::containerToSequence(aFrameProperties));
- }
- }
-
- // We're right after a table conversion.
- m_rDMapper_Impl.m_bConvertedTable = true;
- }
-
- m_aTableProperties.clear();
- m_aCellProperties.clear();
- m_aRowProperties.clear();
- m_bHadFootOrEndnote = false;
-
-#ifdef DBG_UTIL
- TagLogger::getInstance().endElement();
- TagLogger::getInstance().endElement();
-#endif
-}
-
-void DomainMapperTableHandler::startRow(const TablePropertyMapPtr& pProps)
-{
- m_aRowProperties.push_back( pProps.get() );
- m_aCellProperties.emplace_back( );
-
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("table.row");
- if (pProps != nullptr)
- pProps->dumpXml();
-#endif
-
- m_aRowRanges.clear();
-}
-
-void DomainMapperTableHandler::endRow()
-{
- m_aTableRanges.push_back(comphelper::containerToSequence(m_aRowRanges));
-#ifdef DBG_UTIL
- TagLogger::getInstance().endElement();
-#endif
-}
-
-void DomainMapperTableHandler::startCell(const css::uno::Reference< css::text::XTextRange > & start,
- const TablePropertyMapPtr& pProps )
-{
- sal_uInt32 nRow = m_aRowProperties.size();
- if ( pProps )
- m_aCellProperties[nRow - 1].push_back( pProps.get() );
- else
- {
- // Adding an empty cell properties map to be able to get
- // the table defaults properties
- TablePropertyMapPtr pEmptyProps( new TablePropertyMap( ) );
- m_aCellProperties[nRow - 1].push_back( pEmptyProps.get() );
- }
-
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("table.cell");
- TagLogger::getInstance().startElement("table.cell.start");
- TagLogger::getInstance().chars(XTextRangeToString(start));
- TagLogger::getInstance().endElement();
- if (pProps)
- pProps->printProperties();
-#endif
-
- //add a new 'row' of properties
- m_aCellRange.clear();
- uno::Reference<text::XTextRange> xStart;
- if (start)
- xStart = start->getStart();
- m_aCellRange.push_back(xStart);
-}
-
-void DomainMapperTableHandler::endCell(const css::uno::Reference< css::text::XTextRange > & end)
-{
-#ifdef DBG_UTIL
- TagLogger::getInstance().startElement("table.cell.end");
- TagLogger::getInstance().chars(XTextRangeToString(end));
- TagLogger::getInstance().endElement();
- TagLogger::getInstance().endElement();
-#endif
-
- uno::Reference<text::XTextRange> xEnd;
- if (end)
- xEnd = end->getEnd();
- m_aCellRange.push_back(xEnd);
- m_aRowRanges.push_back(comphelper::containerToSequence(m_aCellRange));
-}
-
-void DomainMapperTableHandler::setHadFootOrEndnote(bool bHadFootOrEndnote)
-{
- m_bHadFootOrEndnote = bHadFootOrEndnote;
-}
-
-DomainMapper_Impl& DomainMapperTableHandler::getDomainMapperImpl()
-{
- return m_rDMapper_Impl;
-}
-
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */