LibreOffice Module sw (master)  1
unmove.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 <UndoSplitMove.hxx>
21 #include <doc.hxx>
22 #include <IDocumentUndoRedo.hxx>
23 #include <pam.hxx>
24 #include <swundo.hxx>
25 #include <ndtxt.hxx>
26 #include <UndoCore.hxx>
27 #include <rolbck.hxx>
28 
29 // MOVE
30 SwUndoMove::SwUndoMove( const SwPaM& rRange, const SwPosition& rMvPos )
31  : SwUndo( SwUndoId::MOVE, rRange.GetDoc() )
32  , SwUndRng( rRange )
33  , m_nDestStartNode(0)
34  , m_nDestEndNode(0)
35  , m_nInsPosNode(0)
36  , m_nMoveDestNode(rMvPos.nNode.GetIndex())
37  , m_nDestStartContent(0)
38  , m_nDestEndContent(0)
39  , m_nInsPosContent(0)
40  , m_nMoveDestContent(rMvPos.nContent.GetIndex())
41  , m_bJoinNext(false)
42  , m_bJoinPrev(false)
43  , m_bMoveRange(false)
44  , m_bMoveRedlines(false)
45 {
46  // get StartNode from footnotes before delete!
47  SwDoc* pDoc = rRange.GetDoc();
48  SwTextNode* pTextNd = pDoc->GetNodes()[ m_nSttNode ]->GetTextNode();
49  SwTextNode* pEndTextNd = pDoc->GetNodes()[ m_nEndNode ]->GetTextNode();
50 
51  pHistory.reset( new SwHistory );
52 
53  if( pTextNd )
54  {
55  pHistory->Add( pTextNd->GetTextColl(), m_nSttNode, SwNodeType::Text );
56  if ( pTextNd->GetpSwpHints() )
57  {
58  pHistory->CopyAttr( pTextNd->GetpSwpHints(), m_nSttNode,
59  0, pTextNd->GetText().getLength(), false );
60  }
61  if( pTextNd->HasSwAttrSet() )
62  pHistory->CopyFormatAttr( *pTextNd->GetpSwAttrSet(), m_nSttNode );
63  }
64  if( pEndTextNd && pEndTextNd != pTextNd )
65  {
66  pHistory->Add( pEndTextNd->GetTextColl(), m_nEndNode, SwNodeType::Text );
67  if ( pEndTextNd->GetpSwpHints() )
68  {
69  pHistory->CopyAttr( pEndTextNd->GetpSwpHints(), m_nEndNode,
70  0, pEndTextNd->GetText().getLength(), false );
71  }
72  if( pEndTextNd->HasSwAttrSet() )
73  pHistory->CopyFormatAttr( *pEndTextNd->GetpSwAttrSet(), m_nEndNode );
74  }
75 
76  pTextNd = rMvPos.nNode.GetNode().GetTextNode();
77  if (nullptr != pTextNd)
78  {
80  if ( pTextNd->GetpSwpHints() )
81  {
82  pHistory->CopyAttr( pTextNd->GetpSwpHints(), m_nMoveDestNode,
83  0, pTextNd->GetText().getLength(), false );
84  }
85  if( pTextNd->HasSwAttrSet() )
86  pHistory->CopyFormatAttr( *pTextNd->GetpSwAttrSet(), m_nMoveDestNode );
87  }
88 
89  m_nFootnoteStart = pHistory->Count();
90  DelFootnote( rRange );
91 
92  if( pHistory && !pHistory->Count() )
93  pHistory.reset();
94 }
95 
97  const SwNodeIndex& rMvPos )
98  : SwUndo(SwUndoId::MOVE, pDoc)
99  , m_nDestStartNode(0)
100  , m_nDestEndNode(0)
101  , m_nInsPosNode(0)
102  , m_nMoveDestNode(rMvPos.GetIndex())
103  , m_nDestStartContent(0)
104  , m_nDestEndContent(0)
105  , m_nInsPosContent(0)
106  , m_bMoveRedlines(false)
107 {
108  m_bMoveRange = true;
109  m_bJoinNext = m_bJoinPrev = false;
110 
112 
113  m_nSttNode = rRg.aStart.GetIndex();
114  m_nEndNode = rRg.aEnd.GetIndex();
115 
116 // DelFootnote( rRange );
117 // FIXME: duplication of the method body of DelFootnote below
118 
119  // is the current move from ContentArea into the special section?
120  sal_uLong nContentStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
121  if( m_nMoveDestNode < nContentStt && rRg.aStart.GetIndex() > nContentStt )
122  {
123  // delete all footnotes since they are undesired there
124  SwPosition aPtPos( rRg.aEnd );
125  SwContentNode* pCNd = rRg.aEnd.GetNode().GetContentNode();
126  if( pCNd )
127  aPtPos.nContent.Assign( pCNd, pCNd->Len() );
128  SwPosition aMkPos( rRg.aStart );
129  if( nullptr != ( pCNd = aMkPos.nNode.GetNode().GetContentNode() ))
130  aMkPos.nContent.Assign( pCNd, 0 );
131 
132  DelContentIndex( aMkPos, aPtPos, DelContentType::Ftn );
133 
134  if( pHistory && !pHistory->Count() )
135  pHistory.reset();
136  }
137 
138  m_nFootnoteStart = 0;
139 }
140 
141 void SwUndoMove::SetDestRange( const SwPaM& rRange,
142  const SwPosition& rInsPos,
143  bool bJoin, bool bCorrPam )
144 {
145  const SwPosition *pStt = rRange.Start(),
146  *pEnd = rRange.GetPoint() == pStt
147  ? rRange.GetMark()
148  : rRange.GetPoint();
149 
150  m_nDestStartNode = pStt->nNode.GetIndex();
152  m_nDestEndNode = pEnd->nNode.GetIndex();
153  m_nDestEndContent = pEnd->nContent.GetIndex();
154 
155  m_nInsPosNode = rInsPos.nNode.GetIndex();
156  m_nInsPosContent = rInsPos.nContent.GetIndex();
157 
158  if( bCorrPam )
159  {
161  m_nDestEndNode--;
162  }
163 
165  pStt->nNode.GetNode().GetTextNode() &&
166  pEnd->nNode.GetNode().GetTextNode();
167  m_bJoinPrev = bJoin;
168 }
169 
171  const SwNodeIndex& rEnd,
172  const SwNodeIndex& rInsPos )
173 {
174  m_nDestStartNode = rStt.GetIndex();
175  m_nDestEndNode = rEnd.GetIndex();
177  {
179  m_nDestEndNode = rStt.GetIndex();
180  }
181  m_nInsPosNode = rInsPos.GetIndex();
182 
184 }
185 
187 {
188  SwDoc *const pDoc = & rContext.GetDoc();
189 
190  // Block so that we can jump out of it
191  do {
192  // create index position and section based on the existing values
193  SwNodeIndex aIdx( pDoc->GetNodes(), m_nDestStartNode );
194 
195  if( m_bMoveRange )
196  {
197  // only a move with SwRange
198  SwNodeRange aRg( aIdx, aIdx );
199  aRg.aEnd = m_nDestEndNode;
200  aIdx = m_nInsPosNode;
201  bool bSuccess = pDoc->getIDocumentContentOperations().MoveNodeRange( aRg, aIdx,
203  if (!bSuccess)
204  break;
205  }
206  else
207  {
208  SwPaM aPam( aIdx.GetNode(), m_nDestStartContent,
210 
211  // #i17764# if redlines are to be moved, we may not remove them
212  // before pDoc->Move gets a chance to handle them
213  if( ! m_bMoveRedlines )
214  RemoveIdxFromRange( aPam, false );
215 
216  SwPosition aPos( *pDoc->GetNodes()[ m_nInsPosNode] );
217  SwContentNode* pCNd = aPos.nNode.GetNode().GetContentNode();
218  aPos.nContent.Assign( pCNd, m_nInsPosContent );
219 
220  if( pCNd->HasSwAttrSet() )
221  pCNd->ResetAllAttr();
222 
223  if( pCNd->IsTextNode() && static_cast<SwTextNode*>(pCNd)->GetpSwpHints() )
224  static_cast<SwTextNode*>(pCNd)->ClearSwpHintsArr( false );
225 
226  // first delete all attributes at InsertPos
227  const bool bSuccess = pDoc->getIDocumentContentOperations().MoveRange( aPam, aPos, m_bMoveRedlines
230  if (!bSuccess)
231  break;
232 
233  aPam.Exchange();
234  aPam.DeleteMark();
235  if( aPam.GetNode().IsContentNode() )
236  aPam.GetNode().GetContentNode()->ResetAllAttr();
237  // the Pam will be dropped now
238  }
239 
240  SwTextNode* pTextNd = aIdx.GetNode().GetTextNode();
241  if( m_bJoinNext )
242  {
243  {
244  RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
245  SwIndex(pTextNd, pTextNd->GetText().getLength())));
246  }
247  // Are there any Pams in the next TextNode?
248  pTextNd->JoinNext();
249  }
250 
251  if( m_bJoinPrev && pTextNd->CanJoinPrev( &aIdx ) )
252  {
253  // Are there any Pams in the next TextNode?
254  pTextNd = aIdx.GetNode().GetTextNode();
255  {
256  RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
257  SwIndex( pTextNd, pTextNd->GetText().getLength())));
258  }
259  pTextNd->JoinNext();
260  }
261 
262  } while( false );
263 
264  if( pHistory )
265  {
266  if( m_nFootnoteStart != pHistory->Count() )
267  pHistory->Rollback( pDoc, m_nFootnoteStart );
268  pHistory->TmpRollback( pDoc, 0 );
269  pHistory->SetTmpEnd( pHistory->Count() );
270  }
271 
272  // set the cursor onto Undo area
273  if( !m_bMoveRange )
274  {
275  AddUndoRedoPaM(rContext);
276  }
277 }
278 
280 {
281  SwPaM& rPam = AddUndoRedoPaM(rContext);
282  SwDoc& rDoc = rContext.GetDoc();
283 
284  SwNodes& rNds = rDoc.GetNodes();
285  SwNodeIndex aIdx( rNds, m_nMoveDestNode );
286 
287  if( m_bMoveRange )
288  {
289  // only a move with SwRange
290  SwNodeRange aRg( rNds, m_nSttNode, rNds, m_nEndNode );
294  }
295  else
296  {
297  SwPaM aPam(*rPam.GetPoint());
298  SetPaM( aPam );
299  SwPosition aMvPos( aIdx, SwIndex( aIdx.GetNode().GetContentNode(),
301 
302  DelFootnote( aPam );
303  RemoveIdxFromRange( aPam, false );
304 
305  aIdx = aPam.Start()->nNode;
306  bool bJoinText = aIdx.GetNode().IsTextNode();
307 
308  --aIdx;
309  rDoc.getIDocumentContentOperations().MoveRange( aPam, aMvPos,
311 
312  if( m_nSttNode != m_nEndNode && bJoinText )
313  {
314  ++aIdx;
315  SwTextNode * pTextNd = aIdx.GetNode().GetTextNode();
316  if( pTextNd && pTextNd->CanJoinNext() )
317  {
318  {
319  RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
320  SwIndex(pTextNd, pTextNd->GetText().getLength())));
321  }
322  pTextNd->JoinNext();
323  }
324  }
325  *rPam.GetPoint() = *aPam.GetPoint();
326  rPam.SetMark();
327  *rPam.GetMark() = *aPam.GetMark();
328  }
329 }
330 
331 void SwUndoMove::DelFootnote( const SwPaM& rRange )
332 {
333  // is the current move from ContentArea into the special section?
334  SwDoc* pDoc = rRange.GetDoc();
335  sal_uLong nContentStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
336  if( m_nMoveDestNode < nContentStt &&
337  rRange.GetPoint()->nNode.GetIndex() >= nContentStt )
338  {
339  // delete all footnotes since they are undesired there
340  DelContentIndex( *rRange.GetMark(), *rRange.GetPoint(),
342 
343  if( pHistory && !pHistory->Count() )
344  {
345  pHistory.reset();
346  }
347  }
348 }
349 
350 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 m_nDestStartContent
SwPaM & AddUndoRedoPaM(::sw::UndoRedoContext &, bool const bCorrToContent=false) const
Definition: undobj.cxx:106
virtual sal_Int32 Len() const
Definition: node.cxx:1181
SwUndoMove(const SwPaM &, const SwPosition &)
Definition: unmove.cxx:30
virtual void UndoImpl(::sw::UndoRedoContext &) override
Definition: unmove.cxx:186
sal_uLong GetIndex() const
Definition: node.hxx:282
SwNode & GetEndOfAutotext() const
Section for all Flys/Header/Footers.
Definition: ndarr.hxx:157
std::unique_ptr< SwHistory > pHistory
Definition: undobj.hxx:156
Marks a position in the document model.
Definition: pam.hxx:35
const OUString & GetText() const
Definition: ndtxt.hxx:211
SwUndoId
Definition: swundo.hxx:29
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:219
SwNodeIndex nNode
Definition: pam.hxx:37
sal_uIntPtr sal_uLong
const SwPosition * GetMark() const
Definition: pam.hxx:209
sal_uLong m_nEndNode
Definition: undobj.hxx:218
Definition: doc.hxx:185
sal_uLong m_nDestEndNode
SwNode & GetNode() const
Definition: ndindex.hxx:118
virtual bool MoveRange(SwPaM &, SwPosition &, SwMoveFlags)=0
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:347
bool CanJoinNext(SwNodeIndex *pIdx=nullptr) const
Is it possible to join two nodes? In pIdx the second position can be returned.
Definition: node.cxx:1789
virtual SwContentNode * JoinNext() override
Definition: ndtxt.cxx:949
SwIndex nContent
Definition: pam.hxx:38
SwNodeIndex aStart
Definition: ndindex.hxx:131
sal_uLong GetIndex() const
Definition: ndindex.hxx:151
bool m_bMoveRedlines
void DelFootnote(const SwPaM &)
Definition: unmove.cxx:331
SwDoc & GetDoc() const
Definition: UndoCore.hxx:94
static void RemoveIdxFromRange(SwPaM &rPam, bool bMoveNext)
Definition: undobj.cxx:124
sal_Int32 m_nMoveDestContent
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
const SwAttrSet * GetpSwAttrSet() const
Definition: node.hxx:443
sal_Int32 m_nInsPosContent
const SwPosition * GetPoint() const
Definition: pam.hxx:207
void DelContentIndex(const SwPosition &pMark, const SwPosition &pPoint, DelContentType nDelContentType=DelContentType::AllMask)
Definition: undobj.cxx:846
bool CanJoinPrev(SwNodeIndex *pIdx=nullptr) const
Can we join two Nodes? We can return the 2nd position in pIdx.
Definition: node.cxx:1813
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:198
SwContentNode * GetContentNode()
Definition: node.hxx:615
virtual void RedoImpl(::sw::UndoRedoContext &) override
Definition: unmove.cxx:279
sal_Int32 m_nEndContent
Definition: undobj.hxx:219
SwDoc * GetDoc() const
Definition: pam.hxx:243
Marks a character position inside a document model node.
Definition: index.hxx:37
Marks a node in the document model.
Definition: ndindex.hxx:31
virtual sal_uInt16 ResetAllAttr()
Definition: node.cxx:1684
bool HasSwAttrSet() const
Definition: node.hxx:444
virtual bool MoveNodeRange(SwNodeRange &, SwNodeIndex &, SwMoveFlags)=0
const SwPosition * Start() const
Definition: pam.hxx:212
sal_uLong m_nSttNode
Definition: undobj.hxx:218
sal_uLong m_nDestStartNode
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
void SetPaM(SwPaM &, bool bCorrToContent=false) const
Definition: undobj.cxx:78
void SetDestRange(const SwPaM &, const SwPosition &, bool, bool)
set the destination range after the move
Definition: unmove.cxx:141
sal_Int32 GetIndex() const
Definition: index.hxx:95
SwNodes & GetNodes()
Definition: doc.hxx:402
SwNodeIndex aEnd
Definition: ndindex.hxx:132
static void RemoveIdxRel(sal_uLong, const SwPosition &)
Definition: undobj.cxx:151
sal_uLong m_nMoveDestNode
virtual void SetMark()
Unless this is called, the getter method of Mark will return Point.
Definition: pam.cxx:455
sal_Int32 m_nDestEndContent
bool IsTextNode() const
Definition: node.hxx:636
const sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:61
sal_Int32 m_nSttContent
Definition: undobj.hxx:219
sal_uInt16 m_nFootnoteStart
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:843
sal_uLong m_nInsPosNode
SwTextFormatColl * GetTextColl() const
Definition: ndtxt.hxx:837