1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #ifndef INCLUDED_WRITERFILTER_SOURCE_DMAPPER_TABLEMANAGER_HXX
21 #define INCLUDED_WRITERFILTER_SOURCE_DMAPPER_TABLEMANAGER_HXX
22 
23 #include <memory>
24 #include <stack>
25 
26 #include "PropertyMap.hxx"
27 #include "TableData.hxx"
28 
29 namespace writerfilter
30 {
31 namespace dmapper
32 {
33 
34 class DomainMapperTableHandler;
35 
36 /**
37    The table manager.
38 
39    This class gets forwarded events from the tokenizer. It gathers the
40    table data and after ending the table generates events for the
41    table structure. The events have to be handles by a TableDataHandler.
42 
43  */
44 class TableManager : public virtual SvRefBase
45 {
46     class TableManagerState final
47     {
48         /**
49          properties of the current cell
50          */
51         TablePropertyMapPtr mpCellProps;
52 
53         /**
54          properties of the current row
55          */
56         TablePropertyMapPtr mpRowProps;
57 
58         /**
59          properties of the current table
60          */
61         std::stack<TablePropertyMapPtr> mTableProps;
62 
63         /**
64          true if at the end of a row
65          */
66         bool mbRowEnd;
67 
68         /**
69          true when in a cell
70          */
71         bool mbInCell;
72 
73         /**
74          true when at the end of a cell
75          */
76         bool mbCellEnd;
77 
78     public:
79         /**
80          Constructor
81          */
TableManagerState()82         TableManagerState()
83         : mbRowEnd(false), mbInCell(false), mbCellEnd(false)
84         {
85         }
86 
startLevel()87         void startLevel()
88         {
89             TablePropertyMapPtr pProps;
90             mTableProps.push(pProps);
91         }
92 
endLevel()93         void endLevel()
94         {
95             mTableProps.pop();
96         }
97 
98         /**
99          Reset to initial state at beginning of row.
100          */
resetCellSpecifics()101         void resetCellSpecifics()
102         {
103             mbRowEnd = false;
104             mbInCell = false;
105             mbCellEnd = false;
106         }
107 
resetCellProps()108         void resetCellProps()
109         {
110             mpCellProps.clear();
111         }
112 
setCellProps(TablePropertyMapPtr pProps)113         void setCellProps(TablePropertyMapPtr pProps)
114         {
115             mpCellProps = pProps;
116         }
117 
getCellProps() const118         const TablePropertyMapPtr& getCellProps() const
119         {
120             return mpCellProps;
121         }
122 
resetRowProps()123         void resetRowProps()
124         {
125             mpRowProps.clear();
126         }
127 
setRowProps(TablePropertyMapPtr pProps)128         void setRowProps(TablePropertyMapPtr pProps)
129         {
130             mpRowProps = pProps;
131         }
132 
getRowProps() const133         const TablePropertyMapPtr& getRowProps() const
134         {
135             return mpRowProps;
136         }
137 
resetTableProps()138         void resetTableProps()
139         {
140             if (mTableProps.size() > 0)
141                 mTableProps.top().clear();
142         }
143 
setTableProps(TablePropertyMapPtr pProps)144         void setTableProps(TablePropertyMapPtr pProps)
145         {
146             if (mTableProps.size() > 0)
147                 mTableProps.top() = pProps;
148         }
149 
getTableProps()150         TablePropertyMapPtr getTableProps()
151         {
152             TablePropertyMapPtr pResult;
153 
154             if (mTableProps.size() > 0)
155                 pResult = mTableProps.top();
156 
157             return pResult;
158         }
159 
setInCell(bool bInCell)160         void setInCell(bool bInCell)
161         {
162             mbInCell = bInCell;
163         }
164 
isInCell() const165         bool isInCell() const
166         {
167             return mbInCell;
168         }
169 
setCellEnd(bool bCellEnd)170         void setCellEnd(bool bCellEnd)
171         {
172             mbCellEnd = bCellEnd;
173         }
174 
isCellEnd() const175         bool isCellEnd() const
176         {
177             return mbCellEnd;
178         }
179 
setRowEnd(bool bRowEnd)180         void setRowEnd(bool bRowEnd)
181         {
182             mbRowEnd = bRowEnd;
183         }
184 
isRowEnd() const185         bool isRowEnd() const
186         {
187             return mbRowEnd;
188         }
189     };
190 
191     /**
192      handle for the current position in document
193      */
194     css::uno::Reference<css::text::XTextRange> mCurHandle;
195 
196     TableManagerState mState;
197 
198 protected:
getCellProps() const199     TablePropertyMapPtr const & getCellProps() const
200     {
201         return mState.getCellProps();
202     }
203 
204 public:
getRowProps() const205     TablePropertyMapPtr const & getRowProps() const
206     {
207         return mState.getRowProps();
208     }
209 
210 protected:
setInCell(bool bInCell)211     void setInCell(bool bInCell)
212     {
213         mState.setInCell(bInCell);
214     }
215 
isInCell() const216     bool isInCell() const
217     {
218         return mState.isInCell();
219     }
220 
setCellEnd(bool bCellEnd)221     void setCellEnd(bool bCellEnd)
222     {
223         mState.setCellEnd(bCellEnd);
224     }
225 
setRowEnd(bool bRowEnd)226     void setRowEnd(bool bRowEnd)
227     {
228         mState.setRowEnd(bRowEnd);
229     }
230 
isRowEnd() const231     bool isRowEnd() const
232     {
233         return mState.isRowEnd();
234     }
235 
getTableProps()236     TablePropertyMapPtr getTableProps()
237     {
238         return mState.getTableProps();
239     }
240 
getHandle() const241     const css::uno::Reference<css::text::XTextRange>& getHandle() const
242     {
243         return mCurHandle;
244     }
245 
setHandle(const css::uno::Reference<css::text::XTextRange> & rHandle)246     void setHandle(const css::uno::Reference<css::text::XTextRange>& rHandle)
247     {
248         mCurHandle = rHandle;
249     }
250 
251 private:
252     typedef tools::SvRef< css::uno::Reference<css::text::XTextRange> > T_p;
253 
254     /**
255        depth of the current cell
256     */
257     sal_uInt32 mnTableDepthNew;
258 
259     /**
260         depth of the previous cell
261     */
262     sal_uInt32 mnTableDepth;
263 
264     /**
265        stack of table data
266 
267        for each level of nested tables there is one frame in the stack
268      */
269     std::stack<TableData::Pointer_t> mTableDataStack;
270     RowData::Pointer_t mpUnfinishedRow;
271     bool mbKeepUnfinishedRow;
272     /// If this is a nested table, does it start at cell start?
273     bool m_bTableStartsAtCellStart;
274 
275     bool m_bCellLastParaAfterAutospacing;
276 
277     /**
278        handler for resolveCurrentTable
279      */
280     tools::SvRef<DomainMapperTableHandler> mpTableDataHandler;
281 
282     /**
283        Set flag which indicates the current handle is in a cell.
284      */
285     void inCell();
286 
287     /**
288        Set flag which indicate the current handle is at the end of a cell.
289     */
290     void endCell();
291 
292     /**
293        Set the table depth of the current cell.
294 
295        @param nDepth     the cell depth
296      */
297     void cellDepth(sal_uInt32 nDepth);
298 
299     /**
300        Set flag indication the current handle is at the end of a row.
301     */
302     void endRow();
303 
304     /**
305        Resolve the current table to the TableDataHandler.
306      */
307     void resolveCurrentTable();
308 
309     /**
310      Open a cell at current level.
311      */
312 
313     void openCell(const css::uno::Reference<css::text::XTextRange>& rHandle, const TablePropertyMapPtr& pProps);
314 
315     /**
316      Close a cell at current level.
317      */
318     void closeCell(const css::uno::Reference<css::text::XTextRange>& rHandle);
319 
320     /**
321      Ensure a cell is open at the current level.
322     */
323     void ensureOpenCell(const TablePropertyMapPtr& pProps);
324 
325 protected:
326     /**
327        Return the current table difference, i.e. 1 if we are in the first cell of a new table, etc.
328      */
getTableDepthDifference() const329     sal_uInt32 getTableDepthDifference() const { return mnTableDepthNew - mnTableDepth; }
330 
getTableDepth() const331     sal_uInt32 getTableDepth() const { return mnTableDepthNew; }
332 
333     /**
334        Action to be carried out at the end of the last paragraph of a
335        cell.
336      */
337     virtual void endOfCellAction();
338 
339     /**
340        Action to be carried out at the end of the "table row"
341        paragraph.
342      */
343     virtual void endOfRowAction();
344     /** let the derived class clear their table related data
345      */
346     virtual void clearData();
347 
348     /** Should we keep the unfinished row in endLevel to initialize the table
349         data in the following startLevel.
350       */
setKeepUnfinishedRow(bool bKeep)351     void setKeepUnfinishedRow(bool bKeep)
352     {
353         mbKeepUnfinishedRow = bKeep;
354     }
355 
356 
357 public:
358     TableManager();
359     ~TableManager();
360 
361     /**
362        Set handler for resolveCurrentTable.
363 
364        @param pTableDataHandler     the handler
365      */
366     void setHandler(const tools::SvRef<DomainMapperTableHandler>& pTableDataHandler);
367 
368     /**
369        Set the current handle.
370 
371        @param rHandle     the handle
372      */
373     void handle(const css::uno::Reference<css::text::XTextRange>& rHandle);
374 
375     /**
376        Start a new table level.
377 
378        A new context is pushed onto the table data stack,
379      */
380     virtual void startLevel();
381 
382     /**
383        End a table level.
384 
385        The current table is resolved and the context is popped from
386        the stack.
387      */
388     virtual void endLevel();
389 
390     /**
391      * Signal that the next paragraph definitely won't be part of any table.
392      */
endTable()393     void endTable()
394     {
395         setRowEnd(false);
396     }
397 
398     /**
399        Tells whether a table has been started or not
400       */
401     bool isInTable();
402 
403     /**
404        Handle the start of a paragraph group.
405      */
406     void startParagraphGroup();
407 
408     /**
409        Handle the end of a paragraph group.
410     */
411     void endParagraphGroup();
412 
413     /**
414        Handle an SPRM at current handle.
415 
416        @param rSprm   the SPRM
417      */
418     virtual bool sprm(Sprm & rSprm);
419 
420     /**
421        Handle occurrence of character 0x7.
422      */
423     void handle0x7();
424 
425     /**
426        Handle 8 bit text at current handle.
427 
428        @param data    array of characters
429        @param len     number of characters to handle
430      */
431     void text(const sal_uInt8 * data, size_t len);
432 
433     /**
434        Handle 16 bit text at current handle.
435 
436        @param data    array of characters
437        @param len     number of characters to handle
438      */
439     void utext(const sal_uInt8 * data, size_t len);
440 
441     /**
442        Handle properties of the current cell.
443 
444        @param pProps   the properties
445      */
446     virtual void cellProps(const TablePropertyMapPtr& pProps);
447 
448     /**
449        Handle properties of the current row.
450 
451        @param pProps   the properties
452      */
453     virtual void insertRowProps(const TablePropertyMapPtr& pProps);
454 
455     /**
456        Handle properties of the current table.
457 
458        @param pProps   the properties
459      */
460     virtual void insertTableProps(const TablePropertyMapPtr& pProps);
461 
462     /**
463        Return if table manager has detected paragraph to ignore.
464 
465        If this function returns true the current paragraph contains
466        only control information, e.g. end of row.
467      */
468     bool isIgnore() const;
469 
470 
471     void setTableStartsAtCellStart(bool bTableStartsAtCellStart);
472     void setCellLastParaAfterAutospacing(bool bIsAfterAutospacing);
isCellLastParaAfterAutospacing() const473     bool isCellLastParaAfterAutospacing() const {return m_bCellLastParaAfterAutospacing;}
474 };
475 
476 }
477 
478 }
479 
480 #endif // INCLUDED_WRITERFILTER_INC_RESOURCEMODEL_TABLEMANAGER_HXX
481 
482 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
483