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