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_TABLE_MANAGER_HXX
21 #define INCLUDED_TABLE_MANAGER_HXX
23 #include <resourcemodel/TableData.hxx>
25 #include <resourcemodel/WW8ResourceModel.hxx>
27 #include <doctok/sprmids.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
41 using namespace ::std
;
44 Class to handle events generated by TableManager::resolveCurrentTable
46 template <typename T
, typename PropertiesPointer
>
47 class TableDataHandler
50 typedef boost::shared_ptr
<TableDataHandler
> Pointer_t
;
53 Handle start of table.
55 @param nRows number of rows in the table
56 @param nDepth depth of the table in surrounding table hierarchy
57 @param pProps properties of the table
59 virtual void startTable(unsigned int nRows
, unsigned int nDepth
,
60 PropertiesPointer pProps
) = 0;
65 virtual void endTable(unsigned int nestedTableLevel
) = 0;
70 @param nCols number of columns in the table
71 @param pProps properties of the row
73 virtual void startRow(unsigned int nCols
,
74 PropertiesPointer pProps
) = 0;
79 virtual void endRow() = 0;
84 @param rT start handle of the cell
85 @param pProps properties of the cell
87 virtual void startCell(const T
& rT
, PropertiesPointer pProps
) = 0;
92 @param rT end handle of cell
94 virtual void endCell(const T
& rT
) = 0;
97 ~TableDataHandler() {}
100 template <typename T
, typename PropertiesPointer
>
104 This class gets forwarded events from the tokenizer. It gathers the
105 table data and after ending the table generates events for the
106 table structure. The events have to be handles by a TableDataHandler.
112 TagLogger::Pointer_t mpTableLogger
;
115 class TableManagerState
118 properties at the current point in document
120 PropertiesPointer mpProps
;
123 properties of the current cell
125 PropertiesPointer mpCellProps
;
128 properties of the current row
130 PropertiesPointer mpRowProps
;
133 properties of the current table
135 stack
<PropertiesPointer
> mTableProps
;
138 true if at the end of a row
148 true when at the end of a cell
157 : mbRowEnd(false), mbInCell(false), mbCellEnd(false)
161 virtual ~TableManagerState()
167 PropertiesPointer pProps
;
168 mTableProps
.push(pProps
);
177 Reset to initial state at beginning of row.
179 void resetCellSpecifics()
191 void setProps(PropertiesPointer pProps
)
196 PropertiesPointer
getProps()
201 void resetCellProps()
206 void setCellProps(PropertiesPointer pProps
)
208 mpCellProps
= pProps
;
211 PropertiesPointer
getCellProps()
221 void setRowProps(PropertiesPointer pProps
)
226 PropertiesPointer
getRowProps()
231 void resetTableProps()
233 if (mTableProps
.size() > 0)
234 mTableProps
.top().reset();
237 void setTableProps(PropertiesPointer pProps
)
239 if (mTableProps
.size() > 0)
240 mTableProps
.top() = pProps
;
243 PropertiesPointer
getTableProps()
245 PropertiesPointer pResult
;
247 if (mTableProps
.size() > 0)
248 pResult
= mTableProps
.top();
253 void setInCell(bool bInCell
)
258 bool isInCell() const
263 void setCellEnd(bool bCellEnd
)
265 mbCellEnd
= bCellEnd
;
268 bool isCellEnd() const
273 void setRowEnd(bool bRowEnd
)
278 bool isRowEnd() const
285 handle for the current position in document
289 TableManagerState mState
;
292 PropertiesPointer
getProps()
294 return mState
.getProps();
297 void setProps(PropertiesPointer pProps
)
299 mState
.setProps(pProps
);
307 PropertiesPointer
getCellProps()
309 return mState
.getCellProps();
312 void setCellProps(PropertiesPointer pProps
)
314 mState
.setCellProps(pProps
);
317 void resetCellProps()
319 mState
.resetCellProps();
322 PropertiesPointer
getRowProps()
324 return mState
.getRowProps();
327 void setRowProps(PropertiesPointer pProps
)
329 mState
.setRowProps(pProps
);
334 mState
.resetRowProps();
337 void setInCell(bool bInCell
)
339 mState
.setInCell(bInCell
);
342 bool isInCell() const
344 return mState
.isInCell();
347 void setCellEnd(bool bCellEnd
)
349 mState
.setCellEnd(bCellEnd
);
352 bool isCellEnd() const
354 return mState
.isCellEnd();
357 void setRowEnd(bool bRowEnd
)
359 mState
.setRowEnd(bRowEnd
);
362 bool isRowEnd() const
364 return mState
.isRowEnd();
367 PropertiesPointer
getTableProps()
369 return mState
.getTableProps();
372 void setTableProps(PropertiesPointer pProps
)
374 mState
.setTableProps(pProps
);
377 void resetTableProps()
379 mState
.resetTableProps();
387 void setHandle(const T
& rHandle
)
389 mCurHandle
= rHandle
;
393 typedef boost::shared_ptr
<T
> T_p
;
396 depth of the current cell
398 sal_uInt32 mnTableDepthNew
;
401 depth of the previous cell
403 sal_uInt32 mnTableDepth
;
408 for each level of nested tables there is one frame in the stack
410 stack
<typename TableData
<T
, PropertiesPointer
>::Pointer_t
> mTableDataStack
;
411 typename RowData
<T
, PropertiesPointer
>::Pointer_t mpUnfinishedRow
;
412 bool mbKeepUnfinishedRow
;
414 typedef typename TableDataHandler
<T
, PropertiesPointer
>::Pointer_t TableDataHandlerPointer_t
;
417 handler for resolveCurrentTable
419 TableDataHandlerPointer_t mpTableDataHandler
;
422 Set flag which indicates the current handle is in a cell.
427 Set flag which indicate the current handle is at the end of a cell.
432 Set the table depth of the current cell.
434 @param nDepth the cell depth
436 void cellDepth(sal_uInt32 nDepth
);
439 Set flag indication the current handle is at the end of a row.
444 Resolve the current table to the TableDataHandler.
446 void resolveCurrentTable();
449 Open a cell at current level.
452 void openCell(const T
& handle
, PropertiesPointer pProps
);
455 Close a cell at current level.
457 void closeCell(const T
& handle
);
460 Ensure a cell is open at the current level.
462 void ensureOpenCell(PropertiesPointer pProps
);
467 Return current table depth.
469 sal_uInt32
getTableDepthNew() { return mnTableDepthNew
; }
472 Return the current table difference, i.e. 1 if we are in the first cell of a new table, etc.
474 sal_uInt32
getTableDepthDifference() { return mnTableDepthNew
- mnTableDepth
; }
477 Action to be carried out at the end of the last paragraph of a
480 virtual void endOfCellAction();
483 Action to be carried out at the end of the "table row"
486 virtual void endOfRowAction();
487 /** let the derived class clear their table related data
489 virtual void clearData();
491 /** Should we keep the unfinished row in endLevel to initialize the table
492 data in the following startLevel.
494 void setKeepUnfinishedRow(bool bKeep
)
496 mbKeepUnfinishedRow
= bKeep
;
502 virtual ~TableManager(){}
505 Set handler for resolveCurrentTable.
507 @param pTableDataHandler the handler
509 void setHandler(TableDataHandlerPointer_t pTableDataHandler
);
512 Set the current handle.
514 @param rHandle the handle
516 virtual void handle(const T
& rHandle
);
519 Start a new table level.
521 A new context is pushed onto the table data stack,
523 virtual void startLevel();
528 The current table is resolved and the context is popped from
531 virtual void endLevel();
534 Tells whether a table has been started or not
539 Handle the start of a paragraph group.
541 virtual void startParagraphGroup();
544 Handle the end of a paragraph group.
546 virtual void endParagraphGroup();
549 Handle an SPRM at curent handle.
551 @param rSprm the SPRM
553 virtual bool sprm(Sprm
& rSprm
);
556 Handle properties at current handle.
558 @param pProps the properites
560 virtual void props(PropertiesPointer pProps
);
563 Handle occurrence of character 0x7.
565 virtual void handle0x7();
568 Handle 8 bit text at current handle.
570 @param data array of characters
571 @param len number of characters to handle
573 virtual void text(const sal_uInt8
* data
, size_t len
);
576 Handle 16 bit text at current handle.
578 @param data array of characters
579 @param len number of characters to handle
581 virtual void utext(const sal_uInt8
* data
, size_t len
);
584 Handle properties of the current cell.
586 @param pProps the properties
588 virtual void cellProps(PropertiesPointer pProps
);
591 Handle properties of a certain cell in the current row.
593 @paran i index of the cell in the current row
594 @param pProps the properties
596 virtual void cellPropsByCell(unsigned int i
, PropertiesPointer pProps
);
599 Handle properties of the current row.
601 @param pProps the properties
603 virtual void insertRowProps(PropertiesPointer pProps
);
606 Handle properties of the current table.
608 @param pProps the properties
610 virtual void insertTableProps(PropertiesPointer pProps
);
613 Return if table manager has detected paragraph to ignore.
615 If this function returns true the current paragraph contains
616 only control information, e.g. end of row.
618 virtual bool isIgnore() const;
622 void setTagLogger(TagLogger::Pointer_t _tagLogger
)
624 mpTableLogger
= _tagLogger
;
629 template <typename T
, typename PropertiesPointer
>
630 TableManager
<T
, PropertiesPointer
>::TableManager()
631 : mnTableDepthNew(0), mnTableDepth(0), mbKeepUnfinishedRow( false )
638 template <typename T
, typename PropertiesPointer
>
639 void TableManager
<T
, PropertiesPointer
>::cellDepth(sal_uInt32 nDepth
)
642 if (mpTableLogger
!= NULL
)
644 mpTableLogger
->startElement("tablemanager.cellDepth");
645 mpTableLogger
->attribute("depth", nDepth
);
646 mpTableLogger
->endElement();
650 mnTableDepthNew
= nDepth
;
653 template <typename T
, typename PropertiesPointer
>
654 void TableManager
<T
, PropertiesPointer
>::inCell()
657 if (mpTableLogger
!= NULL
)
658 mpTableLogger
->element("tablemanager.inCell");
662 if (mnTableDepthNew
< 1)
666 template <typename T
, typename PropertiesPointer
>
667 void TableManager
<T
, PropertiesPointer
>::endCell()
670 if (mpTableLogger
!= NULL
)
671 mpTableLogger
->element("tablemanager.endCell");
677 template <typename T
, typename PropertiesPointer
>
678 void TableManager
<T
, PropertiesPointer
>::endRow()
681 if (mpTableLogger
!= NULL
)
682 mpTableLogger
->element("tablemanager.endRow");
688 template <typename T
, typename PropertiesPointer
>
689 void TableManager
<T
, PropertiesPointer
>::setHandler
690 (typename TableDataHandler
<T
, PropertiesPointer
>::Pointer_t pTableDataHandler
)
692 mpTableDataHandler
= pTableDataHandler
;
695 template <typename T
, typename PropertiesPointer
>
696 void TableManager
<T
, PropertiesPointer
>::handle(const T
& rHandle
)
701 mpTableLogger
->startElement("tablemanager.handle");
702 mpTableLogger
->chars(toString(rHandle
));
703 mpTableLogger
->endElement();
710 template <typename T
, typename PropertiesPointer
>
711 bool TableManager
<T
, PropertiesPointer
>::isInTable()
713 bool bInTable
= false;
714 if ( !mTableDataStack
.empty() )
715 bInTable
= mTableDataStack
.top()->getDepth() > 0;
719 template <typename T
, typename PropertiesPointer
>
720 void TableManager
<T
, PropertiesPointer
>::startLevel()
723 if (mpTableLogger
!= NULL
)
725 typename TableData
<T
, PropertiesPointer
>::Pointer_t pTableData
;
727 if (mTableDataStack
.size() > 0)
728 pTableData
= mTableDataStack
.top();
730 mpTableLogger
->startElement("tablemanager.startLevel");
731 mpTableLogger
->attribute("level", mTableDataStack
.size());
733 if (pTableData
.get() != NULL
)
734 mpTableLogger
->attribute("openCell",
735 pTableData
->isCellOpen() ? "yes" : "no");
737 mpTableLogger
->endElement();
741 typename TableData
<T
, PropertiesPointer
>::Pointer_t pTableData
742 (new TableData
<T
, PropertiesPointer
>(mTableDataStack
.size()));
744 // If we have an unfinished row stored here, then push it to the new TableData
745 if ( mpUnfinishedRow
)
747 for (unsigned int i
= 0; i
< mpUnfinishedRow
->getCellCount(); ++i
)
749 pTableData
->addCell( mpUnfinishedRow
->getCellStart(i
),
750 mpUnfinishedRow
->getCellProperties(i
) );
751 pTableData
->endCell( mpUnfinishedRow
->getCellEnd(i
) );
753 mpUnfinishedRow
.reset();
756 mTableDataStack
.push(pTableData
);
760 template <typename T
, typename PropertiesPointer
>
761 void TableManager
<T
, PropertiesPointer
>::endLevel()
763 if (mpTableDataHandler
.get() != NULL
)
764 resolveCurrentTable();
766 // Store the unfinished row as it will be used for the next table
767 if ( mbKeepUnfinishedRow
)
768 mpUnfinishedRow
= mTableDataStack
.top()->getCurrentRow();
770 mTableDataStack
.pop();
773 if (mpTableLogger
!= NULL
)
775 typename TableData
<T
, PropertiesPointer
>::Pointer_t pTableData
;
777 if (mTableDataStack
.size() > 0)
778 pTableData
= mTableDataStack
.top();
780 mpTableLogger
->startElement("tablemanager.endLevel");
781 mpTableLogger
->attribute("level", mTableDataStack
.size());
783 if (pTableData
.get() != NULL
)
784 mpTableLogger
->attribute("openCell",
785 pTableData
->isCellOpen() ? "yes" : "no");
787 mpTableLogger
->endElement();
792 template <typename T
, typename PropertiesPointer
>
793 void TableManager
<T
, PropertiesPointer
>::startParagraphGroup()
795 mState
.resetCellSpecifics();
799 template <typename T
, typename PropertiesPointer
>
800 void TableManager
<T
, PropertiesPointer
>::endParagraphGroup()
802 sal_Int32 nTableDepthDifference
= mnTableDepthNew
- mnTableDepth
;
804 PropertiesPointer pEmptyProps
;
806 while (nTableDepthDifference
> 0)
808 ensureOpenCell(pEmptyProps
);
811 --nTableDepthDifference
;
813 while (nTableDepthDifference
< 0)
817 ++nTableDepthDifference
;
820 mnTableDepth
= mnTableDepthNew
;
822 if (mnTableDepth
> 0)
824 typename TableData
<T
, PropertiesPointer
>::Pointer_t pTableData
=
825 mTableDataStack
.top();
830 mTableDataStack
.top()->endRow(getRowProps());
836 ensureOpenCell(getCellProps());
841 closeCell(getHandle());
848 template <typename T
, typename PropertiesPointer
>
849 bool TableManager
<T
, PropertiesPointer
>::sprm(Sprm
& rSprm
)
852 switch (rSprm
.getId())
854 case NS_sprm::LN_PTableDepth
:
856 Value::Pointer_t pValue
= rSprm
.getValue();
858 cellDepth(pValue
->getInt());
861 case NS_sprm::LN_PFInTable
:
864 case NS_sprm::LN_PCell
:
867 case NS_sprm::LN_PFTtp
:
868 case NS_sprm::LN_PRow
:
876 template <typename T
, typename PropertiesPointer
>
877 void TableManager
<T
, PropertiesPointer
>::props(PropertiesPointer pProps
)
882 template <typename T
, typename PropertiesPointer
>
883 void TableManager
<T
, PropertiesPointer
>::handle0x7()
886 if (mpTableLogger
!= NULL
)
887 mpTableLogger
->startElement("tablemanager.handle0x7");
890 if (mnTableDepthNew
< 1)
899 if (mpTableLogger
!= NULL
)
900 mpTableLogger
->endElement();
904 template <typename T
, typename PropertiesPointer
>
905 void TableManager
<T
, PropertiesPointer
>::text(const sal_uInt8
* data
, size_t len
)
907 // optimization: cell/row end characters are the last characters in a run
910 if (data
[len
- 1] == 0x7)
915 template <typename T
, typename PropertiesPointer
>
916 void TableManager
<T
, PropertiesPointer
>::utext(const sal_uInt8
* data
, size_t len
)
918 // optimization: cell/row end characters are the last characters in a run
922 sal_Unicode nChar
= data
[(len
- 1) * 2] + (data
[(len
- 1) * 2 + 1] << 8);
928 template <typename T
, typename PropertiesPointer
>
929 void TableManager
<T
, PropertiesPointer
>::cellProps(PropertiesPointer pProps
)
932 if (mpTableLogger
!= NULL
)
933 mpTableLogger
->startElement("tablemanager.cellProps");
936 if(getCellProps().get())
937 getCellProps()->InsertProps(pProps
);
939 setCellProps(pProps
);
942 if (mpTableLogger
!= NULL
)
943 mpTableLogger
->endElement();
947 template <typename T
, typename PropertiesPointer
>
948 void TableManager
<T
, PropertiesPointer
>::cellPropsByCell
949 (unsigned int i
, PropertiesPointer pProps
)
952 if (mpTableLogger
!= NULL
)
953 mpTableLogger
->startElement("tablemanager.cellPropsByCell");
956 mTableDataStack
.top()->insertCellProperties(i
, pProps
);
959 if (mpTableLogger
!= NULL
)
960 mpTableLogger
->endElement();
964 template <typename T
, typename PropertiesPointer
>
965 void TableManager
<T
, PropertiesPointer
>::insertRowProps(PropertiesPointer pProps
)
968 if (mpTableLogger
!= NULL
)
969 mpTableLogger
->startElement("tablemanager.insertRowProps");
972 if( getRowProps().get() )
973 getRowProps()->InsertProps(pProps
);
978 if (mpTableLogger
!= NULL
)
979 mpTableLogger
->endElement();
983 template <typename T
, typename PropertiesPointer
>
984 void TableManager
<T
, PropertiesPointer
>::insertTableProps(PropertiesPointer pProps
)
987 if (mpTableLogger
!= NULL
)
988 mpTableLogger
->startElement("tablemanager.insertTableProps");
991 if( getTableProps().get() && getTableProps() != pProps
)
992 getTableProps()->InsertProps(pProps
);
994 setTableProps(pProps
);
997 if (mpTableLogger
!= NULL
)
998 mpTableLogger
->endElement();
1002 template <typename T
, typename PropertiesPointer
>
1003 void TableManager
<T
, PropertiesPointer
>::resolveCurrentTable()
1006 if (mpTableLogger
!= NULL
)
1007 mpTableLogger
->startElement("tablemanager.resolveCurrentTable");
1010 if (mpTableDataHandler
.get() != NULL
)
1014 typename TableData
<T
, PropertiesPointer
>::Pointer_t
1015 pTableData
= mTableDataStack
.top();
1017 unsigned int nRows
= pTableData
->getRowCount();
1019 mpTableDataHandler
->startTable(nRows
, pTableData
->getDepth(), getTableProps());
1021 for (unsigned int nRow
= 0; nRow
< nRows
; ++nRow
)
1023 typename RowData
<T
, PropertiesPointer
>::Pointer_t pRowData
= pTableData
->getRow(nRow
);
1025 unsigned int nCells
= pRowData
->getCellCount();
1027 mpTableDataHandler
->startRow(nCells
, pRowData
->getProperties());
1029 for (unsigned int nCell
= 0; nCell
< nCells
; ++nCell
)
1031 mpTableDataHandler
->startCell
1032 (pRowData
->getCellStart(nCell
),
1033 pRowData
->getCellProperties(nCell
));
1035 mpTableDataHandler
->endCell(pRowData
->getCellEnd(nCell
));
1038 mpTableDataHandler
->endRow();
1041 mpTableDataHandler
->endTable(mTableDataStack
.size() - 1);
1043 catch (uno::Exception
const& e
)
1046 #if OSL_DEBUG_LEVEL > 0
1047 SAL_WARN("writerfilter", "resolving of current table failed with: " << e
.Message
);
1055 if (mpTableLogger
!= NULL
)
1056 mpTableLogger
->endElement();
1060 template <typename T
, typename PropertiesPointer
>
1061 void TableManager
<T
, PropertiesPointer
>::endOfCellAction()
1065 template <typename T
, typename PropertiesPointer
>
1066 void TableManager
<T
, PropertiesPointer
>::endOfRowAction()
1070 template <typename T
, typename PropertiesPointer
>
1071 bool TableManager
<T
, PropertiesPointer
>::isIgnore() const
1076 template <typename T
, typename PropertiesPointer
>
1077 void TableManager
<T
, PropertiesPointer
>::clearData()
1081 template <typename T
, typename PropertiesPointer
>
1082 void TableManager
<T
, PropertiesPointer
>::openCell
1083 (const T
& rHandle
, PropertiesPointer pProps
)
1086 mpTableLogger
->startElement("tablemanager.openCell");
1087 mpTableLogger
->chars(toString(rHandle
));
1088 mpTableLogger
->endElement();
1091 if (mTableDataStack
.size() > 0)
1093 typename TableData
<T
, PropertiesPointer
>::Pointer_t
1094 pTableData
= mTableDataStack
.top();
1096 pTableData
->addCell(rHandle
, pProps
);
1100 template <typename T
, typename PropertiesPointer
>
1101 void TableManager
<T
, PropertiesPointer
>::closeCell
1105 mpTableLogger
->startElement("tablemanager.closeCell");
1106 mpTableLogger
->chars(toString(rHandle
));
1107 mpTableLogger
->endElement();
1110 if (mTableDataStack
.size() > 0)
1112 typename TableData
<T
, PropertiesPointer
>::Pointer_t
1113 pTableData
= mTableDataStack
.top();
1115 pTableData
->endCell(rHandle
);
1119 template <typename T
, typename PropertiesPointer
>
1120 void TableManager
<T
, PropertiesPointer
>::ensureOpenCell(PropertiesPointer pProps
)
1123 mpTableLogger
->startElement("tablemanager.ensureOpenCell");
1126 if (mTableDataStack
.size() > 0)
1128 typename TableData
<T
, PropertiesPointer
>::Pointer_t
1129 pTableData
= mTableDataStack
.top();
1131 if (pTableData
.get() != NULL
)
1133 if (!pTableData
->isCellOpen())
1134 openCell(getHandle(), pProps
);
1136 pTableData
->insertCellProperties(pProps
);
1140 mpTableLogger
->endElement();
1146 #endif // INCLUDED_TABLE_MANAGER_HXX
1148 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */