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_NDHINTS_HXX
20 #define INCLUDED_SW_INC_NDHINTS_HXX
21 
22 #include "swtypes.hxx"
23 
24 class SwTextNode;
25 class SwRegHistory;                 // Is in RolBck.hxx.
26 class SwTextAttr;
27 class SwTextAttrNesting;
28 
29 class SfxPoolItem;
30 class SfxItemSet;
31 class SwDoc;
32 
33 enum class CopyOrNewType { Copy, New };
34 
35 /// if COPY then pTextNode must be given!
36 SwTextAttr * MakeTextAttr(
37     SwDoc & rDoc,
38     SfxPoolItem & rNew,
39     sal_Int32 const nStt,
40     sal_Int32 const nEnd,
41     CopyOrNewType const bIsCopy = CopyOrNewType::New,
42     SwTextNode *const pTextNode = nullptr );
43 
44 SwTextAttr * MakeTextAttr(
45     SwDoc & rDoc,
46     const SfxItemSet & rSet,
47     sal_Int32 nStt,
48     sal_Int32 nEnd );
49 
50 /// create redline dummy text hint that must not be inserted into hints array
51 SwTextAttr* MakeRedlineTextAttr(
52     SwDoc & rDoc,
53     SfxPoolItem const & rAttr );
54 
55 struct CompareSwpHtEnd
56 {
57     bool operator()( sal_Int32 nEndPos, const SwTextAttr* rhs ) const;
58     bool operator()( const SwTextAttr* lhs, const SwTextAttr* rhs ) const;
59 };
60 struct CompareSwpHtWhichStart
61 {
62     bool operator()( const SwTextAttr* lhs, const sal_uInt16 nWhich ) const;
63     bool operator()( const SwTextAttr* lhs, const SwTextAttr* rhs ) const;
64 };
65 
66 /// An SwTextAttr container, stores all directly formatted text portions for a text node.
67 class SwpHints
68 {
69 private:
70     const SwTextNode& m_rParent;
71 
72     // SAL_MAX_SIZE is used by GetStartOf to return
73     // failure, so just allow SAL_MAX_SIZE-1 hints
74     static const size_t MAX_HINTS = SAL_MAX_SIZE-1;
75 
76     std::vector<SwTextAttr*> m_HintsByStart;
77     std::vector<SwTextAttr*> m_HintsByEnd;
78     std::vector<SwTextAttr*> m_HintsByWhichAndStart;
79 
80     SwRegHistory* m_pHistory;                   ///< for Undo
81 
82     /// true: the Node is in Split and Frames are moved
83     bool          m_bInSplitNode         : 1;
84     // m_bHiddenByParaField is invalid, call CalcHiddenParaField()
85     mutable bool  m_bCalcHiddenParaField : 1;
86     // if all fields controlling visibility of the paragraph require to hide it
87     // (if there's no such fields, or if any field requires to show, then this is false)
88     mutable bool  m_bHiddenByParaField   : 1;
89     bool          m_bFootnote            : 1;   ///< footnotes
90     bool          m_bDDEFields           : 1;   ///< the TextNode has DDE fields
91     // Sort on demand to avoid O(n^2) behaviour
92     mutable bool  m_bStartMapNeedsSorting : 1;
93     mutable bool  m_bEndMapNeedsSorting : 1;
94     mutable bool  m_bWhichMapNeedsSorting : 1;
95 
96     /// records a new attribute in m_pHistory.
97     void NoteInHistory( SwTextAttr *pAttr, const bool bNew = false );
98 
99     void CalcFlags( );
100 
101     /** Delete methods may only be called by the TextNode!
102        Because the TextNode also guarantees removal of the Character for
103        attributes without an end. */
104     friend class SwTextNode;
105     void DeleteAtPos( size_t nPos );
106     /// Delete the given Hint. The Hint must actually be in the array!
107     void Delete( SwTextAttr const * pTextHt );
108 
SetInSplitNode(bool bInSplit)109     void SetInSplitNode(bool bInSplit) { m_bInSplitNode = bInSplit; }
SetCalcHiddenParaField() const110     void SetCalcHiddenParaField() const { m_bCalcHiddenParaField = true; }
SetHiddenByParaField(const bool bNew) const111     void SetHiddenByParaField( const bool bNew ) const { m_bHiddenByParaField = bNew; }
IsHiddenByParaField() const112     bool IsHiddenByParaField() const
113     {
114         if ( m_bCalcHiddenParaField )
115         {
116             CalcHiddenParaField();
117         }
118         return m_bHiddenByParaField;
119     }
120 
121     void InsertNesting(SwTextAttrNesting & rNewHint);
122     bool TryInsertNesting(SwTextNode & rNode, SwTextAttrNesting & rNewHint);
123     void BuildPortions( SwTextNode& rNode, SwTextAttr& rNewHint,
124             const SetAttrMode nMode );
125     bool MergePortions( SwTextNode& rNode );
126 
127     void Insert(SwTextAttr* pHt);
128     SW_DLLPUBLIC void Resort() const;
129     SW_DLLPUBLIC void ResortStartMap() const;
130     SW_DLLPUBLIC void ResortEndMap() const;
131     SW_DLLPUBLIC void ResortWhichMap() const;
132 
133     size_t GetIndexOf( const SwTextAttr *pHt ) const;
134 
135 #ifdef DBG_UTIL
136     bool Check(bool) const;
137 #endif
138 
139 public:
140     SwpHints(const SwTextNode& rParent);
141 
Count() const142     size_t Count() const { return m_HintsByStart.size(); }
143     bool Contains( const SwTextAttr *pHt ) const;
Get(size_t nPos) const144     SwTextAttr * Get( size_t nPos ) const
145     {
146         assert( !(nPos != 0 && m_bStartMapNeedsSorting) && "going to trigger a resort in the middle of an iteration, that's bad" );
147         if (m_bStartMapNeedsSorting)
148             ResortStartMap();
149         return m_HintsByStart[nPos];
150     }
151     // Get without triggering resorting - useful if we are modifying start/end pos while iterating
GetWithoutResorting(size_t nPos) const152     SwTextAttr * GetWithoutResorting( size_t nPos ) const
153     {
154         return m_HintsByStart[nPos];
155     }
156 
157     int GetLastPosSortedByEnd(sal_Int32 nEndPos) const;
GetSortedByEnd(size_t nPos) const158     SwTextAttr * GetSortedByEnd( size_t nPos ) const
159     {
160         assert( !(nPos != 0 && m_bEndMapNeedsSorting) && "going to trigger a resort in the middle of an iteration, that's bad" );
161         if (m_bEndMapNeedsSorting)
162             ResortEndMap();
163         return m_HintsByEnd[nPos];
164     }
165 
166     size_t GetFirstPosSortedByWhichAndStart(sal_uInt16 nWhich) const;
GetSortedByWhichAndStart(size_t nPos) const167     SwTextAttr * GetSortedByWhichAndStart( size_t nPos ) const
168     {
169         assert( !(nPos != 0 && m_bWhichMapNeedsSorting) && "going to trigger a resort in the middle of an iteration, that's bad" );
170         if (m_bWhichMapNeedsSorting)
171             ResortWhichMap();
172         return m_HintsByWhichAndStart[nPos];
173     }
174 
175     /// Trigger the sorting if necessary
SortIfNeedBe() const176     void SortIfNeedBe() const
177     {
178         if (m_bStartMapNeedsSorting)
179             ResortStartMap();
180         if (m_bEndMapNeedsSorting)
181             ResortEndMap();
182         if (m_bWhichMapNeedsSorting)
183             ResortWhichMap();
184     }
Cut(const size_t nPosInStart)185     SwTextAttr * Cut( const size_t nPosInStart )
186     {
187         SwTextAttr *pHt = m_HintsByStart[nPosInStart];
188         DeleteAtPos( nPosInStart );
189         return pHt;
190     }
191 
CanBeDeleted() const192     bool CanBeDeleted() const    { return m_HintsByStart.empty(); }
193 
194     /// register a History, which receives all attribute changes (for Undo)
Register(SwRegHistory * pHist)195     void Register( SwRegHistory* pHist ) { m_pHistory = pHist; }
196     /// deregister the currently registered History
DeRegister()197     void DeRegister() { Register(nullptr); }
GetHistory() const198     SwRegHistory* GetHistory() const    { return m_pHistory; }
199 
200     /// try to insert the hint
201     /// @return true iff hint successfully inserted
202     bool TryInsertHint( SwTextAttr * const pHint, SwTextNode & rNode,
203             const SetAttrMode nMode = SetAttrMode::DEFAULT );
204 
HasFootnote() const205     bool HasFootnote() const          { return m_bFootnote; }
IsInSplitNode() const206     bool IsInSplitNode() const   { return m_bInSplitNode; }
207 
208     // calc current value of m_bHiddenByParaField, returns true iff changed
209     bool CalcHiddenParaField() const; // changes mutable state
210 
211     // Marks the hint-maps as needing sorting because the position of something has changed
StartPosChanged() const212     void StartPosChanged() const { m_bStartMapNeedsSorting = true; m_bEndMapNeedsSorting = true; m_bWhichMapNeedsSorting = true; }
EndPosChanged() const213     void EndPosChanged() const { m_bStartMapNeedsSorting = true; m_bEndMapNeedsSorting = true; m_bWhichMapNeedsSorting = true; }
214 };
215 
216 #endif
217 
218 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
219