File: | home/maarten/src/libreoffice/core/sw/inc/ring.hxx |
Warning: | line 85, column 19 Use of memory after it is freed |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | #include <unocrsr.hxx> | |||
21 | #include <doc.hxx> | |||
22 | #include <IDocumentLayoutAccess.hxx> | |||
23 | #include <swtable.hxx> | |||
24 | #include <rootfrm.hxx> | |||
25 | ||||
26 | sw::UnoCursorHint::~UnoCursorHint() {} | |||
27 | ||||
28 | SwUnoCursor::SwUnoCursor( const SwPosition &rPos ) | |||
29 | : SwCursor( rPos, nullptr ) | |||
30 | , m_bRemainInSection(true) | |||
31 | , m_bSkipOverHiddenSections(false) | |||
32 | , m_bSkipOverProtectSections(false) | |||
33 | {} | |||
34 | ||||
35 | SwUnoCursor::~SwUnoCursor() | |||
36 | { | |||
37 | SwDoc& rDoc = GetDoc(); | |||
38 | if( !rDoc.IsInDtor() ) | |||
| ||||
39 | { | |||
40 | assert(!m_aNotifier.HasListeners())(static_cast <bool> (!m_aNotifier.HasListeners()) ? void (0) : __assert_fail ("!m_aNotifier.HasListeners()", "/home/maarten/src/libreoffice/core/sw/source/core/unocore/unocrsr.cxx" , 40, __extension__ __PRETTY_FUNCTION__)); | |||
41 | } | |||
42 | ||||
43 | // delete the whole ring | |||
44 | while( GetNext() != this ) | |||
45 | { | |||
46 | Ring* pNxt = GetNextInRing(); | |||
47 | pNxt->MoveTo(nullptr); // remove from chain | |||
48 | delete pNxt; // and delete | |||
49 | } | |||
50 | } | |||
51 | ||||
52 | bool SwUnoCursor::IsReadOnlyAvailable() const | |||
53 | { | |||
54 | return true; | |||
55 | } | |||
56 | ||||
57 | const SwContentFrame* | |||
58 | SwUnoCursor::DoSetBidiLevelLeftRight( bool &, bool, bool ) | |||
59 | { | |||
60 | return nullptr; // not for uno cursor | |||
61 | } | |||
62 | ||||
63 | void SwUnoCursor::DoSetBidiLevelUpDown() | |||
64 | { | |||
65 | // not for uno cursor | |||
66 | } | |||
67 | ||||
68 | bool SwUnoCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) | |||
69 | { | |||
70 | if (m_bRemainInSection) | |||
71 | { | |||
72 | SwDoc& rDoc = GetDoc(); | |||
73 | SwNodeIndex aOldIdx( *rDoc.GetNodes()[ GetSavePos()->nNode ] ); | |||
74 | SwNodeIndex& rPtIdx = GetPoint()->nNode; | |||
75 | SwStartNode *pOldSttNd = aOldIdx.GetNode().StartOfSectionNode(), | |||
76 | *pNewSttNd = rPtIdx.GetNode().StartOfSectionNode(); | |||
77 | if( pOldSttNd != pNewSttNd ) | |||
78 | { | |||
79 | bool bMoveDown = GetSavePos()->nNode < rPtIdx.GetIndex(); | |||
80 | bool bValidPos = false; | |||
81 | ||||
82 | // search the correct surrounded start node - which the index | |||
83 | // can't leave. | |||
84 | while( pOldSttNd->IsSectionNode() ) | |||
85 | pOldSttNd = pOldSttNd->StartOfSectionNode(); | |||
86 | ||||
87 | // is the new index inside this surrounded section? | |||
88 | if( rPtIdx > *pOldSttNd && | |||
89 | rPtIdx < pOldSttNd->EndOfSectionIndex() ) | |||
90 | { | |||
91 | // check if it a valid move inside this section | |||
92 | // (only over SwSection's !) | |||
93 | const SwStartNode* pInvalidNode; | |||
94 | do { | |||
95 | pInvalidNode = nullptr; | |||
96 | pNewSttNd = rPtIdx.GetNode().StartOfSectionNode(); | |||
97 | ||||
98 | const SwStartNode *pSttNd = pNewSttNd, *pEndNd = pOldSttNd; | |||
99 | if( pSttNd->EndOfSectionIndex() > | |||
100 | pEndNd->EndOfSectionIndex() ) | |||
101 | { | |||
102 | pEndNd = pNewSttNd; | |||
103 | pSttNd = pOldSttNd; | |||
104 | } | |||
105 | ||||
106 | while( pSttNd->GetIndex() > pEndNd->GetIndex() ) | |||
107 | { | |||
108 | if( !pSttNd->IsSectionNode() ) | |||
109 | pInvalidNode = pSttNd; | |||
110 | pSttNd = pSttNd->StartOfSectionNode(); | |||
111 | } | |||
112 | if( pInvalidNode ) | |||
113 | { | |||
114 | if( bMoveDown ) | |||
115 | { | |||
116 | rPtIdx.Assign( *pInvalidNode->EndOfSectionNode(), 1 ); | |||
117 | ||||
118 | if( !rPtIdx.GetNode().IsContentNode() && | |||
119 | ( !rDoc.GetNodes().GoNextSection( &rPtIdx ) || | |||
120 | rPtIdx > pOldSttNd->EndOfSectionIndex() ) ) | |||
121 | break; | |||
122 | } | |||
123 | else | |||
124 | { | |||
125 | rPtIdx.Assign( *pInvalidNode, -1 ); | |||
126 | ||||
127 | if( !rPtIdx.GetNode().IsContentNode() && | |||
128 | ( !SwNodes::GoPrevSection( &rPtIdx ) || | |||
129 | rPtIdx < *pOldSttNd ) ) | |||
130 | break; | |||
131 | } | |||
132 | } | |||
133 | else | |||
134 | bValidPos = true; | |||
135 | } while ( pInvalidNode ); | |||
136 | } | |||
137 | ||||
138 | if( bValidPos ) | |||
139 | { | |||
140 | SwContentNode* pCNd = GetContentNode(); | |||
141 | GetPoint()->nContent.Assign( pCNd, (pCNd && !bMoveDown) ? pCNd->Len() : 0); | |||
142 | } | |||
143 | else | |||
144 | { | |||
145 | rPtIdx = GetSavePos()->nNode; | |||
146 | GetPoint()->nContent.Assign( GetContentNode(), GetSavePos()->nContent ); | |||
147 | return true; | |||
148 | } | |||
149 | } | |||
150 | } | |||
151 | return SwCursor::IsSelOvr( eFlags ); | |||
152 | } | |||
153 | ||||
154 | SwUnoTableCursor::SwUnoTableCursor(const SwPosition& rPos) | |||
155 | : SwCursor(rPos, nullptr) | |||
156 | , SwUnoCursor(rPos) | |||
157 | , SwTableCursor(rPos) | |||
158 | , m_aTableSel(rPos, nullptr) | |||
159 | { | |||
160 | SetRemainInSection(false); | |||
161 | } | |||
162 | ||||
163 | SwUnoTableCursor::~SwUnoTableCursor() | |||
164 | { | |||
165 | while (m_aTableSel.GetNext() != &m_aTableSel) | |||
166 | delete m_aTableSel.GetNext(); | |||
167 | } | |||
168 | ||||
169 | bool SwUnoTableCursor::IsSelOvr( SwCursorSelOverFlags eFlags ) | |||
170 | { | |||
171 | bool bRet = SwUnoCursor::IsSelOvr( eFlags ); | |||
172 | if( !bRet ) | |||
173 | { | |||
174 | const SwTableNode* pTNd = GetPoint()->nNode.GetNode().FindTableNode(); | |||
175 | bRet = !(pTNd == GetDoc().GetNodes()[ GetSavePos()->nNode ]-> | |||
176 | FindTableNode() && (!HasMark() || | |||
177 | pTNd == GetMark()->nNode.GetNode().FindTableNode() )); | |||
178 | } | |||
179 | return bRet; | |||
180 | } | |||
181 | ||||
182 | void SwUnoTableCursor::MakeBoxSels() | |||
183 | { | |||
184 | const SwContentNode* pCNd; | |||
185 | bool bMakeTableCursors = true; | |||
186 | if( GetPoint()->nNode.GetIndex() && GetMark()->nNode.GetIndex() && | |||
187 | nullptr != ( pCNd = GetContentNode() ) && pCNd->getLayoutFrame( pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() ) && | |||
188 | nullptr != ( pCNd = GetContentNode(false) ) && pCNd->getLayoutFrame( pCNd->GetDoc().getIDocumentLayoutAccess().GetCurrentLayout() ) ) | |||
189 | bMakeTableCursors = GetDoc().getIDocumentLayoutAccess().GetCurrentLayout()->MakeTableCursors( *this ); | |||
190 | ||||
191 | if ( !bMakeTableCursors ) | |||
192 | { | |||
193 | SwSelBoxes const& rTmpBoxes = GetSelectedBoxes(); | |||
194 | while (!rTmpBoxes.empty()) | |||
195 | { | |||
196 | DeleteBox(0); | |||
197 | } | |||
198 | } | |||
199 | ||||
200 | if( IsChgd() ) | |||
201 | { | |||
202 | SwTableCursor::MakeBoxSels( &m_aTableSel ); | |||
203 | if (!GetSelectedBoxesCount()) | |||
204 | { | |||
205 | const SwTableBox* pBox; | |||
206 | const SwNode* pBoxNd = GetPoint()->nNode.GetNode().FindTableBoxStartNode(); | |||
207 | const SwTableNode* pTableNd = pBoxNd ? pBoxNd->FindTableNode() : nullptr; | |||
208 | if( pTableNd && nullptr != ( pBox = pTableNd->GetTable().GetTableBox( pBoxNd->GetIndex() )) ) | |||
209 | InsertBox( *pBox ); | |||
210 | } | |||
211 | } | |||
212 | } | |||
213 | ||||
214 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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_SWCRSR_HXX |
20 | #define INCLUDED_SW_INC_SWCRSR_HXX |
21 | |
22 | #include "pam.hxx" |
23 | #include "tblsel.hxx" |
24 | #include "cshtyp.hxx" |
25 | |
26 | class SfxItemSet; |
27 | struct SwCursor_SavePos; |
28 | class SvxSearchItem; |
29 | namespace i18nutil { |
30 | struct SearchOptions2; |
31 | } |
32 | |
33 | // Base structure for parameters of the find-methods. |
34 | // Returns values of found-call. |
35 | const int FIND_NOT_FOUND = 0; |
36 | const int FIND_FOUND = 1; |
37 | const int FIND_NO_RING = 2; |
38 | |
39 | struct SwFindParas |
40 | { |
41 | // @param xSearchItem allocate in parent so we can do so outside the calling loop |
42 | virtual int DoFind(SwPaM &, SwMoveFnCollection const &, const SwPaM&, bool, std::unique_ptr<SvxSearchItem>& xSearchItem) = 0; |
43 | virtual bool IsReplaceMode() const = 0; |
44 | |
45 | protected: |
46 | ~SwFindParas() {} |
47 | }; |
48 | |
49 | enum class SwCursorSelOverFlags : sal_uInt16 |
50 | { |
51 | NONE = 0x00, |
52 | CheckNodeSection = 0x01, |
53 | Toggle = 0x02, |
54 | EnableRevDirection = 0x04, |
55 | ChangePos = 0x08 |
56 | }; |
57 | namespace o3tl { |
58 | template<> struct typed_flags<SwCursorSelOverFlags> : is_typed_flags<SwCursorSelOverFlags, 0x0f> {}; |
59 | } |
60 | |
61 | // define for cursor travelling normally in western text cells and chars do |
62 | // the same, but in complex text cell skip over ligatures and char skip |
63 | // into it. |
64 | // These defines exist only to cut off the dependencies to I18N project. |
65 | const sal_uInt16 CRSR_SKIP_CHARS = 0; |
66 | const sal_uInt16 CRSR_SKIP_CELLS = 1; |
67 | const sal_uInt16 CRSR_SKIP_HIDDEN = 2; |
68 | |
69 | |
70 | class SW_DLLPUBLIC__attribute__ ((visibility("default"))) SwCursor : public SwPaM |
71 | { |
72 | friend class SwCursorSaveState; |
73 | |
74 | std::vector<SwCursor_SavePos> m_vSavePos; // the current entry is the last element |
75 | long m_nRowSpanOffset; // required for travelling in tabs with rowspans |
76 | sal_uInt8 m_nCursorBidiLevel; // bidi level of the cursor |
77 | bool m_bColumnSelection; // true: cursor is aprt of a column selection |
78 | |
79 | sal_uLong FindAll( SwFindParas& , SwDocPositions, SwDocPositions, FindRanges, bool& bCancel ); |
80 | |
81 | SwCursor(SwCursor const& rPaM) = delete; |
82 | |
83 | protected: |
84 | void SaveState(); |
85 | void RestoreState(); |
86 | |
87 | const SwCursor_SavePos* GetSavePos() const { return m_vSavePos.empty() ? nullptr : &m_vSavePos.back(); } |
88 | |
89 | virtual const SwContentFrame* DoSetBidiLevelLeftRight( |
90 | bool & io_rbLeft, bool bVisualAllowed, bool bInsertCursor); |
91 | virtual void DoSetBidiLevelUpDown(); |
92 | virtual bool IsSelOvrCheck(SwCursorSelOverFlags eFlags); |
93 | |
94 | public: |
95 | // single argument ctors shall be explicit. |
96 | SwCursor( const SwPosition &rPos, SwPaM* pRing ); |
97 | virtual ~SwCursor() override; |
98 | |
99 | SwCursor & operator =(SwCursor const &) = default; |
100 | |
101 | /// this takes a second parameter, which indicates the Ring that |
102 | /// the new cursor should be part of (may be null) |
103 | SwCursor(SwCursor const& rCursor, SwPaM* pRing); |
104 | |
105 | public: |
106 | |
107 | virtual SwCursor* Create( SwPaM* pRing = nullptr ) const; |
108 | |
109 | virtual short MaxReplaceArived(); //returns RET_YES/RET_CANCEL/RET_NO |
110 | virtual void SaveTableBoxContent( const SwPosition* pPos ); |
111 | |
112 | void FillFindPos( SwDocPositions ePos, SwPosition& rPos ) const; |
113 | SwMoveFnCollection const & MakeFindRange( SwDocPositions, SwDocPositions, |
114 | SwPaM* ) const; |
115 | |
116 | // note: DO NOT call it FindText because windows.h |
117 | sal_uLong Find_Text( const i18nutil::SearchOptions2& rSearchOpt, |
118 | bool bSearchInNotes, |
119 | SwDocPositions nStart, SwDocPositions nEnd, |
120 | bool& bCancel, |
121 | FindRanges, |
122 | bool bReplace = false, |
123 | SwRootFrame const*const pLayout = nullptr); |
124 | sal_uLong FindFormat( const SwTextFormatColl& rFormatColl, |
125 | SwDocPositions nStart, SwDocPositions nEnd, |
126 | bool& bCancel, |
127 | FindRanges, |
128 | const SwTextFormatColl* pReplFormat, |
129 | SwRootFrame const*const pLayout = nullptr); |
130 | sal_uLong FindAttrs( const SfxItemSet& rSet, bool bNoCollections, |
131 | SwDocPositions nStart, SwDocPositions nEnd, |
132 | bool& bCancel, |
133 | FindRanges, |
134 | const i18nutil::SearchOptions2* pSearchOpt, |
135 | const SfxItemSet* rReplSet = nullptr, |
136 | SwRootFrame const*const pLayout = nullptr); |
137 | |
138 | // UI versions |
139 | bool IsStartEndSentence(bool bEnd, SwRootFrame const* pLayout) const; |
140 | bool SelectWord( SwViewShell const * pViewShell, const Point* pPt ); |
141 | |
142 | // API versions of above functions (will be used with a different |
143 | // WordType for the break iterator) |
144 | bool IsStartWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr) const; |
145 | bool IsEndWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr) const; |
146 | bool IsInWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr) const; |
147 | bool GoStartWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr); |
148 | bool GoEndWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr); |
149 | bool GoNextWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr); |
150 | bool GoPrevWordWT(sal_Int16 nWordType, SwRootFrame const* pLayout = nullptr); |
151 | bool SelectWordWT( SwViewShell const * pViewShell, sal_Int16 nWordType, const Point* pPt ); |
152 | |
153 | enum SentenceMoveType |
154 | { |
155 | NEXT_SENT, |
156 | PREV_SENT, |
157 | START_SENT, |
158 | END_SENT |
159 | }; |
160 | bool GoSentence(SentenceMoveType eMoveType, SwRootFrame const*pLayout = nullptr); |
161 | bool ExpandToSentenceBorders(SwRootFrame const* pLayout); |
162 | |
163 | virtual bool LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, |
164 | bool bAllowVisual, bool bSkipHidden, bool bInsertCursor, |
165 | SwRootFrame const* pLayout, bool isFieldNames); |
166 | bool UpDown(bool bUp, sal_uInt16 nCnt, Point const * pPt, long nUpDownX, SwRootFrame & rLayout); |
167 | bool LeftRightMargin(SwRootFrame const& rLayout, bool bLeftMargin, bool bAPI); |
168 | bool IsAtLeftRightMargin(SwRootFrame const& rLayout, bool bLeftMargin, bool bAPI) const; |
169 | bool SttEndDoc( bool bSttDoc ); |
170 | bool GoPrevNextCell( bool bNext, sal_uInt16 nCnt ); |
171 | |
172 | bool Left( sal_uInt16 nCnt ) { return LeftRight(true, nCnt, CRSR_SKIP_CHARS, false/*bAllowVisual*/, false/*bSkipHidden*/, false, nullptr, false); } |
173 | bool Right( sal_uInt16 nCnt ) { return LeftRight(false, nCnt, CRSR_SKIP_CHARS, false/*bAllowVisual*/, false/*bSkipHidden*/, false, nullptr, false); } |
174 | bool GoNextCell( sal_uInt16 nCnt = 1 ) { return GoPrevNextCell( true, nCnt ); } |
175 | bool GoPrevCell( sal_uInt16 nCnt = 1 ) { return GoPrevNextCell( false, nCnt ); } |
176 | virtual bool GotoTable( const OUString& rName ); |
177 | bool GotoTableBox( const OUString& rName ); |
178 | bool GotoRegion( const OUString& rName ); |
179 | bool GotoFootnoteAnchor(); |
180 | bool GotoFootnoteText(); |
181 | bool GotoNextFootnoteAnchor(); |
182 | bool GotoPrevFootnoteAnchor(); |
183 | |
184 | bool MovePara( SwWhichPara, SwMoveFnCollection const & ); |
185 | bool MoveSection( SwWhichSection, SwMoveFnCollection const & ); |
186 | bool MoveTable( SwWhichTable, SwMoveFnCollection const & ); |
187 | bool MoveRegion( SwWhichRegion, SwMoveFnCollection const & ); |
188 | |
189 | // Is there a selection of content in table? |
190 | // Return value indicates if cursor remains at its old position. |
191 | virtual bool IsSelOvr( SwCursorSelOverFlags eFlags = |
192 | SwCursorSelOverFlags::CheckNodeSection | |
193 | SwCursorSelOverFlags::Toggle | |
194 | SwCursorSelOverFlags::ChangePos ); |
195 | bool IsInProtectTable( bool bMove = false, |
196 | bool bChgCursor = true ); |
197 | bool IsNoContent() const; |
198 | |
199 | /** Restore cursor state to the one saved by SwCursorSaveState **/ |
200 | void RestoreSavePos(); |
201 | |
202 | // true: cursor can be set at this position. |
203 | virtual bool IsAtValidPos( bool bPoint = true ) const; |
204 | |
205 | // Is cursor allowed in ready only ranges? |
206 | virtual bool IsReadOnlyAvailable() const; |
207 | |
208 | virtual bool IsSkipOverProtectSections() const; |
209 | virtual bool IsSkipOverHiddenSections() const; |
210 | |
211 | sal_uInt8 GetCursorBidiLevel() const { return m_nCursorBidiLevel; } |
212 | void SetCursorBidiLevel( sal_uInt8 nNewLevel ) { m_nCursorBidiLevel = nNewLevel; } |
213 | |
214 | bool IsColumnSelection() const { return m_bColumnSelection; } |
215 | void SetColumnSelection( bool bNew ) { m_bColumnSelection = bNew; } |
216 | |
217 | long GetCursorRowSpanOffset() const { return m_nRowSpanOffset; } |
218 | |
219 | SwCursor* GetNext() { return dynamic_cast<SwCursor *>(GetNextInRing()); } |
220 | const SwCursor* GetNext() const { return dynamic_cast<SwCursor const *>(GetNextInRing()); } |
221 | SwCursor* GetPrev() { return dynamic_cast<SwCursor *>(GetPrevInRing()); } |
222 | const SwCursor* GetPrev() const { return dynamic_cast<SwCursor const *>(GetPrevInRing()); } |
223 | }; |
224 | |
225 | /** |
226 | A helper class to save cursor state (position). Create SwCursorSaveState |
227 | object to save current state, use SwCursor::RestoreSavePos() to actually |
228 | restore cursor state to the saved state (SwCursorSaveState destructor only |
229 | removes the saved state from an internal stack). It is possible to stack |
230 | several SwCursorSaveState objects. |
231 | **/ |
232 | class SwCursorSaveState |
233 | { |
234 | private: |
235 | SwCursor& m_rCursor; |
236 | public: |
237 | SwCursorSaveState( SwCursor& rC ) : m_rCursor( rC ) { rC.SaveState(); } |
238 | ~SwCursorSaveState() { m_rCursor.RestoreState(); } |
239 | }; |
240 | |
241 | // internal, used by SwCursor::SaveState() etc. |
242 | struct SwCursor_SavePos final |
243 | { |
244 | sal_uLong nNode; |
245 | sal_Int32 nContent; |
246 | |
247 | SwCursor_SavePos( const SwCursor& rCursor ) |
248 | : nNode( rCursor.GetPoint()->nNode.GetIndex() ), |
249 | nContent( rCursor.GetPoint()->nContent.GetIndex() ) |
250 | {} |
251 | }; |
252 | |
253 | class SwTableCursor : public virtual SwCursor |
254 | { |
255 | |
256 | protected: |
257 | sal_uLong m_nTablePtNd; |
258 | sal_uLong m_nTableMkNd; |
259 | sal_Int32 m_nTablePtCnt; |
260 | sal_Int32 m_nTableMkCnt; |
261 | SwSelBoxes m_SelectedBoxes; |
262 | bool m_bChanged : 1; |
263 | bool m_bParked : 1; // Table-cursor was parked. |
264 | |
265 | virtual bool IsSelOvrCheck(SwCursorSelOverFlags eFlags) override; |
266 | |
267 | public: |
268 | SwTableCursor( const SwPosition &rPos ); |
269 | SwTableCursor( SwTableCursor& ); |
270 | virtual ~SwTableCursor() override; |
271 | |
272 | virtual bool LeftRight( bool bLeft, sal_uInt16 nCnt, sal_uInt16 nMode, |
273 | bool bAllowVisual, bool bSkipHidden, bool bInsertCursor, |
274 | SwRootFrame const*, bool) override; |
275 | virtual bool GotoTable( const OUString& rName ) override; |
276 | |
277 | void InsertBox( const SwTableBox& rTableBox ); |
278 | void DeleteBox(size_t nPos); |
279 | size_t GetSelectedBoxesCount() const { return m_SelectedBoxes.size(); } |
280 | const SwSelBoxes& GetSelectedBoxes() const { return m_SelectedBoxes; } |
281 | |
282 | // Creates cursor for all boxes. |
283 | SwCursor* MakeBoxSels( SwCursor* pCurrentCursor ); |
284 | // Any boxes protected? |
285 | bool HasReadOnlyBoxSel() const; |
286 | |
287 | // Has table cursor been changed? If so, save new values immediately. |
288 | bool IsCursorMovedUpdate(); |
289 | // Has table cursor been changed? |
290 | bool IsCursorMoved() const |
291 | { |
292 | return m_nTableMkNd != GetMark()->nNode.GetIndex() || |
293 | m_nTablePtNd != GetPoint()->nNode.GetIndex() || |
294 | m_nTableMkCnt != GetMark()->nContent.GetIndex() || |
295 | m_nTablePtCnt != GetPoint()->nContent.GetIndex(); |
296 | } |
297 | |
298 | bool IsChgd() const { return m_bChanged; } |
299 | void SetChgd() { m_bChanged = true; } |
300 | |
301 | // Park table cursor at start node of boxes. |
302 | void ParkCursor(); |
303 | |
304 | bool NewTableSelection(); |
305 | void ActualizeSelection( const SwSelBoxes &rBoxes ); |
306 | |
307 | SwTableCursor* GetNext() { return dynamic_cast<SwTableCursor *>(GetNextInRing()); } |
308 | const SwTableCursor* GetNext() const { return dynamic_cast<SwTableCursor const *>(GetNextInRing()); } |
309 | SwTableCursor* GetPrev() { return dynamic_cast<SwTableCursor *>(GetPrevInRing()); } |
310 | const SwTableCursor* GetPrev() const { return dynamic_cast<SwTableCursor const *>(GetPrevInRing()); } |
311 | }; |
312 | |
313 | #endif |
314 | |
315 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |
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_RING_HXX | |||
20 | #define INCLUDED_SW_INC_RING_HXX | |||
21 | ||||
22 | #include <utility> | |||
23 | #include <sal/types.h> | |||
24 | #include <iterator> | |||
25 | #include <type_traits> | |||
26 | #include <boost/iterator/iterator_facade.hpp> | |||
27 | #include <boost/intrusive/circular_list_algorithms.hpp> | |||
28 | ||||
29 | namespace sw | |||
30 | { | |||
31 | template <typename value_type> class RingContainer; | |||
32 | template <typename value_type> class RingIterator; | |||
33 | /** | |||
34 | * An intrusive container class double linking the contained nodes | |||
35 | * @example sw/qa/core/uwriter.cxx | |||
36 | */ | |||
37 | template <typename value_type> | |||
38 | class SAL_WARN_UNUSED__attribute__((warn_unused)) Ring | |||
39 | { | |||
40 | public: | |||
41 | typedef typename std::add_const<value_type>::type const_value_type; | |||
42 | typedef RingContainer<value_type> ring_container; | |||
43 | typedef RingContainer<const_value_type> const_ring_container; | |||
44 | virtual ~Ring() COVERITY_NOEXCEPT_FALSE | |||
45 | { unlink(); }; | |||
46 | /** algo::unlink is buggy! don't call it directly! */ | |||
47 | void unlink() | |||
48 | { | |||
49 | algo::unlink(this); | |||
50 | m_pNext = this; // don't leave pointers to old list behind! | |||
51 | m_pPrev = this; | |||
52 | } | |||
53 | /** | |||
54 | * Removes this item from its current ring container and adds it to | |||
55 | * another ring container. If the item was not alone in the original | |||
56 | * ring container, the other items in the ring will stay in the old | |||
57 | * ring container. | |||
58 | * Note: the newly created item will be inserted just before item pDestRing. | |||
59 | * @param pDestRing the container to add this item to | |||
60 | */ | |||
61 | void MoveTo( value_type* pDestRing ); | |||
62 | /** @return a stl-like container with begin()/end() for iteration */ | |||
63 | ring_container GetRingContainer(); | |||
64 | /** @return a stl-like container with begin()/end() for const iteration */ | |||
65 | const_ring_container GetRingContainer() const; | |||
66 | ||||
67 | protected: | |||
68 | /** | |||
69 | * Creates a new item in a ring container all by itself. | |||
70 | * Note: Ring instances can newer be outside a container. At most, they | |||
71 | * are alone in one. | |||
72 | */ | |||
73 | Ring() | |||
74 | : m_pNext(this) | |||
75 | , m_pPrev(this) | |||
76 | { } | |||
77 | /** | |||
78 | * Creates a new item and add it to an existing ring container. | |||
79 | * Note: the newly created item will be inserted just before item pRing. | |||
80 | * @param pRing ring container to add the created item to | |||
81 | */ | |||
82 | Ring( value_type* pRing ); | |||
83 | /** @return the next item in the ring container */ | |||
84 | value_type* GetNextInRing() | |||
85 | { return static_cast<value_type *>(m_pNext); } | |||
| ||||
86 | /** @return the previous item in the ring container */ | |||
87 | value_type* GetPrevInRing() | |||
88 | { return static_cast<value_type *>(m_pPrev); } | |||
89 | /** @return the next item in the ring container */ | |||
90 | const_value_type* GetNextInRing() const | |||
91 | { return static_cast<value_type *>(m_pNext); } | |||
92 | /** @return the previous item in the ring container */ | |||
93 | const_value_type* GetPrevInRing() const | |||
94 | { return static_cast<value_type *>(m_pPrev); } | |||
95 | /** @return true if and only if this item is alone in its ring */ | |||
96 | bool unique() const | |||
97 | { return algo::unique(static_cast< const_value_type* >(this)); } | |||
98 | ||||
99 | private: | |||
100 | /** internal implementation class -- not for external use */ | |||
101 | struct Ring_node_traits | |||
102 | { | |||
103 | typedef Ring node; | |||
104 | typedef Ring* node_ptr; | |||
105 | typedef const Ring* const_node_ptr; | |||
106 | static node_ptr get_next(const_node_ptr n) { return const_cast<node_ptr>(n)->m_pNext; }; | |||
107 | static void set_next(node_ptr n, node_ptr next) { n->m_pNext = next; }; | |||
108 | static node_ptr get_previous(const_node_ptr n) { return const_cast<node_ptr>(n)->m_pPrev; }; | |||
109 | static void set_previous(node_ptr n, node_ptr previous) { n->m_pPrev = previous; }; | |||
110 | }; | |||
111 | friend ring_container; | |||
112 | friend const_ring_container; | |||
113 | friend typename ring_container::iterator; | |||
114 | friend typename ring_container::const_iterator; | |||
115 | friend typename const_ring_container::iterator; | |||
116 | friend typename const_ring_container::const_iterator; | |||
117 | friend class boost::iterator_core_access; | |||
118 | typedef boost::intrusive::circular_list_algorithms<Ring_node_traits> algo; | |||
119 | Ring* m_pNext; | |||
120 | Ring* m_pPrev; | |||
121 | }; | |||
122 | ||||
123 | template <typename value_type> | |||
124 | inline Ring<value_type>::Ring( value_type* pObj ) | |||
125 | : m_pNext(this) | |||
126 | , m_pPrev(this) | |||
127 | { | |||
128 | if( pObj ) | |||
129 | { | |||
130 | algo::link_before(pObj, this); | |||
131 | } | |||
132 | } | |||
133 | ||||
134 | template <typename value_type> | |||
135 | inline void Ring<value_type>::MoveTo(value_type* pDestRing) | |||
136 | { | |||
137 | value_type* pThis = static_cast< value_type* >(this); | |||
138 | unlink(); | |||
139 | // insert into "new" | |||
140 | if (pDestRing) | |||
141 | { | |||
142 | algo::link_before(pDestRing, pThis); | |||
143 | } | |||
144 | } | |||
145 | ||||
146 | /** | |||
147 | * helper class that provides Svalue_typeL-style container iteration to the ring | |||
148 | */ | |||
149 | template <typename value_type> | |||
150 | class SAL_WARN_UNUSED__attribute__((warn_unused)) RingContainer final | |||
151 | { | |||
152 | private: | |||
153 | /** the item in the ring where iteration starts */ | |||
154 | value_type* m_pStart; | |||
155 | typedef typename std::remove_const<value_type>::type nonconst_value_type; | |||
156 | ||||
157 | public: | |||
158 | RingContainer( value_type* pRing ) : m_pStart(pRing) {}; | |||
159 | typedef RingIterator<value_type> iterator; | |||
160 | typedef RingIterator<const value_type> const_iterator; | |||
161 | /** | |||
162 | * iterator access | |||
163 | * @code | |||
164 | * for(SwPaM& rCurrentPaM : pPaM->GetRingContainer()) | |||
165 | * do_stuff(rCurrentPaM); // this gets called on every SwPaM in the same ring as pPaM | |||
166 | * @endcode | |||
167 | */ | |||
168 | iterator begin(); | |||
169 | iterator end(); | |||
170 | const_iterator begin() const; | |||
171 | const_iterator end() const; | |||
172 | /** @return the number of elements in the container */ | |||
173 | size_t size() const | |||
174 | { return std::distance(begin(), end()); } | |||
175 | /** | |||
176 | * Merges two ring containers. All item from both ring containers will | |||
177 | * be in the same ring container in the end. | |||
178 | * Note: The items of this ring container will be inserted just before | |||
179 | * item pDestRing | |||
180 | * @param pDestRing the container to merge this container with | |||
181 | */ | |||
182 | void merge( RingContainer< value_type > aDestRing ) | |||
183 | { | |||
184 | // first check that we aren't merged already, swapping would | |||
185 | // actually un-merge in this case! | |||
186 | assert(m_pStart->m_pPrev != aDestRing.m_pStart)(static_cast <bool> (m_pStart->m_pPrev != aDestRing. m_pStart) ? void (0) : __assert_fail ("m_pStart->m_pPrev != aDestRing.m_pStart" , "/home/maarten/src/libreoffice/core/sw/inc/ring.hxx", 186, __extension__ __PRETTY_FUNCTION__)); | |||
187 | assert(m_pStart != aDestRing.m_pStart->m_pPrev)(static_cast <bool> (m_pStart != aDestRing.m_pStart-> m_pPrev) ? void (0) : __assert_fail ("m_pStart != aDestRing.m_pStart->m_pPrev" , "/home/maarten/src/libreoffice/core/sw/inc/ring.hxx", 187, __extension__ __PRETTY_FUNCTION__)); | |||
188 | std::swap(m_pStart->m_pPrev->m_pNext, aDestRing.m_pStart->m_pPrev->m_pNext); | |||
189 | std::swap(m_pStart->m_pPrev, aDestRing.m_pStart->m_pPrev); | |||
190 | } | |||
191 | }; | |||
192 | ||||
193 | template <typename value_type> | |||
194 | class RingIterator final : public boost::iterator_facade< | |||
195 | RingIterator<value_type> | |||
196 | , value_type | |||
197 | , boost::forward_traversal_tag | |||
198 | > | |||
199 | { | |||
200 | private: | |||
201 | typedef typename std::remove_const<value_type>::type nonconst_value_type; | |||
202 | public: | |||
203 | RingIterator() | |||
204 | : m_pCurrent(nullptr) | |||
205 | , m_pStart(nullptr) | |||
206 | {} | |||
207 | explicit RingIterator(nonconst_value_type* pRing, bool bStart = true) | |||
208 | : m_pCurrent(nullptr) | |||
209 | , m_pStart(pRing) | |||
210 | { | |||
211 | if(!bStart) | |||
212 | m_pCurrent = m_pStart; | |||
213 | } | |||
214 | ||||
215 | private: | |||
216 | friend class boost::iterator_core_access; | |||
217 | void increment() | |||
218 | { m_pCurrent = m_pCurrent ? m_pCurrent->GetNextInRing() : m_pStart->GetNextInRing(); } | |||
219 | bool equal(RingIterator const& other) const | |||
220 | { | |||
221 | // we never want to compare iterators from | |||
222 | // different rings or starting points | |||
223 | assert(m_pStart == other.m_pStart)(static_cast <bool> (m_pStart == other.m_pStart) ? void (0) : __assert_fail ("m_pStart == other.m_pStart", "/home/maarten/src/libreoffice/core/sw/inc/ring.hxx" , 223, __extension__ __PRETTY_FUNCTION__)); | |||
224 | return m_pCurrent == other.m_pCurrent; | |||
225 | } | |||
226 | value_type& dereference() const | |||
227 | { return m_pCurrent ? *m_pCurrent : * m_pStart; } | |||
228 | /** | |||
229 | * value_type is: | |||
230 | * - pointing to the current item in the iteration in general | |||
231 | * - nullptr if on the first item (begin()) | |||
232 | * - m_pStart when beyond the last item (end()) | |||
233 | */ | |||
234 | nonconst_value_type* m_pCurrent; | |||
235 | /** the first item of the iteration */ | |||
236 | nonconst_value_type* m_pStart; | |||
237 | }; | |||
238 | ||||
239 | template <typename value_type> | |||
240 | inline typename Ring<value_type>::ring_container Ring<value_type>::GetRingContainer() | |||
241 | { return Ring<value_type>::ring_container(static_cast< value_type* >(this)); }; | |||
242 | ||||
243 | template <typename value_type> | |||
244 | inline typename Ring<value_type>::const_ring_container Ring<value_type>::GetRingContainer() const | |||
245 | { return Ring<value_type>::const_ring_container(static_cast< const_value_type* >(this)); }; | |||
246 | ||||
247 | template <typename value_type> | |||
248 | inline typename RingContainer<value_type>::iterator RingContainer<value_type>::begin() | |||
249 | { return RingContainer<value_type>::iterator(const_cast< nonconst_value_type* >(m_pStart)); }; | |||
250 | ||||
251 | template <typename value_type> | |||
252 | inline typename RingContainer<value_type>::iterator RingContainer<value_type>::end() | |||
253 | { return RingContainer<value_type>::iterator(const_cast< nonconst_value_type* >(m_pStart), false); }; | |||
254 | ||||
255 | template <typename value_type> | |||
256 | inline typename RingContainer<value_type>::const_iterator RingContainer<value_type>::begin() const | |||
257 | { return RingContainer<value_type>::const_iterator(const_cast< nonconst_value_type* >(m_pStart)); }; | |||
258 | ||||
259 | template <typename value_type> | |||
260 | inline typename RingContainer<value_type>::const_iterator RingContainer<value_type>::end() const | |||
261 | { return RingContainer<value_type>::const_iterator(const_cast< nonconst_value_type* >(m_pStart), false); }; | |||
262 | } | |||
263 | #endif | |||
264 | ||||
265 | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |