1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_WRITERFILTER_INC_RESOURCEMODEL_TABLEMANAGER_HXX
21 #define INCLUDED_WRITERFILTER_INC_RESOURCEMODEL_TABLEMANAGER_HXX
23 #include <resourcemodel/TableData.hxx>
25 #include <resourcemodel/WW8ResourceModel.hxx>
27 #include <ooxml/resourceids.hxx>
29 #include <boost/shared_ptr.hpp>
32 #include "TagLogger.hxx"
34 #if OSL_DEBUG_LEVEL > 0
35 # include <rtl/strbuf.hxx>
38 namespace writerfilter
42 Class to handle events generated by TableManager::resolveCurrentTable
44 template <typename T
, typename PropertiesPointer
>
45 class TableDataHandler
48 typedef boost::shared_ptr
<TableDataHandler
> Pointer_t
;
51 Handle start of table.
53 @param nRows number of rows in the table
54 @param nDepth depth of the table in surrounding table hierarchy
55 @param pProps properties of the table
57 virtual void startTable(unsigned int nRows
, unsigned int nDepth
,
58 PropertiesPointer pProps
) = 0;
63 virtual void endTable(unsigned int nestedTableLevel
) = 0;
68 @param nCols number of columns in the table
69 @param pProps properties of the row
71 virtual void startRow(unsigned int nCols
,
72 PropertiesPointer pProps
) = 0;
77 virtual void endRow() = 0;
82 @param rT start handle of the cell
83 @param pProps properties of the cell
85 virtual void startCell(const T
& rT
, PropertiesPointer pProps
) = 0;
90 @param rT end handle of cell
92 virtual void endCell(const T
& rT
) = 0;
95 ~TableDataHandler() {}
98 template <typename T
, typename PropertiesPointer
>
102 This class gets forwarded events from the tokenizer. It gathers the
103 table data and after ending the table generates events for the
104 table structure. The events have to be handles by a TableDataHandler.
110 TagLogger::Pointer_t mpTableLogger
;
113 class TableManagerState
116 properties at the current point in document
118 PropertiesPointer mpProps
;
121 properties of the current cell
123 PropertiesPointer mpCellProps
;
126 properties of the current row
128 PropertiesPointer mpRowProps
;
131 properties of the current table
133 std::stack
<PropertiesPointer
> mTableProps
;
136 true if at the end of a row
146 true when at the end of a cell
155 : mbRowEnd(false), mbInCell(false), mbCellEnd(false)
159 virtual ~TableManagerState()
165 PropertiesPointer pProps
;
166 mTableProps
.push(pProps
);
175 Reset to initial state at beginning of row.
177 void resetCellSpecifics()
189 void setProps(PropertiesPointer pProps
)
194 PropertiesPointer
getProps()
199 void resetCellProps()
204 void setCellProps(PropertiesPointer pProps
)
206 mpCellProps
= pProps
;
209 PropertiesPointer
getCellProps()
219 void setRowProps(PropertiesPointer pProps
)
224 PropertiesPointer
getRowProps()
229 void resetTableProps()
231 if (mTableProps
.size() > 0)
232 mTableProps
.top().reset();
235 void setTableProps(PropertiesPointer pProps
)
237 if (mTableProps
.size() > 0)
238 mTableProps
.top() = pProps
;
241 PropertiesPointer
getTableProps()
243 PropertiesPointer pResult
;
245 if (mTableProps
.size() > 0)
246 pResult
= mTableProps
.top();
251 void setInCell(bool bInCell
)
256 bool isInCell() const
261 void setCellEnd(bool bCellEnd
)
263 mbCellEnd
= bCellEnd
;
266 bool isCellEnd() const
271 void setRowEnd(bool bRowEnd
)
276 bool isRowEnd() const
283 handle for the current position in document
287 TableManagerState mState
;
290 PropertiesPointer
getProps()
292 return mState
.getProps();
295 void setProps(PropertiesPointer pProps
)
297 mState
.setProps(pProps
);
305 PropertiesPointer
getCellProps()
307 return mState
.getCellProps();
310 void setCellProps(PropertiesPointer pProps
)
312 mState
.setCellProps(pProps
);
315 void resetCellProps()
317 mState
.resetCellProps();
320 PropertiesPointer
getRowProps()
322 return mState
.getRowProps();
325 void setRowProps(PropertiesPointer pProps
)
327 mState
.setRowProps(pProps
);
332 mState
.resetRowProps();
335 void setInCell(bool bInCell
)
337 mState
.setInCell(bInCell
);
340 bool isInCell() const
342 return mState
.isInCell();
345 void setCellEnd(bool bCellEnd
)
347 mState
.setCellEnd(bCellEnd
);
350 bool isCellEnd() const
352 return mState
.isCellEnd();
355 void setRowEnd(bool bRowEnd
)
357 mState
.setRowEnd(bRowEnd
);
360 bool isRowEnd() const
362 return mState
.isRowEnd();
365 PropertiesPointer
getTableProps()
367 return mState
.getTableProps();
370 void setTableProps(PropertiesPointer pProps
)
372 mState
.setTableProps(pProps
);
375 void resetTableProps()
377 mState
.resetTableProps();
385 void setHandle(const T
& rHandle
)
387 mCurHandle
= rHandle
;
391 typedef boost::shared_ptr
<T
> T_p
;
394 depth of the current cell
396 sal_uInt32 mnTableDepthNew
;
399 depth of the previous cell
401 sal_uInt32 mnTableDepth
;
406 for each level of nested tables there is one frame in the stack
408 std::stack
<typename TableData
<T
, PropertiesPointer
>::Pointer_t
> mTableDataStack
;
409 typename RowData
<T
, PropertiesPointer
>::Pointer_t mpUnfinishedRow
;
410 bool mbKeepUnfinishedRow
;
412 typedef typename TableDataHandler
<T
, PropertiesPointer
>::Pointer_t TableDataHandlerPointer_t
;
415 handler for resolveCurrentTable
417 TableDataHandlerPointer_t mpTableDataHandler
;
420 Set flag which indicates the current handle is in a cell.
425 Set flag which indicate the current handle is at the end of a cell.
430 Set the table depth of the current cell.
432 @param nDepth the cell depth
434 void cellDepth(sal_uInt32 nDepth
);
437 Set flag indication the current handle is at the end of a row.
442 Resolve the current table to the TableDataHandler.
444 void resolveCurrentTable();
447 Open a cell at current level.
450 void openCell(const T
& handle
, PropertiesPointer pProps
);
453 Close a cell at current level.
455 void closeCell(const T
& handle
);
458 Ensure a cell is open at the current level.
460 void ensureOpenCell(PropertiesPointer pProps
);
465 Return current table depth.
467 sal_uInt32
getTableDepthNew() { return mnTableDepthNew
; }
470 Return the current table difference, i.e. 1 if we are in the first cell of a new table, etc.
472 sal_uInt32
getTableDepthDifference() { return mnTableDepthNew
- mnTableDepth
; }
475 Action to be carried out at the end of the last paragraph of a
478 virtual void endOfCellAction();
481 Action to be carried out at the end of the "table row"
484 virtual void endOfRowAction();
485 /** let the derived class clear their table related data
487 virtual void clearData();
489 /** Should we keep the unfinished row in endLevel to initialize the table
490 data in the following startLevel.
492 void setKeepUnfinishedRow(bool bKeep
)
494 mbKeepUnfinishedRow
= bKeep
;
500 virtual ~TableManager(){}
503 Set handler for resolveCurrentTable.
505 @param pTableDataHandler the handler
507 void setHandler(TableDataHandlerPointer_t pTableDataHandler
);
510 Set the current handle.
512 @param rHandle the handle
514 virtual void handle(const T
& rHandle
);
517 Start a new table level.
519 A new context is pushed onto the table data stack,
521 virtual void startLevel();
526 The current table is resolved and the context is popped from
529 virtual void endLevel();
532 * Signal that the next paragraph definitely won't be part of any table.
540 Tells whether a table has been started or not
545 Handle the start of a paragraph group.
547 virtual void startParagraphGroup();
550 Handle the end of a paragraph group.
552 virtual void endParagraphGroup();
555 Handle an SPRM at curent handle.
557 @param rSprm the SPRM
559 virtual bool sprm(Sprm
& rSprm
);
562 Handle properties at current handle.
564 @param pProps the properites
566 virtual void props(PropertiesPointer pProps
);
569 Handle occurrence of character 0x7.
571 virtual void handle0x7();
574 Handle 8 bit text at current handle.
576 @param data array of characters
577 @param len number of characters to handle
579 virtual void text(const sal_uInt8
* data
, size_t len
);
582 Handle 16 bit text at current handle.
584 @param data array of characters
585 @param len number of characters to handle
587 virtual void utext(const sal_uInt8
* data
, size_t len
);
590 Handle properties of the current cell.
592 @param pProps the properties
594 virtual void cellProps(PropertiesPointer pProps
);
597 Handle properties of a certain cell in the current row.
599 @paran i index of the cell in the current row
600 @param pProps the properties
602 virtual void cellPropsByCell(unsigned int i
, PropertiesPointer pProps
);
605 Handle properties of the current row.
607 @param pProps the properties
609 virtual void insertRowProps(PropertiesPointer pProps
);
612 Handle properties of the current table.
614 @param pProps the properties
616 virtual void insertTableProps(PropertiesPointer pProps
);
619 Return if table manager has detected paragraph to ignore.
621 If this function returns true the current paragraph contains
622 only control information, e.g. end of row.
624 virtual bool isIgnore() const;
628 void setTagLogger(TagLogger::Pointer_t _tagLogger
)
630 mpTableLogger
= _tagLogger
;
635 template <typename T
, typename PropertiesPointer
>
636 TableManager
<T
, PropertiesPointer
>::TableManager()
637 : mnTableDepthNew(0), mnTableDepth(0), mbKeepUnfinishedRow( false )
644 template <typename T
, typename PropertiesPointer
>
645 void TableManager
<T
, PropertiesPointer
>::cellDepth(sal_uInt32 nDepth
)
648 if (mpTableLogger
!= NULL
)
650 mpTableLogger
->startElement("tablemanager.cellDepth");
651 mpTableLogger
->attribute("depth", nDepth
);
652 mpTableLogger
->endElement();
656 mnTableDepthNew
= nDepth
;
659 template <typename T
, typename PropertiesPointer
>
660 void TableManager
<T
, PropertiesPointer
>::inCell()
663 if (mpTableLogger
!= NULL
)
664 mpTableLogger
->element("tablemanager.inCell");
668 if (mnTableDepthNew
< 1)
672 template <typename T
, typename PropertiesPointer
>
673 void TableManager
<T
, PropertiesPointer
>::endCell()
676 if (mpTableLogger
!= NULL
)
677 mpTableLogger
->element("tablemanager.endCell");
683 template <typename T
, typename PropertiesPointer
>
684 void TableManager
<T
, PropertiesPointer
>::endRow()
687 if (mpTableLogger
!= NULL
)
688 mpTableLogger
->element("tablemanager.endRow");
694 template <typename T
, typename PropertiesPointer
>
695 void TableManager
<T
, PropertiesPointer
>::setHandler
696 (typename TableDataHandler
<T
, PropertiesPointer
>::Pointer_t pTableDataHandler
)
698 mpTableDataHandler
= pTableDataHandler
;
701 template <typename T
, typename PropertiesPointer
>
702 void TableManager
<T
, PropertiesPointer
>::handle(const T
& rHandle
)
707 mpTableLogger
->startElement("tablemanager.handle");
708 mpTableLogger
->chars(toString(rHandle
));
709 mpTableLogger
->endElement();
716 template <typename T
, typename PropertiesPointer
>
717 bool TableManager
<T
, PropertiesPointer
>::isInTable()
719 bool bInTable
= false;
720 if ( !mTableDataStack
.empty() )
721 bInTable
= mTableDataStack
.top()->getDepth() > 0;
725 template <typename T
, typename PropertiesPointer
>
726 void TableManager
<T
, PropertiesPointer
>::startLevel()
729 if (mpTableLogger
!= NULL
)
731 typename TableData
<T
, PropertiesPointer
>::Pointer_t pTableData
;
733 if (mTableDataStack
.size() > 0)
734 pTableData
= mTableDataStack
.top();
736 mpTableLogger
->startElement("tablemanager.startLevel");
737 mpTableLogger
->attribute("level", mTableDataStack
.size());
739 if (pTableData
.get() != NULL
)
740 mpTableLogger
->attribute("openCell",
741 pTableData
->isCellOpen() ? "yes" : "no");
743 mpTableLogger
->endElement();
747 typename TableData
<T
, PropertiesPointer
>::Pointer_t pTableData
748 (new TableData
<T
, PropertiesPointer
>(mTableDataStack
.size()));
750 // If we have an unfinished row stored here, then push it to the new TableData
751 if ( mpUnfinishedRow
)
753 for (unsigned int i
= 0; i
< mpUnfinishedRow
->getCellCount(); ++i
)
755 pTableData
->addCell( mpUnfinishedRow
->getCellStart(i
),
756 mpUnfinishedRow
->getCellProperties(i
) );
757 pTableData
->endCell( mpUnfinishedRow
->getCellEnd(i
) );
759 mpUnfinishedRow
.reset();
762 mTableDataStack
.push(pTableData
);
766 template <typename T
, typename PropertiesPointer
>
767 void TableManager
<T
, PropertiesPointer
>::endLevel()
769 if (mpTableDataHandler
.get() != NULL
)
770 resolveCurrentTable();
772 // Store the unfinished row as it will be used for the next table
773 if ( mbKeepUnfinishedRow
)
774 mpUnfinishedRow
= mTableDataStack
.top()->getCurrentRow();
776 mTableDataStack
.pop();
779 if (mpTableLogger
!= NULL
)
781 typename TableData
<T
, PropertiesPointer
>::Pointer_t pTableData
;
783 if (mTableDataStack
.size() > 0)
784 pTableData
= mTableDataStack
.top();
786 mpTableLogger
->startElement("tablemanager.endLevel");
787 mpTableLogger
->attribute("level", mTableDataStack
.size());
789 if (pTableData
.get() != NULL
)
790 mpTableLogger
->attribute("openCell",
791 pTableData
->isCellOpen() ? "yes" : "no");
793 mpTableLogger
->endElement();
798 template <typename T
, typename PropertiesPointer
>
799 void TableManager
<T
, PropertiesPointer
>::startParagraphGroup()
801 mState
.resetCellSpecifics();
805 template <typename T
, typename PropertiesPointer
>
806 void TableManager
<T
, PropertiesPointer
>::endParagraphGroup()
808 sal_Int32 nTableDepthDifference
= mnTableDepthNew
- mnTableDepth
;
810 PropertiesPointer pEmptyProps
;
812 while (nTableDepthDifference
> 0)
814 ensureOpenCell(pEmptyProps
);
817 --nTableDepthDifference
;
819 while (nTableDepthDifference
< 0)
823 ++nTableDepthDifference
;
826 mnTableDepth
= mnTableDepthNew
;
828 if (mnTableDepth
> 0)
830 typename TableData
<T
, PropertiesPointer
>::Pointer_t pTableData
=
831 mTableDataStack
.top();
836 mTableDataStack
.top()->endRow(getRowProps());
842 ensureOpenCell(getCellProps());
847 closeCell(getHandle());
854 template <typename T
, typename PropertiesPointer
>
855 bool TableManager
<T
, PropertiesPointer
>::sprm(Sprm
& rSprm
)
858 switch (rSprm
.getId())
860 case NS_ooxml::LN_tblDepth
:
862 Value::Pointer_t pValue
= rSprm
.getValue();
864 cellDepth(pValue
->getInt());
867 case NS_ooxml::LN_inTbl
:
870 case NS_ooxml::LN_tblCell
:
873 case NS_ooxml::LN_tblRow
:
881 template <typename T
, typename PropertiesPointer
>
882 void TableManager
<T
, PropertiesPointer
>::props(PropertiesPointer pProps
)
887 template <typename T
, typename PropertiesPointer
>
888 void TableManager
<T
, PropertiesPointer
>::handle0x7()
891 if (mpTableLogger
!= NULL
)
892 mpTableLogger
->startElement("tablemanager.handle0x7");
895 if (mnTableDepthNew
< 1)
904 if (mpTableLogger
!= NULL
)
905 mpTableLogger
->endElement();
909 template <typename T
, typename PropertiesPointer
>
910 void TableManager
<T
, PropertiesPointer
>::text(const sal_uInt8
* data
, size_t len
)
912 // optimization: cell/row end characters are the last characters in a run
915 if (data
[len
- 1] == 0x7)
920 template <typename T
, typename PropertiesPointer
>
921 void TableManager
<T
, PropertiesPointer
>::utext(const sal_uInt8
* data
, size_t len
)
923 // optimization: cell/row end characters are the last characters in a run
927 sal_Unicode nChar
= data
[(len
- 1) * 2] + (data
[(len
- 1) * 2 + 1] << 8);
933 template <typename T
, typename PropertiesPointer
>
934 void TableManager
<T
, PropertiesPointer
>::cellProps(PropertiesPointer pProps
)
937 if (mpTableLogger
!= NULL
)
938 mpTableLogger
->startElement("tablemanager.cellProps");
941 if(getCellProps().get())
942 getCellProps()->InsertProps(pProps
);
944 setCellProps(pProps
);
947 if (mpTableLogger
!= NULL
)
948 mpTableLogger
->endElement();
952 template <typename T
, typename PropertiesPointer
>
953 void TableManager
<T
, PropertiesPointer
>::cellPropsByCell
954 (unsigned int i
, PropertiesPointer pProps
)
957 if (mpTableLogger
!= NULL
)
958 mpTableLogger
->startElement("tablemanager.cellPropsByCell");
961 mTableDataStack
.top()->insertCellProperties(i
, pProps
);
964 if (mpTableLogger
!= NULL
)
965 mpTableLogger
->endElement();
969 template <typename T
, typename PropertiesPointer
>
970 void TableManager
<T
, PropertiesPointer
>::insertRowProps(PropertiesPointer pProps
)
973 if (mpTableLogger
!= NULL
)
974 mpTableLogger
->startElement("tablemanager.insertRowProps");
977 if( getRowProps().get() )
978 getRowProps()->InsertProps(pProps
);
983 if (mpTableLogger
!= NULL
)
984 mpTableLogger
->endElement();
988 template <typename T
, typename PropertiesPointer
>
989 void TableManager
<T
, PropertiesPointer
>::insertTableProps(PropertiesPointer pProps
)
992 if (mpTableLogger
!= NULL
)
993 mpTableLogger
->startElement("tablemanager.insertTableProps");
996 if( getTableProps().get() && getTableProps() != pProps
)
997 getTableProps()->InsertProps(pProps
);
999 setTableProps(pProps
);
1002 if (mpTableLogger
!= NULL
)
1003 mpTableLogger
->endElement();
1007 template <typename T
, typename PropertiesPointer
>
1008 void TableManager
<T
, PropertiesPointer
>::resolveCurrentTable()
1011 if (mpTableLogger
!= NULL
)
1012 mpTableLogger
->startElement("tablemanager.resolveCurrentTable");
1015 if (mpTableDataHandler
.get() != NULL
)
1019 typename TableData
<T
, PropertiesPointer
>::Pointer_t
1020 pTableData
= mTableDataStack
.top();
1022 unsigned int nRows
= pTableData
->getRowCount();
1024 mpTableDataHandler
->startTable(nRows
, pTableData
->getDepth(), getTableProps());
1026 for (unsigned int nRow
= 0; nRow
< nRows
; ++nRow
)
1028 typename RowData
<T
, PropertiesPointer
>::Pointer_t pRowData
= pTableData
->getRow(nRow
);
1030 unsigned int nCells
= pRowData
->getCellCount();
1032 mpTableDataHandler
->startRow(nCells
, pRowData
->getProperties());
1034 for (unsigned int nCell
= 0; nCell
< nCells
; ++nCell
)
1036 mpTableDataHandler
->startCell
1037 (pRowData
->getCellStart(nCell
),
1038 pRowData
->getCellProperties(nCell
));
1040 mpTableDataHandler
->endCell(pRowData
->getCellEnd(nCell
));
1043 mpTableDataHandler
->endRow();
1046 mpTableDataHandler
->endTable(mTableDataStack
.size() - 1);
1048 catch (css::uno::Exception
const& e
)
1051 #if OSL_DEBUG_LEVEL > 0
1052 SAL_WARN("writerfilter", "resolving of current table failed with: " << e
.Message
);
1060 if (mpTableLogger
!= NULL
)
1061 mpTableLogger
->endElement();
1065 template <typename T
, typename PropertiesPointer
>
1066 void TableManager
<T
, PropertiesPointer
>::endOfCellAction()
1070 template <typename T
, typename PropertiesPointer
>
1071 void TableManager
<T
, PropertiesPointer
>::endOfRowAction()
1075 template <typename T
, typename PropertiesPointer
>
1076 bool TableManager
<T
, PropertiesPointer
>::isIgnore() const
1081 template <typename T
, typename PropertiesPointer
>
1082 void TableManager
<T
, PropertiesPointer
>::clearData()
1086 template <typename T
, typename PropertiesPointer
>
1087 void TableManager
<T
, PropertiesPointer
>::openCell
1088 (const T
& rHandle
, PropertiesPointer pProps
)
1091 mpTableLogger
->startElement("tablemanager.openCell");
1092 mpTableLogger
->chars(toString(rHandle
));
1093 mpTableLogger
->endElement();
1096 if (mTableDataStack
.size() > 0)
1098 typename TableData
<T
, PropertiesPointer
>::Pointer_t
1099 pTableData
= mTableDataStack
.top();
1101 pTableData
->addCell(rHandle
, pProps
);
1105 template <typename T
, typename PropertiesPointer
>
1106 void TableManager
<T
, PropertiesPointer
>::closeCell
1110 mpTableLogger
->startElement("tablemanager.closeCell");
1111 mpTableLogger
->chars(toString(rHandle
));
1112 mpTableLogger
->endElement();
1115 if (mTableDataStack
.size() > 0)
1117 typename TableData
<T
, PropertiesPointer
>::Pointer_t
1118 pTableData
= mTableDataStack
.top();
1120 pTableData
->endCell(rHandle
);
1124 template <typename T
, typename PropertiesPointer
>
1125 void TableManager
<T
, PropertiesPointer
>::ensureOpenCell(PropertiesPointer pProps
)
1128 mpTableLogger
->startElement("tablemanager.ensureOpenCell");
1131 if (mTableDataStack
.size() > 0)
1133 typename TableData
<T
, PropertiesPointer
>::Pointer_t
1134 pTableData
= mTableDataStack
.top();
1136 if (pTableData
.get() != NULL
)
1138 if (!pTableData
->isCellOpen())
1139 openCell(getHandle(), pProps
);
1141 pTableData
->insertCellProperties(pProps
);
1145 mpTableLogger
->endElement();
1151 #endif // INCLUDED_WRITERFILTER_INC_RESOURCEMODEL_TABLEMANAGER_HXX
1153 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */