xref: /aoo4110/main/sw/source/core/undo/unmove.cxx (revision b1cdbd2c)
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