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 <DomainMapperTableManager.hxx>
24 #include <resourcemodel/WW8ResourceModel.hxx>
25 #include <BorderHandler.hxx>
26 #include <CellColorHandler.hxx>
27 #include <CellMarginHandler.hxx>
28 #include <ConversionHelper.hxx>
29 #include <MeasureHandler.hxx>
30 #include <TDefTableHandler.hxx>
31 #include <com/sun/star/text/HoriOrientation.hpp>
32 #include <com/sun/star/text/SizeType.hpp>
33 #include <com/sun/star/text/TableColumnSeparator.hpp>
34 #include <com/sun/star/text/VertOrientation.hpp>
35 #include <ooxml/resourceids.hxx>
36 #include <doctok/sprmids.hxx>
37 #include <dmapperLoggers.hxx>
38 
39 namespace writerfilter {
40 namespace dmapper {
41 
42 using namespace ::com::sun::star;
43 using namespace ::std;
44 /*-- 23.04.2007 14:57:49---------------------------------------------------
45 
46   -----------------------------------------------------------------------*/
DomainMapperTableManager(bool bOOXML)47 DomainMapperTableManager::DomainMapperTableManager(bool bOOXML) :
48     m_nCellCounterForCurrentRow(),
49     m_nGridSpanOfCurrentCell( 1 ),
50     m_nCurrentCellBorderIndex(),
51     m_nCurrentHeaderRepeatCount(),
52     m_nTableWidthOfCurrentTable(),
53     m_bOOXML( bOOXML ),
54     m_pTablePropsHandler( new TablePropertiesHandler( bOOXML ) )
55 {
56     m_pTablePropsHandler->SetTableManager( this );
57 
58 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
59 #ifdef DEBUG_TABLE
60     setTagLogger(dmapper_logger);
61 #endif
62 #endif
63 }
64 /*-- 23.04.2007 14:57:49---------------------------------------------------
65 
66   -----------------------------------------------------------------------*/
~DomainMapperTableManager()67 DomainMapperTableManager::~DomainMapperTableManager()
68 {
69     delete m_pTablePropsHandler;
70   m_pTablePropsHandler = NULL;
71 }
72 /*-- 23.04.2007 15:25:37---------------------------------------------------
73 
74   -----------------------------------------------------------------------*/
sprm(Sprm & rSprm)75 bool DomainMapperTableManager::sprm(Sprm & rSprm)
76 {
77 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
78     dmapper_logger->startElement("tablemanager.sprm");
79     string sSprm = rSprm.toString();
80     dmapper_logger->chars(sSprm);
81     dmapper_logger->endElement("tablemanager.sprm");
82 #endif
83     bool bRet = DomainMapperTableManager_Base_t::sprm(rSprm);
84 
85     if( !bRet )
86     {
87         bRet = m_pTablePropsHandler->sprm( rSprm );
88     }
89 
90     if ( !bRet )
91     {
92         bRet = true;
93         const sal_uInt32 nSprmId = rSprm.getId();
94         const Value::Pointer_t pValue = rSprm.getValue();
95         const sal_Int32 nIntValue = ((pValue.get() != NULL) ? pValue->getInt() : 0);
96         switch ( nSprmId )
97         {
98             case 0xf661: //sprmTTRLeft left table indent
99                 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
100 
101             case 0xf614: // sprmTTPreferredWidth - preferred table width
102                 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
103 
104             case NS_ooxml::LN_CT_TblPrBase_tblW:  //90722;
105                 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
106 
107             case NS_ooxml::LN_CT_TblPrBase_tblInd: //90725
108                 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
109             {
110                 //contains unit and value
111                 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
112                 if( pProperties.get())
113                 {   //contains attributes x2902 (LN_unit) and x17e2 (LN_trleft)
114                     MeasureHandlerPtr pMeasureHandler( new MeasureHandler );
115                     pProperties->resolve(*pMeasureHandler);
116                     TablePropertyMapPtr pPropMap( new TablePropertyMap );
117                     if( nSprmId == 0xf661 || nSprmId == sal_uInt32(NS_ooxml::LN_CT_TblPrBase_tblInd ))
118                     {
119                         pPropMap->setValue( TablePropertyMap::LEFT_MARGIN, pMeasureHandler->getMeasureValue() );
120                     }
121                     else
122                     {
123                         m_nTableWidthOfCurrentTable.top() = pMeasureHandler->getMeasureValue();
124                         if( m_nTableWidthOfCurrentTable.top() > 0 )
125                             pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidthOfCurrentTable.top() );
126                     }
127 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
128                     dmapper_logger->addTag(pPropMap->toTag());
129 #endif
130                     insertTableProps(pPropMap);
131                 }
132             }
133             break;
134 
135             case 0x3404:// sprmTTableHeader
136             case NS_ooxml::LN_CT_TrPrBase_tblHeader:
137                 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
138                 // if nIntValue == 1 then the row is a repeated header line
139                 // to prevent later rows from increasing the repeating m_nHeaderRepeat is set to NULL when repeating stops
140                 if( nIntValue > 0 && m_nCurrentHeaderRepeatCount.top() >= 0 )
141                 {
142                     ++(m_nCurrentHeaderRepeatCount.top());
143                     TablePropertyMapPtr pPropMap( new TablePropertyMap );
144                     pPropMap->Insert( PROP_HEADER_ROW_COUNT, false, uno::makeAny( m_nCurrentHeaderRepeatCount.top() ));
145                     insertTableProps(pPropMap);
146                 }
147                 else
148                     m_nCurrentHeaderRepeatCount.top() = -1;
149             break;
150 
151             case 0xd608: // TDefTable
152                 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
153             {
154                 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
155                 if( pProperties.get())
156                 {
157                     TDefTableHandlerPtr pTDefTableHandler( new TDefTableHandler(m_bOOXML) );
158                     pProperties->resolve( *pTDefTableHandler );
159 
160                     TablePropertyMapPtr pRowPropMap( new TablePropertyMap );
161                     pRowPropMap->insert( pTDefTableHandler->getRowProperties() );
162                     insertRowProps( pRowPropMap );
163                     if( m_nTableWidthOfCurrentTable.top() == 0 )
164                     {
165                         m_nTableWidthOfCurrentTable.top() = pTDefTableHandler->getTableWidth();
166                         if( m_nTableWidthOfCurrentTable.top() > 0 )
167                         {
168                             TablePropertyMapPtr pPropMap( new TablePropertyMap );
169                             pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidthOfCurrentTable.top() );
170                             insertTableProps(pPropMap);
171                         }
172                     }
173                     for( size_t nCell = 0; nCell < pTDefTableHandler->getCellCount(); ++nCell )
174                     {
175                         TablePropertyMapPtr pCellPropMap( new TablePropertyMap );
176                         pTDefTableHandler->fillCellProperties( nCell, pCellPropMap );
177                         cellPropsByCell( nCell, pCellPropMap );
178                     }
179                 }
180             }
181             break;
182 
183             case 0xD605: // sprmTTableBorders
184                 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
185             {
186                 writerfilter::Reference<Properties>::Pointer_t pProperties = rSprm.getProps();
187                 if( pProperties.get())
188                 {
189                     BorderHandlerPtr pBorderHandler( new BorderHandler(m_bOOXML) );
190                     pProperties->resolve(*pBorderHandler);
191                     TablePropertyMapPtr pCellPropMap( new TablePropertyMap() );
192                     pCellPropMap->insert( pBorderHandler->getProperties() );
193                     cellPropsByCell( m_nCurrentCellBorderIndex.top(), pCellPropMap );
194                     ++(m_nCurrentCellBorderIndex.top());
195                 }
196             }
197             break;
198 
199             case 0xd632 : //sprmTNewSpacing
200                 /* WRITERFILTERSTATUS: done: 0, planned: 2, spent: 0 */
201 
202             case 0xd634 : //sprmTNewSpacing
203                 /* WRITERFILTERSTATUS: done: 0, planned: 2, spent: 0 */
204                 //TODO: sprms contain default (TNew) and actual border spacing of cells - not resolvable yet
205             break;
206 
207             case 0xd613: //sprmTGridLineProps
208                 /* WRITERFILTERSTATUS: done: 0, planned: 2, spent: 0 */
209                 // TODO: needs a handler
210                 /*contains:
211                  GridLineProps">
212                     rtf:LINEPROPSTOP
213                     rtf:LINEPROPSLEFT
214                     rtf:LINEPROPSBOTTOM
215                     rtf:LINEPROPSRIGHT
216                     rtf:LINEPROPSHORIZONTAL
217                     rtf:LINEPROPSVERTICAL
218                         rtf:LINECOLOR
219                         rtf:LINEWIDTH
220                         rtf:LINETYPE
221 
222                 */
223             break;
224 
225             case 0x740a : //sprmTTlp
226                 /* WRITERFILTERSTATUS: done: 0, planned: 2, spent: 0 */
227                 //TODO: Table look specifier
228             break;
229 
230             case 0x6816 : //unknown
231             case 0x3466 : //unknown
232             case 0x3615 : //unknown
233             case 0x646b : //unknown - expandable sprm - see ww8scan.cxx
234             case 0x7479 : //unknown
235             case 0xf617 : //unknown
236             case 0xf618 : //unknown
237                 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
238                 bRet = false;
239             break;
240 
241             case NS_ooxml::LN_CT_TblPrBase_tblStyle: //table style name
242                 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
243             {
244                 TablePropertyMapPtr pPropMap( new TablePropertyMap );
245                 pPropMap->Insert( META_PROP_TABLE_STYLE_NAME, false, uno::makeAny( pValue->getString() ));
246                 insertTableProps(pPropMap);
247             }
248             break;
249 
250             case NS_ooxml::LN_CT_TblGridBase_gridCol:
251                 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
252             {
253                 getCurrentGrid()->push_back( ConversionHelper::convertTwipToMM100( nIntValue ) );
254             }
255             break;
256 
257             case NS_ooxml::LN_CT_TcPrBase_vMerge : //vertical merge
258                 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
259             {
260                 // values can be: LN_Value_ST_Merge_restart, LN_Value_ST_Merge_continue, in reality the second one is a 0
261                 TablePropertyMapPtr pMergeProps( new TablePropertyMap );
262                 pMergeProps->Insert( PROP_VERTICAL_MERGE, false, uno::makeAny( bool( sal::static_int_cast<Id>(nIntValue) == NS_ooxml::LN_Value_ST_Merge_restart )) );
263                 cellProps( pMergeProps);
264             }
265             break;
266 
267             case NS_ooxml::LN_CT_TcPrBase_gridSpan: //number of grid positions spanned by this cell
268                 /* WRITERFILTERSTATUS: done: 100, planned: 2, spent: 0 */
269             {
270 #if DEBUG_DMAPPER_TABLE_HANDLER
271                 dmapper_logger->startElement("tablemanager.GridSpan");
272                 dmapper_logger->attribute("gridSpan", nIntValue);
273                 dmapper_logger->endElement("tablemanager.GridSpan");
274 #endif
275                 m_nGridSpanOfCurrentCell = nIntValue;
276             }
277             break;
278             case NS_ooxml::LN_CT_TblPrBase_tblLook:
279                 /* WRITERFILTERSTATUS: done: 0, planned: 2, spent: 0 */
280                 break; //todo: table look specifier
281 
282             case NS_ooxml::LN_CT_TcPrBase_tcW:
283                 /* WRITERFILTERSTATUS: done: 100, planned: 0.5, spent: 0 */
284                 break; //fixed column width is not supported
285 
286             case NS_ooxml::LN_CT_TrPrBase_cnfStyle:
287                 /* WRITERFILTERSTATUS: done: 100, planned: 0.5, spent: 0 */
288                 {
289                     TablePropertyMapPtr pProps( new TablePropertyMap );
290                     pProps->Insert( PROP_CNF_STYLE, true, uno::makeAny( pValue->getString( ) ) );
291                     insertRowProps( pProps );
292                 }
293                 break;
294 
295             case NS_ooxml::LN_CT_PPrBase_cnfStyle:
296                 /* WRITERFILTERSTATUS: done: 0, planned: 0.5, spent: 0 */
297                 // TODO cnfStyle on a paragraph
298                 break;
299 
300             case NS_ooxml::LN_CT_TcPrBase_cnfStyle:
301                 /* WRITERFILTERSTATUS: done: 100, planned: 0.5, spent: 0 */
302                 {
303                     TablePropertyMapPtr pProps( new TablePropertyMap );
304                     pProps->Insert( PROP_CNF_STYLE, true, uno::makeAny( pValue->getString( ) ) );
305                     cellProps( pProps );
306                 }
307                 break;
308 
309             default:
310                 bRet = false;
311 
312 #ifdef DEBUG_DOMAINMAPPER
313                 dmapper_logger->element("TableManager.unhandled");
314 #endif
315         }
316     }
317     return bRet;
318 }
319 
320 
pushStackOfMembers()321 void DomainMapperTableManager::pushStackOfMembers()
322 {
323     m_nCellCounterForCurrentRow.push( 0 );
324     m_nCurrentCellBorderIndex.push( 0 );
325     m_nCurrentHeaderRepeatCount.push( 0 );
326     m_nTableWidthOfCurrentTable.push( 0 );
327 
328     IntVectorPtr pNewGrid( new vector<sal_Int32> );
329     IntVectorPtr pNewSpans( new vector<sal_Int32> );
330     m_aTableGrid.push( pNewGrid );
331     m_aGridSpans.push( pNewSpans );
332 }
333 
334 
popStackOfMembers()335 void DomainMapperTableManager::popStackOfMembers()
336 {
337     if (!m_nCellCounterForCurrentRow.empty()) {
338         m_nCellCounterForCurrentRow.pop();
339     }
340     if (!m_nCurrentCellBorderIndex.empty()) {
341         m_nCurrentCellBorderIndex.pop();
342     }
343     if (!m_nCurrentHeaderRepeatCount.empty()) {
344         m_nCurrentHeaderRepeatCount.pop();
345     }
346     if (!m_nTableWidthOfCurrentTable.empty()) {
347         m_nTableWidthOfCurrentTable.pop();
348     }
349 
350     if (!m_aTableGrid.empty()) {
351         m_aTableGrid.pop();
352     }
353     if (!m_aGridSpans.empty()) {
354         m_aGridSpans.pop();
355     }
356 }
357 
358 
getCurrentGrid()359 boost::shared_ptr< vector<sal_Int32> > DomainMapperTableManager::getCurrentGrid()
360 {
361     return m_aTableGrid.top();
362 }
363 
getCurrentSpans()364 boost::shared_ptr< vector< sal_Int32 > > DomainMapperTableManager::getCurrentSpans()
365 {
366     return m_aGridSpans.top();
367 }
368 
369 
SetStyleProperties(PropertyMapPtr pProperties)370 void DomainMapperTableManager::SetStyleProperties(
371     PropertyMapPtr pProperties )
372 {
373     m_pStyleProps = pProperties;
374     if ( m_pStyleProps.get() )
375     {
376         pushStackOfMembers();
377     }
378     else
379     {
380         popStackOfMembers();
381     }
382 };
383 
384 
startLevel()385 void DomainMapperTableManager::startLevel()
386 {
387     DomainMapperTableManager_Base_t::startLevel();
388 
389     pushStackOfMembers();
390 }
391 
endLevel()392 void DomainMapperTableManager::endLevel()
393 {
394     popStackOfMembers();
395 
396     DomainMapperTableManager_Base_t::endLevel();
397 
398 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
399     dmapper_logger->startElement("dmappertablemanager.endLevel");
400     PropertyMapPtr pProps = getTableProps();
401     if (pProps.get() != NULL)
402         dmapper_logger->addTag(getTableProps()->toTag());
403 
404     dmapper_logger->endElement("dmappertablemanager.endLevel");
405 #endif
406 }
407 
408 /*-- 02.05.2007 14:36:26---------------------------------------------------
409 
410   -----------------------------------------------------------------------*/
endOfCellAction()411 void DomainMapperTableManager::endOfCellAction()
412 {
413 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
414     dmapper_logger->element("endOFCellAction");
415 #endif
416 
417     getCurrentSpans()->push_back( m_nGridSpanOfCurrentCell );
418     m_nGridSpanOfCurrentCell = 1;
419     ++(m_nCellCounterForCurrentRow.top());
420 }
421 /*-- 02.05.2007 14:36:26---------------------------------------------------
422 
423   -----------------------------------------------------------------------*/
endOfRowAction()424 void DomainMapperTableManager::endOfRowAction()
425 {
426 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
427     dmapper_logger->startElement("endOfRowAction");
428 #endif
429 
430     IntVectorPtr pTableGrid = getCurrentGrid( );
431     if( m_nTableWidthOfCurrentTable.top() == 0
432         && pTableGrid->size() > 0 )
433     {
434         ::std::vector<sal_Int32>::const_iterator aCellIter = pTableGrid->begin();
435 
436 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
437         dmapper_logger->startElement("tableWidth");
438 #endif
439 
440         while( aCellIter != pTableGrid->end() )
441         {
442 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
443             dmapper_logger->startElement("col");
444             dmapper_logger->attribute("width", *aCellIter);
445             dmapper_logger->endElement("col");
446 #endif
447 
448              m_nTableWidthOfCurrentTable.top() += *aCellIter++;
449         }
450 
451         if( m_nTableWidthOfCurrentTable.top() > 0)
452         {
453             TablePropertyMapPtr pPropMap( new TablePropertyMap );
454             pPropMap->setValue( TablePropertyMap::TABLE_WIDTH, m_nTableWidthOfCurrentTable.top() );
455             insertTableProps(pPropMap);
456         }
457 
458 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
459         dmapper_logger->endElement("tableWidth");
460 #endif
461     }
462 
463     IntVectorPtr pCurrentSpans = getCurrentSpans( );
464     if( pCurrentSpans->size() < m_nCellCounterForCurrentRow.top() )
465     {
466         //fill missing elements with '1'
467         pCurrentSpans->insert( pCurrentSpans->end( ), m_nCellCounterForCurrentRow.top() - pCurrentSpans->size(), 1 );
468     }
469 
470 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
471     dmapper_logger->startElement("gridSpans");
472     {
473         ::std::vector<sal_Int32>::const_iterator aGridSpanIter = pCurrentSpans->begin();
474         ::std::vector<sal_Int32>::const_iterator aGridSpanIterEnd = pCurrentSpans->end();
475 
476         while (aGridSpanIter != aGridSpanIterEnd)
477         {
478             dmapper_logger->startElement("gridSpan");
479             dmapper_logger->attribute("span", *aGridSpanIter);
480             dmapper_logger->endElement("gridSpan");
481 
482             aGridSpanIter++;
483         }
484     }
485     dmapper_logger->endElement("gridSpans");
486 #endif
487 
488     //calculate number of used grids - it has to match the size of m_aTableGrid
489     size_t nGrids = 0;
490     ::std::vector<sal_Int32>::const_iterator aGridSpanIter = pCurrentSpans->begin();
491     for( ; aGridSpanIter != pCurrentSpans->end(); ++aGridSpanIter)
492         nGrids += *aGridSpanIter;
493 
494     if( pTableGrid->size() == nGrids )
495     {
496         //determine table width
497         double nFullWidth = m_nTableWidthOfCurrentTable.top();
498         //the positions have to be distibuted in a range of 10000
499         const double nFullWidthRelative = 10000.;
500         uno::Sequence< text::TableColumnSeparator > aSeparators( m_nCellCounterForCurrentRow.top() - 1 );
501         text::TableColumnSeparator* pSeparators = aSeparators.getArray();
502         sal_Int16 nLastRelPos = 0;
503         sal_uInt32 nBorderGridIndex = 0;
504 
505         ::std::vector< sal_Int32 >::const_iterator aSpansIter = pCurrentSpans->begin( );
506         for( sal_uInt32 nBorder = 0; nBorder < m_nCellCounterForCurrentRow.top() - 1; ++nBorder )
507         {
508             sal_Int32 nGridCount = *aSpansIter;
509             double fGridWidth = 0.;
510             do
511             {
512                 fGridWidth += (*pTableGrid.get())[nBorderGridIndex++];
513             }while( --nGridCount );
514 
515             sal_Int16 nRelPos =
516                 sal::static_int_cast< sal_Int16 >(fGridWidth * nFullWidthRelative / nFullWidth );
517 
518             pSeparators[nBorder].Position =  nRelPos + nLastRelPos;
519             pSeparators[nBorder].IsVisible = sal_True;
520             nLastRelPos = nLastRelPos + nRelPos;
521             aSpansIter++;
522         }
523         TablePropertyMapPtr pPropMap( new TablePropertyMap );
524         pPropMap->Insert( PROP_TABLE_COLUMN_SEPARATORS, false, uno::makeAny( aSeparators ) );
525 
526 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
527         dmapper_logger->startElement("rowProperties");
528         dmapper_logger->addTag(pPropMap->toTag());
529         dmapper_logger->endElement("rowProperties");
530 #endif
531         insertRowProps(pPropMap);
532     }
533 
534     m_nCellCounterForCurrentRow.top() = 0;
535     m_nCurrentCellBorderIndex.top() = 0;
536     pCurrentSpans->clear();
537 
538 #ifdef DEBUG_DMAPPER_TABLE_HANDLER
539     dmapper_logger->endElement("endOfRowAction");
540 #endif
541 }
542 
543 
544 }}
545