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 : , nDestSttCntnt(0)
38 : , nDestEndCntnt(0)
39 : , nInsPosCntnt(0)
40 0 : , nMvDestCntnt(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 : SwTxtNode* pTxtNd = pDoc->GetNodes()[ nSttNode ]->GetTxtNode();
49 0 : SwTxtNode* pEndTxtNd = pDoc->GetNodes()[ nEndNode ]->GetTxtNode();
50 :
51 0 : pHistory = new SwHistory;
52 :
53 0 : if( pTxtNd )
54 : {
55 0 : pHistory->Add( pTxtNd->GetTxtColl(), nSttNode, ND_TEXTNODE );
56 0 : if ( pTxtNd->GetpSwpHints() )
57 : {
58 : pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode,
59 0 : 0, pTxtNd->GetTxt().getLength(), false );
60 : }
61 0 : if( pTxtNd->HasSwAttrSet() )
62 0 : pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nSttNode );
63 : }
64 0 : if( pEndTxtNd && pEndTxtNd != pTxtNd )
65 : {
66 0 : pHistory->Add( pEndTxtNd->GetTxtColl(), nEndNode, ND_TEXTNODE );
67 0 : if ( pEndTxtNd->GetpSwpHints() )
68 : {
69 : pHistory->CopyAttr( pEndTxtNd->GetpSwpHints(), nEndNode,
70 0 : 0, pEndTxtNd->GetTxt().getLength(), false );
71 : }
72 0 : if( pEndTxtNd->HasSwAttrSet() )
73 0 : pHistory->CopyFmtAttr( *pEndTxtNd->GetpSwAttrSet(), nEndNode );
74 : }
75 :
76 0 : pTxtNd = rMvPos.nNode.GetNode().GetTxtNode();
77 0 : if (0 != pTxtNd)
78 : {
79 0 : pHistory->Add( pTxtNd->GetTxtColl(), nMvDestNode, ND_TEXTNODE );
80 0 : if ( pTxtNd->GetpSwpHints() )
81 : {
82 : pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nMvDestNode,
83 0 : 0, pTxtNd->GetTxt().getLength(), false );
84 : }
85 0 : if( pTxtNd->HasSwAttrSet() )
86 0 : pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nMvDestNode );
87 : }
88 :
89 0 : nFtnStt = pHistory->Count();
90 0 : DelFtn( 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 0 : nMvDestNode( rMvPos.GetIndex() ),
100 0 : bMoveRedlines( false )
101 : {
102 0 : bMoveRange = sal_True;
103 0 : bJoinNext = bJoinPrev = sal_False;
104 :
105 0 : nSttCntnt = nEndCntnt = nMvDestCntnt = COMPLETE_STRING;
106 :
107 0 : nSttNode = rRg.aStart.GetIndex();
108 0 : nEndNode = rRg.aEnd.GetIndex();
109 :
110 : // DelFtn( rRange );
111 : // FIXME: duplication of the method body of DelFtn below
112 :
113 : // is the current move from CntntArea into the special section?
114 0 : sal_uLong nCntntStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
115 0 : if( nMvDestNode < nCntntStt && rRg.aStart.GetIndex() > nCntntStt )
116 : {
117 : // delete all footnotes since they are undesired there
118 0 : SwPosition aPtPos( rRg.aEnd );
119 0 : SwCntntNode* pCNd = rRg.aEnd.GetNode().GetCntntNode();
120 0 : if( pCNd )
121 0 : aPtPos.nContent.Assign( pCNd, pCNd->Len() );
122 0 : SwPosition aMkPos( rRg.aStart );
123 0 : if( 0 != ( pCNd = aMkPos.nNode.GetNode().GetCntntNode() ))
124 0 : aMkPos.nContent.Assign( pCNd, 0 );
125 :
126 0 : DelCntntIndex( aMkPos, aPtPos, nsDelCntntType::DELCNT_FTN );
127 :
128 0 : if( pHistory && !pHistory->Count() )
129 0 : DELETEZ( pHistory );
130 : }
131 :
132 0 : nFtnStt = 0;
133 0 : }
134 :
135 0 : void SwUndoMove::SetDestRange( const SwPaM& rRange,
136 : const SwPosition& rInsPos,
137 : sal_Bool bJoin, sal_Bool bCorrPam )
138 : {
139 0 : const SwPosition *pStt = rRange.Start(),
140 0 : *pEnd = rRange.GetPoint() == pStt
141 : ? rRange.GetMark()
142 0 : : rRange.GetPoint();
143 :
144 0 : nDestSttNode = pStt->nNode.GetIndex();
145 0 : nDestSttCntnt = pStt->nContent.GetIndex();
146 0 : nDestEndNode = pEnd->nNode.GetIndex();
147 0 : nDestEndCntnt = pEnd->nContent.GetIndex();
148 :
149 0 : nInsPosNode = rInsPos.nNode.GetIndex();
150 0 : nInsPosCntnt = rInsPos.nContent.GetIndex();
151 :
152 0 : if( bCorrPam )
153 : {
154 0 : nDestSttNode--;
155 0 : nDestEndNode--;
156 : }
157 :
158 0 : bJoinNext = nDestSttNode != nDestEndNode &&
159 0 : pStt->nNode.GetNode().GetTxtNode() &&
160 0 : pEnd->nNode.GetNode().GetTxtNode();
161 0 : bJoinPrev = bJoin;
162 0 : }
163 :
164 0 : void SwUndoMove::SetDestRange( const SwNodeIndex& rStt,
165 : const SwNodeIndex& rEnd,
166 : const SwNodeIndex& rInsPos )
167 : {
168 0 : nDestSttNode = rStt.GetIndex();
169 0 : nDestEndNode = rEnd.GetIndex();
170 0 : if( nDestSttNode > nDestEndNode )
171 : {
172 0 : nDestSttNode = nDestEndNode;
173 0 : nDestEndNode = rStt.GetIndex();
174 : }
175 0 : nInsPosNode = rInsPos.GetIndex();
176 :
177 0 : nDestSttCntnt = nDestEndCntnt = nInsPosCntnt = COMPLETE_STRING;
178 0 : }
179 :
180 0 : void SwUndoMove::UndoImpl(::sw::UndoRedoContext & rContext)
181 : {
182 0 : SwDoc *const pDoc = & rContext.GetDoc();
183 :
184 : // Block so that we can jump out of it
185 : do {
186 : // create index position and section based on the existing values
187 0 : SwNodeIndex aIdx( pDoc->GetNodes(), nDestSttNode );
188 :
189 0 : if( bMoveRange )
190 : {
191 : // only a move with SwRange
192 0 : SwNodeRange aRg( aIdx, aIdx );
193 0 : aRg.aEnd = nDestEndNode;
194 0 : aIdx = nInsPosNode;
195 : bool bSuccess = pDoc->MoveNodeRange( aRg, aIdx,
196 0 : IDocumentContentOperations::DOC_MOVEDEFAULT );
197 0 : if (!bSuccess)
198 0 : break;
199 : }
200 : else
201 : {
202 0 : SwPaM aPam( aIdx.GetNode(), nDestSttCntnt,
203 0 : *pDoc->GetNodes()[ nDestEndNode ], nDestEndCntnt );
204 :
205 : // #i17764# if redlines are to be moved, we may not remove them
206 : // before pDoc->Move gets a chance to handle them
207 0 : if( ! bMoveRedlines )
208 0 : RemoveIdxFromRange( aPam, false );
209 :
210 0 : SwPosition aPos( *pDoc->GetNodes()[ nInsPosNode] );
211 0 : SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
212 0 : aPos.nContent.Assign( pCNd, nInsPosCntnt );
213 :
214 0 : if( pCNd->HasSwAttrSet() )
215 0 : pCNd->ResetAllAttr();
216 :
217 0 : if( pCNd->IsTxtNode() && ((SwTxtNode*)pCNd)->GetpSwpHints() )
218 0 : ((SwTxtNode*)pCNd)->ClearSwpHintsArr( false );
219 :
220 : // first delete all attributes at InsertPos
221 : const bool bSuccess = pDoc->MoveRange( aPam, aPos, (bMoveRedlines)
222 : ? IDocumentContentOperations::DOC_MOVEREDLINES
223 0 : : IDocumentContentOperations::DOC_MOVEDEFAULT );
224 0 : if (!bSuccess)
225 0 : break;
226 :
227 0 : aPam.Exchange();
228 0 : aPam.DeleteMark();
229 0 : if( aPam.GetNode()->IsCntntNode() )
230 0 : aPam.GetNode()->GetCntntNode()->ResetAllAttr();
231 : // the Pam will be dropped now
232 : }
233 :
234 0 : SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode();
235 0 : if( bJoinNext )
236 : {
237 : {
238 0 : RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
239 0 : SwIndex(pTxtNd, pTxtNd->GetTxt().getLength())));
240 : }
241 : // Are there any Pams in the next TextNode?
242 0 : pTxtNd->JoinNext();
243 : }
244 :
245 0 : if( bJoinPrev && pTxtNd->CanJoinPrev( &aIdx ) )
246 : {
247 : // Are there any Pams in the next TextNode?
248 0 : pTxtNd = aIdx.GetNode().GetTxtNode();
249 : {
250 0 : RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
251 0 : SwIndex( pTxtNd, pTxtNd->GetTxt().getLength())));
252 : }
253 0 : pTxtNd->JoinNext();
254 0 : }
255 :
256 : } while( false );
257 :
258 0 : if( pHistory )
259 : {
260 0 : if( nFtnStt != pHistory->Count() )
261 0 : pHistory->Rollback( pDoc, nFtnStt );
262 0 : pHistory->TmpRollback( pDoc, 0 );
263 0 : pHistory->SetTmpEnd( pHistory->Count() );
264 : }
265 :
266 : // set the cursor onto Undo area
267 0 : if( !bMoveRange )
268 : {
269 0 : AddUndoRedoPaM(rContext);
270 : }
271 0 : }
272 :
273 0 : void SwUndoMove::RedoImpl(::sw::UndoRedoContext & rContext)
274 : {
275 0 : SwPaM *const pPam = & AddUndoRedoPaM(rContext);
276 0 : SwDoc & rDoc = rContext.GetDoc();
277 :
278 0 : SwNodes& rNds = rDoc.GetNodes();
279 0 : SwNodeIndex aIdx( rNds, nMvDestNode );
280 :
281 0 : if( bMoveRange )
282 : {
283 : // only a move with SwRange
284 0 : SwNodeRange aRg( rNds, nSttNode, rNds, nEndNode );
285 : rDoc.MoveNodeRange( aRg, aIdx, (bMoveRedlines)
286 : ? IDocumentContentOperations::DOC_MOVEREDLINES
287 0 : : IDocumentContentOperations::DOC_MOVEDEFAULT );
288 : }
289 : else
290 : {
291 0 : SwPaM aPam( *pPam->GetPoint() );
292 0 : SetPaM( aPam );
293 0 : SwPosition aMvPos( aIdx, SwIndex( aIdx.GetNode().GetCntntNode(),
294 0 : nMvDestCntnt ));
295 :
296 0 : DelFtn( aPam );
297 0 : RemoveIdxFromRange( aPam, false );
298 :
299 0 : aIdx = aPam.Start()->nNode;
300 0 : sal_Bool bJoinTxt = aIdx.GetNode().IsTxtNode();
301 :
302 0 : aIdx--;
303 : rDoc.MoveRange( aPam, aMvPos,
304 0 : IDocumentContentOperations::DOC_MOVEDEFAULT );
305 :
306 0 : if( nSttNode != nEndNode && bJoinTxt )
307 : {
308 0 : ++aIdx;
309 0 : SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
310 0 : if( pTxtNd && pTxtNd->CanJoinNext() )
311 : {
312 : {
313 0 : RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
314 0 : SwIndex(pTxtNd, pTxtNd->GetTxt().getLength())));
315 : }
316 0 : pTxtNd->JoinNext();
317 : }
318 : }
319 0 : *pPam->GetPoint() = *aPam.GetPoint();
320 0 : pPam->SetMark();
321 0 : *pPam->GetMark() = *aPam.GetMark();
322 0 : }
323 0 : }
324 :
325 0 : void SwUndoMove::DelFtn( const SwPaM& rRange )
326 : {
327 : // is the current move from CntntArea into the special section?
328 0 : SwDoc* pDoc = rRange.GetDoc();
329 0 : sal_uLong nCntntStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
330 0 : if( nMvDestNode < nCntntStt &&
331 0 : rRange.GetPoint()->nNode.GetIndex() >= nCntntStt )
332 : {
333 : // delete all footnotes since they are undesired there
334 0 : DelCntntIndex( *rRange.GetMark(), *rRange.GetPoint(),
335 0 : nsDelCntntType::DELCNT_FTN );
336 :
337 0 : if( pHistory && !pHistory->Count() )
338 0 : delete pHistory, pHistory = 0;
339 : }
340 0 : }
341 :
342 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|