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_SW_SOURCE_FILTER_XML_XMLTBLI_HXX
21 #define INCLUDED_SW_SOURCE_FILTER_XML_XMLTBLI_HXX
22 
23 #include <xmloff/XMLTextTableContext.hxx>
24 
25 #include "xmlimp.hxx"
26 
27 #include <memory>
28 #include <unordered_map>
29 #include <vector>
30 
31 class SwXMLImport;
32 class SwTableNode;
33 class SwTableBox;
34 class SwTableLine;
35 class SwStartNode;
36 class SwTableBoxFormat;
37 class SwTableLineFormat;
38 class SwXMLTableCell_Impl;
39 class SwXMLTableRow_Impl;
40 typedef std::vector<std::unique_ptr<SwXMLTableRow_Impl>> SwXMLTableRows_Impl;
41 class SwXMLDDETableContext_Impl;
42 class TableBoxIndexHasher;
43 class TableBoxIndex;
44 
45 namespace com::sun::star {
46     namespace text { class XTextContent; }
47     namespace text { class XTextCursor; }
48 }
49 
50 class SwXMLTableContext : public XMLTextTableContext
51 {
52     OUString     m_aStyleName;
53     OUString     m_aDfltCellStyleName;
54     OUString     m_aTemplateName;
55 
56     //! Holds basic information about a column's width.
57     struct ColumnWidthInfo {
58         sal_uInt16 width;      //!< Column width (absolute or relative).
59         bool   isRelative; //!< True for a relative width, false for absolute.
ColumnWidthInfoSwXMLTableContext::ColumnWidthInfo60         ColumnWidthInfo(sal_uInt16 wdth, bool isRel) : width(wdth), isRelative(isRel) {};
61     };
62     std::vector<ColumnWidthInfo> m_aColumnWidths;
63     std::optional<std::vector<OUString>> m_xColumnDefaultCellStyleNames;
64 
65     css::uno::Reference< css::text::XTextCursor > m_xOldCursor;
66     css::uno::Reference< css::text::XTextContent > m_xTextContent;
67 
68     std::unique_ptr<SwXMLTableRows_Impl> m_pRows;
69 
70     SwTableNode         *m_pTableNode;
71     SwTableBox          *m_pBox1;
72     bool                 m_bOwnsBox1;
73     const SwStartNode   *m_pSttNd1;
74 
75     SwTableBoxFormat       *m_pBoxFormat;
76     SwTableLineFormat      *m_pLineFormat;
77 
78     // hash map of shared format, indexed by the (XML) style name,
79     // the column width, and protection flag
80     typedef std::unordered_map<TableBoxIndex,SwTableBoxFormat*,
81                           TableBoxIndexHasher> map_BoxFormat;
82     std::unique_ptr<map_BoxFormat> m_pSharedBoxFormats;
83 
84     SvXMLImportContextRef   m_xParentTable;   // if table is a sub table
85 
86     rtl::Reference<SwXMLDDETableContext_Impl> m_xDDESource;
87 
88     bool            m_bFirstSection : 1;
89     bool            m_bRelWidth : 1;
90     bool            m_bHasSubTables : 1;
91 
92     sal_uInt16              m_nHeaderRows;
93     sal_uInt32          m_nCurRow;
94     sal_uInt32          m_nCurCol;
95     /// Same as m_nCurCol, but not incremented multiple times for table cells with row span.
96     sal_uInt32 m_nNonMergedCurCol;
97     sal_Int32           m_nWidth;
98 
99     // The maximum table width (i.e., maximum value for m_nWidth); must be >= MINLAY and must also
100     // fit into ColumnWidthInfo::width (of type sal_uInt16), see e.g. the emplacement of
101     // MINLAY<=nWidth2<=MAX_WIDTH into m_aColumnWidths in SwXMLTableContext::InsertColumn:
102     static constexpr sal_Int32 MAX_WIDTH = SAL_MAX_UINT16;
103 
104     SwTableBox *NewTableBox( const SwStartNode *pStNd,
105                              SwTableLine *pUpper );
106     SwTableBox *MakeTableBox( SwTableLine *pUpper,
107                               const SwXMLTableCell_Impl *pStartNode,
108                               sal_uInt32 nLeftCol, sal_uInt32 nRightCol );
109     SwTableBox *MakeTableBox( SwTableLine *pUpper,
110                               sal_uInt32 nTopRow, sal_uInt32 nLeftCol,
111                               sal_uInt32 nBottomRow, sal_uInt32 nRightCol );
112     SwTableLine *MakeTableLine( SwTableBox *pUpper,
113                                 sal_uInt32 nTopRow, sal_uInt32 nLeftCol,
114                                 sal_uInt32 nBottomRow, sal_uInt32 nRightCol );
115 
116     void MakeTable_( SwTableBox *pBox=nullptr );
117     void MakeTable( SwTableBox *pBox, sal_Int32 nWidth );
118     void MakeTable();
119 
120     inline SwXMLTableContext *GetParentTable() const;
121 
122     const SwStartNode *GetPrevStartNode( sal_uInt32 nRow,
123                                          sal_uInt32 nCol ) const;
124     inline const SwStartNode *GetLastStartNode() const;
125     void FixRowSpan( sal_uInt32 nRow, sal_uInt32 nCol, sal_uInt32 nColSpan );
126     void ReplaceWithEmptyCell( sal_uInt32 nRow, sal_uInt32 nCol, bool bRows );
127 
128     /** sets the appropriate SwTableBoxFormat at pBox. */
129     SwTableBoxFormat* GetSharedBoxFormat(
130         SwTableBox* pBox,   /// the table box
131         const OUString& rStyleName, /// XML style name
132         sal_Int32 nColumnWidth,     /// width of column
133         bool bProtected,        /// is cell protected?
134         bool bMayShare, /// may the format be shared (no value, formula...)
135         bool& bNew,     /// true, if the format it not from the cache
136         bool* pModifyLocked );  /// if set, call pBox->LockModify() and return old lock status
137 
138 public:
139 
140 
141     SwXMLTableContext( SwXMLImport& rImport,
142                        const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList );
143     SwXMLTableContext( SwXMLImport& rImport,
144                        SwXMLTableContext *pTable );
145 
146     virtual ~SwXMLTableContext() override;
147 
148     virtual css::uno::Reference< css::xml::sax::XFastContextHandler > SAL_CALL createFastChildContext(
149         sal_Int32 Element,
150         const css::uno::Reference< css::xml::sax::XFastAttributeList > & xAttrList ) override;
151 
GetSwImport()152     SwXMLImport& GetSwImport() { return static_cast<SwXMLImport&>(GetImport()); }
153 
154     void InsertColumn( sal_Int32 nWidth, bool bRelWidth,
155                        const OUString *pDfltCellStyleName = nullptr );
156     sal_Int32 GetColumnWidth( sal_uInt32 nCol, sal_uInt32 nColSpan ) const;
157     OUString GetColumnDefaultCellStyleName( sal_uInt32 nCol ) const;
158     inline sal_uInt32 GetColumnCount() const;
159 
IsInsertCellPossible() const160     bool IsInsertCellPossible() const { return m_nCurCol < GetColumnCount(); }
161 
162     /// Determines if it's OK to insert a covered cell, given the total column count.
IsInsertCoveredCellPossible() const163     bool IsInsertCoveredCellPossible() const { return m_nNonMergedCurCol < GetColumnCount(); }
164 
IsInsertColPossible() const165     bool IsInsertColPossible() const { return m_nCurCol < USHRT_MAX; }
IsInsertRowPossible() const166     bool IsInsertRowPossible() const { return m_nCurRow < USHRT_MAX; }
IsValid() const167     bool IsValid() const { return m_pTableNode != nullptr; }
168 
169     void InsertCell( const OUString& rStyleName,
170                      sal_uInt32 nRowSpan, sal_uInt32 nColSpan,
171                      const SwStartNode *pStNd,
172                      SwXMLTableContext *pTable=nullptr,
173                      bool bIsProtected = false,
174                      const OUString *pFormula=nullptr,
175                      bool bHasValue = false,
176                      double fValue = 0.0,
177                      OUString const*const pStringValue = nullptr);
178 
179     /// Sets formatting of an already created covered cell.
180     void InsertCoveredCell(const OUString& rStyleName);
181 
182     void InsertRow( const OUString& rStyleName,
183                     const OUString& rDfltCellStyleName,
184                     bool bInHead );
185     void FinishRow();
186     void InsertRepRows( sal_uInt32 nCount );
187     const SwXMLTableCell_Impl *GetCell( sal_uInt32 nRow, sal_uInt32 nCol ) const;
188     SwXMLTableCell_Impl *GetCell( sal_uInt32 nRow, sal_uInt32 nCol );
189     const SwStartNode *InsertTableSection(const SwStartNode *pPrevSttNd = nullptr,
190                                   OUString const* pStringValueStyleName = nullptr);
191 
192     virtual void SAL_CALL endFastElement(sal_Int32 nElement) override;
193 
SetHasSubTables(bool bNew)194     void SetHasSubTables( bool bNew ) { m_bHasSubTables = bNew; }
195 };
196 
GetParentTable() const197 inline SwXMLTableContext *SwXMLTableContext::GetParentTable() const
198 {
199     return static_cast<SwXMLTableContext *>(m_xParentTable.get());
200 }
201 
GetColumnCount() const202 inline sal_uInt32 SwXMLTableContext::GetColumnCount() const
203 {
204     return m_aColumnWidths.size();
205 }
206 
GetLastStartNode() const207 inline const SwStartNode *SwXMLTableContext::GetLastStartNode() const
208 {
209     return GetPrevStartNode( 0UL, GetColumnCount() );
210 }
211 
212 #endif
213 
214 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
215