1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27 #include <UndoSplitMove.hxx>
28
29 #include <doc.hxx>
30 #include <IDocumentUndoRedo.hxx>
31 #include <pam.hxx>
32 #include <swundo.hxx> // fuer die UndoIds
33 #include <ndtxt.hxx>
34 #include <UndoCore.hxx>
35 #include <rolbck.hxx>
36
37
38 // MOVE
39
SwUndoMove(const SwPaM & rRange,const SwPosition & rMvPos)40 SwUndoMove::SwUndoMove( const SwPaM& rRange, const SwPosition& rMvPos )
41 : SwUndo( UNDO_MOVE ), SwUndRng( rRange ),
42 nMvDestNode( rMvPos.nNode.GetIndex() ),
43 nMvDestCntnt( rMvPos.nContent.GetIndex() ),
44 bMoveRedlines( false )
45 {
46 bMoveRange = bJoinNext = bJoinPrev = sal_False;
47
48 // StartNode vorm loeschen von Fussnoten besorgen!
49 SwDoc* pDoc = rRange.GetDoc();
50 SwTxtNode* pTxtNd = pDoc->GetNodes()[ nSttNode ]->GetTxtNode();
51 SwTxtNode* pEndTxtNd = pDoc->GetNodes()[ nEndNode ]->GetTxtNode();
52
53 pHistory = new SwHistory;
54
55 if( pTxtNd )
56 {
57 pHistory->Add( pTxtNd->GetTxtColl(), nSttNode, ND_TEXTNODE );
58 if ( pTxtNd->GetpSwpHints() )
59 {
60 pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nSttNode,
61 0, pTxtNd->GetTxt().Len(), false );
62 }
63 if( pTxtNd->HasSwAttrSet() )
64 pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nSttNode );
65 }
66 if( pEndTxtNd && pEndTxtNd != pTxtNd )
67 {
68 pHistory->Add( pEndTxtNd->GetTxtColl(), nEndNode, ND_TEXTNODE );
69 if ( pEndTxtNd->GetpSwpHints() )
70 {
71 pHistory->CopyAttr( pEndTxtNd->GetpSwpHints(), nEndNode,
72 0, pEndTxtNd->GetTxt().Len(), false );
73 }
74 if( pEndTxtNd->HasSwAttrSet() )
75 pHistory->CopyFmtAttr( *pEndTxtNd->GetpSwAttrSet(), nEndNode );
76 }
77
78 pTxtNd = rMvPos.nNode.GetNode().GetTxtNode();
79 if (0 != pTxtNd)
80 {
81 pHistory->Add( pTxtNd->GetTxtColl(), nMvDestNode, ND_TEXTNODE );
82 if ( pTxtNd->GetpSwpHints() )
83 {
84 pHistory->CopyAttr( pTxtNd->GetpSwpHints(), nMvDestNode,
85 0, pTxtNd->GetTxt().Len(), false );
86 }
87 if( pTxtNd->HasSwAttrSet() )
88 pHistory->CopyFmtAttr( *pTxtNd->GetpSwAttrSet(), nMvDestNode );
89 }
90
91
92 nFtnStt = pHistory->Count();
93 DelFtn( rRange );
94
95 if( pHistory && !pHistory->Count() )
96 DELETEZ( pHistory );
97 }
98
99
SwUndoMove(SwDoc * pDoc,const SwNodeRange & rRg,const SwNodeIndex & rMvPos)100 SwUndoMove::SwUndoMove( SwDoc* pDoc, const SwNodeRange& rRg,
101 const SwNodeIndex& rMvPos )
102 : SwUndo( UNDO_MOVE ),
103 nMvDestNode( rMvPos.GetIndex() ),
104 bMoveRedlines( false )
105 {
106 bMoveRange = sal_True;
107 bJoinNext = bJoinPrev = sal_False;
108
109 nSttCntnt = nEndCntnt = nMvDestCntnt = STRING_MAXLEN;
110
111 nSttNode = rRg.aStart.GetIndex();
112 nEndNode = rRg.aEnd.GetIndex();
113
114 // DelFtn( rRange );
115
116 // wird aus dem CntntBereich in den Sonderbereich verschoben ?
117 sal_uLong nCntntStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
118 if( nMvDestNode < nCntntStt && rRg.aStart.GetIndex() > nCntntStt )
119 {
120 // loesche alle Fussnoten. Diese sind dort nicht erwuenscht.
121 SwPosition aPtPos( rRg.aEnd );
122 SwCntntNode* pCNd = rRg.aEnd.GetNode().GetCntntNode();
123 if( pCNd )
124 aPtPos.nContent.Assign( pCNd, pCNd->Len() );
125 SwPosition aMkPos( rRg.aStart );
126 if( 0 != ( pCNd = aMkPos.nNode.GetNode().GetCntntNode() ))
127 aMkPos.nContent.Assign( pCNd, 0 );
128
129 DelCntntIndex( aMkPos, aPtPos, nsDelCntntType::DELCNT_FTN );
130
131 if( pHistory && !pHistory->Count() )
132 DELETEZ( pHistory );
133 }
134
135 nFtnStt = 0;
136 }
137
138
139
SetDestRange(const SwPaM & rRange,const SwPosition & rInsPos,sal_Bool bJoin,sal_Bool bCorrPam)140 void SwUndoMove::SetDestRange( const SwPaM& rRange,
141 const SwPosition& rInsPos,
142 sal_Bool bJoin, sal_Bool bCorrPam )
143 {
144 const SwPosition *pStt = rRange.Start(),
145 *pEnd = rRange.GetPoint() == pStt
146 ? rRange.GetMark()
147 : rRange.GetPoint();
148
149 nDestSttNode = pStt->nNode.GetIndex();
150 nDestSttCntnt = pStt->nContent.GetIndex();
151 nDestEndNode = pEnd->nNode.GetIndex();
152 nDestEndCntnt = pEnd->nContent.GetIndex();
153
154 nInsPosNode = rInsPos.nNode.GetIndex();
155 nInsPosCntnt = rInsPos.nContent.GetIndex();
156
157 if( bCorrPam )
158 {
159 nDestSttNode--;
160 nDestEndNode--;
161 }
162
163 bJoinNext = nDestSttNode != nDestEndNode &&
164 pStt->nNode.GetNode().GetTxtNode() &&
165 pEnd->nNode.GetNode().GetTxtNode();
166 bJoinPrev = bJoin;
167 }
168
169
SetDestRange(const SwNodeIndex & rStt,const SwNodeIndex & rEnd,const SwNodeIndex & rInsPos)170 void SwUndoMove::SetDestRange( const SwNodeIndex& rStt,
171 const SwNodeIndex& rEnd,
172 const SwNodeIndex& rInsPos )
173 {
174 nDestSttNode = rStt.GetIndex();
175 nDestEndNode = rEnd.GetIndex();
176 if( nDestSttNode > nDestEndNode )
177 {
178 nDestSttNode = nDestEndNode;
179 nDestEndNode = rStt.GetIndex();
180 }
181 nInsPosNode = rInsPos.GetIndex();
182
183 nDestSttCntnt = nDestEndCntnt = nInsPosCntnt = STRING_MAXLEN;
184 }
185
186
UndoImpl(::sw::UndoRedoContext & rContext)187 void SwUndoMove::UndoImpl(::sw::UndoRedoContext & rContext)
188 {
189 SwDoc *const pDoc = & rContext.GetDoc();
190
191 // Block, damit aus diesem gesprungen werden kann
192 do {
193 // erzeuge aus den Werten die Insert-Position und den Bereich
194 SwNodeIndex aIdx( pDoc->GetNodes(), nDestSttNode );
195
196 if( bMoveRange )
197 {
198 // nur ein Move mit SwRange
199 SwNodeRange aRg( aIdx, aIdx );
200 aRg.aEnd = nDestEndNode;
201 aIdx = nInsPosNode;
202 bool bSuccess = pDoc->MoveNodeRange( aRg, aIdx,
203 IDocumentContentOperations::DOC_MOVEDEFAULT );
204 if (!bSuccess)
205 break;
206 }
207 else
208 {
209 SwPaM aPam( aIdx.GetNode(), nDestSttCntnt,
210 *pDoc->GetNodes()[ nDestEndNode ], nDestEndCntnt );
211
212 // #i17764# if redlines are to be moved, we may not remove them before
213 // pDoc->Move gets a chance to handle them
214 if( ! bMoveRedlines )
215 RemoveIdxFromRange( aPam, sal_False );
216
217 SwPosition aPos( *pDoc->GetNodes()[ nInsPosNode] );
218 SwCntntNode* pCNd = aPos.nNode.GetNode().GetCntntNode();
219 aPos.nContent.Assign( pCNd, nInsPosCntnt );
220
221 if( pCNd->HasSwAttrSet() )
222 pCNd->ResetAllAttr();
223
224 if( pCNd->IsTxtNode() && ((SwTxtNode*)pCNd)->GetpSwpHints() )
225 ((SwTxtNode*)pCNd)->ClearSwpHintsArr( false );
226
227 // an der InsertPos erstmal alle Attribute entfernen,
228 const bool bSuccess = pDoc->MoveRange( aPam, aPos, (bMoveRedlines)
229 ? IDocumentContentOperations::DOC_MOVEREDLINES
230 : IDocumentContentOperations::DOC_MOVEDEFAULT );
231 if (!bSuccess)
232 break;
233
234 aPam.Exchange();
235 aPam.DeleteMark();
236 // pDoc->ResetAttr( aPam, sal_False );
237 if( aPam.GetNode()->IsCntntNode() )
238 aPam.GetNode()->GetCntntNode()->ResetAllAttr();
239 // der Pam wird jetzt aufgegeben.
240 }
241
242 SwTxtNode* pTxtNd = aIdx.GetNode().GetTxtNode();
243 if( bJoinNext )
244 {
245 {
246 RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
247 SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) );
248 }
249 // sind keine Pams mehr im naechsten TextNode
250 pTxtNd->JoinNext();
251 }
252
253 if( bJoinPrev && pTxtNd->CanJoinPrev( &aIdx ) )
254 {
255 // ?? sind keine Pams mehr im naechsten TextNode ??
256 pTxtNd = aIdx.GetNode().GetTxtNode();
257 {
258 RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
259 SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) );
260 }
261 pTxtNd->JoinNext();
262 }
263
264 } while( sal_False );
265
266 if( pHistory )
267 {
268 if( nFtnStt != pHistory->Count() )
269 pHistory->Rollback( pDoc, nFtnStt );
270 pHistory->TmpRollback( pDoc, 0 );
271 pHistory->SetTmpEnd( pHistory->Count() );
272 }
273
274 // setze noch den Cursor auf den Undo-Bereich
275 if( !bMoveRange )
276 {
277 AddUndoRedoPaM(rContext);
278 }
279 }
280
281
RedoImpl(::sw::UndoRedoContext & rContext)282 void SwUndoMove::RedoImpl(::sw::UndoRedoContext & rContext)
283 {
284 SwPaM *const pPam = & AddUndoRedoPaM(rContext);
285 SwDoc & rDoc = rContext.GetDoc();
286
287 SwNodes& rNds = rDoc.GetNodes();
288 SwNodeIndex aIdx( rNds, nMvDestNode );
289
290 if( bMoveRange )
291 {
292 // nur ein Move mit SwRange
293 SwNodeRange aRg( rNds, nSttNode, rNds, nEndNode );
294 rDoc.MoveNodeRange( aRg, aIdx, (bMoveRedlines)
295 ? IDocumentContentOperations::DOC_MOVEREDLINES
296 : IDocumentContentOperations::DOC_MOVEDEFAULT );
297 }
298 else
299 {
300 SwPaM aPam( *pPam->GetPoint() );
301 SetPaM( aPam );
302 SwPosition aMvPos( aIdx, SwIndex( aIdx.GetNode().GetCntntNode(),
303 nMvDestCntnt ));
304
305 DelFtn( aPam );
306 RemoveIdxFromRange( aPam, sal_False );
307
308 aIdx = aPam.Start()->nNode;
309 sal_Bool bJoinTxt = aIdx.GetNode().IsTxtNode();
310
311 aIdx--;
312 rDoc.MoveRange( aPam, aMvPos,
313 IDocumentContentOperations::DOC_MOVEDEFAULT );
314
315 if( nSttNode != nEndNode && bJoinTxt )
316 {
317 aIdx++;
318 SwTxtNode * pTxtNd = aIdx.GetNode().GetTxtNode();
319 if( pTxtNd && pTxtNd->CanJoinNext() )
320 {
321 {
322 RemoveIdxRel( aIdx.GetIndex() + 1, SwPosition( aIdx,
323 SwIndex( pTxtNd, pTxtNd->GetTxt().Len() ) ) );
324 }
325 pTxtNd->JoinNext();
326 }
327 }
328 *pPam->GetPoint() = *aPam.GetPoint();
329 pPam->SetMark();
330 *pPam->GetMark() = *aPam.GetMark();
331 }
332 }
333
334
DelFtn(const SwPaM & rRange)335 void SwUndoMove::DelFtn( const SwPaM& rRange )
336 {
337 // wird aus dem CntntBereich in den Sonderbereich verschoben ?
338 SwDoc* pDoc = rRange.GetDoc();
339 sal_uLong nCntntStt = pDoc->GetNodes().GetEndOfAutotext().GetIndex();
340 if( nMvDestNode < nCntntStt &&
341 rRange.GetPoint()->nNode.GetIndex() >= nCntntStt )
342 {
343 // loesche alle Fussnoten. Diese sind dort nicht erwuenscht.
344 DelCntntIndex( *rRange.GetMark(), *rRange.GetPoint(),
345 nsDelCntntType::DELCNT_FTN );
346
347 if( pHistory && !pHistory->Count() )
348 delete pHistory, pHistory = 0;
349 }
350 }
351
352