LibreOffice Module sw (master) 1
doccorr.cxx
Go to the documentation of this file.
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 <doc.hxx>
23#include <node.hxx>
24#include <editsh.hxx>
25#include <viscrs.hxx>
26#include <redline.hxx>
27#include <mvsave.hxx>
28#include <docary.hxx>
29#include <unocrsr.hxx>
30
31namespace
32{
35 const SwStartNode* lcl_FindUnoCursorSection( const SwNode& rNode )
36 {
37 const SwStartNode* pStartNode = rNode.StartOfSectionNode();
38 while( ( pStartNode != nullptr ) &&
39 ( pStartNode->StartOfSectionNode() != pStartNode ) &&
40 ( pStartNode->GetStartNodeType() == SwNormalStartNode ) )
41 pStartNode = pStartNode->StartOfSectionNode();
42
43 return pStartNode;
44 }
45
46 bool lcl_PosCorrAbs(SwPosition & rPos,
47 const SwPosition& rStart,
48 const SwPosition& rEnd,
49 const SwPosition& rNewPos)
50 {
51 if ((rStart <= rPos) && (rPos <= rEnd))
52 {
53 rPos = rNewPos;
54 return true;
55 }
56 return false;
57 };
58
59 bool lcl_PaMCorrAbs(SwPaM & rPam,
60 const SwPosition& rStart,
61 const SwPosition& rEnd,
62 const SwPosition& rNewPos)
63 {
64 bool bRet = false;
65 bRet |= lcl_PosCorrAbs(rPam.GetBound(), rStart, rEnd, rNewPos);
66 bRet |= lcl_PosCorrAbs(rPam.GetBound(false), rStart, rEnd, rNewPos);
67 return bRet;
68 };
69
70 void lcl_PaMCorrRel1(SwPaM * pPam,
71 SwNode const * const pOldNode,
72 const SwPosition& rNewPos,
73 const sal_Int32 nCntIdx)
74 {
75 for(int nb = 0; nb < 2; ++nb)
76 {
77 SwPosition & rPos = pPam->GetBound(bool(nb));
78 if(&rPos.GetNode() == pOldNode)
79 {
80 rPos.Assign(rNewPos.GetNode(), SwNodeOffset(0),
81 nCntIdx + rPos.GetContentIndex());
82 }
83 }
84 }
85}
86
87void PaMCorrAbs( const SwPaM& rRange,
88 const SwPosition& rNewPos )
89{
90 SwPosition const aStart( *rRange.Start() );
91 SwPosition const aEnd( *rRange.End() );
92 SwPosition const aNewPos( rNewPos );
93 SwDoc& rDoc = aStart.GetNode().GetDoc();
94 SwCursorShell *const pShell = rDoc.GetEditShell();
95
96 if( pShell )
97 {
98 for(const SwViewShell& rShell : pShell->GetRingContainer())
99 {
100 const SwCursorShell* pCursorShell = dynamic_cast<const SwCursorShell*>(&rShell);
101 if(!pCursorShell)
102 continue;
103 SwPaM *_pStackCursor = pCursorShell->GetStackCursor();
104 if( _pStackCursor )
105 for (;;)
106 {
107 lcl_PaMCorrAbs( *_pStackCursor, aStart, aEnd, aNewPos );
108 if( !_pStackCursor )
109 break;
110 _pStackCursor = _pStackCursor->GetNext();
111 if( _pStackCursor == pCursorShell->GetStackCursor() )
112 break;
113 }
114
115 for(SwPaM& rPaM : const_cast<SwShellCursor*>(pCursorShell->GetCursor_())->GetRingContainer())
116 {
117 lcl_PaMCorrAbs( rPaM, aStart, aEnd, aNewPos );
118 }
119
120 if( pCursorShell->IsTableMode() )
121 lcl_PaMCorrAbs( const_cast<SwPaM &>(*pCursorShell->GetTableCrs()), aStart, aEnd, aNewPos );
122 }
123 }
124
126 for(const auto& pWeakUnoCursor : rDoc.mvUnoCursorTable)
127 {
128 auto pUnoCursor(pWeakUnoCursor.lock());
129 if(!pUnoCursor)
130 continue;
131
132 bool bChange = false; // has the UNO cursor been corrected?
133
134 // determine whether the UNO cursor will leave it's designated
135 // section
136 bool const bLeaveSection =
137 pUnoCursor->IsRemainInSection() &&
138 ( lcl_FindUnoCursorSection( aNewPos.GetNode() ) !=
139 lcl_FindUnoCursorSection(
140 pUnoCursor->GetPoint()->GetNode() ) );
141
142 for(SwPaM& rPaM : pUnoCursor->GetRingContainer())
143 {
144 bChange |= lcl_PaMCorrAbs( rPaM, aStart, aEnd, aNewPos );
145 }
146
147 SwUnoTableCursor *const pUnoTableCursor =
148 dynamic_cast<SwUnoTableCursor *>(pUnoCursor.get());
149 if( pUnoTableCursor )
150 {
151 for(SwPaM& rPaM : pUnoTableCursor->GetSelRing().GetRingContainer())
152 {
153 bChange |=
154 lcl_PaMCorrAbs( rPaM, aStart, aEnd, aNewPos );
155 }
156 }
157
158 // if a UNO cursor leaves its designated section, we must inform
159 // (and invalidate) said cursor
160 if (bChange && bLeaveSection)
161 {
162 // the UNO cursor has left its section. We need to notify it!
163 sw::UnoCursorHint aHint;
164 pUnoCursor->m_aNotifier.Broadcast(aHint);
165 }
166 }
167}
168
169void SwDoc::CorrAbs(const SwNode& rOldNode,
170 const SwPosition& rNewPos,
171 const sal_Int32 nOffset,
172 bool bMoveCursor)
173{
174 const SwContentNode *const pContentNode( rOldNode.GetContentNode() );
175 SwPaM const aPam(rOldNode, 0,
176 rOldNode, pContentNode ? pContentNode->Len() : 0);
177 SwPosition aNewPos(rNewPos);
178 aNewPos.AdjustContent(nOffset);
179
180 getIDocumentMarkAccess()->correctMarksAbsolute(rOldNode, rNewPos, nOffset);
181 // fix redlines
182 {
184 for (SwRedlineTable::size_type n = 0; n < rTable.size(); )
185 {
186 // is on position ??
187 SwRangeRedline *const pRedline( rTable[ n ] );
188 bool const bChanged =
189 lcl_PaMCorrAbs(*pRedline, *aPam.Start(), *aPam.End(), aNewPos);
190 // clean up empty redlines: docredln.cxx asserts these as invalid
191 if (bChanged && (*pRedline->GetPoint() == *pRedline->GetMark())
192 && (pRedline->GetContentIdx() == nullptr))
193 {
194 rTable.DeleteAndDestroy(n);
195 }
196 else
197 {
198 ++n;
199 }
200 }
201
202 // To-Do - need to add here 'SwExtraRedlineTable' also ?
203 }
204
205 if(bMoveCursor)
206 {
207 ::PaMCorrAbs(aPam, aNewPos);
208 }
209}
210
212 const SwPaM& rRange,
213 const SwPosition& rNewPos,
214 bool bMoveCursor )
215{
216 const SwPosition& aStart(*rRange.Start());
217 const SwPosition& aEnd(*rRange.End());
218
219 DelBookmarks( aStart.GetNode(), aEnd.GetNode(), nullptr, aStart.GetContentIndex(), aEnd.GetContentIndex() );
220
221 if(bMoveCursor)
222 ::PaMCorrAbs(rRange, rNewPos);
223}
224
226 const SwNodeIndex& rStartNode,
227 const SwNodeIndex& rEndNode,
228 const SwPosition& rNewPos,
229 bool bMoveCursor )
230{
231 DelBookmarks( rStartNode.GetNode(), rEndNode.GetNode() );
232
233 if(bMoveCursor)
234 {
235 SwContentNode *const pContentNode( rEndNode.GetNode().GetContentNode() );
236 SwPaM const aPam(rStartNode, 0,
237 rEndNode, pContentNode ? pContentNode->Len() : 0);
238 ::PaMCorrAbs(aPam, rNewPos);
239 }
240}
241
242void PaMCorrRel( const SwNode &rOldNode,
243 const SwPosition &rNewPos,
244 const sal_Int32 nOffset )
245{
246 const SwNode* pOldNode = &rOldNode;
247 SwPosition aNewPos( rNewPos );
248 const SwDoc& rDoc = pOldNode->GetDoc();
249
250 const sal_Int32 nCntIdx = rNewPos.GetContentIndex() + nOffset;
251
252 SwCursorShell const* pShell = rDoc.GetEditShell();
253 if( pShell )
254 {
255 for(const SwViewShell& rShell : pShell->GetRingContainer())
256 {
257 SwCursorShell* pCursorShell = const_cast<SwCursorShell*>(dynamic_cast<const SwCursorShell*>(&rShell));
258 if(!pCursorShell)
259 continue;
260 SwPaM *_pStackCursor = pCursorShell->GetStackCursor();
261 if( _pStackCursor )
262 for (;;)
263 {
264 lcl_PaMCorrRel1( _pStackCursor, pOldNode, aNewPos, nCntIdx );
265 if( !_pStackCursor )
266 break;
267 _pStackCursor = _pStackCursor->GetNext();
268 if( _pStackCursor == pCursorShell->GetStackCursor() )
269 break;
270 }
271
272 SwPaM* pStartPaM = pCursorShell->GetCursor_();
273 for(SwPaM& rPaM : pStartPaM->GetRingContainer())
274 {
275 lcl_PaMCorrRel1( &rPaM, pOldNode, aNewPos, nCntIdx);
276 }
277
278 if( pCursorShell->IsTableMode() )
279 lcl_PaMCorrRel1( pCursorShell->GetTableCrs(), pOldNode, aNewPos, nCntIdx );
280 }
281 }
282
284 for(const auto& pWeakUnoCursor : rDoc.mvUnoCursorTable)
285 {
286 auto pUnoCursor(pWeakUnoCursor.lock());
287 if(!pUnoCursor)
288 continue;
289 for(SwPaM& rPaM : pUnoCursor->GetRingContainer())
290 {
291 lcl_PaMCorrRel1( &rPaM, pOldNode, aNewPos, nCntIdx );
292 }
293
294 SwUnoTableCursor* pUnoTableCursor =
295 dynamic_cast<SwUnoTableCursor*>(pUnoCursor.get());
296 if( pUnoTableCursor )
297 {
298 for(SwPaM& rPaM : pUnoTableCursor->GetSelRing().GetRingContainer())
299 {
300 lcl_PaMCorrRel1( &rPaM, pOldNode, aNewPos, nCntIdx );
301 }
302 }
303 }
304}
305
306void SwDoc::CorrRel(const SwNode& rOldNode,
307 const SwPosition& rNewPos,
308 const sal_Int32 nOffset,
309 bool bMoveCursor)
310{
311 getIDocumentMarkAccess()->correctMarksRelative(rOldNode, rNewPos, nOffset);
312
313 { // fix the Redlines
315 SwPosition aNewPos(rNewPos);
316 for(SwRangeRedline* p : rTable)
317 {
318 // lies on the position ??
319 lcl_PaMCorrRel1( p, &rOldNode, aNewPos, aNewPos.GetContentIndex() + nOffset );
320 }
321
322 // To-Do - need to add here 'SwExtraRedlineTable' also ?
323 }
324
325 if(bMoveCursor)
326 ::PaMCorrRel(rOldNode, rNewPos, nOffset);
327}
328
330{
332 // Layout and OLE shells should be available
333 if( pCurrentView )
334 {
335 for(const SwViewShell& rCurrentSh : pCurrentView->GetRingContainer())
336 {
337 // look for an EditShell (if it exists)
338 if( auto pEditShell = dynamic_cast<const SwEditShell *>(&rCurrentSh) )
339 {
340 return pEditShell;
341 }
342 }
343 }
344 return nullptr;
345}
346
348{
349 return const_cast<SwEditShell*>( const_cast<SwDoc const *>( this )->GetEditShell() );
350}
351
353{
354 return GetEditShell();
355}
356
357//bool foo()
358//{
359// bool b1 = true ? true : false;
360// bool b2 = (true ? true : false) ? true : false;
361// bool b3 = true ? (true ? true : false) : false;
362// bool b4 = true ? true : (true ? true : false);
363// return false;
364//}
365
366/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual const SwViewShell * GetCurrentViewShell() const =0
Returns the layout set at the document.
virtual void correctMarksRelative(const SwNode &rOldNode, const SwPosition &rNewPos, const sal_Int32 nOffset)=0
Corrects marks (relative) This method uses the previous position of the mark in the paragraph as offs...
virtual void correctMarksAbsolute(const SwNode &rOldNode, const SwPosition &rNewPos, const sal_Int32 nOffset)=0
Corrects marks (absolute) This method ignores the previous position of the mark in the paragraph.
virtual const SwRedlineTable & GetRedlineTable() const =0
virtual sal_Int32 Len() const
Definition: node.cxx:1257
const SwPaM * GetTableCrs() const
Definition: crsrsh.hxx:924
SwShellCursor * GetCursor_()
Definition: crsrsh.hxx:340
SwPaM * GetStackCursor() const
Definition: crsrsh.hxx:893
bool IsTableMode() const
Definition: crsrsh.hxx:659
Definition: doc.hxx:192
void CorrRel(const SwNode &rOldNode, const SwPosition &rNewPos, const sal_Int32 nOffset=0, bool bMoveCursor=false)
Definition: doccorr.cxx:306
::sw::IShellCursorSupplier * GetIShellCursorSupplier()
Definition: doccorr.cxx:352
std::vector< std::weak_ptr< SwUnoCursor > > mvUnoCursorTable
Definition: doc.hxx:1650
void CorrAbs(const SwNode &rOldNode, const SwPosition &rNewPos, const sal_Int32 nOffset=0, bool bMoveCursor=false)
Definition: doccorr.cxx:169
void cleanupUnoCursorTable() const
Definition: doc.hxx:1653
IDocumentRedlineAccess const & getIDocumentRedlineAccess() const
Definition: doc.cxx:336
SwEditShell const * GetEditShell() const
Definition: doccorr.cxx:329
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:406
IDocumentMarkAccess * getIDocumentMarkAccess()
Definition: docbm.cxx:1793
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNode & GetNode() const
Definition: ndindex.hxx:136
Base class of the Writer document model elements.
Definition: node.hxx:84
SwDoc & GetDoc()
Definition: node.hxx:217
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:137
SwContentNode * GetContentNode()
Definition: node.hxx:644
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:187
const SwPosition * GetMark() const
Definition: pam.hxx:263
const SwPosition * End() const
Definition: pam.hxx:271
SwPaM * GetNext()
Definition: pam.hxx:320
SwPosition & GetBound(bool bOne=true)
Definition: pam.hxx:301
const SwPosition * GetPoint() const
Definition: pam.hxx:261
const SwPosition * Start() const
Definition: pam.hxx:266
const SwNodeIndex * GetContentIdx() const
Definition: redline.hxx:189
void DeleteAndDestroy(size_type nPos)
Definition: docredln.cxx:664
size_type size() const
Definition: docary.hxx:267
vector_type::size_type size_type
Definition: docary.hxx:222
Starts a section of nodes in the document model.
Definition: node.hxx:325
SwStartNodeType GetStartNodeType() const
Definition: node.hxx:341
SwCursor & GetSelRing()
Definition: unocrsr.hxx:101
The Undo actions need to create new Shell cursors.
ring_container GetRingContainer()
Definition: ring.hxx:240
void DelBookmarks(SwNode &rStt, const SwNode &rEnd, std::vector< SaveBookmark > *pSaveBkmk, std::optional< sal_Int32 > oStartContentIdx, std::optional< sal_Int32 > oEndContentIdx)
Definition: docbm.cxx:1914
void PaMCorrRel(const SwNode &rOldNode, const SwPosition &rNewPos, const sal_Int32 nOffset)
Sets all PaMs in OldNode to relative Pos.
Definition: doccorr.cxx:242
void PaMCorrAbs(const SwPaM &rRange, const SwPosition &rNewPos)
Function declarations so that everything below the CursorShell can move the Cursor once in a while.
Definition: doccorr.cxx:87
void * p
sal_Int64 n
@ SwNormalStartNode
Definition: ndtyp.hxx:52
Marks a position in the document model.
Definition: pam.hxx:37
SwNode & GetNode() const
Definition: pam.hxx:80
void Assign(const SwNode &rNd, SwNodeOffset nDelta, sal_Int32 nContentOffset=0)
These all set both nNode and nContent.
Definition: pam.cxx:230
sal_Int32 GetContentIndex() const
Definition: pam.hxx:84
void AdjustContent(sal_Int32 nDelta)
Adjust content index, only valid to call this if the position points to a SwContentNode subclass.
Definition: pam.cxx:261