Bug Summary

File:home/maarten/src/libreoffice/core/sw/inc/ring.hxx
Warning:line 85, column 19
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name unocrsr.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SW_DLLIMPLEMENTATION -D SWUI_DLL_NAME="libswuilo.so" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sw/source/core/inc -I /home/maarten/src/libreoffice/core/sw/source/filter/inc -I /home/maarten/src/libreoffice/core/sw/source/uibase/inc -I /home/maarten/src/libreoffice/core/sw/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sw/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/sw/generated -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sw/source/core/unocore/unocrsr.cxx

/home/maarten/src/libreoffice/core/sw/source/core/unocore/unocrsr.cxx

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
26sw::UnoCursorHint::~UnoCursorHint() {}
27
28SwUnoCursor::SwUnoCursor( const SwPosition &rPos )
29 : SwCursor( rPos, nullptr )
30 , m_bRemainInSection(true)
31 , m_bSkipOverHiddenSections(false)
32 , m_bSkipOverProtectSections(false)
33{}
34
35SwUnoCursor::~SwUnoCursor()
36{
37 SwDoc& rDoc = GetDoc();
38 if( !rDoc.IsInDtor() )
1
Assuming the condition is false
2
Taking false branch
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 )
3
Loop condition is true. Entering loop body
5
Calling 'SwCursor::GetNext'
45 {
46 Ring* pNxt = GetNextInRing();
47 pNxt->MoveTo(nullptr); // remove from chain
48 delete pNxt; // and delete
4
Memory is released
49 }
50}
51
52bool SwUnoCursor::IsReadOnlyAvailable() const
53{
54 return true;
55}
56
57const SwContentFrame*
58SwUnoCursor::DoSetBidiLevelLeftRight( bool &, bool, bool )
59{
60 return nullptr; // not for uno cursor
61}
62
63void SwUnoCursor::DoSetBidiLevelUpDown()
64{
65 // not for uno cursor
66}
67
68bool 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
154SwUnoTableCursor::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
163SwUnoTableCursor::~SwUnoTableCursor()
164{
165 while (m_aTableSel.GetNext() != &m_aTableSel)
166 delete m_aTableSel.GetNext();
167}
168
169bool 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
182void 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: */

/home/maarten/src/libreoffice/core/sw/inc/swcrsr.hxx

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
26class SfxItemSet;
27struct SwCursor_SavePos;
28class SvxSearchItem;
29namespace i18nutil {
30 struct SearchOptions2;
31}
32
33// Base structure for parameters of the find-methods.
34// Returns values of found-call.
35const int FIND_NOT_FOUND = 0;
36const int FIND_FOUND = 1;
37const int FIND_NO_RING = 2;
38
39struct 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
45protected:
46 ~SwFindParas() {}
47};
48
49enum class SwCursorSelOverFlags : sal_uInt16
50{
51 NONE = 0x00,
52 CheckNodeSection = 0x01,
53 Toggle = 0x02,
54 EnableRevDirection = 0x04,
55 ChangePos = 0x08
56};
57namespace 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.
65const sal_uInt16 CRSR_SKIP_CHARS = 0;
66const sal_uInt16 CRSR_SKIP_CELLS = 1;
67const sal_uInt16 CRSR_SKIP_HIDDEN = 2;
68
69
70class 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
83protected:
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
94public:
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
105public:
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()); }
6
Calling 'Ring::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**/
232class SwCursorSaveState
233{
234private:
235 SwCursor& m_rCursor;
236public:
237 SwCursorSaveState( SwCursor& rC ) : m_rCursor( rC ) { rC.SaveState(); }
238 ~SwCursorSaveState() { m_rCursor.RestoreState(); }
239};
240
241// internal, used by SwCursor::SaveState() etc.
242struct 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
253class SwTableCursor : public virtual SwCursor
254{
255
256protected:
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
267public:
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: */

/home/maarten/src/libreoffice/core/sw/inc/ring.hxx

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
29namespace 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); }
7
Use of memory after it is freed
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: */