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