/src/libreoffice/sw/inc/ndarr.hxx
Line | Count | Source |
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_INC_NDARR_HXX |
21 | | #define INCLUDED_SW_INC_NDARR_HXX |
22 | | |
23 | | #include <sal/config.h> |
24 | | |
25 | | #include <limits> |
26 | | #include <vector> |
27 | | #include <memory> |
28 | | #include <optional> |
29 | | #include <tuple> |
30 | | |
31 | | #include "bparr.hxx" |
32 | | #include "ndtyp.hxx" |
33 | | #include <rtl/ustring.hxx> |
34 | | #include <o3tl/sorted_vector.hxx> |
35 | | #include "nodeoffset.hxx" |
36 | | |
37 | | class Graphic; |
38 | | class SwAttrSet; |
39 | | class SfxItemSet; |
40 | | class SwContentNode; |
41 | | class SwDoc; |
42 | | class SwFrameFormat; |
43 | | class SwGrfFormatColl; |
44 | | class SwGrfNode; |
45 | | class SwNode; |
46 | | class SwNodeIndex; |
47 | | class SwNodeRange; |
48 | | class SwOLENode; |
49 | | class SwPaM; |
50 | | class SwRootFrame; |
51 | | class SwSectionData; |
52 | | class SwSectionFormat; |
53 | | class SwTOXBase; |
54 | | class SwSectionNode; |
55 | | class SwStartNode; |
56 | | class SwTableBoxFormat; |
57 | | class SwTableFormat; |
58 | | class SwTableLine; |
59 | | class SwTableLineFormat; |
60 | | class SwTableNode; |
61 | | class SwTextFormatColl; |
62 | | class SwTextNode; |
63 | | class SwUndoTableToText; |
64 | | class SwUndoTextToTable; |
65 | | struct SwPosition; |
66 | | |
67 | | namespace sw { class DocumentContentOperationsManager; } |
68 | | namespace svt { class EmbeddedObjectRef; } |
69 | | |
70 | | |
71 | | typedef bool (*FnForEach_SwNodes)( SwNode*, void* pArgs ); |
72 | | typedef struct _xmlTextWriter *xmlTextWriterPtr; |
73 | | |
74 | | struct CompareSwOutlineNodes |
75 | | { |
76 | | bool operator()(const SwNode* lhs, const SwNode* rhs) const; |
77 | | }; |
78 | | |
79 | | class SwOutlineNodes : public o3tl::sorted_vector<SwNode*, CompareSwOutlineNodes> |
80 | | { |
81 | | public: |
82 | | static constexpr auto npos = std::numeric_limits<size_type>::max(); |
83 | | |
84 | | bool Seek_Entry(const SwNode* rP, size_type* pnPos) const; |
85 | | static const SwNode* GetRootNode(const SwNode* pNode, bool bCheckInlineHeading = true); |
86 | | }; |
87 | | |
88 | | struct CompareSwOutlineNodesInline |
89 | | { |
90 | | bool operator()(const SwNode* lhs, const SwNode* rhs) const; |
91 | | }; |
92 | | |
93 | | class SwOutlineNodesInline : public o3tl::sorted_vector<SwNode*, CompareSwOutlineNodesInline> |
94 | | { |
95 | | public: |
96 | | static constexpr auto npos = std::numeric_limits<size_type>::max(); |
97 | | |
98 | | bool Seek_Entry(const SwNode* rP, size_type* pnPos) const; |
99 | | bool Seek_Entry_By_Anchor(const SwNode* rAnchor, size_type* pnPos) const; |
100 | | }; |
101 | | |
102 | | struct SwTableToTextSave; |
103 | | using SwTableToTextSaves = std::vector<std::unique_ptr<SwTableToTextSave>>; |
104 | | |
105 | | class SwNodes final |
106 | | : private BigPtrArray |
107 | | { |
108 | | friend class SwDoc; |
109 | | friend class SwNode; |
110 | | friend class SwNodeIndex; |
111 | | friend class SwStartNode; |
112 | | friend class ::sw::DocumentContentOperationsManager; |
113 | | |
114 | | void RemoveNode( SwNodeOffset nDelPos, SwNodeOffset nLen, bool bDel ); |
115 | | |
116 | | void InsertNode( SwNode* pNode, const SwNodeIndex& rPos ); |
117 | | void InsertNode( SwNode* pNode, SwNodeOffset nPos ); |
118 | | |
119 | | SwDoc& m_rMyDoc; ///< This Doc contains the nodes-array. |
120 | | |
121 | | SwNode *m_pEndOfPostIts, *m_pEndOfInserts, ///< These are the fixed ranges. |
122 | | *m_pEndOfAutotext, *m_pEndOfRedlines; |
123 | | std::unique_ptr<SwNode> m_pEndOfContent; |
124 | | |
125 | | mutable SwOutlineNodes m_aOutlineNodes; ///< Array of all outline nodes. |
126 | | |
127 | | bool m_bInNodesDel : 1; /**< In Case of recursive calling. |
128 | | Do not update Num/Outline. */ |
129 | | bool m_bInDelUpdOutline : 1; ///< Flag for updating of Outline. |
130 | | |
131 | | // Actions on the nodes. |
132 | | static void SectionUpDown( const SwNodeIndex & aStart, const SwNodeIndex & aEnd ); |
133 | | void DelNodes( const SwNodeIndex& rStart, SwNodeOffset nCnt = SwNodeOffset(1) ); |
134 | | |
135 | | void ChgNode( SwNodeIndex const & rDelPos, SwNodeOffset nSize, |
136 | | SwNodeIndex& rInsPos, bool bNewFrames ); |
137 | | |
138 | | void UpdateOutlineIdx( const SwNode& ); ///< Update all OutlineNodes starting from Node. |
139 | | |
140 | | void CopyNodes( const SwNodeRange&, SwNode& rPos, |
141 | | bool bNewFrames, bool bTableInsDummyNode = false ) const; |
142 | | void DelDummyNodes( const SwNodeRange& rRg ); |
143 | | |
144 | | SwNodes(SwNodes const&) = delete; |
145 | | SwNodes& operator=(SwNodes const&) = delete; |
146 | | |
147 | | SwNodes(SwDoc& rDoc); |
148 | | |
149 | | public: |
150 | | ~SwNodes(); |
151 | | |
152 | | typedef std::vector<SwNodeRange> NodeRanges_t; |
153 | | typedef std::vector<NodeRanges_t> TableRanges_t; |
154 | | |
155 | | SwNode* operator[]( SwNodeOffset n ) const; // defined in node.hxx |
156 | | |
157 | 6.63M | SwNodeOffset Count() const { return SwNodeOffset(BigPtrArray::Count()); } |
158 | | void ForEach( FnForEach_SwNodes fnForEach, void* pArgs = nullptr ) |
159 | 0 | { |
160 | 0 | ForEach( SwNodeOffset(0), Count(), fnForEach, pArgs ); |
161 | 0 | } |
162 | | void ForEach( SwNodeOffset nStt, SwNodeOffset nEnd, FnForEach_SwNodes fnForEach, void* pArgs ); |
163 | | void ForEach( const SwNode& rStart, const SwNode& rEnd, |
164 | | FnForEach_SwNodes fnForEach, void* pArgs ); |
165 | | void ForEach( const SwNodeIndex& rStart, const SwNodeIndex& rEnd, |
166 | | FnForEach_SwNodes fnForEach, void* pArgs ); |
167 | | |
168 | | /// A still empty section. |
169 | 70.0k | SwNode& GetEndOfPostIts() const { return *m_pEndOfPostIts; } |
170 | | /// Section for all footnotes. |
171 | 399k | SwNode& GetEndOfInserts() const { return *m_pEndOfInserts; } |
172 | | /// Section for all Flys/Header/Footers. |
173 | 2.16M | SwNode& GetEndOfAutotext() const { return *m_pEndOfAutotext; } |
174 | | /// Section for all Redlines. |
175 | 2.35M | SwNode& GetEndOfRedlines() const { return *m_pEndOfRedlines; } |
176 | | /** This is the last EndNode of a special section. After it |
177 | | there is only the regular ContentSection (i.e. the BodyText). */ |
178 | 3.10M | SwNode& GetEndOfExtras() const { return *m_pEndOfRedlines; } |
179 | | /// Regular ContentSection (i.e. the BodyText). |
180 | 6.87M | SwNode& GetEndOfContent() const { return *m_pEndOfContent; } |
181 | | |
182 | | /** Is the NodesArray the regular one of Doc? (and not the UndoNds, ...) |
183 | | Implementation in doc.hxx (because one needs to know Doc for it) ! */ |
184 | | SW_DLLPUBLIC bool IsDocNodes() const; |
185 | | |
186 | | static sal_uInt16 GetSectionLevel(const SwNode &rIndex); |
187 | | void Delete(const SwNodeIndex &rPos, SwNodeOffset nNodes = SwNodeOffset(1)); |
188 | | void Delete(const SwNode& rPos, SwNodeOffset nNodes = SwNodeOffset(1)); |
189 | | |
190 | | bool MoveNodes( const SwNodeRange&, SwNodes& rNodes, SwNode& rPos, |
191 | | bool bNewFrames = true ); |
192 | | void MoveRange( SwPaM&, SwPosition&, SwNodes& rNodes ); |
193 | | |
194 | | void Copy_( const SwNodeRange& rRg, SwNode& rInsPos, |
195 | | bool bNewFrames = true ) const |
196 | 127k | { CopyNodes( rRg, rInsPos, bNewFrames ); } |
197 | | |
198 | | void SectionUp( SwNodeRange *); |
199 | | void SectionDown( SwNodeRange *pRange, SwStartNodeType = SwNormalStartNode ); |
200 | | |
201 | | static void GoStartOfSection(SwNodeIndex *); |
202 | | static void GoEndOfSection(SwNodeIndex *); |
203 | | |
204 | | SW_DLLPUBLIC static SwContentNode* GoNext(SwNodeIndex*); |
205 | | static SwContentNode* GoNext(SwPosition*); |
206 | | static SwContentNode* GoPrevious(SwNodeIndex *, bool canCrossBoundary = false); |
207 | | static SwContentNode* GoPrevious(SwPosition *, bool canCrossBoundary = false); |
208 | | |
209 | | /** Go to next content-node that is not protected or hidden |
210 | | (Both set FALSE ==> GoNext/GoPrevious!!!). */ |
211 | | static SwContentNode* GoNextSection( SwNodeIndex *, bool bSkipHidden = true, |
212 | | bool bSkipProtect = true ); |
213 | | static SwContentNode* GoNextSection( SwPosition *, bool bSkipHidden = true, |
214 | | bool bSkipProtect = true ); |
215 | | // canCrossBoundary allows moving out of the current global section (fly / header / footer / |
216 | | // footnote / redlines / content). |
217 | | SW_DLLPUBLIC static SwContentNode* GoPrevSection( SwNodeIndex *, bool bSkipHidden = true, |
218 | | bool bSkipProtect = true, bool canCrossBoundary = false ); |
219 | | static SwContentNode* GoPrevSection( SwPosition *, bool bSkipHidden = true, |
220 | | bool bSkipProtect = true, bool canCrossBoundary = false ); |
221 | | |
222 | | /** Create an empty section of Start- and EndNode. It may be called |
223 | | only if a new section with content is to be created, |
224 | | e.g. at filters/Undo/... */ |
225 | | static SwStartNode* MakeEmptySection( const SwNode& rWhere, |
226 | | SwStartNodeType = SwNormalStartNode ); |
227 | | |
228 | | /// Implementations of "Make...Node" are in the given .cxx-files. |
229 | | SW_DLLPUBLIC SwTextNode *MakeTextNode( const SwNode& rWhere, |
230 | | SwTextFormatColl *pColl, |
231 | | bool bNewFrames = true); ///< in ndtxt.cxx |
232 | | SW_DLLPUBLIC SwStartNode* MakeTextSection( const SwNode & rWhere, |
233 | | SwStartNodeType eSttNdTyp, |
234 | | SwTextFormatColl *pColl ); |
235 | | |
236 | | static SwGrfNode *MakeGrfNode( const SwNode& rWhere, |
237 | | const OUString& rGrfName, |
238 | | const OUString& rFltName, |
239 | | const Graphic* pGraphic, |
240 | | SwGrfFormatColl *pColl, |
241 | | SwAttrSet const * pAutoAttr = nullptr ); ///< in ndgrf.cxx |
242 | | |
243 | | SwOLENode *MakeOLENode( const SwNode& rWhere, |
244 | | const svt::EmbeddedObjectRef&, |
245 | | SwGrfFormatColl *pColl ); ///< in ndole.cxx |
246 | | SwOLENode *MakeOLENode( const SwNode& rWhere, |
247 | | const OUString &rName, |
248 | | sal_Int64 nAspect, |
249 | | SwGrfFormatColl *pColl, |
250 | | SwAttrSet const * pAutoAttr ); ///< in ndole.cxx |
251 | | |
252 | | /// Array of all OutlineNodes. |
253 | 27.6k | const SwOutlineNodes& GetOutLineNds() const { return m_aOutlineNodes;} |
254 | | |
255 | | /// Update all Nodes - Rule/Format-Change. |
256 | | void UpdateOutlineNode(SwNode & rNd); |
257 | | |
258 | | /** Insert nodes for tables. If Lines is given, create the matrix |
259 | | from lines and boxes, else only the count of boxes. |
260 | | |
261 | | New parameter pAttrSet: If pAttrSet is non-null and contains an |
262 | | adjust item it is propagated to the table cells. If there is an |
263 | | adjust in pContentTextColl or pHeadlineTextColl this adjust item |
264 | | overrides the item in pAttrSet. */ |
265 | | |
266 | | static SwTableNode* InsertTable( const SwNode& rNd, |
267 | | sal_uInt16 nBoxes, SwTextFormatColl* pContentTextColl, |
268 | | sal_uInt16 nLines, sal_uInt16 nRepeat, |
269 | | SwTextFormatColl* pHeadlineTextColl, |
270 | | const SwAttrSet * pAttrSet); |
271 | | |
272 | | /// Create balanced table from selected range. |
273 | | /// @param nCols number of additional empty columns to append (tdf#167632) |
274 | | SwTableNode* TextToTable( const SwNodeRange& rRange, sal_Unicode cCh, |
275 | | SwTableFormat* pTableFormat, |
276 | | SwTableLineFormat* pLineFormat, |
277 | | SwTableBoxFormat* pBoxFormat, |
278 | | SwTextFormatColl* pTextColl, |
279 | | SwUndoTextToTable* pUndo, |
280 | | sal_uInt16 nCols = 0 ); |
281 | | |
282 | | void ExpandRangeForTableBox(const SwNodeRange & rRange, |
283 | | std::optional<SwNodeRange>& rExpandedRange); |
284 | | |
285 | | /// create a table from a vector of NodeRanges - API support |
286 | | SwTableNode* TextToTable( const TableRanges_t& rTableNodes, |
287 | | SwTableFormat* pTableFormat, |
288 | | SwTableLineFormat* pLineFormat, |
289 | | SwTableBoxFormat* pBoxFormat ); |
290 | | |
291 | | /// Create regular text from what was table. |
292 | | bool TableToText( const SwNodeRange& rRange, sal_Unicode cCh, |
293 | | SwUndoTableToText* ); |
294 | | /// Is in untbl.cxx and may be called only by Undo-object. |
295 | | SwTableNode* UndoTableToText( SwNodeOffset nStt, SwNodeOffset nEnd, |
296 | | const SwTableToTextSaves& rSavedData ); |
297 | | |
298 | | /** Insert a new box in the line before InsPos. Its format |
299 | | is taken from the following one (or from the previous one if we are |
300 | | at the end). In the line there must be a box already. */ |
301 | | SW_DLLPUBLIC bool InsBoxen( SwTableNode*, SwTableLine*, SwTableBoxFormat*, |
302 | | /// Formats for TextNode of box. |
303 | | SwTextFormatColl*, const SfxItemSet* pAutoAttr, |
304 | | sal_uInt16 nInsPos, sal_uInt16 nCnt = 1 ); |
305 | | /** Splits a table at the base-line which contains the index. |
306 | | All base lines behind it are moved to a new table/ -node. |
307 | | If the flag bCalcNewSize is set to TRUE, the new SSize for both |
308 | | tables is calculated from the Maximum of the boxes, provided |
309 | | SSize is set "absolute" (LONG_MAX). |
310 | | */ |
311 | | SwTableNode* SplitTable( SwNode& rPos, bool bAfter = true, |
312 | | bool bCalcNewSize = false ); |
313 | | void SplitFloatingTableFrame(SwTableNode & rNewTableNode, |
314 | | ::std::tuple<SwStartNode &, SwFrameFormat &, SwTextNode &> floatingFrame); |
315 | | /// Two Tables that are following one another are merged. |
316 | | bool MergeTable( SwNode& rPos, bool bWithPrev = true ); |
317 | | void MergeFloatingTableFrame(SwNodeOffset nEndOfOldFlyIndex); |
318 | | |
319 | | /// Insert a new SwSection. |
320 | | SwSectionNode* InsertTextSection(SwNode& rNd, |
321 | | SwSectionFormat& rSectionFormat, |
322 | | SwSectionData const&, |
323 | | SwTOXBase const*const pTOXBase, |
324 | | SwNode const * pEndNd, |
325 | | bool const bInsAtStart = true, |
326 | | bool const bCreateFrames = true); |
327 | | |
328 | | /// Which Doc contains the nodes-array? |
329 | 179M | SwDoc& GetDoc() { return m_rMyDoc; } |
330 | 85.5M | const SwDoc& GetDoc() const { return m_rMyDoc; } |
331 | | |
332 | | /** Search previous / next content node or table node with frames. |
333 | | Search is started backward with the one before rFrameNd and |
334 | | forward after pEnd. |
335 | | If no valid node is found, return nullptr. **/ |
336 | | SwNode* FindPrvNxtFrameNode( const SwNode& rFrameNd, |
337 | | const SwNode* pEnd, |
338 | | SwRootFrame const* pLayout = nullptr) const; |
339 | | |
340 | | SwNode * DocumentSectionStartNode(SwNode * pNode) const; |
341 | | SwNode * DocumentSectionEndNode(SwNode * pNode) const; |
342 | | |
343 | | /** |
344 | | * Dumps the entire nodes structure to the given destination (file nodes.xml in the current directory by default) |
345 | | */ |
346 | | void dumpAsXml( xmlTextWriterPtr pWriter ) const; |
347 | | }; |
348 | | |
349 | | |
350 | | #endif |
351 | | |
352 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |