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 .
22 #include <type_traits>
23 #include <o3tl/sorted_vector.hxx>
27 #include "section.hxx"
29 #include "numrule.hxx"
39 enum class RedlineType
: sal_uInt16
;
41 /** provides some methods for generic operations on lists that contain SwFormat* subclasses. */
42 class SW_DLLPUBLIC SwFormatsBase
45 virtual size_t GetFormatCount() const = 0;
46 virtual SwFormat
* GetFormat(size_t idx
) const = 0;
47 virtual ~SwFormatsBase();
49 // default linear search implementation, some subclasses will override with a more efficient search
50 virtual SwFormat
* FindFormatByName(const OUString
& rName
) const;
51 virtual void Rename(const SwFrameFormat
&, const OUString
&) {};
53 SwFormatsBase() = default;
54 SwFormatsBase(SwFormatsBase
const &) = default;
55 SwFormatsBase(SwFormatsBase
&&) = default;
56 SwFormatsBase
& operator =(SwFormatsBase
const &) = default;
57 SwFormatsBase
& operator =(SwFormatsBase
&&) = default;
60 template<typename Value
>
61 class SwVectorModifyBase
64 typedef typename
std::vector
<Value
>::iterator iterator
;
65 typedef typename
std::vector
<Value
>::const_iterator const_iterator
;
66 typedef typename
std::vector
<Value
>::size_type size_type
;
67 typedef typename
std::vector
<Value
>::value_type value_type
;
70 enum class DestructorPolicy
{
76 typename
std::vector
<Value
> mvVals
;
77 const DestructorPolicy mPolicy
;
80 // default destructor deletes all contained elements
81 SwVectorModifyBase(DestructorPolicy policy
= DestructorPolicy::FreeElements
)
85 bool empty() const { return mvVals
.empty(); }
86 Value
const& front() const { return mvVals
.front(); }
87 size_t size() const { return mvVals
.size(); }
88 iterator
begin() { return mvVals
.begin(); }
89 const_iterator
begin() const { return mvVals
.begin(); }
90 iterator
end() { return mvVals
.end(); }
91 const_iterator
end() const { return mvVals
.end(); }
92 void clear() { mvVals
.clear(); }
93 iterator
erase(iterator aIt
) { return mvVals
.erase(aIt
); }
94 iterator
erase(iterator aFirst
, iterator aLast
) { return mvVals
.erase(aFirst
, aLast
); }
95 iterator
insert(iterator aIt
, Value
const& rVal
) { return mvVals
.insert(aIt
, rVal
); }
96 template<typename TInputIterator
>
97 void insert(iterator aIt
, TInputIterator aFirst
, TInputIterator aLast
)
99 mvVals
.insert(aIt
, aFirst
, aLast
);
101 void push_back(Value
const& rVal
) { mvVals
.push_back(rVal
); }
102 void reserve(size_type nSize
) { mvVals
.reserve(nSize
); }
103 Value
const& at(size_type nPos
) const { return mvVals
.at(nPos
); }
104 Value
const& operator[](size_type nPos
) const { return mvVals
[nPos
]; }
105 Value
& operator[](size_type nPos
) { return mvVals
[nPos
]; }
107 // free any remaining child objects based on mPolicy
108 virtual ~SwVectorModifyBase()
110 if (mPolicy
== DestructorPolicy::FreeElements
)
111 for(const_iterator it
= begin(); it
!= end(); ++it
)
115 //TODO: These functions are apparently brittle (but the copy functions are actually used by the
116 // code; the move functions will be implicitly-defined as deleted anyway) and should probably
117 // only be used with DestructorPolicy::KeepELements:
118 SwVectorModifyBase(SwVectorModifyBase
const &) = default;
119 SwVectorModifyBase(SwVectorModifyBase
&&) = default;
120 SwVectorModifyBase
& operator =(SwVectorModifyBase
const &) = default;
121 SwVectorModifyBase
& operator =(SwVectorModifyBase
&&) = default;
123 void DeleteAndDestroy(int aStartIdx
, int aEndIdx
)
125 if (aEndIdx
< aStartIdx
)
127 for (const_iterator it
= begin() + aStartIdx
;
128 it
!= begin() + aEndIdx
; ++it
)
130 erase( begin() + aStartIdx
, begin() + aEndIdx
);
133 size_t GetPos(typename
std::remove_pointer_t
<Value
> const* const p
) const
135 const_iterator
const it
= std::find(begin(), end(), p
);
136 return it
== end() ? SIZE_MAX
: it
- begin();
139 /// check that given format is still alive (i.e. contained here)
140 bool IsAlive(typename
std::remove_pointer
<Value
>::type
const*const p
) const
141 { return std::find(begin(), end(), p
) != end(); }
143 static void dumpAsXml(xmlTextWriterPtr
/*pWriter*/) {};
146 /// Provides a generic container for Writer styles: paragraph, graphic, section, etc styles.
147 template<typename Value
>
148 class SwFormatsModifyBase
: public SwVectorModifyBase
<Value
>, public SwFormatsBase
151 SwFormatsModifyBase(typename SwVectorModifyBase
<Value
>::DestructorPolicy
152 policy
= SwVectorModifyBase
<Value
>::DestructorPolicy::FreeElements
)
153 : SwVectorModifyBase
<Value
>(policy
) {}
156 virtual size_t GetFormatCount() const override
157 { return SwVectorModifyBase
<Value
>::size(); }
159 virtual Value
GetFormat(size_t idx
) const override
160 { return SwVectorModifyBase
<Value
>::operator[](idx
); }
162 // Override return type to reduce casting
163 virtual Value
FindFormatByName(const OUString
& rName
) const override
164 { return static_cast<Value
>(SwFormatsBase::FindFormatByName(rName
)); }
167 class SwGrfFormatColls final
: public SwFormatsModifyBase
<SwGrfFormatColl
*>
170 SwGrfFormatColls() : SwFormatsModifyBase( DestructorPolicy::KeepElements
) {}
174 /// Unsorted, undeleting SwFrameFormat vector
175 class SwFrameFormatsV final
: public SwFormatsModifyBase
<SwFrameFormat
*>
178 SwFrameFormatsV() : SwFormatsModifyBase( DestructorPolicy::KeepElements
) {}
181 /// Container of paragraph styles.
182 class SwTextFormatColls final
: public SwFormatsModifyBase
<SwTextFormatColl
*>
185 SwTextFormatColls() : SwFormatsModifyBase( DestructorPolicy::KeepElements
) {}
186 void dumpAsXml(xmlTextWriterPtr pWriter
) const;
189 /// Array of Undo-history.
190 class SwSectionFormats final
: public SwFormatsModifyBase
<SwSectionFormat
*>
193 void dumpAsXml(xmlTextWriterPtr pWriter
) const;
196 class SwFieldTypes
: public std::vector
<std::unique_ptr
<SwFieldType
>> {
198 void dumpAsXml(xmlTextWriterPtr pWriter
) const;
201 class SwTOXTypes
: public std::vector
<std::unique_ptr
<SwTOXType
>> {};
203 class SwNumRuleTable final
: public SwVectorModifyBase
<SwNumRule
*> {
205 void dumpAsXml(xmlTextWriterPtr pWriter
) const;
208 struct CompareSwRedlineTable
210 bool operator()(const SwRangeRedline
* lhs
, const SwRangeRedline
* rhs
) const;
213 // Notification type for notifying about redlines to LOK clients
214 enum class RedlineNotification
{ Add
, Remove
, Modify
};
219 typedef o3tl::sorted_vector
<SwRangeRedline
*, CompareSwRedlineTable
,
220 o3tl::find_partialorder_ptrequals
> vector_type
;
221 typedef vector_type::size_type size_type
;
222 static constexpr size_type npos
= SAL_MAX_INT32
;
224 vector_type maVector
;
225 /// Sometimes we load bad data, and we need to know if we can use
226 /// fast binary search, or if we have to fall back to a linear search
227 bool m_bHasOverlappingElements
= false;
228 mutable sal_uInt32 m_nMaxMovedID
= 1; //every move-redline pair get a unique ID, so they can find each other.
229 mutable const SwRangeRedline
* mpMaxEndPos
= nullptr; // the redline with the maximum end pos
232 bool Contains(const SwRangeRedline
* p
) const { return maVector
.find(p
) != maVector
.end(); }
233 size_type
GetPos(const SwRangeRedline
* p
) const;
235 bool Insert(SwRangeRedline
*& p
);
236 bool Insert(SwRangeRedline
*& p
, size_type
& rInsPos
);
237 bool InsertWithValidRanges(SwRangeRedline
*& p
, size_type
* pInsPos
= nullptr);
238 bool HasOverlappingElements() const { return m_bHasOverlappingElements
; }
239 const SwPosition
& GetMaxEndPos() const;
241 void Remove( size_type nPos
);
242 void Remove( const SwRangeRedline
* p
);
243 void DeleteAndDestroy(size_type nPos
);
244 void DeleteAndDestroyAll();
246 void dumpAsXml(xmlTextWriterPtr pWriter
) const;
248 size_type
FindNextOfSeqNo( size_type nSttPos
) const;
249 size_type
FindPrevOfSeqNo( size_type nSttPos
) const;
250 /** Search next or previous Redline with the same Seq. No.
251 Search can be restricted via Lookahead.
252 Using 0 makes search the whole array. */
253 size_type
FindNextSeqNo( sal_uInt16 nSeqNo
, size_type nSttPos
) const;
254 size_type
FindPrevSeqNo( sal_uInt16 nSeqNo
, size_type nSttPos
) const;
257 Find the redline at the given position.
259 @param tableIndex position in SwRedlineTable to start searching at, will be updated with the index of the returned
260 redline (or the next redline after the given position if not found)
261 @param next true: redline starts at position and ends after, false: redline starts before position and ends at or after
263 const SwRangeRedline
* FindAtPosition( const SwPosition
& startPosition
, size_type
& tableIndex
, bool next
= true ) const;
264 // is there a redline with the same text content from the same author (near the redline),
265 // but with the opposite type (Insert or Delete). It's used to recognize tracked text moving.
266 bool isMoved(size_type tableIndex
) const;
267 bool isMovedImpl(size_type tableIndex
, bool bTryCombined
) const;
268 sal_uInt32
getNewMovedID() const { return ++m_nMaxMovedID
; }
269 void setMovedIDIfNeeded(sal_uInt32 nMax
);
270 void getConnectedArea(size_type nPosOrigin
, size_type
& rPosStart
, size_type
& rPosEnd
,
271 bool bCheckChilds
) const;
272 OUString
getTextOfArea(size_type rPosStart
, size_type rPosEnd
) const;
275 bool empty() const { return maVector
.empty(); }
276 size_type
size() const { return maVector
.size(); }
277 SwRangeRedline
* operator[]( size_type idx
) const { return maVector
[idx
]; }
278 vector_type::const_iterator
begin() const { return maVector
.begin(); }
279 vector_type::const_iterator
end() const { return maVector
.end(); }
280 void Resort() { maVector
.Resort(); mpMaxEndPos
= nullptr; }
282 // Notifies all LOK clients when redlines are added/modified/removed
283 static void LOKRedlineNotification(RedlineNotification eType
, SwRangeRedline
* pRedline
);
286 void CheckOverlapping(vector_type::const_iterator it
);
289 /// Table that holds 'extra' redlines, such as 'table row insert/delete', 'paragraph moves' etc...
290 class SwExtraRedlineTable
293 std::vector
<SwExtraRedline
*> m_aExtraRedlines
;
296 ~SwExtraRedlineTable();
298 void Insert( SwExtraRedline
* p
);
300 void DeleteAndDestroy( sal_uInt16 nPos
);
301 void DeleteAndDestroyAll();
303 void dumpAsXml(xmlTextWriterPtr pWriter
) const;
305 sal_uInt16
GetSize() const { return m_aExtraRedlines
.size(); }
306 SwExtraRedline
* GetRedline( sal_uInt16 uIndex
) const { return m_aExtraRedlines
.operator[]( uIndex
); }
308 SW_DLLPUBLIC
bool DeleteAllTableRedlines( SwDoc
& rDoc
, const SwTable
& rTable
, bool bSaveInUndo
, RedlineType nRedlineTypeToDelete
);
309 bool DeleteTableRowRedline ( SwDoc
* pDoc
, const SwTableLine
& rTableLine
, bool bSaveInUndo
, RedlineType nRedlineTypeToDelete
);
310 bool DeleteTableCellRedline( SwDoc
* pDoc
, const SwTableBox
& rTableBox
, bool bSaveInUndo
, RedlineType nRedlineTypeToDelete
);
313 typedef std::vector
<SwOLENode
*> SwOLENodes
;
315 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */