Line data Source code
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 0 : SwUndoMove::SwUndoMove( const SwPaM& rRange, const SwPosition& rMvPos )
31 : : SwUndo( UNDO_MOVE )
32 : , SwUndRng( rRange )
33 : , nDestSttNode(0)
34 : , nDestEndNode(0)
35 : , nInsPosNode(0)
36 0 : , nMvDestNode(rMvPos.nNode.GetIndex())
37 : , nDestSttContent(0)
38 : , nDestEndContent(0)
39 : , nInsPosContent(0)
40 0 : , nMvDestContent(rMvPos.nContent.GetIndex())
41 : , bJoinNext(false)
42 : , bJoinPrev(false)
43 : , bMoveRange(false)
44 0 : , bMoveRedlines(false)
45 : {
46 : // get StartNode from footnotes before delete!
47 0 : SwDoc* pDoc = rRange.GetDoc();
48 0 : SwTextNode* pTextNd = pDoc->GetNodes()[ nSttNode ]->GetTextNode();
49 0 : SwTextNode* pEndTextNd = pDoc->GetNodes()[ nEndNode ]->GetTextNode();
50 :
51 0 : pHistory = new SwHistory;
52 :
53 0 : if( pTextNd )
54 : {
55 0 : pHistory->Add( pTextNd->GetTextColl(), nSttNode, ND_TEXTNODE );
56 0 : if ( pTextNd->GetpSwpHints() )
57 : {
58 : pHistory->CopyAttr( pTextNd->GetpSwpHints(), nSttNode,
59 0 : 0, pTextNd->GetText().getLength(), false );
60 : }
61 0 : if( pTextNd->HasSwAttrSet() )
62 0 : pHistory->CopyFormatAttr( *pTextNd->GetpSwAttrSet(), nSttNode );
63 : }
64 0 : if( pEndTextNd && pEndTextNd != pTextNd )
65 : {
66 0 : pHistory->Add( pEndTextNd->GetTextColl(), nEndNode, ND_TEXTNODE );
67 0 : if ( pEndTextNd->GetpSwpHints() )
68 : {
69 : pHistory->CopyAttr( pEndTextNd->GetpSwpHints(), nEndNode,
70 0 : 0, pEndTextNd->GetText().getLength(), false );
71 : }
72 0 : if( pEndTextNd->HasSwAttrSet() )
73 0 : pHistory->CopyFormatAttr( *pEndTextNd->GetpSwAttrSet(), nEndNode );
74 : }
75 :
76 0 : pTextNd = rMvPos.nNode.GetNode().GetTextNode();
77 0 : if (0 != pTextNd)
78 : {
79 0 : pHistory->Add( pTextNd->GetTextColl(), nMvDestNode, ND_TEXTNODE );
80 0 : if ( pTextNd->GetpSwpHints() )
81 : {
82 : pHistory->CopyAttr( pTextNd->GetpSwpHints(), nMvDestNode,
83 0 : 0, pTextNd->GetText().getLength(), false );
84 : }
85 0 : if( pTextNd->HasSwAttrSet() )
86 0 : pHistory->CopyFormatAttr( *pTextNd->GetpSwAttrSet(), nMvDestNode );
87 : }
88 :
89 0 : nFootnoteStt = pHistory->Count();
90 0 : DelFootnote( rRange );
91 :
92 0 : if( pHistory && !pHistory->Count() )
93 0 : DELETEZ( pHistory );
94 0 : }
95 :
96 0 : SwUndoMove::SwUndoMove( SwDoc* pDoc, const SwNodeRange& rRg,
97 : const SwNodeIndex& rMvPos )
98 : : SwUndo(UNDO_MOVE)
99 : , nDestSttNode(0)
100 : , nDestEndNode(0)
101 : , nInsPosNode(0)
102 0 : , nMvDestNode(rMvPos.GetIndex())
103 : , nDestSttContent(0)
104 : , nDestEndContent(0)
105 : , nInsPosContent(0)
106 0 : , bMoveRedlines(false)
107 : {
108 0 : bMoveRange = true;
109 0 : bJoinNext = bJoinPrev = false;
110 :
111 0 : nSttContent = nEndContent = nMvDestContent = COMPLETE_STRING;
112 :
113 0 : nSttNode = rRg.aStart.GetIndex();
114 0 : 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 0 : sal_uLong nContentStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
121 0 : if( nMvDestNode < nContentStt && rRg.aStart.GetIndex() > nContentStt )
122 : {
123 : // delete all footnotes since they are undesired there
124 0 : SwPosition aPtPos( rRg.aEnd );
125 0 : SwContentNode* pCNd = rRg.aEnd.GetNode().GetContentNode();
126 0 : if( pCNd )
127 0 : aPtPos.nContent.Assign( pCNd, pCNd->Len() );
128 0 : SwPosition aMkPos( rRg.aStart );
129 0 : if( 0 != ( pCNd = aMkPos.nNode.GetNode().GetContentNode() ))
130 0 : aMkPos.nContent.Assign( pCNd, 0 );
131 :
132 0 : DelContentIndex( aMkPos, aPtPos, nsDelContentType::DELCNT_FTN );
133 :
134 0 : if( pHistory && !pHistory->Count() )
135 0 : DELETEZ( pHistory );
136 : }
137 :
138 0 : nFootnoteStt = 0;
139 0 : }
140 :
141 0 : void SwUndoMove::SetDestRange( const SwPaM& rRange,
142 : const SwPosition& rInsPos,
143 : bool bJoin, bool bCorrPam )
144 : {
145 0 : const SwPosition *pStt = rRange.Start(),
146 0 : *pEnd = rRange.GetPoint() == pStt
147 : ? rRange.GetMark()
148 0 : : rRange.GetPoint();
149 :
150 0 : nDestSttNode = pStt->nNode.GetIndex();
151 0 : nDestSttContent = pStt->nContent.GetIndex();
152 0 : nDestEndNode = pEnd->nNode.GetIndex();
153 0 : nDestEndContent = pEnd->nContent.GetIndex();
154 :
155 0 : nInsPosNode = rInsPos.nNode.GetIndex();
156 0 : nInsPosContent = rInsPos.nContent.GetIndex();
157 :
158 0 : if( bCorrPam )
159 : {
160 0 : nDestSttNode--;
161 0 : nDestEndNode--;
162 : }
163 :
164 0 : bJoinNext = nDestSttNode != nDestEndNode &&
165 0 : pStt->nNode.GetNode().GetTextNode() &&
166 0 : pEnd->nNode.GetNode().GetTextNode();
167 0 : bJoinPrev = bJoin;
168 0 : }
169 :
170 0 : void SwUndoMove::SetDestRange( const SwNodeIndex& rStt,
171 : const SwNodeIndex& rEnd,
172 : const SwNodeIndex& rInsPos )
173 : {
174 0 : nDestSttNode = rStt.GetIndex();
175 0 : nDestEndNode = rEnd.GetIndex();
176 0 : if( nDestSttNode > nDestEndNode )
177 : {
178 0 : nDestSttNode = nDestEndNode;
179 0 : nDestEndNode = rStt.GetIndex();
180 : }
181 0 : nInsPosNode = rInsPos.GetIndex();
182 :
183 0 : nDestSttContent = nDestEndContent = nInsPosContent = COMPLETE_STRING;
184 0 : }
185 :
186 0 : void SwUndoMove::UndoImpl(::sw::UndoRedoContext & rContext)
187 : {
188 0 : 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 0 : SwNodeIndex aIdx( pDoc->GetNodes(), nDestSttNode );
194 :
195 0 : if( bMoveRange )
196 : {
197 : // only a move with SwRange
198 0 : SwNodeRange aRg( aIdx, aIdx );
199 0 : aRg.aEnd = nDestEndNode;
200 0 : aIdx = nInsPosNode;
201 0 : bool bSuccess = pDoc->getIDocumentContentOperations().MoveNodeRange( aRg, aIdx,
202 0 : SwMoveFlags::DEFAULT );
203 0 : if (!bSuccess)
204 0 : break;
205 : }
206 : else
207 : {
208 0 : SwPaM aPam( aIdx.GetNode(), nDestSttContent,
209 0 : *pDoc->GetNodes()[ nDestEndNode ], nDestEndContent );
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 0 : if( ! bMoveRedlines )
214 0 : RemoveIdxFromRange( aPam, false );
215 :
216 0 : SwPosition aPos( *pDoc->GetNodes()[ nInsPosNode] );
217 0 : SwContentNode* pCNd = aPos.nNode.GetNode().GetContentNode();
218 0 : aPos.nContent.Assign( pCNd, nInsPosContent );
219 :
220 0 : if( pCNd->HasSwAttrSet() )
221 0 : pCNd->ResetAllAttr();
222 :
223 0 : if( pCNd->IsTextNode() && static_cast<SwTextNode*>(pCNd)->GetpSwpHints() )
224 0 : static_cast<SwTextNode*>(pCNd)->ClearSwpHintsArr( false );
225 :
226 : // first delete all attributes at InsertPos
227 0 : const bool bSuccess = pDoc->getIDocumentContentOperations().MoveRange( aPam, aPos, (bMoveRedlines)
228 : ? SwMoveFlags::REDLINES
229 0 : : SwMoveFlags::DEFAULT );
230 0 : if (!bSuccess)
231 0 : break;
232 :
233 0 : aPam.Exchange();
234 0 : aPam.DeleteMark();
235 0 : if( aPam.GetNode().IsContentNode() )
236 0 : aPam.GetNode().GetContentNode()->ResetAllAttr();
237 : // the Pam will be dropped now
238 : }
239 :
240 0 : SwTextNode* pTextNd = aIdx.GetNode().GetTextNode();
241 0 : if( bJoinNext )
242 : {
243 : {
244 0 : RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
245 0 : SwIndex(pTextNd, pTextNd->GetText().getLength())));
246 : }
247 : // Are there any Pams in the next TextNode?
248 0 : pTextNd->JoinNext();
249 : }
250 :
251 0 : if( bJoinPrev && pTextNd->CanJoinPrev( &aIdx ) )
252 : {
253 : // Are there any Pams in the next TextNode?
254 0 : pTextNd = aIdx.GetNode().GetTextNode();
255 : {
256 0 : RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
257 0 : SwIndex( pTextNd, pTextNd->GetText().getLength())));
258 : }
259 0 : pTextNd->JoinNext();
260 0 : }
261 :
262 : } while( false );
263 :
264 0 : if( pHistory )
265 : {
266 0 : if( nFootnoteStt != pHistory->Count() )
267 0 : pHistory->Rollback( pDoc, nFootnoteStt );
268 0 : pHistory->TmpRollback( pDoc, 0 );
269 0 : pHistory->SetTmpEnd( pHistory->Count() );
270 : }
271 :
272 : // set the cursor onto Undo area
273 0 : if( !bMoveRange )
274 : {
275 0 : AddUndoRedoPaM(rContext);
276 : }
277 0 : }
278 :
279 0 : void SwUndoMove::RedoImpl(::sw::UndoRedoContext & rContext)
280 : {
281 0 : SwPaM *const pPam = & AddUndoRedoPaM(rContext);
282 0 : SwDoc & rDoc = rContext.GetDoc();
283 :
284 0 : SwNodes& rNds = rDoc.GetNodes();
285 0 : SwNodeIndex aIdx( rNds, nMvDestNode );
286 :
287 0 : if( bMoveRange )
288 : {
289 : // only a move with SwRange
290 0 : SwNodeRange aRg( rNds, nSttNode, rNds, nEndNode );
291 0 : rDoc.getIDocumentContentOperations().MoveNodeRange( aRg, aIdx, (bMoveRedlines)
292 : ? SwMoveFlags::REDLINES
293 0 : : SwMoveFlags::DEFAULT );
294 : }
295 : else
296 : {
297 0 : SwPaM aPam( *pPam->GetPoint() );
298 0 : SetPaM( aPam );
299 0 : SwPosition aMvPos( aIdx, SwIndex( aIdx.GetNode().GetContentNode(),
300 0 : nMvDestContent ));
301 :
302 0 : DelFootnote( aPam );
303 0 : RemoveIdxFromRange( aPam, false );
304 :
305 0 : aIdx = aPam.Start()->nNode;
306 0 : bool bJoinText = aIdx.GetNode().IsTextNode();
307 :
308 0 : --aIdx;
309 0 : rDoc.getIDocumentContentOperations().MoveRange( aPam, aMvPos,
310 0 : SwMoveFlags::DEFAULT );
311 :
312 0 : if( nSttNode != nEndNode && bJoinText )
313 : {
314 0 : ++aIdx;
315 0 : SwTextNode * pTextNd = aIdx.GetNode().GetTextNode();
316 0 : if( pTextNd && pTextNd->CanJoinNext() )
317 : {
318 : {
319 0 : RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
320 0 : SwIndex(pTextNd, pTextNd->GetText().getLength())));
321 : }
322 0 : pTextNd->JoinNext();
323 : }
324 : }
325 0 : *pPam->GetPoint() = *aPam.GetPoint();
326 0 : pPam->SetMark();
327 0 : *pPam->GetMark() = *aPam.GetMark();
328 0 : }
329 0 : }
330 :
331 0 : void SwUndoMove::DelFootnote( const SwPaM& rRange )
332 : {
333 : // is the current move from ContentArea into the special section?
334 0 : SwDoc* pDoc = rRange.GetDoc();
335 0 : sal_uLong nContentStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
336 0 : if( nMvDestNode < nContentStt &&
337 0 : rRange.GetPoint()->nNode.GetIndex() >= nContentStt )
338 : {
339 : // delete all footnotes since they are undesired there
340 0 : DelContentIndex( *rRange.GetMark(), *rRange.GetPoint(),
341 0 : nsDelContentType::DELCNT_FTN );
342 :
343 0 : if( pHistory && !pHistory->Count() )
344 0 : delete pHistory, pHistory = 0;
345 : }
346 177 : }
347 :
348 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|