1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 #include <DomainMapperTableHandler.hxx>
25 #include <DomainMapper_Impl.hxx>
26 #include <StyleSheetTable.hxx>
27 #include <com/sun/star/table/TableBorderDistances.hpp>
28 #include <com/sun/star/table/TableBorder.hpp>
29 #include <com/sun/star/text/HoriOrientation.hpp>
30 #include <dmapperLoggers.hxx>
31 
32 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
33 #include <PropertyMapHelper.hxx>
34 #endif
35 
36 namespace writerfilter {
37 namespace dmapper {
38 
39 using namespace ::com::sun::star;
40 using namespace ::std;
41 
42 #define DEF_BORDER_DIST 190 // 0,19 cm
43 #define DEFAULT_CELL_MARGIN 108 // default cell margin, not documented
44 
45 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
handleToTag(Handle_t & rHandle)46 XMLTag::Pointer_t handleToTag(Handle_t & rHandle)
47 {
48 	XMLTag::Pointer_t pTag(new XMLTag("handle"));
49 
50 	pTag->chars(rHandle->getString());
51 
52 	return pTag;
53 }
54 
cellSequenceToTags(XMLTag::Pointer_t pTag,CellSequence_t & rCellSequence)55 void cellSequenceToTags(XMLTag::Pointer_t pTag, CellSequence_t & rCellSequence)
56 {
57 	sal_Int32 nCount = rCellSequence.getLength();
58 	pTag->addAttr("count", nCount);
59 
60 	for (sal_Int32 n = 0; n < nCount; n++)
61 	{
62 		Handle_t aHandle = rCellSequence[n];
63 		pTag->addTag(handleToTag(aHandle));
64 	}
65 }
66 
rowSequenceToTags(XMLTag::Pointer_t pTag,RowSequence_t & rRowSequence)67 void rowSequenceToTags(XMLTag::Pointer_t pTag, RowSequence_t & rRowSequence)
68 {
69 	sal_Int32 nCount = rRowSequence.getLength();
70 	pTag->addAttr("count", nCount);
71 
72     for (sal_Int32 n = 0; n < nCount; n++)
73     {
74         CellSequence_t & rCells = rRowSequence[n];
75         XMLTag::Pointer_t pCellTag(new XMLTag("cell"));
76         cellSequenceToTags(pCellTag, rCells);
77         pTag->addTag(pCellTag);
78     }
79 }
80 
tableSequenceToTag(TableSequence_t & rTableSequence)81 XMLTag::Pointer_t tableSequenceToTag(TableSequence_t & rTableSequence)
82 {
83     XMLTag::Pointer_t pTag(new XMLTag("table"));
84     sal_Int32 nCount = rTableSequence.getLength();
85     pTag->addAttr("count", nCount);
86 
87     for (sal_Int32 n = 0; n < nCount; n++)
88     {
89         RowSequence_t & rRowSequence = rTableSequence[n];
90         XMLTag::Pointer_t pRowTag(new XMLTag("row"));
91         rowSequenceToTags(pRowTag, rRowSequence);
92         pTag->addTag(pRowTag);
93     }
94 
95     return pTag;
96 }
97 
lcl_printProperties(PropertyMapPtr pProps)98 static void  lcl_printProperties( PropertyMapPtr pProps )
99 {
100     if( pProps.get() )
101     {
102         dmapper_logger->startElement("properties");
103 
104         PropertyMap::const_iterator aMapIter = pProps->begin();
105         PropertyMap::const_iterator aEndIter = pProps->end();
106         PropertyNameSupplier& rPropSupplier = PropertyNameSupplier::GetPropertyNameSupplier();
107         for( ; aMapIter != aEndIter; ++aMapIter )
108         {
109             rtl::OUString aOUStr = rPropSupplier.GetName( aMapIter->first.eId );
110             dmapper_logger->startElement("entry");
111             dmapper_logger->chars(aOUStr);
112             dmapper_logger->endElement("entry");
113 
114             table::BorderLine aLine;
115             sal_Int32 nColor;
116             if ( aMapIter->second >>= aLine )
117             {
118                 dmapper_logger->startElement("borderline");
119                 dmapper_logger->attribute("color", aLine.Color);
120                 dmapper_logger->attribute("inner", aLine.InnerLineWidth);
121                 dmapper_logger->attribute("outer", aLine.OuterLineWidth);
122                 dmapper_logger->endElement("borderline");
123             }
124             else if ( aMapIter->second >>= nColor )
125             {
126                 dmapper_logger->startElement("color");
127                 dmapper_logger->attribute("number", nColor);
128                 dmapper_logger->endElement("color");
129             }
130         }
131 
132         dmapper_logger->endElement("properties");
133     }
134 }
135 #endif
136 
DomainMapperTableHandler(TextReference_t xText,DomainMapper_Impl & rDMapper_Impl)137 DomainMapperTableHandler::DomainMapperTableHandler(TextReference_t xText, DomainMapper_Impl& rDMapper_Impl)
138     : m_xText(xText),
139         m_rDMapper_Impl( rDMapper_Impl ),
140         m_nCellIndex(0),
141         m_nRowIndex(0)
142 {
143 }
144 
~DomainMapperTableHandler()145 DomainMapperTableHandler::~DomainMapperTableHandler()
146 {
147 }
148 
startTable(unsigned int nRows,unsigned int,TablePropertyMapPtr pProps)149 void DomainMapperTableHandler::startTable(unsigned int nRows,
150                                           unsigned int /*nDepth*/,
151                                           TablePropertyMapPtr pProps)
152 {
153     m_aTableProperties = pProps;
154     m_pTableSeq = TableSequencePointer_t(new TableSequence_t(nRows));
155     m_nRowIndex = 0;
156 
157 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
158     dmapper_logger->startElement("tablehandler.table");
159     dmapper_logger->attribute("rows", nRows);
160 
161     if (pProps.get() != NULL)
162         dmapper_logger->addTag(pProps->toTag());
163 #endif
164 }
165 
166 /*-- 22.02.2008 10:18:37---------------------------------------------------
167 
168   -----------------------------------------------------------------------*/
lcl_SearchParentStyleSheetAndMergeProperties(const StyleSheetEntryPtr pStyleSheet,StyleSheetTablePtr pStyleSheetTable)169 PropertyMapPtr lcl_SearchParentStyleSheetAndMergeProperties(const StyleSheetEntryPtr pStyleSheet, StyleSheetTablePtr pStyleSheetTable)
170 {
171     PropertyMapPtr pRet;
172     if( pStyleSheet->sBaseStyleIdentifier.getLength())
173     {
174         const StyleSheetEntryPtr pParentStyleSheet = pStyleSheetTable->FindStyleSheetByISTD( pStyleSheet->sBaseStyleIdentifier );
175         pRet = lcl_SearchParentStyleSheetAndMergeProperties( pParentStyleSheet, pStyleSheetTable );
176     }
177     else
178     {
179         pRet.reset( new PropertyMap );
180     }
181 
182     pRet->insert(  pStyleSheet->pProperties, true );
183 
184     return pRet;
185 }
186 
lcl_mergeBorder(PropertyIds nId,PropertyMapPtr pOrig,PropertyMapPtr pDest)187 void lcl_mergeBorder( PropertyIds nId, PropertyMapPtr pOrig, PropertyMapPtr pDest )
188 {
189     PropertyDefinition aDef( nId, false );
190     PropertyMap::iterator pOrigIt = pOrig->find( aDef );
191 
192     if ( pOrigIt != pOrig->end( ) )
193     {
194         pDest->Insert( nId, false, pOrigIt->second, false );
195     }
196 }
197 
lcl_computeCellBorders(PropertyMapPtr pTableBorders,PropertyMapPtr pCellProps,sal_Int32 nCell,sal_Int32 nRow,bool bIsEndCol,bool bIsEndRow)198 void lcl_computeCellBorders( PropertyMapPtr pTableBorders, PropertyMapPtr pCellProps,
199         sal_Int32 nCell, sal_Int32 nRow, bool bIsEndCol, bool bIsEndRow )
200 {
201     PropertyDefinition aVertPDef( META_PROP_VERTICAL_BORDER, false );
202     PropertyDefinition aHorizPDef( META_PROP_HORIZONTAL_BORDER, false );
203 
204     PropertyMap::iterator aVerticalIter = pCellProps->find( aVertPDef );
205     PropertyMap::iterator aHorizontalIter = pCellProps->find( aHorizPDef );
206 
207     // Handle the vertical and horizontal borders
208     bool bHasVert = ( aVerticalIter != pCellProps->end(  ) );
209     uno::Any aVertProp;
210     if ( !bHasVert )
211     {
212         aVerticalIter = pTableBorders->find( aVertPDef );
213         bHasVert = ( aVerticalIter != pTableBorders->end( ) );
214         if ( bHasVert )
215             aVertProp = aVerticalIter->second;
216     }
217     else
218     {
219         aVertProp = aVerticalIter->second;
220         pCellProps->erase( aVerticalIter );
221     }
222 
223     bool bHasHoriz = ( aHorizontalIter != pCellProps->end(  ) );
224     uno::Any aHorizProp;
225     if ( !bHasHoriz )
226     {
227         aHorizontalIter = pTableBorders->find( aHorizPDef );
228         bHasHoriz = ( aHorizontalIter != pTableBorders->end( ) );
229         if ( bHasHoriz )
230             aHorizProp = aHorizontalIter->second;
231     }
232     else
233     {
234         aHorizProp = aHorizontalIter->second;
235         pCellProps->erase( aHorizontalIter );
236     }
237 
238     if ( nCell == 0 )
239     {
240         lcl_mergeBorder( PROP_LEFT_BORDER, pTableBorders, pCellProps );
241         if ( bHasVert )
242             pCellProps->Insert( PROP_RIGHT_BORDER, false, aVertProp, false );
243     }
244 
245     if ( bIsEndCol )
246     {
247         lcl_mergeBorder( PROP_RIGHT_BORDER, pTableBorders, pCellProps );
248         if ( bHasVert )
249             pCellProps->Insert( PROP_LEFT_BORDER, false, aVertProp, false );
250     }
251 
252     if ( nCell > 0 && !bIsEndCol )
253     {
254         if ( bHasVert )
255         {
256             pCellProps->Insert( PROP_RIGHT_BORDER, false, aVertProp, false );
257             pCellProps->Insert( PROP_LEFT_BORDER, false, aVertProp, false );
258         }
259     }
260 
261     if ( nRow == 0 )
262     {
263         lcl_mergeBorder( PROP_TOP_BORDER, pTableBorders, pCellProps );
264         if ( bHasHoriz )
265             pCellProps->Insert( PROP_BOTTOM_BORDER, false, aHorizProp, false );
266     }
267 
268     if ( bIsEndRow )
269     {
270         lcl_mergeBorder( PROP_BOTTOM_BORDER, pTableBorders, pCellProps );
271         if ( bHasHoriz )
272             pCellProps->Insert( PROP_TOP_BORDER, false, aHorizProp, false );
273     }
274 
275     if ( nRow > 0 && !bIsEndRow )
276     {
277         if ( bHasHoriz )
278         {
279             pCellProps->Insert( PROP_TOP_BORDER, false, aHorizProp, false );
280             pCellProps->Insert( PROP_BOTTOM_BORDER, false, aHorizProp, false );
281         }
282     }
283 }
284 
285 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
286 
lcl_debug_BorderLine(table::BorderLine & rLine)287 void lcl_debug_BorderLine(table::BorderLine & rLine)
288 {
289     dmapper_logger->startElement("BorderLine");
290     dmapper_logger->attribute("Color", rLine.Color);
291     dmapper_logger->attribute("InnerLineWidth", rLine.InnerLineWidth);
292     dmapper_logger->attribute("OuterLineWidth", rLine.OuterLineWidth);
293     dmapper_logger->attribute("LineDistance", rLine.LineDistance);
294     dmapper_logger->endElement("BorderLine");
295 }
296 
lcl_debug_TableBorder(table::TableBorder & rBorder)297 void lcl_debug_TableBorder(table::TableBorder & rBorder)
298 {
299     dmapper_logger->startElement("TableBorder");
300     lcl_debug_BorderLine(rBorder.TopLine);
301     dmapper_logger->attribute("IsTopLineValid", rBorder.IsTopLineValid);
302     lcl_debug_BorderLine(rBorder.BottomLine);
303     dmapper_logger->attribute("IsBottomLineValid", rBorder.IsBottomLineValid);
304     lcl_debug_BorderLine(rBorder.LeftLine);
305     dmapper_logger->attribute("IsLeftLineValid", rBorder.IsLeftLineValid);
306     lcl_debug_BorderLine(rBorder.RightLine);
307     dmapper_logger->attribute("IsRightLineValid", rBorder.IsRightLineValid);
308     lcl_debug_BorderLine(rBorder.VerticalLine);
309     dmapper_logger->attribute("IsVerticalLineValid", rBorder.IsVerticalLineValid);
310     lcl_debug_BorderLine(rBorder.HorizontalLine);
311     dmapper_logger->attribute("IsHorizontalLineValid", rBorder.IsHorizontalLineValid);
312     dmapper_logger->attribute("Distance", rBorder.Distance);
313     dmapper_logger->attribute("IsDistanceValid", rBorder.IsDistanceValid);
314     dmapper_logger->endElement("TableBorder");
315 }
316 #endif
317 
318 struct WRITERFILTER_DLLPRIVATE TableInfo
319 {
320     sal_Int32 nLeftBorderDistance;
321     sal_Int32 nRightBorderDistance;
322     sal_Int32 nTopBorderDistance;
323     sal_Int32 nBottomBorderDistance;
324     PropertyMapPtr pTableDefaults;
325     PropertyMapPtr pTableBorders;
326     TableStyleSheetEntry* pTableStyle;
327     TablePropertyValues_t aTableProperties;
328 
TableInfowriterfilter::dmapper::TableInfo329     TableInfo()
330     : nLeftBorderDistance(DEF_BORDER_DIST)
331     , nRightBorderDistance(DEF_BORDER_DIST)
332     , nTopBorderDistance(0)
333     , nBottomBorderDistance(0)
334     , pTableDefaults(new PropertyMap)
335     , pTableBorders(new PropertyMap)
336     , pTableStyle(NULL)
337     {
338     }
339 
340 };
341 
endTableGetTableStyle(TableInfo & rInfo,const bool bAdjustLeftMarginByDefaultValue)342 TableStyleSheetEntry * DomainMapperTableHandler::endTableGetTableStyle(
343     TableInfo & rInfo,
344     const bool bAdjustLeftMarginByDefaultValue )
345 {
346     // will receive the table style if any
347     TableStyleSheetEntry* pTableStyle = NULL;
348 
349     if( m_aTableProperties.get() )
350     {
351         //create properties from the table attributes
352         //...pPropMap->Insert( PROP_LEFT_MARGIN, false, uno::makeAny( m_nLeftMargin - m_nGapHalf ));
353         //pPropMap->Insert( PROP_HORI_ORIENT, false, uno::makeAny( text::HoriOrientation::RIGHT ));
354         sal_Int32 nGapHalf = 0;
355         sal_Int32 nLeftMargin = 0;
356         sal_Int32 nTableWidth = 0;
357 
358         PropertyMap::iterator aTableStyleIter =
359         m_aTableProperties->find( PropertyDefinition( META_PROP_TABLE_STYLE_NAME, false ) );
360         if(aTableStyleIter != m_aTableProperties->end())
361         {
362             // Apply table style properties recursively
363             ::rtl::OUString sTableStyleName;
364             aTableStyleIter->second >>= sTableStyleName;
365             StyleSheetTablePtr pStyleSheetTable = m_rDMapper_Impl.GetStyleSheetTable();
366             const StyleSheetEntryPtr pStyleSheet = pStyleSheetTable->FindStyleSheetByISTD( sTableStyleName );
367             pTableStyle = dynamic_cast<TableStyleSheetEntry*>( pStyleSheet.get( ) );
368             m_aTableProperties->erase( aTableStyleIter );
369 
370             if( pStyleSheet )
371             {
372                 // First get the style properties, then the table ones
373                 PropertyMapPtr pTableProps( m_aTableProperties );
374                 TablePropertyMapPtr pEmptyProps( new TablePropertyMap );
375 
376                 m_aTableProperties = pEmptyProps;
377 
378                 PropertyMapPtr pMergedProperties = lcl_SearchParentStyleSheetAndMergeProperties(pStyleSheet, pStyleSheetTable);
379 
380 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
381                 dmapper_logger->startElement("mergedProps");
382                 dmapper_logger->addTag(pMergedProperties->toTag());
383                 dmapper_logger->endElement("mergedProps");
384 #endif
385 
386                 m_aTableProperties->insert( pMergedProperties );
387                 m_aTableProperties->insert( pTableProps );
388 
389 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
390                 dmapper_logger->startElement("TableProperties");
391                 dmapper_logger->addTag(m_aTableProperties->toTag());
392                 dmapper_logger->endElement("TableProperties");
393 #endif
394             }
395         }
396 
397         // Set the table default attributes for the cells
398         rInfo.pTableDefaults->insert( m_aTableProperties );
399 
400 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
401         dmapper_logger->startElement("TableDefaults");
402         dmapper_logger->addTag(rInfo.pTableDefaults->toTag());
403         dmapper_logger->endElement("TableDefaults");
404 #endif
405 
406         m_aTableProperties->getValue( TablePropertyMap::GAP_HALF, nGapHalf );
407         m_aTableProperties->getValue( TablePropertyMap::LEFT_MARGIN, nLeftMargin );
408 
409         m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_LEFT,
410                                      rInfo.nLeftBorderDistance );
411         m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_RIGHT,
412                                      rInfo.nRightBorderDistance );
413         m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_TOP,
414                                      rInfo.nTopBorderDistance );
415         m_aTableProperties->getValue( TablePropertyMap::CELL_MAR_BOTTOM,
416                                      rInfo.nBottomBorderDistance );
417 
418         table::TableBorderDistances aDistances;
419         aDistances.IsTopDistanceValid =
420         aDistances.IsBottomDistanceValid =
421         aDistances.IsLeftDistanceValid =
422         aDistances.IsRightDistanceValid = sal_True;
423         aDistances.TopDistance = static_cast<sal_Int16>( rInfo.nTopBorderDistance );
424         aDistances.BottomDistance = static_cast<sal_Int16>( rInfo.nBottomBorderDistance );
425         aDistances.LeftDistance = static_cast<sal_Int16>( rInfo.nLeftBorderDistance );
426         aDistances.RightDistance = static_cast<sal_Int16>( rInfo.nRightBorderDistance );
427 
428         m_aTableProperties->Insert( PROP_TABLE_BORDER_DISTANCES, false, uno::makeAny( aDistances ) );
429 
430         //table border settings
431         table::TableBorder aTableBorder;
432 
433         PropertyMap::iterator aTblBorderIter = m_aTableProperties->find( PropertyDefinition(PROP_TOP_BORDER, false) );
434         if( aTblBorderIter != m_aTableProperties->end() )
435         {
436             aTblBorderIter->second >>= aTableBorder.TopLine;
437             aTableBorder.IsTopLineValid = true;
438             m_aTableProperties->erase( aTblBorderIter );
439 
440             rInfo.pTableBorders->Insert( PROP_TOP_BORDER, false,
441                                         uno::makeAny( aTableBorder.TopLine ) );
442             PropertyMap::iterator pIt = rInfo.pTableDefaults->find( PropertyDefinition( PROP_TOP_BORDER, false ) );
443             if ( pIt != rInfo.pTableDefaults->end( ) )
444                 rInfo.pTableDefaults->erase( pIt );
445         }
446         aTblBorderIter = m_aTableProperties->find( PropertyDefinition(PROP_BOTTOM_BORDER, false) );
447         if( aTblBorderIter != m_aTableProperties->end() )
448         {
449             aTblBorderIter->second >>= aTableBorder.BottomLine;
450             aTableBorder.IsBottomLineValid = true;
451             m_aTableProperties->erase( aTblBorderIter );
452 
453             rInfo.pTableBorders->Insert( PROP_BOTTOM_BORDER, false,
454                                         uno::makeAny( aTableBorder.BottomLine));
455             PropertyMap::iterator pIt = rInfo.pTableDefaults->find( PropertyDefinition( PROP_BOTTOM_BORDER, false ) );
456             if ( pIt != rInfo.pTableDefaults->end( ) )
457                 rInfo.pTableDefaults->erase( pIt );
458         }
459         aTblBorderIter = m_aTableProperties->find( PropertyDefinition(PROP_LEFT_BORDER, false) );
460         if( aTblBorderIter != m_aTableProperties->end() )
461         {
462             aTblBorderIter->second >>= aTableBorder.LeftLine;
463             aTableBorder.IsLeftLineValid = true;
464             m_aTableProperties->erase( aTblBorderIter );
465 
466             rInfo.pTableBorders->Insert( PROP_LEFT_BORDER, false,
467                                         uno::makeAny( aTableBorder.LeftLine ) );
468             PropertyMap::iterator pIt = rInfo.pTableDefaults->find( PropertyDefinition( PROP_LEFT_BORDER, false ) );
469             if ( pIt != rInfo.pTableDefaults->end( ) )
470                 rInfo.pTableDefaults->erase( pIt );
471         }
472         aTblBorderIter = m_aTableProperties->find( PropertyDefinition(PROP_RIGHT_BORDER, false) );
473         if( aTblBorderIter != m_aTableProperties->end() )
474         {
475             aTblBorderIter->second >>= aTableBorder.RightLine;
476             aTableBorder.IsRightLineValid = true;
477             m_aTableProperties->erase( aTblBorderIter );
478 
479             rInfo.pTableBorders->Insert( PROP_RIGHT_BORDER, false,
480                                         uno::makeAny( aTableBorder.RightLine ) );
481             PropertyMap::iterator pIt = rInfo.pTableDefaults->find( PropertyDefinition( PROP_RIGHT_BORDER, false ) );
482             if ( pIt != rInfo.pTableDefaults->end( ) )
483                 rInfo.pTableDefaults->erase( pIt );
484         }
485         aTblBorderIter = m_aTableProperties->find( PropertyDefinition(META_PROP_HORIZONTAL_BORDER, false) );
486         if( aTblBorderIter != m_aTableProperties->end() )
487         {
488             aTblBorderIter->second >>= aTableBorder.HorizontalLine;
489             aTableBorder.IsHorizontalLineValid = true;
490             m_aTableProperties->erase( aTblBorderIter );
491 
492             rInfo.pTableBorders->Insert
493                 (META_PROP_HORIZONTAL_BORDER, false,
494                  uno::makeAny( aTableBorder.HorizontalLine ) );
495             PropertyMap::iterator pIt = rInfo.pTableDefaults->find( PropertyDefinition( META_PROP_HORIZONTAL_BORDER, false ) );
496             if ( pIt != rInfo.pTableDefaults->end( ) )
497                 rInfo.pTableDefaults->erase( pIt );
498         }
499         aTblBorderIter = m_aTableProperties->find( PropertyDefinition(META_PROP_VERTICAL_BORDER, false) );
500         if( aTblBorderIter != m_aTableProperties->end() )
501         {
502             aTblBorderIter->second >>= aTableBorder.VerticalLine;
503             aTableBorder.IsVerticalLineValid = true;
504             m_aTableProperties->erase( aTblBorderIter );
505 
506             rInfo.pTableBorders->Insert
507                 (META_PROP_VERTICAL_BORDER, false,
508                  uno::makeAny( aTableBorder.VerticalLine ) );
509             PropertyMap::iterator pIt = rInfo.pTableDefaults->find( PropertyDefinition( META_PROP_VERTICAL_BORDER, false ) );
510             if ( pIt != rInfo.pTableDefaults->end( ) )
511                 rInfo.pTableDefaults->erase( pIt );
512         }
513         aTableBorder.Distance = 0;
514         aTableBorder.IsDistanceValid = false;
515 
516         m_aTableProperties->Insert( PROP_TABLE_BORDER, false, uno::makeAny( aTableBorder ) );
517 
518 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
519         lcl_debug_TableBorder(aTableBorder);
520 #endif
521 
522         m_aTableProperties->Insert(
523             PROP_LEFT_MARGIN,
524             false,
525             uno::makeAny( nLeftMargin - nGapHalf - ( bAdjustLeftMarginByDefaultValue ? rInfo.nLeftBorderDistance : 0 ) ) );
526 
527         // no bottom margin - set it explicitly to avoid inheritance from a set dynamic pool default
528         // which might be provided via document default paragraph properties.
529         m_aTableProperties->Insert( PROP_BOTTOM_MARGIN, false, uno::makeAny( (sal_Int32)0 ) );
530 
531         m_aTableProperties->getValue( TablePropertyMap::TABLE_WIDTH, nTableWidth );
532         if( nTableWidth > 0 )
533             m_aTableProperties->Insert( PROP_WIDTH, false, uno::makeAny( nTableWidth ));
534 
535         sal_Int32 nHoriOrient = text::HoriOrientation::LEFT_AND_WIDTH;
536         m_aTableProperties->getValue( TablePropertyMap::HORI_ORIENT, nHoriOrient ) ;
537         m_aTableProperties->Insert( PROP_HORI_ORIENT, false, uno::makeAny( sal_Int16(nHoriOrient) ) );
538 
539         // fill default value - if not available
540         const PropertyMap::const_iterator aRepeatIter =
541         m_aTableProperties->find( PropertyDefinition( PROP_HEADER_ROW_COUNT, false ) );
542         if( aRepeatIter == m_aTableProperties->end() )
543             m_aTableProperties->Insert( PROP_HEADER_ROW_COUNT, false, uno::makeAny( (sal_Int32)0 ));
544 
545         // Remove the PROP_HEADER_ROW_COUNT from the table default to avoid
546         // propagating it to the cells
547         PropertyMap::iterator aDefaultRepeatIt =
548         rInfo.pTableDefaults->find( PropertyDefinition( PROP_HEADER_ROW_COUNT, false ) );
549         if ( aDefaultRepeatIt != rInfo.pTableDefaults->end( ) )
550             rInfo.pTableDefaults->erase( aDefaultRepeatIt );
551 
552         rInfo.aTableProperties = m_aTableProperties->GetPropertyValues();
553 
554 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
555         dmapper_logger->startElement("debug.tableprops");
556         dmapper_logger->addTag(m_aTableProperties->toTag());
557         dmapper_logger->endElement("debug.tableprops");
558 #endif
559 
560     }
561 
562     return pTableStyle;
563 }
564 
endTableGetCellProperties(TableInfo & rInfo)565 CellPropertyValuesSeq_t DomainMapperTableHandler::endTableGetCellProperties(TableInfo & rInfo)
566 {
567 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
568     dmapper_logger->startElement("getCellProperties");
569 #endif
570 
571     CellPropertyValuesSeq_t aCellProperties( m_aCellProperties.size() );
572 
573     if ( ! m_aCellProperties.empty())
574     {
575 
576         // std::vector< std::vector<PropertyMapPtr> > m_aCellProperties
577         PropertyMapVector2::const_iterator aRowOfCellsIterator = m_aCellProperties.begin();
578         PropertyMapVector2::const_iterator aRowOfCellsIteratorEnd = m_aCellProperties.end();
579         PropertyMapVector2::const_iterator aLastRowIterator = m_aCellProperties.end() - 1;
580         sal_Int32 nRow = 0;
581 
582         //it's a uno::Sequence< beans::PropertyValues >*
583         RowPropertyValuesSeq_t* pCellProperties = aCellProperties.getArray();
584         while( aRowOfCellsIterator != aRowOfCellsIteratorEnd )
585         {
586             if ( ! aRowOfCellsIterator->empty())
587             {
588                 //aRowOfCellsIterator points to a vector of PropertyMapPtr
589                 PropertyMapVector1::const_iterator aCellIterator = aRowOfCellsIterator->begin();
590                 PropertyMapVector1::const_iterator aCellIteratorEnd = aRowOfCellsIterator->end();
591                 PropertyMapVector1::const_iterator aLastCellIterator = aRowOfCellsIterator->end() - 1;
592 
593                 // Get the row style properties
594                 sal_Int32 nRowStyleMask = sal_Int32( 0 );
595                 PropertyMapPtr pRowProps = m_aRowProperties[nRow];
596                 if ( pRowProps.get( ) )
597                 {
598                     PropertyMap::iterator pTcCnfStyleIt = pRowProps->find( PropertyDefinition( PROP_CNF_STYLE, true ) );
599                     if ( pTcCnfStyleIt != pRowProps->end( ) )
600                     {
601                         if ( rInfo.pTableStyle )
602                         {
603                             rtl::OUString sMask;
604                             pTcCnfStyleIt->second >>= sMask;
605                             nRowStyleMask = sMask.toInt32( 2 );
606                         }
607                         pRowProps->erase( pTcCnfStyleIt );
608                     }
609                 }
610 
611                 sal_Int32 nCell = 0;
612                 pCellProperties[nRow].realloc( aRowOfCellsIterator->size() );
613                 beans::PropertyValues* pSingleCellProperties = pCellProperties[nRow].getArray();
614                 while( aCellIterator != aCellIteratorEnd )
615                 {
616                     PropertyMapPtr pAllCellProps( new PropertyMap );
617 
618                     bool bIsEndCol = aCellIterator == aLastCellIterator;
619                     bool bIsEndRow = aRowOfCellsIterator == aLastRowIterator;
620 
621                     //aCellIterator points to a PropertyMapPtr;
622                     if( aCellIterator->get() )
623                     {
624                         if ( rInfo.pTableDefaults->size( ) )
625                             pAllCellProps->insert( rInfo.pTableDefaults );
626 
627                         // Fill the cell properties with the ones of the style
628                         sal_Int32 nCellStyleMask = 0;
629                         const PropertyMap::iterator aCnfStyleIter =
630                             aCellIterator->get()->find( PropertyDefinition( PROP_CNF_STYLE, false ) );
631                         if ( aCnfStyleIter != aCellIterator->get( )->end( ) )
632                         {
633                             if ( rInfo.pTableStyle ) {
634                                 rtl::OUString sMask;
635                                 aCnfStyleIter->second >>= sMask;
636                                 nCellStyleMask = sMask.toInt32( 2 );
637                             }
638                             aCellIterator->get( )->erase( aCnfStyleIter );
639                         }
640 
641                         if ( rInfo.pTableStyle )
642                         {
643                             PropertyMapPtr pStyleProps = rInfo.pTableStyle->GetProperties( nCellStyleMask + nRowStyleMask );
644                             pAllCellProps->insert( pStyleProps );
645                         }
646 
647                         // Then add the cell properties
648                         pAllCellProps->insert( *aCellIterator );
649                         aCellIterator->get( )->swap( *pAllCellProps.get( ) );
650 
651 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
652                         dmapper_logger->startElement("cell");
653                         dmapper_logger->attribute("cell", nCell);
654                         dmapper_logger->attribute("row", nRow);
655 #endif
656 
657                         lcl_computeCellBorders( rInfo.pTableBorders, *aCellIterator, nCell, nRow, bIsEndCol, bIsEndRow );
658 
659                         //now set the default left+right border distance TODO: there's an sprm containing the default distance!
660                         const PropertyMap::const_iterator aLeftDistanceIter =
661                             aCellIterator->get()->find( PropertyDefinition(PROP_LEFT_BORDER_DISTANCE, false) );
662                         if( aLeftDistanceIter == aCellIterator->get()->end() )
663                             aCellIterator->get()->Insert( PROP_LEFT_BORDER_DISTANCE, false,
664                                 uno::makeAny(rInfo.nLeftBorderDistance ) );
665                         const PropertyMap::const_iterator aRightDistanceIter =
666                             aCellIterator->get()->find( PropertyDefinition(PROP_RIGHT_BORDER_DISTANCE, false) );
667                         if( aRightDistanceIter == aCellIterator->get()->end() )
668                             aCellIterator->get()->Insert( PROP_RIGHT_BORDER_DISTANCE, false,
669                                 uno::makeAny((sal_Int32) rInfo.nRightBorderDistance ) );
670 
671                         const PropertyMap::const_iterator aTopDistanceIter =
672                             aCellIterator->get()->find( PropertyDefinition(PROP_TOP_BORDER_DISTANCE, false) );
673                         if( aTopDistanceIter == aCellIterator->get()->end() )
674                             aCellIterator->get()->Insert( PROP_TOP_BORDER_DISTANCE, false,
675                                 uno::makeAny((sal_Int32) rInfo.nTopBorderDistance ) );
676 
677                         const PropertyMap::const_iterator aBottomDistanceIter =
678                             aCellIterator->get()->find( PropertyDefinition(PROP_BOTTOM_BORDER_DISTANCE, false) );
679                         if( aBottomDistanceIter == aCellIterator->get()->end() )
680                             aCellIterator->get()->Insert( PROP_BOTTOM_BORDER_DISTANCE, false,
681                                 uno::makeAny((sal_Int32) rInfo.nBottomBorderDistance ) );
682 
683                         pSingleCellProperties[nCell] = aCellIterator->get()->GetPropertyValues();
684 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
685                         dmapper_logger->endElement("cell");
686 #endif
687                     }
688                     ++nCell;
689                     ++aCellIterator;
690                 }
691 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
692                 //-->debug cell properties
693                 {
694                     ::rtl::OUString sNames;
695                     const uno::Sequence< beans::PropertyValues > aDebugCurrentRow = aCellProperties[nRow];
696                     sal_Int32 nDebugCells = aDebugCurrentRow.getLength();
697                     (void) nDebugCells;
698                     for( sal_Int32  nDebugCell = 0; nDebugCell < nDebugCells; ++nDebugCell)
699                     {
700                         const uno::Sequence< beans::PropertyValue >& aDebugCellProperties = aDebugCurrentRow[nDebugCell];
701                         sal_Int32 nDebugCellProperties = aDebugCellProperties.getLength();
702                         for( sal_Int32  nDebugProperty = 0; nDebugProperty < nDebugCellProperties; ++nDebugProperty)
703                         {
704                             const ::rtl::OUString sName = aDebugCellProperties[nDebugProperty].Name;
705                             sNames += sName;
706                             sNames += ::rtl::OUString('-');
707                         }
708                         sNames += ::rtl::OUString('\n');
709                     }
710                     (void)sNames;
711                 }
712                 //--<
713 #endif
714                 ++nRow;
715                 ++aRowOfCellsIterator;
716             }
717         }
718     }
719 
720 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
721     dmapper_logger->endElement("getCellProperties");
722 #endif
723 
724     return aCellProperties;
725 }
726 
endTableGetRowProperties()727 RowPropertyValuesSeq_t DomainMapperTableHandler::endTableGetRowProperties()
728 {
729 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
730     dmapper_logger->startElement("getRowProperties");
731 #endif
732 
733     RowPropertyValuesSeq_t aRowProperties( m_aRowProperties.size() );
734     PropertyMapVector1::const_iterator aRowIter = m_aRowProperties.begin();
735     PropertyMapVector1::const_iterator aRowIterEnd = m_aRowProperties.end();
736     sal_Int32 nRow = 0;
737     while( aRowIter != aRowIterEnd )
738     {
739 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
740         dmapper_logger->startElement("rowProps.row");
741 #endif
742         if( aRowIter->get() )
743         {
744             // set default to 'break across pages'
745             if( aRowIter->get()->find( PropertyDefinition( PROP_IS_SPLIT_ALLOWED, false )) == aRowIter->get()->end())
746                 aRowIter->get()->Insert( PROP_IS_SPLIT_ALLOWED, false, uno::makeAny(sal_True ) );
747 
748             aRowProperties[nRow] = (*aRowIter)->GetPropertyValues();
749 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
750             dmapper_logger->addTag((*aRowIter)->toTag());
751             dmapper_logger->addTag(lcl_PropertyValuesToTag(aRowProperties[nRow]));
752 #endif
753         }
754         ++nRow;
755         ++aRowIter;
756 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
757         dmapper_logger->endElement("rowProps.row");
758 #endif
759     }
760 
761 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
762     dmapper_logger->endElement("getRowProperties");
763 #endif
764 
765     return aRowProperties;
766 }
767 
endTable(const unsigned int nDepth)768 void DomainMapperTableHandler::endTable(
769     const unsigned int nDepth )
770 {
771 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
772     dmapper_logger->startElement("tablehandler.endTable");
773 #endif
774 
775     TableInfo aTableInfo;
776     // adjust left margin only for tables in the body text, not for sub tables.
777     const bool bAdjustLeftMarginByDefaultValue = (nDepth == 0);
778     aTableInfo.pTableStyle =
779             endTableGetTableStyle( aTableInfo, bAdjustLeftMarginByDefaultValue );
780     //  expands to uno::Sequence< Sequence< beans::PropertyValues > >
781 
782     CellPropertyValuesSeq_t aCellProperties = endTableGetCellProperties(aTableInfo);
783 
784     RowPropertyValuesSeq_t aRowProperties = endTableGetRowProperties();
785 
786 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
787     dmapper_logger->addTag(lcl_PropertyValueSeqToTag(aRowProperties));
788 #endif
789 
790     if (m_pTableSeq->getLength() > 0)
791     {
792         try
793         {
794 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
795             XMLTag::Pointer_t pTag = tableSequenceToTag(*m_pTableSeq);
796             dmapper_logger->addTag(pTag);
797 
798             ::std::clog << pTag->toTree() << ::std::endl;
799 #endif
800             uno::Reference< text::XTextTable > xTable =
801                     m_xText->convertToTable(
802                         *m_pTableSeq,
803                         aCellProperties,
804                         aRowProperties,
805                         aTableInfo.aTableProperties );
806 
807             m_xTableRange = xTable->getAnchor( );
808         }
809         catch (lang::IllegalArgumentException e)
810         {
811             (void) e;
812 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
813             dmapper_logger->chars("failed to import table!");
814 #endif
815         }
816         catch ( uno::Exception e )
817         {
818             (void) e;
819 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
820             dmapper_logger->startElement("exception");
821             dmapper_logger->chars(rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr( ));
822             dmapper_logger->endElement("exception");
823 #endif
824         }
825     }
826 
827     m_aTableProperties.reset();
828     m_aCellProperties.clear();
829     m_aRowProperties.clear();
830 
831 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
832     dmapper_logger->endElement("tablehandler.endTable");
833     dmapper_logger->endElement("tablehandler.table");
834 #endif
835 }
836 
startRow(unsigned int nCells,TablePropertyMapPtr pProps)837 void DomainMapperTableHandler::startRow(unsigned int nCells,
838                                         TablePropertyMapPtr pProps)
839 {
840     m_aRowProperties.push_back( pProps );
841     m_aCellProperties.push_back( PropertyMapVector1() );
842 
843 #if DEBUG_DMAPPER_TABLE_HANDLER
844     dmapper_logger->startElement("table.row");
845     dmapper_logger->attribute("cells", nCells);
846     if (pProps != NULL)
847         dmapper_logger->addTag(pProps->toTag());
848 #endif
849 
850     m_pRowSeq = RowSequencePointer_t(new RowSequence_t(nCells));
851     m_nCellIndex = 0;
852 }
853 
endRow()854 void DomainMapperTableHandler::endRow()
855 {
856     (*m_pTableSeq)[m_nRowIndex] = *m_pRowSeq;
857     ++m_nRowIndex;
858     m_nCellIndex = 0;
859 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
860     dmapper_logger->endElement("table.row");
861 #endif
862 }
863 
startCell(const Handle_t & start,TablePropertyMapPtr pProps)864 void DomainMapperTableHandler::startCell(const Handle_t & start,
865                                          TablePropertyMapPtr pProps )
866 {
867     sal_uInt32 nRow = m_aRowProperties.size();
868     if ( pProps.get( ) )
869         m_aCellProperties[nRow - 1].push_back( pProps );
870     else
871     {
872         // Adding an empty cell properties map to be able to get
873         // the table defaults properties
874         TablePropertyMapPtr pEmptyProps( new TablePropertyMap( ) );
875         m_aCellProperties[nRow - 1].push_back( pEmptyProps );
876     }
877 
878 #if DEBUG_DMAPPER_TABLE_HANDLER
879     dmapper_logger->startElement("table.cell");
880     dmapper_logger->startElement("table.cell.start");
881     dmapper_logger->chars(toString(start));
882     dmapper_logger->endElement("table.cell.start");
883     lcl_printProperties( pProps );
884 #endif
885 
886     //add a new 'row' of properties
887 //    if( m_pCellProperties.size() <= sal::static_int_cast< sal_uInt32, sal_Int32>(m_nRowIndex) )
888 //        m_pCellProperties.push_back( RowProperties_t() );
889 //    m_pCellProperties[m_nRowIndex].push_back( pProps );
890     m_pCellSeq = CellSequencePointer_t(new CellSequence_t(2));
891     if (!start.get())
892         return;
893     (*m_pCellSeq)[0] = start->getStart();
894 }
895 
endCell(const Handle_t & end)896 void DomainMapperTableHandler::endCell(const Handle_t & end)
897 {
898 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
899     dmapper_logger->startElement("table.cell.end");
900     dmapper_logger->chars(toString(end));
901     dmapper_logger->endElement("table.cell.end");
902     dmapper_logger->endElement("table.cell");
903 #endif
904 
905     if (!end.get())
906         return;
907     (*m_pCellSeq)[1] = end->getEnd();
908     (*m_pRowSeq)[m_nCellIndex] = *m_pCellSeq;
909     ++m_nCellIndex;
910 }
911 
912 }}
913