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 #ifndef INCLUDED_SW_INC_DOCARY_HXX
20 #define INCLUDED_SW_INC_DOCARY_HXX
21 
22 #include <vector>
23 #include <type_traits>
24 #include <o3tl/sorted_vector.hxx>
25 
26 #include <boost/multi_index_container.hpp>
27 #include <boost/multi_index/composite_key.hpp>
28 #include <boost/multi_index/identity.hpp>
29 #include <boost/multi_index/mem_fun.hpp>
30 #include <boost/multi_index/ordered_index.hpp>
31 #include <boost/multi_index/random_access_index.hpp>
32 
33 #include "fmtcol.hxx"
34 #include "frmfmt.hxx"
35 #include "section.hxx"
36 #include "tox.hxx"
37 #include "numrule.hxx"
38 #include "fldbas.hxx"
39 
40 class SwRangeRedline;
41 class SwExtraRedline;
42 class SwOLENode;
43 class SwTable;
44 class SwTableLine;
45 class SwTableBox;
46 struct SwPosition;
47 enum class RedlineType : sal_uInt16;
48 
49 /** provides some methods for generic operations on lists that contain SwFormat* subclasses. */
50 class SwFormatsBase
51 {
52 public:
53     virtual size_t GetFormatCount() const = 0;
54     virtual SwFormat* GetFormat(size_t idx) const = 0;
~SwFormatsBase()55     virtual ~SwFormatsBase() {};
56 
57     SwFormatsBase() = default;
58     SwFormatsBase(SwFormatsBase const &) = default;
59     SwFormatsBase(SwFormatsBase &&) = default;
60     SwFormatsBase & operator =(SwFormatsBase const &) = default;
61     SwFormatsBase & operator =(SwFormatsBase &&) = default;
62 };
63 
64 template<typename Value>
65 class SwVectorModifyBase
66 {
67 public:
68     typedef typename std::vector<Value>::iterator iterator;
69     typedef typename std::vector<Value>::const_iterator const_iterator;
70     typedef typename std::vector<Value>::size_type size_type;
71     typedef typename std::vector<Value>::value_type value_type;
72 
73 protected:
74     enum class DestructorPolicy {
75         KeepElements,
76         FreeElements,
77     };
78 
79 private:
80     typename std::vector<Value> mvVals;
81     const DestructorPolicy mPolicy;
82 
83 protected:
84     // default destructor deletes all contained elements
SwVectorModifyBase(DestructorPolicy policy=DestructorPolicy::FreeElements)85     SwVectorModifyBase(DestructorPolicy policy = DestructorPolicy::FreeElements)
86         : mPolicy(policy) {}
87 
88 public:
empty() const89     bool empty() const { return mvVals.empty(); }
front() const90     Value const& front() const { return mvVals.front(); }
size() const91     size_t size() const { return mvVals.size(); }
begin()92     iterator begin() { return mvVals.begin(); }
begin() const93     const_iterator begin() const { return mvVals.begin(); }
end()94     iterator end() { return mvVals.end(); }
end() const95     const_iterator end() const { return mvVals.end(); }
clear()96     void clear() { mvVals.clear(); }
erase(iterator aIt)97     iterator erase(iterator aIt) { return mvVals.erase(aIt); }
erase(iterator aFirst,iterator aLast)98     iterator erase(iterator aFirst, iterator aLast) { return mvVals.erase(aFirst, aLast); }
insert(iterator aIt,Value const & rVal)99     iterator insert(iterator aIt, Value const& rVal) { return mvVals.insert(aIt, rVal); }
100     template<typename TInputIterator>
insert(iterator aIt,TInputIterator aFirst,TInputIterator aLast)101     void insert(iterator aIt, TInputIterator aFirst, TInputIterator aLast)
102     {
103         mvVals.insert(aIt, aFirst, aLast);
104     }
push_back(Value const & rVal)105     void push_back(Value const& rVal) { mvVals.push_back(rVal); }
reserve(size_type nSize)106     void reserve(size_type nSize) { mvVals.reserve(nSize); }
at(size_type nPos) const107     Value const& at(size_type nPos) const { return mvVals.at(nPos); }
operator [](size_type nPos) const108     Value const& operator[](size_type nPos) const { return mvVals[nPos]; }
operator [](size_type nPos)109     Value& operator[](size_type nPos) { return mvVals[nPos]; }
110 
111     // free any remaining child objects based on mPolicy
~SwVectorModifyBase()112     virtual ~SwVectorModifyBase()
113     {
114         if (mPolicy == DestructorPolicy::FreeElements)
115             for(const_iterator it = begin(); it != end(); ++it)
116                 delete *it;
117     }
118 
119     //TODO: These functions are apparently brittle (but the copy functions are actually used by the
120     // code; the move functions will be implicitly-defined as deleted anyway) and should probably
121     // only be used with DestructorPolicy::KeepELements:
122     SwVectorModifyBase(SwVectorModifyBase const &) = default;
123     SwVectorModifyBase(SwVectorModifyBase &&) = default;
124     SwVectorModifyBase & operator =(SwVectorModifyBase const &) = default;
125     SwVectorModifyBase & operator =(SwVectorModifyBase &&) = default;
126 
DeleteAndDestroy(int aStartIdx,int aEndIdx)127     void DeleteAndDestroy(int aStartIdx, int aEndIdx)
128     {
129         if (aEndIdx < aStartIdx)
130             return;
131         for (const_iterator it = begin() + aStartIdx;
132                             it != begin() + aEndIdx; ++it)
133             delete *it;
134         erase( begin() + aStartIdx, begin() + aEndIdx);
135     }
136 
GetPos(Value const & p) const137     size_t GetPos(Value const& p) const
138     {
139         const_iterator const it = std::find(begin(), end(), p);
140         return it == end() ? SIZE_MAX : it - begin();
141     }
142 
143     /// check that given format is still alive (i.e. contained here)
IsAlive(typename std::remove_pointer<Value>::type const * const p) const144     bool IsAlive(typename std::remove_pointer<Value>::type const*const p) const
145         { return std::find(begin(), end(), p) != end(); }
146 
dumpAsXml(xmlTextWriterPtr)147     static void dumpAsXml(xmlTextWriterPtr /*pWriter*/) {};
148 };
149 
150 template<typename Value>
151 class SwFormatsModifyBase : public SwVectorModifyBase<Value>, public SwFormatsBase
152 {
153 protected:
SwFormatsModifyBase(typename SwVectorModifyBase<Value>::DestructorPolicy policy=SwVectorModifyBase<Value>::DestructorPolicy::FreeElements)154     SwFormatsModifyBase(typename SwVectorModifyBase<Value>::DestructorPolicy
155             policy = SwVectorModifyBase<Value>::DestructorPolicy::FreeElements)
156         : SwVectorModifyBase<Value>(policy) {}
157 
158 public:
GetFormatCount() const159     virtual size_t GetFormatCount() const override
160         { return SwVectorModifyBase<Value>::size(); }
161 
GetFormat(size_t idx) const162     virtual Value GetFormat(size_t idx) const override
163         { return SwVectorModifyBase<Value>::operator[](idx); }
164 
GetPos(const SwFormat * p) const165     size_t GetPos(const SwFormat *p) const
166         { return SwVectorModifyBase<Value>::GetPos( static_cast<Value>( const_cast<SwFormat*>( p ) ) ); }
167 
168     /// check if given format is contained here
169     /// @precond pFormat must not have been deleted
ContainsFormat(SwFormat const * const pFormat) const170     bool ContainsFormat(SwFormat const*const pFormat) const {
171         Value p = dynamic_cast<Value>(const_cast<SwFormat*>(pFormat));
172         return p != nullptr && SwVectorModifyBase<Value>::IsAlive(p);
173     }
174 };
175 
176 class SwGrfFormatColls final : public SwFormatsModifyBase<SwGrfFormatColl*>
177 {
178 public:
SwGrfFormatColls()179     SwGrfFormatColls() : SwFormatsModifyBase( DestructorPolicy::KeepElements ) {}
180 };
181 
182 // Like o3tl::find_partialorder_ptrequals
183 // We don't allow duplicated object entries!
184 struct type_name_key:boost::multi_index::composite_key<
185     SwFrameFormat*,
186     boost::multi_index::const_mem_fun<SwFormat,sal_uInt16,&SwFormat::Which>,
187     boost::multi_index::const_mem_fun<SwFormat,const OUString&,&SwFormat::GetName>,
188     boost::multi_index::identity<SwFrameFormat*> // the actual object pointer
189 >{};
190 
191 typedef boost::multi_index_container<
192         SwFrameFormat*,
193         boost::multi_index::indexed_by<
194             boost::multi_index::random_access<>,
195             boost::multi_index::ordered_unique< type_name_key >
196         >
197     >
198     SwFrameFormatsBase;
199 
200 /// Specific frame formats (frames, DrawObjects).
201 class SW_DLLPUBLIC SwFrameFormats : public SwFormatsBase
202 {
203     // function updating ByName index via modify
204     friend void SwFrameFormat::SetName( const OUString&, bool );
205 
206     typedef SwFrameFormatsBase::nth_index<0>::type ByPos;
207     typedef SwFrameFormatsBase::nth_index<1>::type ByTypeAndName;
208     typedef ByPos::iterator iterator;
209 
210     SwFrameFormatsBase   m_Array;
211     ByPos               &m_PosIndex;
212     ByTypeAndName       &m_TypeAndNameIndex;
213 
214 public:
215     typedef ByPos::const_iterator const_iterator;
216     typedef ByTypeAndName::const_iterator const_range_iterator;
217     typedef SwFrameFormatsBase::size_type size_type;
218     typedef SwFrameFormatsBase::value_type value_type;
219 
220     SwFrameFormats();
221     // frees all SwFrameFormat!
222     virtual ~SwFrameFormats() override;
223 
empty() const224     bool empty()  const { return m_Array.empty(); }
size() const225     size_t size() const { return m_Array.size(); }
226 
227     // Only fails, if you try to insert the same object twice
228     std::pair<const_iterator,bool> push_back( const value_type& x );
229 
230     // This will try to remove the exact object!
231     bool erase( const value_type& x );
232     void erase( size_type index );
233     void erase( const_iterator const& position );
234 
235     // Get the iterator of the exact object (includes pointer!),
236     // e.g for position with std::distance.
237     // There is also ContainsFormat, if you don't need the position.
238     const_iterator find( const value_type& x ) const;
239 
240     // As this array is non-unique related to type and name,
241     // we always get ranges for the "key" values.
242     std::pair<const_range_iterator,const_range_iterator>
243         rangeFind( sal_uInt16 type, const OUString& name ) const;
244     // Convenience function, which just uses type and name!
245     // To look for the exact object use find.
246     std::pair<const_range_iterator,const_range_iterator>
247         rangeFind( const value_type& x ) const;
248     // So we can actually check for end()
rangeEnd() const249     const_range_iterator rangeEnd() const { return m_TypeAndNameIndex.end(); }
rangeProject(const_range_iterator const & position)250     const_iterator rangeProject( const_range_iterator const& position )
251         { return m_Array.project<0>( position ); }
252 
operator [](size_t index_) const253     const value_type& operator[]( size_t index_ ) const
254         { return m_PosIndex.operator[]( index_ ); }
front() const255     const value_type& front() const { return m_PosIndex.front(); }
back() const256     const value_type& back() const { return m_PosIndex.back(); }
begin() const257     const_iterator begin() const { return m_PosIndex.begin(); }
end() const258     const_iterator end() const { return m_PosIndex.end(); }
259 
260     void dumpAsXml(xmlTextWriterPtr pWriter, const char* pName) const;
261 
GetFormatCount() const262     virtual size_t GetFormatCount() const override { return m_Array.size(); }
GetFormat(size_t idx) const263     virtual SwFormat* GetFormat(size_t idx) const override { return operator[]( idx ); }
264 
265     /// fast check if given format is contained here
266     /// @precond pFormat must not have been deleted
267     bool ContainsFormat(SwFrameFormat const& rFormat) const;
268     /// not so fast check that given format is still alive (i.e. contained here)
269     bool IsAlive(SwFrameFormat const*) const;
270 
271     void DeleteAndDestroyAll( bool keepDefault = false );
272 
273     bool newDefault( const value_type& x );
274     void newDefault( const_iterator const& position );
275 };
276 
277 
278 /// Unsorted, undeleting SwFrameFormat vector
279 class SwFrameFormatsV final : public SwFormatsModifyBase<SwFrameFormat*>
280 {
281 public:
SwFrameFormatsV()282     SwFrameFormatsV() : SwFormatsModifyBase( DestructorPolicy::KeepElements ) {}
283 };
284 
285 class SwCharFormats final : public SwFormatsModifyBase<SwCharFormat*>
286 {
287 public:
288     void dumpAsXml(xmlTextWriterPtr pWriter) const;
289 };
290 
291 class SwTextFormatColls final : public SwFormatsModifyBase<SwTextFormatColl*>
292 {
293 public:
SwTextFormatColls()294     SwTextFormatColls() : SwFormatsModifyBase( DestructorPolicy::KeepElements ) {}
295     void dumpAsXml(xmlTextWriterPtr pWriter) const;
296 };
297 
298 /// Array of Undo-history.
299 class SwSectionFormats final : public SwFormatsModifyBase<SwSectionFormat*>
300 {
301 public:
302     void dumpAsXml(xmlTextWriterPtr pWriter) const;
303 };
304 
305 class SwFieldTypes : public std::vector<std::unique_ptr<SwFieldType>> {
306 public:
307     void dumpAsXml(xmlTextWriterPtr pWriter) const;
308 };
309 
310 class SwTOXTypes : public std::vector<std::unique_ptr<SwTOXType>> {};
311 
312 class SwNumRuleTable final : public SwVectorModifyBase<SwNumRule*> {
313 public:
314     void dumpAsXml(xmlTextWriterPtr pWriter) const;
315 };
316 
317 struct CompareSwRedlineTable
318 {
319     bool operator()(SwRangeRedline* const &lhs, SwRangeRedline* const &rhs) const;
320 };
321 
322 // Notification type for notifying about redlines to LOK clients
323 enum class RedlineNotification { Add, Remove, Modify };
324 
325 class SwRedlineTable
326 {
327 public:
328     typedef o3tl::sorted_vector<SwRangeRedline*, CompareSwRedlineTable,
329                 o3tl::find_partialorder_ptrequals> vector_type;
330     typedef vector_type::size_type size_type;
331     static constexpr size_type npos = SAL_MAX_INT32;
332 private:
333     vector_type maVector;
334 public:
335     ~SwRedlineTable();
Contains(const SwRangeRedline * p) const336     bool Contains(const SwRangeRedline* p) const { return maVector.find(const_cast<SwRangeRedline*>(p)) != maVector.end(); }
337     size_type GetPos(const SwRangeRedline* p) const;
338 
339     bool Insert(SwRangeRedline*& p);
340     bool Insert(SwRangeRedline*& p, size_type& rInsPos);
341     bool InsertWithValidRanges(SwRangeRedline*& p, size_type* pInsPos = nullptr);
342 
343     void Remove( size_type nPos );
344     void Remove( const SwRangeRedline* p );
345     void DeleteAndDestroy(size_type nPos);
346     void DeleteAndDestroyAll();
347 
348     void dumpAsXml(xmlTextWriterPtr pWriter) const;
349 
350     size_type FindNextOfSeqNo( size_type nSttPos ) const;
351     size_type FindPrevOfSeqNo( size_type nSttPos ) const;
352     /** Search next or previous Redline with the same Seq. No.
353        Search can be restricted via Lookahead.
354        Using 0 makes search the whole array. */
355     size_type FindNextSeqNo( sal_uInt16 nSeqNo, size_type nSttPos ) const;
356     size_type FindPrevSeqNo( sal_uInt16 nSeqNo, size_type nSttPos ) const;
357 
358     /**
359      Find the redline at the given position.
360 
361      @param tableIndex position in SwRedlineTable to start searching at, will be updated with the index of the returned
362                        redline (or the next redline after the given position if not found)
363      @param next true: redline starts at position and ends after, false: redline starts before position and ends at or after
364     */
365     const SwRangeRedline* FindAtPosition( const SwPosition& startPosition, size_type& tableIndex, bool next = true ) const;
366 
empty() const367     bool                        empty() const { return maVector.empty(); }
size() const368     size_type                   size() const { return maVector.size(); }
operator [](size_type idx) const369     SwRangeRedline*             operator[]( size_type idx ) const { return maVector[idx]; }
begin() const370     vector_type::const_iterator begin() const { return maVector.begin(); }
end() const371     vector_type::const_iterator end() const { return maVector.end(); }
Resort()372     void                        Resort() { maVector.Resort(); }
373 
374     // Notifies all LOK clients when redlines are added/modified/removed
375     static void                 LOKRedlineNotification(RedlineNotification eType, SwRangeRedline* pRedline);
376 };
377 
378 /// Table that holds 'extra' redlines, such as 'table row insert/delete', 'paragraph moves' etc...
379 class SwExtraRedlineTable
380 {
381 private:
382     std::vector<SwExtraRedline*>    m_aExtraRedlines;
383 
384 public:
385     ~SwExtraRedlineTable();
386 
387     void Insert( SwExtraRedline* p );
388 
389     void DeleteAndDestroy( sal_uInt16 nPos);
390     void DeleteAndDestroyAll();
391 
392     void dumpAsXml(xmlTextWriterPtr pWriter) const;
393 
GetSize() const394     sal_uInt16 GetSize() const                              {     return m_aExtraRedlines.size();                }
GetRedline(sal_uInt16 uIndex) const395     SwExtraRedline* GetRedline( sal_uInt16 uIndex ) const   {     return m_aExtraRedlines.operator[]( uIndex );  }
396 
397     SW_DLLPUBLIC bool DeleteAllTableRedlines( SwDoc* pDoc, const SwTable& rTable, bool bSaveInUndo, RedlineType nRedlineTypeToDelete );
398     bool DeleteTableRowRedline ( SwDoc* pDoc, const SwTableLine& rTableLine, bool bSaveInUndo, RedlineType nRedlineTypeToDelete );
399     bool DeleteTableCellRedline( SwDoc* pDoc, const SwTableBox& rTableBox, bool bSaveInUndo, RedlineType nRedlineTypeToDelete );
400 };
401 
402 typedef std::vector<SwOLENode*> SwOLENodes;
403 
404 #endif // INCLUDED_SW_INC_DOCARY_HXX
405 
406 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
407