update emoji autocorrect entries from po-files
[LibreOffice.git] / writerfilter / source / dmapper / DomainMapperTableHandler.cxx
blob5dcae2b8184350c89d17d841517b676eae72da67
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 #include <DomainMapperTableHandler.hxx>
20 #include <DomainMapper_Impl.hxx>
21 #include <StyleSheetTable.hxx>
22 #include <com/sun/star/beans/XPropertyState.hpp>
23 #include <com/sun/star/container/XEnumerationAccess.hpp>
24 #include <com/sun/star/table/TableBorderDistances.hpp>
25 #include <com/sun/star/table/TableBorder.hpp>
26 #include <com/sun/star/table/BorderLine2.hpp>
27 #include <com/sun/star/table/BorderLineStyle.hpp>
28 #include <com/sun/star/table/XCellRange.hpp>
29 #include <com/sun/star/text/HoriOrientation.hpp>
30 #include <com/sun/star/text/RelOrientation.hpp>
31 #include <com/sun/star/text/SizeType.hpp>
32 #include <com/sun/star/text/VertOrientation.hpp>
33 #include <com/sun/star/text/XTextRangeCompare.hpp>
34 #include <com/sun/star/style/ParagraphAdjust.hpp>
35 #include <TablePositionHandler.hxx>
36 #include <ConversionHelper.hxx>
37 #include <util.hxx>
38 #include <osl/diagnose.h>
39 #include <comphelper/sequence.hxx>
41 #ifdef DEBUG_WRITERFILTER
42 #include <PropertyMapHelper.hxx>
43 #include <rtl/ustring.hxx>
44 #endif
46 namespace writerfilter {
47 namespace dmapper {
49 using namespace ::com::sun::star;
50 using namespace ::std;
52 #define DEF_BORDER_DIST 190 //0,19cm
54 DomainMapperTableHandler::DomainMapperTableHandler(TextReference_t const& xText,
55 DomainMapper_Impl& rDMapper_Impl)
56 : m_xText(xText),
57 m_rDMapper_Impl( rDMapper_Impl ),
58 m_nCellIndex(0),
59 m_nRowIndex(0),
60 m_bHadFootOrEndnote(false)
64 DomainMapperTableHandler::~DomainMapperTableHandler()
68 void DomainMapperTableHandler::startTable(unsigned int nRows,
69 unsigned int /*nDepth*/,
70 TablePropertyMapPtr pProps)
72 m_aTableProperties = pProps;
73 m_pTableSeq = TableSequencePointer_t(new TableSequence_t(nRows));
74 m_nRowIndex = 0;
76 #ifdef DEBUG_WRITERFILTER
77 TagLogger::getInstance().startElement("tablehandler.table");
78 TagLogger::getInstance().attribute("rows", nRows);
80 if (pProps.get() != nullptr)
81 pProps->dumpXml();
82 #endif
87 PropertyMapPtr lcl_SearchParentStyleSheetAndMergeProperties(const StyleSheetEntryPtr& rStyleSheet, StyleSheetTablePtr pStyleSheetTable)
89 PropertyMapPtr pRet;
91 if (!rStyleSheet)
92 return pRet;
94 if(!rStyleSheet->sBaseStyleIdentifier.isEmpty())
96 const StyleSheetEntryPtr pParentStyleSheet = pStyleSheetTable->FindStyleSheetByISTD(rStyleSheet->sBaseStyleIdentifier);
97 //a loop in the style hierarchy, bail out
98 if (pParentStyleSheet == rStyleSheet)
99 return pRet;
101 pRet = lcl_SearchParentStyleSheetAndMergeProperties( pParentStyleSheet, pStyleSheetTable );
103 else
105 pRet.reset( new PropertyMap );
108 if (pRet)
110 pRet->InsertProps(rStyleSheet->pProperties);
113 return pRet;
116 void lcl_mergeBorder( PropertyIds nId, PropertyMapPtr pOrig, PropertyMapPtr pDest )
118 boost::optional<PropertyMap::Property> pOrigVal = pOrig->getProperty(nId);
120 if ( pOrigVal )
122 pDest->Insert( nId, pOrigVal->second, false );
126 void lcl_computeCellBorders( PropertyMapPtr pTableBorders, PropertyMapPtr pCellProps,
127 sal_Int32 nCell, sal_Int32 nRow, bool bIsEndCol, bool bIsEndRow )
129 boost::optional<PropertyMap::Property> pVerticalVal = pCellProps->getProperty(META_PROP_VERTICAL_BORDER);
130 boost::optional<PropertyMap::Property> pHorizontalVal = pCellProps->getProperty(META_PROP_HORIZONTAL_BORDER);
132 // Handle the vertical and horizontal borders
133 uno::Any aVertProp;
134 if ( !pVerticalVal)
136 pVerticalVal = pTableBorders->getProperty(META_PROP_VERTICAL_BORDER);
137 if ( pVerticalVal )
138 aVertProp = pVerticalVal->second;
140 else
142 aVertProp = pVerticalVal->second;
143 pCellProps->Erase( pVerticalVal->first );
146 uno::Any aHorizProp;
147 if ( !pHorizontalVal )
149 pHorizontalVal = pTableBorders->getProperty(META_PROP_HORIZONTAL_BORDER);
150 if ( pHorizontalVal )
151 aHorizProp = pHorizontalVal->second;
153 else
155 aHorizProp = pHorizontalVal->second;
156 pCellProps->Erase( pHorizontalVal->first );
159 if ( nCell == 0 )
161 lcl_mergeBorder( PROP_LEFT_BORDER, pTableBorders, pCellProps );
162 if ( pVerticalVal )
163 pCellProps->Insert( PROP_RIGHT_BORDER, aVertProp, false );
166 if ( bIsEndCol )
168 lcl_mergeBorder( PROP_RIGHT_BORDER, pTableBorders, pCellProps );
169 if ( pVerticalVal )
170 pCellProps->Insert( PROP_LEFT_BORDER, aVertProp, false );
173 if ( nCell > 0 && !bIsEndCol )
175 if ( pVerticalVal )
177 pCellProps->Insert( PROP_RIGHT_BORDER, aVertProp, false );
178 pCellProps->Insert( PROP_LEFT_BORDER, aVertProp, false );
182 if ( nRow == 0 )
184 lcl_mergeBorder( PROP_TOP_BORDER, pTableBorders, pCellProps );
185 if ( pHorizontalVal )
186 pCellProps->Insert( PROP_BOTTOM_BORDER, aHorizProp, false );
189 if ( bIsEndRow )
191 lcl_mergeBorder( PROP_BOTTOM_BORDER, pTableBorders, pCellProps );
192 if ( pHorizontalVal )
193 pCellProps->Insert( PROP_TOP_BORDER, aHorizProp, false );
196 if ( nRow > 0 && !bIsEndRow )
198 if ( pHorizontalVal )
200 pCellProps->Insert( PROP_TOP_BORDER, aHorizProp, false );
201 pCellProps->Insert( PROP_BOTTOM_BORDER, aHorizProp, false );
206 #ifdef DEBUG_WRITERFILTER
208 void lcl_debug_BorderLine(table::BorderLine & rLine)
210 TagLogger::getInstance().startElement("BorderLine");
211 TagLogger::getInstance().attribute("Color", rLine.Color);
212 TagLogger::getInstance().attribute("InnerLineWidth", rLine.InnerLineWidth);
213 TagLogger::getInstance().attribute("OuterLineWidth", rLine.OuterLineWidth);
214 TagLogger::getInstance().attribute("LineDistance", rLine.LineDistance);
215 TagLogger::getInstance().endElement();
218 void lcl_debug_TableBorder(table::TableBorder & rBorder)
220 TagLogger::getInstance().startElement("TableBorder");
221 lcl_debug_BorderLine(rBorder.TopLine);
222 TagLogger::getInstance().attribute("IsTopLineValid", sal_uInt32(rBorder.IsTopLineValid));
223 lcl_debug_BorderLine(rBorder.BottomLine);
224 TagLogger::getInstance().attribute("IsBottomLineValid", sal_uInt32(rBorder.IsBottomLineValid));
225 lcl_debug_BorderLine(rBorder.LeftLine);
226 TagLogger::getInstance().attribute("IsLeftLineValid", sal_uInt32(rBorder.IsLeftLineValid));
227 lcl_debug_BorderLine(rBorder.RightLine);
228 TagLogger::getInstance().attribute("IsRightLineValid", sal_uInt32(rBorder.IsRightLineValid));
229 lcl_debug_BorderLine(rBorder.VerticalLine);
230 TagLogger::getInstance().attribute("IsVerticalLineValid", sal_uInt32(rBorder.IsVerticalLineValid));
231 lcl_debug_BorderLine(rBorder.HorizontalLine);
232 TagLogger::getInstance().attribute("IsHorizontalLineValid", sal_uInt32(rBorder.IsHorizontalLineValid));
233 TagLogger::getInstance().attribute("Distance", rBorder.Distance);
234 TagLogger::getInstance().attribute("IsDistanceValid", sal_uInt32(rBorder.IsDistanceValid));
235 TagLogger::getInstance().endElement();
237 #endif
239 struct TableInfo
241 sal_Int32 nLeftBorderDistance;
242 sal_Int32 nRightBorderDistance;
243 sal_Int32 nTopBorderDistance;
244 sal_Int32 nBottomBorderDistance;
245 sal_Int32 nTblLook;
246 sal_Int32 nNestLevel;
247 PropertyMapPtr pTableDefaults;
248 PropertyMapPtr pTableBorders;
249 TableStyleSheetEntry* pTableStyle;
250 TablePropertyValues_t aTableProperties;
252 TableInfo()
253 : nLeftBorderDistance(DEF_BORDER_DIST)
254 , nRightBorderDistance(DEF_BORDER_DIST)
255 , nTopBorderDistance(0)
256 , nBottomBorderDistance(0)
257 , nTblLook(0x4a0)
258 , nNestLevel(0)
259 , pTableDefaults(new PropertyMap)
260 , pTableBorders(new PropertyMap)
261 , pTableStyle(nullptr)
267 namespace
270 bool lcl_extractTableBorderProperty(PropertyMapPtr pTableProperties, const PropertyIds nId, TableInfo& rInfo, table::BorderLine2& rLine)
272 if (!pTableProperties)
273 return false;
275 const boost::optional<PropertyMap::Property> aTblBorder = pTableProperties->getProperty(nId);
276 if( aTblBorder )
278 OSL_VERIFY(aTblBorder->second >>= rLine);
280 rInfo.pTableBorders->Insert( nId, uno::makeAny( rLine ) );
281 rInfo.pTableDefaults->Erase( nId );
283 return true;
286 return false;
291 bool lcl_extractHoriOrient(std::vector<beans::PropertyValue>& rFrameProperties, sal_Int32& nHoriOrient)
293 // Shifts the frame left by the given value.
294 for (size_t i = 0; i < rFrameProperties.size(); ++i)
296 if (rFrameProperties[i].Name == "HoriOrient")
298 nHoriOrient = rFrameProperties[i].Value.get<sal_Int32>();
299 return true;
302 return false;
305 void lcl_DecrementHoriOrientPosition(std::vector<beans::PropertyValue>& rFrameProperties, sal_Int32 nAmount)
307 // Shifts the frame left by the given value.
308 for (size_t i = 0; i < rFrameProperties.size(); ++i)
310 beans::PropertyValue& rPropertyValue = rFrameProperties[i];
311 if (rPropertyValue.Name == "HoriOrientPosition")
313 sal_Int32 nValue = rPropertyValue.Value.get<sal_Int32>();
314 nValue -= nAmount;
315 rPropertyValue.Value <<= nValue;
316 return;
321 TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(TableInfo & rInfo, std::vector<beans::PropertyValue>& rFrameProperties)
323 // will receive the table style if any
324 TableStyleSheetEntry* pTableStyle = nullptr;
326 if( m_aTableProperties.get() )
328 //create properties from the table attributes
329 //...pPropMap->Insert( PROP_LEFT_MARGIN, uno::makeAny( m_nLeftMargin - m_nGapHalf ));
330 //pPropMap->Insert( PROP_HORI_ORIENT, uno::makeAny( text::HoriOrientation::RIGHT ));
331 sal_Int32 nGapHalf = 0;
332 sal_Int32 nLeftMargin = 0;
333 sal_Int32 nTableWidth = 0;
334 sal_Int32 nTableWidthType = text::SizeType::FIX;
336 comphelper::SequenceAsHashMap aGrabBag;
338 if (nullptr != m_rDMapper_Impl.getTableManager().getCurrentTableRealPosition())
340 TablePositionHandler *pTablePositions = m_rDMapper_Impl.getTableManager().getCurrentTableRealPosition();
342 uno::Sequence< beans::PropertyValue > aGrabBagTS( 10 );
344 aGrabBagTS[0].Name = "bottomFromText";
345 aGrabBagTS[0].Value = uno::makeAny(pTablePositions->getBottomFromText() );
347 aGrabBagTS[1].Name = "horzAnchor";
348 aGrabBagTS[1].Value = uno::makeAny( pTablePositions->getHorzAnchor() );
350 aGrabBagTS[2].Name = "leftFromText";
351 aGrabBagTS[2].Value = uno::makeAny( pTablePositions->getLeftFromText() );
353 aGrabBagTS[3].Name = "rightFromText";
354 aGrabBagTS[3].Value = uno::makeAny( pTablePositions->getRightFromText() );
356 aGrabBagTS[4].Name = "tblpX";
357 aGrabBagTS[4].Value = uno::makeAny( pTablePositions->getX() );
359 aGrabBagTS[5].Name = "tblpXSpec";
360 aGrabBagTS[5].Value = uno::makeAny( pTablePositions->getXSpec() );
362 aGrabBagTS[6].Name = "tblpY";
363 aGrabBagTS[6].Value = uno::makeAny( pTablePositions->getY() );
365 aGrabBagTS[7].Name = "tblpYSpec";
366 aGrabBagTS[7].Value = uno::makeAny( pTablePositions->getYSpec() );
368 aGrabBagTS[8].Name = "topFromText";
369 aGrabBagTS[8].Value = uno::makeAny( pTablePositions->getTopFromText() );
371 aGrabBagTS[9].Name = "vertAnchor";
372 aGrabBagTS[9].Value = uno::makeAny( pTablePositions->getVertAnchor() );
374 aGrabBag["TablePosition"] = uno::makeAny( aGrabBagTS );
377 boost::optional<PropertyMap::Property> aTableStyleVal = m_aTableProperties->getProperty(META_PROP_TABLE_STYLE_NAME);
378 if(aTableStyleVal)
380 // Apply table style properties recursively
381 OUString sTableStyleName;
382 aTableStyleVal->second >>= sTableStyleName;
383 StyleSheetTablePtr pStyleSheetTable = m_rDMapper_Impl.GetStyleSheetTable();
384 const StyleSheetEntryPtr pStyleSheet = pStyleSheetTable->FindStyleSheetByISTD( sTableStyleName );
385 pTableStyle = dynamic_cast<TableStyleSheetEntry*>( pStyleSheet.get( ) );
386 m_aTableProperties->Erase( aTableStyleVal->first );
388 aGrabBag["TableStyleName"] = uno::makeAny( sTableStyleName );
390 if( pStyleSheet )
392 // First get the style properties, then the table ones
393 PropertyMapPtr pTableProps( m_aTableProperties );
394 TablePropertyMapPtr pEmptyProps( new TablePropertyMap );
396 m_aTableProperties = pEmptyProps;
398 PropertyMapPtr pMergedProperties = lcl_SearchParentStyleSheetAndMergeProperties(pStyleSheet, pStyleSheetTable);
400 table::BorderLine2 aBorderLine;
401 TableInfo rStyleInfo;
402 if (lcl_extractTableBorderProperty(pMergedProperties, PROP_TOP_BORDER, rStyleInfo, aBorderLine))
404 aGrabBag["TableStyleTopBorder"] = uno::makeAny( aBorderLine );
406 if (lcl_extractTableBorderProperty(pMergedProperties, PROP_BOTTOM_BORDER, rStyleInfo, aBorderLine))
408 aGrabBag["TableStyleBottomBorder"] = uno::makeAny( aBorderLine );
410 if (lcl_extractTableBorderProperty(pMergedProperties, PROP_LEFT_BORDER, rStyleInfo, aBorderLine))
412 aGrabBag["TableStyleLeftBorder"] = uno::makeAny( aBorderLine );
414 if (lcl_extractTableBorderProperty(pMergedProperties, PROP_RIGHT_BORDER, rStyleInfo, aBorderLine))
416 aGrabBag["TableStyleRightBorder"] = uno::makeAny( aBorderLine );
419 #ifdef DEBUG_WRITERFILTER
420 TagLogger::getInstance().startElement("mergedProps");
421 if (pMergedProperties)
422 pMergedProperties->dumpXml();
423 TagLogger::getInstance().endElement();
424 #endif
426 m_aTableProperties->InsertProps(pMergedProperties);
427 m_aTableProperties->InsertProps(pTableProps);
429 #ifdef DEBUG_WRITERFILTER
430 TagLogger::getInstance().startElement("TableProperties");
431 m_aTableProperties->dumpXml();
432 TagLogger::getInstance().endElement();
433 #endif
437 // This is the one preserving just all the table look attributes.
438 boost::optional<PropertyMap::Property> oTableLook = m_aTableProperties->getProperty(META_PROP_TABLE_LOOK);
439 if (oTableLook)
441 aGrabBag["TableStyleLook"] = oTableLook->second;
442 m_aTableProperties->Erase(oTableLook->first);
445 // This is just the "val" attribute's numeric value.
446 const boost::optional<PropertyMap::Property> aTblLook = m_aTableProperties->getProperty(PROP_TBL_LOOK);
447 if(aTblLook)
449 aTblLook->second >>= rInfo.nTblLook;
450 m_aTableProperties->Erase( aTblLook->first );
453 // Set the table default attributes for the cells
454 rInfo.pTableDefaults->InsertProps(m_aTableProperties);
456 #ifdef DEBUG_WRITERFILTER
457 TagLogger::getInstance().startElement("TableDefaults");
458 rInfo.pTableDefaults->dumpXml();
459 TagLogger::getInstance().endElement();
460 #endif
462 if (!aGrabBag.empty())
464 m_aTableProperties->Insert( PROP_TABLE_INTEROP_GRAB_BAG, uno::makeAny( aGrabBag.getAsConstPropertyValueList() ) );
467 m_aTableProperties->getValue( TablePropertyMap::GAP_HALF, nGapHalf );
468 m_aTableProperties->getValue( TablePropertyMap::LEFT_MARGIN, nLeftMargin );
470 m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_LEFT,
471 rInfo.nLeftBorderDistance );
472 m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_RIGHT,
473 rInfo.nRightBorderDistance );
474 m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_TOP,
475 rInfo.nTopBorderDistance );
476 m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_BOTTOM,
477 rInfo.nBottomBorderDistance );
479 table::TableBorderDistances aDistances;
480 aDistances.IsTopDistanceValid =
481 aDistances.IsBottomDistanceValid =
482 aDistances.IsLeftDistanceValid =
483 aDistances.IsRightDistanceValid = sal_True;
484 aDistances.TopDistance = static_cast<sal_Int16>( rInfo.nTopBorderDistance );
485 aDistances.BottomDistance = static_cast<sal_Int16>( rInfo.nBottomBorderDistance );
486 aDistances.LeftDistance = static_cast<sal_Int16>( rInfo.nLeftBorderDistance );
487 aDistances.RightDistance = static_cast<sal_Int16>( rInfo.nRightBorderDistance );
489 m_aTableProperties->Insert( PROP_TABLE_BORDER_DISTANCES, uno::makeAny( aDistances ) );
491 if (!rFrameProperties.empty())
492 lcl_DecrementHoriOrientPosition(rFrameProperties, rInfo.nLeftBorderDistance);
494 // Set table above/bottom spacing to 0.
495 m_aTableProperties->Insert( PROP_TOP_MARGIN, uno::makeAny( sal_Int32( 0 ) ) );
496 m_aTableProperties->Insert( PROP_BOTTOM_MARGIN, uno::makeAny( sal_Int32( 0 ) ) );
498 //table border settings
499 table::TableBorder aTableBorder;
500 table::BorderLine2 aBorderLine, aLeftBorder;
502 if (lcl_extractTableBorderProperty(m_aTableProperties, PROP_TOP_BORDER, rInfo, aBorderLine))
504 aTableBorder.TopLine = aBorderLine;
505 aTableBorder.IsTopLineValid = sal_True;
507 if (lcl_extractTableBorderProperty(m_aTableProperties, PROP_BOTTOM_BORDER, rInfo, aBorderLine))
509 aTableBorder.BottomLine = aBorderLine;
510 aTableBorder.IsBottomLineValid = sal_True;
512 if (lcl_extractTableBorderProperty(m_aTableProperties, PROP_LEFT_BORDER, rInfo, aLeftBorder))
514 aTableBorder.LeftLine = aLeftBorder;
515 aTableBorder.IsLeftLineValid = sal_True;
516 // Only top level table position depends on border width
517 if (rInfo.nNestLevel == 1)
519 if (rFrameProperties.empty())
520 rInfo.nLeftBorderDistance += aLeftBorder.LineWidth * 0.5;
521 else
522 lcl_DecrementHoriOrientPosition(rFrameProperties, aLeftBorder.LineWidth * 0.5);
525 if (lcl_extractTableBorderProperty(m_aTableProperties, PROP_RIGHT_BORDER, rInfo, aBorderLine))
527 aTableBorder.RightLine = aBorderLine;
528 aTableBorder.IsRightLineValid = sal_True;
530 if (lcl_extractTableBorderProperty(m_aTableProperties, META_PROP_HORIZONTAL_BORDER, rInfo, aBorderLine))
532 aTableBorder.HorizontalLine = aBorderLine;
533 aTableBorder.IsHorizontalLineValid = sal_True;
535 if (lcl_extractTableBorderProperty(m_aTableProperties, META_PROP_VERTICAL_BORDER, rInfo, aBorderLine))
537 aTableBorder.VerticalLine = aBorderLine;
538 aTableBorder.IsVerticalLineValid = sal_True;
541 aTableBorder.Distance = 0;
542 aTableBorder.IsDistanceValid = sal_False;
544 m_aTableProperties->Insert( PROP_TABLE_BORDER, uno::makeAny( aTableBorder ) );
546 #ifdef DEBUG_WRITERFILTER
547 lcl_debug_TableBorder(aTableBorder);
548 #endif
550 // Table position in Office is computed in 2 different ways :
551 // - top level tables: the goal is to have in-cell text starting at table indent pos (tblInd),
552 // so table's position depends on table's cells margin
553 // - nested tables: the goal is to have left-most border starting at table_indent pos
554 if (rInfo.nNestLevel > 1)
556 m_aTableProperties->Insert( PROP_LEFT_MARGIN, uno::makeAny( nLeftMargin - nGapHalf ));
558 else
560 m_aTableProperties->Insert( PROP_LEFT_MARGIN, uno::makeAny( nLeftMargin - nGapHalf - rInfo.nLeftBorderDistance ));
563 m_aTableProperties->getValue( TablePropertyMap::TABLE_WIDTH, nTableWidth );
564 m_aTableProperties->getValue( TablePropertyMap::TABLE_WIDTH_TYPE, nTableWidthType );
565 if( nTableWidthType == text::SizeType::FIX )
567 if( nTableWidth > 0 )
568 m_aTableProperties->Insert( PROP_WIDTH, uno::makeAny( nTableWidth ));
570 else
572 m_aTableProperties->Insert( PROP_RELATIVE_WIDTH, uno::makeAny( sal_Int16( nTableWidth ) ) );
573 m_aTableProperties->Insert( PROP_IS_WIDTH_RELATIVE, uno::makeAny( true ) );
576 sal_Int32 nHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH;
577 // Fetch Horizontal Orientation in rFrameProperties if not set in m_aTableProperties
578 if ( !m_aTableProperties->getValue( TablePropertyMap::HORI_ORIENT, nHoriOrient ) )
579 lcl_extractHoriOrient( rFrameProperties, nHoriOrient );
580 m_aTableProperties->Insert( PROP_HORI_ORIENT, uno::makeAny( sal_Int16(nHoriOrient) ) );
581 //fill default value - if not available
582 m_aTableProperties->Insert( PROP_HEADER_ROW_COUNT, uno::makeAny( (sal_Int32)0), false);
584 rInfo.aTableProperties = m_aTableProperties->GetPropertyValues();
586 #ifdef DEBUG_WRITERFILTER
587 TagLogger::getInstance().startElement("debug.tableprops");
588 m_aTableProperties->dumpXml();
589 TagLogger::getInstance().endElement();
590 #endif
594 return pTableStyle;
597 #define CNF_FIRST_ROW 0x800
598 #define CNF_LAST_ROW 0x400
599 #define CNF_FIRST_COLUMN 0x200
600 #define CNF_LAST_COLUMN 0x100
601 #define CNF_ODD_VBAND 0x080
602 #define CNF_EVEN_VBAND 0x040
603 #define CNF_ODD_HBAND 0x020
604 #define CNF_EVEN_HBAND 0x010
605 #define CNF_FIRST_ROW_LAST_COLUMN 0x008
606 #define CNF_FIRST_ROW_FIRST_COLUMN 0x004
607 #define CNF_LAST_ROW_LAST_COLUMN 0x002
608 #define CNF_LAST_ROW_FIRST_COLUMN 0x001
610 CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(TableInfo & rInfo, std::vector<HorizontallyMergedCell>& rMerges)
612 #ifdef DEBUG_WRITERFILTER
613 TagLogger::getInstance().startElement("getCellProperties");
614 #endif
616 CellPropertyValuesSeq_t aCellProperties( m_aCellProperties.size() );
618 if ( !m_aCellProperties.size() )
620 #ifdef DEBUG_WRITERFILTER
621 TagLogger::getInstance().endElement();
622 #endif
623 return aCellProperties;
625 // std::vector< std::vector<PropertyMapPtr> > m_aCellProperties
626 PropertyMapVector2::const_iterator aRowOfCellsIterator = m_aCellProperties.begin();
627 PropertyMapVector2::const_iterator aRowOfCellsIteratorEnd = m_aCellProperties.end();
628 PropertyMapVector2::const_iterator aLastRowIterator = m_aCellProperties.end() - 1;
629 sal_Int32 nRow = 0;
631 //it's a uno::Sequence< beans::PropertyValues >*
632 RowPropertyValuesSeq_t* pCellProperties = aCellProperties.getArray();
633 PropertyMapVector1::const_iterator aRowIter = m_aRowProperties.begin();
634 while( aRowOfCellsIterator != aRowOfCellsIteratorEnd )
636 //aRowOfCellsIterator points to a vector of PropertyMapPtr
637 PropertyMapVector1::const_iterator aCellIterator = aRowOfCellsIterator->begin();
638 PropertyMapVector1::const_iterator aCellIteratorEnd = aRowOfCellsIterator->end();
640 sal_Int32 nRowStyleMask = 0;
642 if (aRowOfCellsIterator==m_aCellProperties.begin())
644 if(rInfo.nTblLook&0x20)
645 nRowStyleMask |= CNF_FIRST_ROW; // first row style used
647 else if (aRowOfCellsIterator==aLastRowIterator)
649 if(rInfo.nTblLook&0x40)
650 nRowStyleMask |= CNF_LAST_ROW; // last row style used
652 else if (*aRowIter && (*aRowIter)->isSet(PROP_TBL_HEADER))
653 nRowStyleMask |= CNF_FIRST_ROW; // table header implies first row
654 if(!nRowStyleMask) // if no row style used yet
656 // banding used only if not first and or last row style used
657 if(!(rInfo.nTblLook&0x200))
658 { // hbanding used
659 int n = nRow + 1;
660 if(rInfo.nTblLook&0x20)
661 n++;
662 if(n & 1)
663 nRowStyleMask = CNF_ODD_HBAND;
664 else
665 nRowStyleMask = CNF_EVEN_HBAND;
669 sal_Int32 nCell = 0;
670 pCellProperties[nRow].realloc( aRowOfCellsIterator->size() );
671 beans::PropertyValues* pSingleCellProperties = pCellProperties[nRow].getArray();
672 while( aCellIterator != aCellIteratorEnd )
674 PropertyMapPtr pAllCellProps( new PropertyMap );
676 PropertyMapVector1::const_iterator aLastCellIterator = aRowOfCellsIterator->end() - 1;
677 bool bIsEndCol = aCellIterator == aLastCellIterator;
678 bool bIsEndRow = aRowOfCellsIterator == aLastRowIterator;
680 //aCellIterator points to a PropertyMapPtr;
681 if( *aCellIterator )
683 pAllCellProps->InsertProps(rInfo.pTableDefaults);
685 sal_Int32 nCellStyleMask = 0;
686 if (aCellIterator==aRowOfCellsIterator->begin())
688 if(rInfo.nTblLook&0x80)
689 nCellStyleMask = CNF_FIRST_COLUMN; // first col style used
691 else if (bIsEndCol)
693 if(rInfo.nTblLook&0x100)
694 nCellStyleMask = CNF_LAST_COLUMN; // last col style used
696 if(!nCellStyleMask) // if no cell style is used yet
698 if(!(rInfo.nTblLook&0x400))
699 { // vbanding used
700 int n = nCell + 1;
701 if(rInfo.nTblLook&0x80)
702 n++;
703 if(n & 1)
704 nCellStyleMask = CNF_ODD_VBAND;
705 else
706 nCellStyleMask = CNF_EVEN_VBAND;
709 sal_Int32 nCnfStyleMask = nCellStyleMask + nRowStyleMask;
710 if(nCnfStyleMask == CNF_FIRST_COLUMN + CNF_FIRST_ROW)
711 nCnfStyleMask |= CNF_FIRST_ROW_FIRST_COLUMN;
712 else if(nCnfStyleMask == CNF_FIRST_COLUMN + CNF_LAST_ROW)
713 nCnfStyleMask |= CNF_LAST_ROW_FIRST_COLUMN;
714 else if(nCnfStyleMask == CNF_LAST_COLUMN + CNF_FIRST_ROW)
715 nCnfStyleMask |= CNF_FIRST_ROW_LAST_COLUMN;
716 else if(nCnfStyleMask == CNF_LAST_COLUMN + CNF_LAST_ROW)
717 nCnfStyleMask |= CNF_LAST_ROW_LAST_COLUMN;
719 if ( rInfo.pTableStyle )
721 PropertyMapPtr pStyleProps = rInfo.pTableStyle->GetProperties( nCnfStyleMask );
723 // Check if we need to clean up some empty border definitions to match what Word does.
724 static const PropertyIds pBorders[] =
726 PROP_TOP_BORDER, PROP_LEFT_BORDER, PROP_BOTTOM_BORDER, PROP_RIGHT_BORDER
728 for (size_t i = 0; i < SAL_N_ELEMENTS(pBorders); ++i)
730 boost::optional<PropertyMap::Property> oStyleCellBorder = pStyleProps->getProperty(pBorders[i]);
731 boost::optional<PropertyMap::Property> oDirectCellBorder = (*aCellIterator)->getProperty(pBorders[i]);
732 if (oStyleCellBorder && oDirectCellBorder)
734 // We have a cell border from the table style and as direct formatting as well.
735 table::BorderLine2 aStyleCellBorder = oStyleCellBorder->second.get<table::BorderLine2>();
736 table::BorderLine2 aDirectCellBorder = oDirectCellBorder->second.get<table::BorderLine2>();
737 if (aStyleCellBorder.LineStyle != table::BorderLineStyle::NONE && aDirectCellBorder.LineStyle == table::BorderLineStyle::NONE)
739 // The style one would be visible, but then cleared away as direct formatting.
740 // Delete both, so that table formatting can become visible.
741 pStyleProps->Erase(pBorders[i]);
742 (*aCellIterator)->Erase(pBorders[i]);
744 else
746 boost::optional<PropertyMap::Property> oTableBorder = rInfo.pTableBorders->getProperty(pBorders[i]);
747 if (oTableBorder)
749 table::BorderLine2 aTableBorder = oTableBorder->second.get<table::BorderLine2>();
750 // Both style and direct formatting says that the cell has no border.
751 bool bNoCellBorder = aStyleCellBorder.LineStyle == table::BorderLineStyle::NONE && aDirectCellBorder.LineStyle == table::BorderLineStyle::NONE;
752 if (aTableBorder.LineStyle != table::BorderLineStyle::NONE && bNoCellBorder)
754 // But at a table-level, there is a border, then again delete both cell properties.
755 pStyleProps->Erase(pBorders[i]);
756 (*aCellIterator)->Erase(pBorders[i]);
763 pAllCellProps->InsertProps( pStyleProps );
766 // Remove properties from style/row that aren't allowed in cells
767 pAllCellProps->Erase( PROP_HEADER_ROW_COUNT );
768 pAllCellProps->Erase( PROP_TBL_HEADER );
770 // Then add the cell properties
771 pAllCellProps->InsertProps(*aCellIterator);
772 std::swap(*(*aCellIterator), *pAllCellProps );
774 #ifdef DEBUG_WRITERFILTER
775 TagLogger::getInstance().startElement("cell");
776 TagLogger::getInstance().attribute("cell", nCell);
777 TagLogger::getInstance().attribute("row", nRow);
778 #endif
780 lcl_computeCellBorders( rInfo.pTableBorders, *aCellIterator, nCell, nRow, bIsEndCol, bIsEndRow );
782 //now set the default left+right border distance TODO: there's an sprm containing the default distance!
783 aCellIterator->get()->Insert( PROP_LEFT_BORDER_DISTANCE,
784 uno::makeAny(rInfo.nLeftBorderDistance ), false);
785 aCellIterator->get()->Insert( PROP_RIGHT_BORDER_DISTANCE,
786 uno::makeAny((sal_Int32) rInfo.nRightBorderDistance ), false);
787 aCellIterator->get()->Insert( PROP_TOP_BORDER_DISTANCE,
788 uno::makeAny((sal_Int32) rInfo.nTopBorderDistance ), false);
789 aCellIterator->get()->Insert( PROP_BOTTOM_BORDER_DISTANCE,
790 uno::makeAny((sal_Int32) rInfo.nBottomBorderDistance ), false);
792 // Horizontal merge is not an UNO property, extract that info here to rMerges, and then remove it from the map.
793 const boost::optional<PropertyMap::Property> aHorizontalMergeVal = (*aCellIterator)->getProperty(PROP_HORIZONTAL_MERGE);
794 if (aHorizontalMergeVal)
796 if (aHorizontalMergeVal->second.get<sal_Bool>())
798 // first cell in a merge
799 HorizontallyMergedCell aMerge(nRow, nCell);
800 rMerges.push_back(aMerge);
802 else if (!rMerges.empty())
804 // resuming an earlier merge
805 HorizontallyMergedCell& rMerge = rMerges.back();
806 rMerge.m_nLastRow = nRow;
807 rMerge.m_nLastCol = nCell;
809 (*aCellIterator)->Erase(PROP_HORIZONTAL_MERGE);
812 // Cell direction is not an UNO Property, either.
813 const boost::optional<PropertyMap::Property> aCellDirectionVal = (*aCellIterator)->getProperty(PROP_CELL_DIRECTION);
814 if (aCellDirectionVal)
816 if (aCellDirectionVal->second.get<sal_Int32>() == static_cast<sal_Int32>(NS_ooxml::LN_Value_ST_TextDirection_btLr))
818 // btLr, so map ParagraphAdjust_CENTER to VertOrientation::CENTER.
819 uno::Reference<beans::XPropertySet> xPropertySet((*m_pTableSeq)[nRow][nCell][0], uno::UNO_QUERY);
820 if (xPropertySet->getPropertyValue("ParaAdjust").get<sal_Int16>() == style::ParagraphAdjust_CENTER)
821 (*aCellIterator)->Insert(PROP_VERT_ORIENT, uno::makeAny(text::VertOrientation::CENTER));
823 (*aCellIterator)->Erase(PROP_CELL_DIRECTION);
826 pSingleCellProperties[nCell] = (*aCellIterator)->GetPropertyValues();
827 #ifdef DEBUG_WRITERFILTER
828 TagLogger::getInstance().endElement();
829 #endif
831 ++nCell;
832 ++aCellIterator;
834 #ifdef DEBUG_WRITERFILTER
835 //-->debug cell properties
837 OUString sNames;
838 const uno::Sequence< beans::PropertyValues > aDebugCurrentRow = aCellProperties[nRow];
839 sal_Int32 nDebugCells = aDebugCurrentRow.getLength();
840 (void) nDebugCells;
841 for( sal_Int32 nDebugCell = 0; nDebugCell < nDebugCells; ++nDebugCell)
843 const uno::Sequence< beans::PropertyValue >& aDebugCellProperties = aDebugCurrentRow[nDebugCell];
844 sal_Int32 nDebugCellProperties = aDebugCellProperties.getLength();
845 for( sal_Int32 nDebugProperty = 0; nDebugProperty < nDebugCellProperties; ++nDebugProperty)
847 const OUString sName = aDebugCellProperties[nDebugProperty].Name;
848 sNames += sName;
849 sNames += OUString('-');
851 sNames += OUString('\n');
853 (void)sNames;
855 //--<
856 #endif
857 ++nRow;
858 ++aRowOfCellsIterator;
859 ++aRowIter;
862 #ifdef DEBUG_WRITERFILTER
863 TagLogger::getInstance().endElement();
864 #endif
866 return aCellProperties;
869 /// Do all cells in this row have a CellHideMark property?
870 bool lcl_hideMarks(PropertyMapVector1& rCellProperties)
872 for (size_t nCell = 0; nCell < rCellProperties.size(); ++nCell)
873 if (!rCellProperties[nCell]->isSet(PROP_CELL_HIDE_MARK))
874 return false;
875 return true;
878 /// Are all cells in this row empty?
879 bool lcl_emptyRow(TableSequence_t& rTableSeq, sal_Int32 nRow)
881 if (nRow >= rTableSeq.getLength())
883 SAL_WARN("writerfilter", "m_aCellProperties not in sync with m_pTableSeq?");
884 return false;
887 RowSequence_t rRowSeq = rTableSeq[nRow];
888 if (rRowSeq.getLength() == 0)
890 SAL_WARN("writerfilter", "m_aCellProperties not in sync with m_pTableSeq?");
891 return false;
894 uno::Reference<text::XTextRangeCompare> xTextRangeCompare(rRowSeq[0][0]->getText(), uno::UNO_QUERY);
897 for (sal_Int32 nCell = 0; nCell < rRowSeq.getLength(); ++nCell)
898 // See SwXText::Impl::ConvertCell(), we need to compare the start of
899 // the start and the end of the end. However for our text ranges, only
900 // the starts are set, so compareRegionStarts() does what we need.
901 if (xTextRangeCompare->compareRegionStarts(rRowSeq[nCell][0], rRowSeq[nCell][1]) != 0)
902 return false;
904 catch (const lang::IllegalArgumentException& e)
906 SAL_WARN("writerfilter", "compareRegionStarts() failed: " << e.Message);
907 return false;
909 return true;
912 RowPropertyValuesSeq_t DomainMapperTableHandler::endTableGetRowProperties()
914 #ifdef DEBUG_WRITERFILTER
915 TagLogger::getInstance().startElement("getRowProperties");
916 #endif
918 static const int MINLAY = 23; // sw/inc/swtypes.hxx, minimal possible size of frames.
919 RowPropertyValuesSeq_t aRowProperties( m_aRowProperties.size() );
920 PropertyMapVector1::const_iterator aRowIter = m_aRowProperties.begin();
921 PropertyMapVector1::const_iterator aRowIterEnd = m_aRowProperties.end();
922 sal_Int32 nRow = 0;
923 while( aRowIter != aRowIterEnd )
925 #ifdef DEBUG_WRITERFILTER
926 TagLogger::getInstance().startElement("rowProps.row");
927 #endif
928 if( aRowIter->get() )
930 //set default to 'break across pages"
931 (*aRowIter)->Insert( PROP_IS_SPLIT_ALLOWED, uno::makeAny(sal_True ), false );
932 // tblHeader is only our property, remove before the property map hits UNO
933 (*aRowIter)->Erase(PROP_TBL_HEADER);
935 if (lcl_hideMarks(m_aCellProperties[nRow]) && lcl_emptyRow(*m_pTableSeq, nRow))
937 // We have CellHideMark on all cells, and also all cells are empty:
938 // Set the row height to minimal as Word does.
939 (*aRowIter)->Insert(PROP_SIZE_TYPE, uno::makeAny(text::SizeType::FIX));
940 (*aRowIter)->Insert(PROP_HEIGHT, uno::makeAny(static_cast<sal_Int32>(ConversionHelper::convertTwipToMM100(MINLAY))));
943 aRowProperties[nRow] = (*aRowIter)->GetPropertyValues();
944 #ifdef DEBUG_WRITERFILTER
945 (*aRowIter)->dumpXml();
946 lcl_DumpPropertyValues(aRowProperties[nRow]);
947 #endif
949 ++nRow;
950 ++aRowIter;
951 #ifdef DEBUG_WRITERFILTER
952 TagLogger::getInstance().endElement();
953 #endif
956 #ifdef DEBUG_WRITERFILTER
957 TagLogger::getInstance().endElement();
958 #endif
960 return aRowProperties;
963 // Apply paragraph property to each paragraph within a cell.
964 static void lcl_ApplyCellParaProps(uno::Reference<table::XCell> const& xCell,
965 const uno::Any& rBottomMargin)
967 uno::Reference<container::XEnumerationAccess> xEnumerationAccess(xCell, uno::UNO_QUERY);
968 uno::Reference<container::XEnumeration> xEnumeration = xEnumerationAccess->createEnumeration();
969 while (xEnumeration->hasMoreElements())
971 uno::Reference<beans::XPropertySet> xParagraph(xEnumeration->nextElement(), uno::UNO_QUERY);
972 uno::Reference<beans::XPropertyState> xPropertyState(xParagraph, uno::UNO_QUERY);
973 // Don't apply in case direct formatting is already present.
974 // TODO: probably paragraph style has priority over table style here.
975 if (xPropertyState.is() && xPropertyState->getPropertyState("ParaBottomMargin") == beans::PropertyState_DEFAULT_VALUE)
976 xParagraph->setPropertyValue("ParaBottomMargin", rBottomMargin);
980 void DomainMapperTableHandler::endTable(unsigned int nestedTableLevel)
982 #ifdef DEBUG_WRITERFILTER
983 TagLogger::getInstance().startElement("tablehandler.endTable");
984 #endif
986 // If we want to make this table a floating one.
987 std::vector<beans::PropertyValue> aFrameProperties = comphelper::sequenceToContainer<std::vector<beans::PropertyValue> >
988 (m_rDMapper_Impl.getTableManager().getCurrentTablePosition());
989 TableInfo aTableInfo;
990 aTableInfo.nNestLevel = nestedTableLevel;
991 aTableInfo.pTableStyle = endTableGetTableStyle(aTableInfo, aFrameProperties);
992 // expands to uno::Sequence< Sequence< beans::PropertyValues > >
994 std::vector<HorizontallyMergedCell> aMerges;
995 CellPropertyValuesSeq_t aCellProperties = endTableGetCellProperties(aTableInfo, aMerges);
997 RowPropertyValuesSeq_t aRowProperties = endTableGetRowProperties();
999 #ifdef DEBUG_WRITERFILTER
1000 lcl_DumpPropertyValueSeq(aRowProperties);
1001 #endif
1003 if (m_pTableSeq->getLength() > 0)
1005 uno::Reference<text::XTextRange> xStart;
1006 uno::Reference<text::XTextRange> xEnd;
1008 bool bFloating = !aFrameProperties.empty();
1009 // Additional checks: if we can do this.
1010 if (bFloating && (*m_pTableSeq)[0].getLength() > 0 && (*m_pTableSeq)[0][0].getLength() > 0)
1012 xStart = (*m_pTableSeq)[0][0][0];
1013 uno::Sequence< uno::Sequence< uno::Reference<text::XTextRange> > >& rLastRow = (*m_pTableSeq)[m_pTableSeq->getLength() - 1];
1014 uno::Sequence< uno::Reference<text::XTextRange> >& rLastCell = rLastRow[rLastRow.getLength() - 1];
1015 xEnd = rLastCell[1];
1017 uno::Reference<text::XTextTable> xTable;
1020 if (m_xText.is())
1022 xTable = m_xText->convertToTable(*m_pTableSeq,
1023 aCellProperties,
1024 aRowProperties,
1025 aTableInfo.aTableProperties);
1027 if (xTable.is())
1029 m_xTableRange = xTable->getAnchor( );
1031 if (!aMerges.empty())
1033 // Perform horizontal merges in reverse order, so the fact that merging changes the position of cells won't cause a problem for us.
1034 for (std::vector<HorizontallyMergedCell>::reverse_iterator it = aMerges.rbegin(); it != aMerges.rend(); ++it)
1036 uno::Reference<table::XCellRange> xCellRange(xTable, uno::UNO_QUERY_THROW);
1037 uno::Reference<beans::XPropertySet> xCell(xCellRange->getCellByPosition(it->m_nFirstCol, it->m_nFirstRow), uno::UNO_QUERY_THROW);
1038 OUString aFirst = xCell->getPropertyValue("CellName").get<OUString>();
1039 xCell.set(xCellRange->getCellByPosition(it->m_nLastCol, it->m_nLastRow), uno::UNO_QUERY_THROW);
1040 OUString aLast = xCell->getPropertyValue("CellName").get<OUString>();
1042 uno::Reference<text::XTextTableCursor> xCursor = xTable->createCursorByCellName(aFirst);
1043 xCursor->gotoCellByName(aLast, true);
1044 xCursor->mergeRange();
1049 // OOXML table style may container paragraph properties, apply these now.
1050 for (int i = 0; i < aTableInfo.aTableProperties.getLength(); ++i)
1052 if (aTableInfo.aTableProperties[i].Name == "ParaBottomMargin")
1054 uno::Reference<table::XCellRange> xCellRange(xTable, uno::UNO_QUERY);
1055 uno::Any aBottomMargin = aTableInfo.aTableProperties[i].Value;
1056 sal_Int32 nRows = aCellProperties.getLength();
1057 for (sal_Int32 nRow = 0; nRow < nRows; ++nRow)
1059 const uno::Sequence< beans::PropertyValues > aCurrentRow = aCellProperties[nRow];
1060 sal_Int32 nCells = aCurrentRow.getLength();
1061 for (sal_Int32 nCell = 0; nCell < nCells; ++nCell)
1062 lcl_ApplyCellParaProps(xCellRange->getCellByPosition(nCell, nRow), aBottomMargin);
1064 break;
1069 catch ( const lang::IllegalArgumentException &e )
1071 SAL_INFO("writerfilter.dmapper",
1072 "Conversion to table error: " << e.Message);
1073 #ifdef DEBUG_WRITERFILTER
1074 TagLogger::getInstance().chars(std::string("failed to import table!"));
1075 #endif
1077 catch ( const uno::Exception &e )
1079 SAL_INFO("writerfilter.dmapper",
1080 "Exception during table creation: " << e.Message);
1083 // If we have a table with a start and an end position, we should make it a floating one.
1084 // Unless the table had a foot or endnote, as Writer doesn't support those in TextFrames.
1085 if (xTable.is() && xStart.is() && xEnd.is() && !m_bHadFootOrEndnote)
1087 uno::Reference<beans::XPropertySet> xTableProperties(xTable, uno::UNO_QUERY);
1088 bool bIsRelative = false;
1089 xTableProperties->getPropertyValue("IsWidthRelative") >>= bIsRelative;
1090 if (!bIsRelative)
1092 beans::PropertyValue aValue;
1093 aValue.Name = "Width";
1094 aValue.Value = xTableProperties->getPropertyValue("Width");
1095 aFrameProperties.push_back(aValue);
1097 else
1099 beans::PropertyValue aValue;
1100 aValue.Name = "FrameWidthPercent";
1101 aValue.Value = xTableProperties->getPropertyValue("RelativeWidth");
1102 aFrameProperties.push_back(aValue);
1104 // Applying the relative width to the frame, needs to have the table width to be 100% of the frame width
1105 xTableProperties->setPropertyValue("RelativeWidth", uno::makeAny(sal_Int16(100)));
1108 // A non-zero left margin would move the table out of the frame, move the frame itself instead.
1109 xTableProperties->setPropertyValue("LeftMargin", uno::makeAny(sal_Int32(0)));
1111 // In case the document ends with a table, we're called after
1112 // SectionPropertyMap::CloseSectionGroup(), so we'll have no idea
1113 // about the text area width, nor can fix this by delaying the text
1114 // frame conversion: just do it here.
1115 // Also, when the anchor is within a table, then do it here as well,
1116 // as xStart/xEnd would not point to the start/end at conversion
1117 // time anyway.
1118 // Next exception: it's pointless to delay the conversion if the
1119 // table is not in the body text.
1120 sal_Int32 nTableWidth = 0;
1121 m_aTableProperties->getValue(TablePropertyMap::TABLE_WIDTH, nTableWidth);
1122 if (m_rDMapper_Impl.GetSectionContext() && nestedTableLevel <= 1 && !m_rDMapper_Impl.IsInHeaderFooter())
1123 m_rDMapper_Impl.m_aPendingFloatingTables.push_back(FloatingTableInfo(xStart, xEnd, comphelper::containerToSequence(aFrameProperties), nTableWidth));
1124 else
1126 // m_xText points to the body text, get to current xText from m_rDMapper_Impl, in case e.g. we would be in a header.
1127 uno::Reference<text::XTextAppendAndConvert> xTextAppendAndConvert(m_rDMapper_Impl.GetTopTextAppend(), uno::UNO_QUERY);
1128 if (xTextAppendAndConvert.is())
1129 xTextAppendAndConvert->convertToTextFrame(xStart, xEnd, comphelper::containerToSequence(aFrameProperties));
1134 m_aTableProperties.reset();
1135 m_aCellProperties.clear();
1136 m_aRowProperties.clear();
1137 m_bHadFootOrEndnote = false;
1139 #ifdef DEBUG_WRITERFILTER
1140 TagLogger::getInstance().endElement();
1141 TagLogger::getInstance().endElement();
1142 #endif
1145 void DomainMapperTableHandler::startRow(unsigned int nCells,
1146 TablePropertyMapPtr pProps)
1148 m_aRowProperties.push_back( pProps );
1149 m_aCellProperties.push_back( PropertyMapVector1() );
1151 #ifdef DEBUG_WRITERFILTER
1152 TagLogger::getInstance().startElement("table.row");
1153 TagLogger::getInstance().attribute("cells", nCells);
1154 if (pProps != nullptr)
1155 pProps->dumpXml();
1156 #endif
1158 m_pRowSeq = RowSequencePointer_t(new RowSequence_t(nCells));
1159 m_nCellIndex = 0;
1162 void DomainMapperTableHandler::endRow()
1164 (*m_pTableSeq)[m_nRowIndex] = *m_pRowSeq;
1165 ++m_nRowIndex;
1166 m_nCellIndex = 0;
1167 #ifdef DEBUG_WRITERFILTER
1168 TagLogger::getInstance().endElement();
1169 #endif
1172 void DomainMapperTableHandler::startCell(const Handle_t & start,
1173 TablePropertyMapPtr pProps )
1175 sal_uInt32 nRow = m_aRowProperties.size();
1176 if ( pProps.get( ) )
1177 m_aCellProperties[nRow - 1].push_back( pProps );
1178 else
1180 // Adding an empty cell properties map to be able to get
1181 // the table defaults properties
1182 TablePropertyMapPtr pEmptyProps( new TablePropertyMap( ) );
1183 m_aCellProperties[nRow - 1].push_back( pEmptyProps );
1186 #ifdef DEBUG_WRITERFILTER
1187 TagLogger::getInstance().startElement("table.cell");
1188 TagLogger::getInstance().startElement("table.cell.start");
1189 TagLogger::getInstance().chars(XTextRangeToString(start));
1190 TagLogger::getInstance().endElement();
1191 if (pProps.get())
1192 pProps->printProperties();
1193 #endif
1195 //add a new 'row' of properties
1196 m_pCellSeq = CellSequencePointer_t(new CellSequence_t(2));
1197 if (!start.get())
1198 return;
1199 (*m_pCellSeq)[0] = start->getStart();
1202 void DomainMapperTableHandler::endCell(const Handle_t & end)
1204 #ifdef DEBUG_WRITERFILTER
1205 TagLogger::getInstance().startElement("table.cell.end");
1206 TagLogger::getInstance().chars(XTextRangeToString(end));
1207 TagLogger::getInstance().endElement();
1208 TagLogger::getInstance().endElement();
1209 #endif
1211 if (!end.get())
1212 return;
1213 (*m_pCellSeq)[1] = end->getEnd();
1214 (*m_pRowSeq)[m_nCellIndex] = *m_pCellSeq;
1215 ++m_nCellIndex;
1218 void DomainMapperTableHandler::setHadFootOrEndnote(bool bHadFootOrEndnote)
1220 m_bHadFootOrEndnote = bHadFootOrEndnote;
1225 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */