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