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_bMoveRange(false)
43  , m_bMoveRedlines(false)
44 {
45  // get StartNode from footnotes before delete!
46  SwDoc* pDoc = rRange.GetDoc();
47  SwTextNode* pTextNd = pDoc->GetNodes()[ m_nSttNode ]->GetTextNode();
48  SwTextNode* pEndTextNd = pDoc->GetNodes()[ m_nEndNode ]->GetTextNode();
49 
50  m_pHistory.reset( new SwHistory );
51 
52  if( pTextNd )
53  {
55  if ( pTextNd->GetpSwpHints() )
56  {
57  m_pHistory->CopyAttr( pTextNd->GetpSwpHints(), m_nSttNode,
58  0, pTextNd->GetText().getLength(), false );
59  }
60  if( pTextNd->HasSwAttrSet() )
61  m_pHistory->CopyFormatAttr( *pTextNd->GetpSwAttrSet(), m_nSttNode );
62  }
63  if( pEndTextNd && pEndTextNd != pTextNd )
64  {
65  m_pHistory->Add( pEndTextNd->GetTextColl(), m_nEndNode, SwNodeType::Text );
66  if ( pEndTextNd->GetpSwpHints() )
67  {
68  m_pHistory->CopyAttr( pEndTextNd->GetpSwpHints(), m_nEndNode,
69  0, pEndTextNd->GetText().getLength(), false );
70  }
71  if( pEndTextNd->HasSwAttrSet() )
72  m_pHistory->CopyFormatAttr( *pEndTextNd->GetpSwAttrSet(), m_nEndNode );
73  }
74 
75  pTextNd = rMvPos.nNode.GetNode().GetTextNode();
76  if (nullptr != pTextNd)
77  {
79  if ( pTextNd->GetpSwpHints() )
80  {
81  m_pHistory->CopyAttr( pTextNd->GetpSwpHints(), m_nMoveDestNode,
82  0, pTextNd->GetText().getLength(), false );
83  }
84  if( pTextNd->HasSwAttrSet() )
85  m_pHistory->CopyFormatAttr( *pTextNd->GetpSwAttrSet(), m_nMoveDestNode );
86  }
87 
88  m_nFootnoteStart = m_pHistory->Count();
89  DelFootnote( rRange );
90 
91  if( m_pHistory && !m_pHistory->Count() )
92  m_pHistory.reset();
93 }
94 
96  const SwNodeIndex& rMvPos )
97  : SwUndo(SwUndoId::MOVE, pDoc)
98  , m_nDestStartNode(0)
99  , m_nDestEndNode(0)
100  , m_nInsPosNode(0)
101  , m_nMoveDestNode(rMvPos.GetIndex())
102  , m_nDestStartContent(0)
103  , m_nDestEndContent(0)
104  , m_nInsPosContent(0)
105  , m_bMoveRedlines(false)
106 {
107  m_bMoveRange = true;
108  m_bJoinNext = false;
109 
111 
112  m_nSttNode = rRg.aStart.GetIndex();
113  m_nEndNode = rRg.aEnd.GetIndex();
114 
115 // DelFootnote( rRange );
116 // FIXME: duplication of the method body of DelFootnote below
117 
118  // is the current move from ContentArea into the special section?
119  sal_uLong nContentStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
120  if( m_nMoveDestNode < nContentStt && rRg.aStart.GetIndex() > nContentStt )
121  {
122  // delete all footnotes since they are undesired there
123  SwPosition aPtPos( rRg.aEnd );
124  SwContentNode* pCNd = rRg.aEnd.GetNode().GetContentNode();
125  if( pCNd )
126  aPtPos.nContent.Assign( pCNd, pCNd->Len() );
127  SwPosition aMkPos( rRg.aStart );
128  if( nullptr != ( pCNd = aMkPos.nNode.GetNode().GetContentNode() ))
129  aMkPos.nContent.Assign( pCNd, 0 );
130 
131  DelContentIndex( aMkPos, aPtPos, DelContentType::Ftn );
132 
133  if( m_pHistory && !m_pHistory->Count() )
134  m_pHistory.reset();
135  }
136 
137  m_nFootnoteStart = 0;
138 }
139 
141  const SwNodeIndex& rEnd,
142  const SwNodeIndex& rInsPos )
143 {
144  m_nDestStartNode = rStt.GetIndex();
145  m_nDestEndNode = rEnd.GetIndex();
147  {
149  m_nDestEndNode = rStt.GetIndex();
150  }
151  m_nInsPosNode = rInsPos.GetIndex();
152 
154 }
155 
157 {
158  SwDoc *const pDoc = & rContext.GetDoc();
159 
160  // Block so that we can jump out of it
161  do {
162  // create index position and section based on the existing values
163  SwNodeIndex aIdx( pDoc->GetNodes(), m_nDestStartNode );
164 
165  if( m_bMoveRange )
166  {
167  // only a move with SwRange
168  SwNodeRange aRg( aIdx, aIdx );
169  aRg.aEnd = m_nDestEndNode;
170  aIdx = m_nInsPosNode;
171  bool bSuccess = pDoc->getIDocumentContentOperations().MoveNodeRange( aRg, aIdx,
173  if (!bSuccess)
174  break;
175  }
176  else
177  {
178  SwPaM aPam( aIdx.GetNode(), m_nDestStartContent,
180 
181  // #i17764# if redlines are to be moved, we may not remove them
182  // before pDoc->Move gets a chance to handle them
183  if( ! m_bMoveRedlines )
184  RemoveIdxFromRange( aPam, false );
185 
186  SwPosition aPos( *pDoc->GetNodes()[ m_nInsPosNode] );
187  SwContentNode* pCNd = aPos.nNode.GetNode().GetContentNode();
188  aPos.nContent.Assign( pCNd, m_nInsPosContent );
189 
190  if( pCNd->HasSwAttrSet() )
191  pCNd->ResetAllAttr();
192 
193  if( pCNd->IsTextNode() && static_cast<SwTextNode*>(pCNd)->GetpSwpHints() )
194  static_cast<SwTextNode*>(pCNd)->ClearSwpHintsArr( false );
195 
196  // first delete all attributes at InsertPos
197  const bool bSuccess = pDoc->getIDocumentContentOperations().MoveRange( aPam, aPos, m_bMoveRedlines
200  if (!bSuccess)
201  break;
202 
203  aPam.Exchange();
204  aPam.DeleteMark();
205  if( aPam.GetNode().IsContentNode() )
206  aPam.GetNode().GetContentNode()->ResetAllAttr();
207  // the Pam will be dropped now
208  }
209 
210  SwTextNode* pTextNd = aIdx.GetNode().GetTextNode();
211  if( m_bJoinNext )
212  {
213  {
214  RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
215  SwIndex(pTextNd, pTextNd->GetText().getLength())));
216  }
217  // Are there any Pams in the next TextNode?
218  pTextNd->JoinNext();
219  }
220 
221  } while( false );
222 
223  if( m_pHistory )
224  {
225  if( m_nFootnoteStart != m_pHistory->Count() )
226  m_pHistory->Rollback( pDoc, m_nFootnoteStart );
227  m_pHistory->TmpRollback( pDoc, 0 );
228  m_pHistory->SetTmpEnd( m_pHistory->Count() );
229  }
230 
231  // set the cursor onto Undo area
232  if( !m_bMoveRange )
233  {
234  AddUndoRedoPaM(rContext);
235  }
236 }
237 
239 {
240  SwPaM& rPam = AddUndoRedoPaM(rContext);
241  SwDoc& rDoc = rContext.GetDoc();
242 
243  SwNodes& rNds = rDoc.GetNodes();
244  SwNodeIndex aIdx( rNds, m_nMoveDestNode );
245 
246  if( m_bMoveRange )
247  {
248  // only a move with SwRange
249  SwNodeRange aRg( rNds, m_nSttNode, rNds, m_nEndNode );
253  }
254  else
255  {
256  SwPaM aPam(*rPam.GetPoint());
257  SetPaM( aPam );
258  SwPosition aMvPos( aIdx, SwIndex( aIdx.GetNode().GetContentNode(),
260 
261  DelFootnote( aPam );
262  RemoveIdxFromRange( aPam, false );
263 
264  aIdx = aPam.Start()->nNode;
265  bool bJoinText = aIdx.GetNode().IsTextNode();
266 
267  --aIdx;
268  rDoc.getIDocumentContentOperations().MoveRange( aPam, aMvPos,
270 
271  if( m_nSttNode != m_nEndNode && bJoinText )
272  {
273  ++aIdx;
274  SwTextNode * pTextNd = aIdx.GetNode().GetTextNode();
275  if( pTextNd && pTextNd->CanJoinNext() )
276  {
277  {
278  RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
279  SwIndex(pTextNd, pTextNd->GetText().getLength())));
280  }
281  pTextNd->JoinNext();
282  }
283  }
284  *rPam.GetPoint() = *aPam.GetPoint();
285  rPam.SetMark();
286  *rPam.GetMark() = *aPam.GetMark();
287  }
288 }
289 
290 void SwUndoMove::DelFootnote( const SwPaM& rRange )
291 {
292  // is the current move from ContentArea into the special section?
293  SwDoc* pDoc = rRange.GetDoc();
294  sal_uLong nContentStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
295  if( m_nMoveDestNode < nContentStt &&
296  rRange.GetPoint()->nNode.GetIndex() >= nContentStt )
297  {
298  // delete all footnotes since they are undesired there
299  DelContentIndex( *rRange.GetMark(), *rRange.GetPoint(),
301 
302  if( m_pHistory && !m_pHistory->Count() )
303  {
304  m_pHistory.reset();
305  }
306  }
307 }
308 
309 /* 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:1180
SwUndoMove(const SwPaM &, const SwPosition &)
Definition: unmove.cxx:30
virtual void UndoImpl(::sw::UndoRedoContext &) override
Definition: unmove.cxx:156
sal_uLong GetIndex() const
Definition: node.hxx:282
SwNode & GetEndOfAutotext() const
Section for all Flys/Header/Footers.
Definition: ndarr.hxx:157
Marks a position in the document model.
Definition: pam.hxx:35
void SetDestRange(const SwNodeIndex &rStt, const SwNodeIndex &rEnd, const SwNodeIndex &rInsPos)
set the destination range after the move
Definition: unmove.cxx:140
std::unique_ptr< SwHistory > m_pHistory
Definition: undobj.hxx:156
const OUString & GetText() const
Definition: ndtxt.hxx:210
SwUndoId
Definition: swundo.hxx:29
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:218
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:119
virtual bool MoveRange(SwPaM &, SwPosition &, SwMoveFlags)=0
IDocumentContentOperations const & getIDocumentContentOperations() const
Definition: doc.cxx:314
bool CanJoinNext(SwNodeIndex *pIdx=nullptr) const
Is it possible to join two nodes? In pIdx the second position can be returned.
Definition: node.cxx:1788
virtual SwContentNode * JoinNext() override
Definition: ndtxt.cxx:949
SwIndex nContent
Definition: pam.hxx:38
SwNodeIndex aStart
Definition: ndindex.hxx:132
sal_uLong GetIndex() const
Definition: ndindex.hxx:152
bool m_bMoveRedlines
void DelFootnote(const SwPaM &)
Definition: unmove.cxx:290
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:843
SwIndex & Assign(SwIndexReg *, sal_Int32)
Definition: index.cxx:198
SwContentNode * GetContentNode()
Definition: node.hxx:615
virtual void RedoImpl(::sw::UndoRedoContext &) override
Definition: unmove.cxx:238
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:1683
bool HasSwAttrSet() const
Definition: node.hxx:444
virtual bool MoveNodeRange(SwNodeRange &, SwNodeIndex &, SwMoveFlags)=0
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
SwNodes & GetNodes()
Definition: doc.hxx:402
SwNodeIndex aEnd
Definition: ndindex.hxx:133
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:459
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:842
sal_uLong m_nInsPosNode
SwTextFormatColl * GetTextColl() const
Definition: ndtxt.hxx:836